Muqeeth commited on
Commit
b58202d
·
verified ·
1 Parent(s): c119aea

Add files using upload-large-folder tool

Browse files
seed_0/Qwen/Qwen2.5-7B-Instruct/adapters/agent_adapter/adapter_model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:c16535e7f7522e43d52d16319b25be9039a76e8011e8be99babaed04058392e3
3
+ size 323014168
seed_0/Qwen/Qwen2.5-7B-Instruct/adapters/critic_adapter/adapter_model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:50cfa136e5499e5b1f83c90753b519572d60a378c94d09953a2738af6a8ae3c1
3
+ size 323014168
seed_0/agent_trainer/critic_optimizer_state.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:f1574fdb90735a922b09c67d07f7abdbd51181f00dc7bed878cb80adb5f50c1d
3
+ size 2631
seed_0/agent_trainer/policy_optimizer_state.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:1c2be6a8c459515ebcd2c32c479d30006845c45324af0dbe6dba681288e570f0
3
+ size 646269121
seed_0/agent_trainer/trainer_annealing_state.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:e442622b890bb5f2a6e624536a24dbd81595b382a1cc6a1d8b4042ef92a96349
3
+ size 104
seed_0/random_state.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:2d559a99fbcb12704a9154f40714cecfd95f7c6064036617fdab8a1f9c7e0160
3
+ size 12176
src_code_for_reproducibility/markov_games/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (301 Bytes). View file
 
src_code_for_reproducibility/markov_games/__pycache__/agent.cpython-312.pyc ADDED
Binary file (3.17 kB). View file
 
src_code_for_reproducibility/markov_games/__pycache__/group_timesteps.cpython-312.pyc ADDED
Binary file (6.24 kB). View file
 
src_code_for_reproducibility/markov_games/__pycache__/linear_runner.cpython-312.pyc ADDED
Binary file (1.64 kB). View file
 
src_code_for_reproducibility/markov_games/__pycache__/run_markov_games.cpython-312.pyc ADDED
Binary file (1.54 kB). View file
 
