From 85ef0e8103a743d617b88fd4b7a47e71a72edc30 Mon Sep 17 00:00:00 2001 From: MaxRobinsonTheGreat Date: Thu, 9 Jan 2025 12:43:29 -0600 Subject: [PATCH 1/4] fix help command --- src/agent/commands/queries.js | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/agent/commands/queries.js b/src/agent/commands/queries.js index ad02af5..ef65b4d 100644 --- a/src/agent/commands/queries.js +++ b/src/agent/commands/queries.js @@ -1,5 +1,6 @@ import * as world from '../library/world.js'; import * as mc from '../../utils/mcdata.js'; +import { getCommandDocs } from './index.js'; import convoManager from '../conversation.js'; const pad = (str) => { @@ -181,12 +182,7 @@ export const queryList = [ name: '!help', description: 'Lists all available commands and their descriptions.', perform: async function (agent) { - const commandList = actionsList.map(action => { - return `${action.name.padEnd(15)} - ${action.description}`; // Ensure consistent spacing - }).join('\n'); - - console.log(commandList); - return `Available Commands:\n${commandList}`; + return getCommandDocs(); } }, ]; From 6167aeeec49486c3911dc23b312ceeb075c2ea0a Mon Sep 17 00:00:00 2001 From: MaxRobinsonTheGreat Date: Thu, 9 Jan 2025 15:15:25 -0600 Subject: [PATCH 2/4] added restrict to inventory and better blacklist --- example_tasks.json | 8 ++++++++ src/agent/agent.js | 5 +++-- src/agent/commands/index.js | 17 +++++++++++++---- src/agent/library/skills.js | 10 +++++++++- src/agent/modes.js | 3 +++ src/agent/prompter.js | 2 +- src/agent/tasks.js | 1 + 7 files changed, 38 insertions(+), 8 deletions(-) diff --git a/example_tasks.json b/example_tasks.json index b579233..ef81f9b 100644 --- a/example_tasks.json +++ b/example_tasks.json @@ -17,6 +17,14 @@ }, "type": "debug" }, + "debug_inventory_restriction": { + "goal": "Place 1 oak plank, then place 1 stone brick", + "initial_inventory": { + "oak_planks": 20 + }, + "type": "debug", + "restrict_to_inventory": true + }, "construction": { "type": "construction", "goal": "Build a house", diff --git a/src/agent/agent.js b/src/agent/agent.js index 9a35cf0..4691079 100644 --- a/src/agent/agent.js +++ b/src/agent/agent.js @@ -3,7 +3,7 @@ import { Coder } from './coder.js'; import { Prompter } from './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'; @@ -47,7 +47,8 @@ export class Agent { await this.prompter.initExamples(); console.log('Initializing task...'); this.task = new Task(this, task_path, task_id); - this.blocked_actions = this.task.blocked_actions || []; + const blocked_actions = this.task.blocked_actions || []; + blacklistCommands(blocked_actions); serverProxy.connect(this); diff --git a/src/agent/commands/index.js b/src/agent/commands/index.js index a8d09db..3f3f967 100644 --- a/src/agent/commands/index.js +++ b/src/agent/commands/index.js @@ -14,6 +14,18 @@ export function getCommand(name) { return commandMap[name]; } +export function blacklistCommands(commands) { + const unblockable = ['!stop', '!stats', '!goal', '!endGoal', '!endConversation']; + for (let command_name of commands) { + if (unblockable.includes(command_name)){ + console.warn(`Command ${command_name} is unblockable`); + continue; + } + delete commandMap[command_name]; + delete commandList.find(command => command.name === command_name); + } +} + const commandRegex = /!(\w+)(?:\(((?:-?\d+(?:\.\d+)?|true|false|"[^"]*")(?:\s*,\s*(?:-?\d+(?:\.\d+)?|true|false|"[^"]*"))*)\))?/ const argRegex = /-?\d+(?:\.\d+)?|true|false|"[^"]*"/g; @@ -214,7 +226,7 @@ export async function executeCommand(agent, message) { } } -export function getCommandDocs(blacklist=null) { +export function getCommandDocs() { const typeTranslations = { //This was added to keep the prompt the same as before type checks were implemented. //If the language model is giving invalid inputs changing this might help. @@ -228,9 +240,6 @@ export function getCommandDocs(blacklist=null) { Use the commands with the syntax: !commandName or !commandName("arg1", 1.2, ...) if the command takes arguments.\n Do not use codeblocks. Use double quotes for strings. Only use one command in each response, trailing commands and comments will be ignored.\n`; for (let command of commandList) { - if (blacklist && blacklist.includes(command.name)) { - continue; - } docs += command.name + ': ' + command.description + '\n'; if (command.params) { docs += 'Params:\n'; diff --git a/src/agent/library/skills.js b/src/agent/library/skills.js index c0d448f..be5882f 100644 --- a/src/agent/library/skills.js +++ b/src/agent/library/skills.js @@ -558,6 +558,14 @@ export async function placeBlock(bot, blockType, x, y, z, placeOn='bottom', dont const target_dest = new Vec3(Math.floor(x), Math.floor(y), Math.floor(z)); if (bot.modes.isOn('cheat') && !dontCheat) { + if (bot.restrict_to_inventory) { + let block = bot.inventory.items().find(item => item.name === blockType); + if (!block) { + log(bot, `Cannot place ${blockType}, you are restricted to your current inventory.`); + return false; + } + } + // invert the facing direction let face = placeOn === 'north' ? 'south' : placeOn === 'south' ? 'north' : placeOn === 'east' ? 'west' : 'east'; if (blockType.includes('torch') && placeOn !== 'bottom') { @@ -599,7 +607,7 @@ export async function placeBlock(bot, blockType, x, y, z, placeOn='bottom', dont if (item_name == "redstone_wire") item_name = "redstone"; let block = bot.inventory.items().find(item => item.name === item_name); - if (!block && bot.game.gameMode === 'creative') { + if (!block && bot.game.gameMode === 'creative' && !bot.restrict_to_inventory) { await bot.creative.setInventorySlot(36, mc.makeItem(item_name, 1)); // 36 is first hotbar slot block = bot.inventory.items().find(item => item.name === item_name); } diff --git a/src/agent/modes.js b/src/agent/modes.js index d9ec75f..8bf1594 100644 --- a/src/agent/modes.js +++ b/src/agent/modes.js @@ -404,6 +404,9 @@ export function initModes(agent) { _agent = agent; // the mode controller is added to the bot object so it is accessible from anywhere the bot is used agent.bot.modes = new ModeController(); + if (agent.task) { + agent.bot.restrict_to_inventory = agent.task.restrict_to_inventory; + } let modes_json = agent.prompter.getInitModes(); if (modes_json) { agent.bot.modes.loadJson(modes_json); diff --git a/src/agent/prompter.js b/src/agent/prompter.js index 8feda0c..bc05860 100644 --- a/src/agent/prompter.js +++ b/src/agent/prompter.js @@ -186,7 +186,7 @@ export class Prompter { prompt = prompt.replaceAll('$ACTION', this.agent.actions.currentActionLabel); } if (prompt.includes('$COMMAND_DOCS')) - prompt = prompt.replaceAll('$COMMAND_DOCS', getCommandDocs(this.agent.blocked_actions)); + prompt = prompt.replaceAll('$COMMAND_DOCS', getCommandDocs()); if (prompt.includes('$CODE_DOCS')) prompt = prompt.replaceAll('$CODE_DOCS', getSkillDocs()); if (prompt.includes('$EXAMPLES') && examples !== null) diff --git a/src/agent/tasks.js b/src/agent/tasks.js index f7527f1..6d968a9 100644 --- a/src/agent/tasks.js +++ b/src/agent/tasks.js @@ -51,6 +51,7 @@ export class Task { this.taskStartTime = Date.now(); this.validator = new TaskValidator(this.data, this.agent); this.blocked_actions = this.data.blocked_actions || []; + this.restrict_to_inventory = !!this.data.restrict_to_inventory; if (this.data.goal) this.blocked_actions.push('!endGoal'); if (this.data.conversation) From 7eef80539519208b9b6fc3af57a89ce6439106aa Mon Sep 17 00:00:00 2001 From: MaxRobinsonTheGreat Date: Thu, 9 Jan 2025 15:16:35 -0600 Subject: [PATCH 3/4] added num_examples --- settings.js | 3 ++- src/agent/prompter.js | 5 +++-- src/utils/examples.js | 6 ++++++ 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/settings.js b/settings.js index add5297..a4681fa 100644 --- a/settings.js +++ b/settings.js @@ -35,7 +35,8 @@ export default "code_timeout_mins": 10, // minutes code is allowed to run. -1 for no timeout "max_messages": 15, // max number of messages to keep in context - "max_commands": -1, // max number of commands to use in a response. -1 for no limit + "num_examples": 2, // number of examples to give to the model + "max_commands": -1, // max number of commands that can be used in consecutive responses. -1 for no limit "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 diff --git a/src/agent/prompter.js b/src/agent/prompter.js index bc05860..310ca3e 100644 --- a/src/agent/prompter.js +++ b/src/agent/prompter.js @@ -4,6 +4,7 @@ import { getCommandDocs } from './commands/index.js'; import { getSkillDocs } from './library/index.js'; import { stringifyTurns } from '../utils/text.js'; import { getCommand } from './commands/index.js'; +import settings from '../../settings.js'; import { Gemini } from '../models/gemini.js'; import { GPT } from '../models/gpt.js'; @@ -155,8 +156,8 @@ export class Prompter { async initExamples() { try { - this.convo_examples = new Examples(this.embedding_model); - this.coding_examples = new Examples(this.embedding_model); + this.convo_examples = new Examples(this.embedding_model, settings.num_examples); + this.coding_examples = new Examples(this.embedding_model, settings.num_examples); // Wait for both examples to load before proceeding await Promise.all([ diff --git a/src/utils/examples.js b/src/utils/examples.js index 31ef3ab..ca6de79 100644 --- a/src/utils/examples.js +++ b/src/utils/examples.js @@ -33,6 +33,9 @@ export class Examples { this.examples = examples; if (!this.model) return; // Early return if no embedding model + if (this.select_num === 0) + return; + try { // Create array of promises first const embeddingPromises = examples.map(example => { @@ -52,6 +55,9 @@ export class Examples { } async getRelevant(turns) { + if (this.select_num === 0) + return []; + let turn_text = this.turnsToText(turns); if (this.model !== null) { let embedding = await this.model.embed(turn_text); From eeaf33c4d290a4ffeab5d59e8a671a55bb6ba0f4 Mon Sep 17 00:00:00 2001 From: MaxRobinsonTheGreat Date: Fri, 10 Jan 2025 12:41:00 -0600 Subject: [PATCH 4/4] changed unblockables --- src/agent/commands/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/agent/commands/index.js b/src/agent/commands/index.js index 3f3f967..008c1d0 100644 --- a/src/agent/commands/index.js +++ b/src/agent/commands/index.js @@ -15,7 +15,7 @@ export function getCommand(name) { } export function blacklistCommands(commands) { - const unblockable = ['!stop', '!stats', '!goal', '!endGoal', '!endConversation']; + const unblockable = ['!stop', '!stats', '!inventory', '!goal']; for (let command_name of commands) { if (unblockable.includes(command_name)){ console.warn(`Command ${command_name} is unblockable`);