kushalExplores commited on
Commit
20c29f9
·
verified ·
1 Parent(s): 59ed515

Upload server/scenario_variants.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. server/scenario_variants.py +133 -0
server/scenario_variants.py ADDED
@@ -0,0 +1,133 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Seeded value variants for Flatmate RL scenarios.
2
+
3
+ Variants intentionally preserve episode flow: same task id, post ids, required
4
+ tools, required bookings, feasible slots, and phase transitions. Only safe
5
+ surface values are shifted so train/test episodes can differ without changing
6
+ the canonical solution structure.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import random
12
+ from copy import deepcopy
13
+ from typing import Any
14
+
15
+
16
+ OCCUPATIONS = [
17
+ "software engineer at a startup",
18
+ "backend engineer at a fintech company",
19
+ "data engineer at a healthtech company",
20
+ "platform engineer at a SaaS company",
21
+ ]
22
+
23
+ RENT_DELTAS = [-1200, -800, -500, 0, 500, 800, 1200]
24
+
25
+
26
+ def _format_rs(amount: int) -> str:
27
+ return f"{amount:,}"
28
+
29
+
30
+ def _buyer_message(scenario: dict[str, Any]) -> str:
31
+ buyer = scenario["buyer_profile"]
32
+ areas = " or ".join(buyer["areas"])
33
+ budget = _format_rs(int(buyer["budget_max"]))
34
+ occupation = buyer["occupation"]
35
+ availability = " or ".join(buyer["visit_availability"])
36
+ task_id = scenario["task_id"]
37
+
38
+ if task_id == "task_visit_multi":
39
+ return (
40
+ "Hi, I want to line up visits for at least two good flatmate-share options before deciding. "
41
+ f"My budget is Rs. {budget}, I'm focused on {areas}, and I work in Goregaon East as a {occupation}."
42
+ )
43
+ if task_id == "task_visit_single_seller_followup":
44
+ return (
45
+ f"Hi, I'm looking for a flatmate-share in {areas}. My budget is Rs. {budget}, "
46
+ f"I work in Goregaon East as a {occupation}, and {availability} are the only times I can visit."
47
+ )
48
+ if "visit_availability" in buyer.get("initial_disclosure_fields", []):
49
+ return (
50
+ f"Hi, I'm looking for a flatmate-share around {areas}. My budget is Rs. {budget}, "
51
+ f"I work in Goregaon East as a {occupation}, and {availability} is the slot I can do right now."
52
+ )
53
+ return (
54
+ "Hi, I'm looking for a flatmate-share near Goregaon East. "
55
+ f"My budget is up to Rs. {budget} and I'm mainly considering {areas} "
56
+ f"because I work as a {occupation}."
57
+ )
58
+
59
+
60
+ def _seller_message(scenario: dict[str, Any]) -> str:
61
+ seller = scenario.get("seller_profile")
62
+ if not seller:
63
+ return scenario.get("seller_initial_message", "")
64
+ return (
65
+ f"Hi, I want help listing a new flatmate-share opening in {seller['area']}. "
66
+ f"The rent is around Rs. {_format_rs(int(seller['rent']))} for a {seller['listing_type']}. "
67
+ "I can tell you more about the listing and available visit times."
68
+ )
69
+
70
+
71
+ def _shift_amount(value: Any, delta: int) -> Any:
72
+ if value is None:
73
+ return None
74
+ return max(1, int(value) + delta)
75
+
76
+
77
+ def apply_seed_variant(
78
+ scenario: dict[str, Any],
79
+ posts: dict[str, dict[str, Any]],
80
+ seed: int | None,
81
+ ) -> tuple[dict[str, Any], dict[str, dict[str, Any]]]:
82
+ """Return seeded copies of a scenario and its posts.
83
+
84
+ The same seed always produces the same value variant for a scenario. A
85
+ missing seed returns the original values, preserving existing tests and
86
+ default behavior.
87
+ """
88
+
89
+ variant_scenario = deepcopy(scenario)
90
+ variant_posts = deepcopy(posts)
91
+ if seed is None:
92
+ return variant_scenario, variant_posts
93
+
94
+ rng = random.Random(f"{variant_scenario['task_id']}:{seed}")
95
+ rent_delta = rng.choice(RENT_DELTAS)
96
+ occupation = rng.choice(OCCUPATIONS)
97
+
98
+ buyer = variant_scenario["buyer_profile"]
99
+ buyer["budget_max"] = _shift_amount(buyer["budget_max"], rent_delta)
100
+ if buyer.get("hidden_budget_ceiling") is not None:
101
+ buyer["hidden_budget_ceiling"] = _shift_amount(buyer["hidden_budget_ceiling"], rent_delta)
102
+ buyer["occupation"] = occupation
103
+
104
+ expected_answers = variant_scenario["scenario_creation_config"].get("expected_answers", {})
105
+ if "budget_max" in expected_answers:
106
+ expected_answers["budget_max"] = buyer["budget_max"]
107
+ if "occupation" in expected_answers:
108
+ expected_answers["occupation"] = buyer["occupation"]
109
+
110
+ negotiation_config = variant_scenario["scenario_creation_config"].get("negotiation_config", {})
111
+ for key in ("buyer_ceiling", "seller_floor"):
112
+ if key in negotiation_config:
113
+ negotiation_config[key] = _shift_amount(negotiation_config[key], rent_delta)
114
+
115
+ for post in variant_posts.values():
116
+ post["rent"] = _shift_amount(post["rent"], rent_delta)
117
+
118
+ seller = variant_scenario.get("seller_profile")
119
+ if seller:
120
+ seller["rent"] = _shift_amount(seller["rent"], rent_delta)
121
+ followup = variant_scenario["scenario_creation_config"].get("followup_seller_expected_answers", {})
122
+ if "rent" in followup:
123
+ followup["rent"] = seller["rent"]
124
+
125
+ variant_scenario["initial_user_message"] = _buyer_message(variant_scenario)
126
+ if seller:
127
+ variant_scenario["seller_initial_message"] = _seller_message(variant_scenario)
128
+ variant_scenario["scenario_creation_config"]["variant"] = {
129
+ "seed": seed,
130
+ "rent_delta": rent_delta,
131
+ "occupation": occupation,
132
+ }
133
+ return variant_scenario, variant_posts