From 32810722fb016dd8e4633fd7a3a4239fc8a26d4d Mon Sep 17 00:00:00 2001 From: MaxRobinsonTheGreat Date: Wed, 8 Nov 2023 19:24:24 -0600 Subject: [PATCH 1/3] fixed placeBlock, use Vec3, improved code gen --- utils/coder.js | 43 ++++++++++++++++++++---------- utils/gpt.js | 2 +- utils/skill_library.js | 13 ++++++--- utils/skills.js | 60 +++++++++++++----------------------------- 4 files changed, 58 insertions(+), 60 deletions(-) diff --git a/utils/coder.js b/utils/coder.js index a1e6a5a..bfa1b78 100644 --- a/utils/coder.js +++ b/utils/coder.js @@ -9,9 +9,18 @@ export class Coder { } queueCode(code) { - if (code.startsWith('javascript')) - code = code.slice(10); - this.current_code = code; + this.current_code = this.santitizeCode(code); + } + + santitizeCode(code) { + const remove_strs = ['javascript', 'js'] + for (let r of remove_strs) { + if (code.startsWith(r)) { + code = code.slice(r.length); + return code; + } + } + return code; } hasCode() { @@ -35,6 +44,7 @@ export class Coder { if (!this.current_code) return {success: false, message: "No code to execute."}; let src = "import * as skills from '../utils/skills.js';"; src += "\nimport * as world from '../utils/world.js';" + src += "\nimport Vec3 from 'vec3';" src += `\n\nexport async function main(bot) {\n`; for (let line of this.current_code.split('\n')) { src += ` ${line}\n`; @@ -44,18 +54,18 @@ export class Coder { console.log("writing to file...", src) let filename = this.fp + this.file_counter + '.js'; - if (this.file_counter > 0) { - let prev_filename = this.fp + (this.file_counter-1) + '.js'; - unlink(prev_filename, (err) => { - console.log("deleted file " + prev_filename); - if (err) console.error(err); - }); - } + // if (this.file_counter > 0) { + // let prev_filename = this.fp + (this.file_counter-1) + '.js'; + // unlink(prev_filename, (err) => { + // console.log("deleted file " + prev_filename); + // if (err) console.error(err); + // }); + // } commented for now, useful to keep files for debugging this.file_counter++; - let result = await this.writeFilePromise(filename, src); + let write_result = await this.writeFilePromise(filename, src); - if (result) { + if (write_result) { console.error('Error writing code execution file: ' + result); return {success: false, message: result}; } @@ -65,9 +75,14 @@ export class Coder { let execution_file = await import('.'+filename); this.clear(); let success = await execution_file.main(this.agent.bot); - return {success, message: ""}; + let message = success ? 'Code await returned successfully.' : 'Code await return failed!'; + if (success) + console.log(message) + else + console.error(message); + return {success, message}; } catch (err) { - console.error("Problem executing code:" + err); + console.error("Code execution triggered catch:" + err); this.clear(); return {success: false, message: err}; } diff --git a/utils/gpt.js b/utils/gpt.js index afbe611..296c2be 100644 --- a/utils/gpt.js +++ b/utils/gpt.js @@ -22,7 +22,7 @@ export async function sendRequest(turns, systemMessage, stop_seq='***') { let res = null; try { let completion = await openai.chat.completions.create({ - model: 'gpt-4', + model: 'gpt-3.5-turbo', messages: messages, stop: stop_seq, }); diff --git a/utils/skill_library.js b/utils/skill_library.js index 13ea0fb..e9830dd 100644 --- a/utils/skill_library.js +++ b/utils/skill_library.js @@ -4,14 +4,21 @@ import * as world from './world.js'; export function getSkillDocs() { let docstring = "\n*SKILL DOCS\nThese skills are javascript functions that can be called with a js function by writing a code block. Ex: '```// write description comment and code here```' \n\ Your code block should return a bool indicating if the task was completed successfully. It will return true if you don't write a return statement.\n"; - for (let skillFunc of Object.values(world).concat(Object.values(skills))) { + docstring += docHelper(Object.values(skills), 'skills'); + docstring += docHelper(Object.values(world), 'world'); + return docstring + '*\n'; +} + +export function docHelper(functions, module_name) { + let docstring = ''; + for (let skillFunc of functions) { let str = skillFunc.toString(); if (str.includes('/**')){ - docstring += skillFunc.name; + docstring += module_name+'.'+skillFunc.name; docstring += str.substring(str.indexOf('/**')+3, str.indexOf('**/')) + '\n'; } } - return docstring + '*\n'; + return docstring; } export function containsCodeBlock(message) { diff --git a/utils/skills.js b/utils/skills.js index 0d95ac0..0c82b6e 100644 --- a/utils/skills.js +++ b/utils/skills.js @@ -1,6 +1,7 @@ import { getItemId } from "./mcdata.js"; import { getCraftingTable, getInventoryCounts, getInventoryStacks, getNearbyMobs, getNearbyBlocks } from "./world.js"; import pf from 'mineflayer-pathfinder'; +import Vec3 from 'vec3'; export async function craftItem(bot, itemName) { @@ -71,64 +72,39 @@ export async function breakBlockAt(bot, x, y, z) { * let position = world.getPosition(bot); * await skills.breakBlockAt(bot, position.x, position.y - 1, position.x); **/ - let current = bot.blockAt({ x: x, y: y, z: z }); + let current = bot.blockAt(Vec3(x, y, z)); if (current.name != 'air') await bot.dig(current, true); return true; } -export async function placeBlock(bot, blockType, x, y, z) { +export async function placeBlock(bot, blockType, x, y, z, faceVec=new Vec3(0, 1, 0)) { /** * Place the given block type at the given position. * @param {MinecraftBot} bot, reference to the minecraft bot. * @param {string} blockType, the type of block to place. - * @param {number} x, the x coordinate to place the block at. - * @param {number} y, the y coordinate to place the block at. - * @param {number} z, the z coordinate to place the block at. + * @param {number} x, the x coordinate of the block to place. + * @param {number} y, the y coordinate of the block to place. + * @param {number} z, the z coordinate of the block to place. + * @param {Vec3} faceVec, the face of the block to place against. Defaults to the top face. * @returns {Promise} true if the block was placed, false otherwise. * @example * let position = world.getPosition(bot); - * await skills.placeBlock(bot, "oak_log", position.x + 1, position.y, position.x); + * await skills.placeBlock(bot, "oak_log", position.x + 1, position.y, position.x, new Vec3(1, 0, 0)); **/ - let referenceBlock = null; - let refVec = null; - if (bot.blockAt({ x: x + 1, y: y, z: z }).name != "air") { - referenceBlock = bot.blockAt({ x: x + 1, y: y, z: z }); - refVec = { x: x - 1, y: y, z: z }; - } else if (bot.blockAt({ x: x - 1, y: y, z: z }).name != "air") { - referenceBlock = bot.blockAt({ x: x - 1, y: y, z: z }); - refVec = { x: x + 1, y: y, z: z }; - } else if (bot.blockAt({ x: x, y: y + 1, z: z }).name != "air") { - referenceBlock = bot.blockAt({ x: x, y: y + 1, z: z }); - refVec = { x: x, y: y - 1, z: z }; - } else if (bot.blockAt({ x: x, y: y - 1, z: z }).name != "air") { - referenceBlock = bot.blockAt({ x: x, y: y - 1, z: z }); - refVec = { x: x, y: y + 1, z: z }; - } else if (bot.blockAt({ x: x, y: y, z: z + 1 }).name != "air") { - referenceBlock = bot.blockAt({ x: x, y: y, z: z + 1 }); - refVec = { x: x, y: y, z: z - 1 }; - } else if (bot.blockAt({ x: x, y: y, z: z - 1 }).name != "air") { - referenceBlock = bot.blockAt({ x: x, y: y, z: z - 1 }); - refVec = { x: x, y: y, z: z + 1 }; - } else { + let referenceBlock = bot.blockAt(new Vec3(x, y, z)); + if (referenceBlock.name != 'air') return false; - } - - let block = null; - for (let stack of getInventoryStacks(bot)) { - if (stack.name == blockType) { - block = stack; - break; - } - } - if (block == null) + let block = bot.inventory.items().find(item => item.name === blockType); + if (!block) return false; - - breakBlockAt(bot, x, y, z); await bot.equip(block, 'hand'); - await bot.placeBlock(referenceBlock, refVec); - return true; + bot.placeBlock(referenceBlock, faceVec).then(() => { + return true; + }).catch((err) => { + return false; + }); } @@ -164,7 +140,7 @@ export async function goToPosition(bot, x, y, z) { * @param {number} z, the z coordinate to navigate to. If null, the bot's current z coordinate will be used. * @returns {Promise} true if the position was reached, false otherwise. * @example - * let position = world.getPosition(bot); + * let position = getPosition(bot); * await skills.goToPosition(bot, position.x, position.y, position.x + 20); **/ if (x == null) x = bot.entity.position.x; From cd26c646b0b4bea1bce63924f5a1c1cac13b7dfb Mon Sep 17 00:00:00 2001 From: Kolby Nottingham Date: Wed, 8 Nov 2023 19:06:48 -0800 Subject: [PATCH 2/3] fixed execution errors when generated code used returns --- utils/coder.js | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/utils/coder.js b/utils/coder.js index bfa1b78..2242339 100644 --- a/utils/coder.js +++ b/utils/coder.js @@ -74,13 +74,10 @@ export class Coder { console.log('executing code...\n'); let execution_file = await import('.'+filename); this.clear(); - let success = await execution_file.main(this.agent.bot); - let message = success ? 'Code await returned successfully.' : 'Code await return failed!'; - if (success) - console.log(message) - else - console.error(message); - return {success, message}; + await execution_file.main(this.agent.bot); + let msg = 'Code executed successfully.'; + console.log(msg) + return {success: true, message: msg}; } catch (err) { console.error("Code execution triggered catch:" + err); this.clear(); From 960fc2ff2603152537e28933ff50e3ebe971db0a Mon Sep 17 00:00:00 2001 From: Kolby Nottingham Date: Wed, 8 Nov 2023 19:09:58 -0800 Subject: [PATCH 3/3] doc string was missing module name --- utils/skills.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/skills.js b/utils/skills.js index 0c82b6e..54e9219 100644 --- a/utils/skills.js +++ b/utils/skills.js @@ -140,7 +140,7 @@ export async function goToPosition(bot, x, y, z) { * @param {number} z, the z coordinate to navigate to. If null, the bot's current z coordinate will be used. * @returns {Promise} true if the position was reached, false otherwise. * @example - * let position = getPosition(bot); + * let position = world.getPosition(bot); * await skills.goToPosition(bot, position.x, position.y, position.x + 20); **/ if (x == null) x = bot.entity.position.x;