mirror of
https://github.com/kolbytn/mindcraft.git
synced 2025-04-22 06:02:07 +02:00
memories init
This commit is contained in:
parent
305d233f62
commit
8b0ad55451
3 changed files with 110 additions and 5 deletions
19
agent.js
19
agent.js
|
@ -14,10 +14,13 @@ export class Agent {
|
||||||
Act human-like as if you were a typical Minecraft player, rather than an AI. Be brief in your responses, omit needless words, and do not give instructions unless asked.`;
|
Act human-like as if you were a typical Minecraft player, rather than an AI. Be brief in your responses, omit needless words, and do not give instructions unless asked.`;
|
||||||
this.system_message += getQueryDocs();
|
this.system_message += getQueryDocs();
|
||||||
this.system_message += getSkillDocs();
|
this.system_message += getSkillDocs();
|
||||||
|
this.current_system_message = this.system_message;
|
||||||
|
|
||||||
this.bot = initBot(name);
|
this.bot = initBot(name);
|
||||||
this.history = new History(this);
|
this.history = new History(this);
|
||||||
this.coder = new Coder(this);
|
this.coder = new Coder(this);
|
||||||
|
this.history.load();
|
||||||
|
this.updateSystemMessage();
|
||||||
|
|
||||||
this.bot.on('login', () => {
|
this.bot.on('login', () => {
|
||||||
this.bot.chat('Hello world! I am ' + this.name);
|
this.bot.chat('Hello world! I am ' + this.name);
|
||||||
|
@ -29,6 +32,8 @@ export class Agent {
|
||||||
console.log('received message from', username, ':', message);
|
console.log('received message from', username, ':', message);
|
||||||
|
|
||||||
this.respond(username, message);
|
this.respond(username, message);
|
||||||
|
this.history.save();
|
||||||
|
this.updateSystemMessage();
|
||||||
});
|
});
|
||||||
|
|
||||||
this.bot.on('finished_executing', () => {
|
this.bot.on('finished_executing', () => {
|
||||||
|
@ -40,10 +45,22 @@ export class Agent {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateSystemMessage() {
|
||||||
|
if (this.history.bio != '') {
|
||||||
|
this.current_system_message = this.system_message + '\n\nBio:\n' + this.history.bio;
|
||||||
|
}
|
||||||
|
if (this.history.memory != '') {
|
||||||
|
this.current_system_message = this.current_system_message + '\n\nMemories:\n' + this.history.memory;
|
||||||
|
}
|
||||||
|
if (this.history.knowledge != '') {
|
||||||
|
this.current_system_message = this.current_system_message + '\n\nKnowledge:\n' + this.history.knowledge;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async respond(username, message) {
|
async respond(username, message) {
|
||||||
this.history.add(username, message);
|
this.history.add(username, message);
|
||||||
for (let i=0; i<5; i++) {
|
for (let i=0; i<5; i++) {
|
||||||
let res = await sendRequest(this.history.getHistory(), this.system_message);
|
let res = await sendRequest(this.history.getHistory(), this.current_system_message);
|
||||||
this.history.add(this.name, res);
|
this.history.add(this.name, res);
|
||||||
let query_cmd = containsQuery(res);
|
let query_cmd = containsQuery(res);
|
||||||
if (query_cmd) { // contains query
|
if (query_cmd) { // contains query
|
||||||
|
|
|
@ -29,8 +29,13 @@ export async function sendRequest(turns, systemMessage, stop_seq='***') {
|
||||||
res = completion.choices[0].message.content;
|
res = completion.choices[0].message.content;
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
console.log(err);
|
if (err.code == 'context_length_exceeded' && turns.length > 1) {
|
||||||
res = 'My brain disconnected, try again.';
|
console.log('Context length exceeded, trying again with shorter context.');
|
||||||
|
return await sendRequest(turns.slice(1), systemMessage, stop_seq);
|
||||||
|
} else {
|
||||||
|
console.log(err);
|
||||||
|
res = 'My brain disconnected, try again.';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
import { writeFileSync, readFileSync, mkdirSync } from 'fs';
|
||||||
|
import { sendRequest } from './gpt.js';
|
||||||
|
|
||||||
|
|
||||||
let history_examples = [
|
let history_examples = [
|
||||||
{'role': 'user', 'content': 'miner_32: Hey! What are you up to?'},
|
{'role': 'user', 'content': 'miner_32: Hey! What are you up to?'},
|
||||||
{'role': 'assistant', 'content': 'Nothing much miner_32, what do you need?'},
|
{'role': 'assistant', 'content': 'Nothing much miner_32, what do you need?'},
|
||||||
|
@ -35,15 +39,52 @@ let history_examples = [
|
||||||
|
|
||||||
export class History {
|
export class History {
|
||||||
constructor(agent) {
|
constructor(agent) {
|
||||||
this.agent = agent;
|
this.name = agent.name;
|
||||||
this.turns = history_examples;
|
this.turns = history_examples;
|
||||||
|
|
||||||
|
// These define an agent's long term memory
|
||||||
|
this.bio = 'Your personality is friendly. Your goal is to help.';
|
||||||
|
this.memory = '';
|
||||||
|
this.knowledge = '';
|
||||||
|
this.num_saved_turns = 0;
|
||||||
|
|
||||||
|
// Variables for controlling how often we summarize the agent's memory and knowledge
|
||||||
|
this.max_messages = 20;
|
||||||
|
this.save_size = 10;
|
||||||
|
this.save_step = 7;
|
||||||
}
|
}
|
||||||
|
|
||||||
getHistory() {
|
getHistory() {
|
||||||
return this.turns;
|
return this.turns;
|
||||||
}
|
}
|
||||||
|
|
||||||
add(name, content) {
|
async storeMemories(turns) {
|
||||||
|
const memory_message = 'You are a minecraft bot. ' + this.bio + '\n\nCurrent Memory:\n' + this.memory;
|
||||||
|
let memory_prompt = 'Update your memory with the following conversation. Include only conversational details about other players that you may need to remember for later. Your output should be a short paragraph summarizing what you have experienced.\n';
|
||||||
|
for (let turn of turns) {
|
||||||
|
if (turn.role === 'user') {
|
||||||
|
memory_prompt += `\n${turn.content}`;
|
||||||
|
} else {
|
||||||
|
memory_prompt += `\nYou: ${turn.content}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let memory_turns = [{'role': 'user', 'content': memory_prompt}]
|
||||||
|
this.memory = await sendRequest(memory_turns, memory_message);
|
||||||
|
|
||||||
|
const knowledge_message = 'You are a minecraft bot. ' + this.bio + '\n\nCurrent Knowledge: ' + this.knowledge;
|
||||||
|
let knowledge_prompt = 'Update your current knowledge with the following conversation. Include only knowledge you have gained about how to interact with the world and execute actions that you may need to remember for later. Your output should be a short paragraph summarizing what you have learned.\n';
|
||||||
|
for (let turn of turns) {
|
||||||
|
if (turn.role === 'user') {
|
||||||
|
knowledge_prompt += `\n${turn.content}`;
|
||||||
|
} else {
|
||||||
|
knowledge_prompt += `\nYou: ${turn.content}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let knowledge_turns = [{'role': 'user', 'content': knowledge_prompt}]
|
||||||
|
this.knowledge = await sendRequest(knowledge_turns, knowledge_message);
|
||||||
|
}
|
||||||
|
|
||||||
|
async add(name, content) {
|
||||||
let role = 'assistant';
|
let role = 'assistant';
|
||||||
if (name === 'system') {
|
if (name === 'system') {
|
||||||
role = 'system';
|
role = 'system';
|
||||||
|
@ -53,5 +94,47 @@ export class History {
|
||||||
content = `${name}: ${content}`;
|
content = `${name}: ${content}`;
|
||||||
}
|
}
|
||||||
this.turns.push({role, content});
|
this.turns.push({role, content});
|
||||||
|
|
||||||
|
// Summarize older turns into memory
|
||||||
|
if (this.turns.length >= this.max_messages) {
|
||||||
|
// Don't summarize the examples
|
||||||
|
if (this.num_saved_turns + this.save_step >= history_examples.length &&
|
||||||
|
this.num_saved_turns < history_examples.length) {
|
||||||
|
await this.storeMemories(
|
||||||
|
this.turns.slice(history_examples.length - this.num_saved_turns, this.save_size)
|
||||||
|
);
|
||||||
|
} else if (this.num_saved_turns >= history_examples.length) {
|
||||||
|
await this.storeMemories(this.turns.slice(0, this.save_size));
|
||||||
|
}
|
||||||
|
this.turns = this.turns.slice(this.save_step);
|
||||||
|
this.num_saved_turns += this.save_step;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
save() {
|
||||||
|
// save history object to json file
|
||||||
|
mkdirSync('bots', { recursive: true });
|
||||||
|
const data = JSON.stringify(this, null, 4);
|
||||||
|
writeFileSync('bots/' + this.name + '.json', data, (err) => {
|
||||||
|
if (err) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
console.log("JSON data is saved.");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
load() {
|
||||||
|
try {
|
||||||
|
// load history object from json file
|
||||||
|
const data = readFileSync('bots/' + this.name + '.json', 'utf8');
|
||||||
|
const obj = JSON.parse(data);
|
||||||
|
this.turns = obj.turns;
|
||||||
|
this.bio = obj.bio;
|
||||||
|
this.memory = obj.memory;
|
||||||
|
this.knowledge = obj.knowledge;
|
||||||
|
this.num_saved_turns = obj.num_saved_turns;
|
||||||
|
} catch (err) {
|
||||||
|
console.log('No history file found for ' + this.name + '.');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Add table
Reference in a new issue