akshaypulla commited on
Commit
e3cc9b2
ยท
verified ยท
1 Parent(s): 39f9ab0

Upload folder using huggingface_hub

Browse files
Files changed (1) hide show
  1. server/app.py +42 -130
server/app.py CHANGED
@@ -36,6 +36,17 @@ sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
36
 
37
  try:
38
  from openenv.core.env_server.http_server import create_app
 
 
 
 
 
 
 
 
 
 
 
39
  except Exception as e:
40
  raise ImportError(
41
  "openenv is required for the web interface. Install dependencies with '\n uv sync\n'"
@@ -62,7 +73,6 @@ def build_custom_gradio_ui(
62
  readme_content = _load_readme_content(metadata)
63
  display_title = metadata.name if metadata else title
64
 
65
- # Custom Quick Start (override OpenEnv default which uses port 8000)
66
  custom_quick_start_md = """### Connect to this environment
67
 
68
  Connect from Python using `ProcureRLEnv`:
@@ -86,15 +96,6 @@ Access the visual playground at `/web` to:
86
  - **Watch Agent**: See a strategic agent negotiate step-by-step
87
  - **Instructions**: Learn how to play and what each field means
88
 
89
- ### API Endpoints
90
-
91
- | Endpoint | Method | Description |
92
- |----------|--------|-------------|
93
- | `/reset` | POST | Reset environment with task_id and seed |
94
- | `/step` | POST | Execute an action |
95
- | `/state` | GET | Get current negotiation state |
96
- | `/health` | GET | Health check |
97
-
98
  ### Quick Tips
99
 
100
  - Use **collaborative language** ("partnership", "mutual") to increase rapport
@@ -102,7 +103,6 @@ Access the visual playground at `/web` to:
102
  - In **adversarial**, avoid 2+ consecutive concessions or opponent hardens
103
  """
104
 
105
- # Example actions for the Example tab
106
  EXAMPLE_1 = {
107
  "move_type": "make_offer",
108
  "terms": {"price": 48000},
@@ -115,28 +115,11 @@ Access the visual playground at `/web` to:
115
  "message": "We appreciate your flexibility. Here's our counter-offer to move us closer to a mutual agreement.",
116
  }
117
 
118
- # Agent strategies for auto-play
119
  AGENT_STRATEGY = [
120
- (
121
- "make_offer",
122
- {"price": 48000},
123
- "I value our partnership and believe we can reach a fair agreement together.",
124
- ),
125
- (
126
- "make_offer",
127
- {"price": 46000},
128
- "I appreciate your movement. Let's see if we can meet in the middle.",
129
- ),
130
- (
131
- "make_offer",
132
- {"price": 44000},
133
- "We're getting closer. I think we can finalize this at a fair price for both parties.",
134
- ),
135
- (
136
- "make_offer",
137
- {"price": 42000},
138
- "I believe we've found a good deal. Let's accept these terms.",
139
- ),
140
  ("accept", {}, ""),
141
  ]
142
 
@@ -160,7 +143,6 @@ Access the visual playground at `/web` to:
160
  action_data = {"move_type": move_type, "terms": terms, "message": message}
161
  data = await web_manager.step_environment(action_data)
162
 
163
- # Update conversation
164
  new_conv = conversation_state.copy() if conversation_state else []
165
  new_conv.append(
166
  {
@@ -169,6 +151,7 @@ Access the visual playground at `/web` to:
169
  "terms": terms,
170
  }
171
  )
 
172
  if not data.get("observation", {}).get("done"):
173
  supplier_msg = data.get("observation", {}).get("supplier_message", "")
174
  new_conv.append(
@@ -179,11 +162,8 @@ Access the visual playground at `/web` to:
179
  }
180
  )
181
 
182
- # Get price info for chart
183
  obs = data.get("observation", {})
184
  current_price = obs.get("current_offer", {}).get("price", 0)
185
- opponent_opening = 52000 # Will be extracted from state
186
-
187
  reward = obs.get("reward")
188
  done = obs.get("done", False)
189
  status_msg = f"Step complete! Round {obs.get('round_number', 0)}/{obs.get('max_rounds', 6)}"
@@ -207,9 +187,7 @@ Access the visual playground at `/web` to:
207
 
208
  async def run_agent_example(task_id="single_issue", seed=42):
209
  try:
210
- # Reset first
211
  await web_manager.reset_environment({"task_id": task_id, "seed": seed})
212
-
213
  conv = []
214
  steps_log = []
215
  price_points = []
@@ -225,7 +203,6 @@ Access the visual playground at `/web` to:
225
 
226
  current_price = obs.get("current_offer", {}).get("price", 0)
227
  price_points.append(current_price)
228
-
229
  conv.append(
230
  {
231
  "role": "you",
@@ -265,17 +242,9 @@ Access the visual playground at `/web` to:
265
  "โœ… Agent demo complete!",
266
  )
267
  except Exception as e:
268
- return f"Error: {e}", "", f"Error: {e}", ""
269
-
270
- def apply_example(example_data):
271
- return (
272
- example_data["move_type"],
273
- json.dumps(example_data["terms"]),
274
- example_data["message"],
275
- )
276
 
277
  def _format_observation_full(data):
278
- """Format observation as rich markdown."""
279
  if not data:
280
  return "No data"
281
  obs = data.get("observation", data)
@@ -319,7 +288,6 @@ Access the visual playground at `/web` to:
319
  return "๐Ÿ˜"
320
 
321
  def _build_conversation_hist(conv):
322
- """Build conversation history HTML."""
323
  if not conv:
324
  return "**Conversation will appear here...**\n\nMake your first offer to start the negotiation!"
325
  lines = ["## ๐Ÿ’ฌ Conversation History\n"]
@@ -333,7 +301,6 @@ Access the visual playground at `/web` to:
333
  return "\n".join(lines)
334
 
335
  def _build_price_display(round_num, current_price, target, opening):
336
- """Build price tracker display."""
337
  range_price = opening - target
338
  progress = (
339
  ((opening - current_price) / range_price * 100) if range_price > 0 else 0
@@ -351,10 +318,11 @@ Access the visual playground at `/web` to:
351
  return "\n".join(lines)
352
 
353
  def _build_agent_demo_result(steps_log, conv, price_points):
354
- """Build agent demo result display."""
355
- lines = ["## ๐Ÿค– Agent Negotiation Demo\n"]
356
- lines.append("Watch how a strategic agent negotiates:\n")
357
- lines.append("### ๐Ÿ“œ Steps:")
 
358
  lines.extend(steps_log)
359
  lines.append("\n### ๐Ÿ’ฌ Full Conversation:")
360
  for msg in conv:
@@ -371,14 +339,11 @@ Access the visual playground at `/web` to:
371
  gr.Markdown(f"# ๐Ÿค {display_title}")
372
  gr.Markdown("### Interactive Procurement Negotiation Simulation")
373
 
374
- with gr.Tabs() as tabs:
375
  with gr.TabItem("๐ŸŽฎ Play Now"):
376
- """Interactive tab where user plays against the opponent."""
377
  with gr.Row():
378
  with gr.Column(scale=2):
379
- conversation_display = gr.Markdown(
380
- "*Click Reset to start a new negotiation!*"
381
- )
382
  price_tracker = gr.Markdown(
383
  "## ๐Ÿ“Š Price Tracker\n*Reset to see price tracker*"
384
  )
@@ -389,27 +354,21 @@ Access the visual playground at `/web` to:
389
  choices=["single_issue", "multi_issue", "adversarial"],
390
  value="single_issue",
391
  label="Task",
392
- info="Choose which negotiation scenario",
393
- )
394
- seed_input = gr.Number(
395
- value=42,
396
- label="Seed",
397
- info="Random seed for reproducibility",
398
  )
 
399
  move_type_input = gr.Textbox(
400
  label="Move Type",
401
- info="make_offer | accept | reject | bundle",
402
  value="make_offer",
 
403
  )
404
  terms_input = gr.Textbox(
405
  label="Terms (JSON)",
406
- info='Example: {"price": 45000}',
407
  value='{"price": 48000}',
 
408
  )
409
  message_input = gr.Textbox(
410
  label="Your Message",
411
- info="Be collaborative for better rapport!",
412
- value="I value our partnership and believe we can reach a fair agreement.",
413
  lines=2,
414
  )
415
 
@@ -433,27 +392,25 @@ Access the visual playground at `/web` to:
433
  status_output = gr.Textbox(
434
  label="Status", interactive=False, lines=1
435
  )
436
-
437
  with gr.Accordion("๐Ÿ“‹ Raw JSON", open=False):
438
  raw_json = gr.Code(
439
  label="", language="json", interactive=False, lines=10
440
  )
441
 
442
- # Example messages for quick fill
443
  FRIENDLY_EX = (
444
  "make_offer",
445
  '{"price": 48000}',
446
- "I truly value our partnership and believe we can find a fair solution that benefits both parties. I'm flexible and want to work with you.",
447
  )
448
  PROF_EX = (
449
  "make_offer",
450
  '{"price": 46000}',
451
- "Based on market research and our long-term relationship potential, I believe $46,000 is a fair price. What do you think?",
452
  )
453
  COUNTER_EX = (
454
  "make_offer",
455
  '{"price": 44000}',
456
- "We've made good progress. I can meet you at $44,000 if you can agree to these terms today.",
457
  )
458
 
459
  def get_friendly():
@@ -470,8 +427,7 @@ Access the visual playground at `/web` to:
470
  outputs=[move_type_input, terms_input, message_input],
471
  )
472
  eg2_btn.click(
473
- fn=get_prof,
474
- outputs=[move_type_input, terms_input, message_input],
475
  )
476
  eg3_btn.click(
477
  fn=get_counter,
@@ -523,10 +479,9 @@ Access the visual playground at `/web` to:
523
  )
524
 
525
  with gr.TabItem("๐Ÿค– Watch Agent"):
526
- """Example tab showing agent negotiation demo."""
527
  gr.Markdown("### Watch a Strategic Agent Negotiate")
528
  gr.Markdown(
529
- "This demo shows how an LLM agent would approach the negotiation with collaborative language and strategic pricing."
530
  )
531
  with gr.Row():
532
  task_selector = gr.Dropdown(
@@ -556,7 +511,6 @@ Access the visual playground at `/web` to:
556
  )
557
 
558
  with gr.TabItem("๐Ÿ“– Instructions"):
559
- """Instructions tab."""
560
  gr.Markdown("""
561
  ## ๐ŸŽฎ How to Play
562
 
@@ -566,34 +520,28 @@ Access the visual playground at `/web` to:
566
  - **adversarial**: Negotiate price + payment + support (hardest)
567
 
568
  ### 2. Make Offers
569
- - **Move Type**: `make_offer` to propose terms, `accept` to take current deal, `reject` to walk away
570
- - **Terms**: JSON with your offered price (and payment_days for multi_issue/adversarial)
571
- - **Message**: Be collaborative! Use words like "partnership", "mutual", "flexible" to increase rapport
572
 
573
  ### 3. Watch the Response
574
- - The supplier will counter-offer or accept
575
- - Your **rapport** changes based on your language quality
576
  - Higher rapport โ†’ opponent gives better concessions
577
 
578
  ### 4. Goal
579
- - Get the price as close to your target (shown in observations) as possible
580
- - Use fewer rounds for a better efficiency score
581
  - **Don't make 2+ consecutive concessions** in adversarial mode!
582
 
583
  ## ๐ŸŽฏ Quick Tips
584
 
585
  | Do | Don't |
586
  |---|---|
587
- | Use collaborative language | Use aggressive language ("final offer", "ultimatum") |
588
- | Make strategic concessions | Concede every round (adversarial mode) |
589
- | Offer Net-30 payment (multi_issue) | Ignore payment terms |
590
- | Accept when terms are good | Wait until max rounds |
591
-
592
- ## ๐Ÿค– Agent Demo
593
- The "Watch Agent" tab shows how a strategic agent negotiates step-by-step.
594
  """)
595
 
596
- # Quick Start and README accordions
597
  with gr.Accordion("๐Ÿ“˜ Quick Start Guide", open=False):
598
  gr.Markdown(custom_quick_start_md)
599
  with gr.Accordion("๐Ÿ“š Full README", open=False):
@@ -603,7 +551,6 @@ Access the visual playground at `/web` to:
603
 
604
 
605
  def _load_readme_content(metadata):
606
- """Load README content from metadata or filesystem."""
607
  if metadata and hasattr(metadata, "readme_content") and metadata.readme_content:
608
  return metadata.readme_content
609
  try:
@@ -617,41 +564,6 @@ def _load_readme_content(metadata):
617
  return "No README available."
618
 
619
 
620
- def _format_observation(data):
621
- """Format observation as markdown for display."""
622
- if not data:
623
- return "No data"
624
-
625
- obs = data.get("observation", data)
626
- lines = []
627
-
628
- task_id = obs.get("task_id", "")
629
- round_num = obs.get("round_number", 0)
630
- max_rounds = obs.get("max_rounds", 0)
631
- done = obs.get("done", False)
632
- reward = obs.get("reward")
633
-
634
- lines.append(f"### Round {round_num}/{max_rounds}")
635
- lines.append(f"**Task:** {task_id}")
636
- lines.append(f"**Done:** {done}")
637
-
638
- if reward is not None:
639
- lines.append(f"**Reward:** {reward:.4f}")
640
-
641
- supplier_msg = obs.get("supplier_message", "")
642
- if supplier_msg:
643
- lines.append(f"\n**Supplier:** {supplier_msg}")
644
-
645
- current_offer = obs.get("current_offer", {})
646
- if current_offer:
647
- lines.append(f"\n**Current Offer:** {json.dumps(current_offer)}")
648
-
649
- rapport = obs.get("rapport_hint", "neutral")
650
- lines.append(f"\n**Rapport:** {rapport}")
651
-
652
- return "\n".join(lines)
653
-
654
-
655
  app = create_app(
656
  lambda: _env_instance,
657
  NegotiationAction,
 
36
 
37
  try:
38
  from openenv.core.env_server.http_server import create_app
39
+ import openenv.core.env_server.web_interface as _mod
40
+
41
+ _orig = _mod.get_quick_start_markdown
42
+
43
+ def _fixed(md, ac, oc):
44
+ return _orig(md, ac, oc).replace(
45
+ "http://localhost:8000", "http://localhost:7860"
46
+ )
47
+
48
+ _mod.get_quick_start_markdown = _fixed
49
+
50
  except Exception as e:
51
  raise ImportError(
52
  "openenv is required for the web interface. Install dependencies with '\n uv sync\n'"
 
73
  readme_content = _load_readme_content(metadata)
74
  display_title = metadata.name if metadata else title
75
 
 
76
  custom_quick_start_md = """### Connect to this environment
77
 
78
  Connect from Python using `ProcureRLEnv`:
 
96
  - **Watch Agent**: See a strategic agent negotiate step-by-step
97
  - **Instructions**: Learn how to play and what each field means
98
 
 
 
 
 
 
 
 
 
 
99
  ### Quick Tips
100
 
101
  - Use **collaborative language** ("partnership", "mutual") to increase rapport
 
103
  - In **adversarial**, avoid 2+ consecutive concessions or opponent hardens
104
  """
105
 
 
106
  EXAMPLE_1 = {
107
  "move_type": "make_offer",
108
  "terms": {"price": 48000},
 
115
  "message": "We appreciate your flexibility. Here's our counter-offer to move us closer to a mutual agreement.",
116
  }
117
 
 
118
  AGENT_STRATEGY = [
119
+ ("make_offer", {"price": 48000}, "I value our partnership."),
120
+ ("make_offer", {"price": 46000}, "I appreciate your movement."),
121
+ ("make_offer", {"price": 44000}, "We're getting closer."),
122
+ ("make_offer", {"price": 42000}, "I believe we've found a good deal."),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
123
  ("accept", {}, ""),
124
  ]
125
 
 
143
  action_data = {"move_type": move_type, "terms": terms, "message": message}
144
  data = await web_manager.step_environment(action_data)
145
 
 
146
  new_conv = conversation_state.copy() if conversation_state else []
147
  new_conv.append(
148
  {
 
151
  "terms": terms,
152
  }
153
  )
154
+
155
  if not data.get("observation", {}).get("done"):
156
  supplier_msg = data.get("observation", {}).get("supplier_message", "")
157
  new_conv.append(
 
162
  }
163
  )
164
 
 
165
  obs = data.get("observation", {})
166
  current_price = obs.get("current_offer", {}).get("price", 0)
 
 
167
  reward = obs.get("reward")
168
  done = obs.get("done", False)
169
  status_msg = f"Step complete! Round {obs.get('round_number', 0)}/{obs.get('max_rounds', 6)}"
 
187
 
188
  async def run_agent_example(task_id="single_issue", seed=42):
189
  try:
 
190
  await web_manager.reset_environment({"task_id": task_id, "seed": seed})
 
191
  conv = []
192
  steps_log = []
193
  price_points = []
 
203
 
204
  current_price = obs.get("current_offer", {}).get("price", 0)
205
  price_points.append(current_price)
 
206
  conv.append(
207
  {
208
  "role": "you",
 
242
  "โœ… Agent demo complete!",
243
  )
244
  except Exception as e:
245
+ return f"Error: {e}", "", f"Error: {e}"
 
 
 
 
 
 
 
246
 
247
  def _format_observation_full(data):
 
248
  if not data:
249
  return "No data"
250
  obs = data.get("observation", data)
 
288
  return "๐Ÿ˜"
289
 
290
  def _build_conversation_hist(conv):
 
291
  if not conv:
292
  return "**Conversation will appear here...**\n\nMake your first offer to start the negotiation!"
293
  lines = ["## ๐Ÿ’ฌ Conversation History\n"]
 
301
  return "\n".join(lines)
302
 
303
  def _build_price_display(round_num, current_price, target, opening):
 
304
  range_price = opening - target
305
  progress = (
306
  ((opening - current_price) / range_price * 100) if range_price > 0 else 0
 
318
  return "\n".join(lines)
319
 
320
  def _build_agent_demo_result(steps_log, conv, price_points):
321
+ lines = [
322
+ "## ๐Ÿค– Agent Negotiation Demo\n",
323
+ "Watch how a strategic agent negotiates:\n",
324
+ "### ๐Ÿ“œ Steps:",
325
+ ]
326
  lines.extend(steps_log)
327
  lines.append("\n### ๐Ÿ’ฌ Full Conversation:")
328
  for msg in conv:
 
339
  gr.Markdown(f"# ๐Ÿค {display_title}")
340
  gr.Markdown("### Interactive Procurement Negotiation Simulation")
341
 
342
+ with gr.Tabs():
343
  with gr.TabItem("๐ŸŽฎ Play Now"):
 
344
  with gr.Row():
345
  with gr.Column(scale=2):
346
+ conversation_display = gr.Markdown("*Click Reset to start!*")
 
 
347
  price_tracker = gr.Markdown(
348
  "## ๐Ÿ“Š Price Tracker\n*Reset to see price tracker*"
349
  )
 
354
  choices=["single_issue", "multi_issue", "adversarial"],
355
  value="single_issue",
356
  label="Task",
 
 
 
 
 
 
357
  )
358
+ seed_input = gr.Number(value=42, label="Seed")
359
  move_type_input = gr.Textbox(
360
  label="Move Type",
 
361
  value="make_offer",
362
+ info="make_offer | accept | reject | bundle",
363
  )
364
  terms_input = gr.Textbox(
365
  label="Terms (JSON)",
 
366
  value='{"price": 48000}',
367
+ info='Example: {"price": 45000}',
368
  )
369
  message_input = gr.Textbox(
370
  label="Your Message",
371
+ value="I value our partnership.",
 
372
  lines=2,
373
  )
374
 
 
392
  status_output = gr.Textbox(
393
  label="Status", interactive=False, lines=1
394
  )
 
395
  with gr.Accordion("๐Ÿ“‹ Raw JSON", open=False):
396
  raw_json = gr.Code(
397
  label="", language="json", interactive=False, lines=10
398
  )
399
 
 
400
  FRIENDLY_EX = (
401
  "make_offer",
402
  '{"price": 48000}',
403
+ "I truly value our partnership and believe we can find a fair solution.",
404
  )
405
  PROF_EX = (
406
  "make_offer",
407
  '{"price": 46000}',
408
+ "Based on market research and our long-term relationship, I believe $46,000 is fair.",
409
  )
410
  COUNTER_EX = (
411
  "make_offer",
412
  '{"price": 44000}',
413
+ "We've made good progress. I can meet you at $44,000.",
414
  )
415
 
416
  def get_friendly():
 
427
  outputs=[move_type_input, terms_input, message_input],
428
  )
429
  eg2_btn.click(
430
+ fn=get_prof, outputs=[move_type_input, terms_input, message_input]
 
431
  )
432
  eg3_btn.click(
433
  fn=get_counter,
 
479
  )
480
 
481
  with gr.TabItem("๐Ÿค– Watch Agent"):
 
482
  gr.Markdown("### Watch a Strategic Agent Negotiate")
483
  gr.Markdown(
484
+ "This demo shows how a strategic agent approaches the negotiation."
485
  )
486
  with gr.Row():
487
  task_selector = gr.Dropdown(
 
511
  )
512
 
513
  with gr.TabItem("๐Ÿ“– Instructions"):
 
514
  gr.Markdown("""
515
  ## ๐ŸŽฎ How to Play
516
 
 
520
  - **adversarial**: Negotiate price + payment + support (hardest)
521
 
522
  ### 2. Make Offers
523
+ - **Move Type**: `make_offer` to propose, `accept` to take deal, `reject` to walk away
524
+ - **Terms**: JSON with your offered price
525
+ - **Message**: Be collaborative for better rapport!
526
 
527
  ### 3. Watch the Response
528
+ - Your **rapport** changes based on language quality
 
529
  - Higher rapport โ†’ opponent gives better concessions
530
 
531
  ### 4. Goal
532
+ - Get price close to your target
533
+ - Use fewer rounds for better efficiency score
534
  - **Don't make 2+ consecutive concessions** in adversarial mode!
535
 
536
  ## ๐ŸŽฏ Quick Tips
537
 
538
  | Do | Don't |
539
  |---|---|
540
+ | Use collaborative language | Use aggressive language |
541
+ | Make strategic concessions | Concede every round |
542
+ | Offer Net-30 payment | Ignore payment terms |
 
 
 
 
543
  """)
544
 
 
545
  with gr.Accordion("๐Ÿ“˜ Quick Start Guide", open=False):
546
  gr.Markdown(custom_quick_start_md)
547
  with gr.Accordion("๐Ÿ“š Full README", open=False):
 
551
 
552
 
553
  def _load_readme_content(metadata):
 
554
  if metadata and hasattr(metadata, "readme_content") and metadata.readme_content:
555
  return metadata.readme_content
556
  try:
 
564
  return "No README available."
565
 
566
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
567
  app = create_app(
568
  lambda: _env_instance,
569
  NegotiationAction,