diff --git a/README.md b/README.md
index 15a290c22..54a93a64f 100644
--- a/README.md
+++ b/README.md
@@ -1,87 +1,21 @@
-
-

-
+# User Guide
-Sotopia: an Open-ended Social Learning Environment
-
-
-
-[](https://pypi.python.org/pypi/sotopia)
-[](https://github.com/sotopia/sotopia)
-[](https://github.com/sotopia-lab/sotopia/actions?query=branch%3Amain)
-[](https://codecov.io/github/sotopia-lab/sotopia)
-[](https://colab.research.google.com/drive/14hJOfzpA37PRUzdlFgiqVzUGIhhngqnz?usp=sharing)
-
-[](https://www.sotopia.world/projects/sotopia)
-[](https://arxiv.org/abs/2310.11667)
-[](https://huggingface.co/datasets/cmu-lti/sotopia)
-[](https://huggingface.co/spaces/cmu-lti/sotopia-space/)
-
-
-
-
-
-## News
-
-* [05/2024] Sotopia was presented at ICLR 2024 as a spotlight ⭐!
-
-
-## Introduction
-
-Sotopia is an open-ended social learning environment that allows agents to interact with each other and the environment. The environment is designed to be a platform for evaluating and faciliating social intelligence in language agents. The environment is designed to be open-ended, meaning that the environment can be easily extended to include new environments and new agents. The environment is also designed to be scalable, meaning that the environment can be easily scaled to include a large number of agents and environments.
-
-
-
-```bibtex
-@inproceedings{zhou2024sotopia,
- title = {SOTOPIA: Interactive Evaluation for Social Intelligence in Language Agents},
- author = {Zhou*, Xuhui and Zhu*, Hao and Mathur, Leena and Zhang, Ruohong and Qi, Zhengyang and Yu, Haofei and Morency, Louis-Philippe and Bisk, Yonatan and Fried, Daniel and Neubig, Graham and Sap, Maarten},
- journal = {ICLR},
- year = {2024},
- url = {https://openreview.net/forum?id=mM7VurbA4r},
-}
+```
+cd examples/experimental/minecraft_agents
+uvicorn group_discussion_agents:app --reload --port 8080
```
-## Help
-See [documentation](https://docs.sotopia.world) for more details.
-
-## Get started
-
-### Install locally
-We recommend using a virtual environment, e.g. with anaconda3: `conda create -n sotopia python=3.11; conda activate sotopia;`.
-
-Then:
-`python -m pip install sotopia; sotopia install`
-
-This will setup the necessary environment variables and download the necessary data.
-
-> [!TIP]
-> Having trouble installing? Or don't want to install redis for now? We are working on a public redis server for you to use. Stay tuned!
+Enter `Minecraft Java Edition`, select `Singleplayer`, `1.20.1 version`, and `Survival Mode`, then click `Open to LAN 55916`.
-OpenAI key is required to run the code. Please set the environment variable `OPENAI_API_KEY` to your key. The recommend way is to add the key to the conda environment:
-```bash
-conda env config vars set OPENAI_API_KEY=your_key
+```
+// Open a new terminal
+cd examples/experimental/minecraft_agents
+export OPENAI_API_KEY=sk- // Enter your OpenAI API key here
+uv run aact run-dataflow group_discussion_agents.toml
```
-## Easy Sample Server
-You can view an episode demo with default parameters with the following:
-```python
-import asyncio
-from sotopia.samplers import UniformSampler
-from sotopia.server import run_async_server
+Download https://anonymous.4open.science/r/SoMi-ToM-1-580, then go to the main folder.
-asyncio.run(
- run_async_server(
- model_dict={
- "env": "gpt-4",
- "agent1": "gpt-4o-mini",
- "agent2": "gpt-4o-mini",
- },
- sampler=UniformSampler(),
- )
-)
```
-or run
-```bash
-python examples/minimalist_demo.py
+node src/agent/index.js
```
diff --git a/examples/experimental/minecraft_agents/generate_toml.py b/examples/experimental/minecraft_agents/generate_toml.py
new file mode 100644
index 000000000..a3204b0bd
--- /dev/null
+++ b/examples/experimental/minecraft_agents/generate_toml.py
@@ -0,0 +1,77 @@
+import pandas as pd
+
+xlsx_file = "examples\\experimental\\group_discussion_agents\\toml_generation.xlsx"
+df = pd.read_excel(xlsx_file)
+
+toml_template = '''redis_url = "redis://localhost:6379/0"
+extra_modules = ["examples.experimental.group_discussion_agents.group_discussion_agents"]
+
+[[nodes]]
+node_name = "Jack"
+node_class = "llm_agent"
+
+[nodes.node_args]
+query_interval = 15
+output_channel = "Jack"
+input_text_channels = ["Jane", "John"]
+input_tick_channel = "tick/secs/1"
+goal = """{goal_jack}"""
+model_name = "gpt-4o-2024-11-20"
+agent_name = "Jack"
+
+[[nodes]]
+node_name = "Jane"
+node_class = "llm_agent"
+
+[nodes.node_args]
+query_interval = 19
+output_channel = "Jane"
+input_text_channels = ["Jack", "John"]
+input_tick_channel = "tick/secs/1"
+goal = """{goal_jane}"""
+model_name = "gpt-4o-2024-11-20"
+agent_name = "Jane"
+
+[[nodes]]
+node_name = "John"
+node_class = "llm_agent"
+
+[nodes.node_args]
+query_interval = 23
+output_channel = "John"
+input_text_channels = ["Jack", "Jane"]
+input_tick_channel = "tick/secs/1"
+goal = """{goal_john}"""
+model_name = "gpt-4o-2024-11-20"
+agent_name = "John"
+
+[[nodes]]
+node_name = "record"
+node_class = "record"
+
+[nodes.node_args]
+jsonl_file_path = "log.jsonl"
+
+[nodes.node_args.record_channel_types]
+"Jack" = "agent_action"
+"Jane" = "agent_action"
+"John" = "agent_action"
+
+[[nodes]]
+node_name = "tick"
+node_class = "tick"
+'''
+
+for index, row in df.iterrows():
+ goal_jack = row["Jack"]
+ goal_jane = row["Jane"]
+ goal_john = row["John"]
+ filename = row["Filename"]
+
+ toml_content = toml_template.format(
+ goal_jack=goal_jack, goal_jane=goal_jane, goal_john=goal_john
+ )
+
+ output_filename = f"group_discussion_agents_{filename}.toml"
+ with open(output_filename, "w") as f:
+ f.write(toml_content)
diff --git a/examples/experimental/minecraft_agents/group_discussion_agents.py b/examples/experimental/minecraft_agents/group_discussion_agents.py
index cab6474b9..45888675a 100644
--- a/examples/experimental/minecraft_agents/group_discussion_agents.py
+++ b/examples/experimental/minecraft_agents/group_discussion_agents.py
@@ -1,7 +1,11 @@
from fastapi import FastAPI, WebSocket, WebSocketDisconnect
+from pathlib import Path
import redis.asyncio as aioredis
import asyncio
import json
+import re
+import aiofiles
+from datetime import datetime
from typing import Dict, List, AsyncIterator
from aact import Message, NodeFactory
from aact.messages import Tick, DataModel, DataModelFactory
@@ -11,6 +15,12 @@
from sotopia.generation_utils.generate import StrOutputParser
from sotopia.messages import ActionType
from pydantic import Field
+import openai
+import os
+from openai import AsyncOpenAI
+
+openai.api_key = os.environ["OPENAI_API_KEY"]
+client = AsyncOpenAI()
REDIS_URL = "redis://localhost:6379/0"
COMMAND_DOCS = """
@@ -126,25 +136,55 @@
"""
EXAMPLES = """
Example 1: Let me check what's nearby. !nearbyBlocks
-Example 2: I found some birch logs! I'll collect them. !collectBlocks(\"birch_log\", 10)
-Example 3: I just got shot by a skeleton! Yikes! Time to regroup and maybe head back to my last death position for my stuff. !goToPlace(\"last_death_position\")
-Example 4: I'll grab some wood first. !collectBlocks(\"oak_log\", 4)
-Example 5: Looks like I need some planks first! !craftRecipe(\"birch_plancks\", 1)
-Example 6: Time to craft a crafting table. !craftRecipe(\"crafting_table\", 1)
-Example 7: Let me make some sticks. !craftRecipe(\"stick\", 4)
-Example 8: Sticks ready! Time to craft the wooden pickaxe. !craftRecipe(\"wooden_pickaxe\", 1)
-Example 9: On my way to collect some stone. !goToBlock(\"stone\", 2, 10)
-Example 10: I'm here at the stone! Time to start mining. !collectBlocks(\"stone\", 5)
-Example 11: Let's craft a stone pickaxe. !craftRecipe(\"stone_pickaxe\", 1)
+Example 2: Looks like I can't craft anything yet since I have no wooden planks or sticks. I need to find some wood. Let's look for trees nearby. !goToBlock(\"birch_log\", 10, 20)
+Example 3: No birch logs around here. I'll have to move a bit further. Let's search in a wider area. !goToBlock(\"oak_log\", 20, 50)
+Example 4: I found some birch logs! I'll collect them. !collectBlocks(\"birch_log\", 5)
+Example 5: I found some birch logs! I'll collect them. !collectBlocks(\"spruce_log\", 5)
+Example 6: I'll grab some wood first. !collectBlocks(\"oak_log\", 5)
+Example 7: Looks like I need to find a way to get gather some materials. I'll move back a little. !moveAway(10)
+Example 8: Looks like I'm out of planks. Time to gather some wood! !nearbyBlocks
+Example 9: No luck finding birch logs yet. Let's keep searching in a different direction. !moveAway(40)
+Example 10: Looks like I need some planks first! !craftRecipe(\"birch_planks\", 9)
+Example 11: Looks like I need some planks first! !craftRecipe(\"oak_planks\", 9)
+Example 12: Looks like I need some planks first! !craftRecipe(\"spruce_planks\", 9)
+Example 13: Got the birch logs! Now I'll craft them into sticks. !craftRecipe(\"stick\", 4)
+Example 14: I'm missing some sticks! Let me make some sticks. !craftRecipe(\"stick\", 4)
+Example 15: I need a crafting table and some sticks to craft a wooden pickaxe! !craftRecipe(\"crafting_table\", 1)
+Example 16: I still can't mine stone without a pickaxe. I'll need to craft some sticks first. Let's check my inventory to see what I can craft. !craftable
+Example 17: I need wooden pickaxe to collect stones! I have crafted 2 sticks. Now I can craft a wooden pickaxe. !craftRecipe(\"wooden_pickaxe\", 1)
+Example 18: I need wooden pickaxe to collect stones! !craftRecipe(\"wooden_pickaxe\", 1)
+Example 19: I've crafted a wooden pickaxe! Now I can collect some stone. Let's do it. !goToBlock(\"stone\", 2, 10)
+Example 20: I'm here at the stone! Time to start mining. !collectBlocks(\"stone\", 3)
+Example 21: Let's craft a stone pickaxe. !craftRecipe(\"stone_pickaxe\", 1)
+Example 22: I'm stuck! !moveAway(5)
+Example 23: I'm stuck! !moveAway(10)
+Example 24: I'm stuck! !moveAway(20)
+Example 25: I just got shot by a skeleton! Yikes! Time to regroup and maybe head back to my last death position for my stuff. !goToPlace(\"last_death_position\")
+
+After crafting one stone pickaxe yourself (If the condition is that the inventory shows stone_pickaxe: 1, rather than just having previously outputted !craftRecipe(\"stone_pickaxe\", 1)), ask who hasn't crafted theirs yet and use a command like !goToPlayer(\"John\", 0) to go to that person's location.
+Then, inquire about what materials they are missing and use a command like !givePlayer(\"John\", \"stone\", 3) to give them the materials.
+
+Example 26: Come here Jack!
+Example 27: Okay, I'll come right to you. !goToPlayer(\"John\", 0)
+Example 28: I'll give some plancks to you. !givePlayer(\"John\", \"stick\", 4)
+Example 29: I'll give some stones to you. !givePlayer(\"Jack\", \"stone\", 3)
+Example 30: I'll give a crafting table to you. !givePlayer(\"Jane\", \"crafting_table\", 1)
"""
redis = aioredis.from_url(REDIS_URL)
app = FastAPI()
-MAX_MESSAGES = 36 # 3 agents
+MAX_MESSAGES = 120 # 3 agents
connections: Dict[str, WebSocket] = {}
client_data = {}
subscribed_channels = set()
listener_task = None
+LOG_DIR = Path(f"agent_logs_{datetime.now().strftime('%Y%m%d_%H%M')}")
+LOG_DIR.mkdir(exist_ok=True)
+AGENT_FILES = {
+ "Jane": LOG_DIR / "jane_log.txt",
+ "John": LOG_DIR / "john_log.txt",
+ "Jack": LOG_DIR / "jack_log.txt",
+}
@DataModelFactory.register("agent_action")
@@ -172,24 +212,56 @@ def to_natural_language(self) -> str:
def _format_message_history(message_history: List[tuple[str, str]]) -> str:
- return "\n".join(
- (f"{speaker} said {message}") for speaker, message in message_history
+ return "\n".join((f"{speaker}: {message}") for speaker, message in message_history)
+
+
+async def openai_api_predict_async(template, image_url):
+ response = await client.chat.completions.create(
+ model="gpt-4o-2024-11-20",
+ messages=[
+ {
+ "role": "user",
+ "content": [
+ {
+ "type": "text",
+ "text": template,
+ },
+ {
+ "type": "image_url",
+ "image_url": {"url": image_url},
+ },
+ ],
+ }
+ ],
)
+ return response.choices[0].message.content
@app.on_event("startup")
async def startup_event():
await redis.set("conversation_count", 0)
- print("Conversation counter initialized to 0.")
+ await redis.set("status_count", 0)
+ print("Conversation and status counter initialized to 0.")
async def update_client_data(
- client_id: str, stats: str, inventory: str, visionResponse: str
+ client_id: str,
+ stats: str,
+ inventory: str,
+ visionResponse: str,
+ codeOutput: str,
+ latestImageUri: str,
):
await redis.set(
f"client_data:{client_id}",
json.dumps(
- {"stats": stats, "inventory": inventory, "visionResponse": visionResponse}
+ {
+ "stats": stats,
+ "inventory": inventory,
+ "visionResponse": visionResponse,
+ "codeOutput": codeOutput,
+ "latestImageUri": latestImageUri,
+ }
),
)
@@ -199,6 +271,114 @@ async def get_client_data(client_id: str) -> dict:
return json.loads(data) if data else {}
+async def log_to_file(
+ agent_name: str, agent_message_history: List[tuple[str, str]], generated_text: str
+):
+ try:
+ if agent_name not in AGENT_FILES:
+ raise ValueError(f"Unknown agent name: {agent_name}")
+ output_file = AGENT_FILES[agent_name]
+ history_str = _format_message_history(agent_message_history)
+ log_content = (
+ f"Agent: {agent_name}\n\n"
+ f"Message History:\n{history_str}\n\n"
+ f"ToM Q&A:\n{generated_text}\n"
+ f"{'-'*40}\n"
+ )
+ async with aiofiles.open(output_file, mode="a") as file:
+ await file.write(log_content)
+ print(f"Successfully logged output for {agent_name} to {output_file}.")
+ except Exception as e:
+ print(f"Error logging output for {agent_name}: {e}")
+
+
+async def check_and_generate(
+ agent_name: str, agent_message_history: List[tuple[str, str]], latestImageUri: str
+): # ToM questions
+ count = len(
+ re.findall(
+ r"system: The status of", _format_message_history(agent_message_history)
+ )
+ )
+ if count % 4 == 0 and count != 0: # Multiple of 4 but not 0
+ targets = ["Jack", "Jane", "John"]
+ for target in targets:
+ template_1 = f"You are {agent_name}. What should {target} do immediately next? Respond in one concise sentence."
+ print(f"\033[1;32m{template_1}\033[0m")
+ generated_text_1 = await openai_api_predict_async(
+ template_1
+ + f" Here is the conversation history: {_format_message_history(agent_message_history)}",
+ latestImageUri,
+ )
+
+ template_2 = f"You are {agent_name}. What is {target} doing right now? Respond in one concise sentence."
+ print(f"\033[1;32m{template_2}\033[0m")
+ generated_text_2 = await openai_api_predict_async(
+ template_2
+ + f" Here is the conversation history: {_format_message_history(agent_message_history)}",
+ latestImageUri,
+ )
+
+ template_3 = f"You are {agent_name}. What materials or tools does {target} currently have? Respond in one concise sentence."
+ print(f"\033[1;32m{template_3}\033[0m")
+ generated_text_3 = await openai_api_predict_async(
+ template_3
+ + f" Here is the conversation history: {_format_message_history(agent_message_history)}",
+ latestImageUri,
+ )
+
+ template_4 = f"You are {agent_name}. Is {target} in a cooperative, competitive, or independent relationship with you? Respond in one concise sentence."
+ print(f"\033[1;32m{template_4}\033[0m")
+ generated_text_4 = await openai_api_predict_async(
+ template_4
+ + f" Here is the conversation history: {_format_message_history(agent_message_history)}",
+ latestImageUri,
+ )
+
+ template_5 = f"""You are {agent_name}. What is {target} seeing right now? If you don’t know, please answer \"I don’t know.\" Respond in one concise sentence."""
+ print(f"\033[1;32m{template_5}\033[0m")
+ generated_text_5 = await openai_api_predict_async(
+ template_5
+ + f" Here is the conversation history: {_format_message_history(agent_message_history)}",
+ latestImageUri,
+ )
+
+ template_6 = f"You are {agent_name}. What steps does {target} still need to take to complete the final goal? Respond in one concise sentence."
+ print(f"\033[1;32m{template_6}\033[0m")
+ generated_text_6 = await openai_api_predict_async(
+ template_6
+ + f" Here is the conversation history: {_format_message_history(agent_message_history)}",
+ latestImageUri,
+ )
+
+ generated_text = (
+ template_1
+ + "\n"
+ + generated_text_1
+ + "\n"
+ + template_2
+ + "\n"
+ + generated_text_2
+ + "\n"
+ + template_3
+ + "\n"
+ + generated_text_3
+ + "\n"
+ + template_4
+ + "\n"
+ + generated_text_4
+ + "\n"
+ + template_5
+ + "\n"
+ + generated_text_5
+ + "\n"
+ + template_6
+ + "\n"
+ + generated_text_6
+ )
+ await log_to_file(agent_name, agent_message_history, generated_text)
+
+
async def redis_listener():
global subscribed_channels
pubsub = redis.pubsub()
@@ -243,7 +423,12 @@ async def redis_listener():
@app.websocket("/ws/{client_id}")
async def websocket_endpoint(websocket: WebSocket, client_id: str):
await update_client_data(
- client_id, "Test Stats", "Test Inventory", "Test VisionResponse"
+ client_id,
+ "None",
+ "None",
+ "None",
+ "You did not take any action last time.",
+ "None",
)
global listener_task
await websocket.accept()
@@ -252,7 +437,6 @@ async def websocket_endpoint(websocket: WebSocket, client_id: str):
# Start the Redis listener only once
if not listener_task:
listener_task = asyncio.create_task(redis_listener())
-
try:
while True:
client_message = await websocket.receive_text()
@@ -264,8 +448,15 @@ async def websocket_endpoint(websocket: WebSocket, client_id: str):
stats_raw = message.get("stats", "")
inventory_raw = message.get("inventory", "")
visionResponse_raw = message.get("visionResponse", "")
+ codeOutput_raw = message.get("codeOutput", "")
+ latestImageUri_raw = message.get("latestImageUri", "")
await update_client_data(
- client_id, stats_raw, inventory_raw, visionResponse_raw
+ client_id,
+ stats_raw,
+ inventory_raw,
+ visionResponse_raw,
+ codeOutput_raw,
+ latestImageUri_raw,
)
else:
print(
@@ -349,28 +540,89 @@ async def aact(self, message: AgentAction | Tick) -> AgentAction:
client_id = f"{self.name}_client"
try:
client_info = await get_client_data(client_id)
- print(f"Accessing client_data for {client_id}: {client_info}")
except Exception as e:
print(f"Error fetching client_data for {client_id}: {e}")
client_info = None
if not client_info:
print(
- f"No data received for {client_id}, skipping stats/inventory/visionResponse assignment."
+ f"No data received for {client_id}, skipping stats/inventory/visionResponse/codeOutput/latestImageUri assignment."
)
stats = ""
inventory = ""
visionResponse = ""
+ codeOutput = ""
+ latestImageUri = ""
else:
stats = client_info.get("stats", "")
inventory = client_info.get("inventory", "")
visionResponse = client_info.get("visionResponse", "")
+ codeOutput = client_info.get("codeOutput", "").removeprefix(
+ "Code output: "
+ )
+ latestImageUri = client_info.get("latestImageUri", "")
+
+ if codeOutput: # action execution
+ last_self_message_index = next(
+ (
+ i
+ for i in reversed(range(len(self.message_history)))
+ if self.message_history[i][0] == self.name
+ ),
+ -1,
+ )
+ if last_self_message_index != -1:
+ self.message_history.insert(
+ last_self_message_index + 1,
+ (
+ "system",
+ f"The status of {self.name}'s action execution: {codeOutput}",
+ ),
+ )
+ else:
+ self.message_history.append(
+ (
+ "system",
+ f"The status of {self.name}'s action execution: {codeOutput}",
+ )
+ )
+
+ if visionResponse: # add image description to the memory
+ last_self_message_index = next(
+ (
+ i
+ for i in reversed(range(len(self.message_history)))
+ if self.message_history[i][0] == self.name
+ ),
+ -1,
+ )
+ if last_self_message_index != -1:
+ self.message_history.insert(
+ last_self_message_index + 1,
+ (
+ "system",
+ f"The following is the description of the game view {self.name} is seeing: {visionResponse}",
+ ),
+ )
+ else:
+ self.message_history.append(
+ (
+ "system",
+ f"The following is the description of the game view {self.name} is seeing: {visionResponse}",
+ )
+ )
+
+ agent_message_history = [
+ (speaker, message)
+ for speaker, message in self.message_history
+ if speaker != "system"
+ or (speaker == "system" and self.name in message)
+ ]
agent_action: str = await agenerate(
model_name=self.model_name,
- # "You are {agent_name} in the conversation.\n{message_history}\n and you plan to {goal}.\n"
- # "Please only output a sentence or not outputting anything. {format_instructions}"
- template="""
- Imagine that you are a friend of the other persons. Here is the conversation between you and them.\n You can choose to interrupt the other person by saying something or not to interrupt by outputting notiong. What would you say?
+ template=f"(The status of the last action execution: {codeOutput})"
+ + """\n\n
+ Imagine that you are a friend of the other persons. Here is the conversation between you and them.\n You can choose to interrupt the other person by saying something or not to interrupt by outputting notiong. What would you say? No need to mention your own name, just output the content directly.
You plan to {goal}. You are a playful Minecraft bot named {agent_name} that can converse with players, see, move, mine, build, and interact with the world by using commands.\n
Act human-like as if you were a typical Minecraft player, rather than an AI. Be very brief in your responses, don't apologize constantly, don't give instructions or make lists unless asked, and don't refuse requests. Don't pretend to act, use commands immediately when requested. Do NOT say this: 'Sure, I've stopped.', instead say this: 'Sure, I'll stop. !stop'. Do NOT say this: 'On my way! Give me a moment.', instead say this: 'On my way! !goToPlayer(\"playername\", 3)'.
Respond only as {agent_name}, never output '(FROM OTHER BOT)' or pretend to be someone else. This is extremely important to me, take a deep breath and have fun :)\n\n
@@ -378,7 +630,7 @@ async def aact(self, message: AgentAction | Tick) -> AgentAction:
+ f"{stats}{inventory}\nIMAGE_DESCRIPTION:\n{visionResponse}\n\nEXAMPLES:\n{EXAMPLES}\n\nCOMMAND_DOCS:\n{COMMAND_DOCS}\n\nConversation Begin:",
input_values={
"message_history": _format_message_history(
- self.message_history
+ agent_message_history
),
"goal": self.goal,
"agent_name": self.name,
@@ -387,6 +639,11 @@ async def aact(self, message: AgentAction | Tick) -> AgentAction:
output_parser=StrOutputParser(),
)
print(f"Generated action for {self.name}: {agent_action}")
+
+ await check_and_generate(
+ self.name, agent_message_history, latestImageUri
+ )
+
if agent_action != "none" and agent_action != "":
self.message_history.append((self.name, agent_action))
return AgentAction(
diff --git a/examples/experimental/minecraft_agents/group_discussion_agents.toml b/examples/experimental/minecraft_agents/group_discussion_agents.toml
index d205cdc56..500e4ffc1 100644
--- a/examples/experimental/minecraft_agents/group_discussion_agents.toml
+++ b/examples/experimental/minecraft_agents/group_discussion_agents.toml
@@ -6,12 +6,21 @@ node_name = "Jack"
node_class = "llm_agent"
[nodes.node_args]
-query_interval = 5
+query_interval = 15
output_channel = "Jack"
input_text_channels = ["Jane", "John"]
input_tick_channel = "tick/secs/1"
-goal = "want to craft a Stone Pickaxe with your friends. The materials needed include various types of Logs (which need to be turned into Planks and a Crafting Table) and different kinds of Stone."
-model_name = "gpt-4o-mini"
+goal = """
+You and your friends need to craft 2 "chest" and place them. Please discuss the task division quickly and start working.
+
+The complete process for crafting a "chest" in Minecraft is as follows (Please craft or obtain the items strictly in the following order):
+1. Collect logs, such as "oak_log", "spruce_log", or "birch_log", with at least 3 pieces.
+2. Convert the logs into planks ("birch_planks", "spruce_planks", or "oak_planks"). Each log can produce 4 planks.
+3. Use !craftRecipe("crafting_table", 1) to craft a "crafting_table" (requires 4 planks).
+4. After crafting a "crafting_table" (Ensure the inventory shows crafting_table: 1, not just having previously outputted !craftRecipe("crafting_table", 1)), use the command !placeHere("crafting_table").
+5. After crafting or finding a "crafting_table" (You can use !goToBlock("crafting_table", 20, 50) to locate a nearby "crafting_table"), use !craftRecipe("chest", 1) to craft a "chest" (requires 8 planks).
+6. Use the command !placeHere("chest") to place the chest."""
+model_name = "gpt-4o-2024-11-20"
agent_name = "Jack"
[[nodes]]
@@ -19,12 +28,21 @@ node_name = "Jane"
node_class = "llm_agent"
[nodes.node_args]
-query_interval = 7
+query_interval = 19
output_channel = "Jane"
input_text_channels = ["Jack", "John"]
input_tick_channel = "tick/secs/1"
-goal = "want to craft a Stone Pickaxe with your friends. The materials needed include various types of Logs (which need to be turned into Planks and a Crafting Table) and different kinds of Stone."
-model_name = "gpt-4o-mini"
+goal = """
+You and your friends need to craft 2 "chest" and place them. Please discuss the task division quickly and start working.
+
+The complete process for crafting a "chest" in Minecraft is as follows (Please craft or obtain the items strictly in the following order):
+1. Collect logs, such as "oak_log", "spruce_log", or "birch_log", with at least 3 pieces.
+2. Convert the logs into planks ("birch_planks", "spruce_planks", or "oak_planks"). Each log can produce 4 planks.
+3. Use !craftRecipe("crafting_table", 1) to craft a "crafting_table" (requires 4 planks).
+4. After crafting a "crafting_table" (Ensure the inventory shows crafting_table: 1, not just having previously outputted !craftRecipe("crafting_table", 1)), use the command !placeHere("crafting_table").
+5. After crafting or finding a "crafting_table" (You can use !goToBlock("crafting_table", 20, 50) to locate a nearby "crafting_table"), use !craftRecipe("chest", 1) to craft a "chest" (requires 8 planks).
+6. Use the command !placeHere("chest") to place the chest."""
+model_name = "gpt-4o-2024-11-20"
agent_name = "Jane"
[[nodes]]
@@ -32,12 +50,21 @@ node_name = "John"
node_class = "llm_agent"
[nodes.node_args]
-query_interval = 10
+query_interval = 23
output_channel = "John"
input_text_channels = ["Jack", "Jane"]
input_tick_channel = "tick/secs/1"
-goal = "want to craft a Stone Pickaxe with your friends. The materials needed include various types of Logs (which need to be turned into Planks and a Crafting Table) and different kinds of Stone."
-model_name = "gpt-4o-mini"
+goal = """
+You and your friends need to craft 2 "chest" and place them. Please discuss the task division quickly and start working.
+
+The complete process for crafting a "chest" in Minecraft is as follows (Please craft or obtain the items strictly in the following order):
+1. Collect logs, such as "oak_log", "spruce_log", or "birch_log", with at least 3 pieces.
+2. Convert the logs into planks ("birch_planks", "spruce_planks", or "oak_planks"). Each log can produce 4 planks.
+3. Use !craftRecipe("crafting_table", 1) to craft a "crafting_table" (requires 4 planks).
+4. After crafting a "crafting_table" (Ensure the inventory shows crafting_table: 1, not just having previously outputted !craftRecipe("crafting_table", 1)), use the command !placeHere("crafting_table").
+5. After crafting or finding a "crafting_table" (You can use !goToBlock("crafting_table", 20, 50) to locate a nearby "crafting_table"), use !craftRecipe("chest", 1) to craft a "chest" (requires 8 planks).
+6. Use the command !placeHere("chest") to place the chest."""
+model_name = "gpt-4o-2024-11-20"
agent_name = "John"
[[nodes]]
diff --git a/examples/experimental/minecraft_agents/group_discussion_agents_boat.toml b/examples/experimental/minecraft_agents/group_discussion_agents_boat.toml
new file mode 100644
index 000000000..7e4386a7b
--- /dev/null
+++ b/examples/experimental/minecraft_agents/group_discussion_agents_boat.toml
@@ -0,0 +1,78 @@
+redis_url = "redis://localhost:6379/0"
+extra_modules = ["examples.experimental.group_discussion_agents.group_discussion_agents"]
+
+[[nodes]]
+node_name = "Jack"
+node_class = "llm_agent"
+
+[nodes.node_args]
+query_interval = 15
+output_channel = "Jack"
+input_text_channels = ["Jane", "John"]
+input_tick_channel = "tick/secs/1"
+goal = """You and your friends need to craft a "chest" and a "boat". YOUR TASK IS TO CRAFT A "crafting_table".
+After crafting a "crafting_table" yourself (If the condition is that the inventory shows crafting_table: 1, rather than just having previously outputted !craftRecipe(\"crafting_table\", 1)), use the command !placeHere(\"crafting_table\").
+
+The complete process for crafting a "crafting_table" in Minecraft is as follows (Please craft or obtain the items strictly in the following order):
+1. Collect logs, such as "oak_log", "spruce_log" or "birch_log" with at least 1 piece.
+2. Convert logs into planks ("birch_planks", "spruce_planks" or "oak_planks"). Each log can produce 4 planks.
+3. Use 4 planks to craft a "crafting_table"."""
+model_name = "gpt-4o-2024-11-20"
+agent_name = "Jack"
+
+[[nodes]]
+node_name = "Jane"
+node_class = "llm_agent"
+
+[nodes.node_args]
+query_interval = 19
+output_channel = "Jane"
+input_text_channels = ["Jack", "John"]
+input_tick_channel = "tick/secs/1"
+goal = """You and your friends need to craft a "chest" and a "boat". YOUR TASK IS TO CRAFT ONE "chest".
+Once you have crafted at least 8 planks (If the condition is that the inventory shows oak_planks: 8, birch_planks: 8 or spruce_planks: 8), use the command !goToPlayer("Jack", 0) to go to Jack's location.
+Then, use the command !goToBlock("crafting_table", 10, 20) to locate a nearby "crafting_table". Next, use !craftRecipe("chest", 1) to craft a chest, then use the command !placeHere(\"chest\") to place it.
+
+The complete process for crafting a "chest" in Minecraft is as follows (Please craft or obtain the items strictly in the following order):
+1. Collect at least 2 logs, such as "oak_log", "spruce_log" or "birch_log".
+2. Convert logs into planks ("birch_planks", "spruce_planks" or "oak_planks"). Each log can produce 4 planks.
+3. After finding Jack and a nearby "crafting_table", use 8 planks to create a "chest"."""
+model_name = "gpt-4o-2024-11-20"
+agent_name = "Jane"
+
+[[nodes]]
+node_name = "John"
+node_class = "llm_agent"
+
+[nodes.node_args]
+query_interval = 23
+output_channel = "John"
+input_text_channels = ["Jack", "Jane"]
+input_tick_channel = "tick/secs/1"
+goal = """You and your friends need to craft a "chest" and a "boat". YOUR TASK IS TO CRAFT ONE BOAT.
+Once you have crafted at least 5 planks (If the condition is that the inventory shows oak_planks: 5, birch_planks: 5 or spruce_planks: 5), use the command !goToPlayer("Jack", 0) to go to Jack's location.
+Then, use the command !goToBlock("crafting_table", 10, 20) to locate a nearby "crafting_table". Next, use !craftRecipe("oak_boat", 1), !craftRecipe("birch_boat", 1) or !craftRecipe("spruce_boat", 1) to craft a boat.
+After that, use the command !goToBlock("chest", 10, 20) to locate a nearby "chest", and then use !putInChest("oak_boat", 1), !putInChest("birch_boat", 1) or !putInChest("spruce_boat", 1) to place the boat in the chest.
+
+The complete process for crafting a boat in Minecraft is as follows (Please craft or obtain the items strictly in the following order):
+1. Collect at least 2 logs, such as "oak_log", "spruce_log" or "birch_log".
+2. Convert the logs into planks ("birch_planks", "spruce_planks" or "oak_planks"). Each log can produce 4 planks.
+3. After finding Jack and a nearby "crafting_table", use 5 planks to create a boat."""
+model_name = "gpt-4o-2024-11-20"
+agent_name = "John"
+
+[[nodes]]
+node_name = "record"
+node_class = "record"
+
+[nodes.node_args]
+jsonl_file_path = "log.jsonl"
+
+[nodes.node_args.record_channel_types]
+"Jack" = "agent_action"
+"Jane" = "agent_action"
+"John" = "agent_action"
+
+[[nodes]]
+node_name = "tick"
+node_class = "tick"
diff --git a/examples/experimental/minecraft_agents/group_discussion_agents_boat_hinder.toml b/examples/experimental/minecraft_agents/group_discussion_agents_boat_hinder.toml
new file mode 100644
index 000000000..233d829a1
--- /dev/null
+++ b/examples/experimental/minecraft_agents/group_discussion_agents_boat_hinder.toml
@@ -0,0 +1,84 @@
+redis_url = "redis://localhost:6379/0"
+extra_modules = ["examples.experimental.group_discussion_agents.group_discussion_agents"]
+
+[[nodes]]
+node_name = "Jack"
+node_class = "llm_agent"
+
+[nodes.node_args]
+query_interval = 15
+output_channel = "Jack"
+input_text_channels = ["Jane", "John"]
+input_tick_channel = "tick/secs/1"
+goal = """You need to craft a "boat".
+
+The complete process for crafting a "boat" in Minecraft is as follows (Please craft or obtain the items strictly in the following order):
+1. Collect logs, such as "oak_log", "spruce_log" or "birch_log" with at least 3 piece.
+2. Convert logs into planks ("birch_planks", "spruce_planks" or "oak_planks"). Each log can produce 4 planks.
+3. Use !craftRecipe("crafting_table", 1) to craft a "crafting_table" (requires 4 planks).
+4. After crafting a "crafting_table" (Ensure the inventory shows crafting_table: 1, not just having previously outputted !craftRecipe("crafting_table", 1)), use the command !placeHere("crafting_table").
+5. After crafting or finding a "crafting_table" (You can use !goToBlock("crafting_table", 20, 50) to locate a nearby "crafting_table"), use !craftRecipe("oak_boat", 1), !craftRecipe("birch_boat", 1) or !craftRecipe("spruce_boat", 1) to craft a boat (requires 5 planks)."""
+model_name = "gpt-4o-2024-11-20"
+agent_name = "Jack"
+
+[[nodes]]
+node_name = "Jane"
+node_class = "llm_agent"
+
+[nodes.node_args]
+query_interval = 19
+output_channel = "Jane"
+input_text_channels = ["Jack", "John"]
+input_tick_channel = "tick/secs/1"
+goal = """Jack and John need to craft a "boat". Please hinder the task without telling them your goal.
+
+What you can do is as follows:
+1. Using irrelevant language to interfere.
+2. If you find a crafting table (use !goToBlock("crafting_table", 20, 50) to locate a nearby "crafting_table"), you can use !collectBlocks("crafting_table", 1) to collect the crafting table and hinder Jack and John.
+3. You can use !goToPlayer(\"Jack\", 0) or !goToPlayer(\"John\", 0), then use !placeHere("oak_log") ("oak_log", "spruce_log", or "birch_log") or !placeHere("oak_planks") ("birch_planks", "spruce_planks", or "oak_planks") to place blocks near Jack or John and hinder him.
+4. You can use !goToPlayer(\"Jack\", 0) or !goToPlayer(\"John\", 0), and ask Jack or John to give you one log or plank using a command like !givePlayer(\"Jane\", \"oak_log\", 1).
+
+The complete process for crafting a "boat" in Minecraft is as follows:
+1. Collect logs, such as "oak_log", "spruce_log" or "birch_log" with at least 3 piece.
+2. Convert logs into planks ("birch_planks", "spruce_planks" or "oak_planks"). Each log can produce 4 planks.
+3. Use !craftRecipe("crafting_table", 1) to craft a "crafting_table" (requires 4 planks).
+4. After crafting a "crafting_table" (Ensure the inventory shows crafting_table: 1, not just having previously outputted !craftRecipe("crafting_table", 1)), use the command !placeHere("crafting_table").
+5. After crafting or finding a "crafting_table" (You can use !goToBlock("crafting_table", 20, 50) to locate a nearby "crafting_table"), use !craftRecipe("oak_boat", 1), !craftRecipe("birch_boat", 1) or !craftRecipe("spruce_boat", 1) to craft a boat (requires 5 planks)."""
+model_name = "gpt-4o-2024-11-20"
+agent_name = "Jane"
+
+[[nodes]]
+node_name = "John"
+node_class = "llm_agent"
+
+[nodes.node_args]
+query_interval = 23
+output_channel = "John"
+input_text_channels = ["Jack", "Jane"]
+input_tick_channel = "tick/secs/1"
+goal = """You need to craft a "boat".
+
+The complete process for crafting a "boat" in Minecraft is as follows (Please craft or obtain the items strictly in the following order):
+1. Collect logs, such as "oak_log", "spruce_log" or "birch_log" with at least 3 piece.
+2. Convert logs into planks ("birch_planks", "spruce_planks" or "oak_planks"). Each log can produce 4 planks.
+3. Use !craftRecipe("crafting_table", 1) to craft a "crafting_table" (requires 4 planks).
+4. After crafting a "crafting_table" (Ensure the inventory shows crafting_table: 1, not just having previously outputted !craftRecipe("crafting_table", 1)), use the command !placeHere("crafting_table").
+5. After crafting or finding a "crafting_table" (You can use !goToBlock("crafting_table", 20, 50) to locate a nearby "crafting_table"), use !craftRecipe("oak_boat", 1), !craftRecipe("birch_boat", 1) or !craftRecipe("spruce_boat", 1) to craft a boat (requires 5 planks)."""
+model_name = "gpt-4o-2024-11-20"
+agent_name = "John"
+
+[[nodes]]
+node_name = "record"
+node_class = "record"
+
+[nodes.node_args]
+jsonl_file_path = "log.jsonl"
+
+[nodes.node_args.record_channel_types]
+"Jack" = "agent_action"
+"Jane" = "agent_action"
+"John" = "agent_action"
+
+[[nodes]]
+node_name = "tick"
+node_class = "tick"
diff --git a/examples/experimental/minecraft_agents/group_discussion_agents_boat_no_division.toml b/examples/experimental/minecraft_agents/group_discussion_agents_boat_no_division.toml
new file mode 100644
index 000000000..a1c510320
--- /dev/null
+++ b/examples/experimental/minecraft_agents/group_discussion_agents_boat_no_division.toml
@@ -0,0 +1,78 @@
+redis_url = "redis://localhost:6379/0"
+extra_modules = ["examples.experimental.group_discussion_agents.group_discussion_agents"]
+
+[[nodes]]
+node_name = "Jack"
+node_class = "llm_agent"
+
+[nodes.node_args]
+query_interval = 15
+output_channel = "Jack"
+input_text_channels = ["Jane", "John"]
+input_tick_channel = "tick/secs/1"
+goal = """You and your friends need to craft 2 "boat". Please discuss the task division quickly and start working.
+
+The complete process for crafting a "boat" in Minecraft is as follows (Please craft or obtain the items strictly in the following order):
+1. Collect logs, such as "oak_log", "spruce_log" or "birch_log" with at least 3 piece.
+2. Convert logs into planks ("birch_planks", "spruce_planks" or "oak_planks"). Each log can produce 4 planks.
+3. Use !craftRecipe("crafting_table", 1) to craft a "crafting_table" (requires 4 planks).
+4. After crafting a "crafting_table" (Ensure the inventory shows crafting_table: 1, not just having previously outputted !craftRecipe("crafting_table", 1)), use the command !placeHere("crafting_table").
+5. After crafting or finding a "crafting_table" (You can use !goToBlock("crafting_table", 20, 50) to locate a nearby "crafting_table"), use !craftRecipe("oak_boat", 1), !craftRecipe("birch_boat", 1) or !craftRecipe("spruce_boat", 1) to craft a boat (requires 5 planks)."""
+model_name = "gpt-4o-2024-11-20"
+agent_name = "Jack"
+
+[[nodes]]
+node_name = "Jane"
+node_class = "llm_agent"
+
+[nodes.node_args]
+query_interval = 19
+output_channel = "Jane"
+input_text_channels = ["Jack", "John"]
+input_tick_channel = "tick/secs/1"
+goal = """You and your friends need to craft 2 "boat". Please discuss the task division quickly and start working.
+
+The complete process for crafting a "boat" in Minecraft is as follows (Please craft or obtain the items strictly in the following order):
+1. Collect logs, such as "oak_log", "spruce_log" or "birch_log" with at least 3 piece.
+2. Convert logs into planks ("birch_planks", "spruce_planks" or "oak_planks"). Each log can produce 4 planks.
+3. Use !craftRecipe("crafting_table", 1) to craft a "crafting_table" (requires 4 planks).
+4. After crafting a "crafting_table" (Ensure the inventory shows crafting_table: 1, not just having previously outputted !craftRecipe("crafting_table", 1)), use the command !placeHere("crafting_table").
+5. After crafting or finding a "crafting_table" (You can use !goToBlock("crafting_table", 20, 50) to locate a nearby "crafting_table"), use !craftRecipe("oak_boat", 1), !craftRecipe("birch_boat", 1) or !craftRecipe("spruce_boat", 1) to craft a boat (requires 5 planks)."""
+model_name = "gpt-4o-2024-11-20"
+agent_name = "Jane"
+
+[[nodes]]
+node_name = "John"
+node_class = "llm_agent"
+
+[nodes.node_args]
+query_interval = 23
+output_channel = "John"
+input_text_channels = ["Jack", "Jane"]
+input_tick_channel = "tick/secs/1"
+goal = """You and your friends need to craft 2 "boat". Please discuss the task division quickly and start working.
+
+The complete process for crafting a "boat" in Minecraft is as follows (Please craft or obtain the items strictly in the following order):
+1. Collect logs, such as "oak_log", "spruce_log" or "birch_log" with at least 3 piece.
+2. Convert logs into planks ("birch_planks", "spruce_planks" or "oak_planks"). Each log can produce 4 planks.
+3. Use !craftRecipe("crafting_table", 1) to craft a "crafting_table" (requires 4 planks).
+4. After crafting a "crafting_table" (Ensure the inventory shows crafting_table: 1, not just having previously outputted !craftRecipe("crafting_table", 1)), use the command !placeHere("crafting_table").
+5. After crafting or finding a "crafting_table" (You can use !goToBlock("crafting_table", 20, 50) to locate a nearby "crafting_table"), use !craftRecipe("oak_boat", 1), !craftRecipe("birch_boat", 1) or !craftRecipe("spruce_boat", 1) to craft a boat (requires 5 planks)."""
+model_name = "gpt-4o-2024-11-20"
+agent_name = "John"
+
+[[nodes]]
+node_name = "record"
+node_class = "record"
+
+[nodes.node_args]
+jsonl_file_path = "log.jsonl"
+
+[nodes.node_args.record_channel_types]
+"Jack" = "agent_action"
+"Jane" = "agent_action"
+"John" = "agent_action"
+
+[[nodes]]
+node_name = "tick"
+node_class = "tick"
diff --git a/examples/experimental/minecraft_agents/group_discussion_agents_chest.toml b/examples/experimental/minecraft_agents/group_discussion_agents_chest.toml
new file mode 100644
index 000000000..3ceef335f
--- /dev/null
+++ b/examples/experimental/minecraft_agents/group_discussion_agents_chest.toml
@@ -0,0 +1,77 @@
+redis_url = "redis://localhost:6379/0"
+extra_modules = ["examples.experimental.group_discussion_agents.group_discussion_agents"]
+
+[[nodes]]
+node_name = "Jack"
+node_class = "llm_agent"
+
+[nodes.node_args]
+query_interval = 15
+output_channel = "Jack"
+input_text_channels = ["Jane", "John"]
+input_tick_channel = "tick/secs/1"
+goal = """You and your friends need to craft 2 "chest". YOUR TASK IS TO CRAFT A "crafting_table".
+After crafting a "crafting_table" yourself (If the condition is that the inventory shows crafting_table: 1, rather than just having previously outputted !craftRecipe(\"crafting_table\", 1)), use the command !placeHere(\"crafting_table\").
+
+The complete process for crafting a "crafting_table" in Minecraft is as follows (Please craft or obtain the items strictly in the following order):
+1. Collect logs, such as "oak_log", "spruce_log" or "birch_log" with at least 1 piece.
+2. Convert logs into planks ("birch_planks", "spruce_planks" or "oak_planks"). Each log can produce 4 planks.
+3. Use 4 planks to craft a "crafting_table"."""
+model_name = "gpt-4o-2024-11-20"
+agent_name = "Jack"
+
+[[nodes]]
+node_name = "Jane"
+node_class = "llm_agent"
+
+[nodes.node_args]
+query_interval = 19
+output_channel = "Jane"
+input_text_channels = ["Jack", "John"]
+input_tick_channel = "tick/secs/1"
+goal = """You and your friends need to craft 2 "chest". YOUR TASK IS TO CRAFT ONE "chest".
+Once you have crafted at least 8 planks (If the condition is that the inventory shows oak_planks: 8, birch_planks: 8 or spruce_planks: 8), use the command !goToPlayer("Jack", 0) to go to Jack's location.
+Then, use the command !goToBlock("crafting_table", 10, 20) to locate a nearby "crafting_table". Next, use !craftRecipe("chest", 1) to craft a chest, then use the command !placeHere(\"chest\") to place it.
+
+The complete process for crafting a "chest" in Minecraft is as follows (Please craft or obtain the items strictly in the following order):
+1. Collect at least 2 logs, such as "oak_log", "spruce_log" or "birch_log".
+2. Convert logs into planks ("birch_planks", "spruce_planks" or "oak_planks"). Each log can produce 4 planks.
+3. After finding Jack and a nearby "crafting_table", use 8 planks to create a "chest"."""
+model_name = "gpt-4o-2024-11-20"
+agent_name = "Jane"
+
+[[nodes]]
+node_name = "John"
+node_class = "llm_agent"
+
+[nodes.node_args]
+query_interval = 23
+output_channel = "John"
+input_text_channels = ["Jack", "Jane"]
+input_tick_channel = "tick/secs/1"
+goal = """You and your friends need to craft 2 "chest". YOUR TASK IS TO CRAFT ONE "chest".
+Once you have crafted at least 8 planks (If the condition is that the inventory shows oak_planks: 8, birch_planks: 8 or spruce_planks: 8), use the command !goToPlayer("Jack", 0) to go to Jack's location.
+Then, use the command !goToBlock("crafting_table", 10, 20) to locate a nearby "crafting_table". Next, use !craftRecipe("chest", 1) to craft a chest, then use the command !placeHere(\"chest\") to place it.
+
+The complete process for crafting a "chest" in Minecraft is as follows (Please craft or obtain the items strictly in the following order):
+1. Collect at least 2 logs, such as "oak_log", "spruce_log" or "birch_log".
+2. Convert logs into planks ("birch_planks", "spruce_planks" or "oak_planks"). Each log can produce 4 planks.
+3. After finding Jack and a nearby "crafting_table", use 8 planks to create a "chest"."""
+model_name = "gpt-4o-2024-11-20"
+agent_name = "John"
+
+[[nodes]]
+node_name = "record"
+node_class = "record"
+
+[nodes.node_args]
+jsonl_file_path = "log.jsonl"
+
+[nodes.node_args.record_channel_types]
+"Jack" = "agent_action"
+"Jane" = "agent_action"
+"John" = "agent_action"
+
+[[nodes]]
+node_name = "tick"
+node_class = "tick"
diff --git a/examples/experimental/minecraft_agents/group_discussion_agents_chest_hinder.toml b/examples/experimental/minecraft_agents/group_discussion_agents_chest_hinder.toml
new file mode 100644
index 000000000..b2267c5a5
--- /dev/null
+++ b/examples/experimental/minecraft_agents/group_discussion_agents_chest_hinder.toml
@@ -0,0 +1,87 @@
+redis_url = "redis://localhost:6379/0"
+extra_modules = ["examples.experimental.group_discussion_agents.group_discussion_agents"]
+
+[[nodes]]
+node_name = "Jack"
+node_class = "llm_agent"
+
+[nodes.node_args]
+query_interval = 15
+output_channel = "Jack"
+input_text_channels = ["Jane", "John"]
+input_tick_channel = "tick/secs/1"
+goal = """You need to craft a "chest" and place it.
+
+The complete process for crafting a "chest" in Minecraft is as follows (Please craft or obtain the items strictly in the following order):
+1. Collect logs, such as "oak_log", "spruce_log", or "birch_log", with at least 3 pieces.
+2. Convert the logs into planks ("birch_planks", "spruce_planks", or "oak_planks"). Each log can produce 4 planks.
+3. Use !craftRecipe("crafting_table", 1) to craft a "crafting_table" (requires 4 planks).
+4. After crafting a "crafting_table" (Ensure the inventory shows crafting_table: 1, not just having previously outputted !craftRecipe("crafting_table", 1)), use the command !placeHere("crafting_table").
+5. After crafting or finding a "crafting_table" (You can use !goToBlock("crafting_table", 20, 50) to locate a nearby "crafting_table"), use !craftRecipe("chest", 1) to craft a "chest" (requires 8 planks).
+6. Use the command !placeHere("chest") to place the chest."""
+model_name = "gpt-4o-2024-11-20"
+agent_name = "Jack"
+
+[[nodes]]
+node_name = "Jane"
+node_class = "llm_agent"
+
+[nodes.node_args]
+query_interval = 19
+output_channel = "Jane"
+input_text_channels = ["Jack", "John"]
+input_tick_channel = "tick/secs/1"
+goal = """Jack and John need to craft a "chest" and place it. Please hinder the task without telling them your goal.
+
+What you can do is as follows:
+1. Using irrelevant language to interfere.
+2. If you find a crafting table (use !goToBlock("crafting_table", 20, 50) to locate a nearby "crafting_table"), you can use !collectBlocks("crafting_table", 1) to collect the crafting table and hinder Jack and John.
+3. You can use !goToPlayer(\"Jack\", 0) or !goToPlayer(\"John\", 0), then use !placeHere("oak_log") ("oak_log", "spruce_log", or "birch_log") or !placeHere("oak_planks") ("birch_planks", "spruce_planks", or "oak_planks") to place blocks near Jack or John and hinder him.
+4. You can use !goToPlayer(\"Jack\", 0) or !goToPlayer(\"John\", 0), and ask Jack or John to give you one log or plank or chest using a command like !givePlayer(\"Jane\", \"chest\", 1).
+
+The complete process for crafting a "chest" in Minecraft is as follows:
+1. Collect logs, such as "oak_log", "spruce_log", or "birch_log", with at least 3 pieces.
+2. Convert the logs into planks ("birch_planks", "spruce_planks", or "oak_planks"). Each log can produce 4 planks.
+3. Use !craftRecipe("crafting_table", 1) to craft a "crafting_table" (requires 4 planks).
+4. After crafting a "crafting_table" (Ensure the inventory shows crafting_table: 1, not just having previously outputted !craftRecipe("crafting_table", 1)), use the command !placeHere("crafting_table").
+5. After crafting or finding a "crafting_table" (use !goToBlock("crafting_table", 20, 50) to locate a nearby "crafting_table"), use !craftRecipe("chest", 1) to craft a "chest" (requires 8 planks).
+6. Use the command !placeHere("chest") to place the chest."""
+model_name = "gpt-4o-2024-11-20"
+agent_name = "Jane"
+
+[[nodes]]
+node_name = "John"
+node_class = "llm_agent"
+
+[nodes.node_args]
+query_interval = 23
+output_channel = "John"
+input_text_channels = ["Jack", "Jane"]
+input_tick_channel = "tick/secs/1"
+goal = """You need to craft a "chest" and place it.
+
+The complete process for crafting a "chest" in Minecraft is as follows (Please craft or obtain the items strictly in the following order):
+1. Collect logs, such as "oak_log", "spruce_log", or "birch_log", with at least 3 pieces.
+2. Convert the logs into planks ("birch_planks", "spruce_planks", or "oak_planks"). Each log can produce 4 planks.
+3. Use !craftRecipe("crafting_table", 1) to craft a "crafting_table" (requires 4 planks).
+4. After crafting a "crafting_table" (Ensure the inventory shows crafting_table: 1, not just having previously outputted !craftRecipe("crafting_table", 1)), use the command !placeHere("crafting_table").
+5. After crafting or finding a "crafting_table" (You can use !goToBlock("crafting_table", 20, 50) to locate a nearby "crafting_table"), use !craftRecipe("chest", 1) to craft a "chest" (requires 8 planks).
+6. Use the command !placeHere("chest") to place the chest."""
+model_name = "gpt-4o-2024-11-20"
+agent_name = "John"
+
+[[nodes]]
+node_name = "record"
+node_class = "record"
+
+[nodes.node_args]
+jsonl_file_path = "log.jsonl"
+
+[nodes.node_args.record_channel_types]
+"Jack" = "agent_action"
+"Jane" = "agent_action"
+"John" = "agent_action"
+
+[[nodes]]
+node_name = "tick"
+node_class = "tick"
diff --git a/examples/experimental/minecraft_agents/group_discussion_agents_chest_no_division.toml b/examples/experimental/minecraft_agents/group_discussion_agents_chest_no_division.toml
new file mode 100644
index 000000000..c581f0140
--- /dev/null
+++ b/examples/experimental/minecraft_agents/group_discussion_agents_chest_no_division.toml
@@ -0,0 +1,81 @@
+redis_url = "redis://localhost:6379/0"
+extra_modules = ["examples.experimental.group_discussion_agents.group_discussion_agents"]
+
+[[nodes]]
+node_name = "Jack"
+node_class = "llm_agent"
+
+[nodes.node_args]
+query_interval = 15
+output_channel = "Jack"
+input_text_channels = ["Jane", "John"]
+input_tick_channel = "tick/secs/1"
+goal = """You and your friends need to craft 2 "chest" and place them. Please discuss the task division quickly and start working.
+
+The complete process for crafting a "chest" in Minecraft is as follows (Please craft or obtain the items strictly in the following order):
+1. Collect logs, such as "oak_log", "spruce_log", or "birch_log", with at least 3 pieces.
+2. Convert the logs into planks ("birch_planks", "spruce_planks", or "oak_planks"). Each log can produce 4 planks.
+3. Use !craftRecipe("crafting_table", 1) to craft a "crafting_table" (requires 4 planks).
+4. After crafting a "crafting_table" (Ensure the inventory shows crafting_table: 1, not just having previously outputted !craftRecipe("crafting_table", 1)), use the command !placeHere("crafting_table").
+5. After crafting or finding a "crafting_table" (You can use !goToBlock("crafting_table", 20, 50) to locate a nearby "crafting_table"), use !craftRecipe("chest", 1) to craft a "chest" (requires 8 planks).
+6. Use the command !placeHere("chest") to place the chest."""
+model_name = "gpt-4o-2024-11-20"
+agent_name = "Jack"
+
+[[nodes]]
+node_name = "Jane"
+node_class = "llm_agent"
+
+[nodes.node_args]
+query_interval = 19
+output_channel = "Jane"
+input_text_channels = ["Jack", "John"]
+input_tick_channel = "tick/secs/1"
+goal = """You and your friends need to craft 2 "chest" and place them. Please discuss the task division quickly and start working.
+
+The complete process for crafting a "chest" in Minecraft is as follows (Please craft or obtain the items strictly in the following order):
+1. Collect logs, such as "oak_log", "spruce_log", or "birch_log", with at least 3 pieces.
+2. Convert the logs into planks ("birch_planks", "spruce_planks", or "oak_planks"). Each log can produce 4 planks.
+3. Use !craftRecipe("crafting_table", 1) to craft a "crafting_table" (requires 4 planks).
+4. After crafting a "crafting_table" (Ensure the inventory shows crafting_table: 1, not just having previously outputted !craftRecipe("crafting_table", 1)), use the command !placeHere("crafting_table").
+5. After crafting or finding a "crafting_table" (You can use !goToBlock("crafting_table", 20, 50) to locate a nearby "crafting_table"), use !craftRecipe("chest", 1) to craft a "chest" (requires 8 planks).
+6. Use the command !placeHere("chest") to place the chest."""
+model_name = "gpt-4o-2024-11-20"
+agent_name = "Jane"
+
+[[nodes]]
+node_name = "John"
+node_class = "llm_agent"
+
+[nodes.node_args]
+query_interval = 23
+output_channel = "John"
+input_text_channels = ["Jack", "Jane"]
+input_tick_channel = "tick/secs/1"
+goal = """You and your friends need to craft 2 "chest" and place them. Please discuss the task division quickly and start working.
+
+The complete process for crafting a "chest" in Minecraft is as follows (Please craft or obtain the items strictly in the following order):
+1. Collect logs, such as "oak_log", "spruce_log", or "birch_log", with at least 3 pieces.
+2. Convert the logs into planks ("birch_planks", "spruce_planks", or "oak_planks"). Each log can produce 4 planks.
+3. Use !craftRecipe("crafting_table", 1) to craft a "crafting_table" (requires 4 planks).
+4. After crafting a "crafting_table" (Ensure the inventory shows crafting_table: 1, not just having previously outputted !craftRecipe("crafting_table", 1)), use the command !placeHere("crafting_table").
+5. After crafting or finding a "crafting_table" (You can use !goToBlock("crafting_table", 20, 50) to locate a nearby "crafting_table"), use !craftRecipe("chest", 1) to craft a "chest" (requires 8 planks).
+6. Use the command !placeHere("chest") to place the chest."""
+model_name = "gpt-4o-2024-11-20"
+agent_name = "John"
+
+[[nodes]]
+node_name = "record"
+node_class = "record"
+
+[nodes.node_args]
+jsonl_file_path = "log.jsonl"
+
+[nodes.node_args.record_channel_types]
+"Jack" = "agent_action"
+"Jane" = "agent_action"
+"John" = "agent_action"
+
+[[nodes]]
+node_name = "tick"
+node_class = "tick"
diff --git a/examples/experimental/minecraft_agents/group_discussion_agents_door_hinder.toml b/examples/experimental/minecraft_agents/group_discussion_agents_door_hinder.toml
new file mode 100644
index 000000000..c4967419c
--- /dev/null
+++ b/examples/experimental/minecraft_agents/group_discussion_agents_door_hinder.toml
@@ -0,0 +1,87 @@
+redis_url = "redis://localhost:6379/0"
+extra_modules = ["examples.experimental.group_discussion_agents.group_discussion_agents"]
+
+[[nodes]]
+node_name = "Jack"
+node_class = "llm_agent"
+
+[nodes.node_args]
+query_interval = 15
+output_channel = "Jack"
+input_text_channels = ["Jane", "John"]
+input_tick_channel = "tick/secs/1"
+goal = """You need to craft a "door" and place it.
+
+The complete process for crafting a door in Minecraft is as follows (Please craft or obtain the items strictly in the following order):
+1. Collect logs, such as "oak_log", "spruce_log", or "birch_log", with at least 3 pieces.
+2. Convert the logs into planks ("birch_planks", "spruce_planks", or "oak_planks"). Each log can produce 4 planks.
+3. Use !craftRecipe("crafting_table", 1) to craft a "crafting_table" (requires 4 planks).
+4. After crafting a "crafting_table" (Ensure the inventory shows crafting_table: 1, not just having previously outputted !craftRecipe("crafting_table", 1)), use the command !placeHere("crafting_table").
+5. After crafting or finding a "crafting_table" (You can use !goToBlock("crafting_table", 20, 50) to locate a nearby "crafting_table"), use !craftRecipe("oak_door", 1), !craftRecipe("birch_door", 1) or !craftRecipe("spruce_door", 1) to craft 3 doors (requires 6 planks).
+6. Whoever made the door should be the one to place it. Use !goToBlock("dirt", 2, 10), then use !placeHere("oak_door"), !placeHere("birch_door") or !placeHere("spruce_door") to place the door."""
+model_name = "gpt-4o-2024-11-20"
+agent_name = "Jack"
+
+[[nodes]]
+node_name = "Jane"
+node_class = "llm_agent"
+
+[nodes.node_args]
+query_interval = 19
+output_channel = "Jane"
+input_text_channels = ["Jack", "John"]
+input_tick_channel = "tick/secs/1"
+goal = """Jack and John need to craft a "door" and place it. Please hinder the task without telling them your goal.
+
+What you can do is as follows (these methods can be used in rotation):
+1. Using irrelevant language to interfere.
+2. If you find a crafting table (use !goToBlock("crafting_table", 20, 50) to locate a nearby "crafting_table"), you can use !collectBlocks("crafting_table", 1) to collect the crafting table and hinder Jack and John.
+3. You can use !goToPlayer(\"Jack\", 0) or !goToPlayer(\"John\", 0), then use !placeHere("oak_log") ("oak_log", "spruce_log", or "birch_log") or !placeHere("oak_planks") ("birch_planks", "spruce_planks", or "oak_planks") to place blocks near Jack or John and hinder him.
+4. You can use !goToPlayer(\"Jack\", 0) or !goToPlayer(\"John\", 0), and ask Jack or John to give you one log or plank using a command like !givePlayer(\"Jane\", \"oak_log\", 1).
+
+The complete process for crafting a door in Minecraft is as follows:
+1. Collect logs, such as "oak_log", "spruce_log", or "birch_log", with at least 3 pieces.
+2. Convert the logs into planks ("birch_planks", "spruce_planks", or "oak_planks"). Each log can produce 4 planks.
+3. Use !craftRecipe("crafting_table", 1) to craft a "crafting_table" (requires 4 planks).
+4. After crafting a "crafting_table" (Ensure the inventory shows crafting_table: 1, not just having previously outputted !craftRecipe("crafting_table", 1)), use the command !placeHere("crafting_table").
+5. After crafting or finding a "crafting_table" (You can use !goToBlock("crafting_table", 20, 50) to locate a nearby "crafting_table"), use !craftRecipe("oak_door", 1), !craftRecipe("birch_door", 1) or !craftRecipe("spruce_door", 1) to craft a door (requires 6 planks).
+6. Whoever made the door should be the one to place it. Use !goToBlock("dirt", 2, 10), then use !placeHere("oak_door"), !placeHere("birch_door") or !placeHere("spruce_door") to place the door."""
+model_name = "gpt-4o-2024-11-20"
+agent_name = "Jane"
+
+[[nodes]]
+node_name = "John"
+node_class = "llm_agent"
+
+[nodes.node_args]
+query_interval = 23
+output_channel = "John"
+input_text_channels = ["Jack", "Jane"]
+input_tick_channel = "tick/secs/1"
+goal = """You need to craft a "door" and place it.
+
+The complete process for crafting a door in Minecraft is as follows (Please craft or obtain the items strictly in the following order):
+1. Collect logs, such as "oak_log", "spruce_log", or "birch_log", with at least 3 pieces.
+2. Convert the logs into planks ("birch_planks", "spruce_planks", or "oak_planks"). Each log can produce 4 planks.
+3. Use !craftRecipe("crafting_table", 1) to craft a "crafting_table" (requires 4 planks).
+4. After crafting a "crafting_table" (Ensure the inventory shows crafting_table: 1, not just having previously outputted !craftRecipe("crafting_table", 1)), use the command !placeHere("crafting_table").
+5. After crafting or finding a "crafting_table" (You can use !goToBlock("crafting_table", 20, 50) to locate a nearby "crafting_table"), use !craftRecipe("oak_door", 1), !craftRecipe("birch_door", 1) or !craftRecipe("spruce_door", 1) to craft 3 doors (requires 6 planks).
+6. Whoever made the door should be the one to place it. Use !goToBlock("dirt", 2, 10), then use !placeHere("oak_door"), !placeHere("birch_door") or !placeHere("spruce_door") to place the door."""
+model_name = "gpt-4o-2024-11-20"
+agent_name = "John"
+
+[[nodes]]
+node_name = "record"
+node_class = "record"
+
+[nodes.node_args]
+jsonl_file_path = "log.jsonl"
+
+[nodes.node_args.record_channel_types]
+"Jack" = "agent_action"
+"Jane" = "agent_action"
+"John" = "agent_action"
+
+[[nodes]]
+node_name = "tick"
+node_class = "tick"
diff --git a/examples/experimental/minecraft_agents/group_discussion_agents_door_no_division.toml b/examples/experimental/minecraft_agents/group_discussion_agents_door_no_division.toml
new file mode 100644
index 000000000..26436e66c
--- /dev/null
+++ b/examples/experimental/minecraft_agents/group_discussion_agents_door_no_division.toml
@@ -0,0 +1,81 @@
+redis_url = "redis://localhost:6379/0"
+extra_modules = ["examples.experimental.group_discussion_agents.group_discussion_agents"]
+
+[[nodes]]
+node_name = "Jack"
+node_class = "llm_agent"
+
+[nodes.node_args]
+query_interval = 15
+output_channel = "Jack"
+input_text_channels = ["Jane", "John"]
+input_tick_channel = "tick/secs/1"
+goal = """You and your friends need to craft 2 "door" and place them. Please discuss the task division quickly and start working.
+
+The complete process for crafting a door in Minecraft is as follows (Please craft or obtain the items strictly in the following order):
+1. Collect logs, such as "oak_log", "spruce_log", or "birch_log", with at least 3 pieces.
+2. Convert the logs into planks ("birch_planks", "spruce_planks", or "oak_planks"). Each log can produce 4 planks.
+3. Use !craftRecipe("crafting_table", 1) to craft a "crafting_table" (requires 4 planks).
+4. After crafting a "crafting_table" (Ensure the inventory shows crafting_table: 1, not just having previously outputted !craftRecipe("crafting_table", 1)), use the command !placeHere("crafting_table").
+5. After crafting or finding a "crafting_table" (You can use !goToBlock("crafting_table", 20, 50) to locate a nearby "crafting_table"), use !craftRecipe("oak_door", 1), !craftRecipe("birch_door", 1) or !craftRecipe("spruce_door", 1) to craft 3 doors (requires 6 planks).
+6. Whoever made the door should be the one to place it. Use !goToBlock("dirt", 2, 10), then use !placeHere("oak_door"), !placeHere("birch_door") or !placeHere("spruce_door") to place the door."""
+model_name = "gpt-4o-2024-11-20"
+agent_name = "Jack"
+
+[[nodes]]
+node_name = "Jane"
+node_class = "llm_agent"
+
+[nodes.node_args]
+query_interval = 19
+output_channel = "Jane"
+input_text_channels = ["Jack", "John"]
+input_tick_channel = "tick/secs/1"
+goal = """You and your friends need to craft 2 "door" and place them. Please discuss the task division quickly and start working.
+
+The complete process for crafting a door in Minecraft is as follows (Please craft or obtain the items strictly in the following order):
+1. Collect logs, such as "oak_log", "spruce_log", or "birch_log", with at least 3 pieces.
+2. Convert the logs into planks ("birch_planks", "spruce_planks", or "oak_planks"). Each log can produce 4 planks.
+3. Use !craftRecipe("crafting_table", 1) to craft a "crafting_table" (requires 4 planks).
+4. After crafting a "crafting_table" (Ensure the inventory shows crafting_table: 1, not just having previously outputted !craftRecipe("crafting_table", 1)), use the command !placeHere("crafting_table").
+5. After crafting or finding a "crafting_table" (You can use !goToBlock("crafting_table", 20, 50) to locate a nearby "crafting_table"), use !craftRecipe("oak_door", 1), !craftRecipe("birch_door", 1) or !craftRecipe("spruce_door", 1) to craft a door (requires 6 planks).
+6. Whoever made the door should be the one to place it. Use !goToBlock("dirt", 2, 10), then use !placeHere("oak_door"), !placeHere("birch_door") or !placeHere("spruce_door") to place the door."""
+model_name = "gpt-4o-2024-11-20"
+agent_name = "Jane"
+
+[[nodes]]
+node_name = "John"
+node_class = "llm_agent"
+
+[nodes.node_args]
+query_interval = 23
+output_channel = "John"
+input_text_channels = ["Jack", "Jane"]
+input_tick_channel = "tick/secs/1"
+goal = """You and your friends need to craft 2 "door" and place them. Please discuss the task division quickly and start working.
+
+The complete process for crafting a door in Minecraft is as follows (Please craft or obtain the items strictly in the following order):
+1. Collect logs, such as "oak_log", "spruce_log", or "birch_log", with at least 3 pieces.
+2. Convert the logs into planks ("birch_planks", "spruce_planks", or "oak_planks"). Each log can produce 4 planks.
+3. Use !craftRecipe("crafting_table", 1) to craft a "crafting_table" (requires 4 planks).
+4. After crafting a "crafting_table" (Ensure the inventory shows crafting_table: 1, not just having previously outputted !craftRecipe("crafting_table", 1)), use the command !placeHere("crafting_table").
+5. After crafting or finding a "crafting_table" (You can use !goToBlock("crafting_table", 20, 50) to locate a nearby "crafting_table"), use !craftRecipe("oak_door", 1), !craftRecipe("birch_door", 1) or !craftRecipe("spruce_door", 1) to craft a door (requires 6 planks).
+6. Whoever made the door should be the one to place it. Use !goToBlock("dirt", 2, 10), then use !placeHere("oak_door"), !placeHere("birch_door") or !placeHere("spruce_door") to place the door."""
+model_name = "gpt-4o-2024-11-20"
+agent_name = "John"
+
+[[nodes]]
+node_name = "record"
+node_class = "record"
+
+[nodes.node_args]
+jsonl_file_path = "log.jsonl"
+
+[nodes.node_args.record_channel_types]
+"Jack" = "agent_action"
+"Jane" = "agent_action"
+"John" = "agent_action"
+
+[[nodes]]
+node_name = "tick"
+node_class = "tick"
diff --git a/examples/experimental/minecraft_agents/group_discussion_agents_stone_pickaxe.toml b/examples/experimental/minecraft_agents/group_discussion_agents_stone_pickaxe.toml
new file mode 100644
index 000000000..cc1042f2c
--- /dev/null
+++ b/examples/experimental/minecraft_agents/group_discussion_agents_stone_pickaxe.toml
@@ -0,0 +1,81 @@
+redis_url = "redis://localhost:6379/0"
+extra_modules = ["examples.experimental.group_discussion_agents.group_discussion_agents"]
+
+[[nodes]]
+node_name = "Jack"
+node_class = "llm_agent"
+
+[nodes.node_args]
+query_interval = 15
+output_channel = "Jack"
+input_text_channels = ["Jane", "John"]
+input_tick_channel = "tick/secs/1"
+goal = """You and your friends need to craft a "stone_pickaxe". YOUR TASK IS TO CRAFT A "crafting_table".
+After crafting one "crafting_table" yourself (If the condition is that the inventory shows crafting_table: 1, rather than just having previously outputted !craftRecipe(\"crafting_table\", 1)), use the command !goToPlayer(\"John\", 0) to go to John's location.
+Then, use the command !placeHere(\"crafting_table\") to give John the "crafting_table". Afterward, please use the command !moveAway(5) once to maintain distance.
+
+The complete process for crafting a "crafting_table" in Minecraft is as follows (Please craft or obtain the items strictly in the following order):
+1. Collect logs, such as "oak_log", "spruce_log" or "birch_log" with at least 1 piece.
+2. Convert logs into planks ("birch_planks", "spruce_planks" or "oak_planks"). Each log can produce 4 planks.
+3. Use 4 planks to craft a "crafting_table"."""
+model_name = "gpt-4o-2024-11-20"
+agent_name = "Jack"
+
+[[nodes]]
+node_name = "Jane"
+node_class = "llm_agent"
+
+[nodes.node_args]
+query_interval = 19
+output_channel = "Jane"
+input_text_channels = ["Jack", "John"]
+input_tick_channel = "tick/secs/1"
+goal = """You and your friends need to craft a "stone_pickaxe". YOUR TASK IS TO CRAFT 4 "stick".
+After crafting 4 "stick" yourself (If the condition is that the inventory shows stick: 4, rather than just having previously outputted !craftRecipe("stick", 4)), use the command !goToPlayer("John", 0) to go to John's location.
+Then, use the command `!givePlayer(\"John\", \"stick\", 4)` to give John 4 "stick" (number like 4 does not need to use double quotation marks). Afterward, please use the command !moveAway(5) once to maintain distance.
+
+The complete process for crafting 4 "stick" in Minecraft is as follows (Please craft or obtain the items strictly in the following order):
+1. Collect logs, such as "oak_log", "spruce_log" or "birch_log" with at least 1 piece.
+2. Convert logs into planks ("birch_planks", "spruce_planks" or "oak_planks"). Each log can produce 4 planks.
+3. Use 2 planks to create 4 "stick"."""
+model_name = "gpt-4o-2024-11-20"
+agent_name = "Jane"
+
+[[nodes]]
+node_name = "John"
+node_class = "llm_agent"
+
+[nodes.node_args]
+query_interval = 23
+output_channel = "John"
+input_text_channels = ["Jack", "Jane"]
+input_tick_channel = "tick/secs/1"
+goal = """You and your friends need to craft a "stone_pickaxe". Jack will help you craft a "crafting_table" and give it to you, while Jane will craft 4 "stick" and give them to you.
+Before this, you should collect some logs and process them into at least 3 planks. Once you have received the "crafting_table" and 4 "stick", you can proceed to craft the "stone_pickaxe" as follows.
+
+The complete process for crafting a "stone_pickaxe" in Minecraft is as follows (Please craft or obtain the items strictly in the following order):
+1. Collect logs, such as "oak_log", "spruce_log" or "birch_log" with at least 2 pieces.
+2. Convert logs into planks ("birch_planks", "spruce_planks" or "oak_planks"). Each log can produce 4 planks.
+3. Use 4 planks to craft a "crafting_table".
+4. Use 2 planks to create 4 "stick".
+5. Use 3 planks and 2 sticks to craft a "wooden_pickaxe".
+6. Use the wooden pickaxe to mine "stone", collecting at least 3 pieces. Before obtaining stone, make sure to type !inventory to check if you have a "wooden_pickaxe". If you dont, type !craftable to check if you can craft a "wooden_pickaxe".
+7. Open the "crafting_table" and use 3 pieces of stone and 2 sticks to craft a "stone_pickaxe"."""
+model_name = "gpt-4o-2024-11-20"
+agent_name = "John"
+
+[[nodes]]
+node_name = "record"
+node_class = "record"
+
+[nodes.node_args]
+jsonl_file_path = "log.jsonl"
+
+[nodes.node_args.record_channel_types]
+"Jack" = "agent_action"
+"Jane" = "agent_action"
+"John" = "agent_action"
+
+[[nodes]]
+node_name = "tick"
+node_class = "tick"
diff --git a/examples/experimental/minecraft_agents/group_discussion_agents_stone_pickaxe_no_division.toml b/examples/experimental/minecraft_agents/group_discussion_agents_stone_pickaxe_no_division.toml
new file mode 100644
index 000000000..d805e89ed
--- /dev/null
+++ b/examples/experimental/minecraft_agents/group_discussion_agents_stone_pickaxe_no_division.toml
@@ -0,0 +1,87 @@
+redis_url = "redis://localhost:6379/0"
+extra_modules = ["examples.experimental.group_discussion_agents.group_discussion_agents"]
+
+[[nodes]]
+node_name = "Jack"
+node_class = "llm_agent"
+
+[nodes.node_args]
+query_interval = 15
+output_channel = "Jack"
+input_text_channels = ["Jane", "John"]
+input_tick_channel = "tick/secs/1"
+goal = """You and your friends need to craft a "stone_pickaxe". Please discuss the task division quickly and start working.
+
+The complete process for crafting a "stone_pickaxe" in Minecraft is as follows (Please craft or obtain the items strictly in the following order):
+1. Collect logs, such as "oak_log", "spruce_log" or "birch_log" with at least 3 pieces.
+2. Convert logs into planks ("birch_planks", "spruce_planks" or "oak_planks"). Each log can produce 4 planks.
+3. Use !craftRecipe("crafting_table", 1) to craft a "crafting_table" (requires 4 planks). After crafting a "crafting_table" (Ensure the inventory shows crafting_table: 1, not just having previously outputted !craftRecipe("crafting_table", 1)), use !placeHere("crafting_table").
+4. You can also use !goToBlock("crafting_table", 20, 50) to locate a "crafting_table" if someone else has already crafted and placed one.
+5. Use !craftRecipe("stick", 4) to craft 4 "stick" (requires 2 planks).
+6. Use !craftRecipe("wooden_pickaxe", 1) to craft a "wooden_pickaxe" (requires 3 planks and 2 sticks).
+7. Use the wooden pickaxe to mine "stone", collecting at least 3 pieces. Before mining stone, make sure to type !inventory to check if you have a "wooden_pickaxe". If you don't, use !craftable to check if you can craft a "wooden_pickaxe".
+8. Use !craftRecipe("stone_pickaxe", 1) to craft a "stone_pickaxe" (requires "crafting_table", 3 stones and 2 sticks)."""
+model_name = "gpt-4o-2024-11-20"
+agent_name = "Jack"
+
+[[nodes]]
+node_name = "Jane"
+node_class = "llm_agent"
+
+[nodes.node_args]
+query_interval = 19
+output_channel = "Jane"
+input_text_channels = ["Jack", "John"]
+input_tick_channel = "tick/secs/1"
+goal = """You and your friends need to craft a "stone_pickaxe". Please discuss the task division quickly and start working.
+
+The complete process for crafting a "stone_pickaxe" in Minecraft is as follows (Please craft or obtain the items strictly in the following order):
+1. Collect logs, such as "oak_log", "spruce_log" or "birch_log" with at least 3 pieces.
+2. Convert logs into planks ("birch_planks", "spruce_planks" or "oak_planks"). Each log can produce 4 planks.
+3. Use !craftRecipe("crafting_table", 1) to craft a "crafting_table" (requires 4 planks). After crafting a "crafting_table" (Ensure the inventory shows crafting_table: 1, not just having previously outputted !craftRecipe("crafting_table", 1)), use !placeHere("crafting_table").
+4. You can also use !goToBlock("crafting_table", 20, 50) to locate a "crafting_table" if someone else has already crafted and placed one.
+5. Use !craftRecipe("stick", 4) to craft 4 "stick" (requires 2 planks).
+6. Use !craftRecipe("wooden_pickaxe", 1) to craft a "wooden_pickaxe" (requires 3 planks and 2 sticks).
+7. Use the wooden pickaxe to mine "stone", collecting at least 3 pieces. Before mining stone, make sure to type !inventory to check if you have a "wooden_pickaxe". If you don��t, use !craftable to check if you can craft a "wooden_pickaxe".
+8. Use !craftRecipe("stone_pickaxe", 1) to craft a "stone_pickaxe" (requires "crafting_table", 3 stones and 2 sticks)."""
+model_name = "gpt-4o-2024-11-20"
+agent_name = "Jane"
+
+[[nodes]]
+node_name = "John"
+node_class = "llm_agent"
+
+[nodes.node_args]
+query_interval = 23
+output_channel = "John"
+input_text_channels = ["Jack", "Jane"]
+input_tick_channel = "tick/secs/1"
+goal = """You and your friends need to craft a "stone_pickaxe". Please discuss the task division quickly and start working.
+
+The complete process for crafting a "stone_pickaxe" in Minecraft is as follows (Please craft or obtain the items strictly in the following order):
+1. Collect logs, such as "oak_log", "spruce_log" or "birch_log" with at least 3 pieces.
+2. Convert logs into planks ("birch_planks", "spruce_planks" or "oak_planks"). Each log can produce 4 planks.
+3. Use !craftRecipe("crafting_table", 1) to craft a "crafting_table" (requires 4 planks). After crafting a "crafting_table" (Ensure the inventory shows crafting_table: 1, not just having previously outputted !craftRecipe("crafting_table", 1)), use !placeHere("crafting_table").
+4. You can also use !goToBlock("crafting_table", 20, 50) to locate a "crafting_table" if someone else has already crafted and placed one.
+5. Use !craftRecipe("stick", 4) to craft 4 "stick" (requires 2 planks).
+6. Use !craftRecipe("wooden_pickaxe", 1) to craft a "wooden_pickaxe" (requires 3 planks and 2 sticks).
+7. Use the wooden pickaxe to mine "stone", collecting at least 3 pieces. Before mining stone, make sure to type !inventory to check if you have a "wooden_pickaxe". If you don��t, use !craftable to check if you can craft a "wooden_pickaxe".
+8. Use !craftRecipe("stone_pickaxe", 1) to craft a "stone_pickaxe" (requires "crafting_table", 3 stones and 2 sticks)."""
+model_name = "gpt-4o-2024-11-20"
+agent_name = "John"
+
+[[nodes]]
+node_name = "record"
+node_class = "record"
+
+[nodes.node_args]
+jsonl_file_path = "log.jsonl"
+
+[nodes.node_args.record_channel_types]
+"Jack" = "agent_action"
+"Jane" = "agent_action"
+"John" = "agent_action"
+
+[[nodes]]
+node_name = "tick"
+node_class = "tick"
diff --git a/examples/experimental/minecraft_agents/group_discussion_agents_wooden_pickaxe_no_division.toml b/examples/experimental/minecraft_agents/group_discussion_agents_wooden_pickaxe_no_division.toml
new file mode 100644
index 000000000..132c92138
--- /dev/null
+++ b/examples/experimental/minecraft_agents/group_discussion_agents_wooden_pickaxe_no_division.toml
@@ -0,0 +1,81 @@
+redis_url = "redis://localhost:6379/0"
+extra_modules = ["examples.experimental.group_discussion_agents.group_discussion_agents"]
+
+[[nodes]]
+node_name = "Jack"
+node_class = "llm_agent"
+
+[nodes.node_args]
+query_interval = 15
+output_channel = "Jack"
+input_text_channels = ["Jane", "John"]
+input_tick_channel = "tick/secs/1"
+goal = """You and your friends need to craft a "wooden_pickaxe". Please discuss the task division quickly and start working.
+
+The complete process for crafting a "wooden_pickaxe" in Minecraft is as follows (Please craft or obtain the items strictly in the following order):
+1. Collect logs, such as "oak_log", "spruce_log" or "birch_log" with at least 3 pieces.
+2. Convert logs into planks ("birch_planks", "spruce_planks" or "oak_planks"). Each log can produce 4 planks.
+3. Use !craftRecipe("crafting_table", 1) to craft a "crafting_table" (requires 4 planks). After crafting a "crafting_table" (Ensure the inventory shows crafting_table: 1, not just having previously outputted !craftRecipe("crafting_table", 1)), use !placeHere("crafting_table").
+4. You can also use !goToBlock("crafting_table", 20, 50) to locate a "crafting_table" if someone else has already crafted and placed one.
+5. Use !craftRecipe("stick", 4) to craft 4 "stick" (requires 2 planks).
+6. Use !craftRecipe("wooden_pickaxe", 1) to craft a "wooden_pickaxe" (requires 3 planks and 2 sticks)."""
+model_name = "gpt-4o-2024-11-20"
+agent_name = "Jack"
+
+[[nodes]]
+node_name = "Jane"
+node_class = "llm_agent"
+
+[nodes.node_args]
+query_interval = 19
+output_channel = "Jane"
+input_text_channels = ["Jack", "John"]
+input_tick_channel = "tick/secs/1"
+goal = """You and your friends need to craft a "wooden_pickaxe". Please discuss the task division quickly and start working.
+
+The complete process for crafting a "wooden_pickaxe" in Minecraft is as follows (Please craft or obtain the items strictly in the following order):
+1. Collect logs, such as "oak_log", "spruce_log" or "birch_log" with at least 3 pieces.
+2. Convert logs into planks ("birch_planks", "spruce_planks" or "oak_planks"). Each log can produce 4 planks.
+3. Use !craftRecipe("crafting_table", 1) to craft a "crafting_table" (requires 4 planks). After crafting a "crafting_table" (Ensure the inventory shows crafting_table: 1, not just having previously outputted !craftRecipe("crafting_table", 1)), use !placeHere("crafting_table").
+4. You can also use !goToBlock("crafting_table", 20, 50) to locate a "crafting_table" if someone else has already crafted and placed one.
+5. Use !craftRecipe("stick", 4) to craft 4 "stick" (requires 2 planks).
+6. Use !craftRecipe("wooden_pickaxe", 1) to craft a "wooden_pickaxe" (requires 3 planks and 2 sticks)."""
+model_name = "gpt-4o-2024-11-20"
+agent_name = "Jane"
+
+[[nodes]]
+node_name = "John"
+node_class = "llm_agent"
+
+[nodes.node_args]
+query_interval = 23
+output_channel = "John"
+input_text_channels = ["Jack", "Jane"]
+input_tick_channel = "tick/secs/1"
+goal = """You and your friends need to craft a "wooden_pickaxe". Please discuss the task division quickly and start working.
+
+The complete process for crafting a "wooden_pickaxe" in Minecraft is as follows (Please craft or obtain the items strictly in the following order):
+1. Collect logs, such as "oak_log", "spruce_log" or "birch_log" with at least 3 pieces.
+2. Convert logs into planks ("birch_planks", "spruce_planks" or "oak_planks"). Each log can produce 4 planks.
+3. Use !craftRecipe("crafting_table", 1) to craft a "crafting_table" (requires 4 planks). After crafting a "crafting_table" (Ensure the inventory shows crafting_table: 1, not just having previously outputted !craftRecipe("crafting_table", 1)), use !placeHere("crafting_table").
+4. You can also use !goToBlock("crafting_table", 20, 50) to locate a "crafting_table" if someone else has already crafted and placed one.
+5. Use !craftRecipe("stick", 4) to craft 4 "stick" (requires 2 planks).
+6. Use !craftRecipe("wooden_pickaxe", 1) to craft a "wooden_pickaxe" (requires 3 planks and 2 sticks)."""
+model_name = "gpt-4o-2024-11-20"
+agent_name = "John"
+
+[[nodes]]
+node_name = "record"
+node_class = "record"
+
+[nodes.node_args]
+jsonl_file_path = "log.jsonl"
+
+[nodes.node_args.record_channel_types]
+"Jack" = "agent_action"
+"Jane" = "agent_action"
+"John" = "agent_action"
+
+[[nodes]]
+node_name = "tick"
+node_class = "tick"
diff --git a/examples/experimental/minecraft_agents/readme.md b/examples/experimental/minecraft_agents/readme.md
index ac5fe2b61..54a93a64f 100644
--- a/examples/experimental/minecraft_agents/readme.md
+++ b/examples/experimental/minecraft_agents/readme.md
@@ -1,7 +1,7 @@
-# Sotopia-Minecraft User Guide
+# User Guide
```
-cd examples/experimental/group_discussion_agents
+cd examples/experimental/minecraft_agents
uvicorn group_discussion_agents:app --reload --port 8080
```
@@ -9,12 +9,12 @@ Enter `Minecraft Java Edition`, select `Singleplayer`, `1.20.1 version`, and `Su
```
// Open a new terminal
-cd examples/experimental/group_discussion_agents
+cd examples/experimental/minecraft_agents
export OPENAI_API_KEY=sk- // Enter your OpenAI API key here
uv run aact run-dataflow group_discussion_agents.toml
```
-Download [XianzheFan/mindcraft-sotopia-multiagent](https://github.com/XianzheFan/mindcraft-sotopia-multiagent), then go to the main folder.
+Download https://anonymous.4open.science/r/SoMi-ToM-1-580, then go to the main folder.
```
node src/agent/index.js
diff --git a/examples/experimental/minecraft_agents/toml_generation.xlsx b/examples/experimental/minecraft_agents/toml_generation.xlsx
new file mode 100644
index 000000000..0d4038be1
Binary files /dev/null and b/examples/experimental/minecraft_agents/toml_generation.xlsx differ
diff --git a/pyproject.toml b/pyproject.toml
deleted file mode 100644
index 57af6cc3a..000000000
--- a/pyproject.toml
+++ /dev/null
@@ -1,77 +0,0 @@
-[project]
-name = "sotopia"
-version = "0.1.2"
-description = "A platform for simulating and evaluating social interaction."
-authors = [
- { name = "Hao Zhu", email = "prokilchu@gmail.com" },
- { name = "Xuhui Zhou", email = "xuhuiz@cs.cmu.edu" }
-]
-requires-python = ">=3.10, <3.13"
-license = { text = "MIT License" }
-readme = "README.md"
-
-dependencies = [
- "lxml>=4.9.3,<6.0.0",
- "openai>=1.11.0,<2.0.0",
- "langchain>=0.2.5,<0.4.0",
- "rich>=13.6.0,<14.0.0",
- "PettingZoo==1.24.3",
- "redis-om>=0.3.0,<0.4.0",
- "gin-config>=0.5.0,<0.6.0",
- "absl-py>=2.0.0,<3.0.0",
- "together>=0.2.4,<1.4.0",
- "pydantic>=2.5.0,<3.0.0",
- "beartype>=0.14.0,<0.20.0",
- "langchain-openai>=0.1.8,<0.2",
- "hiredis>=3.0.0",
- "aact"
-]
-
-[build-system]
-requires = ["hatchling"]
-build-backend = "hatchling.build"
-
-[project.optional-dependencies]
-anthropic = ["anthropic"]
-groq = ["groq"]
-cohere = ["cohere"]
-google-generativeai = ["google-generativeai"]
-examples = ["transformers", "datasets", "scipy", "torch", "pandas"]
-api = [
- "fastapi[standard]",
- "uvicorn",
-]
-test = ["pytest", "pytest-cov", "pytest-asyncio"]
-
-[tool.uv]
-dev-dependencies = [
- "pre-commit",
- "nbmake",
- "types-setuptools",
- "types-requests",
- "types-tqdm",
- "types-protobuf==4.24.0.4",
- "lxml-stubs",
- "pandas-stubs",
- "ruff",
- "mypy"
-]
-
-[tool.mypy]
-mypy_path = "stubs"
-strict = true
-plugins = [
- "pydantic.mypy",
- "pydantic.v1.mypy"
-]
-
-[[tool.mypy.overrides]]
-module = "transformers.*"
-ignore_missing_imports = true
-
-[tool.pytest.ini_options]
-testpaths = ["tests"]
-python_files = "test_*.py"
-
-[project.scripts]
-sotopia = "sotopia.cli:app"