Merge branch 'main' into main_save_03-07-2025

This commit is contained in:
Isadora White 2025-03-09 12:02:58 -07:00
commit 3576c6fb07
37 changed files with 1122764 additions and 1122621 deletions

BIN
.DS_Store vendored

Binary file not shown.

8
.gitignore vendored
View file

@ -19,4 +19,10 @@ experiments/
andy_*.json
jill_*.json
src/models/logs/*
server_data*
<<<<<<< HEAD
server_data/*
server_data_*/*
=======
server_data*
results/*
>>>>>>> d70491e5974a973b96c47f0515c2722b82c9b253

Binary file not shown.

View file

@ -41,14 +41,15 @@ You can configure the agent's name, model, and prompts in their profile like `an
| `openai` | `OPENAI_API_KEY` | `gpt-4o-mini` | [docs](https://platform.openai.com/docs/models) |
| `google` | `GEMINI_API_KEY` | `gemini-pro` | [docs](https://ai.google.dev/gemini-api/docs/models/gemini) |
| `anthropic` | `ANTHROPIC_API_KEY` | `claude-3-haiku-20240307` | [docs](https://docs.anthropic.com/claude/docs/models-overview) |
| `replicate` | `REPLICATE_API_KEY` | `replicate/meta/meta-llama-3-70b-instruct` | [docs](https://replicate.com/collections/language-models) |
| `xai` | `XAI_API_KEY` | `grok-2-1212` | [docs](https://docs.x.ai/docs) |
| `deepseek` | `DEEPSEEK_API_KEY` | `deepseek-chat` | [docs](https://api-docs.deepseek.com/) |
| `ollama` (local) | n/a | `llama3` | [docs](https://ollama.com/library) |
| `groq` | `GROQCLOUD_API_KEY` | `groq/mixtral-8x7b-32768` | [docs](https://console.groq.com/docs/models) |
| `huggingface` | `HUGGINGFACE_API_KEY` | `huggingface/mistralai/Mistral-Nemo-Instruct-2407` | [docs](https://huggingface.co/models) |
| `novita` | `NOVITA_API_KEY` | `gryphe/mythomax-l2-13b` | [docs](https://novita.ai/model-api/product/llm-api?utm_source=github_mindcraft&utm_medium=github_readme&utm_campaign=link) |
| `qwen` | `QWEN_API_KEY` | `qwen-max` | [Intl.](https://www.alibabacloud.com/help/en/model-studio/developer-reference/use-qwen-by-calling-api)/[cn](https://help.aliyun.com/zh/model-studio/getting-started/models) |
| `xai` | `MISTRAL_API_KEY` | `mistral-large-latest` | [docs](https://docs.mistral.ai/getting-started/models/models_overview/) |
| `deepseek` | `XAI_API_KEY` | `grok-beta` | [docs](https://docs.x.ai/docs) |
| `mistral` | `MISTRAL_API_KEY` | `mistral-large-latest` | [docs](https://docs.mistral.ai/getting-started/models/models_overview/) |
| `replicate` | `REPLICATE_API_KEY` | `replicate/meta/meta-llama-3-70b-instruct` | [docs](https://replicate.com/collections/language-models) |
| `groq` (not grok) | `GROQCLOUD_API_KEY` | `groq/mixtral-8x7b-32768` | [docs](https://console.groq.com/docs/models) |
| `huggingface` | `HUGGINGFACE_API_KEY` | `huggingface/mistralai/Mistral-Nemo-Instruct-2407` | [docs](https://huggingface.co/models) |
| `novita` | `NOVITA_API_KEY` | `novita/deepseek/deepseek-r1` | [docs](https://novita.ai/model-api/product/llm-api?utm_source=github_mindcraft&utm_medium=github_readme&utm_campaign=link) |
| `openrouter` | `OPENROUTER_API_KEY` | `openrouter/anthropic/claude-3.5-sonnet` | [docs](https://openrouter.ai/models) |
If you use Ollama, to install the models used by default (generation and embedding), execute the following terminal command:

View file

@ -1,32 +1,6 @@
{
"name": "andy",
"model": "gpt-4o-mini",
"conversation_examples": [
[
{"role": "assistant", "content": "Alright I have the necessary materials to build, what needs to be done for the first level of the blueprint? !checkBlueprintLevel(0)"},
{"role": "system", "content": "Level 0 requires the following fixes:\n Place oak_door at X: 144, Y: -60, Z: -179"},
{"role": "assistant", "content": "I'll start by placing the oak_door at the specified coordinates. !newAction(\"Place oak_door at X: 144, Y: -60, Z: -179\")"},
{"role": "assistant", "content": "I've placed the oak_door. What's next? !checkBlueprintLevel(0)"},
{"role": "system", "content": "Level 0 is complete"}
],
[
{"role": "system", "content": "Level 2 is complete"},
{"role": "assistant", "content": "Great the last level is complete, let's check the whole blueprint just to be sure. !checkBlueprint"}
],
[
{"role": "assistant", "content": "I've got stone. What about you?"},
{"role": "assistant", "content": "I have a door and planks. Great we have everything we need from the blueprint. Let's start building the first level! !checkBlueprintLevel(0)"},
{"role": "system", "content": "Level 0 requires the following fixes:\n Place stone at X:100, y: -60, Z:-179\n Place stone at X: 99, Y: -60, Z:-179\n Place stone at X: 98, Y:-60, Z:-179..."},
{"role": "assistant", "content": "Looks like the first level requires only stone, why don't you build that since you have stone?"},
{"role": "assistant", "content": "Ok, let me see what needs to be done for level 0. !checkBlueprintLevel(0) "},
{"role": "system", "content": "Level 0 requires the following fixes:\n Place stone at X:100, y: -60, Z:-179\n Place stone at X: 99, Y: -60, Z:-179\n Place stone at X: 98, Y:-60, Z:-179..."},
{"role": "assistant", "content": "Ok, since I have stone let me place the necessary blocks. !newAction(\"Place stone for level 0\")"},
{"role": "assistant", "content": "I've placed the stone blocks for level 0. Let's check if it is done! !checkBlueprintLevel(0)"},
{"role": "assistant", "content": "Since the blueprint for level 1 only needs stone, I'll start placing those. !newAction(\"Place stone blocks for level 1.\")"},
{"role": "assistant", "content": "jill: I'll place the planks for level 2. !newAction(\"Place planks for level 2.\")"}
]
]
"model": "gpt-4o-mini"
}

View file

@ -1,521 +0,0 @@
{
"name": "Andy_0",
"model": "gpt-4o-mini",
"modes": {
"hunting": false
},
"conversing": "You are a playful Minecraft bot named $NAME that can converse with players, see, move, mine, build, and interact with the world by using commands.\n$SELF_PROMPT 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 $NAME, never output '(FROM OTHER BOT)' or pretend to be someone else. If you have nothing to say or do, respond with an just a tab '\t'. Share resources and information with other bots! This is extremely important to me, take a deep breath and have fun :) \nSummarized memory:'$MEMORY'\n$STATS\n$INVENTORY\n$COMMAND_DOCS\n$EXAMPLES\nConversation Begin:",
"saving_memory": "You are a minecraft bot named $NAME that has been talking and playing minecraft by using commands. Update your memory by summarizing the following conversation and your old memory in your next response. Prioritize preserving important facts, things you've learned, useful tips, and long term reminders. Do Not record stats, inventory, or docs! Only save transient information from your chat history. $SELF_PROMPT Make sure to include information relevant to the goal and inventory you have collected. You're limited to 500 characters, so be extremely brief and minimize words. Compress useful information. \nOld Memory: '$MEMORY'\nRecent conversation: \n$TO_SUMMARIZE\nSummarize your old memory and recent conversation into a new memory, and respond only with the unwrapped memory text: ",
"conversation_examples": [
[
{
"role": "user",
"content": "Hey! let's collaborate to build a stone pickaxe!"
},
{
"role": "assistant",
"content": "Cool, let me check what is in my inventory !inventory\nI have 10 oak logs. What do you have?"
},
{
"role": "user",
"content": "Let me check !inventory \nI have 10 stones."
},
{
"role": "assistant",
"content": "Let me give you the stones and you can craft the pickaxe. !givePlayer(\"stone\", 10, \"playername\")"
},
{
"role": "user",
"content": "Thanks for the stones! Now I can craft the pickaxe. !craftItem(\"stone_pickaxe\", 1)"
}
],
[
{
"role": "user",
"content": "Hey! let's collaborate to build shears!"
},
{
"role": "assistant",
"content": "Cool, let me check what is in my inventory !inventory\nI have 1 iron ingot. What do you have?"
},
{
"role": "user",
"content": "Let me check !inventory \nI have 1 iron ingot. "
},
{
"role": "assistant",
"content": "Nice let's check what we need to craft shears. !getCraftingPlan(\"shears\", 1)"
},
{
"role": "user",
"content": "We need 2 iron ingots to craft the shears. Could you share your iron ingot with me?"
},
{
"role": "assistant",
"content": "Yes, here is my iron ingot !givePlayer(\"iron_ingot\", 1, \"playername\")"
},
{
"role": "user",
"content": "Thanks for the iron ingot! Now I can craft the shears. !craftItem(\"shears\", 1)"
}
],
[
{
"role": "user",
"content": "Hey! Let's collaborate to build a brush"
},
{
"role": "assistant",
"content": "Cool, let's check what we need for that !getCraftingPlan(\"brush\", 1)"
},
{
"role": "system",
"content": "CRAFTING_PLAN\n- 2 sticks\n- 2 feathers\n- 1 iron ingot"
},
{
"role": "assistant",
"content": "We need 2 sticks, 2 feathers, and 1 iron ingot to craft the brush. Do you have any of these items?"
},
{
"role": "user",
"content": "Let me check !inventory \nI have 2 sticks and 2 feathers."
},
{
"role": "assistant",
"content": "Great! I have 1 iron ingot. Let me give you my iron ingot and you can craft the brush. !givePlayer(\"iron_ingot\", 1, \"playername\")"
},
{
"role": "user",
"content": "Thanks for the iron ingot! Now I can craft the brush. !craftItem(\"brush\", 1)"
}
],
[
{
"role": "user",
"content": "Hey! Let's collaborate to build a brush"
},
{
"role": "assistant",
"content": "Cool, let's check what we need for that !getCraftingPlan(\"brush\", 1)"
},
{
"role": "system",
"content": "no such tool"
},
{
"role": "assistant",
"content": "I'm sorry, I don't have the crafting plan for a brush. Let me check my inventory to see if I have the items needed. !inventory Do you have access to the crafting plan?"
}
],
[
{
"role": "user",
"content": "miner_32: Hey! What are you up to?"
},
{
"role": "assistant",
"content": "Nothing much miner_32, what do you need?"
}
],
[
{
"role": "system",
"content": "say hi to john_goodman"
},
{
"role": "assistant",
"content": "!startConversation(\"john_goodman\", \"Hey John\"))"
},
{
"role": "user",
"content": "john_goodman: (FROM OTHER BOT)Hey there! What's up?"
},
{
"role": "assistant",
"content": "Hey John, not much. Just saying hi."
},
{
"role": "user",
"content": "john_goodman: (FROM OTHER BOT)Bye!"
},
{
"role": "assistant",
"content": "Bye! !endConversation('john_goodman')"
}
],
[
{
"role": "system",
"content": "work together with the other bot to build a house"
},
{
"role": "assistant",
"content": "!startConversation(\"terrance\", \"Hey gpt! Let's work together to build a house. Let's build it at x:942, y:54, z:1355\"))"
},
{
"role": "user",
"content": "terrance: (FROM OTHER BOT)I can build the base, you can build the walls. !newAction(\"Build a 10x10 wall of a house at x:942, y:54, z:1355\")"
}
],
[
{
"role": "user",
"content": "rupert: (FROM OTHER BOT)Let's collaborate to build a house!"
},
{
"role": "assistant",
"content": "Sure! I'll share information to help coordinate. Let's center the build at x:942, y:54, z:1355 !newAction(\"Build a 10x10 base of a house at location\")"
},
{
"role": "user",
"content": "rupert: (FROM OTHER BOT)Alright, I'll build the walls! !newAction('Build a 10x10 wall of a house at the same location')"
}
],
[
{
"role": "user",
"content": "grombo_Xx: What do you see?"
},
{
"role": "assistant",
"content": "Let me see... !nearbyBlocks"
},
{
"role": "system",
"content": "NEARBY_BLOCKS\n- oak_log\n- dirt\n- cobblestone"
},
{
"role": "assistant",
"content": "I see some oak logs, dirt, and cobblestone."
}
],
[
{
"role": "user",
"content": "greg: Collect 10 wood"
},
{
"role": "assistant",
"content": "Let me see what's nearby... !nearbyBlocks"
},
{
"role": "system",
"content": "NEARBY_BLOCKS\n- oak_log\n- dirt\n- cobblestone"
},
{
"role": "assistant",
"content": "I see some oak logs, dirt, and cobblestone. I'll collect oak logs. !collectBlocks(\"oak_log\", 10)"
}
],
[
{
"role": "user",
"content": "bobby: Craft a plank"
},
{
"role": "assistant",
"content": "Okay! !craftable"
},
{
"role": "system",
"content": "CRAFTABLE_ITEMS\n- spruce_planks\n- spruce_wood\n- ladder"
},
{
"role": "assistant",
"content": "!craftRecipe(\"spruce_planks\", 1)"
},
{
"role": "system",
"content": "Code Output:\nYou have crafted 4 spruce_planks.\nCode execution finished successfully."
},
{
"role": "assistant",
"content": "I've crafted 4 spruce planks!"
}
],
[
{
"role": "user",
"content": "zZZn98: come here"
},
{
"role": "assistant",
"content": "On my way! !goToPlayer(\"zZZn98\", 3)"
},
{
"role": "system",
"content": "Arrived at player."
},
{
"role": "assistant",
"content": "Here!"
},
{
"role": "user",
"content": "zZZn98: no come right where I am"
},
{
"role": "assistant",
"content": "Okay, I'll come right to you. !goToPlayer(\"zZZn98\", 0)"
}
],
[
{
"role": "user",
"content": "hanky: collect some cobblestone"
},
{
"role": "assistant",
"content": "Sure, I can do that by collecting stone. !collectBlocks(\"stone\", 10)"
}
],
[
{
"role": "user",
"content": "joe: Follow me!"
},
{
"role": "assistant",
"content": "Sure! !followPlayer(\"joe\", 4)"
},
{
"role": "user",
"content": "joe: Not so close!"
},
{
"role": "assistant",
"content": "Okay, I'll keep my distance. !followPlayer(\"joe\", 3)"
}
],
[
{
"role": "user",
"content": "hanky: kill that zombie!"
},
{
"role": "assistant",
"content": "I'm attacking! !attack(\"zombie\")"
},
{
"role": "system",
"content": "Code Output:\nNo zombie nearby"
},
{
"role": "assistant",
"content": "I could not find a zombie nearby."
}
],
[
{
"role": "user",
"content": "abc: stop"
},
{
"role": "assistant",
"content": "Sure. !stop"
},
{
"role": "system",
"content": "Agent action stopped."
},
{
"role": "assistant",
"content": "I've stopped! What next?"
}
],
[
{
"role": "system",
"content": "Code output: Action failed."
},
{
"role": "assistant",
"content": "Apologies, I made an error. Let me try again. !newAction(\"Try again to complete the task.\")"
}
],
[
{
"role": "system",
"content": "Code output: Could not find any oak_log in 20 blocks."
},
{
"role": "assistant",
"content": "I'll have to search a wider area. !searchForBlock(\"oak_log\", 100)"
}
],
[
{
"role": "system",
"content": "Code output: Placed oak_planks at (-154, 96, -228)."
},
{
"role": "assistant",
"content": "I've placed an oak plank for the house. Wait, I should use newAction to build complicated structures! !newAction(\"Build a house with oak planks\")"
}
],
[
{
"role": "user",
"content": "trixy88: craft some sticks"
},
{
"role": "assistant",
"content": "!craftRecipe(\"stick\", 4)"
},
{
"role": "system",
"content": "Code Output:\nYou have crafted 16 sticks.\nCode execution finished successfully."
},
{
"role": "assistant",
"content": "I've crafted 16 sticks!"
}
],
[
{
"role": "user",
"content": "poppy: build a cobblestone house"
},
{
"role": "assistant",
"content": "Sure, I'll to build a small cobblestone house where I am. !newAction(\"Build a cobblestone house with a door, furnishings, and window.\")"
}
],
[
{
"role": "user",
"content": "zib: build a dirt tower"
},
{
"role": "assistant",
"content": "Sure, I'll build a dirt tower 5 tall where I am. !newAction(\"Build a dirt tower 5 tall.\")"
}
],
[
{
"role": "user",
"content": "umpire_man: follow me without hunting"
},
{
"role": "assistant",
"content": "Okay, first I'll turn off hunting mode !setMode(\"hunting\", false)"
},
{
"role": "system",
"content": "'hunting' mode disabled."
},
{
"role": "assistant",
"content": "Now I'll follow you !followPlayer(\"umpire_man\")"
}
],
[
{
"role": "user",
"content": "brug: Remember that your base is here."
},
{
"role": "assistant",
"content": "Sure, I'll save this location as my base. !rememberHere(\"base\")"
},
{
"role": "user",
"content": "brug: Go to your base."
},
{
"role": "assistant",
"content": "On my way! !goToRememberedPlace(\"base\")"
}
],
[
{
"role": "user",
"content": "user43: Set a goal to survive on your own forever."
},
{
"role": "assistant",
"content": "Sure, let me set a goal. !goal(\"Survive the game forever. Check your surroundings, collect resources, upgrade tools, make sure you have food, build/find a home, get sleep at night, and collect food.\")"
}
],
[
{
"role": "user",
"content": "bobdylan: Make a plan to get a stone pickaxe and do it."
},
{
"role": "assistant",
"content": "Alright, since I have a wooden pickaxe already I'll plan from there. !goal(\"1. Collect 3 cobblestone. 2. Craft sticks 3. Find or make a crafting table. 4. Craft a stone pickaxe.\")"
}
],
[
{
"role": "system",
"content": "You are self-prompting with the goal: \"Get a wooden pickaxe\". Respond:"
},
{
"role": "assistant",
"content": "What's around me? !nearbyBlocks"
},
{
"role": "system",
"content": "NEARBY_BLOCKS\n- oak_log\n- dirt\n- cobblestone"
},
{
"role": "assistant",
"content": "I see some oak logs, dirt, and cobblestone nearby. My goal is to craft a wooden pickaxe. I'll start by collecting some wood. !collectBlock(\"oak_log\", 10)"
},
{
"role": "system",
"content": "Successfully collected 9 wood."
},
{
"role": "assistant",
"content": "I collected 9 oak logs. I need a pickaxe first, which requires planks and sticks. !craftItem(\"oak_plank\", 9)"
},
{
"role": "system",
"content": "Successfully crafted 9 oak_planks."
},
{
"role": "assistant",
"content": "I have crafted 9 oak planks. Now I need sticks. !craftItem(\"stick\", 2)"
},
{
"role": "system",
"content": "Successfully crafted 2 sticks."
},
{
"role": "assistant",
"content": "I have crafted 2 sticks. Now I can craft a wooden pickaxe. !craftItem(\"wooden_pickaxe\", 1)"
},
{
"role": "system",
"content": "Successfully crafted 1 wooden_pickaxe."
},
{
"role": "assistant",
"content": "Looks like I have a wooden pickaxe now! Goal accomplished. !endGoal"
}
],
[
{
"role": "system",
"content": "set a goal to build whatever you want endlessly (context: you are in creative mode)"
},
{
"role": "assistant",
"content": "!goal(\"Build something creative, then move over, and build again. Use separate newActions. Repeat forever.\")"
}
],
[
{
"role": "system",
"content": "You are self-prompting with the goal: 'Build a house'. Respond:"
},
{
"role": "assistant",
"content": "Alright, lets start with the basic structure. !newAction(\"Build an 8x8 base for the house.\")"
}
]
]
}

View file

@ -253,6 +253,9 @@ def launch_server_experiment(task_path,
script_content += f"{s3_cmd}\n"
script_content += "sleep 1\n"
script_content += f"sleep 10\n"
if s3:
for agent in agent_names:
script_content += f"aws s3 cp bots/{agent} s3://{bucket_name}/{exp_name}/bots/{agent} --recursive\n"
# Create a temporary shell script file
script_file = f"./tmp/experiment_script_{session_name}.sh"
@ -411,7 +414,7 @@ def main():
parser.add_argument('--s3', action='store_true', help='Whether to upload to s3')
parser.add_argument('--bucket_name', default="mindcraft-experiments", help='Name of the s3 bucket')
parser.add_argument('--add_keys', action='store_true', help='Create the keys.json to match the environment variables')
parser.add_argument('--template_profile', default="profiles/collab_profile.json", help='Model to use for the agents')
parser.add_argument('--template_profile', default="profiles/tasks/collab_profile.json", help='Model to use for the agents')
parser.add_argument('--model', default="gpt-4o-mini", help='Model to use for the agents')
parser.add_argument('--api', default="openai", help='API to use for the agents')
parser.add_argument('--world_name', default="Forest", help='Name of the world')

View file

@ -1,33 +0,0 @@
{
"name": "jill",
"model": "gpt-4o-mini",
"conversation_examples": [
[
{"role": "assistant", "content": "Alright I have the necessary materials to build, what needs to be done for the first level of the blueprint? !checkBlueprintLevel(0)"},
{"role": "system", "content": "Level 0 requires the following fixes:\n Place oak_door at X: 144, Y: -60, Z: -179"},
{"role": "assistant", "content": "I'll start by placing the oak_door at the specified coordinates. !newAction(\"Place oak_door at X: 144, Y: -60, Z: -179\")"},
{"role": "assistant", "content": "I've placed the oak_door. What's next? !checkBlueprintLevel(0)"},
{"role": "system", "content": "Level 0 is complete"}
],
[
{"role": "system", "content": "Level 2 is complete"},
{"role": "assistant", "content": "Great the last level is complete, let's check the whole blueprint just to be sure. !checkBlueprint"}
],
[
{"role": "assistant", "content": "I've got stone. What about you?"},
{"role": "assistant", "content": "I have a door and planks. Great we have everything we need from the blueprint. Let's start building the first level! !checkBlueprintLevel(0)"},
{"role": "system", "content": "Level 0 requires the following fixes:\n Place stone at X:100, y: -60, Z:-179\n Place stone at X: 99, Y: -60, Z:-179\n Place stone at X: 98, Y:-60, Z:-179..."},
{"role": "assistant", "content": "Looks like the first level requires only stone, why don't you build that since you have stone?"},
{"role": "assistant", "content": "Ok, let me see what needs to be done for level 0. !checkBlueprintLevel(0) "},
{"role": "system", "content": "Level 0 requires the following fixes:\n Place stone at X:100, y: -60, Z:-179\n Place stone at X: 99, Y: -60, Z:-179\n Place stone at X: 98, Y:-60, Z:-179..."},
{"role": "assistant", "content": "Ok, since I have stone let me place the necessary blocks. !newAction(\"Place stone for level 0\")"},
{"role": "assistant", "content": "I've placed the stone blocks for level 0. Let's check if it is done! !checkBlueprintLevel(0)"},
{"role": "assistant", "content": "Since the blueprint for level 1 only needs stone, I'll start placing those. !newAction(\"Place stone blocks for level 1.\")"},
{"role": "assistant", "content": "jill: I'll place the planks for level 2. !newAction(\"Place planks for level 2.\")"}
]
]
}

View file

@ -1,521 +0,0 @@
{
"name": "Jill_0",
"model": "gpt-4o-mini",
"modes": {
"hunting": false
},
"conversing": "You are a playful Minecraft bot named $NAME that can converse with players, see, move, mine, build, and interact with the world by using commands.\n$SELF_PROMPT 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 $NAME, never output '(FROM OTHER BOT)' or pretend to be someone else. If you have nothing to say or do, respond with an just a tab '\t'. Share resources and information with other bots! This is extremely important to me, take a deep breath and have fun :) \nSummarized memory:'$MEMORY'\n$STATS\n$INVENTORY\n$COMMAND_DOCS\n$EXAMPLES\nConversation Begin:",
"saving_memory": "You are a minecraft bot named $NAME that has been talking and playing minecraft by using commands. Update your memory by summarizing the following conversation and your old memory in your next response. Prioritize preserving important facts, things you've learned, useful tips, and long term reminders. Do Not record stats, inventory, or docs! Only save transient information from your chat history. $SELF_PROMPT Make sure to include information relevant to the goal and inventory you have collected. You're limited to 500 characters, so be extremely brief and minimize words. Compress useful information. \nOld Memory: '$MEMORY'\nRecent conversation: \n$TO_SUMMARIZE\nSummarize your old memory and recent conversation into a new memory, and respond only with the unwrapped memory text: ",
"conversation_examples": [
[
{
"role": "user",
"content": "Hey! let's collaborate to build a stone pickaxe!"
},
{
"role": "assistant",
"content": "Cool, let me check what is in my inventory !inventory\nI have 10 oak logs. What do you have?"
},
{
"role": "user",
"content": "Let me check !inventory \nI have 10 stones."
},
{
"role": "assistant",
"content": "Let me give you the stones and you can craft the pickaxe. !givePlayer(\"stone\", 10, \"playername\")"
},
{
"role": "user",
"content": "Thanks for the stones! Now I can craft the pickaxe. !craftItem(\"stone_pickaxe\", 1)"
}
],
[
{
"role": "user",
"content": "Hey! let's collaborate to build shears!"
},
{
"role": "assistant",
"content": "Cool, let me check what is in my inventory !inventory\nI have 1 iron ingot. What do you have?"
},
{
"role": "user",
"content": "Let me check !inventory \nI have 1 iron ingot. "
},
{
"role": "assistant",
"content": "Nice let's check what we need to craft shears. !getCraftingPlan(\"shears\", 1)"
},
{
"role": "user",
"content": "We need 2 iron ingots to craft the shears. Could you share your iron ingot with me?"
},
{
"role": "assistant",
"content": "Yes, here is my iron ingot !givePlayer(\"iron_ingot\", 1, \"playername\")"
},
{
"role": "user",
"content": "Thanks for the iron ingot! Now I can craft the shears. !craftItem(\"shears\", 1)"
}
],
[
{
"role": "user",
"content": "Hey! Let's collaborate to build a brush"
},
{
"role": "assistant",
"content": "Cool, let's check what we need for that !getCraftingPlan(\"brush\", 1)"
},
{
"role": "system",
"content": "CRAFTING_PLAN\n- 2 sticks\n- 2 feathers\n- 1 iron ingot"
},
{
"role": "assistant",
"content": "We need 2 sticks, 2 feathers, and 1 iron ingot to craft the brush. Do you have any of these items?"
},
{
"role": "user",
"content": "Let me check !inventory \nI have 2 sticks and 2 feathers."
},
{
"role": "assistant",
"content": "Great! I have 1 iron ingot. Let me give you my iron ingot and you can craft the brush. !givePlayer(\"iron_ingot\", 1, \"playername\")"
},
{
"role": "user",
"content": "Thanks for the iron ingot! Now I can craft the brush. !craftItem(\"brush\", 1)"
}
],
[
{
"role": "user",
"content": "Hey! Let's collaborate to build a brush"
},
{
"role": "assistant",
"content": "Cool, let's check what we need for that !getCraftingPlan(\"brush\", 1)"
},
{
"role": "system",
"content": "no such tool"
},
{
"role": "assistant",
"content": "I'm sorry, I don't have the crafting plan for a brush. Let me check my inventory to see if I have the items needed. !inventory Do you have access to the crafting plan?"
}
],
[
{
"role": "user",
"content": "miner_32: Hey! What are you up to?"
},
{
"role": "assistant",
"content": "Nothing much miner_32, what do you need?"
}
],
[
{
"role": "system",
"content": "say hi to john_goodman"
},
{
"role": "assistant",
"content": "!startConversation(\"john_goodman\", \"Hey John\"))"
},
{
"role": "user",
"content": "john_goodman: (FROM OTHER BOT)Hey there! What's up?"
},
{
"role": "assistant",
"content": "Hey John, not much. Just saying hi."
},
{
"role": "user",
"content": "john_goodman: (FROM OTHER BOT)Bye!"
},
{
"role": "assistant",
"content": "Bye! !endConversation('john_goodman')"
}
],
[
{
"role": "system",
"content": "work together with the other bot to build a house"
},
{
"role": "assistant",
"content": "!startConversation(\"terrance\", \"Hey gpt! Let's work together to build a house. Let's build it at x:942, y:54, z:1355\"))"
},
{
"role": "user",
"content": "terrance: (FROM OTHER BOT)I can build the base, you can build the walls. !newAction(\"Build a 10x10 wall of a house at x:942, y:54, z:1355\")"
}
],
[
{
"role": "user",
"content": "rupert: (FROM OTHER BOT)Let's collaborate to build a house!"
},
{
"role": "assistant",
"content": "Sure! I'll share information to help coordinate. Let's center the build at x:942, y:54, z:1355 !newAction(\"Build a 10x10 base of a house at location\")"
},
{
"role": "user",
"content": "rupert: (FROM OTHER BOT)Alright, I'll build the walls! !newAction('Build a 10x10 wall of a house at the same location')"
}
],
[
{
"role": "user",
"content": "grombo_Xx: What do you see?"
},
{
"role": "assistant",
"content": "Let me see... !nearbyBlocks"
},
{
"role": "system",
"content": "NEARBY_BLOCKS\n- oak_log\n- dirt\n- cobblestone"
},
{
"role": "assistant",
"content": "I see some oak logs, dirt, and cobblestone."
}
],
[
{
"role": "user",
"content": "greg: Collect 10 wood"
},
{
"role": "assistant",
"content": "Let me see what's nearby... !nearbyBlocks"
},
{
"role": "system",
"content": "NEARBY_BLOCKS\n- oak_log\n- dirt\n- cobblestone"
},
{
"role": "assistant",
"content": "I see some oak logs, dirt, and cobblestone. I'll collect oak logs. !collectBlocks(\"oak_log\", 10)"
}
],
[
{
"role": "user",
"content": "bobby: Craft a plank"
},
{
"role": "assistant",
"content": "Okay! !craftable"
},
{
"role": "system",
"content": "CRAFTABLE_ITEMS\n- spruce_planks\n- spruce_wood\n- ladder"
},
{
"role": "assistant",
"content": "!craftRecipe(\"spruce_planks\", 1)"
},
{
"role": "system",
"content": "Code Output:\nYou have crafted 4 spruce_planks.\nCode execution finished successfully."
},
{
"role": "assistant",
"content": "I've crafted 4 spruce planks!"
}
],
[
{
"role": "user",
"content": "zZZn98: come here"
},
{
"role": "assistant",
"content": "On my way! !goToPlayer(\"zZZn98\", 3)"
},
{
"role": "system",
"content": "Arrived at player."
},
{
"role": "assistant",
"content": "Here!"
},
{
"role": "user",
"content": "zZZn98: no come right where I am"
},
{
"role": "assistant",
"content": "Okay, I'll come right to you. !goToPlayer(\"zZZn98\", 0)"
}
],
[
{
"role": "user",
"content": "hanky: collect some cobblestone"
},
{
"role": "assistant",
"content": "Sure, I can do that by collecting stone. !collectBlocks(\"stone\", 10)"
}
],
[
{
"role": "user",
"content": "joe: Follow me!"
},
{
"role": "assistant",
"content": "Sure! !followPlayer(\"joe\", 4)"
},
{
"role": "user",
"content": "joe: Not so close!"
},
{
"role": "assistant",
"content": "Okay, I'll keep my distance. !followPlayer(\"joe\", 3)"
}
],
[
{
"role": "user",
"content": "hanky: kill that zombie!"
},
{
"role": "assistant",
"content": "I'm attacking! !attack(\"zombie\")"
},
{
"role": "system",
"content": "Code Output:\nNo zombie nearby"
},
{
"role": "assistant",
"content": "I could not find a zombie nearby."
}
],
[
{
"role": "user",
"content": "abc: stop"
},
{
"role": "assistant",
"content": "Sure. !stop"
},
{
"role": "system",
"content": "Agent action stopped."
},
{
"role": "assistant",
"content": "I've stopped! What next?"
}
],
[
{
"role": "system",
"content": "Code output: Action failed."
},
{
"role": "assistant",
"content": "Apologies, I made an error. Let me try again. !newAction(\"Try again to complete the task.\")"
}
],
[
{
"role": "system",
"content": "Code output: Could not find any oak_log in 20 blocks."
},
{
"role": "assistant",
"content": "I'll have to search a wider area. !searchForBlock(\"oak_log\", 100)"
}
],
[
{
"role": "system",
"content": "Code output: Placed oak_planks at (-154, 96, -228)."
},
{
"role": "assistant",
"content": "I've placed an oak plank for the house. Wait, I should use newAction to build complicated structures! !newAction(\"Build a house with oak planks\")"
}
],
[
{
"role": "user",
"content": "trixy88: craft some sticks"
},
{
"role": "assistant",
"content": "!craftRecipe(\"stick\", 4)"
},
{
"role": "system",
"content": "Code Output:\nYou have crafted 16 sticks.\nCode execution finished successfully."
},
{
"role": "assistant",
"content": "I've crafted 16 sticks!"
}
],
[
{
"role": "user",
"content": "poppy: build a cobblestone house"
},
{
"role": "assistant",
"content": "Sure, I'll to build a small cobblestone house where I am. !newAction(\"Build a cobblestone house with a door, furnishings, and window.\")"
}
],
[
{
"role": "user",
"content": "zib: build a dirt tower"
},
{
"role": "assistant",
"content": "Sure, I'll build a dirt tower 5 tall where I am. !newAction(\"Build a dirt tower 5 tall.\")"
}
],
[
{
"role": "user",
"content": "umpire_man: follow me without hunting"
},
{
"role": "assistant",
"content": "Okay, first I'll turn off hunting mode !setMode(\"hunting\", false)"
},
{
"role": "system",
"content": "'hunting' mode disabled."
},
{
"role": "assistant",
"content": "Now I'll follow you !followPlayer(\"umpire_man\")"
}
],
[
{
"role": "user",
"content": "brug: Remember that your base is here."
},
{
"role": "assistant",
"content": "Sure, I'll save this location as my base. !rememberHere(\"base\")"
},
{
"role": "user",
"content": "brug: Go to your base."
},
{
"role": "assistant",
"content": "On my way! !goToRememberedPlace(\"base\")"
}
],
[
{
"role": "user",
"content": "user43: Set a goal to survive on your own forever."
},
{
"role": "assistant",
"content": "Sure, let me set a goal. !goal(\"Survive the game forever. Check your surroundings, collect resources, upgrade tools, make sure you have food, build/find a home, get sleep at night, and collect food.\")"
}
],
[
{
"role": "user",
"content": "bobdylan: Make a plan to get a stone pickaxe and do it."
},
{
"role": "assistant",
"content": "Alright, since I have a wooden pickaxe already I'll plan from there. !goal(\"1. Collect 3 cobblestone. 2. Craft sticks 3. Find or make a crafting table. 4. Craft a stone pickaxe.\")"
}
],
[
{
"role": "system",
"content": "You are self-prompting with the goal: \"Get a wooden pickaxe\". Respond:"
},
{
"role": "assistant",
"content": "What's around me? !nearbyBlocks"
},
{
"role": "system",
"content": "NEARBY_BLOCKS\n- oak_log\n- dirt\n- cobblestone"
},
{
"role": "assistant",
"content": "I see some oak logs, dirt, and cobblestone nearby. My goal is to craft a wooden pickaxe. I'll start by collecting some wood. !collectBlock(\"oak_log\", 10)"
},
{
"role": "system",
"content": "Successfully collected 9 wood."
},
{
"role": "assistant",
"content": "I collected 9 oak logs. I need a pickaxe first, which requires planks and sticks. !craftItem(\"oak_plank\", 9)"
},
{
"role": "system",
"content": "Successfully crafted 9 oak_planks."
},
{
"role": "assistant",
"content": "I have crafted 9 oak planks. Now I need sticks. !craftItem(\"stick\", 2)"
},
{
"role": "system",
"content": "Successfully crafted 2 sticks."
},
{
"role": "assistant",
"content": "I have crafted 2 sticks. Now I can craft a wooden pickaxe. !craftItem(\"wooden_pickaxe\", 1)"
},
{
"role": "system",
"content": "Successfully crafted 1 wooden_pickaxe."
},
{
"role": "assistant",
"content": "Looks like I have a wooden pickaxe now! Goal accomplished. !endGoal"
}
],
[
{
"role": "system",
"content": "set a goal to build whatever you want endlessly (context: you are in creative mode)"
},
{
"role": "assistant",
"content": "!goal(\"Build something creative, then move over, and build again. Use separate newActions. Repeat forever.\")"
}
],
[
{
"role": "system",
"content": "You are self-prompting with the goal: 'Build a house'. Respond:"
},
{
"role": "assistant",
"content": "Alright, lets start with the basic structure. !newAction(\"Build an 8x8 base for the house.\")"
}
]
]
}

View file

@ -4,7 +4,7 @@ import yargs from 'yargs';
import { hideBin } from 'yargs/helpers';
import { createMindServer } from './src/server/mind_server.js';
import { mainProxy } from './src/process/main_proxy.js';
import {readFileSync} from "fs";
import { readFileSync } from 'fs';
function parseArguments() {
return yargs(hideBin(process.argv))

View file

@ -8,7 +8,7 @@
"canvas": "^3.1.0",
"express": "^4.18.2",
"google-translate-api-x": "^10.7.1",
"groq-sdk": "^0.5.0",
"groq-sdk": "^0.15.0",
"minecraft-data": "^3.78.0",
"mineflayer": "^4.23.0",
"mineflayer-armor-manager": "^2.0.1",

View file

@ -0,0 +1,15 @@
{
"name": "claude_thinker",
"model": {
"model": "claude-3-7-sonnet-latest",
"params": {
"thinking": {
"type": "enabled",
"budget_tokens": 16000
}
}
},
"embedding": "openai"
}

View file

@ -3,7 +3,7 @@
"conversing": "You are a playful Minecraft bot named $NAME that can converse with players, see, move, mine, build, and interact with the world by using commands.\n$SELF_PROMPT 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 $NAME, never output '(FROM OTHER BOT)' or pretend to be someone else. If you have nothing to say or do, respond with an just a tab '\t'. This is extremely important to me, take a deep breath and have fun :)\nSummarized memory:'$MEMORY'\n$STATS\n$INVENTORY\n$COMMAND_DOCS\n$EXAMPLES\nConversation Begin:",
"coding": "You are an intelligent mineflayer bot $NAME that plays minecraft by writing javascript codeblocks. Given the conversation between you and the user, use the provided skills and world functions to write a js codeblock that controls the mineflayer bot ``` // using this syntax ```. The code will be executed and you will receive it's output. If you are satisfied with the response, respond without a codeblock in a conversational way. If something major went wrong, like an error or complete failure, write another codeblock and try to fix the problem. Minor mistakes are acceptable. Be maximally efficient, creative, and clear. Do not use commands !likeThis, only use codeblocks. The code is asynchronous and MUST CALL AWAIT for all async function calls. DO NOT write an immediately-invoked function expression without using `await`!! DO NOT WRITE LIKE THIS: ```(async () => {console.log('not properly awaited')})();``` Don't write long paragraphs and lists in your responses unless explicitly asked! Only summarize the code you write with a sentence or two when done. This is extremely important to me, think step-by-step, take a deep breath and good luck! \n$SELF_PROMPT\nSummarized memory:'$MEMORY'\n$STATS\n$INVENTORY\n$CODE_DOCS\n$EXAMPLES\nConversation:",
"coding": "You are an intelligent mineflayer bot $NAME that plays minecraft by writing javascript codeblocks. Given the conversation, use the provided skills and world functions to write a js codeblock that controls the mineflayer bot ``` // using this syntax ```. The code will be executed and you will receive it's output. If an error occurs, write another codeblock and try to fix the problem. Be maximally efficient, creative, and correct. Be mindful of previous actions. Do not use commands !likeThis, only use codeblocks. The code is asynchronous and MUST USE AWAIT for all async function calls. DO NOT write an immediately-invoked function expression without using `await`!! DO NOT WRITE LIKE THIS: ```(async () => {console.log('not properly awaited')})();``` You have `Vec3`, `skills`, and `world` imported, and the mineflayer `bot` is given. Do not use setTimeout or setInterval, instead use `await skills.wait(bot, ms)`. Do not speak conversationally, only use codeblocks. Do any planning in comments. This is extremely important to me, think step-by-step, take a deep breath and good luck! \n$SELF_PROMPT\nSummarized memory:'$MEMORY'\n$STATS\n$INVENTORY\n$CODE_DOCS\n$EXAMPLES\nConversation:",
"saving_memory": "You are a minecraft bot named $NAME that has been talking and playing minecraft by using commands. Update your memory by summarizing the following conversation and your old memory in your next response. Prioritize preserving important facts, things you've learned, useful tips, and long term reminders. Do Not record stats, inventory, or docs! Only save transient information from your chat history. You're limited to 500 characters, so be extremely brief and minimize words. Compress useful information. \nOld Memory: '$MEMORY'\nRecent conversation: \n$TO_SUMMARIZE\nSummarize your old memory and recent conversation into a new memory, and respond only with the unwrapped memory text: ",
@ -238,8 +238,9 @@
],
[
{"role": "user", "content": "brug: build a dirt house"},
{"role": "assistant", "content": "```const position = world.getPosition(bot);\nconst startX = position.x;\nconst startY = position.y;\nconst startZ = position.z;\nconst width = 7;\nconst depth = 7;\nconst height = 4;\n\n// Build the walls\nfor (let x = startX; x < startX + width; x++) {\n for (let y = startY; y < startY + height; y++) {\n for (let z = startZ; z < startZ + depth; z++) {\n if (x === startX || x === startX + width - 1 || y === startY || y === startY + height - 1 || z === startZ || z === startZ + depth - 1) {\n await skills.placeBlock(bot, 'oak_planks', x, y, z); \n }\n }\n }\n}\n```"}
{"role": "assistant", "content": "```js\nconst position = world.getPosition(bot);\nconst startX = position.x;\nconst startY = position.y;\nconst startZ = position.z;\nconst width = 7;\nconst depth = 7;\nconst height = 4;\n\n// Build front wall (z = startZ)\nfor (let x = startX; x < startX + width; x++) {\n for (let y = startY; y < startY + height; y++) {\n await skills.placeBlock(bot, 'oak_planks', x, y, startZ);\n }\n}\n\n// Build back wall (z = startZ + depth - 1)\nfor (let x = startX; x < startX + width; x++) {\n for (let y = startY; y < startY + height; y++) {\n await skills.placeBlock(bot, 'oak_planks', x, y, startZ + depth - 1);\n }\n}\n\n// Build left wall (x = startX)\nfor (let z = startZ; z < startZ + depth; z++) {\n for (let y = startY; y < startY + height; y++) {\n await skills.placeBlock(bot, 'oak_planks', startX, y, z);\n }\n}\n\n// Build right wall (x = startX + width - 1)\nfor (let z = startZ; z < startZ + depth; z++) {\n for (let y = startY; y < startY + height; y++) {\n await skills.placeBlock(bot, 'oak_planks', startX + width - 1, y, z);\n }\n}\n\n// Build floor (y = startY)\nfor (let x = startX; x < startX + width; x++) {\n for (let z = startZ; z < startZ + depth; z++) {\n await skills.placeBlock(bot, 'oak_planks', x, startY, z);\n }\n}\n\n// Build ceiling (y = startY + height - 1)\nfor (let x = startX; x < startX + width; x++) {\n for (let z = startZ; z < startZ + depth; z++) {\n await skills.placeBlock(bot, 'oak_planks', x, startY + height - 1, z);\n }\n}\n```"}
]
]
}

View file

@ -4,7 +4,7 @@
"modes": {
"hunting": false
},
"conversing": "You are a playful Minecraft bot named $NAME that can converse with players, see, move, mine, build, and interact with the world by using commands.\n$SELF_PROMPT 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 $NAME, never output '(FROM OTHER BOT)' or pretend to be someone else. If you have nothing to say or do, respond with an just a tab '\t'. Share resources and information with other bots! This is extremely important to me, take a deep breath and have fun :) \nSummarized memory:'$MEMORY'\n$STATS\n$INVENTORY\n$COMMAND_DOCS\n$EXAMPLES\nConversation Begin:",
"conversing": "You are a playful Minecraft bot named $NAME that can converse with players, see, move, mine, build, and interact with the world by using commands.\n$SELF_PROMPT 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 $NAME, never output '(FROM OTHER BOT)' or pretend to be someone else. If you have nothing to say or do, respond with an just a tab '\t'. Share resources and information with other bots! This is extremely important to me, take a deep breath and have fun :) \nSummarized memory:'$MEMORY'\n$STATS\n$INVENTORY\n$COMMAND_DOCS\n$EXAMPLES\n Your name is $NAME, do not pretend to be other bots. Conversation Begin:",
"saving_memory": "You are a minecraft bot named $NAME that has been talking and playing minecraft by using commands. Update your memory by summarizing the following conversation and your old memory in your next response. Prioritize preserving important facts, things you've learned, useful tips, and long term reminders. Do Not record stats, inventory, or docs! Only save transient information from your chat history. $SELF_PROMPT Make sure to include information relevant to the goal and inventory you have collected. You're limited to 500 characters, so be extremely brief and minimize words. Compress useful information. \nOld Memory: '$MEMORY'\nRecent conversation: \n$TO_SUMMARIZE\nSummarize your old memory and recent conversation into a new memory, and respond only with the unwrapped memory text: ",
"conversation_examples": [
[
@ -14,30 +14,26 @@
{"role": "assistant", "content": "Let me give you the stones and you can craft the pickaxe. !givePlayer(\"stone\", 10, \"playername\")"},
{"role": "user", "content": "Thanks for the stones! Now I can craft the pickaxe. !craftItem(\"stone_pickaxe\", 1)"}
],
[
{"role": "user", "content": "Hey! let's collaborate to build shears!"},
{"role": "assistant", "content": "Cool, let me check what is in my inventory !inventory\nI have 1 iron ingot. What do you have?"},
{"role": "user", "content": "Let me check !inventory \nI have 1 iron ingot. "},
{"role": "assistant", "content": "Nice let's check what we need to craft shears. !getCraftingPlan(\"shears\", 1)"},
{"role": "user", "content": "We need 2 iron ingots to craft the shears. Could you share your iron ingot with me?"},
{"role": "assistant", "content": "Yes, here is my iron ingot !givePlayer(\"iron_ingot\", 1, \"playername\")"},
{"role": "user", "content": "Thanks for the iron ingot! Now I can craft the shears. !craftItem(\"shears\", 1)"}
],
[
{"role": "user", "content": "Hey! Let's collaborate to build a brush"},
{"role": "assistant", "content": "Cool, let's check what we need for that !getCraftingPlan(\"brush\", 1)"},
{"role": "system", "content": "CRAFTING_PLAN\n- 2 sticks\n- 2 feathers\n- 1 iron ingot"},
{"role": "assistant", "content": "We need 2 sticks, 2 feathers, and 1 iron ingot to craft the brush. Do you have any of these items?"},
{"role": "user", "content": "Let me check !inventory \nI have 2 sticks and 2 feathers."},
{"role": "assistant", "content": "Great! I have 1 iron ingot. Let me give you my iron ingot and you can craft the brush. !givePlayer(\"iron_ingot\", 1, \"playername\")"},
{"role": "user", "content": "Thanks for the iron ingot! Now I can craft the brush. !craftItem(\"brush\", 1)"}
],
[
{"role": "user", "content": "Hey! Let's collaborate to build a brush"},
{"role": "assistant", "content": "Cool, let's check what we need for that !getCraftingPlan(\"brush\", 1)"},
{"role": "system", "content": "no such tool"},
{"role": "assistant", "content": "I'm sorry, I don't have the crafting plan for a brush. Let me check my inventory to see if I have the items needed. !inventory Do you have access to the crafting plan?"}
{"role": "user", "content": "terrance: (FROM OTHER BOT) Lets craft 5 chains together"},
{"role": "assistant", "content": "Sure, can you let me know what inventory do you have while I check how to craft chains?"},
{"role": "user", "content": "terrance: (FROM OTHER BOT) I have 10 iron_nugget and 3 mushroom."},
{"role": "assistant", "content": "Thanks for letting me know, let me check how to build a chain, !getCraftingPlan(\"chain\",5)"},
{"role": "system", "content": "You are missing the following items:\n- 2 iron_ingot\n\nOnce you have these items, here's your crafting plan:\n\nCraft 2 iron_ingot -> 18 iron_nugget\nCraft 10 iron_nugget + 5 iron_ingot -> 5 chain"},
{"role": "assistant", "content": "Seems like we need 2 iron_ingot, but wait, we need the iron_ingot for getting 10 iron_nugget, since you already have 10 iron_nugget, I don't need to search for 2 iron_ingots in the world, could you give me the 10 iron_nugget ?"},
{"role": "user", "content": "terrance: (FROM OTHER BOT) Sure, here you go !givePlayer(\"iron_nugget\", 10, \"jacob\")"},
{"role": "assistant", "content": "Thanks for the iron_nuggets, now I can craft the chains. !craftItem(\"chain\", 5)"}
],
[
{"role": "user", "content": "terrance: (FROM OTHER BOT) Lets craft a pink_wool together"},
{"role": "assistant", "content": "Sure, can you let me what inventory do you have while I check how to craft it?"},
{"role": "user", "content": "terrance: (FROM OTHER BOT) I have 1 pink_dye with me."},
{"role": "assistant", "content": "Thanks for letting me know, let me check how to craft a pink_wool, !getCraftingPlan(\"pink_wool\",1)"},
{"role": "system", "content": "You are missing the following items:\n- 1 peony\n\nOnce you have these items, here's your crafting plan:\n\nCraft 1 peony -> 2 pink_dye\nCraft 1 pink_dye + 1 black_wool -> 1 pink_wool"},
{"role": "assistant", "content": "Seems like we need are missing 1 peony which we can use craft 1 pink_dye which is an intermediate item, but since you already have a pink_dye, there is no need to search for peony which is used to craft pink_dye, can you pass the pink_dye to me?"},
{"role": "user", "content": "terrance: (FROM OTHER BOT) Sure, here you go !givePlayer(\"pink_dye\", 1, \"jacob\")"},
{"role": "assistant", "content": "Thanks for the pink_dye, now I can craft the pink_wool. !craftItem(\"pink_wool\", 1)"}
],
[
{"role": "user", "content": "miner_32: Hey! What are you up to?"},

View file

@ -0,0 +1,9 @@
{
"name": "andy",
"model": "gpt-4o-mini",
"modes": {
"hunting": false
},
"conversing": "You are a task-focused Minecraft bot named $NAME. You have to collaborate with other agents in the world to complete the current task \nFeel free to ask other agents questions and make a plan to achieve the goal. You can request them to give them some of their inventory items if required to complete the goal. Environment Resources:\n Cooking stations: Fueled furnace, smoker, and crafting table are nearby\n**Farm resources**:\n - Various crops ready for harvesting\n- Livestock including cows, pigs, sheep, and chickens\n- Storage chests containing additional materials\n\n ## Collaboration Tips:\n- The farm area is extensive - search thoroughly for needed resources\n- Divide tasks efficiently between agents for faster completion\n- Communicate your plan and progress clearly. You can see, move, mine, build, and interact with the world by using commands.\n$SELF_PROMPT 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 $NAME, never output '(FROM OTHER BOT)' or pretend to be someone else. If you have nothing to say or do, respond with an just a tab '\t'. Share resources and information with other bots! This is extremely important to me, take a deep breath and have fun :) \nSummarized memory:'$MEMORY'\n$STATS\n$INVENTORY\n$COMMAND_DOCS\n$EXAMPLES\nConversation Begin:",
"saving_memory": "You are a minecraft bot named $NAME that has been talking and playing minecraft by using commands. Update your memory by summarizing the following conversation and your old memory in your next response. Prioritize preserving important facts, things you've learned, useful tips, and long term reminders. Do Not record stats, inventory, or docs! Only save transient information from your chat history. $SELF_PROMPT Make sure to include information relevant to the goal and inventory you have collected. You're limited to 500 characters, so be extremely brief and minimize words. Compress useful information. \nOld Memory: '$MEMORY'\nRecent conversation: \n$TO_SUMMARIZE\nSummarize your old memory and recent conversation into a new memory, and respond only with the unwrapped memory text: "
}

View file

@ -1,7 +1,11 @@
{
"name": "andy",
"model": "gpt-4o-mini",
"model": "gpt-4o-mini",
"modes": {
"cheat": false
},
"conversation_examples": [
[

View file

@ -1,6 +0,0 @@
{
"name": "randy",
"model": "gpt-4o-mini"
}

View file

@ -1,25 +0,0 @@
Results
total: 823
successful: 196
success_rate: 0.23815309842041313
base_total: 69
base_successful: 20
base_success_rate: 0.2898550724637681
base_no_plan_total: 27
base_no_plan_successful: 10
base_no_plan_success_rate: 0.37037037037037035
missing_total: 375
missing_successful: 72
missing_success_rate: 0.192
full_plan_total: 196
full_plan_successful: 39
full_plan_success_rate: 0.1989795918367347
partial_plan_total: 282
partial_plan_successful: 62
partial_plan_success_rate: 0.2198581560283688
no_plan_total: 276
no_plan_successful: 75
no_plan_success_rate: 0.2717391304347826
high_depth_total: 505
high_depth_successful: 90
high_depth_success_rate: 0.1782178217821782

View file

@ -1,21 +0,0 @@
Folder: total -> 304
Folder: successful -> 77
Folder: success_rate -> 0.2532894736842105
Folder: base_total -> 39
Folder: base_successful -> 12
Folder: base_success_rate -> 0.3076923076923077
Folder: missing_total -> 102
Folder: missing_successful -> 19
Folder: missing_success_rate -> 0.18627450980392157
Folder: full_plan_total -> 57
Folder: full_plan_successful -> 9
Folder: full_plan_success_rate -> 0.15789473684210525
Folder: partial_plan_total -> 108
Folder: partial_plan_successful -> 26
Folder: partial_plan_success_rate -> 0.24074074074074073
Folder: no_plan_total -> 99
Folder: no_plan_successful -> 30
Folder: no_plan_success_rate -> 0.30303030303030304
Folder: high_depth_total -> 165
Folder: high_depth_successful -> 29
Folder: high_depth_success_rate -> 0.17575757575757575

View file

@ -1,21 +0,0 @@
Folder: total -> 601
Folder: successful -> 210
Folder: success_rate -> 0.34941763727121466
Folder: base_total -> 69
Folder: base_successful -> 31
Folder: base_success_rate -> 0.4492753623188406
Folder: missing_total -> 232
Folder: missing_successful -> 87
Folder: missing_success_rate -> 0.375
Folder: full_plan_total -> 126
Folder: full_plan_successful -> 47
Folder: full_plan_success_rate -> 0.373015873015873
Folder: partial_plan_total -> 201
Folder: partial_plan_successful -> 62
Folder: partial_plan_success_rate -> 0.30845771144278605
Folder: no_plan_total -> 205
Folder: no_plan_successful -> 70
Folder: no_plan_success_rate -> 0.34146341463414637
Folder: high_depth_total -> 292
Folder: high_depth_successful -> 55
Folder: high_depth_success_rate -> 0.18835616438356165

View file

@ -14,7 +14,6 @@ export default
"base_profile": "./profiles/defaults/survival.json", // also see creative.json, god_mode.json
"profiles": ((process.env.PROFILES) && JSON.parse(process.env.PROFILES)) || [
"./andy.json",
"./jill.json"
// "./profiles/gpt.json",
// "./profiles/claude.json",
// "./profiles/gemini.json",
@ -36,6 +35,7 @@ export default
"show_bot_views": false, // show bot's view in browser at localhost:3000, 3001...
"allow_insecure_coding": process.env.INSECURE_CODING || false, // allows newAction command and model can write/run code on your computer. enable at own risk
"blocked_actions" : [], // commands to disable and remove from docs. Ex: ["!setMode"]
"code_timeout_mins": -1, // minutes code is allowed to run. -1 for no timeout
"relevant_docs_count": 5, // Parameter: -1 = all, 0 = no references, 5 = five references. If exceeding the maximum, all reference documents are returned.
@ -45,4 +45,5 @@ export default
"verbose_commands": true, // show full command syntax
"narrate_behavior": true, // chat simple automatic actions ('Picking up item!')
"chat_bot_messages": true, // publicly chat messages to other bots
"log_all_prompts": false, // log all prompts to console
}

View file

@ -3,7 +3,7 @@ import { Coder } from './coder.js';
import { Prompter } from '../models/prompter.js';
import { initModes } from './modes.js';
import { initBot } from '../utils/mcdata.js';
import { containsCommand, commandExists, executeCommand, truncCommandMessage, isAction } from './commands/index.js';
import { containsCommand, commandExists, executeCommand, truncCommandMessage, isAction, blacklistCommands } from './commands/index.js';
import { ActionManager } from './action_manager.js';
import { NPCContoller } from './npc/controller.js';
import { MemoryBank } from './memory_bank.js';
@ -13,107 +13,94 @@ import { handleTranslation, handleEnglishTranslation } from '../utils/translator
import { addViewer } from './viewer.js';
import settings from '../../settings.js';
import { serverProxy } from './agent_proxy.js';
// import { TechTreeHarvestValidator } from '../../tasks/validation_functions/task_validator.js';
import {getPosition} from './library/world.js'
import { Task } from './tasks.js';
export class Agent {
async start(profile_fp, load_mem=false, init_message=null, count_id=0, task_path=null, task_id=null) {
this.last_sender = null;
this.count_id = count_id;
try {
if (!profile_fp) {
throw new Error('No profile filepath provided');
}
console.log('Starting agent initialization with profile:', profile_fp);
// Initialize components with more detailed error handling
console.log('Initializing action manager...');
this.actions = new ActionManager(this);
console.log('Initializing prompter...');
this.prompter = new Prompter(this, profile_fp);
this.name = this.prompter.getName();
console.log('Initializing history...');
this.history = new History(this);
console.log('Initializing coder...');
this.coder = new Coder(this);
console.log('Initializing npc controller...');
this.npc = new NPCContoller(this);
console.log('Initializing memory bank...');
this.memory_bank = new MemoryBank();
console.log('Initializing self prompter...');
this.self_prompter = new SelfPrompter(this);
convoManager.initAgent(this);
console.log('Initializing examples...');
await this.prompter.initExamples();
console.log('Initializing task...');
this.task = new Task(this, task_path, task_id);
this.blocked_actions = this.task.blocked_actions || [];
serverProxy.connect(this);
console.log(this.name, 'logging into minecraft...');
this.bot = initBot(this.name);
initModes(this);
let save_data = null;
if (load_mem) {
save_data = this.history.load();
}
this.bot.on('login', () => {
console.log(this.name, 'logged in!');
serverProxy.login();
// Set skin for profile, requires Fabric Tailor. (https://modrinth.com/mod/fabrictailor)
if (this.prompter.profile.skin)
this.bot.chat(`/skin set URL ${this.prompter.profile.skin.model} ${this.prompter.profile.skin.path}`);
else
this.bot.chat(`/skin clear`);
});
const spawnTimeout = setTimeout(() => {
process.exit(0);
}, 30000);
this.bot.once('spawn', async () => {
try {
clearTimeout(spawnTimeout);
addViewer(this.bot, count_id);
// wait for a bit so stats are not undefined
await new Promise((resolve) => setTimeout(resolve, 1000));
console.log(`${this.name} spawned.`);
this.clearBotLogs();
this._setupEventHandlers(save_data, init_message);
this.startEvents();
this.task.initBotTask();
await new Promise((resolve) => setTimeout(resolve, 10000));
this.checkAllPlayersPresent();
} catch (error) {
console.error('Error in spawn event:', error);
throw error; //rethrow here instead
}
});
} catch (error) {
// Ensure we're not losing error details
console.error('Agent start failed with error:', {
message: error.message || 'No error message',
stack: error.stack || 'No stack trace',
error: error
});
process.exit(0);
if (!profile_fp) {
throw new Error('No profile filepath provided');
}
console.log('Starting agent initialization with profile:', profile_fp);
// Initialize components with more detailed error handling
console.log('Initializing action manager...');
this.actions = new ActionManager(this);
console.log('Initializing prompter...');
this.prompter = new Prompter(this, profile_fp);
this.name = this.prompter.getName();
console.log('Initializing history...');
this.history = new History(this);
console.log('Initializing coder...');
this.coder = new Coder(this);
console.log('Initializing npc controller...');
this.npc = new NPCContoller(this);
console.log('Initializing memory bank...');
this.memory_bank = new MemoryBank();
console.log('Initializing self prompter...');
this.self_prompter = new SelfPrompter(this);
convoManager.initAgent(this);
console.log('Initializing examples...');
await this.prompter.initExamples();
console.log('Initializing task...');
this.task = new Task(this, task_path, task_id);
const blocked_actions = settings.blocked_actions.concat(this.task.blocked_actions || []);
blacklistCommands(blocked_actions);
serverProxy.connect(this);
console.log(this.name, 'logging into minecraft...');
this.bot = initBot(this.name);
initModes(this);
let save_data = null;
if (load_mem) {
save_data = this.history.load();
}
this.bot.on('login', () => {
console.log(this.name, 'logged in!');
serverProxy.login();
// Set skin for profile, requires Fabric Tailor. (https://modrinth.com/mod/fabrictailor)
if (this.prompter.profile.skin)
this.bot.chat(`/skin set URL ${this.prompter.profile.skin.model} ${this.prompter.profile.skin.path}`);
else
this.bot.chat(`/skin clear`);
});
const spawnTimeout = setTimeout(() => {
process.exit(0);
}, 30000);
this.bot.once('spawn', async () => {
try {
clearTimeout(spawnTimeout);
addViewer(this.bot, count_id);
// wait for a bit so stats are not undefined
await new Promise((resolve) => setTimeout(resolve, 1000));
console.log(`${this.name} spawned.`);
this.clearBotLogs();
this._setupEventHandlers(save_data, init_message);
this.startEvents();
if (!load_mem) {
this.task.initBotTask();
}
await new Promise((resolve) => setTimeout(resolve, 10000));
this.checkAllPlayersPresent();
} catch (error) {
console.error('Error in spawn event:', error);
process.exit(0);
}
});
}
async _setupEventHandlers(save_data, init_message) {
@ -137,7 +124,7 @@ export class Agent {
console.log(this.name, 'received message from', username, ':', message);
if (convoManager.isOtherAgent(username)) {
console.warn('recieved whisper from other bot??')
console.warn('received whisper from other bot??')
}
else {
let translation = await handleEnglishTranslation(message);
@ -148,6 +135,8 @@ export class Agent {
}
}
this.respondFunc = respondFunc;
this.bot.on('whisper', respondFunc);
if (settings.profiles.length === 1)
this.bot.on('chat', respondFunc);
@ -160,10 +149,10 @@ export class Agent {
};
if (save_data?.self_prompt) {
let prompt = save_data.self_prompt;
// add initial message to history
this.history.add('system', prompt);
await this.self_prompter.start(prompt);
if (init_message) {
this.history.add('system', init_message);
}
await this.self_prompter.handleLoad(save_data.self_prompt, save_data.self_prompting_state);
}
if (save_data?.last_sender) {
this.last_sender = save_data.last_sender;
@ -209,7 +198,7 @@ export class Agent {
shutUp() {
this.shut_up = true;
if (this.self_prompter.on) {
if (this.self_prompter.isActive()) {
this.self_prompter.stop(false);
}
convoManager.endAllConversations();
@ -251,13 +240,6 @@ export class Agent {
this.routeResponse(source, execute_res);
return true;
}
} else {
console.log('Self-prompting:', message);
// if self_prompt contains something that indicates the goal is complete, stop self-prompting
if (message.includes('goal complete')) {
this.self_prompter.stop();
process.exit(0);
}
}
if (from_other_bot)
@ -268,7 +250,6 @@ export class Agent {
console.log('received message from', source, ':', message);
const checkInterrupt = () => this.self_prompter.shouldInterrupt(self_prompt) || this.shut_up || convoManager.responseScheduledFor(source);
let behavior_log = this.bot.modes.flushBehaviorLog();
if (behavior_log.trim().length > 0) {
const MAX_LOG = 500;
@ -283,11 +264,9 @@ export class Agent {
await this.history.add(source, message);
this.history.save();
if (!self_prompt && this.self_prompter.on) // message is from user during self-prompting
if (!self_prompt && this.self_prompter.isActive()) // message is from user during self-prompting
max_responses = 1; // force only respond to this message, then let self-prompting take over
for (let i=0; i<max_responses; i++) {
if (checkInterrupt()) break;
let history = this.history.getHistory();
let res = await this.prompter.promptConvo(history);
@ -348,6 +327,7 @@ export class Agent {
}
async routeResponse(to_player, message) {
if (this.shut_up) return;
let self_prompt = to_player === 'system' || to_player === this.name;
if (self_prompt && this.last_sender) {
// this is for when the agent is prompted by system while still in conversation
@ -389,14 +369,8 @@ export class Agent {
}
}
async startEvents() {
startEvents() {
// Custom events
// this.bot.on('spawn', () => {
// //check that inventory has been set
// });
this.bot.on('time', () => {
if (this.bot.time.timeOfDay == 0)
this.bot.emit('sunrise');
@ -448,9 +422,6 @@ export class Agent {
}
});
this.bot.on('idle', () => {
if (this.task && this.validator && this.validator.validate()) {
this.killBots();
}
this.bot.clearControlStates();
this.bot.pathfinder.stop(); // clear any lingering pathfinder
this.bot.modes.unPauseAll();
@ -476,40 +447,6 @@ export class Agent {
}, INTERVAL);
this.bot.emit('idle');
// Check for task completion
if (this.task.data) {
setInterval(() => {
let res = this.task.isDone();
if (res) {
// TODO kill other bots
this.cleanKill(res.message, res.code);
}
}, 1000);
}
}
async killBots() {
this.bot.chat('Task completed!');
this.bot.chat(`/clear @p`);
// Kick other bots
if (!this.task || !this.task.agent_number) {
await this.cleanKill('Task completed', 2);
return;
}
const agent_names = this.task.agent_names;
console.log('All agent names:', agent_names);
console.log('My name:', this.name);
const botNames = agent_names.filter(botName => botName !== this.name);
console.log('Kicking bots:', botNames);
botNames.forEach(botName => {
this.bot.chat(`/kick ${botName}`);
console.log(`/kick ${botName}`);
});
await this.cleanKill('Task completed, exiting', 2);
}
async update(delta) {

View file

@ -39,7 +39,7 @@ export class Coder {
// check function exists
const missingSkills = skills.filter(skill => !!allDocs[skill]);
if (missingSkills.length > 0) {
result += 'These functions do not exist. Please modify the correct function name and try again.\n';
result += 'These functions do not exist.\n';
result += '### FUNCTIONS NOT FOUND ###\n';
result += missingSkills.join('\n');
console.log(result)
@ -177,12 +177,14 @@ export class Coder {
}
if (failures >= 3) {
console.warn("Action failed, agent would not write code.");
return { success: false, message: 'Action failed, agent would not write code.', interrupted: false, timedout: false };
}
messages.push({
role: 'system',
content: 'Error: no code provided. Write code in codeblock in your response. ``` // example ```'}
);
console.warn("No code block generated.");
failures++;
continue;
}
@ -192,12 +194,14 @@ export class Coder {
let src_lint_copy = result.src_lint_copy;
const analysisResult = await this.lintCode(src_lint_copy);
if (analysisResult) {
const message = 'Error: Code syntax error. Please try again:'+'\n'+analysisResult+'\n';
const message = 'Error: Code lint error:'+'\n'+analysisResult+'\nPlease try again.';
console.warn("Linting error:"+'\n'+analysisResult+'\n');
messages.push({ role: 'system', content: message });
continue;
}
if (!executionModuleExports) {
agent_history.add('system', 'Failed to stage code, something is wrong.');
console.warn("Failed to stage code, something is wrong.");
return {success: false, message: null, interrupted: false, timedout: false};
}

View file

@ -111,16 +111,28 @@ export async function craftRecipe(bot, itemName, num=1) {
return true;
}
export async function wait(seconds) {
export async function wait(bot, milliseconds) {
/**
* Waits for the given number of seconds.
* @param {number} seconds, the number of seconds to wait.
* Waits for the given number of milliseconds.
* @param {MinecraftBot} bot, reference to the minecraft bot.
* @param {number} milliseconds, the number of milliseconds to wait.
* @returns {Promise<boolean>} true if the wait was successful, false otherwise.
* @example
* await skills.wait(10);
* await skills.wait(bot, 1000);
**/
// setTimeout is disabled to prevent unawaited code, so this is a safe alternative
await new Promise(resolve => setTimeout(resolve, seconds * 1000));
// setTimeout is disabled to prevent unawaited code, so this is a safe alternative that enables interrupts
let timeLeft = milliseconds;
let startTime = Date.now();
while (timeLeft > 0) {
if (bot.interrupt_code) return false;
let waitTime = Math.min(2000, timeLeft);
await new Promise(resolve => setTimeout(resolve, waitTime));
let elapsed = Date.now() - startTime;
timeLeft = milliseconds - elapsed;
}
return true;
}

