mirror of
https://github.com/kolbytn/mindcraft.git
synced 2025-07-01 14:15:18 +02:00
refactored examples/startup
This commit is contained in:
parent
193f794f3d
commit
2f4ecfada3
7 changed files with 123 additions and 119 deletions
|
@ -1,26 +1,31 @@
|
|||
import { initBot } from '../utils/mcdata.js';
|
||||
import { sendRequest } from '../utils/gpt.js';
|
||||
import { History } from './history.js';
|
||||
import { Examples } from './examples.js';
|
||||
import { Coder } from './coder.js';
|
||||
import { containsCommand, commandExists, executeCommand } from './commands.js';
|
||||
import { Events } from './events.js';
|
||||
|
||||
|
||||
export class Agent {
|
||||
constructor(name, profile=null, init_message=null) {
|
||||
async start(name, profile=null, init_message=null) {
|
||||
this.name = name;
|
||||
this.bot = initBot(name);
|
||||
this.examples = new Examples();
|
||||
this.history = new History(this);
|
||||
this.coder = new Coder(this);
|
||||
|
||||
this.history.load(profile);
|
||||
await this.examples.load('./src/examples.json');
|
||||
await this.coder.load();
|
||||
|
||||
this.bot = initBot(name);
|
||||
|
||||
this.events = new Events(this, this.history.events)
|
||||
|
||||
this.bot.on('login', async () => {
|
||||
await this.history.loadExamples();
|
||||
|
||||
console.log(`${this.name} logged in.`);
|
||||
this.coder.clear();
|
||||
|
||||
const ignore_messages = [
|
||||
"Set own game mode to",
|
||||
|
@ -76,7 +81,8 @@ export class Agent {
|
|||
}
|
||||
|
||||
for (let i=0; i<5; i++) {
|
||||
let res = await sendRequest(this.history.getHistory(), this.history.getSystemMessage());
|
||||
let history = await this.history.getHistory(this.examples);
|
||||
let res = await sendRequest(history, this.history.getSystemMessage());
|
||||
this.history.add(this.name, res);
|
||||
|
||||
let command_name = containsCommand(res);
|
||||
|
@ -85,6 +91,7 @@ export class Agent {
|
|||
console.log('Command message:', res);
|
||||
if (!commandExists(command_name)) {
|
||||
this.history.add('system', `Command ${command_name} does not exist. Use !newAction to perform custom actions.`);
|
||||
console.log('Agent hallucinated command:', command_name)
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { writeFile, readFile, mkdirSync } from 'fs';
|
||||
import { sendRequest, embed, cosineSimilarity } from '../utils/gpt.js';
|
||||
import { stringifyTurns } from '../utils/text.js';
|
||||
import { sendRequest } from '../utils/gpt.js';
|
||||
import { getSkillDocs } from './skill-library.js';
|
||||
import { Examples } from './examples.js';
|
||||
|
||||
|
||||
export class Coder {
|
||||
|
@ -11,13 +11,14 @@ export class Coder {
|
|||
this.current_code = '';
|
||||
this.file_counter = 0;
|
||||
this.fp = '/bots/'+agent.name+'/action-code/';
|
||||
this.agent.bot.interrupt_code = false;
|
||||
this.executing = false;
|
||||
this.agent.bot.output = '';
|
||||
this.code_template = '';
|
||||
this.timedout = false;
|
||||
this.fewshot = 3;
|
||||
this.examples = [];
|
||||
}
|
||||
|
||||
async load() {
|
||||
this.examples = new Examples();
|
||||
await this.examples.load('./src/examples_coder.json');
|
||||
|
||||
readFile('./bots/template.js', 'utf8', (err, data) => {
|
||||
if (err) throw err;
|
||||
|
@ -62,7 +63,7 @@ export class Coder {
|
|||
|
||||
system_message += "\n\nExamples:\nUser zZZn98: come here \nAssistant: I am going to navigate to zZZn98. ```\nawait skills.goToPlayer(bot, 'zZZn98');```\nSystem: Code execution finished successfully.\nAssistant: Done.";
|
||||
|
||||
let messages = agent_history.getHistory(false);
|
||||
let messages = await agent_history.getHistory(this.examples);
|
||||
|
||||
let code_return = null;
|
||||
let failures = 0;
|
||||
|
|
|
@ -18,7 +18,7 @@ const argRegex = /(?:"[^"]*"|'[^']*'|[^,])+/g;
|
|||
export function containsCommand(message) {
|
||||
const commandMatch = message.match(commandRegex);
|
||||
if (commandMatch)
|
||||
return commandName;
|
||||
return "!" + commandMatch[1];
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
64
src/agent/examples.js
Normal file
64
src/agent/examples.js
Normal file
|
@ -0,0 +1,64 @@
|
|||
import { readFileSync } from 'fs';
|
||||
import { embed, cosineSimilarity } from '../utils/gpt.js';
|
||||
import { stringifyTurns } from '../utils/text.js';
|
||||
|
||||
|
||||
export class Examples {
|
||||
constructor(select_num=3) {
|
||||
this.examples = [];
|
||||
this.select_num = select_num;
|
||||
}
|
||||
|
||||
async load(path) {
|
||||
let examples = [];
|
||||
try {
|
||||
const data = readFileSync(path, 'utf8');
|
||||
examples = JSON.parse(data);
|
||||
} catch (err) {
|
||||
console.error('Examples failed to load!', err);
|
||||
}
|
||||
|
||||
this.examples = [];
|
||||
for (let example of examples) {
|
||||
let messages = '';
|
||||
for (let turn of example) {
|
||||
if (turn.role != 'assistant')
|
||||
messages += turn.content.substring(turn.content.indexOf(':')+1).trim() + '\n';
|
||||
}
|
||||
messages = messages.trim();
|
||||
const embedding = await embed(messages);
|
||||
this.examples.push({'embedding': embedding, 'turns': example});
|
||||
}
|
||||
}
|
||||
|
||||
async getRelevant(turns) {
|
||||
let messages = '';
|
||||
for (let turn of turns) {
|
||||
if (turn.role != 'assistant')
|
||||
messages += turn.content.substring(turn.content.indexOf(':')+1).trim() + '\n';
|
||||
}
|
||||
messages = messages.trim();
|
||||
const embedding = await embed(messages);
|
||||
this.examples.sort((a, b) => {
|
||||
return cosineSimilarity(b.embedding, embedding) - cosineSimilarity(a.embedding, embedding);
|
||||
});
|
||||
let selected = this.examples.slice(0, this.select_num);
|
||||
return JSON.parse(JSON.stringify(selected)); // deep copy
|
||||
}
|
||||
|
||||
async createExampleMessage(turns) {
|
||||
let selected_examples = await this.getRelevant(turns);
|
||||
|
||||
console.log('selected examples:');
|
||||
for (let example of selected_examples) {
|
||||
console.log(example.turns[0])
|
||||
}
|
||||
|
||||
let msg = 'Here are some examples of how to respond:\n';
|
||||
for (let i=0; i<selected_examples.length; i++) {
|
||||
let example = selected_examples[i];
|
||||
msg += `Example ${i+1}:\n${stringifyTurns(example.turns)}\n\n`;
|
||||
}
|
||||
return [{'role': 'system', 'content': msg}];
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
import { writeFileSync, readFileSync, mkdirSync } from 'fs';
|
||||
import { getCommandDocs } from './commands.js';
|
||||
import { sendRequest, embed, cosineSimilarity } from '../utils/gpt.js';
|
||||
import { sendRequest } from '../utils/gpt.js';
|
||||
import { stringifyTurns } from '../utils/text.js';
|
||||
|
||||
|
||||
|
@ -19,21 +19,15 @@ export class History {
|
|||
|
||||
// Variables for controlling the agent's memory and knowledge
|
||||
this.max_messages = 20;
|
||||
this.fewshot = 5;
|
||||
this.examples = [];
|
||||
this.selected_examples = [];
|
||||
}
|
||||
|
||||
getHistory(include_examples=true) {
|
||||
// return deep copy of history
|
||||
async getHistory(examples=null) { // expects an Examples object
|
||||
let turns = JSON.parse(JSON.stringify(this.turns));
|
||||
if (include_examples && this.selected_examples.length > 0) {
|
||||
let example_messages = 'Here are some examples of how to respond:\n';
|
||||
for (let example of this.selected_examples) {
|
||||
example_messages += 'Example:\n' + stringifyTurns(example.turns) + '\n';
|
||||
}
|
||||
return [{'role': 'system', 'content': example_messages}].concat(turns);
|
||||
if (examples) {
|
||||
let examples_msg = await examples.createExampleMessage(turns);
|
||||
turns = examples_msg.concat(turns);
|
||||
}
|
||||
|
||||
return turns;
|
||||
}
|
||||
|
||||
|
@ -69,47 +63,6 @@ export class History {
|
|||
this.memory = await sendRequest(memory_turns, this.getSystemMessage());
|
||||
}
|
||||
|
||||
async loadExamples() {
|
||||
let examples = [];
|
||||
try {
|
||||
const data = readFileSync('./src/examples.json', 'utf8');
|
||||
examples = JSON.parse(data);
|
||||
} catch (err) {
|
||||
console.log('No history examples found.');
|
||||
}
|
||||
|
||||
this.examples = [];
|
||||
for (let example of examples) {
|
||||
let messages = '';
|
||||
for (let turn of example) {
|
||||
if (turn.role != 'assistant')
|
||||
messages += turn.content.substring(turn.content.indexOf(':')+1).trim() + '\n';
|
||||
}
|
||||
messages = messages.trim();
|
||||
const embedding = await embed(messages);
|
||||
this.examples.push({'embedding': embedding, 'turns': example});
|
||||
}
|
||||
|
||||
await this.setExamples();
|
||||
}
|
||||
|
||||
async setExamples() {
|
||||
let messages = '';
|
||||
for (let turn of this.turns) {
|
||||
if (turn.role != 'assistant')
|
||||
messages += turn.content.substring(turn.content.indexOf(':')+1).trim() + '\n';
|
||||
}
|
||||
messages = messages.trim();
|
||||
const embedding = await embed(messages);
|
||||
this.examples.sort((a, b) => {
|
||||
return cosineSimilarity(a.embedding, embedding) - cosineSimilarity(b.embedding, embedding);
|
||||
});
|
||||
this.selected_examples = this.examples.slice(-this.fewshot);
|
||||
for (let example of this.selected_examples) {
|
||||
console.log('selected example: ', example.turns[0].content);
|
||||
}
|
||||
}
|
||||
|
||||
async add(name, content) {
|
||||
let role = 'assistant';
|
||||
if (name === 'system') {
|
||||
|
@ -129,9 +82,6 @@ export class History {
|
|||
to_summarize.push(this.turns.shift());
|
||||
await this.storeMemories(to_summarize);
|
||||
}
|
||||
|
||||
if (role != 'assistant')
|
||||
await this.setExamples();
|
||||
}
|
||||
|
||||
save() {
|
||||
|
|
|
@ -1,52 +1,34 @@
|
|||
[
|
||||
{
|
||||
"conversation": [
|
||||
{"role": "user", "content": "greg: Collect 10 wood"},
|
||||
{"role": "assistant", "content": "Let me see what's nearby... !blocks"},
|
||||
{"role": "system", "content": "NEARBY_BLOCKS\n- oak_log\n- dirt\n- cobblestone"}
|
||||
],
|
||||
"coder": [
|
||||
{"role": "assistant", "content": "I see some oak logs, dirt, and cobblestone. I'll collect oak logs.\n```\n// I am going to collect 10 oak_log.\nawait skills.collectBlock(bot, 'oak_log', 10);\n```"},
|
||||
{"role": "user", "content": "Code execution finished successfully."},
|
||||
{"role": "assistant", "content": "DONE"}
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
"conversation": [
|
||||
{"role": "user", "content": "bobby: Craft a plank"},
|
||||
{"role": "assistant", "content": "Okay! !craftable"},
|
||||
{"role": "system", "content": "CRAFTABLE_ITEMS\n- spruce_planks\n- spruce_wood\n- ladder"}
|
||||
],
|
||||
"coder": [
|
||||
{"role": "assistant", "content": "```\n// I am going to craft a spruce_planks.\nawait skills.craftRecipe(bot, 'spruce_planks');\n```"},
|
||||
{"role": "user", "content": "Code execution finished successfully."},
|
||||
{"role": "assistant", "content": "DONE"}
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
"conversation": [
|
||||
{"role": "user", "content": "zZZn98: come here"}
|
||||
],
|
||||
"coder": [
|
||||
{"role": "assistant", "content": "```\n// I am going to navigate to zZZn98.\nawait skills.goToPlayer(bot, 'zZZn98');\n```"},
|
||||
{"role": "user", "content": "Code execution finished successfully."},
|
||||
{"role": "assistant", "content": "DONE"}
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
"conversation": [
|
||||
{"role": "user", "content": "maya: go to the nearest oak log"}
|
||||
],
|
||||
"coder": [
|
||||
{"role": "assistant", "content": "```\n// I am navigating to the nearest oak log.\nawait skills.goToPosition(bot, nearestOakLog.x, nearestOakLog.y, nearestOakLog.z);\n```"},
|
||||
{"role": "system", "content": "Code output:\n!!Code threw exception!! Error: ReferenceError: nearestOakLog is not defined\n Write code to fix the problem and try again."},
|
||||
{"role": "assistant", "content": "Apologies, I made an error. Let me try that again.```\n// I am navigating to the nearest oak log.\nlet position = world.getNearestBlock(bot, 'oak_log', 20);\nawait skills.goToPosition(bot, position.x, position.y, position.z);\n```"},
|
||||
{"role": "user", "content": "Code execution finished successfully."},
|
||||
{"role": "assistant", "content": "DONE"}
|
||||
]
|
||||
}
|
||||
|
||||
[
|
||||
{"role": "user", "content": "greg: Collect 10 wood"},
|
||||
{"role": "assistant", "content": "```await skills.collectBlock(bot, 'oak_log', 10);\n```"},
|
||||
{"role": "system", "content": "Successfully collected 9 wood."},
|
||||
{"role": "assistant", "content": "I collected 9 oak logs, what next?"}
|
||||
],
|
||||
[
|
||||
{"role": "user", "content": "bobby: Craft a plank"},
|
||||
{"role": "assistant", "content": "```\nawait skills.craftRecipe(bot, 'spruce_planks');\n```"},
|
||||
{"role": "system", "content": "Successfully crafted 4 spruce_planks."},
|
||||
{"role": "assistant", "content": "I crafted 4 spruce planks!"}
|
||||
],
|
||||
[
|
||||
{"role": "user", "content": "zZZn98: come here"},
|
||||
{"role": "assistant", "content": "```await skills.goToPlayer(bot, 'zZZn98');\n```"},
|
||||
{"role": "system", "content": "Code execution finished successfully."},
|
||||
{"role": "assistant", "content": "Here!"}
|
||||
],
|
||||
[
|
||||
{"role": "user", "content": "maya: go to the nearest oak log"},
|
||||
{"role": "assistant", "content": "```await skills.goToPosition(bot, nearestOakLog.x, nearestOakLog.y, nearestOakLog.z);\n```"},
|
||||
{"role": "system", "content": "Code output:\n!!Code threw exception!! Error: ReferenceError: nearestOakLog is not defined\n Write code to fix the problem and try again."},
|
||||
{"role": "assistant", "content": "Apologies, I made an error. Let me try that again.```\n// I am navigating to the nearest oak log.\nlet position = world.getNearestBlock(bot, 'oak_log', 20);\nawait skills.goToPosition(bot, position.x, position.y, position.z);\n```"},
|
||||
{"role": "system", "content": "Arrived at location."},
|
||||
{"role": "assistant", "content": "I found an oak log and I am now standing next to it. What next?"}
|
||||
],
|
||||
[
|
||||
{"role": "user", "content": "234jeb: build a little tower"},
|
||||
{"role": "assistant", "content": "```let pos = bot.entity.position;\nfor (let i = 0; i < 5; i++) {\n await skills.placeBlock(bot, 'dirt', pos.x, pos.y + i, pos.z);\n}\n```"},
|
||||
{"role": "system", "content": "Successfully placed 5 dirt."},
|
||||
{"role": "assistant", "content": "I built a little tower!"}
|
||||
]
|
||||
]
|
|
@ -20,4 +20,4 @@ const argv = yargs(args)
|
|||
}).argv
|
||||
|
||||
const name = args[0];
|
||||
new Agent(name, argv.profile, argv.init_message);
|
||||
new Agent().start(name, argv.profile, argv.init_message);
|
||||
|
|
Loading…
Add table
Reference in a new issue