Thanks to visit codestin.com
Credit goes to github.com

Skip to content

feat(envs): SallySoprano — LLM-judged salary negotiation game - #202

Open
borgr wants to merge 6 commits into
TextArena:mainfrom
borgr:sally_soprano
Open

feat(envs): SallySoprano — LLM-judged salary negotiation game#202
borgr wants to merge 6 commits into
TextArena:mainfrom
borgr:sally_soprano

Conversation

@borgr

@borgr borgr commented Aug 9, 2026

Copy link
Copy Markdown
Collaborator

Rebases and finishes @cstorm125's #167 against current main.

What it is

The classic Sally Soprano negotiation exercise as a 3-player FFAMultiPlayerState game: Player 0 = Sally's Agent, Player 1 = the Lyric Opera's Business Manager, Player 2 = an LLM judge who scores the outcome once a deal is struck (or max rounds elapse). Each side gets confidential instructions; they exchange free text and [Propose] <amount> / [Accept].

Changes on top of #167

  • Reward convention normalized to -1 / 0 / 1, registered SallySoprano-v0 (+ -train).
  • Wired error_allowance into the state — it was declared on the env (and asserted in the tests) but never passed through, so the state silently used its default of 1.
  • Repeated invalid moves now forfeit to the opponent (the repo-wide "invalid move ⇒ you lose" convention). Previously an exhausted-retry player was added to elimination_order but the env ignored it, leaving that player stuck on their turn — a persistently malformed agent could hang the game since only valid moves advance the round counter. step() now also reports done correctly after a forfeit.
  • Removed self.rewards = {...} writes that were shadowed by state.set_winners/set_draw (dead — close() reads state.rewards), plus a redundant local import re.

Verification (no CI — all local)

  • Author's suite: 18/18 pass.
  • Deterministic (no model needed):
    • free-text to max_rounds with no deal → automatic draw {0:0,1:0,2:0}, terminates.
    • negotiator spams malformed [Propose] → exhausts allowance → forfeits, opponent +1, offender -1, terminates.
    • judge parser over all three verdicts + a parse-failure → correct rewards / draw fallback.

Verification gap (called out honestly)

The full deal→judge→reward path needs a real model acting as Player 2 (the judge). I verified the judge's parser and reward mapping directly and via the author's canned-decision tests, but did not run a live model as judge. Everything not requiring the judge is exercised end-to-end above.

Credit to @cstorm125 (#167) for the design and implementation.

cstorm125 and others added 6 commits August 23, 2025 04:32
- Implement 2-player bilateral negotiation game with LLM judge evaluation
- Add complete environment with proposal/acceptance mechanics and automatic draw
- Include robust action parsing, invalid move handling, and round management
- Add full test suite (18 tests) covering all game mechanics and edge cases
The environment shipped without a register_with_versions entry, so
ta.make("SallySoprano-v0") — the call used in the env's own README and
examples — raised. Register it alongside the other negotiation role-plays
(3 players: two negotiators + LLM judge, max_rounds=60).
…moves, drop dead reward writes

- Pass error_allowance through to FFAMultiPlayerState (was declared but unused; state defaulted to 1).
- Repeated invalid moves now forfeit to the opponent instead of leaving the offender stuck on their turn, which could hang the game against a persistently malformed agent.
- step() reports done correctly after a forfeit.
- Remove self.rewards writes shadowed by state.set_winners/set_draw, and a redundant local import re.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants