Memory refinement
This commit is contained in:
57
src/llm.ts
57
src/llm.ts
@@ -1,4 +1,4 @@
|
||||
import {snakeCase} from '@ztimson/utils';
|
||||
import {clean, snakeCase} from '@ztimson/utils';
|
||||
import {AbortablePromise, Ai} from './ai.ts';
|
||||
import {Anthropic} from './antrhopic.ts';
|
||||
import {OpenAi} from './open-ai.ts';
|
||||
@@ -132,7 +132,7 @@ class LLM {
|
||||
return {
|
||||
name: toolName,
|
||||
description: `${a.delegate ? 'Delegate to ' : ''}Subagent: ${a.description || a.name}`,
|
||||
args: <any>({
|
||||
args: clean<any>({
|
||||
context: !a.delegate ? {type: 'string', description: 'Summary of related messages, samples, files, etc...', required: true} : undefined,
|
||||
instructions: {type: 'string', description: 'Detailed instructions for subagent to complete', required: true},
|
||||
}),
|
||||
@@ -143,8 +143,6 @@ class LLM {
|
||||
.map(name => allAgents.find(x => x.name === name))
|
||||
.filter((x): x is Agent => !!x && x.name !== a.name);
|
||||
|
||||
// Delegate continues the SAME live conversation - no new user turn needed,
|
||||
// `history` is always current (shared, mutated in place) by the time this runs
|
||||
const q = a.delegate ? '' : `${args.instructions}${args.context ? `\n\n<context>${args.context}</context>` : ''}`;
|
||||
|
||||
const request = this.ask(q, {
|
||||
@@ -218,7 +216,7 @@ ${a.system}`,
|
||||
if(!skills?.length) return {prompt: '', tools: []};
|
||||
const list = skills.map(s => `- ${s.name}: ${s.description}`).join('\n');
|
||||
return {
|
||||
prompt: `You have access to the following skill documents, use \`read_skill\` to access them:\n${list}`,
|
||||
prompt: `You have access to the following skill documents, whenever there is overlap between a question and a skill file, use \`skill_read\` to get instructions and background knowledge:\n${list}`,
|
||||
tools: [{
|
||||
name: 'skill_read',
|
||||
description: 'Read the full content of a skill/knowledge document',
|
||||
@@ -318,19 +316,30 @@ ${a.system}`,
|
||||
} else listed.push(r);
|
||||
}
|
||||
|
||||
prompts.unshift(`You have access to the following memory files:
|
||||
${mems.map(m => `- ${m.name}: ${m.description}`).join('\n')}
|
||||
prompts.unshift(`You have a background memory process which has prefetched relevant information${mem.update ? ' and will create new memories from this conversation' : ''} for you
|
||||
Assume it is perfect and never mention this process to anyone ever
|
||||
Always use your memories to craft a personalized response, they contain links / [[wiki links]] which you use navigate between them
|
||||
${mem.tool ? `You can access memory files via the \`memory_search\` and \`memory_recall\` tools
|
||||
When you need information about the user, \`memory_recall\` \`People/User\` before asking (fetch if not included bellow)
|
||||
When you need information not provided, attempt 1-3 \`memory_search\` calls with unique queries before asking` : ''}
|
||||
|
||||
${preloaded.length ? `
|
||||
Relevant memories have been preloaded:
|
||||
${preloaded.map(r => `
|
||||
**${r.name}**
|
||||
${r.description}
|
||||
Prefetched Memories (Most relevant first):
|
||||
|
||||
${preloaded.map(r => `Memory: ${r.name}
|
||||
Description: ${r.description}
|
||||
Linked: ${[r.links, ...r.backlinks].join(', ')}
|
||||
\`\`\`
|
||||
${r.content}
|
||||
`).join('\n---\n')}
|
||||
` : ''}${listed.length ? `
|
||||
Additional relevant memories (use \`memory_recall\`):
|
||||
${listed.map(r => r.name).join(', ')}
|
||||
` : ''}`.trim());
|
||||
\`\`\``).join('\n\n')}` : ''}
|
||||
|
||||
${mem.tool && listed.length ? listed.map(r => `Memory: ${r.name}
|
||||
Description: ${r.description}
|
||||
Linked: ${[r.links, ...r.backlinks].join(', ')}
|
||||
<!-- Truncated -->`).join('\n\n') : ''}
|
||||
|
||||
${mem.tool ? `Full memory list:
|
||||
${mems.map(m => `- ${m.name}: ${m.description}`).join('\n')}` : ''}`.trim())
|
||||
}
|
||||
if(mem.tool) tools.push(this.memoryManager.tools.read(mem.memory));
|
||||
}
|
||||
@@ -374,14 +383,6 @@ ${listed.map(r => r.name).join(', ')}
|
||||
return Object.assign(promise, {abort});
|
||||
}
|
||||
|
||||
/**
|
||||
* Digest full conversation history into memory documents.
|
||||
* Call on session end to persist the conversation.
|
||||
*/
|
||||
async updateMemory(history: LLMMessage[], memories: Memory[] | MemoryCache, options: LLMRequest = {}): Promise<Memory[]> {
|
||||
return this.memoryManager.memorize(history, memories, {model: this.defaultModel, ...options});
|
||||
}
|
||||
|
||||
/**
|
||||
* Compress chat history to reduce context size
|
||||
* @param {LLMMessage[]} history Chatlog that will be compressed
|
||||
@@ -561,6 +562,14 @@ ${listed.map(r => r.name).join(', ')}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Digest full conversation history into memory documents.
|
||||
* Call on session end to persist the conversation.
|
||||
*/
|
||||
async memorize(history: LLMMessage[], memories: Memory[] | MemoryCache, options: LLMRequest = {}): Promise<Memory[]> {
|
||||
return this.memoryManager.memorize(history, memories, {model: this.defaultModel, ...options});
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a summary of some text
|
||||
* @param {string} text Text to summarize
|
||||
|
||||
Reference in New Issue
Block a user