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",
"port": 55916,
"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
async stageCode(code) {
code = this.santitizeCode(code);
code = this.sanitizeCode(code);
let src = '';
code = code.replaceAll('console.log(', 'log(bot,');
code = code.replaceAll('log("', 'log(bot,"');
@ -62,7 +62,8 @@ export class Coder {
return await import('../..' + this.fp + filename);
}
santitizeCode(code) {
sanitizeCode(code) {
code = code.trim();
const remove_strs = ['Javascript', 'javascript', 'js']
for (let r of remove_strs) {
if (code.startsWith(r)) {
@ -93,6 +94,7 @@ export class Coder {
let res = await this.generateCodeLoop(agent_history);
this.generating = false;
if (!res.interrupted) this.agent.bot.emit('idle');
return res.message;
}
async generateCodeLoop(agent_history) {
@ -107,7 +109,7 @@ export class Coder {
let failures = 0;
for (let i=0; i<5; i++) {
if (this.agent.bot.interrupt_code)
return;
return {success: true, message: null, interrupted: true, timedout: false};
console.log(messages)
let res = await sendRequest(messages, system_message);
console.log('Code generation response:', res)
@ -120,8 +122,7 @@ export class Coder {
return {success: true, message: null, interrupted: false, timedout: false};
}
if (failures >= 1) {
agent_history.add('system', 'Action failed, agent would not write code.');
return {success: false, message: null, interrupted: false, timedout: false};
return {success: false, message: 'Action failed, agent would not write code.', interrupted: false, timedout: false};
}
messages.push({
role: 'system',
@ -143,7 +144,7 @@ export class Coder {
if (code_return.interrupted && !code_return.timedout)
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({
role: 'assistant',
@ -219,7 +220,7 @@ export class Coder {
formatOutput(bot) {
if (bot.interrupt_code && !this.timedout) return '';
let output = bot.output;
const MAX_OUT = 1000;
const MAX_OUT = 500;
if (output.length > MAX_OUT) {
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)}`;

View file

@ -26,7 +26,7 @@ export const actionsList = [
perform: async function (agent) {
if (!settings.allow_insecure_coding)
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.',
perform: async function (agent) {
agent.history.clear();
@ -84,7 +84,7 @@ export const actionsList = [
},
{
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: {
'player_name': '(string) The name of the player to follow.',
'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.",
perform: function (agent) {
let bot = agent.bot;

View file

@ -29,8 +29,8 @@ export class History {
}
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.
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`;
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 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();
if (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);
* 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));
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) {
let pos = block.position;
let movements = new pf.Movements(bot);
@ -437,7 +432,18 @@ export async function breakBlockAt(bot, x, y, z) {
bot.pathfinder.setMovements(movements);
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);
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;
}

View file

@ -6,14 +6,14 @@
[
{"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": "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... !blocks"},
{"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)"}
],
@ -77,8 +77,13 @@
],
[
{"role": "user", "content": "brung00: build a house"},
{"role": "assistant", "content": "Sure, I'll try to build a house where I am. !newAction"}
{"role": "user", "content": "poppy: build a cobblestone house"},
{"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 {
constructor(select_num=3) {
constructor(select_num=2) {
this.examples = [];
this.select_num = select_num;
}

View file

@ -20,14 +20,28 @@ else {
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 res = null;
try {
console.log('Awaiting openai api response...')
console.log('Awaiting openai api response...');
let completion = await openai.chat.completions.create({
model: 'gpt-3.5-turbo',
messages: messages,
@ -35,13 +49,12 @@ export async function sendRequest(turns, systemMessage, stop_seq='***') {
});
if (completion.choices[0].finish_reason == 'length')
throw new Error('Context length exceeded');
console.log('Received.')
res = completion.choices[0].message.content;
}
catch (err) {
if ((err.message == 'Context length exceeded' || err.code == 'context_length_exceeded') && turns.length > 1) {
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 {
console.log(err);
res = 'My brain disconnected, try again.';