added various fixes/improvements

This commit is contained in:
MaxRobinsonTheGreat 2024-02-16 11:57:48 -06:00
parent feac9ab424
commit 3e3e80c0ed
9 changed files with 55 additions and 30 deletions

View file

@ -3,5 +3,5 @@
"host": "localhost", "host": "localhost",
"port": 55916, "port": 55916,
"auth": "offline", "auth": "offline",
"allow_insecure_coding": true "allow_insecure_coding": false
} }

View file

@ -29,7 +29,7 @@ export class Coder {
// write custom code to file and import it // write custom code to file and import it
async stageCode(code) { async stageCode(code) {
code = this.santitizeCode(code); code = this.sanitizeCode(code);
let src = ''; let src = '';
code = code.replaceAll('console.log(', 'log(bot,'); code = code.replaceAll('console.log(', 'log(bot,');
code = code.replaceAll('log("', 'log(bot,"'); code = code.replaceAll('log("', 'log(bot,"');
@ -62,7 +62,8 @@ export class Coder {
return await import('../..' + this.fp + filename); return await import('../..' + this.fp + filename);
} }
santitizeCode(code) { sanitizeCode(code) {
code = code.trim();
const remove_strs = ['Javascript', 'javascript', 'js'] const remove_strs = ['Javascript', 'javascript', 'js']
for (let r of remove_strs) { for (let r of remove_strs) {
if (code.startsWith(r)) { if (code.startsWith(r)) {
@ -93,6 +94,7 @@ export class Coder {
let res = await this.generateCodeLoop(agent_history); let res = await this.generateCodeLoop(agent_history);
this.generating = false; this.generating = false;
if (!res.interrupted) this.agent.bot.emit('idle'); if (!res.interrupted) this.agent.bot.emit('idle');
return res.message;
} }
async generateCodeLoop(agent_history) { async generateCodeLoop(agent_history) {
@ -107,7 +109,7 @@ export class Coder {
let failures = 0; let failures = 0;
for (let i=0; i<5; i++) { for (let i=0; i<5; i++) {
if (this.agent.bot.interrupt_code) if (this.agent.bot.interrupt_code)
return; return {success: true, message: null, interrupted: true, timedout: false};
console.log(messages) console.log(messages)
let res = await sendRequest(messages, system_message); let res = await sendRequest(messages, system_message);
console.log('Code generation response:', res) console.log('Code generation response:', res)
@ -120,8 +122,7 @@ export class Coder {
return {success: true, message: null, interrupted: false, timedout: false}; return {success: true, message: null, interrupted: false, timedout: false};
} }
if (failures >= 1) { if (failures >= 1) {
agent_history.add('system', 'Action failed, agent would not write code.'); return {success: false, message: 'Action failed, agent would not write code.', interrupted: false, timedout: false};
return {success: false, message: null, interrupted: false, timedout: false};
} }
messages.push({ messages.push({
role: 'system', role: 'system',
@ -143,7 +144,7 @@ export class Coder {
if (code_return.interrupted && !code_return.timedout) if (code_return.interrupted && !code_return.timedout)
return {success: false, message: null, interrupted: true, timedout: false}; return {success: false, message: null, interrupted: true, timedout: false};
console.log(code_return.message); console.log("Code generation result:", code_return.success, code_return.message);
messages.push({ messages.push({
role: 'assistant', role: 'assistant',
@ -219,7 +220,7 @@ export class Coder {
formatOutput(bot) { formatOutput(bot) {
if (bot.interrupt_code && !this.timedout) return ''; if (bot.interrupt_code && !this.timedout) return '';
let output = bot.output; let output = bot.output;
const MAX_OUT = 1000; const MAX_OUT = 500;
if (output.length > MAX_OUT) { if (output.length > MAX_OUT) {
output = `Code output is very long (${output.length} chars) and has been shortened.\n output = `Code output is very long (${output.length} chars) and has been shortened.\n
First outputs:\n${output.substring(0, MAX_OUT/2)}\n...skipping many lines.\nFinal outputs:\n ${output.substring(output.length - MAX_OUT/2)}`; First outputs:\n${output.substring(0, MAX_OUT/2)}\n...skipping many lines.\nFinal outputs:\n ${output.substring(output.length - MAX_OUT/2)}`;

View file

@ -26,7 +26,7 @@ export const actionsList = [
perform: async function (agent) { perform: async function (agent) {
if (!settings.allow_insecure_coding) if (!settings.allow_insecure_coding)
return 'Agent is not allowed to write code.'; return 'Agent is not allowed to write code.';
await agent.coder.generateCode(agent.history); return await agent.coder.generateCode(agent.history);
} }
}, },
{ {
@ -47,7 +47,7 @@ export const actionsList = [
} }
}, },
{ {
name: '!clear', name: '!clearChat',
description: 'Clear the chat history.', description: 'Clear the chat history.',
perform: async function (agent) { perform: async function (agent) {
agent.history.clear(); agent.history.clear();
@ -84,7 +84,7 @@ export const actionsList = [
}, },
{ {
name: '!followPlayer', name: '!followPlayer',
description: 'Endlessly follow the given player. Will defend that player if self_defense mode is on. Ex: !followPlayer("stevie")', description: 'Endlessly follow the given player. Will defend that player if self_defense mode is on. Ex: !followPlayer("stevie", 4)',
params: { params: {
'player_name': '(string) The name of the player to follow.', 'player_name': '(string) The name of the player to follow.',
'follow_dist': '(number) The distance to follow from.' 'follow_dist': '(number) The distance to follow from.'

View file

@ -59,7 +59,7 @@ export const queryList = [
} }
}, },
{ {
name: "!blocks", name: "!nearbyBlocks",
description: "Get the blocks near the bot.", description: "Get the blocks near the bot.",
perform: function (agent) { perform: function (agent) {
let bot = agent.bot; let bot = agent.bot;

View file

@ -29,8 +29,8 @@ export class History {
} }
getSystemMessage() { getSystemMessage() {
let system_message = `You are a playful Minecraft bot named '${this.name}' that can communicate with players, see, move, mine, build, and interact with the world by using commands. Act human-like as if you were a typical Minecraft player, rather than an AI. Be very brief in your responses, use commands often, and do not give instructions unless asked. let system_message = `You are a playful Minecraft bot named '${this.name}' that can communicate with players, see, move, mine, build, and interact with the world by using commands. 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, do not give instructions unless asked, and do not refuse requests.
Don't pretend to act, use commands immediately when requested. Do NOT do this: "Sure, I'll follow you! *follows you*", instead do this: "Sure I'll follow you! !followPlayer('steve')". Have fun :) \n`; 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('bingo', 3)". Have fun :) \n`;
system_message += getCommandDocs(); system_message += getCommandDocs();
if (this.bio != '') if (this.bio != '')
system_message += '\n\nBio:\n' + this.bio; system_message += '\n\nBio:\n' + this.bio;

View file

@ -421,14 +421,9 @@ export async function breakBlockAt(bot, x, y, z) {
* let position = world.getPosition(bot); * let position = world.getPosition(bot);
* await skills.breakBlockAt(bot, position.x, position.y - 1, position.x); * await skills.breakBlockAt(bot, position.x, position.y - 1, position.x);
**/ **/
if (x == null || y == null || z == null) throw new Error('Invalid position to break block at.');
let block = bot.blockAt(Vec3(x, y, z)); let block = bot.blockAt(Vec3(x, y, z));
if (block.name !== 'air' && block.name !== 'water' && block.name !== 'lava') { if (block.name !== 'air' && block.name !== 'water' && block.name !== 'lava') {
await bot.tool.equipForBlock(block);
const itemId = bot.heldItem ? bot.heldItem.type : null
if (!block.canHarvest(itemId)) {
log(bot, `Don't have right tools to break ${block.name}.`);
return false;
}
if (bot.entity.position.distanceTo(block.position) > 4.5) { if (bot.entity.position.distanceTo(block.position) > 4.5) {
let pos = block.position; let pos = block.position;
let movements = new pf.Movements(bot); let movements = new pf.Movements(bot);
@ -437,7 +432,18 @@ export async function breakBlockAt(bot, x, y, z) {
bot.pathfinder.setMovements(movements); bot.pathfinder.setMovements(movements);
await bot.pathfinder.goto(new pf.goals.GoalNear(pos.x, pos.y, pos.z, 4)); await bot.pathfinder.goto(new pf.goals.GoalNear(pos.x, pos.y, pos.z, 4));
} }
await bot.tool.equipForBlock(block);
const itemId = bot.heldItem ? bot.heldItem.type : null
if (!block.canHarvest(itemId)) {
log(bot, `Don't have right tools to break ${block.name}.`);
return false;
}
await bot.dig(block, true); await bot.dig(block, true);
log(bot, `Broke ${block.name} at x:${x.toFixed(1)}, y:${y.toFixed(1)}, z:${z.toFixed(1)}.`);
}
else {
log(bot, `Skipping block at x:${x.toFixed(1)}, y:${y.toFixed(1)}, z:${z.toFixed(1)} because it is ${block.name}.`);
return false;
} }
return true; return true;
} }

View file

@ -6,14 +6,14 @@
[ [
{"role": "user", "content": "grombo_Xx: What do you see?"}, {"role": "user", "content": "grombo_Xx: What do you see?"},
{"role": "assistant", "content": "Let me see... !blocks"}, {"role": "assistant", "content": "Let me see... !nearbyBlocks"},
{"role": "system", "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": "assistant", "content": "I see some oak logs, dirt, and cobblestone."}
], ],
[ [
{"role": "user", "content": "greg: Collect 10 wood"}, {"role": "user", "content": "greg: Collect 10 wood"},
{"role": "assistant", "content": "Let me see what's nearby... !blocks"}, {"role": "assistant", "content": "Let me see what's nearby... !nearbyBlocks"},
{"role": "system", "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. I'll collect oak logs. !collectBlocks('oak_log', 10)"} {"role": "assistant", "content": "I see some oak logs, dirt, and cobblestone. I'll collect oak logs. !collectBlocks('oak_log', 10)"}
], ],
@ -77,8 +77,13 @@
], ],
[ [
{"role": "user", "content": "brung00: build a house"}, {"role": "user", "content": "poppy: build a cobblestone house"},
{"role": "assistant", "content": "Sure, I'll try to build a house where I am. !newAction"} {"role": "assistant", "content": "Sure, I'll to build a small cobblestone house where I am. !newAction"}
],
[
{"role": "user", "content": "zib: build a dirt tower"},
{"role": "assistant", "content": "Sure, I'll build a dirt tower 5 tall where I am. !newAction"}
], ],
[ [

View file

@ -4,7 +4,7 @@ import { stringifyTurns } from './text.js';
export class Examples { export class Examples {
constructor(select_num=3) { constructor(select_num=2) {
this.examples = []; this.examples = [];
this.select_num = select_num; this.select_num = select_num;
} }

View file

@ -20,14 +20,28 @@ else {
const openai = new OpenAIApi(openAiConfig); const openai = new OpenAIApi(openAiConfig);
let counter = 0;
let request_queue = [];
export async function sendRequest(turns, systemMessage) {
// this wrapper function ensures that new requests await the completion of previous requests in order
let id = counter++;
request_queue.push(id);
if (request_queue.length > 1)
console.log('awaiting previous requests to complete, queueing request', id);
while (request_queue[0] !== id) {
await new Promise(r => setTimeout(r, 100));
}
let res = await queryGPT(turns, systemMessage);
request_queue.shift();
return res;
}
export async function sendRequest(turns, systemMessage, stop_seq='***') { async function queryGPT(turns, systemMessage, stop_seq='***') {
let messages = [{'role': 'system', 'content': systemMessage}].concat(turns); let messages = [{'role': 'system', 'content': systemMessage}].concat(turns);
let res = null; let res = null;
try { try {
console.log('Awaiting openai api response...') console.log('Awaiting openai api response...');
let completion = await openai.chat.completions.create({ let completion = await openai.chat.completions.create({
model: 'gpt-3.5-turbo', model: 'gpt-3.5-turbo',
messages: messages, messages: messages,
@ -35,13 +49,12 @@ export async function sendRequest(turns, systemMessage, stop_seq='***') {
}); });
if (completion.choices[0].finish_reason == 'length') if (completion.choices[0].finish_reason == 'length')
throw new Error('Context length exceeded'); throw new Error('Context length exceeded');
console.log('Received.')
res = completion.choices[0].message.content; res = completion.choices[0].message.content;
} }
catch (err) { catch (err) {
if ((err.message == 'Context length exceeded' || err.code == 'context_length_exceeded') && turns.length > 1) { if ((err.message == 'Context length exceeded' || err.code == 'context_length_exceeded') && turns.length > 1) {
console.log('Context length exceeded, trying again with shorter context.'); console.log('Context length exceeded, trying again with shorter context.');
return await sendRequest(turns.slice(1), systemMessage, stop_seq); return await queryGPT(turns.slice(1), systemMessage, stop_seq);
} else { } else {
console.log(err); console.log(err);
res = 'My brain disconnected, try again.'; res = 'My brain disconnected, try again.';