2023-11-12 14:53:23 -08:00
import { writeFileSync , readFileSync , mkdirSync } from 'fs' ;
import { sendRequest } from './gpt.js' ;
2023-11-07 12:00:55 -06:00
let history _examples = [
{ 'role' : 'user' , 'content' : 'miner_32: Hey! What are you up to?' } ,
2023-11-07 09:44:56 -06:00
{ 'role' : 'assistant' , 'content' : 'Nothing much miner_32, what do you need?' } ,
2023-11-07 22:23:42 -06:00
{ 'role' : 'user' , 'content' : 'grombo_Xx: What do you see?' } ,
2023-11-07 09:44:56 -06:00
{ 'role' : 'assistant' , 'content' : 'Let me see... !blocks' } ,
2023-11-12 13:57:22 -06:00
{ 'role' : 'system' , 'content' : 'NEARBY_BLOCKS\n- oak_log\n- dirt\n- cobblestone' } ,
2023-11-07 09:44:56 -06:00
{ 'role' : 'assistant' , 'content' : 'I see some oak logs, dirt, and cobblestone.' } ,
2023-11-07 12:00:55 -06:00
{ 'role' : 'user' , 'content' : 'zZZn98: come here' } ,
2023-11-12 23:19:58 -06:00
{ 'role' : 'assistant' , 'content' : '```// I am going to navigate to zZZn98.\nawait skills.goToPlayer(bot, "zZZn98");```' } ,
2023-11-12 13:57:22 -06:00
{ 'role' : 'system' , 'content' : 'Code execution finished successfully.' } ,
{ 'role' : 'assistant' , 'content' : 'Here!' } ,
2023-11-07 09:44:56 -06:00
2023-11-07 12:00:55 -06:00
{ 'role' : 'user' , 'content' : 'hanky: collect some sand for me please' } ,
2023-11-07 09:44:56 -06:00
{ 'role' : 'assistant' , 'content' : ' Collecting sand ... ` ` ` // I am going to collect 3 sand and give to hanky. \n \
2023-11-12 23:19:58 -06:00
await skills . collectBlock ( bot , "sand" ) ; \ nawait skills . giveToPlayer ( bot , "sand" , "hanky" ) ; ` ` ` '},
2023-11-12 13:57:22 -06:00
{ 'role' : 'system' , 'content' : 'Code Output:\nYou have reached player hanky.\nCode execution finished successfully.' } ,
{ 'role' : 'assistant' , 'content' : 'Here!' } ,
2023-11-07 09:44:56 -06:00
2023-11-12 13:57:22 -06:00
{ 'role' : 'user' , 'content' : 'sarah_O.o: can you fly up in the air?' } ,
{ 'role' : 'assistant' , 'content' : "I can't do that." } ,
2023-11-07 09:44:56 -06:00
2023-11-07 12:00:55 -06:00
{ 'role' : 'user' , 'content' : 'hanky: kill that zombie!' } ,
2023-11-07 09:44:56 -06:00
{ 'role' : 'assistant' , 'content' : " I 'm attacking! ```//I' m going to attack the nearest zombie . \ n \
2023-11-12 23:19:58 -06:00
await skills . attackMob ( bot , 'zombie' ) ; ` ` ` "},
2023-11-12 13:57:22 -06:00
{ 'role' : 'system' , 'content' : 'Code Output:\nNo zombie nearby\nCode execution failed!' } ,
{ 'role' : 'assistant' , 'content' : 'I could not find a zombie nearby.' } ,
2023-11-07 22:23:42 -06:00
2023-11-13 00:57:20 -06:00
{ 'role' : 'user' , 'content' : 'billybob: stop' } ,
{ 'role' : 'assistant' , 'content' : '```// I am going to write empty code to stop whatever I am doing\n```' } ,
2023-11-12 13:57:22 -06:00
2023-11-07 09:44:56 -06:00
]
export class History {
constructor ( agent ) {
2023-11-12 14:53:23 -08:00
this . name = agent . name ;
2023-11-07 12:00:55 -06:00
this . turns = history _examples ;
2023-11-12 14:53:23 -08:00
// 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 ;
2023-11-07 09:44:56 -06:00
}
2023-08-15 23:39:02 -07:00
2023-11-07 09:44:56 -06:00
getHistory ( ) {
return this . turns ;
}
2023-08-15 23:39:02 -07:00
2023-11-12 14:53:23 -08:00
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 += ` \n You: ${ 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 += ` \n You: ${ turn . content } ` ;
}
}
let knowledge _turns = [ { 'role' : 'user' , 'content' : knowledge _prompt } ]
this . knowledge = await sendRequest ( knowledge _turns , knowledge _message ) ;
}
async add ( name , content ) {
2023-11-07 09:44:56 -06:00
let role = 'assistant' ;
2023-11-12 13:57:22 -06:00
if ( name === 'system' ) {
role = 'system' ;
}
else if ( name !== this . agent . name ) {
2023-11-07 09:44:56 -06:00
role = 'user' ;
2023-11-07 12:00:55 -06:00
content = ` ${ name } : ${ content } ` ;
2023-08-17 00:00:57 -07:00
}
2023-11-07 09:44:56 -06:00
this . turns . push ( { role , content } ) ;
2023-11-12 14:53:23 -08:00
// 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 + '.' ) ;
}
2023-08-17 00:00:57 -07:00
}
2023-11-07 09:44:56 -06:00
}