read template.js/feed code output to gpt

This commit is contained in:
MaxRobinsonTheGreat 2023-11-12 13:57:22 -06:00
parent 4acc19f1ff
commit fed5a6d887
5 changed files with 118 additions and 34 deletions

View file

@ -45,26 +45,22 @@ export class Agent {
console.log('Agent used query:', query_cmd);
let query = getQuery(query_cmd);
let query_res = query.perform(this);
this.history.add(this.name, query_res);
this.history.add('system', query_res);
}
else if (containsCodeBlock(res)) { // contains code block
let message = res.substring(0, res.indexOf('```')).trim();
if (message)
this.bot.chat(message);
else
this.bot.chat("Executing code...");
let code = res.substring(res.indexOf('```')+3, res.lastIndexOf('```'));
if (code) {
console.log('Queuing code: ' + code);
this.coder.queueCode(code);
let code_return = await this.coder.execute();
if (code_return.success)
break;
else {
let message = "Code execution failed: " + code_return.message;
let message = code_return.message;
if (!code_return.success) {
message += "\n Write code to fix the problem and try again.";
this.history.add(this.name, message);
}
console.log('code return:', message);
this.history.add('system', message);
}
}
else { // conversation response

View file

@ -1,6 +1,8 @@
import * as skills from '../utils/skills.js';
import * as world from '../utils/world.js';
// this file is currently unused
import Vec3 from 'vec3';
export async function main(bot) {
// agent's code goes here
/* CODE HERE */
return true; // potentially redundant return statement, in case agent doesn't return anything
}

View file

@ -1,4 +1,4 @@
import { writeFile, unlink } from 'fs';
import { writeFile, readFile, unlink } from 'fs';
export class Coder {
constructor(agent) {
@ -6,6 +6,14 @@ export class Coder {
this.current_code = '';
this.file_counter = 0;
this.fp = './agent_code/';
this.agent.bot.output = '';
this.code_template = '';
readFile(this.fp+'template.js', 'utf8', (err, data) => {
if (err) throw err;
console.log('Template str:', data);
this.code_template = data;
});
}
queueCode(code) {
@ -42,14 +50,12 @@ export class Coder {
async execute() {
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`;
if (!this.code_template) return {success: false, message: "Code template not loaded."};
let src = '';
for (let line of this.current_code.split('\n')) {
src += ` ${line}\n`;
}
src += ` return true;\n}\n`; // potentially redundant return statement, in case agent doesn't return anything
src = this.code_template.replace('/* CODE HERE */', src);
console.log("writing to file...", src)
@ -73,20 +79,34 @@ export class Coder {
try {
console.log('executing code...\n');
let execution_file = await import('.'+filename);
this.stop();
let success = await execution_file.main(this.agent.bot);
console.log('code execution finished.', success)
let output = this.agent.bot.output ? 'Code output: \n' + this.agent.bot.output : '';
// if there is output, add it to the message
if (success)
output += 'Code execution finished successfully.';
else
output += 'Code execution failed!';
console.log(output)
this.clear();
await execution_file.main(this.agent.bot);
let msg = 'Code executed successfully.';
console.log(msg)
return {success: true, message: msg};
return {success, message: output};
} catch (err) {
console.error("Code execution triggered catch:" + err);
this.clear();
return {success: false, message: err};
let message = 'Code output: \n' + this.agent.bot.output + '\n';
message += '!!Code threw exception!! Error: ' + err;
this.stop();
return {success: false, message};
}
}
clear() {
this.current_code = '';
this.agent.bot.output = '';
}
stop() {
this.clear();
this.agent.bot.pathfinder.setGoal(null);
}
}

View file

@ -4,25 +4,33 @@ let history_examples = [
{'role': 'user', 'content': 'grombo_Xx: What do you see?'},
{'role': 'assistant', 'content': 'Let me see... !blocks'},
{'role': 'assistant', 'content': 'NEARBY_BLOCKS\n- oak_log\n- dirt\n- cobblestone'},
{'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': 'zZZn98: come here'},
{'role': 'assistant', 'content': '```// I am going to navigate to zZZn98.\nreturn await skills.goToPlayer(bot, "zZZn98");```'},
{'role': 'system', 'content': 'Code execution finished successfully.'},
{'role': 'assistant', 'content': 'Here!'},
{'role': 'user', 'content': 'hanky: collect some sand for me please'},
{'role': 'assistant', 'content': 'Collecting sand...```// I am going to collect 3 sand and give to hanky.\n\
await skills.collectBlock(bot, "sand");\nreturn await skills.giveToPlayer(bot, "sand", "hanky");```'},
{'role': 'system', 'content': 'Code Output:\nYou have reached player hanky.\nCode execution finished successfully.'},
{'role': 'assistant', 'content': 'Here!'},
{'role': 'user', 'content': 'sarah_O.o: can you do a dance for me?'},
{'role': 'assistant', 'content': "I don't know how to do that."},
{'role': 'user', 'content': 'sarah_O.o: can you fly up in the air?'},
{'role': 'assistant', 'content': "I can't do that."},
{'role': 'user', 'content': 'hanky: kill that zombie!'},
{'role': 'assistant', 'content': "I'm attacking! ```//I'm going to attack the nearest zombie.\n\
return await skills.attackMob(bot, 'zombie');```"},
{'role': 'system', 'content': 'Code Output:\nNo zombie nearby\nCode execution failed!'},
{'role': 'assistant', 'content': 'I could not find a zombie nearby.'},
{'role': 'user', 'content': 'billybob: stop what you are doing'},
{'role': 'assistant', 'content': '```// I am going to write nothing to clear my code\n return true;```'},
]
export class History {
@ -37,7 +45,10 @@ export class History {
add(name, content) {
let role = 'assistant';
if (name !== this.agent.name) {
if (name === 'system') {
role = 'system';
}
else if (name !== this.agent.name) {
role = 'user';
content = `${name}: ${content}`;
}

View file

@ -3,6 +3,13 @@ import { getCraftingTable, getInventoryCounts, getInventoryStacks, getNearbyMobs
import pf from 'mineflayer-pathfinder';
import Vec3 from 'vec3';
function log(bot, message) {
bot.output += message + '\n';
}
function f(x) {
return Math.floor(x);
}
export async function craftItem(bot, itemName) {
/**
@ -93,17 +100,58 @@ export async function placeBlock(bot, blockType, x, y, z, faceVec=new Vec3(0, 1,
* let position = world.getPosition(bot);
* await skills.placeBlock(bot, "oak_log", position.x + 1, position.y, position.x, new Vec3(1, 0, 0));
**/
// top face: new Vec3(0, 1, 0)
// bottom face: new Vec3(0, -1, 0)
// north face: new Vec3(0, 0, -1)
// south face: new Vec3(0, 0, 1)
// east face: new Vec3(1, 0, 0)
// west face: new Vec3(-1, 0, 0)
let referenceBlock = bot.blockAt(new Vec3(x, y, z));
if (referenceBlock.name != 'air')
console.log("reference block", referenceBlock.name)
// check if bot is blocking the block to place
// if (bot.entity.position.distanceTo(referenceBlock.position) < 2) {
// console.log("bot is blocking block to place")
// // move out of the way
// let pos = bot.entity.position;
// let dx = pos.x - referenceBlock.position.x;
// let dz = pos.z - referenceBlock.position.z;
// let moveVec = new Vec3(dx, 0, dz);
// await bot.pathfinder.setMovements(new pf.Movements(bot));
// bot.pathfinder.setGoal(new pf.goals.GoalBlock(referenceBlock.position.x + moveVec.x, referenceBlock.position.y, referenceBlock.position.z + moveVec.z));
// }
// all blocks that can be replaced by another block:
let blocks_to_allow = ['air', 'water', 'lava', 'grass', 'tall_grass'];
if (!blocks_to_allow.includes(referenceBlock.name)) {
log(bot, `Block at ${f(x)}, ${f(y)}, ${f(z)} is ${referenceBlock.name} and cannot be replaced.`);
return false;
}
let block = bot.inventory.items().find(item => item.name === blockType);
if (!block)
if (!block) {
log(bot, `Don't have any ${blockType} to place.`);
return false;
}
await bot.equip(block, 'hand');
bot.placeBlock(referenceBlock, faceVec).then(() => {
return true;
}).catch((err) => {
return false;
// placeblock's callback is broken (always returns error)
bot.placeBlock(referenceBlock, faceVec).catch(err => {});
// await to check if block was actually placed
return await new Promise((resolve) => {
setTimeout(() => {
let current = bot.blockAt(new Vec3(x, y, z));
console.log("Checking current block", current.name);
if (current.name !== blockType) {
console.log('Failed to place block')
log(bot, `Failed to place block ${blockType} at ${f(x)}, ${f(y)}, ${f(z)}, which is ${current.name}.`);
resolve(false);
} else {
console.log('Successfully placed block')
resolve(true);
}
}, 1000);
});
}
@ -191,7 +239,13 @@ export async function goToPlayer(bot, username) {
bot.pathfinder.setMovements(new pf.Movements(bot));
let pos = player.position;
bot.pathfinder.setGoal(new pf.goals.GoalNear(pos.x, pos.y, pos.z, 3));
let distance = 2;
await bot.pathfinder.goto(new pf.goals.GoalNear(pos.x, pos.y, pos.z, distance));
if (bot.entity.position.distanceTo(pos) > distance+1) {
log(bot, `Failed to reach player ${username} (${bot.entity.position.distanceTo(pos)}m away)`);
return false;
}
log(bot, `You have reached player ${username}.`);
return true;
}
@ -212,6 +266,7 @@ export async function followPlayer(bot, username) {
bot.pathfinder.setMovements(new pf.Movements(bot));
let pos = player.position;
bot.pathfinder.setGoal(new pf.goals.GoalFollow(player, 3), true);
log(bot, `You are now actively following player ${username}.`);
return true;
}