2024-10-10 22:15:55 -05:00
|
|
|
import { writeFileSync, readFileSync, mkdirSync } from 'fs';
|
2024-03-05 12:05:46 -08:00
|
|
|
import { NPCData } from './npc/data.js';
|
2024-10-10 22:15:55 -05:00
|
|
|
import settings from '../../settings.js';
|
2023-11-12 14:53:23 -08:00
|
|
|
|
|
|
|
|
2023-11-07 09:44:56 -06:00
|
|
|
export class History {
|
2023-12-21 20:42:01 -07:00
|
|
|
constructor(agent) {
|
2024-02-25 14:13:32 -06:00
|
|
|
this.agent = agent;
|
2023-11-12 14:53:23 -08:00
|
|
|
this.name = agent.name;
|
2024-02-25 14:13:32 -06:00
|
|
|
this.memory_fp = `./bots/${this.name}/memory.json`;
|
2024-10-10 22:15:55 -05:00
|
|
|
this.full_history_fp = undefined;
|
|
|
|
|
|
|
|
mkdirSync(`./bots/${this.name}/histories`, { recursive: true });
|
|
|
|
|
2023-11-15 13:18:38 -08:00
|
|
|
this.turns = [];
|
2023-11-12 14:53:23 -08:00
|
|
|
|
2024-10-10 22:15:55 -05:00
|
|
|
// Natural language memory as a summary of recent messages + previous memory
|
2023-11-12 14:53:23 -08:00
|
|
|
this.memory = '';
|
|
|
|
|
2024-10-10 22:15:55 -05:00
|
|
|
// Maximum number of messages to keep in context before saving chunk to memory
|
|
|
|
this.max_messages = settings.max_messages;
|
|
|
|
|
|
|
|
// Number of messages to remove from current history and save into memory
|
|
|
|
this.summary_chunk_size = 5;
|
|
|
|
// chunking reduces expensive calls to promptMemSaving and appendFullHistory
|
2023-11-07 09:44:56 -06:00
|
|
|
}
|
2023-08-15 23:39:02 -07:00
|
|
|
|
2024-02-25 14:13:32 -06:00
|
|
|
getHistory() { // expects an Examples object
|
|
|
|
return JSON.parse(JSON.stringify(this.turns));
|
2023-11-13 20:33:34 -08:00
|
|
|
}
|
2023-11-12 14:53:23 -08:00
|
|
|
|
2024-10-10 22:15:55 -05:00
|
|
|
async summarizeMemories(turns) {
|
2024-02-25 14:13:32 -06:00
|
|
|
console.log("Storing memories...");
|
2024-10-10 22:15:55 -05:00
|
|
|
this.memory = await this.agent.prompter.promptMemSaving(turns);
|
2024-10-11 14:49:40 -05:00
|
|
|
|
|
|
|
if (this.memory.length > 500) {
|
|
|
|
this.memory = this.memory.slice(0, 500);
|
|
|
|
this.memory += '...(Memory truncated to 500 chars. Compress it more next time)';
|
|
|
|
}
|
|
|
|
|
2024-02-25 14:13:32 -06:00
|
|
|
console.log("Memory updated to: ", this.memory);
|
2023-11-15 13:18:38 -08:00
|
|
|
}
|
|
|
|
|
2024-10-10 22:15:55 -05:00
|
|
|
appendFullHistory(to_store) {
|
|
|
|
if (this.full_history_fp === undefined) {
|
|
|
|
const string_timestamp = new Date().toLocaleString().replace(/[/:]/g, '-').replace(/ /g, '').replace(/,/g, '_');
|
|
|
|
this.full_history_fp = `./bots/${this.name}/histories/${string_timestamp}.json`;
|
|
|
|
writeFileSync(this.full_history_fp, '[]', 'utf8');
|
|
|
|
}
|
|
|
|
try {
|
|
|
|
const data = readFileSync(this.full_history_fp, 'utf8');
|
|
|
|
let full_history = JSON.parse(data);
|
|
|
|
full_history.push(...to_store);
|
|
|
|
writeFileSync(this.full_history_fp, JSON.stringify(full_history, null, 4), 'utf8');
|
|
|
|
} catch (err) {
|
|
|
|
console.error(`Error reading ${this.name}'s full history file: ${err.message}`);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-11-12 14:53:23 -08:00
|
|
|
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';
|
|
|
|
}
|
2023-11-13 20:33:34 -08:00
|
|
|
else if (name !== this.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
|
|
|
|
|
|
|
if (this.turns.length >= this.max_messages) {
|
2024-10-10 22:15:55 -05:00
|
|
|
let chunk = this.turns.splice(0, this.summary_chunk_size);
|
2024-10-11 14:49:40 -05:00
|
|
|
while (this.turns.length > 0 && this.turns[0].role === 'assistant')
|
|
|
|
chunk.push(this.turns.shift()); // remove until turns starts with system/user message
|
|
|
|
|
2024-10-10 22:15:55 -05:00
|
|
|
await this.summarizeMemories(chunk);
|
|
|
|
this.appendFullHistory(chunk);
|
2023-11-12 14:53:23 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-05-10 12:18:47 -05:00
|
|
|
save() {
|
2023-11-12 14:53:23 -08:00
|
|
|
// save history object to json file
|
2023-11-15 13:18:38 -08:00
|
|
|
let data = {
|
|
|
|
'name': this.name,
|
|
|
|
'memory': this.memory,
|
|
|
|
'turns': this.turns
|
|
|
|
};
|
2024-03-05 12:05:46 -08:00
|
|
|
if (this.agent.npc.data !== null)
|
|
|
|
data.npc = this.agent.npc.data.toObject();
|
2024-04-20 22:18:26 -05:00
|
|
|
const modes = this.agent.bot.modes.getJson();
|
|
|
|
if (modes !== null)
|
|
|
|
data.modes = modes;
|
2024-04-27 23:28:34 -05:00
|
|
|
const memory_bank = this.agent.memory_bank.getJson();
|
|
|
|
if (memory_bank !== null)
|
|
|
|
data.memory_bank = memory_bank;
|
2024-05-08 23:59:44 -05:00
|
|
|
if (this.agent.self_prompter.on) {
|
|
|
|
data.self_prompt = this.agent.self_prompter.prompt;
|
|
|
|
}
|
2023-11-15 13:18:38 -08:00
|
|
|
const json_data = JSON.stringify(data, null, 4);
|
2024-02-25 14:13:32 -06:00
|
|
|
writeFileSync(this.memory_fp, json_data, (err) => {
|
2023-11-12 14:53:23 -08:00
|
|
|
if (err) {
|
|
|
|
throw err;
|
|
|
|
}
|
|
|
|
console.log("JSON data is saved.");
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2024-02-25 14:13:32 -06:00
|
|
|
load() {
|
2023-11-12 14:53:23 -08:00
|
|
|
try {
|
|
|
|
// load history object from json file
|
2024-02-25 14:13:32 -06:00
|
|
|
const data = readFileSync(this.memory_fp, 'utf8');
|
2023-11-12 14:53:23 -08:00
|
|
|
const obj = JSON.parse(data);
|
|
|
|
this.memory = obj.memory;
|
2024-03-05 12:05:46 -08:00
|
|
|
this.agent.npc.data = NPCData.fromObject(obj.npc);
|
2024-04-20 22:18:26 -05:00
|
|
|
if (obj.modes)
|
|
|
|
this.agent.bot.modes.loadJson(obj.modes);
|
2024-04-27 23:28:34 -05:00
|
|
|
if (obj.memory_bank)
|
|
|
|
this.agent.memory_bank.loadJson(obj.memory_bank);
|
2023-12-04 23:26:21 -08:00
|
|
|
this.turns = obj.turns;
|
2024-05-08 23:59:44 -05:00
|
|
|
return obj;
|
2023-11-12 14:53:23 -08:00
|
|
|
} catch (err) {
|
2024-04-20 22:18:26 -05:00
|
|
|
console.error(`Error reading ${this.name}'s memory file: ${err.message}`);
|
2023-11-12 14:53:23 -08:00
|
|
|
}
|
2024-05-08 23:59:44 -05:00
|
|
|
return null;
|
2023-08-17 00:00:57 -07:00
|
|
|
}
|
2024-01-27 19:16:54 -06:00
|
|
|
|
|
|
|
clear() {
|
|
|
|
this.turns = [];
|
|
|
|
this.memory = '';
|
|
|
|
}
|
2023-11-07 09:44:56 -06:00
|
|
|
}
|