Add files using upload-large-folder tool
Browse filesThis view is limited to 50 files because it contains too many changes. See raw diff
- src_code_for_reproducibility/__pycache__/__init__.cpython-311.pyc +0 -0
- src_code_for_reproducibility/__pycache__/__init__.cpython-312.pyc +0 -0
- src_code_for_reproducibility/chat_utils/__pycache__/chat_turn.cpython-312.pyc +0 -0
- src_code_for_reproducibility/chat_utils/__pycache__/template_specific.cpython-312.pyc +0 -0
- src_code_for_reproducibility/chat_utils/apply_template.py +78 -0
- src_code_for_reproducibility/chat_utils/chat_turn.py +27 -0
- src_code_for_reproducibility/chat_utils/template_specific.py +87 -0
- src_code_for_reproducibility/docs/Makefile +19 -0
- src_code_for_reproducibility/docs/generate_docs.py +249 -0
- src_code_for_reproducibility/docs/make.bat +35 -0
- src_code_for_reproducibility/docs/source/environments.rst +35 -0
- src_code_for_reproducibility/docs/source/environments/dond.rst +410 -0
- src_code_for_reproducibility/docs/source/modules.rst +7 -0
- src_code_for_reproducibility/docs/source/src.environments.dond.dond_statistics_funcs.rst +7 -0
- src_code_for_reproducibility/docs/source/src.environments.dond.rst +19 -0
- src_code_for_reproducibility/docs/source/src.environments.ipd.ipd_log_funcs.rst +7 -0
- src_code_for_reproducibility/docs/source/src.environments.ipd.ipd_training_data_funcs.rst +7 -0
- src_code_for_reproducibility/docs/source/src.environments.ipd.rst +19 -0
- src_code_for_reproducibility/docs/source/src.experiments.dond_run_train.rst +7 -0
- src_code_for_reproducibility/docs/source/src.experiments.generate_and_train.rst +7 -0
- src_code_for_reproducibility/docs/source/src.experiments.rst +17 -0
- src_code_for_reproducibility/docs/source/src.generation.run_games.rst +7 -0
- src_code_for_reproducibility/docs/source/src.models.dummy_hf_agent.rst +7 -0
- src_code_for_reproducibility/docs/source/src.models.hf_agent.rst +7 -0
- src_code_for_reproducibility/docs/source/src.models.oai_agent.rst +7 -0
- src_code_for_reproducibility/docs/source/src.models.server_llm.rst +7 -0
- src_code_for_reproducibility/docs/source/src.models.vllm_worker_wrap.rst +7 -0
- src_code_for_reproducibility/docs/source/src.rst +28 -0
- src_code_for_reproducibility/docs/source/src.run.rst +7 -0
- src_code_for_reproducibility/docs/source/src.training.ppo_train_value_head.rst +7 -0
- src_code_for_reproducibility/docs/source/src.utils.common_imports.rst +7 -0
- src_code_for_reproducibility/docs/source/src.utils.export_ppo_training_set.rst +7 -0
- src_code_for_reproducibility/docs/source/src.utils.log_statistics.rst +7 -0
- src_code_for_reproducibility/docs/source/src.utils.parallel_shuffle.rst +7 -0
- src_code_for_reproducibility/markov_games/__init__.py +0 -0
- src_code_for_reproducibility/markov_games/__pycache__/mg_utils.cpython-312.pyc +0 -0
- src_code_for_reproducibility/markov_games/agent.py +76 -0
- src_code_for_reproducibility/markov_games/alternative_actions_runner.py +138 -0
- src_code_for_reproducibility/markov_games/linear_runner.py +30 -0
- src_code_for_reproducibility/markov_games/mg_utils.py +89 -0
- src_code_for_reproducibility/markov_games/negotiation/__pycache__/tas_simple_simulation.cpython-312.pyc +0 -0
- src_code_for_reproducibility/markov_games/rollout_tree.py +86 -0
- src_code_for_reproducibility/markov_games/run_markov_games.py +24 -0
- src_code_for_reproducibility/markov_games/simulation.py +87 -0
- src_code_for_reproducibility/markov_games/vine_ppo.py +10 -0
- src_code_for_reproducibility/models/__pycache__/__init__.cpython-312.pyc +0 -0
- src_code_for_reproducibility/models/__pycache__/adapter_training_wrapper.cpython-312.pyc +0 -0
- src_code_for_reproducibility/models/__pycache__/human_policy.cpython-312.pyc +0 -0
- src_code_for_reproducibility/models/__pycache__/inference_backend_sglang.cpython-312.pyc +0 -0
- src_code_for_reproducibility/models/__pycache__/large_language_model_api.cpython-312.pyc +0 -0
src_code_for_reproducibility/__pycache__/__init__.cpython-311.pyc
ADDED
|
Binary file (160 Bytes). View file
|
|
|
src_code_for_reproducibility/__pycache__/__init__.cpython-312.pyc
ADDED
|
Binary file (148 Bytes). View file
|
|
|
src_code_for_reproducibility/chat_utils/__pycache__/chat_turn.cpython-312.pyc
ADDED
|
Binary file (1.32 kB). View file
|
|
|
src_code_for_reproducibility/chat_utils/__pycache__/template_specific.cpython-312.pyc
ADDED
|
Binary file (3.61 kB). View file
|
|
|
src_code_for_reproducibility/chat_utils/apply_template.py
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import torch
|
| 2 |
+
|
| 3 |
+
from mllm.chat_utils.chat_turn import ChatTurn
|
| 4 |
+
from mllm.chat_utils.template_specific import (
|
| 5 |
+
custom_llama3_template,
|
| 6 |
+
custom_qwen2_template,
|
| 7 |
+
custom_qwen3_template,
|
| 8 |
+
qwen2_assistant_postfix,
|
| 9 |
+
qwen3_assistant_postfix,
|
| 10 |
+
)
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
def get_custom_chat_template(tokenizer) -> str:
|
| 14 |
+
"""
|
| 15 |
+
Get the chat template for the tokenizer.
|
| 16 |
+
"""
|
| 17 |
+
if "qwen2" in tokenizer.name_or_path.lower():
|
| 18 |
+
return custom_qwen2_template
|
| 19 |
+
elif "llama" in tokenizer.name_or_path.lower():
|
| 20 |
+
return custom_llama3_template
|
| 21 |
+
elif "qwen3" in tokenizer.name_or_path.lower():
|
| 22 |
+
return custom_qwen3_template
|
| 23 |
+
else:
|
| 24 |
+
raise ValueError(f"Tokenizer {tokenizer.name_or_path} not supported")
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
def get_custom_assistant_postfix(tokenizer) -> torch.Tensor:
|
| 28 |
+
"""
|
| 29 |
+
Get the custom assistant postfix for the tokenizer.
|
| 30 |
+
"""
|
| 31 |
+
if "qwen2" in tokenizer.name_or_path.lower():
|
| 32 |
+
return qwen2_assistant_postfix
|
| 33 |
+
elif "qwen3" in tokenizer.name_or_path.lower():
|
| 34 |
+
return qwen3_assistant_postfix
|
| 35 |
+
return torch.tensor([], dtype=torch.long)
|
| 36 |
+
|
| 37 |
+
|
| 38 |
+
def tokenize_chats(chats: list[ChatTurn], tokenizer, enable_thinking) -> None:
|
| 39 |
+
"""
|
| 40 |
+
Set the chat_template_token_ids for each chat turn.
|
| 41 |
+
# TODO: use engine tokens if available
|
| 42 |
+
"""
|
| 43 |
+
custom_template = get_custom_chat_template(tokenizer)
|
| 44 |
+
custom_assistant_postfix: torch.Tensor = get_custom_assistant_postfix(tokenizer)
|
| 45 |
+
for i, chat in enumerate(chats):
|
| 46 |
+
if chat.chat_template_token_ids is None:
|
| 47 |
+
if chat.role == "user":
|
| 48 |
+
next_chat = chats[i + 1] if i + 1 < len(chats) else None
|
| 49 |
+
add_generation_prompt = True
|
| 50 |
+
if next_chat and next_chat.role == "user":
|
| 51 |
+
add_generation_prompt = False
|
| 52 |
+
encoded_chat = tokenizer.apply_chat_template(
|
| 53 |
+
[chat],
|
| 54 |
+
return_tensors="pt",
|
| 55 |
+
chat_template=custom_template,
|
| 56 |
+
add_generation_prompt=add_generation_prompt,
|
| 57 |
+
add_system_prompt=True if i == 0 else False,
|
| 58 |
+
enable_thinking=enable_thinking,
|
| 59 |
+
).flatten()
|
| 60 |
+
previous_chat = chats[i - 1] if i > 0 else None
|
| 61 |
+
if previous_chat and previous_chat.role == "assistant":
|
| 62 |
+
encoded_chat = torch.cat([custom_assistant_postfix, encoded_chat])
|
| 63 |
+
elif chat.role == "assistant":
|
| 64 |
+
encoded_chat = chat.out_token_ids
|
| 65 |
+
chat.chat_template_token_ids = encoded_chat
|
| 66 |
+
|
| 67 |
+
|
| 68 |
+
def chat_turns_to_token_ids(
|
| 69 |
+
chats: list[ChatTurn], tokenizer, enable_thinking
|
| 70 |
+
) -> list[int]:
|
| 71 |
+
"""
|
| 72 |
+
Tokenize the chat turns and set the chat_template_token_ids for each chat turn.
|
| 73 |
+
"""
|
| 74 |
+
tokenize_chats(chats=chats, tokenizer=tokenizer, enable_thinking=enable_thinking)
|
| 75 |
+
token_ids = []
|
| 76 |
+
for chat in chats:
|
| 77 |
+
token_ids.append(chat.chat_template_token_ids)
|
| 78 |
+
return torch.cat(token_ids)
|
src_code_for_reproducibility/chat_utils/chat_turn.py
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from __future__ import annotations
|
| 2 |
+
|
| 3 |
+
import json
|
| 4 |
+
from dataclasses import dataclass
|
| 5 |
+
from pathlib import Path
|
| 6 |
+
from typing import Any, List, Literal, Optional, Tuple
|
| 7 |
+
|
| 8 |
+
import jsonschema
|
| 9 |
+
import torch
|
| 10 |
+
from pydantic import BaseModel, ConfigDict, Field, model_validator
|
| 11 |
+
|
| 12 |
+
AgentId = str
|
| 13 |
+
|
| 14 |
+
|
| 15 |
+
class ChatTurn(BaseModel):
|
| 16 |
+
model_config = ConfigDict(arbitrary_types_allowed=True) # needed for torch tensors
|
| 17 |
+
|
| 18 |
+
role: str = Field(pattern="^(user|assistant)$")
|
| 19 |
+
agent_id: AgentId # ID of the agent with which the chat occured
|
| 20 |
+
content: str
|
| 21 |
+
reasoning_content: str | None = None
|
| 22 |
+
chat_template_token_ids: torch.LongTensor | None = None # Token ids of chat template format. For example, token ids of "<assistant>{content}</assistant>""
|
| 23 |
+
out_token_ids: torch.LongTensor | None = (
|
| 24 |
+
None # tokens generated from inference engine
|
| 25 |
+
)
|
| 26 |
+
log_probs: torch.FloatTensor | None = None
|
| 27 |
+
is_state_end: bool = False # indicates whether this chat turn marks the end of a state in the trajectory
|
src_code_for_reproducibility/chat_utils/template_specific.py
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import huggingface_hub
|
| 2 |
+
import torch
|
| 3 |
+
from transformers import AutoTokenizer
|
| 4 |
+
|
| 5 |
+
custom_llama3_template = """
|
| 6 |
+
{%- if add_system_prompt %}
|
| 7 |
+
{{- '<|begin_of_text|><|start_header_id|>system<|end_header_id|>\n\nCutting Knowledge Date: December 2023\nToday Date: 26 Jul 2024\n\n<|eot_id|>' }}
|
| 8 |
+
{%- endif %}
|
| 9 |
+
{%- for message in messages %}
|
| 10 |
+
{{- '<|start_header_id|>' + message['role'] + '<|end_header_id|>\n\n' + message['content'] | trim + '<|eot_id|>' }}
|
| 11 |
+
{%- endfor %}
|
| 12 |
+
|
| 13 |
+
{%- if add_generation_prompt %}
|
| 14 |
+
{{- '<|start_header_id|>' + 'assistant' + '<|end_header_id|>\n\n' }}
|
| 15 |
+
{%- endif %}
|
| 16 |
+
"""
|
| 17 |
+
|
| 18 |
+
qwen2_assistant_postfix = (
|
| 19 |
+
AutoTokenizer.from_pretrained("Qwen/Qwen2.5-7B-Instruct")
|
| 20 |
+
.encode("\n", return_tensors="pt")
|
| 21 |
+
.flatten()
|
| 22 |
+
)
|
| 23 |
+
qwen3_assistant_postfix = (
|
| 24 |
+
AutoTokenizer.from_pretrained("Qwen/Qwen3-8B")
|
| 25 |
+
.encode("\n", return_tensors="pt")
|
| 26 |
+
.flatten()
|
| 27 |
+
)
|
| 28 |
+
custom_qwen2_template = """
|
| 29 |
+
{%- if add_system_prompt %}
|
| 30 |
+
{{- '<|im_start|>system\nYou are Qwen, created by Alibaba Cloud. You are a helpful assistant.<|im_end|>\n' }}
|
| 31 |
+
{%- endif %}
|
| 32 |
+
{%- set ns = namespace(multi_step_tool=true, last_query_index=messages|length - 1) %}
|
| 33 |
+
{%- for message in messages %}
|
| 34 |
+
{%- if message.content is string %}
|
| 35 |
+
{%- set content = message.content %}
|
| 36 |
+
{%- else %}
|
| 37 |
+
{%- set content = '' %}
|
| 38 |
+
{%- endif %}
|
| 39 |
+
{%- if (message.role == "user") %}
|
| 40 |
+
{{- '<|im_start|>' + message.role + '\n' + content + '<|im_end|>' + '\n' }}
|
| 41 |
+
{%- elif message.role == "assistant" %}
|
| 42 |
+
{%- set reasoning_content = '' %}
|
| 43 |
+
{%- if message.reasoning_content is string %}
|
| 44 |
+
{%- set reasoning_content = message.reasoning_content %}
|
| 45 |
+
{%- else %}
|
| 46 |
+
{%- if '</think>' in content %}
|
| 47 |
+
{%- set reasoning_content = content.split('</think>')[0].rstrip('\n').split('<think>')[-1].lstrip('\n') %}
|
| 48 |
+
{%- set content = content.split('</think>')[-1].lstrip('\n') %}
|
| 49 |
+
{%- endif %}
|
| 50 |
+
{%- endif %}
|
| 51 |
+
{%- if loop.index0 > ns.last_query_index %}
|
| 52 |
+
{%- if reasoning_content %}
|
| 53 |
+
{{- '<|im_start|>' + message.role + '\n<think>\n' + reasoning_content.strip('\n') + '\n</think>\n\n' + content.lstrip('\n') }}
|
| 54 |
+
{%- else %}
|
| 55 |
+
{{- '<|im_start|>' + message.role + '\n' + content }}
|
| 56 |
+
{%- endif %}
|
| 57 |
+
{%- else %}
|
| 58 |
+
{{- '<|im_start|>' + message.role + '\n' + content }}
|
| 59 |
+
{%- endif %}
|
| 60 |
+
{{- '<|im_end|>\n' }}
|
| 61 |
+
{%- endif %}
|
| 62 |
+
{%- endfor %}
|
| 63 |
+
{%- if add_generation_prompt %}
|
| 64 |
+
{{- '<|im_start|>assistant\n' }}
|
| 65 |
+
{%- endif %}
|
| 66 |
+
"""
|
| 67 |
+
|
| 68 |
+
custom_qwen3_template = """
|
| 69 |
+
{%- for message in messages %}
|
| 70 |
+
{%- if message.content is string %}
|
| 71 |
+
{%- set content = message.content %}
|
| 72 |
+
{%- else %}
|
| 73 |
+
{%- set content = '' %}
|
| 74 |
+
{%- endif %}
|
| 75 |
+
{%- if (message.role == "user") %}
|
| 76 |
+
{{- '<|im_start|>' + message.role + '\n' + content + '<|im_end|>' + '\n' }}
|
| 77 |
+
{%- elif message.role == "assistant" %}
|
| 78 |
+
{{- '<|im_start|>' + message.role + '\n' + content + '<|im_end|>' + '\n' }}
|
| 79 |
+
{%- endif %}
|
| 80 |
+
{%- endfor %}
|
| 81 |
+
{%- if add_generation_prompt %}
|
| 82 |
+
{{- '<|im_start|>assistant\n' }}
|
| 83 |
+
{%- if enable_thinking is defined and enable_thinking is false %}
|
| 84 |
+
{{- '<think>\n\n</think>\n\n' }}
|
| 85 |
+
{%- endif %}
|
| 86 |
+
{%- endif %}
|
| 87 |
+
"""
|
src_code_for_reproducibility/docs/Makefile
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Minimal makefile for Sphinx documentation
|
| 2 |
+
|
| 3 |
+
# You can set these variables from the command line, and also
|
| 4 |
+
# from the environment for the first two.
|
| 5 |
+
SPHINXOPTS ?=
|
| 6 |
+
SPHINXBUILD ?= sphinx-build
|
| 7 |
+
SOURCEDIR = source
|
| 8 |
+
BUILDDIR = build
|
| 9 |
+
|
| 10 |
+
# Put it first so that "make" without argument is like "make help".
|
| 11 |
+
help:
|
| 12 |
+
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(SPHINXFLAGS)
|
| 13 |
+
|
| 14 |
+
.PHONY: help Makefile
|
| 15 |
+
|
| 16 |
+
# Catch-all target: route all unknown targets to Sphinx using the new
|
| 17 |
+
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
|
| 18 |
+
%: Makefile
|
| 19 |
+
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(SPHINXFLAGS)
|
src_code_for_reproducibility/docs/generate_docs.py
ADDED
|
@@ -0,0 +1,249 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
"""
|
| 3 |
+
Script to automatically generate Sphinx documentation for all modules and build the HTML website.
|
| 4 |
+
"""
|
| 5 |
+
import importlib.util
|
| 6 |
+
import os
|
| 7 |
+
import subprocess
|
| 8 |
+
import sys
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
def check_and_install_dependencies():
|
| 12 |
+
"""Check for required dependencies and install them if missing."""
|
| 13 |
+
required_packages = [
|
| 14 |
+
"sphinx",
|
| 15 |
+
"sphinx-rtd-theme",
|
| 16 |
+
"sphinxcontrib-napoleon",
|
| 17 |
+
"sphinxcontrib-mermaid",
|
| 18 |
+
"sphinx-autodoc-typehints",
|
| 19 |
+
]
|
| 20 |
+
|
| 21 |
+
missing_packages = []
|
| 22 |
+
|
| 23 |
+
for package in required_packages:
|
| 24 |
+
# Convert package name to module name (replace - with _)
|
| 25 |
+
module_name = package.replace("-", "_")
|
| 26 |
+
|
| 27 |
+
# Check if the package is installed
|
| 28 |
+
if importlib.util.find_spec(module_name) is None:
|
| 29 |
+
missing_packages.append(package)
|
| 30 |
+
|
| 31 |
+
# Install missing packages
|
| 32 |
+
if missing_packages:
|
| 33 |
+
print(f"Installing missing dependencies: {', '.join(missing_packages)}")
|
| 34 |
+
subprocess.check_call(
|
| 35 |
+
[sys.executable, "-m", "pip", "install"] + missing_packages
|
| 36 |
+
)
|
| 37 |
+
print("Dependencies installed successfully")
|
| 38 |
+
else:
|
| 39 |
+
print("All required dependencies are already installed")
|
| 40 |
+
|
| 41 |
+
|
| 42 |
+
def create_makefile(docs_dir):
|
| 43 |
+
"""Create a Makefile for Sphinx documentation if it doesn't exist."""
|
| 44 |
+
makefile_path = os.path.join(docs_dir, "Makefile")
|
| 45 |
+
|
| 46 |
+
if os.path.exists(makefile_path):
|
| 47 |
+
print(f"Makefile already exists at {makefile_path}")
|
| 48 |
+
return
|
| 49 |
+
|
| 50 |
+
print(f"Creating Makefile at {makefile_path}")
|
| 51 |
+
|
| 52 |
+
makefile_content = """# Minimal makefile for Sphinx documentation
|
| 53 |
+
|
| 54 |
+
# You can set these variables from the command line, and also
|
| 55 |
+
# from the environment for the first two.
|
| 56 |
+
SPHINXOPTS ?=
|
| 57 |
+
SPHINXBUILD ?= sphinx-build
|
| 58 |
+
SOURCEDIR = source
|
| 59 |
+
BUILDDIR = build
|
| 60 |
+
|
| 61 |
+
# Put it first so that "make" without argument is like "make help".
|
| 62 |
+
help:
|
| 63 |
+
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(SPHINXFLAGS)
|
| 64 |
+
|
| 65 |
+
.PHONY: help Makefile
|
| 66 |
+
|
| 67 |
+
# Catch-all target: route all unknown targets to Sphinx using the new
|
| 68 |
+
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
|
| 69 |
+
%: Makefile
|
| 70 |
+
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(SPHINXFLAGS)
|
| 71 |
+
"""
|
| 72 |
+
|
| 73 |
+
with open(makefile_path, "w") as f:
|
| 74 |
+
f.write(makefile_content)
|
| 75 |
+
|
| 76 |
+
print("Makefile created successfully")
|
| 77 |
+
|
| 78 |
+
|
| 79 |
+
def create_make_bat(docs_dir):
|
| 80 |
+
"""Create a make.bat file for Windows if it doesn't exist."""
|
| 81 |
+
make_bat_path = os.path.join(docs_dir, "make.bat")
|
| 82 |
+
|
| 83 |
+
if os.path.exists(make_bat_path):
|
| 84 |
+
print(f"make.bat already exists at {make_bat_path}")
|
| 85 |
+
return
|
| 86 |
+
|
| 87 |
+
print(f"Creating make.bat at {make_bat_path}")
|
| 88 |
+
|
| 89 |
+
make_bat_content = """@ECHO OFF
|
| 90 |
+
|
| 91 |
+
pushd %~dp0
|
| 92 |
+
|
| 93 |
+
REM Command file for Sphinx documentation
|
| 94 |
+
|
| 95 |
+
if "%SPHINXBUILD%" == "" (
|
| 96 |
+
set SPHINXBUILD=sphinx-build
|
| 97 |
+
)
|
| 98 |
+
set SOURCEDIR=source
|
| 99 |
+
set BUILDDIR=build
|
| 100 |
+
|
| 101 |
+
%SPHINXBUILD% >NUL 2>NUL
|
| 102 |
+
if errorlevel 9009 (
|
| 103 |
+
echo.
|
| 104 |
+
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
|
| 105 |
+
echo.installed, then set the SPHINXBUILD environment variable to point
|
| 106 |
+
echo.to the full path of the 'sphinx-build' executable. Alternatively you
|
| 107 |
+
echo.may add the Sphinx directory to PATH.
|
| 108 |
+
echo.
|
| 109 |
+
echo.If you don't have Sphinx installed, grab it from
|
| 110 |
+
echo.https://www.sphinx-doc.org/
|
| 111 |
+
exit /b 1
|
| 112 |
+
)
|
| 113 |
+
|
| 114 |
+
if "%1" == "" goto help
|
| 115 |
+
|
| 116 |
+
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
|
| 117 |
+
goto end
|
| 118 |
+
|
| 119 |
+
:help
|
| 120 |
+
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
|
| 121 |
+
|
| 122 |
+
:end
|
| 123 |
+
popd
|
| 124 |
+
"""
|
| 125 |
+
|
| 126 |
+
with open(make_bat_path, "w") as f:
|
| 127 |
+
f.write(make_bat_content)
|
| 128 |
+
|
| 129 |
+
print("make.bat created successfully")
|
| 130 |
+
|
| 131 |
+
|
| 132 |
+
def main():
|
| 133 |
+
# Check and install required dependencies
|
| 134 |
+
print("=== Checking dependencies ===")
|
| 135 |
+
check_and_install_dependencies()
|
| 136 |
+
|
| 137 |
+
# Get the directory of this script
|
| 138 |
+
script_dir = os.path.dirname(os.path.abspath(__file__))
|
| 139 |
+
|
| 140 |
+
# Path to the project root
|
| 141 |
+
project_root = os.path.dirname(script_dir)
|
| 142 |
+
|
| 143 |
+
# Path to the source directory
|
| 144 |
+
source_dir = os.path.join(project_root, "src")
|
| 145 |
+
|
| 146 |
+
# Path to the docs source directory
|
| 147 |
+
docs_source_dir = os.path.join(script_dir, "source")
|
| 148 |
+
|
| 149 |
+
# Print paths for debugging
|
| 150 |
+
print(f"Script directory: {script_dir}")
|
| 151 |
+
print(f"Project root: {project_root}")
|
| 152 |
+
print(f"Source directory: {source_dir}")
|
| 153 |
+
print(f"Docs source directory: {docs_source_dir}")
|
| 154 |
+
|
| 155 |
+
# Make sure the source directory exists
|
| 156 |
+
if not os.path.exists(source_dir):
|
| 157 |
+
print(f"Error: Source directory {source_dir} does not exist!")
|
| 158 |
+
sys.exit(1)
|
| 159 |
+
|
| 160 |
+
# Make sure the docs source directory exists
|
| 161 |
+
if not os.path.exists(docs_source_dir):
|
| 162 |
+
print(f"Creating docs source directory: {docs_source_dir}")
|
| 163 |
+
os.makedirs(docs_source_dir)
|
| 164 |
+
|
| 165 |
+
# Step 1: Run sphinx-apidoc to generate .rst files for all modules
|
| 166 |
+
print("\n=== Generating API documentation ===")
|
| 167 |
+
cmd = [
|
| 168 |
+
"sphinx-apidoc",
|
| 169 |
+
"-f", # Force overwriting of existing files
|
| 170 |
+
"-e", # Put module documentation before submodule documentation
|
| 171 |
+
"-M", # Put module documentation before subpackage documentation
|
| 172 |
+
"-o",
|
| 173 |
+
docs_source_dir, # Output directory
|
| 174 |
+
source_dir, # Source code directory
|
| 175 |
+
]
|
| 176 |
+
|
| 177 |
+
print(f"Running command: {' '.join(cmd)}")
|
| 178 |
+
result = subprocess.run(cmd, capture_output=True, text=True)
|
| 179 |
+
|
| 180 |
+
# Print the output of the command
|
| 181 |
+
print("STDOUT:")
|
| 182 |
+
print(result.stdout)
|
| 183 |
+
|
| 184 |
+
print("STDERR:")
|
| 185 |
+
print(result.stderr)
|
| 186 |
+
|
| 187 |
+
if result.returncode != 0:
|
| 188 |
+
print(f"Error: sphinx-apidoc failed with return code {result.returncode}")
|
| 189 |
+
sys.exit(1)
|
| 190 |
+
|
| 191 |
+
# List the files in the docs source directory
|
| 192 |
+
print("\nFiles in docs/source directory:")
|
| 193 |
+
for file in sorted(os.listdir(docs_source_dir)):
|
| 194 |
+
print(f" {file}")
|
| 195 |
+
|
| 196 |
+
print("\nDocumentation source files generated successfully!")
|
| 197 |
+
|
| 198 |
+
# Step 2: Create Makefile and make.bat if they don't exist
|
| 199 |
+
create_makefile(script_dir)
|
| 200 |
+
create_make_bat(script_dir)
|
| 201 |
+
|
| 202 |
+
# Step 3: Build the HTML documentation
|
| 203 |
+
print("\n=== Building HTML documentation ===")
|
| 204 |
+
|
| 205 |
+
# Determine the build command based on the platform
|
| 206 |
+
if os.name == "nt": # Windows
|
| 207 |
+
build_cmd = ["make.bat", "html"]
|
| 208 |
+
else: # Unix/Linux/Mac
|
| 209 |
+
build_cmd = ["make", "html"]
|
| 210 |
+
|
| 211 |
+
# Change to the docs directory to run the build command
|
| 212 |
+
os.chdir(script_dir)
|
| 213 |
+
|
| 214 |
+
print(f"Running command: {' '.join(build_cmd)}")
|
| 215 |
+
build_result = subprocess.run(build_cmd, capture_output=True, text=True)
|
| 216 |
+
|
| 217 |
+
# Print the output of the build command
|
| 218 |
+
print("STDOUT:")
|
| 219 |
+
print(build_result.stdout)
|
| 220 |
+
|
| 221 |
+
print("STDERR:")
|
| 222 |
+
print(build_result.stderr)
|
| 223 |
+
|
| 224 |
+
if build_result.returncode != 0:
|
| 225 |
+
print(f"Error: HTML build failed with return code {build_result.returncode}")
|
| 226 |
+
sys.exit(1)
|
| 227 |
+
|
| 228 |
+
# Get the path to the built HTML documentation
|
| 229 |
+
html_dir = os.path.join(script_dir, "build", "html")
|
| 230 |
+
index_path = os.path.join(html_dir, "index.html")
|
| 231 |
+
|
| 232 |
+
if os.path.exists(index_path):
|
| 233 |
+
print(f"\nHTML documentation built successfully!")
|
| 234 |
+
print(f"You can view it by opening: {index_path}")
|
| 235 |
+
|
| 236 |
+
# Try to open the documentation in a browser
|
| 237 |
+
try:
|
| 238 |
+
import webbrowser
|
| 239 |
+
|
| 240 |
+
print("\nAttempting to open documentation in your default browser...")
|
| 241 |
+
webbrowser.open(f"file://{index_path}")
|
| 242 |
+
except Exception as e:
|
| 243 |
+
print(f"Could not open browser automatically: {e}")
|
| 244 |
+
else:
|
| 245 |
+
print(f"\nWarning: HTML index file not found at {index_path}")
|
| 246 |
+
|
| 247 |
+
|
| 248 |
+
if __name__ == "__main__":
|
| 249 |
+
main()
|
src_code_for_reproducibility/docs/make.bat
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
@ECHO OFF
|
| 2 |
+
|
| 3 |
+
pushd %~dp0
|
| 4 |
+
|
| 5 |
+
REM Command file for Sphinx documentation
|
| 6 |
+
|
| 7 |
+
if "%SPHINXBUILD%" == "" (
|
| 8 |
+
set SPHINXBUILD=sphinx-build
|
| 9 |
+
)
|
| 10 |
+
set SOURCEDIR=source
|
| 11 |
+
set BUILDDIR=build
|
| 12 |
+
|
| 13 |
+
%SPHINXBUILD% >NUL 2>NUL
|
| 14 |
+
if errorlevel 9009 (
|
| 15 |
+
echo.
|
| 16 |
+
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
|
| 17 |
+
echo.installed, then set the SPHINXBUILD environment variable to point
|
| 18 |
+
echo.to the full path of the 'sphinx-build' executable. Alternatively you
|
| 19 |
+
echo.may add the Sphinx directory to PATH.
|
| 20 |
+
echo.
|
| 21 |
+
echo.If you don't have Sphinx installed, grab it from
|
| 22 |
+
echo.https://www.sphinx-doc.org/
|
| 23 |
+
exit /b 1
|
| 24 |
+
)
|
| 25 |
+
|
| 26 |
+
if "%1" == "" goto help
|
| 27 |
+
|
| 28 |
+
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
|
| 29 |
+
goto end
|
| 30 |
+
|
| 31 |
+
:help
|
| 32 |
+
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
|
| 33 |
+
|
| 34 |
+
:end
|
| 35 |
+
popd
|
src_code_for_reproducibility/docs/source/environments.rst
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
=================
|
| 2 |
+
MARL Environments
|
| 3 |
+
=================
|
| 4 |
+
|
| 5 |
+
This section provides detailed documentation for the multi-agent negotiation environments included in the library.
|
| 6 |
+
|
| 7 |
+
Each environment follows the standard interface described in :doc:`../environments` but has its own unique game rules,
|
| 8 |
+
dynamics, and implementation details.
|
| 9 |
+
|
| 10 |
+
.. toctree::
|
| 11 |
+
:maxdepth: 2
|
| 12 |
+
:caption: Available Environments:
|
| 13 |
+
|
| 14 |
+
environments/ipd
|
| 15 |
+
environments/diplomacy
|
| 16 |
+
environments/dond
|
| 17 |
+
|
| 18 |
+
Overview
|
| 19 |
+
--------
|
| 20 |
+
|
| 21 |
+
The library currently includes the following environments:
|
| 22 |
+
|
| 23 |
+
1. **Iterated Prisoner's Dilemma (IPD)**: A classic game theory problem where two agents repeatedly decide whether to cooperate or defect, with different payoffs based on their joint actions.
|
| 24 |
+
|
| 25 |
+
2. **Diplomacy**: An adaptation of the board game Diplomacy, where seven European powers compete for control of supply centers through strategic moves and alliances.
|
| 26 |
+
|
| 27 |
+
3. **Deal or No Deal (DOND)**: A negotiation environment based on `the paper Deal or No Deal? End-to-End Learning for Negotiation Dialogues <https://arxiv.org/pdf/1706.05125>`_ in which agents negotiate over the distribution of a set of prizes.
|
| 28 |
+
|
| 29 |
+
Each environment documentation includes:
|
| 30 |
+
|
| 31 |
+
- Game rules and background
|
| 32 |
+
- Implementation details
|
| 33 |
+
- API reference
|
| 34 |
+
- Example usage
|
| 35 |
+
- Advanced features and customization options
|
src_code_for_reproducibility/docs/source/environments/dond.rst
ADDED
|
@@ -0,0 +1,410 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
=================
|
| 2 |
+
Deal or No Deal
|
| 3 |
+
=================
|
| 4 |
+
|
| 5 |
+
The Deal or No Deal (DoND) environment provides a multi-agent negotiation interface where players trade
|
| 6 |
+
items with different values. This document describes the API for interacting with the DoND environment
|
| 7 |
+
and its associated agent handler.
|
| 8 |
+
|
| 9 |
+
Overview
|
| 10 |
+
--------
|
| 11 |
+
|
| 12 |
+
Deal or No Deal is a negotiation game where two agents must agree on how to divide a set of items,
|
| 13 |
+
each of which has different values to each agent. The agents engage in a back-and-forth dialogue to
|
| 14 |
+
determine an allocation of the items, with each trying to maximize their own total value.
|
| 15 |
+
|
| 16 |
+
Our implementation follows the Multi-Agent Negotiation Environment standard, allowing it to be used
|
| 17 |
+
with LLM agents through a text-based interface.
|
| 18 |
+
|
| 19 |
+
Game Rules
|
| 20 |
+
----------
|
| 21 |
+
|
| 22 |
+
### Basic Structure
|
| 23 |
+
|
| 24 |
+
The core mechanics of Deal or No Deal are:
|
| 25 |
+
|
| 26 |
+
1. Two agents negotiate over a set of items (e.g., books, balls, hats)
|
| 27 |
+
2. Each item has:
|
| 28 |
+
- A specific quantity (how many of each item is available)
|
| 29 |
+
- A value for each agent (which may differ between agents)
|
| 30 |
+
3. Agents take turns sending messages to negotiate how to split the items
|
| 31 |
+
4. Once an agreement is reached, agents finalize the deal
|
| 32 |
+
5. Points are awarded based on the value of items each agent receives
|
| 33 |
+
|
| 34 |
+
### Detailed Gameplay
|
| 35 |
+
|
| 36 |
+
#### Setup Phase
|
| 37 |
+
|
| 38 |
+
The game begins with:
|
| 39 |
+
- A set of items (e.g., "book", "hat", "ball")
|
| 40 |
+
- Each item has a quantity (e.g., 6 books, 2 hats, 4 balls)
|
| 41 |
+
- Each agent has private values for each item (e.g., books might be worth 5 points to one agent but only 2 points to the other)
|
| 42 |
+
- Agents are assigned roles (starting negotiator and responding negotiator)
|
| 43 |
+
|
| 44 |
+
#### Negotiation Phase
|
| 45 |
+
|
| 46 |
+
1. Agents take turns sending free-form text messages to each other
|
| 47 |
+
2. Messages can include offers, counter-offers, questions, or strategic communication
|
| 48 |
+
3. There is a maximum number of messages permitted (preventing endless negotiations)
|
| 49 |
+
4. Either agent can propose to finalize an agreement at any time
|
| 50 |
+
|
| 51 |
+
For example:
|
| 52 |
+
- Agent 1: "I propose I get all the books and you get all the hats and balls."
|
| 53 |
+
- Agent 2: "That doesn't work for me. How about you get 3 books and I get 3 books, all the hats, and all the balls?"
|
| 54 |
+
- Agent 1: "Let me counter-offer: I get 4 books and 2 balls, you get 2 books, all hats, and 2 balls."
|
| 55 |
+
|
| 56 |
+
#### Finalization Phase
|
| 57 |
+
|
| 58 |
+
1. When an agent wants to finalize a deal, they must specify the exact allocation:
|
| 59 |
+
- How many of each item they receive
|
| 60 |
+
- How many of each item the other agent receives
|
| 61 |
+
2. The other agent must then either agree (by submitting the same allocation) or reject the finalization
|
| 62 |
+
3. If both agents submit matching finalizations, the deal is executed
|
| 63 |
+
4. If finalizations don't match, no agreement is reached, and both agents receive 0 points
|
| 64 |
+
|
| 65 |
+
#### Scoring
|
| 66 |
+
|
| 67 |
+
1. Each agent's score is calculated based on the value of items they receive
|
| 68 |
+
2. The formula is: Sum(quantity_of_item_i × value_of_item_i_to_agent)
|
| 69 |
+
3. If no agreement is reached, both agents receive 0 points
|
| 70 |
+
|
| 71 |
+
### Example Game
|
| 72 |
+
|
| 73 |
+
Let's walk through a simple example:
|
| 74 |
+
|
| 75 |
+
**Setup:**
|
| 76 |
+
- Items: Books (4), Hats (2), Balls (6)
|
| 77 |
+
- Agent 1 values: Books=5, Hats=1, Balls=2
|
| 78 |
+
- Agent 2 values: Books=3, Hats=6, Balls=1
|
| 79 |
+
|
| 80 |
+
**Negotiation (simplified):**
|
| 81 |
+
1. Agent 1: "I would like all the books and balls. You can have the hats."
|
| 82 |
+
2. Agent 2: "That doesn't work for me. Books are valuable. I propose I get all the hats and 2 books, you get 2 books and all the balls."
|
| 83 |
+
3. Agent 1: "How about I get 3 books and all the balls, and you get 1 book and all the hats?"
|
| 84 |
+
4. Agent 2: "I accept your proposal."
|
| 85 |
+
|
| 86 |
+
**Finalization:**
|
| 87 |
+
- Agent 1 submits: Agent 1 gets (Books: 3, Hats: 0, Balls: 6), Agent 2 gets (Books: 1, Hats: 2, Balls: 0)
|
| 88 |
+
- Agent 2 submits the same allocation, confirming agreement
|
| 89 |
+
|
| 90 |
+
**Scoring:**
|
| 91 |
+
- Agent 1 score: (3 books × 5) + (0 hats × 1) + (6 balls × 2) = 15 + 0 + 12 = 27 points
|
| 92 |
+
- Agent 2 score: (1 book × 3) + (2 hats × 6) + (0 balls × 1) = 3 + 12 + 0 = 15 points
|
| 93 |
+
|
| 94 |
+
### Game Variations
|
| 95 |
+
|
| 96 |
+
The DoND environment supports several variations through configuration parameters:
|
| 97 |
+
|
| 98 |
+
#### Different Value Distributions
|
| 99 |
+
|
| 100 |
+
The environment offers multiple ways to assign values to items:
|
| 101 |
+
|
| 102 |
+
1. **Standard Random Setup (dond_random_setup)**:
|
| 103 |
+
- Items have even-numbered quantities
|
| 104 |
+
- Each agent receives distinct random values for each item
|
| 105 |
+
- Values are drawn from a uniform distribution
|
| 106 |
+
|
| 107 |
+
2. **Independent Random Values (independent_random_vals)**:
|
| 108 |
+
- Item quantities can be any number in the specified range
|
| 109 |
+
- Values for each agent are drawn independently
|
| 110 |
+
- Creates more varied negotiation scenarios
|
| 111 |
+
|
| 112 |
+
3. **Bicameral Value Distribution (bicameral_vals_assignator)**:
|
| 113 |
+
- Creates a "high value" and "low value" distribution for each item
|
| 114 |
+
- Each agent values approximately half the items highly and half lowly
|
| 115 |
+
- Values are drawn from normal distributions with different means
|
| 116 |
+
- Creates scenarios with clear trade opportunities
|
| 117 |
+
|
| 118 |
+
#### Visibility Options
|
| 119 |
+
|
| 120 |
+
1. **Finalization Visibility**:
|
| 121 |
+
- When enabled, both agents can see each other's finalization proposals
|
| 122 |
+
- When disabled, finalization proposals remain private until both are submitted
|
| 123 |
+
|
| 124 |
+
2. **Other Values Visibility**:
|
| 125 |
+
- When enabled, agents can see each other's value functions
|
| 126 |
+
- When disabled, agents only know their own values
|
| 127 |
+
- Creates information asymmetry and richer negotiation dynamics
|
| 128 |
+
|
| 129 |
+
#### Game Modes
|
| 130 |
+
|
| 131 |
+
1. **Cooperative Mode ("coop")**:
|
| 132 |
+
- Agents are encouraged to find mutually beneficial solutions
|
| 133 |
+
- Success is measured by the sum of both agents' scores
|
| 134 |
+
|
| 135 |
+
2. **Competitive Mode ("comp")**:
|
| 136 |
+
- Agents aim to maximize their individual scores
|
| 137 |
+
- Creates more adversarial negotiations
|
| 138 |
+
|
| 139 |
+
#### Round Structure
|
| 140 |
+
|
| 141 |
+
1. **Single Round**:
|
| 142 |
+
- One negotiation session between the same agents
|
| 143 |
+
- Simple evaluation of negotiation skills
|
| 144 |
+
|
| 145 |
+
2. **Multiple Rounds**:
|
| 146 |
+
- Agents negotiate multiple times with different item setups
|
| 147 |
+
- Allows for learning and adaptation over time
|
| 148 |
+
- Roles can be swapped between rounds
|
| 149 |
+
|
| 150 |
+
DondEnv
|
| 151 |
+
------------
|
| 152 |
+
|
| 153 |
+
The ``DondEnv`` class provides an interface to the Deal or No Deal environment that follows the Multi-Agent
|
| 154 |
+
Negotiation Environment standard.
|
| 155 |
+
|
| 156 |
+
.. code-block:: python
|
| 157 |
+
|
| 158 |
+
class DondEnv:
|
| 159 |
+
"""
|
| 160 |
+
Multi-Agent Negotiation Environment for Deal or No Deal.
|
| 161 |
+
"""
|
| 162 |
+
def __init__(
|
| 163 |
+
self,
|
| 164 |
+
agents,
|
| 165 |
+
mode="coop",
|
| 166 |
+
max_messages=None,
|
| 167 |
+
min_messages=None,
|
| 168 |
+
max_chars_per_message=None,
|
| 169 |
+
rounds_per_game=1,
|
| 170 |
+
random_setup_func=None,
|
| 171 |
+
random_setup_kwargs=None,
|
| 172 |
+
role_assignator_func=None,
|
| 173 |
+
role_assignator_func_kwargs=None,
|
| 174 |
+
finalization_visibility=False,
|
| 175 |
+
other_values_visibility=False,
|
| 176 |
+
random_seed=None
|
| 177 |
+
):
|
| 178 |
+
"""Initialize the Deal or No Deal environment.
|
| 179 |
+
|
| 180 |
+
Args:
|
| 181 |
+
agents: List of agent IDs participating in the game
|
| 182 |
+
mode: Game mode ("coop" or "comp")
|
| 183 |
+
max_messages: Maximum number of messages per agent per round
|
| 184 |
+
min_messages: Minimum number of messages per agent per round
|
| 185 |
+
max_chars_per_message: Maximum characters per message
|
| 186 |
+
rounds_per_game: Number of negotiation rounds to play
|
| 187 |
+
random_setup_func: Function to generate item quantities and values
|
| 188 |
+
random_setup_kwargs: Arguments for the random setup function
|
| 189 |
+
role_assignator_func: Function to assign roles to agents
|
| 190 |
+
role_assignator_func_kwargs: Arguments for the role assignator
|
| 191 |
+
finalization_visibility: Whether agents can see each other's finalizations
|
| 192 |
+
other_values_visibility: Whether agents can see each other's values
|
| 193 |
+
random_seed: Seed for reproducibility
|
| 194 |
+
"""
|
| 195 |
+
# ...
|
| 196 |
+
|
| 197 |
+
def reset(self):
|
| 198 |
+
"""Reset the environment to an initial state and return the initial observation.
|
| 199 |
+
|
| 200 |
+
Returns:
|
| 201 |
+
observation (dict): A dictionary where keys are agent identifiers and values are observations.
|
| 202 |
+
"""
|
| 203 |
+
# ...
|
| 204 |
+
|
| 205 |
+
def step(self, actions):
|
| 206 |
+
"""Take a step in the environment using the provided actions.
|
| 207 |
+
|
| 208 |
+
Args:
|
| 209 |
+
actions (dict): A dictionary where keys are agent identifiers and values are actions.
|
| 210 |
+
Actions can be messages or finalization proposals.
|
| 211 |
+
|
| 212 |
+
Returns:
|
| 213 |
+
observations (dict): A dictionary where keys are agent identifiers and values are observations.
|
| 214 |
+
done (bool): Whether the episode has ended.
|
| 215 |
+
info (dict): Additional information about the environment.
|
| 216 |
+
"""
|
| 217 |
+
# ...
|
| 218 |
+
|
| 219 |
+
def get_state(self):
|
| 220 |
+
"""Retrieve the current state of the game.
|
| 221 |
+
|
| 222 |
+
Returns:
|
| 223 |
+
state (dict): The current state of the game, including items, quantities, values, etc.
|
| 224 |
+
"""
|
| 225 |
+
# ...
|
| 226 |
+
|
| 227 |
+
Key Implementation Details
|
| 228 |
+
~~~~~~~~~~~~~~~~~~~~~~~~~
|
| 229 |
+
|
| 230 |
+
The ``DondEnv`` class implements several key features:
|
| 231 |
+
|
| 232 |
+
1. **Multi-Agent Support**: The environment tracks two agents and manages their alternating messages.
|
| 233 |
+
|
| 234 |
+
2. **Turn-Based Dialogue**: The environment enforces turn structure and limits on message count.
|
| 235 |
+
|
| 236 |
+
3. **Finalization Processing**: The environment validates and processes finalization proposals.
|
| 237 |
+
|
| 238 |
+
4. **Random Setup**: The environment supports multiple methods of generating negotiation scenarios.
|
| 239 |
+
|
| 240 |
+
5. **Round Management**: The environment can handle multiple rounds with different setups.
|
| 241 |
+
|
| 242 |
+
Observation Structure
|
| 243 |
+
~~~~~~~~~~~~~~~~~~~~
|
| 244 |
+
|
| 245 |
+
Each agent receives an observation (state) dictionary with rich information about the game:
|
| 246 |
+
|
| 247 |
+
.. code-block:: python
|
| 248 |
+
|
| 249 |
+
{
|
| 250 |
+
"mode": str, # Game mode ("coop" or "comp")
|
| 251 |
+
"role_values": dict, # Value mappings for each role
|
| 252 |
+
"role_props": dict, # Properties for each role
|
| 253 |
+
"agent_to_role": dict, # Mapping from agent IDs to roles
|
| 254 |
+
"is_new_round": bool, # Whether this is the start of a new round
|
| 255 |
+
"is_new_game": bool, # Whether this is the start of a new game
|
| 256 |
+
"game_over": bool, # Whether the game is over
|
| 257 |
+
"items": list, # List of item names
|
| 258 |
+
"quantities": dict, # Quantities of each item
|
| 259 |
+
"has_finalized": bool, # Whether finalization has been proposed
|
| 260 |
+
"last_message": dict, # The last message sent
|
| 261 |
+
"messages_remaining": dict, # Number of messages each agent can still send
|
| 262 |
+
# And various history tracking fields
|
| 263 |
+
}
|
| 264 |
+
|
| 265 |
+
Action Structure
|
| 266 |
+
~~~~~~~~~~~~~~~
|
| 267 |
+
|
| 268 |
+
Actions can be:
|
| 269 |
+
|
| 270 |
+
1. **Text Messages**: Free-form text for negotiation.
|
| 271 |
+
2. **Finalization Proposals**: Structured data specifying the exact allocation of items.
|
| 272 |
+
|
| 273 |
+
Example finalization format:
|
| 274 |
+
|
| 275 |
+
.. code-block:: python
|
| 276 |
+
|
| 277 |
+
{
|
| 278 |
+
"type": "finalize",
|
| 279 |
+
"allocation": {
|
| 280 |
+
"agent1": {"book": 3, "hat": 0, "ball": 6},
|
| 281 |
+
"agent2": {"book": 1, "hat": 2, "ball": 0}
|
| 282 |
+
}
|
| 283 |
+
}
|
| 284 |
+
|
| 285 |
+
Value Setup Functions
|
| 286 |
+
--------------------
|
| 287 |
+
|
| 288 |
+
The DoND environment provides several functions for setting up item values:
|
| 289 |
+
|
| 290 |
+
.. code-block:: python
|
| 291 |
+
|
| 292 |
+
def dond_random_setup(items, min_quant, max_quant, min_val, max_val, random_seed=None):
|
| 293 |
+
"""
|
| 294 |
+
Generates items, even-numbered quantities and distinct random values for each category for both agents.
|
| 295 |
+
|
| 296 |
+
Args:
|
| 297 |
+
items (list): List of items.
|
| 298 |
+
min_quant (int): Minimum quantity per item.
|
| 299 |
+
max_quant (int): Maximum quantity per item.
|
| 300 |
+
min_val (int): Minimum value per item.
|
| 301 |
+
max_val (int): Maximum value per item.
|
| 302 |
+
random_seed (int, optional): Seed for random generation.
|
| 303 |
+
|
| 304 |
+
Returns:
|
| 305 |
+
tuple: (items, quantities, (val_starting_negotiator, val_responding_negotiator))
|
| 306 |
+
"""
|
| 307 |
+
# ...
|
| 308 |
+
|
| 309 |
+
def independent_random_vals(items, min_quant, max_quant, min_val, max_val, random_seed=None):
|
| 310 |
+
"""
|
| 311 |
+
Generates random quantities and independent random values for both agents.
|
| 312 |
+
|
| 313 |
+
Args:
|
| 314 |
+
Similar to dond_random_setup
|
| 315 |
+
|
| 316 |
+
Returns:
|
| 317 |
+
tuple: (items, quantities, (val_starting_negotiator, val_responding_negotiator))
|
| 318 |
+
"""
|
| 319 |
+
# ...
|
| 320 |
+
|
| 321 |
+
def bicameral_vals_assignator(items, min_quant, max_quant, low_val_mean, low_val_std, high_val_mean, high_val_std, random_seed=None):
|
| 322 |
+
"""
|
| 323 |
+
Generates values with a bicameral distribution - each agent values half the items highly.
|
| 324 |
+
|
| 325 |
+
Args:
|
| 326 |
+
items (list): List of items.
|
| 327 |
+
min_quant, max_quant: Range for quantities
|
| 328 |
+
low_val_mean, low_val_std: Mean and standard deviation for the "low value" distribution
|
| 329 |
+
high_val_mean, high_val_std: Mean and standard deviation for the "high value" distribution
|
| 330 |
+
random_seed: Seed for reproducibility
|
| 331 |
+
|
| 332 |
+
Returns:
|
| 333 |
+
tuple: (items, quantities, (val_starting_negotiator, val_responding_negotiator))
|
| 334 |
+
"""
|
| 335 |
+
# ...
|
| 336 |
+
|
| 337 |
+
Running DoND Games
|
| 338 |
+
----------------------
|
| 339 |
+
|
| 340 |
+
To run Deal or No Deal games with LLM agents, you can use the following structure:
|
| 341 |
+
|
| 342 |
+
.. code-block:: python
|
| 343 |
+
|
| 344 |
+
from mllm.environments.dond.dond_game import DondEnv
|
| 345 |
+
from mllm.environments.dond.dond_agent import DondAgent
|
| 346 |
+
from src.run_matches import run_batched_matches
|
| 347 |
+
|
| 348 |
+
# Create environment
|
| 349 |
+
env = DondEnv(
|
| 350 |
+
agents=["agent1", "agent2"],
|
| 351 |
+
mode="coop",
|
| 352 |
+
max_messages=10,
|
| 353 |
+
rounds_per_game=1,
|
| 354 |
+
random_setup_func="dond_random_setup",
|
| 355 |
+
random_setup_kwargs={
|
| 356 |
+
"items": ["book", "hat", "ball"],
|
| 357 |
+
"min_quant": 2,
|
| 358 |
+
"max_quant": 8,
|
| 359 |
+
"min_val": 1,
|
| 360 |
+
"max_val": 10
|
| 361 |
+
},
|
| 362 |
+
finalization_visibility=False
|
| 363 |
+
)
|
| 364 |
+
|
| 365 |
+
# Create agent handlers (implementation details would vary)
|
| 366 |
+
agent_handlers = {
|
| 367 |
+
"agent1": DondAgent(agent_id="agent1"),
|
| 368 |
+
"agent2": DondAgent(agent_id="agent2")
|
| 369 |
+
}
|
| 370 |
+
|
| 371 |
+
# Define policy mapping
|
| 372 |
+
policy_mapping = {
|
| 373 |
+
"llm_policy": my_llm_policy_function
|
| 374 |
+
}
|
| 375 |
+
|
| 376 |
+
# Run the game
|
| 377 |
+
game_results = run_batched_matches(
|
| 378 |
+
envs=[env],
|
| 379 |
+
agent_handlers_per_env=[agent_handlers],
|
| 380 |
+
policy_mapping=policy_mapping,
|
| 381 |
+
max_parallel_matches=1
|
| 382 |
+
)
|
| 383 |
+
|
| 384 |
+
Limitations and Considerations
|
| 385 |
+
-----------------------------
|
| 386 |
+
|
| 387 |
+
1. **Negotiation Complexity**: The open-ended nature of negotiations can be challenging for some LLM agents.
|
| 388 |
+
|
| 389 |
+
2. **Parsing Challenges**: Extracting structured finalization proposals from free-form text requires robust parsing.
|
| 390 |
+
|
| 391 |
+
3. **Optimization Opportunities**: Different agents may employ different negotiation strategies to optimize outcomes.
|
| 392 |
+
|
| 393 |
+
4. **Fairness Evaluation**: The environment allows research into questions of fair division and Pareto optimality.
|
| 394 |
+
|
| 395 |
+
5. **Strategic Deception**: Agents might strategically misrepresent their true values, adding complexity to negotiations.
|
| 396 |
+
|
| 397 |
+
Advanced Usage
|
| 398 |
+
------------
|
| 399 |
+
|
| 400 |
+
For advanced usage, you can:
|
| 401 |
+
|
| 402 |
+
1. **Custom Value Functions**: Create more complex distributions of item values for specific research questions.
|
| 403 |
+
|
| 404 |
+
2. **Novel Negotiation Scenarios**: Design item sets and values to test specific negotiation skills.
|
| 405 |
+
|
| 406 |
+
3. **Curriculum Learning**: Create progressively more difficult negotiation scenarios.
|
| 407 |
+
|
| 408 |
+
4. **Communication Analysis**: Analyze the language and strategies used in successful negotiations.
|
| 409 |
+
|
| 410 |
+
5. **Multi-Round Dynamics**: Study how agents adapt their strategies over multiple rounds.
|
src_code_for_reproducibility/docs/source/modules.rst
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
src
|
| 2 |
+
===
|
| 3 |
+
|
| 4 |
+
.. toctree::
|
| 5 |
+
:maxdepth: 4
|
| 6 |
+
|
| 7 |
+
src
|
src_code_for_reproducibility/docs/source/src.environments.dond.dond_statistics_funcs.rst
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
src.environments.dond.dond\_statistics\_funcs module
|
| 2 |
+
====================================================
|
| 3 |
+
|
| 4 |
+
.. automodule:: src.environments.dond.dond_statistics_funcs
|
| 5 |
+
:members:
|
| 6 |
+
:undoc-members:
|
| 7 |
+
:show-inheritance:
|
src_code_for_reproducibility/docs/source/src.environments.dond.rst
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
src.environments.dond package
|
| 2 |
+
=============================
|
| 3 |
+
|
| 4 |
+
.. automodule:: src.environments.dond
|
| 5 |
+
:members:
|
| 6 |
+
:undoc-members:
|
| 7 |
+
:show-inheritance:
|
| 8 |
+
|
| 9 |
+
Submodules
|
| 10 |
+
----------
|
| 11 |
+
|
| 12 |
+
.. toctree::
|
| 13 |
+
:maxdepth: 4
|
| 14 |
+
|
| 15 |
+
src.environments.dond.dond_agent
|
| 16 |
+
src.environments.dond.dond_game
|
| 17 |
+
src.environments.dond.dond_log_funcs
|
| 18 |
+
src.environments.dond.dond_statistics_funcs
|
| 19 |
+
src.environments.dond.dond_training_data_funcs
|
src_code_for_reproducibility/docs/source/src.environments.ipd.ipd_log_funcs.rst
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
src.environments.ipd.ipd\_log\_funcs module
|
| 2 |
+
===========================================
|
| 3 |
+
|
| 4 |
+
.. automodule:: src.environments.ipd.ipd_log_funcs
|
| 5 |
+
:members:
|
| 6 |
+
:undoc-members:
|
| 7 |
+
:show-inheritance:
|
src_code_for_reproducibility/docs/source/src.environments.ipd.ipd_training_data_funcs.rst
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
src.environments.ipd.ipd\_training\_data\_funcs module
|
| 2 |
+
======================================================
|
| 3 |
+
|
| 4 |
+
.. automodule:: src.environments.ipd.ipd_training_data_funcs
|
| 5 |
+
:members:
|
| 6 |
+
:undoc-members:
|
| 7 |
+
:show-inheritance:
|
src_code_for_reproducibility/docs/source/src.environments.ipd.rst
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
src.environments.ipd package
|
| 2 |
+
============================
|
| 3 |
+
|
| 4 |
+
.. automodule:: src.environments.ipd
|
| 5 |
+
:members:
|
| 6 |
+
:undoc-members:
|
| 7 |
+
:show-inheritance:
|
| 8 |
+
|
| 9 |
+
Submodules
|
| 10 |
+
----------
|
| 11 |
+
|
| 12 |
+
.. toctree::
|
| 13 |
+
:maxdepth: 4
|
| 14 |
+
|
| 15 |
+
src.environments.ipd.ipd_agent
|
| 16 |
+
src.environments.ipd.ipd_game
|
| 17 |
+
src.environments.ipd.ipd_log_funcs
|
| 18 |
+
src.environments.ipd.ipd_statistics_funcs
|
| 19 |
+
src.environments.ipd.ipd_training_data_funcs
|
src_code_for_reproducibility/docs/source/src.experiments.dond_run_train.rst
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
src.experiments.dond\_run\_train module
|
| 2 |
+
=======================================
|
| 3 |
+
|
| 4 |
+
.. automodule:: src.experiments.dond_run_train
|
| 5 |
+
:members:
|
| 6 |
+
:undoc-members:
|
| 7 |
+
:show-inheritance:
|
src_code_for_reproducibility/docs/source/src.experiments.generate_and_train.rst
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
src.experiments.generate\_and\_train module
|
| 2 |
+
===========================================
|
| 3 |
+
|
| 4 |
+
.. automodule:: src.experiments.generate_and_train
|
| 5 |
+
:members:
|
| 6 |
+
:undoc-members:
|
| 7 |
+
:show-inheritance:
|
src_code_for_reproducibility/docs/source/src.experiments.rst
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
src.experiments package
|
| 2 |
+
=======================
|
| 3 |
+
|
| 4 |
+
.. automodule:: src.experiments
|
| 5 |
+
:members:
|
| 6 |
+
:undoc-members:
|
| 7 |
+
:show-inheritance:
|
| 8 |
+
|
| 9 |
+
Submodules
|
| 10 |
+
----------
|
| 11 |
+
|
| 12 |
+
.. toctree::
|
| 13 |
+
:maxdepth: 4
|
| 14 |
+
|
| 15 |
+
src.experiments.arithmetic_test
|
| 16 |
+
src.experiments.generate_and_train
|
| 17 |
+
src.experiments.last_completion
|
src_code_for_reproducibility/docs/source/src.generation.run_games.rst
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
src.generation.run\_games module
|
| 2 |
+
================================
|
| 3 |
+
|
| 4 |
+
.. automodule:: src.generation.run_games
|
| 5 |
+
:members:
|
| 6 |
+
:undoc-members:
|
| 7 |
+
:show-inheritance:
|
src_code_for_reproducibility/docs/source/src.models.dummy_hf_agent.rst
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
src.models.dummy\_hf\_agent module
|
| 2 |
+
==================================
|
| 3 |
+
|
| 4 |
+
.. automodule:: src.models.dummy_llm_agent
|
| 5 |
+
:members:
|
| 6 |
+
:undoc-members:
|
| 7 |
+
:show-inheritance:
|
src_code_for_reproducibility/docs/source/src.models.hf_agent.rst
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
src.models.hf\_agent module
|
| 2 |
+
===========================
|
| 3 |
+
|
| 4 |
+
.. automodule:: src.models.hf_agent
|
| 5 |
+
:members:
|
| 6 |
+
:undoc-members:
|
| 7 |
+
:show-inheritance:
|
src_code_for_reproducibility/docs/source/src.models.oai_agent.rst
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
src.models.oai\_agent module
|
| 2 |
+
============================
|
| 3 |
+
|
| 4 |
+
.. automodule:: src.models.oai_agent
|
| 5 |
+
:members:
|
| 6 |
+
:undoc-members:
|
| 7 |
+
:show-inheritance:
|
src_code_for_reproducibility/docs/source/src.models.server_llm.rst
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
src.models.server\_llm module
|
| 2 |
+
=============================
|
| 3 |
+
|
| 4 |
+
.. automodule:: src.models.server_llm
|
| 5 |
+
:members:
|
| 6 |
+
:undoc-members:
|
| 7 |
+
:show-inheritance:
|
src_code_for_reproducibility/docs/source/src.models.vllm_worker_wrap.rst
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
src.models.vllm\_worker\_wrap module
|
| 2 |
+
====================================
|
| 3 |
+
|
| 4 |
+
.. automodule:: src.models.vllm_worker_wrap
|
| 5 |
+
:members:
|
| 6 |
+
:undoc-members:
|
| 7 |
+
:show-inheritance:
|
src_code_for_reproducibility/docs/source/src.rst
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
src package
|
| 2 |
+
===========
|
| 3 |
+
|
| 4 |
+
.. automodule:: src
|
| 5 |
+
:members:
|
| 6 |
+
:undoc-members:
|
| 7 |
+
:show-inheritance:
|
| 8 |
+
|
| 9 |
+
Subpackages
|
| 10 |
+
-----------
|
| 11 |
+
|
| 12 |
+
.. toctree::
|
| 13 |
+
:maxdepth: 4
|
| 14 |
+
|
| 15 |
+
src.environments
|
| 16 |
+
src.experiments
|
| 17 |
+
src.generation
|
| 18 |
+
src.models
|
| 19 |
+
src.training
|
| 20 |
+
src.utils
|
| 21 |
+
|
| 22 |
+
Submodules
|
| 23 |
+
----------
|
| 24 |
+
|
| 25 |
+
.. toctree::
|
| 26 |
+
:maxdepth: 4
|
| 27 |
+
|
| 28 |
+
src.run
|
src_code_for_reproducibility/docs/source/src.run.rst
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
src.run module
|
| 2 |
+
==============
|
| 3 |
+
|
| 4 |
+
.. automodule:: src.run
|
| 5 |
+
:members:
|
| 6 |
+
:undoc-members:
|
| 7 |
+
:show-inheritance:
|
src_code_for_reproducibility/docs/source/src.training.ppo_train_value_head.rst
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
src.training.ppo\_train\_value\_head module
|
| 2 |
+
===========================================
|
| 3 |
+
|
| 4 |
+
.. automodule:: src.training.ppo_train_value_head
|
| 5 |
+
:members:
|
| 6 |
+
:undoc-members:
|
| 7 |
+
:show-inheritance:
|
src_code_for_reproducibility/docs/source/src.utils.common_imports.rst
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
src.utils.common\_imports module
|
| 2 |
+
================================
|
| 3 |
+
|
| 4 |
+
.. automodule:: src.utils.common_imports
|
| 5 |
+
:members:
|
| 6 |
+
:undoc-members:
|
| 7 |
+
:show-inheritance:
|
src_code_for_reproducibility/docs/source/src.utils.export_ppo_training_set.rst
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
src.utils.export\_ppo\_training\_set module
|
| 2 |
+
===========================================
|
| 3 |
+
|
| 4 |
+
.. automodule:: src.utils.export_ppo_training_set
|
| 5 |
+
:members:
|
| 6 |
+
:undoc-members:
|
| 7 |
+
:show-inheritance:
|
src_code_for_reproducibility/docs/source/src.utils.log_statistics.rst
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
src.utils.log\_statistics module
|
| 2 |
+
================================
|
| 3 |
+
|
| 4 |
+
.. automodule:: src.utils.log_statistics
|
| 5 |
+
:members:
|
| 6 |
+
:undoc-members:
|
| 7 |
+
:show-inheritance:
|
src_code_for_reproducibility/docs/source/src.utils.parallel_shuffle.rst
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
src.utils.parallel\_shuffle module
|
| 2 |
+
==================================
|
| 3 |
+
|
| 4 |
+
.. automodule:: src.utils.parallel_shuffle
|
| 5 |
+
:members:
|
| 6 |
+
:undoc-members:
|
| 7 |
+
:show-inheritance:
|
src_code_for_reproducibility/markov_games/__init__.py
ADDED
|
File without changes
|
src_code_for_reproducibility/markov_games/__pycache__/mg_utils.cpython-312.pyc
ADDED
|
Binary file (3.98 kB). View file
|
|
|
src_code_for_reproducibility/markov_games/agent.py
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
In simple RL paradise, where the action dimensions are constant and well defined,
|
| 3 |
+
Agent classes are not necessary. But in MARL, with LLM's, there isn't always
|
| 4 |
+
a direct path from policy to action. For instance, from the observation of the environment,
|
| 5 |
+
a prompt must be created. Then, the outputs of the policy might be incorrect, so a second
|
| 6 |
+
request to the LLM must be sent before the action is well defined. This is why this Agent class exists.
|
| 7 |
+
It acts as a mini environment, bridging the gap between the core simulation and
|
| 8 |
+
the LLM policies.
|
| 9 |
+
"""
|
| 10 |
+
|
| 11 |
+
from abc import ABC, abstractmethod
|
| 12 |
+
from collections.abc import Callable
|
| 13 |
+
from typing import Any, Tuple
|
| 14 |
+
|
| 15 |
+
from numpy.random import default_rng
|
| 16 |
+
|
| 17 |
+
from mllm.markov_games.rollout_tree import AgentActLog
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
class Agent(ABC):
|
| 21 |
+
@abstractmethod
|
| 22 |
+
def __init__(
|
| 23 |
+
self,
|
| 24 |
+
seed: int,
|
| 25 |
+
agent_id: str,
|
| 26 |
+
agent_name: str,
|
| 27 |
+
agent_policy: Callable[[list[dict]], str],
|
| 28 |
+
*args,
|
| 29 |
+
**kwargs,
|
| 30 |
+
):
|
| 31 |
+
"""
|
| 32 |
+
Initialize the agent state.
|
| 33 |
+
"""
|
| 34 |
+
self.seed = seed
|
| 35 |
+
self.agent_id = agent_id
|
| 36 |
+
self.agent_name = agent_name
|
| 37 |
+
self.policy = policy
|
| 38 |
+
self.rng = default_rng(self.seed)
|
| 39 |
+
raise NotImplementedError
|
| 40 |
+
|
| 41 |
+
async def act(self, observation) -> Tuple[Any, AgentActLog]:
|
| 42 |
+
"""
|
| 43 |
+
Query (possibly multiple times) a policy (or possibly a pool of policies) to
|
| 44 |
+
obtain the action of the agent.
|
| 45 |
+
|
| 46 |
+
Example:
|
| 47 |
+
action = None
|
| 48 |
+
prompt = self.observation_to_prompt(observation)
|
| 49 |
+
while not self.valid(action):
|
| 50 |
+
output = await self.policy.generate(prompt)
|
| 51 |
+
action = self.policy_output_to_action(output)
|
| 52 |
+
return action
|
| 53 |
+
|
| 54 |
+
Returns:
|
| 55 |
+
action
|
| 56 |
+
step_info
|
| 57 |
+
"""
|
| 58 |
+
raise NotImplementedError
|
| 59 |
+
|
| 60 |
+
def get_safe_copy(self):
|
| 61 |
+
"""
|
| 62 |
+
Return copy of the agent object that is decorrelated from the original object.
|
| 63 |
+
"""
|
| 64 |
+
raise NotImplementedError
|
| 65 |
+
|
| 66 |
+
def reset(self):
|
| 67 |
+
raise NotImplementedError
|
| 68 |
+
|
| 69 |
+
def render(self):
|
| 70 |
+
raise NotImplementedError
|
| 71 |
+
|
| 72 |
+
def close(self):
|
| 73 |
+
raise NotImplementedError
|
| 74 |
+
|
| 75 |
+
def get_agent_info(self):
|
| 76 |
+
raise NotImplementedError
|
src_code_for_reproducibility/markov_games/alternative_actions_runner.py
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import asyncio
|
| 2 |
+
import copy
|
| 3 |
+
import json
|
| 4 |
+
import os.path
|
| 5 |
+
from typing import Any, Tuple
|
| 6 |
+
|
| 7 |
+
from mllm.markov_games.markov_game import AgentAndActionSafeCopy, MarkovGame
|
| 8 |
+
from mllm.markov_games.rollout_tree import (
|
| 9 |
+
AgentActLog,
|
| 10 |
+
RolloutTreeBranchNode,
|
| 11 |
+
RolloutTreeNode,
|
| 12 |
+
RolloutTreeRootNode,
|
| 13 |
+
StepLog,
|
| 14 |
+
)
|
| 15 |
+
|
| 16 |
+
AgentId = str
|
| 17 |
+
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
async def run_with_unilateral_alt_action(
|
| 21 |
+
markov_game: MarkovGame,
|
| 22 |
+
agent_id: AgentId,
|
| 23 |
+
time_step: int,
|
| 24 |
+
branch_node: RolloutTreeBranchNode,
|
| 25 |
+
max_depth: int,
|
| 26 |
+
):
|
| 27 |
+
"""
|
| 28 |
+
This function is used to generate a new branch for a given agent.
|
| 29 |
+
"""
|
| 30 |
+
|
| 31 |
+
# Generate alternative action and take a step
|
| 32 |
+
await markov_game.set_action_of_agent(agent_id)
|
| 33 |
+
terminated: bool = markov_game.take_simulation_step()
|
| 34 |
+
step_log = markov_game.get_step_log()
|
| 35 |
+
first_alternative_node = RolloutTreeNode(
|
| 36 |
+
step_log=step_log,
|
| 37 |
+
time_step=time_step,
|
| 38 |
+
)
|
| 39 |
+
|
| 40 |
+
# Generate rest of trajectory up to max depth
|
| 41 |
+
time_step += 1
|
| 42 |
+
counter = 1
|
| 43 |
+
previous_node = first_alternative_node
|
| 44 |
+
while not terminated and counter <= max_depth:
|
| 45 |
+
terminated, step_log = await markov_game.step()
|
| 46 |
+
current_node = RolloutTreeNode(step_log=step_log, time_step=time_step)
|
| 47 |
+
previous_node.child = current_node
|
| 48 |
+
previous_node = current_node
|
| 49 |
+
counter += 1
|
| 50 |
+
time_step += 1
|
| 51 |
+
|
| 52 |
+
if branch_node.branches == None:
|
| 53 |
+
branch_node.branches = {agent_id: [first_alternative_node]}
|
| 54 |
+
else:
|
| 55 |
+
agent_branches = branch_node.branches.get(agent_id, [])
|
| 56 |
+
agent_branches.append(first_alternative_node)
|
| 57 |
+
branch_node.branches[agent_id] = agent_branches
|
| 58 |
+
|
| 59 |
+
|
| 60 |
+
async def AlternativeActionsRunner(
|
| 61 |
+
markov_game: MarkovGame,
|
| 62 |
+
output_folder: str,
|
| 63 |
+
nb_alternative_actions: int,
|
| 64 |
+
max_depth: int,
|
| 65 |
+
branch_only_on_new_round: bool = False,
|
| 66 |
+
):
|
| 67 |
+
"""
|
| 68 |
+
This method generates a trajectory with partially completed branches,
|
| 69 |
+
where the branching comes from taking unilateraly different actions.
|
| 70 |
+
The resulting data is used to estimate the updated advantage alignment policy gradient terms.
|
| 71 |
+
Let k := nb_sub_steps. Then the number of steps generated is O(Tk), where T is
|
| 72 |
+
the maximum trajectory length.
|
| 73 |
+
"""
|
| 74 |
+
|
| 75 |
+
tasks = []
|
| 76 |
+
time_step = 0
|
| 77 |
+
terminated = False
|
| 78 |
+
root = RolloutTreeRootNode(
|
| 79 |
+
id=markov_game.get_id(),
|
| 80 |
+
crn_id=markov_game.get_crn_id()
|
| 81 |
+
)
|
| 82 |
+
previous_node = root
|
| 83 |
+
|
| 84 |
+
while not terminated:
|
| 85 |
+
mg_before_action = markov_game.get_safe_copy()
|
| 86 |
+
|
| 87 |
+
# Get safe copies for main branch
|
| 88 |
+
agent_action_safe_copies: dict[
|
| 89 |
+
AgentId, AgentAndActionSafeCopy
|
| 90 |
+
] = await markov_game.get_actions_of_agents_without_side_effects()
|
| 91 |
+
|
| 92 |
+
markov_game.set_actions_of_agents_manually(agent_action_safe_copies)
|
| 93 |
+
terminated = markov_game.take_simulation_step()
|
| 94 |
+
main_node = RolloutTreeNode(
|
| 95 |
+
step_log=markov_game.get_step_log(), time_step=time_step
|
| 96 |
+
)
|
| 97 |
+
branch_node = RolloutTreeBranchNode(main_child=main_node)
|
| 98 |
+
previous_node.child = branch_node
|
| 99 |
+
previous_node = main_node
|
| 100 |
+
|
| 101 |
+
# Get alternative branches by generating new unilateral actions
|
| 102 |
+
for agent_id in markov_game.agent_ids:
|
| 103 |
+
for _ in range(nb_alternative_actions):
|
| 104 |
+
# Get safe copies for branches
|
| 105 |
+
branch_agent_action_safe_copies: dict[
|
| 106 |
+
AgentId, AgentAndActionSafeCopy
|
| 107 |
+
] = {
|
| 108 |
+
agent_id: AgentAndActionSafeCopy(
|
| 109 |
+
action=copy.deepcopy(agent_action_safe_copy.action),
|
| 110 |
+
action_info=copy.deepcopy(agent_action_safe_copy.action_info),
|
| 111 |
+
agent_after_action=agent_action_safe_copy.agent_after_action.get_safe_copy(),
|
| 112 |
+
)
|
| 113 |
+
for agent_id, agent_action_safe_copy in agent_action_safe_copies.items()
|
| 114 |
+
}
|
| 115 |
+
mg_branch: MarkovGame = mg_before_action.get_safe_copy()
|
| 116 |
+
other_agent_id = [id for id in mg_branch.agent_ids if id != agent_id][0]
|
| 117 |
+
mg_branch.set_action_and_agent_after_action_manually(
|
| 118 |
+
agent_id=other_agent_id,
|
| 119 |
+
agent_action_safe_copy=branch_agent_action_safe_copies[
|
| 120 |
+
other_agent_id
|
| 121 |
+
],
|
| 122 |
+
)
|
| 123 |
+
task = asyncio.create_task(
|
| 124 |
+
run_with_unilateral_alt_action(
|
| 125 |
+
markov_game=mg_branch,
|
| 126 |
+
time_step=time_step,
|
| 127 |
+
agent_id=agent_id,
|
| 128 |
+
branch_node=branch_node,
|
| 129 |
+
max_depth=max_depth,
|
| 130 |
+
)
|
| 131 |
+
)
|
| 132 |
+
tasks.append(task)
|
| 133 |
+
time_step += 1
|
| 134 |
+
|
| 135 |
+
# wait for all branches to complete
|
| 136 |
+
await asyncio.gather(*tasks)
|
| 137 |
+
|
| 138 |
+
return root
|
src_code_for_reproducibility/markov_games/linear_runner.py
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import asyncio
|
| 2 |
+
import json
|
| 3 |
+
import os.path
|
| 4 |
+
|
| 5 |
+
from mllm.markov_games.markov_game import MarkovGame
|
| 6 |
+
from mllm.markov_games.rollout_tree import RolloutTreeNode, RolloutTreeRootNode
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
async def LinearRunner(
|
| 10 |
+
markov_game: MarkovGame, output_folder: str
|
| 11 |
+
) -> RolloutTreeRootNode:
|
| 12 |
+
"""
|
| 13 |
+
This method generates a trajectory without branching.
|
| 14 |
+
"""
|
| 15 |
+
time_step = 0
|
| 16 |
+
terminated = False
|
| 17 |
+
root = RolloutTreeRootNode(
|
| 18 |
+
id=markov_game.get_id(),
|
| 19 |
+
crn_id=markov_game.get_crn_id(),
|
| 20 |
+
agent_ids=markov_game.get_agent_ids(),
|
| 21 |
+
)
|
| 22 |
+
previous_node = root
|
| 23 |
+
while not terminated:
|
| 24 |
+
terminated, step_log = await markov_game.step()
|
| 25 |
+
current_node = RolloutTreeNode(step_log=step_log, time_step=time_step)
|
| 26 |
+
previous_node.child = current_node
|
| 27 |
+
previous_node = current_node
|
| 28 |
+
time_step += 1
|
| 29 |
+
|
| 30 |
+
return root
|
src_code_for_reproducibility/markov_games/mg_utils.py
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import asyncio
|
| 2 |
+
import copy
|
| 3 |
+
from collections.abc import Callable
|
| 4 |
+
from dataclasses import dataclass
|
| 5 |
+
|
| 6 |
+
from mllm.markov_games.ipd.ipd_agent import IPDAgent
|
| 7 |
+
from mllm.markov_games.ipd.ipd_simulation import IPD
|
| 8 |
+
from mllm.markov_games.markov_game import MarkovGame
|
| 9 |
+
from mllm.markov_games.negotiation.dond_agent import DealNoDealAgent
|
| 10 |
+
from mllm.markov_games.negotiation.dond_simulation import DealNoDealSimulation
|
| 11 |
+
from mllm.markov_games.negotiation.nego_hard_coded_policies import (
|
| 12 |
+
HardCodedNegoGreedyPolicy,
|
| 13 |
+
HardCodedNegoWelfareMaximizingPolicy,
|
| 14 |
+
)
|
| 15 |
+
from mllm.markov_games.ipd.Ipd_hard_coded_agents import AlwaysCooperateIPDAgent, AlwaysDefectIPDAgent
|
| 16 |
+
from mllm.markov_games.negotiation.no_press_nego_agent import NoPressAgent
|
| 17 |
+
from mllm.markov_games.negotiation.no_press_nego_simulation import NoPressSimulation
|
| 18 |
+
from mllm.markov_games.negotiation.tas_agent import TrustAndSplitAgent
|
| 19 |
+
from mllm.markov_games.negotiation.tas_rps_agent import TrustAndSplitRPSAgent
|
| 20 |
+
from mllm.markov_games.negotiation.tas_rps_simulation import TrustAndSplitRPSSimulation
|
| 21 |
+
from mllm.markov_games.negotiation.tas_simple_agent import TrustAndSplitSimpleAgent
|
| 22 |
+
from mllm.markov_games.negotiation.tas_simple_simulation import (
|
| 23 |
+
TrustAndSplitSimpleSimulation,
|
| 24 |
+
)
|
| 25 |
+
from mllm.markov_games.negotiation.tas_simulation import TrustAndSplitSimulation
|
| 26 |
+
from mllm.markov_games.rollout_tree import (
|
| 27 |
+
AgentActLog,
|
| 28 |
+
RolloutTreeBranchNode,
|
| 29 |
+
RolloutTreeNode,
|
| 30 |
+
RolloutTreeRootNode,
|
| 31 |
+
StepLog,
|
| 32 |
+
)
|
| 33 |
+
from mllm.markov_games.simulation import SimulationStepLog
|
| 34 |
+
|
| 35 |
+
AgentId = str
|
| 36 |
+
|
| 37 |
+
|
| 38 |
+
@dataclass
|
| 39 |
+
class AgentConfig:
|
| 40 |
+
agent_id: str
|
| 41 |
+
agent_name: str
|
| 42 |
+
agent_class_name: str
|
| 43 |
+
policy_id: str
|
| 44 |
+
init_kwargs: dict
|
| 45 |
+
|
| 46 |
+
|
| 47 |
+
@dataclass
|
| 48 |
+
class MarkovGameConfig:
|
| 49 |
+
id: int
|
| 50 |
+
seed: int
|
| 51 |
+
simulation_class_name: str
|
| 52 |
+
simulation_init_args: dict
|
| 53 |
+
agent_configs: list[AgentConfig]
|
| 54 |
+
|
| 55 |
+
|
| 56 |
+
def init_markov_game_components(
|
| 57 |
+
config: MarkovGameConfig, policies: dict[str, Callable[[list[dict]], str]]
|
| 58 |
+
):
|
| 59 |
+
"""
|
| 60 |
+
TOWRITE
|
| 61 |
+
"""
|
| 62 |
+
agents = {}
|
| 63 |
+
agent_names = []
|
| 64 |
+
for agent_config in config.agent_configs:
|
| 65 |
+
agent_id = agent_config.agent_id
|
| 66 |
+
agent_name = agent_config.agent_name
|
| 67 |
+
agent_class = eval(agent_config.agent_class_name)
|
| 68 |
+
agent = agent_class(
|
| 69 |
+
seed=config.seed,
|
| 70 |
+
agent_id=agent_id,
|
| 71 |
+
agent_name=agent_name,
|
| 72 |
+
policy=policies[agent_config.policy_id],
|
| 73 |
+
**agent_config.init_kwargs,
|
| 74 |
+
)
|
| 75 |
+
agents[agent_id] = agent
|
| 76 |
+
agent_names.append(agent_name)
|
| 77 |
+
simulation = eval(config.simulation_class_name)(
|
| 78 |
+
seed=config.seed,
|
| 79 |
+
agent_ids=list(agents.keys()),
|
| 80 |
+
agent_names=agent_names,
|
| 81 |
+
**config.simulation_init_args,
|
| 82 |
+
)
|
| 83 |
+
markov_game = MarkovGame(
|
| 84 |
+
id=config.id,
|
| 85 |
+
crn_id=config.seed,
|
| 86 |
+
agents=agents,
|
| 87 |
+
simulation=simulation,
|
| 88 |
+
)
|
| 89 |
+
return markov_game
|
src_code_for_reproducibility/markov_games/negotiation/__pycache__/tas_simple_simulation.cpython-312.pyc
ADDED
|
Binary file (8.68 kB). View file
|
|
|
src_code_for_reproducibility/markov_games/rollout_tree.py
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
TODO: add parent to nodes so that some verification can be done. For instance, to ensure that node reward keys match the parent node.
|
| 3 |
+
"""
|
| 4 |
+
|
| 5 |
+
from __future__ import annotations
|
| 6 |
+
|
| 7 |
+
import json
|
| 8 |
+
from dataclasses import dataclass
|
| 9 |
+
from pathlib import Path
|
| 10 |
+
from typing import Any, List, Literal, Optional, Tuple
|
| 11 |
+
|
| 12 |
+
import jsonschema
|
| 13 |
+
from pydantic import BaseModel, Field, model_validator
|
| 14 |
+
|
| 15 |
+
from mllm.chat_utils.chat_turn import ChatTurn
|
| 16 |
+
|
| 17 |
+
AgentId = str
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
class SimulationStepLog(BaseModel):
|
| 21 |
+
rewards: dict[AgentId, float]
|
| 22 |
+
info: Any = None
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
class AgentActLog(BaseModel):
|
| 26 |
+
chat_turns: list[ChatTurn] | None
|
| 27 |
+
info: Any = None
|
| 28 |
+
|
| 29 |
+
@model_validator(mode="after")
|
| 30 |
+
def _exactly_one_state_end(self):
|
| 31 |
+
"""
|
| 32 |
+
This method is used to enforce that for each AgentActLog, there is exactly one ChatTurn which is a state end.
|
| 33 |
+
"""
|
| 34 |
+
if self.chat_turns != []:
|
| 35 |
+
n = sum(1 for t in self.chat_turns if t.is_state_end)
|
| 36 |
+
if n != 1:
|
| 37 |
+
raise ValueError(
|
| 38 |
+
f"AgentActLog must have exactly one ChatTurn with is_state_end=True; got {self.chat_turns}."
|
| 39 |
+
)
|
| 40 |
+
return self
|
| 41 |
+
else:
|
| 42 |
+
return self
|
| 43 |
+
|
| 44 |
+
|
| 45 |
+
class StepLog(BaseModel):
|
| 46 |
+
action_logs: dict[AgentId, AgentActLog]
|
| 47 |
+
simulation_step_log: SimulationStepLog
|
| 48 |
+
|
| 49 |
+
|
| 50 |
+
# BranchType = Literal["unilateral_deviation", "common_deviation"] # might not be necessary
|
| 51 |
+
# class BranchNodeInfo(BaseModel):
|
| 52 |
+
# branch_id: str
|
| 53 |
+
# branch_for: AgentId
|
| 54 |
+
# branch_type: BranchType
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
class RolloutTreeNode(BaseModel):
|
| 58 |
+
step_log: StepLog
|
| 59 |
+
time_step: int
|
| 60 |
+
child: RolloutTreeNode | RolloutTreeBranchNode | None = None
|
| 61 |
+
|
| 62 |
+
|
| 63 |
+
class RolloutTreeBranchNode(BaseModel):
|
| 64 |
+
"""
|
| 65 |
+
First item of the tuple indicates which agent "called" for an alternative branch.
|
| 66 |
+
"""
|
| 67 |
+
|
| 68 |
+
main_child: RolloutTreeNode
|
| 69 |
+
branches: dict[AgentId, list[RolloutTreeNode]] | None = None
|
| 70 |
+
|
| 71 |
+
|
| 72 |
+
class RolloutTreeRootNode(BaseModel):
|
| 73 |
+
id: int
|
| 74 |
+
crn_id: int # ID of the rng used to generate this rollout tree
|
| 75 |
+
child: RolloutTreeNode | RolloutTreeBranchNode | None = None
|
| 76 |
+
agent_ids: List[AgentId] = Field(min_length=1)
|
| 77 |
+
|
| 78 |
+
|
| 79 |
+
# class RolloutTreeLeafNode(BaseModel):
|
| 80 |
+
# step_log: StepLog
|
| 81 |
+
# time_step: int
|
| 82 |
+
|
| 83 |
+
|
| 84 |
+
# Necessary for self-referential stuff in pydantic
|
| 85 |
+
RolloutTreeBranchNode.model_rebuild()
|
| 86 |
+
RolloutTreeNode.model_rebuild()
|
src_code_for_reproducibility/markov_games/run_markov_games.py
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import asyncio
|
| 2 |
+
from collections.abc import Callable
|
| 3 |
+
from dataclasses import dataclass
|
| 4 |
+
|
| 5 |
+
from torch._C import ClassType
|
| 6 |
+
|
| 7 |
+
from mllm.markov_games.markov_game import MarkovGame
|
| 8 |
+
from mllm.markov_games.rollout_tree import RolloutTreeRootNode
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
async def run_markov_games(
|
| 12 |
+
runner: Callable[[MarkovGame], RolloutTreeRootNode],
|
| 13 |
+
runner_kwargs: dict,
|
| 14 |
+
output_folder: str,
|
| 15 |
+
markov_games: list[MarkovGame],
|
| 16 |
+
) -> list[RolloutTreeRootNode]:
|
| 17 |
+
tasks = []
|
| 18 |
+
for mg in markov_games:
|
| 19 |
+
tasks.append(
|
| 20 |
+
asyncio.create_task(
|
| 21 |
+
runner(markov_game=mg, output_folder=output_folder, **runner_kwargs)
|
| 22 |
+
)
|
| 23 |
+
)
|
| 24 |
+
return await asyncio.gather(*tasks)
|
src_code_for_reproducibility/markov_games/simulation.py
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
A Simulation is the environment of a Markov Game.
|
| 3 |
+
The Simulation is not responsible for properly checking / formatting the responses of LLM's.
|
| 4 |
+
This is the job of the `Agent` class.
|
| 5 |
+
Simulations expect clean actions, and are defined similarly to `gymnasium` environments, except that they are adapted for the Multi-agent setting.
|
| 6 |
+
"""
|
| 7 |
+
|
| 8 |
+
from abc import ABC, abstractmethod
|
| 9 |
+
from typing import Any, Tuple
|
| 10 |
+
|
| 11 |
+
from numpy.random import default_rng
|
| 12 |
+
|
| 13 |
+
from mllm.markov_games.rollout_tree import SimulationStepLog
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
class Simulation(ABC):
|
| 17 |
+
@abstractmethod
|
| 18 |
+
def __init__(self, seed: int, *args, **kwargs):
|
| 19 |
+
self.seed = seed
|
| 20 |
+
self.rng = default_rng(self.seed)
|
| 21 |
+
|
| 22 |
+
@abstractmethod
|
| 23 |
+
def step(self, actions: Any) -> Tuple[bool, SimulationStepLog]:
|
| 24 |
+
"""
|
| 25 |
+
Returns terminated, info
|
| 26 |
+
"""
|
| 27 |
+
raise NotImplementedError
|
| 28 |
+
|
| 29 |
+
def get_obs(self):
|
| 30 |
+
"""Returns all agent observations in dict
|
| 31 |
+
|
| 32 |
+
Returns:
|
| 33 |
+
observations
|
| 34 |
+
"""
|
| 35 |
+
raise NotImplementedError
|
| 36 |
+
|
| 37 |
+
def get_obs_agent(self, agent_id):
|
| 38 |
+
"""Returns observation for agent_id"""
|
| 39 |
+
raise NotImplementedError
|
| 40 |
+
|
| 41 |
+
def get_obs_size(self):
|
| 42 |
+
"""Returns the shape of the observation"""
|
| 43 |
+
raise NotImplementedError
|
| 44 |
+
|
| 45 |
+
def get_state(self):
|
| 46 |
+
raise NotImplementedError
|
| 47 |
+
|
| 48 |
+
def get_state_size(self):
|
| 49 |
+
"""Returns the shape of the state"""
|
| 50 |
+
raise NotImplementedError
|
| 51 |
+
|
| 52 |
+
def get_avail_actions(self):
|
| 53 |
+
raise NotImplementedError
|
| 54 |
+
|
| 55 |
+
def get_avail_agent_actions(self, agent_id):
|
| 56 |
+
"""Returns the available actions for agent_id"""
|
| 57 |
+
raise NotImplementedError
|
| 58 |
+
|
| 59 |
+
def get_total_actions(self):
|
| 60 |
+
"""Returns the total number of actions an agent could ever take"""
|
| 61 |
+
# TODO: This is only suitable for a discrete 1 dimensional action space for each agent
|
| 62 |
+
raise NotImplementedError
|
| 63 |
+
|
| 64 |
+
def get_safe_copy(self):
|
| 65 |
+
"""
|
| 66 |
+
Return copy of the agent object that is decorrelated from the original object.
|
| 67 |
+
"""
|
| 68 |
+
raise NotImplementedError
|
| 69 |
+
|
| 70 |
+
def reset(self):
|
| 71 |
+
"""Returns initial observations and states"""
|
| 72 |
+
raise NotImplementedError
|
| 73 |
+
|
| 74 |
+
def render(self):
|
| 75 |
+
raise NotImplementedError
|
| 76 |
+
|
| 77 |
+
def close(self):
|
| 78 |
+
raise NotImplementedError
|
| 79 |
+
|
| 80 |
+
# def seed(self):
|
| 81 |
+
# raise NotImplementedError
|
| 82 |
+
|
| 83 |
+
def save_replay(self):
|
| 84 |
+
raise NotImplementedError
|
| 85 |
+
|
| 86 |
+
def get_simulation_info(self):
|
| 87 |
+
raise NotImplementedError
|
src_code_for_reproducibility/markov_games/vine_ppo.py
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from anytree import Node, RenderTree
|
| 2 |
+
from anytree.exporter import DotExporter
|
| 3 |
+
import os.path
|
| 4 |
+
import asyncio
|
| 5 |
+
from mllm.markov_games.markov_game import MarkovGame
|
| 6 |
+
|
| 7 |
+
async def VinePPORunner(
|
| 8 |
+
markov_game: MarkovGame,
|
| 9 |
+
**kwargs):
|
| 10 |
+
pass
|
src_code_for_reproducibility/models/__pycache__/__init__.cpython-312.pyc
ADDED
|
Binary file (155 Bytes). View file
|
|
|
src_code_for_reproducibility/models/__pycache__/adapter_training_wrapper.cpython-312.pyc
ADDED
|
Binary file (4.92 kB). View file
|
|
|
src_code_for_reproducibility/models/__pycache__/human_policy.cpython-312.pyc
ADDED
|
Binary file (11.9 kB). View file
|
|
|
src_code_for_reproducibility/models/__pycache__/inference_backend_sglang.cpython-312.pyc
ADDED
|
Binary file (3.67 kB). View file
|
|
|
src_code_for_reproducibility/models/__pycache__/large_language_model_api.cpython-312.pyc
ADDED
|
Binary file (6.94 kB). View file
|
|
|