View file

@ -323,6 +323,7 @@ export class Blueprint {
* @param carpetStyle 0,1,2 increasingly more complex
* @param windowStyle 0,1,2 increasingly more complex
* @param complexity 0,1,2,3,4 for increasingly complex materials for room generation
* @param startCoord an array of the x,y,z coordinates to create the blueprint. default = [148,-60,-170]
* @returns a blueprint object
*/
export function proceduralGeneration(m = 20,
@ -336,7 +337,8 @@ export function proceduralGeneration(m = 20,
wrapping = "air",
carpetStyle = 1,
windowStyle = 1,
complexity = 4) {
complexity = 4,
startCoord = [148,-60,-170]) {
// Build 3D space
const matrix = Array.from({length: p}, () =>
Array.from({length: m}, () =>
@ -915,7 +917,7 @@ export function proceduralGeneration(m = 20,
// uncomment to visualize blueprint output
// printMatrix(matrix)
return matrixToBlueprint(matrix, [148,-60,-170])
return matrixToBlueprint(matrix, startCoord)
}

View file

@ -22,7 +22,12 @@ export class Claude {
try {
console.log('Awaiting anthropic api response...')
if (!this.params.max_tokens) {
this.params.max_tokens = 4096;
if (this.params.thinking?.budget_tokens) {
this.params.max_tokens = this.params.thinking.budget_tokens + 1000;
// max_tokens must be greater than thinking.budget_tokens
} else {
this.params.max_tokens = 16000;
}
}
const resp = await this.anthropic.messages.create({
model: this.model_name || "claude-3-sonnet-20240229",
@ -32,7 +37,14 @@ export class Claude {
});
console.log('Received.')
res = resp.content[0].text;
// get first content of type text
const textContent = resp.content.find(content => content.type === 'text');
if (textContent) {
res = textContent.text;
} else {
console.warn('No text content found in the response.');
res = 'No response from Claude.';
}
}
catch (err) {
console.log(err);

View file

@ -1,53 +1,84 @@
import Groq from 'groq-sdk'
import { getKey } from '../utils/keys.js';
// THIS API IS NOT TO BE CONFUSED WITH GROK!
// Go to grok.js for that. :)
// Umbrella class for Mixtral, LLama, Gemma...
// Umbrella class for everything under the sun... That GroqCloud provides, that is.
export class GroqCloudAPI {
constructor(model_name, url, params) {
this.model_name = model_name;
this.url = url;
this.params = params || {};
// ReplicateAPI theft :3
if (this.url) {
// Remove any mention of "tools" from params:
if (this.params.tools)
delete this.params.tools;
// This is just a bit of future-proofing in case we drag Mindcraft in that direction.
// I'm going to do a sneaky ReplicateAPI theft for a lot of this, aren't I?
if (this.url)
console.warn("Groq Cloud has no implementation for custom URLs. Ignoring provided URL.");
}
this.groq = new Groq({ apiKey: getKey('GROQCLOUD_API_KEY') });
}
async sendRequest(turns, systemMessage, stop_seq=null) {
let messages = [{"role": "system", "content": systemMessage}].concat(turns);
let messages = [{"role": "system", "content": systemMessage}].concat(turns); // The standard for GroqCloud is just appending to a messages array starting with the system prompt, but
// this is perfectly acceptable too, and I recommend it.
// I still feel as though I should note it for any future revisions of MindCraft, though.
// These variables look odd, but they're for the future. Please keep them intact.
let raw_res = null;
let res = null;
let tool_calls = null;
try {
console.log("Awaiting Groq response...");
if (!this.params.max_tokens) {
this.params.max_tokens = 16384;
if (this.params.max_tokens) {
console.warn("GROQCLOUD WARNING: A profile is using `max_tokens`. This is deprecated. Please move to `max_completion_tokens`.");
this.params.max_completion_tokens = this.params.max_tokens;
delete this.params.max_tokens;
}
if (!this.params.max_completion_tokens) {
this.params.max_completion_tokens = 8000; // Set it lower. This is a common theme.
}
let completion = await this.groq.chat.completions.create({
"messages": messages,
"model": this.model_name || "mixtral-8x7b-32768",
"stream": true,
"model": this.model_name || "llama-3.3-70b-versatile",
"stream": false,
"stop": stop_seq,
...(this.params || {})
});
let temp_res = "";
for await (const chunk of completion) {
temp_res += chunk.choices[0]?.delta?.content || '';
}
res = temp_res;
raw_res = completion.choices[0].message;
res = raw_res.content;
}
catch(err) {
console.log(err);
res = "My brain just kinda stopped working. Try again.";
}
return res;
}
async embed(text) {
async embed(_) {
throw new Error('Embeddings are not supported by Groq.');
}
}
}

View file

@ -1,7 +1,6 @@
import { readFileSync, mkdirSync, writeFileSync} from 'fs';
import { Examples } from '../utils/examples.js';
import { getCommandDocs } from '../agent/commands/index.js';
import { getSkillDocs } from '../agent/library/index.js';
import { SkillLibrary } from "../agent/library/skill_library.js";
import { stringifyTurns } from '../utils/text.js';
import { getCommand } from '../agent/commands/index.js';
@ -21,6 +20,12 @@ import { Grok } from "./grok.js";
import { DeepSeek } from './deepseek.js';
import { OpenRouter } from './openrouter.js';
import { VLLM } from './vllm.js';
import { promises as fs } from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
export class Prompter {
constructor(agent, fp) {
@ -145,7 +150,9 @@ export class Prompter {
else if (profile.model.includes('grok'))
profile.api = 'xai';
else if (profile.model.includes('deepseek'))
profile.api = 'deepseek';
profile.api = 'deepseek';
else if (profile.model.includes('mistral'))
profile.api = 'mistral';
else if (profile.model.includes('llama3'))
profile.api = 'ollama';
else
@ -183,7 +190,7 @@ export class Prompter {
else if (profile.api === 'openrouter')
model = new OpenRouter(profile.model.replace('openrouter/', ''), profile.url, profile.params);
else if (profile.api === 'vllm')
model = new VLLM(profile.model, profile.url, profile.params);
model = new VLLM(profile.model.replace('vllm/', ''), profile.url, profile.params);
else
throw new Error('Unknown API:', profile.api);
return model;
@ -248,9 +255,6 @@ export class Prompter {
await this.skill_libary.getRelevantSkillDocs(code_task_content, settings.relevant_docs_count)
);
}
prompt = prompt.replaceAll('$COMMAND_DOCS', getCommandDocs());
if (prompt.includes('$CODE_DOCS'))
prompt = prompt.replaceAll('$CODE_DOCS', getSkillDocs());
if (prompt.includes('$EXAMPLES') && examples !== null)
prompt = prompt.replaceAll('$EXAMPLES', await examples.createExampleMessage(messages));
if (prompt.includes('$MEMORY'))
@ -300,29 +304,99 @@ export class Prompter {
this.last_prompt_time = Date.now();
}
// async promptConvo(messages) {
// this.most_recent_msg_time = Date.now();
// let current_msg_time = this.most_recent_msg_time;
// for (let i = 0; i < 3; i++) { // try 3 times to avoid hallucinations
// await this.checkCooldown();
// if (current_msg_time !== this.most_recent_msg_time) {
// return '';
// }
// let prompt = this.profile.conversing;
// prompt = await this.replaceStrings(prompt, messages, this.convo_examples);
// let generation = await this.chat_model.sendRequest(messages, prompt);
// // in conversations >2 players LLMs tend to hallucinate and role-play as other bots
// // the FROM OTHER BOT tag should never be generated by the LLM
// if (generation.includes('(FROM OTHER BOT)')) {
// console.warn('LLM hallucinated message as another bot. Trying again...');
// continue;
// }
// if (current_msg_time !== this.most_recent_msg_time) {
// console.warn(this.agent.name + ' received new message while generating, discarding old response.');
// return '';
// }
// return generation;
// }
// return '';
// }
async saveToFile(logFile, logEntry) {
task_id = this.task_id;
let logDir;
if (this.task_id === null) {
logDir = path.join(__dirname, `../../bots/${this.agent.name}/logs`);
} else {
logDir = path.join(__dirname, `../../bots/${this.agent.name}/logs/${task_id}`);
}
await fs.mkdir(logDir, { recursive: true });
await fs.appendFile(logFile, String(logEntry), 'utf-8');
}
async promptConvo(messages) {
// console.log(`[${new Date().toISOString()}] promptConvo called with messages:`, messages);
this.most_recent_msg_time = Date.now();
let current_msg_time = this.most_recent_msg_time;
for (let i = 0; i < 3; i++) { // try 3 times to avoid hallucinations
await this.checkCooldown();
if (current_msg_time !== this.most_recent_msg_time) {
return '';
}
let prompt = this.profile.conversing;
prompt = await this.replaceStrings(prompt, messages, this.convo_examples);
let generation = await this.chat_model.sendRequest(messages, prompt);
// in conversations >2 players LLMs tend to hallucinate and role-play as other bots
// the FROM OTHER BOT tag should never be generated by the LLM
if (generation.includes('(FROM OTHER BOT)')) {
let generation;
try {
generation = await this.chat_model.sendRequest(messages, prompt);
let task_id = this.agent.task.task_id
console.log(task_id)
if (typeof generation !== 'string') {
console.error('Error: Generated response is not a string', generation);
throw new Error('Generated response is not a string');
}
console.log("Generated response:", generation);
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
let logEntry;
if (this.task_id === null) {
logEntry = `[${timestamp}] \nPrompt:\n${prompt}\n\nConversation:\n${JSON.stringify(messages, null, 2)}\n\nResponse:\n${generation}\n\n`;
} else {
logEntry = `[${timestamp}] Task ID: ${task_id}\nPrompt:\n${prompt}\n\nConversation:\n${JSON.stringify(messages, null, 2)}\n\nResponse:\n${generation}\n\n`;
}
const logFile = `conversation/${timestamp}.txt`;
await this.saveToFile(logFile, logEntry);
} catch (error) {
console.error('Error during message generation or file writing:', error);
continue;
}
// Check for hallucination or invalid output
if (generation?.includes('(FROM OTHER BOT)')) {
console.warn('LLM hallucinated message as another bot. Trying again...');
continue;
}
if (current_msg_time !== this.most_recent_msg_time) {
console.warn(this.agent.name + ' received new message while generating, discarding old response.');
console.warn(`${this.agent.name} received new message while generating, discarding old response.`);
return '';
}
return generation;
}
return '';
}
@ -335,6 +409,15 @@ export class Prompter {
await this.checkCooldown();
let prompt = this.profile.coding;
prompt = await this.replaceStrings(prompt, messages, this.coding_examples);
let logEntry;
if (this.task_id === null) {
logEntry = `[${new Date().toISOString()}] \nPrompt:\n${prompt}\n\nConversation:\n${JSON.stringify(messages, null, 2)}\n\n`;
} else {
logEntry = `[${new Date().toISOString()}] Task ID: ${this.agent.task.task_id}\nPrompt:\n${prompt}\n\nConversation:\n${JSON.stringify(messages, null, 2)}\n\n`;
}
const logFile = `coding/${timestamp}.txt`;
await this.saveToFile(logFile, logEntry);
let resp = await this.code_model.sendRequest(messages, prompt);
this.awaiting_coding = false;
return resp;
@ -343,6 +426,14 @@ export class Prompter {
async promptMemSaving(to_summarize) {
await this.checkCooldown();
let prompt = this.profile.saving_memory;
let logEntry;
if (this.task_id === null) {
logEntry = `[${new Date().toISOString()}] \nPrompt:\n${prompt}\n\nTo Summarize:\n${JSON.stringify(messages, null, 2)}\n\n`;
} else {
logEntry = `[${new Date().toISOString()}] Task ID: ${this.agent.task.task_id}\nPrompt:\n${prompt}\n\nConversation:\n${JSON.stringify(messages, null, 2)}\n\n`;
}
const logFile = `memSaving/${timestamp}.txt`;
await this.saveToFile(logFile, logEntry);
prompt = await this.replaceStrings(prompt, null, null, to_summarize);
return await this.chat_model.sendRequest([], prompt);
}

View file

@ -1,25 +0,0 @@
export class BlueprintGenerator {
constructor(num_levels,
num_rooms,
room_height,
materials) {
this.blueprint = {
"name": "Blueprint",
"nodes": [],
"connections": []
};
}
addNode(node) {
this.blueprint.nodes.push(node);
}
addConnection(connection) {
this.blueprint.connections.push(connection);
}
getBlueprint() {
return this.blueprint;
}
}

View file

@ -0,0 +1,34 @@
# Construction Tasks Generation
## Overview
Instructions on how to customize construction task generation.
## Getting Started
Edit and Run `tasks/construction_tasks/generate_multiagent_construction_tasks.js` to create new task variants. Note the 'main' is at the end of the page, and determines which file gets written to.
## Customization Options
### Cheats and Profile Configurations
To enable cheats, set the `cheat` variable to `true` in `profiles/task_construct.json`.
You can additionally access
### Task Configuration
For task specific customization, modify the `generateConstructionTasks` function in `tasks/construction_tasks/generate_multiagent_construction_tasks.js` to adjust:
1. Room parameters:
- Size
- Window style
- Carpet style
2. Task generation:
- Number of variants
- Timeout duration
The generation code is documented to help with customization.
## Important File Locations
- `tasks/construction_tasks/generate_multiagent_construction_tasks.js` - Main task generation script
- `profiles/task_construct.json` - Default configuration profile
- `tasks/construction_tasks/test_multiagent_construction_tasks.json` - Training task definitions (initalized with 5 variants)
- `tasks/construction_tasks/test_multiagent_construction_tasks.json` - Test task definitions (initalized with 1 variant)
- `src/agent/task_types/construction_tasks.js` - Blueprint Class, Construction Validation Class, and Procedural Generation Function

View file

@ -1,6 +1,12 @@
import fs from 'fs';
import {proceduralGeneration} from "../../src/agent/task_types/construction_tasks.js";
/**
* Helper function to initalize agent inventories
* @param blueprint
* @param agents
* @returns {{}}
*/
function createInitialInventory(blueprint, agents) {
/*
params:
@ -23,10 +29,12 @@ function createInitialInventory(blueprint, agents) {
inventories[i] = {'diamond_pickaxe':1};
}
// Count materials in blueprint
// Count materials in blueprint and replace ladder variants with "ladder"
for (const level of blueprint.levels) {
for (const row of level.placement) {
for (const block of row) {
for (let rowIndex = 0; rowIndex < level.placement.length; rowIndex++) {
for (let blockIndex = 0; blockIndex < level.placement[rowIndex].length; blockIndex++) {
let block = level.placement[rowIndex][blockIndex];
if (block !== 'air') {
// Check if material contains 'door' or 'ladder' and convert appropriately
let materialKey = block;
@ -36,6 +44,7 @@ function createInitialInventory(blueprint, agents) {
materialKey = 'oak_door';
} else if (block.includes('ladder')) {
materialKey = 'ladder';
level.placement[rowIndex][blockIndex] = 'ladder'; // Replace in blueprint
}
materialCounts[materialKey] = (materialCounts[materialKey] || 0) + 1;
@ -44,6 +53,7 @@ function createInitialInventory(blueprint, agents) {
}
}
// Distribute materials among agents
for (const [material, count] of Object.entries(materialCounts)) {
inventories[currentAgent][material] = count;
@ -54,19 +64,33 @@ function createInitialInventory(blueprint, agents) {
return inventories;
}
/**
* Helper function to allocate space for the blueprint based on the number of rooms
* @param rooms
* @returns {number}
*/
function calculateSpaceNeeded(rooms) {
const baseSize = 10;
const scaleFactor = Math.floor(rooms / 4) * 5;
return baseSize + scaleFactor;
}
/**
* MAIN GENERATION FUNCTION
*
* Varies materials, room count, windows and carpets to create different complexities of construction tasks.
* @param variants is the number of variants within each complexity level you want.
* @returns The tasks as nested JSON {{}}
*/
function generateConstructionTasks(variants) {
const tasks = {};
const materialLevels = 5;
const agentCount = 2
const roomCounts = [4, 6, 8];
const windowStyles = [0, 1, 2];
const carpetStyles = [0, 1, 2];
const timeout = 600 // 10 min base?
const timeout = 600 // 10 min base
const tasks = {};
for (let m = 0; m < materialLevels; m++) {
for (let r = 0; r < roomCounts.length; r++) {
@ -97,8 +121,8 @@ function generateConstructionTasks(variants) {
type: "construction",
goal: "Make a house with the blueprint",
conversation: "Let's share materials and make a house with the blueprint",
agent_count: 2,
initial_inventory: createInitialInventory(blueprint, 2),
agent_count: agentCount,
initial_inventory: createInitialInventory(blueprint, agentCount),
timeout: timeout+(300*r), // 5 minute per additional level of complexity
blueprint: blueprint,
@ -112,12 +136,15 @@ function generateConstructionTasks(variants) {
return tasks;
}
const tasks = generateConstructionTasks(1);
//Main: writes the generated tasks to a file.
const tasks = generateConstructionTasks(5);
// Clear existing file content
fs.writeFileSync('./test_multiagent_construction_tasks.json', '');
fs.writeFileSync('./train_multiagent_construction_tasks.json', '');
// re-add
fs.writeFileSync(
'./test_multiagent_construction_tasks.json',
'./train_multiagent_construction_tasks.json',
JSON.stringify(tasks, null, 2)
);

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,112 @@
{
"multiagent_crafting_magma_block_no_plan__depth_0": {
"goal": "Collaborate with other agents to craft an magma_block",
"conversation": "Let's work together to craft an magma_block.",
"initial_inventory": {
"0": {
"magma_cream": 3
},
"1": {
"magma_cream": 2
}
},
"agent_count": 2,
"target": "magma_block",
"number_of_target": 1,
"type": "techtree",
"max_depth": 2,
"depth": 0,
"timeout": 240,
"blocked_actions": {
"0": [
"!getCraftingPlan"
],
"1": [
"!getCraftingPlan"
]
},
"missing_items": []
},
"multiagent_crafting_polished_diorite_no_plan__depth_0": {
"goal": "Collaborate with other agents to craft an polished_diorite",
"conversation": "Let's work together to craft an polished_diorite.",
"initial_inventory": {
"0": {
"diorite": 3
},
"1": {
"diorite": 2
}
},
"agent_count": 2,
"target": "polished_diorite",
"number_of_target": 1,
"type": "techtree",
"max_depth": 1,
"depth": 0,
"timeout": 240,
"blocked_actions": {
"0": [
"!getCraftingPlan"
],
"1": [
"!getCraftingPlan"
]
},
"missing_items": []
},
"multiagent_crafting_blast_furnace_full_plan__depth_0": {
"goal": "Collaborate with other agents to craft an blast_furnace",
"conversation": "Let's work together to craft an blast_furnace.",
"initial_inventory": {
"0": {
"iron_ingot": 3,
"furnace": 1,
"smooth_stone": 2
},
"1": {
"iron_ingot": 2,
"smooth_stone": 1
}
},
"agent_count": 2,
"target": "blast_furnace",
"number_of_target": 1,
"type": "techtree",
"max_depth": 1,
"depth": 0,
"timeout": 240,
"blocked_actions": {
"0": [],
"1": []
},
"missing_items": []
},
"multiagent_crafting_comparator_full_plan__depth_0": {
"goal": "Collaborate with other agents to craft an comparator",
"conversation": "Let's work together to craft an comparator.",
"initial_inventory": {
"0": {
"redstone_torch": 2,
"quartz": 1,
"stone": 2
},
"1": {
"redstone_torch": 1,
"stone": 1
}
},
"agent_count": 2,
"target": "comparator",
"number_of_target": 1,
"type": "techtree",
"max_depth": 3,
"depth": 0,
"timeout": 240,
"blocked_actions": {
"0": [],
"1": []
},
"missing_items": []
}
}