src_code_for_reproducibility/markov_games/ipd/ipd_agent.py ADDED
@@ -0,0 +1,120 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ File: mllm/markov_games/ipd/ipd_agent.py
3
+ Summary: Implements the IPD agent abstraction used during simulations.
4
+ """
5
+
6
+ import copy
7
+ import json
8
+ import random
9
+ import re
10
+ from collections.abc import Callable
11
+ from copy import deepcopy
12
+ from dataclasses import dataclass, field
13
+ from typing import Any, Dict, List, Optional, Tuple, Union
14
+
15
+ from mllm.markov_games.agent import Agent
16
+ from mllm.markov_games.rollout_tree import AgentActLog, ChatTurn
17
+
18
+
19
+ @dataclass
20
+ class IPDAgentState:
21
+ """
22
+ Tracks retry count, round index, and chat history for a single IPD agent.
23
+ """
24
+
25
+ nb_retries: int
26
+ round_nb: int
27
+ chat_counter: int
28
+ chat_history: List[ChatTurn]
29
+
30
+
31
+ @dataclass
32
+ class IPDAgent(Agent):
33
+ seed: int
34
+ agent_id: str
35
+ agent_name: str
36
+ policy: Callable[[List[Dict]], str]
37
+ intro_prompt: str # Introduction prompt explaining the game rules
38
+ goal_prompt: str # Prompt explaining the agent's goal
39
+ strategy_prompt: str # Prompt suggesting a strategy to the agent
40
+ max_errors: int # Maximum number of errors allowed before default action
41
+ allow_reasoning: bool # Whether to allow reasoning in the response
42
+ max_reasoning_chars: int # Maximum number of characters for reasoning
43
+ cooperate_string: str # string parsed as playing cooperate by simulation
44
+ defect_string: str # string parsed as playing defect by simulation
45
+
46
+ def __post_init__(self):
47
+ self.state = IPDAgentState(
48
+ nb_retries=0, round_nb=0, chat_counter=0, chat_history=[]
49
+ )
50
+
51
+ async def act(self, observation) -> Tuple[Any, AgentActLog]:
52
+ """
53
+ Run the LLM policy conversation until a valid cooperate/defect action is produced.
54
+ """
55
+
56
+ action = None
57
+ action_is_ready = False
58
+ round_nb = observation.round_nb
59
+
60
+ # If it's the first round, we need to send the intro prompt
61
+ if round_nb == 0 and self.state.chat_counter == 0:
62
+ self.state.chat_history.append(
63
+ ChatTurn(
64
+ agent_id=self.agent_id,
65
+ role="user",
66
+ content=self.intro_prompt,
67
+ is_state_end=True,
68
+ )
69
+ )
70
+
71
+ # If new round
72
+ if round_nb > self.state.round_nb:
73
+ coagent_action = observation.last_coagent_move
74
+ user_message = f"Last round, the other agent played {coagent_action}."
75
+ self.state.chat_history.append(
76
+ ChatTurn(
77
+ agent_id=self.agent_id,
78
+ role="user",
79
+ content=user_message,
80
+ is_state_end=True,
81
+ )
82
+ )
83
+
84
+ # If not new round, try to get valid action from policy
85
+ output_chat_turn: ChatTurn = await self.policy(
86
+ state=self.state.chat_history,
87
+ agent_id=self.agent_id,
88
+ regex=f"({self.cooperate_string}|{self.defect_string})",
89
+ )
90
+ self.state.chat_history.append(output_chat_turn)
91
+ action = output_chat_turn.content
92
+
93
+ agent_step_log = AgentActLog(
94
+ chat_turns=self.state.chat_history[self.state.chat_counter :], info=None
95
+ )
96
+ self.state.chat_counter = len(self.state.chat_history)
97
+ self.state.round_nb = round_nb
98
+
99
+ return action, agent_step_log
100
+
101
+ def get_safe_copy(self):
102
+ """
103
+ Return a safe copy of the agent.
104
+ """
105
+ agent_copy = copy.copy(self)
106
+ agent_copy.state = copy.deepcopy(self.state)
107
+ return agent_copy
108
+
109
+ def reset(self):
110
+ self.state = IPDAgentState()
111
+ raise NotImplementedError
112
+
113
+ def render(self):
114
+ pass
115
+
116
+ def close(self):
117
+ pass
118
+
119
+ def get_agent_info(self):
120
+ pass
src_code_for_reproducibility/markov_games/ipd/ipd_simulation.py ADDED
@@ -0,0 +1,167 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ File: mllm/markov_games/ipd/ipd_simulation.py
3
+ Summary: Runs Iterated Prisoner's Dilemma simulations under the Markov-game API.
4
+ """
5
+
6
+ import copy
7
+ import random
8
+ from dataclasses import dataclass
9
+ from typing import Any, Dict, List, Optional, Tuple
10
+
11
+ import numpy as np
12
+
13
+ from mllm.markov_games.markov_game import Simulation
14
+ from mllm.markov_games.rollout_tree import SimulationStepLog
15
+ from mllm.utils.get_coagent_id import get_coagent_id
16
+
17
+
18
+ @dataclass
19
+ class IPDState:
20
+ """
21
+ State of the Iterated Prisoner's Dilemma game.
22
+ """
23
+
24
+ round_nb: int = 0
25
+ done: bool = False
26
+ last_moves: Dict[str, str] | None = None
27
+
28
+
29
+ @dataclass
30
+ class IPDObs:
31
+ """
32
+ Observation in Iterated Prisoner's Dilemma game.
33
+ """
34
+
35
+ round_nb: int
36
+ last_coagent_move: str | None
37
+
38
+
39
+ class IPD(Simulation):
40
+ """
41
+ Iterated Prisoner's Dilemma simulation following the standard.
42
+
43
+ In each round of the game, two agents simultaneously choose to either cooperate (C) or defect (D).
44
+ The payoffs are as follows:
45
+ - If both cooperate: Both receive the "reward" (usually 3 points)
46
+ - If both defect: Both receive the "punishment" (usually 1 point)
47
+ - If one cooperates and one defects: The defector receives the "temptation" (usually 5 points)
48
+ and the cooperator receives the "sucker" payoff (usually 0 points)
49
+
50
+ The game is played for a specified number of rounds.
51
+ """
52
+
53
+ def __init__(
54
+ self,
55
+ agent_ids: List[str],
56
+ agent_names: List[str],
57
+ seed: int,
58
+ rounds_per_game: int,
59
+ reward: float, # Both cooperate
60
+ punishment: float, # Both defect
61
+ temptation: float, # Defector's reward when other cooperates
62
+ sucker: float, # Cooperator's reward when other defects
63
+ cooperate_actions: List[str],
64
+ defect_actions: List[str],
65
+ ):
66
+ self.agent_ids = agent_ids
67
+ self.agent_names = agent_names
68
+ self.seed = seed
69
+ self.rounds_per_game = rounds_per_game
70
+ self.reward = reward
71
+ self.punishment = punishment
72
+ self.temptation = temptation
73
+ self.sucker = sucker
74
+ self.cooperate_actions = cooperate_actions
75
+ self.defect_actions = defect_actions
76
+ self.state = IPDState()
77
+
78
+ def step(self, actions: Dict[str, str]) -> Tuple[bool, SimulationStepLog]:
79
+ """
80
+ Take a step in the environment using the provided actions.
81
+ Here, the observations are just the states of the game.
82
+
83
+ Args:
84
+ actions (dict): A dictionary where keys are agent identifiers and values are actions ('C' or 'D').
85
+
86
+ Returns:
87
+ observations (dict): A dictionary where keys are agent identifiers and values are observations.
88
+ done (bool): Whether the episode has ended.
89
+ info (dict): Additional information about the environment.
90
+ """
91
+
92
+ # Calculate rewards using payoff matrix
93
+ agent0_action = actions[self.agent_ids[0]]
94
+ agent1_action = actions[self.agent_ids[1]]
95
+
96
+ # Normalize actions to standard cooperate/defect/gibberish format
97
+ def normalize_action(action):
98
+ if action in self.cooperate_actions:
99
+ return "C"
100
+ elif action in self.defect_actions:
101
+ return "D"
102
+ else:
103
+ return "D"
104
+
105
+ norm_action0 = normalize_action(agent0_action)
106
+ norm_action1 = normalize_action(agent1_action)
107
+
108
+ payoffs = {
109
+ ("C", "C"): [self.reward, self.reward],
110
+ ("C", "D"): [self.sucker, self.temptation],
111
+ ("D", "C"): [self.temptation, self.sucker],
112
+ ("D", "D"): [self.punishment, self.punishment],
113
+ }
114
+
115
+ round_rewards = {
116
+ self.agent_ids[0]: payoffs[(norm_action0, norm_action1)][0],
117
+ self.agent_ids[1]: payoffs[(norm_action0, norm_action1)][1],
118
+ }
119
+
120
+ # Update game state
121
+ self.state.round_nb += 1
122
+ self.state.last_moves = copy.deepcopy(actions)
123
+ done = self.state.round_nb >= self.rounds_per_game
124
+ step_log = SimulationStepLog(
125
+ rewards=round_rewards,
126
+ info={
127
+ "actions": {
128
+ self.agent_ids[0]: norm_action0,
129
+ self.agent_ids[1]: norm_action1,
130
+ }
131
+ },
132
+ )
133
+
134
+ return done, step_log
135
+
136
+ def get_obs(self):
137
+ """Returns all agent observations in dict
138
+ Returns:
139
+ observations
140
+ """
141
+ observations = {}
142
+ for agent_id in self.agent_ids:
143
+ observations[agent_id] = self.get_obs_agent(agent_id)
144
+ return observations
145
+
146
+ def get_obs_agent(self, agent_id):
147
+ """Returns observation for agent_id"""
148
+ if self.state.last_moves != None:
149
+ other_id = get_coagent_id(self.agent_ids, agent_id)
150
+ last_coagent_move = self.state.last_moves[other_id]
151
+ else:
152
+ last_coagent_move = None
153
+ obs = IPDObs(round_nb=self.state.round_nb, last_coagent_move=last_coagent_move)
154
+ return obs
155
+
156
+ def reset(self):
157
+ """Returns initial observations and states"""
158
+ self.state = IPDState()
159
+ return self.get_obs()
160
+
161
+ def get_safe_copy(self):
162
+ """
163
+ Return a safe copy of the simulation.
164
+ """
165
+ simulation_copy = copy.copy(self)
166
+ simulation_copy.state = copy.deepcopy(self.state)
167
+ return simulation_copy
src_code_for_reproducibility/markov_games/ipd/ipd_statistics.py ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ File: mllm/markov_games/ipd/ipd_statistics.py
3
+ Summary: Computes statistics and summaries for IPD experiments.
4
+ """
5
+
6
+ from __future__ import annotations
7
+
8
+ from typing import Callable, Dict, List, Tuple
9
+
10
+ from mllm.markov_games.rollout_tree import SimulationStepLog
11
+
12
+
13
+ def avg_reward(sl: SimulationStepLog) -> List[Tuple[str, float]]:
14
+ for aid in sl.rewards.keys():
15
+ if "buffer" in str(aid) and "live" not in str(aid):
16
+ return None
17
+ # One value per agent at each step
18
+ rewards_dict = {f"reward-{aid}": float(v) for aid, v in (sl.rewards or {}).items()}
19
+ return [(key, value) for key, value in rewards_dict.items() if value is not None]
20
+
21
+
22
+ stat_functs: list[Callable[[SimulationStepLog], List[Tuple[str, float]]]] = [
23
+ avg_reward,
24
+ ]
src_code_for_reproducibility/markov_games/negotiation/__pycache__/no_press_nego_agent.cpython-312.pyc ADDED
Binary file (6.11 kB). View file
 
src_code_for_reproducibility/markov_games/negotiation/no_press_nego_agent.py ADDED
@@ -0,0 +1,108 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ File: mllm/markov_games/negotiation/no_press_nego_agent.py
3
+ Summary: Agent variant for no-press negotiations without explicit messaging.
4
+ """
5
+
6
+ from typing import Any, Dict, List, Tuple
7
+
8
+ from mllm.markov_games.negotiation.nego_agent import (
9
+ NegotiationAgent,
10
+ NegotiationAgentState,
11
+ )
12
+ from mllm.markov_games.negotiation.nego_simulation import Split
13
+ from mllm.markov_games.negotiation.no_press_nego_simulation import NoPressObs
14
+ from mllm.markov_games.rollout_tree import AgentActLog, ChatTurn
15
+
16
+
17
+ class NoPressAgent(NegotiationAgent):
18
+ def __init__(self, *args, **kwargs):
19
+ super().__init__(*args, **kwargs)
20
+ # No communication in this variant
21
+ self.intro_prompt = (
22
+ "Welcome to an iterated game. You are {agent}. The other agent is {other_agent}.\n"
23
+ "Setup:\n"
24
+ "1. The game consists of multiple independent rounds.\n"
25
+ "2. In each round, there are multiple items to split between the two agents.\n"
26
+ "3. Both agents are assigned a per-item value between 1 and 20 (inclusive) in each round.\n"
27
+ "4. You can observe per-item values of both agents.\n"
28
+ "5. Because assignments are random, both agents are equally likely to have same expected per-item value.\n"
29
+ "\n"
30
+ "Protocol:\n"
31
+ "1. Both agents simultaneously propose the amount of each item they will keep.\n"
32
+ "2. If the total sum of proposals is less than or equal to the item quantity, both agents receive their proposed amounts.\n"
33
+ "3. If the total sum of proposals exceeds the item quantity, they are allocated proportionally.\n"
34
+ "4. Your points for the round = (amount you receive per item) x (your per-item value for that round), added across all items.\n"
35
+ "5. Points are accumulated across rounds.\n"
36
+ "Your goal: {goal}\n"
37
+ )
38
+ self.new_round_prompt = (
39
+ "A New Round Begins\n"
40
+ "The items to split are {quantities}.\n"
41
+ "Your per-item values are {value} and {other_agent}'s per-item values are {other_value}."
42
+ )
43
+ self.last_round_prompt = (
44
+ "Last Round Summary:\n"
45
+ " - Items to split: {last_quantities}\n"
46
+ " - Your per-item values: {last_value_agent}\n"
47
+ " - {other_agent}'s per-item values: {last_value_coagent}\n"
48
+ " - You proposed: {last_split_agent}\n"
49
+ " - You earned: {last_points_agent} points\n"
50
+ " - {other_agent} proposed: {last_split_coagent}\n"
51
+ " - {other_agent} earned: {last_points_coagent} points\n"
52
+ " - Round Complete.\n"
53
+ )
54
+ self.send_split_prompt = "Submit Your Proposal\n" "Respond as {proposal_style}"
55
+
56
+ def get_message_regex(self, observation: NoPressObs) -> str:
57
+ """Return an empty pattern because the no-press variant forbids chat."""
58
+ return r"^$" # No messages allowed
59
+
60
+ def get_split_regex(self, observation: NoPressObs) -> str:
61
+ """Match proposals like ``Proposal: 4 coins, 6 apples`` case-insensitively."""
62
+ items = list(observation.quantities.keys())
63
+ # Accept both singular and plural forms
64
+ item_pattern = "|".join(
65
+ [f"{item[:-1]}s?" if item.endswith("s") else f"{item}s?" for item in items]
66
+ )
67
+ regex = rf"(?i)Proposal:\s*((?:\s*(?P<num>(10|[0-9]))\s*(?P<item>{item_pattern})\s*,?)+)"
68
+ return regex
69
+
70
+ def get_split_action(self, policy_output: str, observation: NoPressObs) -> Split:
71
+ """
72
+ Parse the LLM proposal into a normalized ``Split`` structure.
73
+
74
+ The regex-based parser is lenient (accepts pluralization variants) so that
75
+ prompt tweaks do not require re-training the extraction logic.
76
+ """
77
+ items = list(observation.quantities.keys())
78
+ import re as _re
79
+
80
+ split_regex = self.get_split_regex(observation)
81
+ items_given_to_self = {item: 0 for item in items}
82
+ m = _re.match(split_regex, policy_output.strip())
83
+ if m:
84
+ # Find all (number, item) pairs
85
+ item_pattern = "|".join(
86
+ [
87
+ f"{item[:-1]}s?" if item.endswith("s") else f"{item}s?"
88
+ for item in items
89
+ ]
90
+ )
91
+ inner_regex = rf"(?i)(10|[0-9])\s*({item_pattern})"
92
+
93
+ def normalize_item_name(item_str):
94
+ """Canonicalize plural/singular user text back to the config item id."""
95
+ for orig in items:
96
+ if item_str.lower() == orig.lower():
97
+ return orig
98
+ if orig.endswith("s") and item_str.lower() == orig[:-1].lower():
99
+ return orig
100
+ if (
101
+ not orig.endswith("s")
102
+ and item_str.lower() == orig.lower() + "s"
103
+ ):
104
+ return orig
105
+
106
+ for num, item in _re.findall(inner_regex, m.group(1)):
107
+ items_given_to_self[normalize_item_name(item)] = int(num)
108
+ return Split(items_given_to_self=items_given_to_self)