updatememory awaits full result
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ztimson/ai-utils",
|
"name": "@ztimson/ai-utils",
|
||||||
"version": "1.2.4",
|
"version": "1.2.5",
|
||||||
"description": "AI Utility library",
|
"description": "AI Utility library",
|
||||||
"author": "Zak Timson",
|
"author": "Zak Timson",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@@ -229,8 +229,8 @@ ${r.content}
|
|||||||
* Digest full conversation history into memory documents.
|
* Digest full conversation history into memory documents.
|
||||||
* Call on session end to persist the conversation.
|
* Call on session end to persist the conversation.
|
||||||
*/
|
*/
|
||||||
async updateMemory(history: LLMMessage[], memories: Memory[] | MemoryCache, options: LLMRequest = {}): Promise<void> {
|
async updateMemory(history: LLMMessage[], memories: Memory[] | MemoryCache, options: LLMRequest = {}): Promise<Memory[]> {
|
||||||
await this.memoryManager.memorize(history, memories, {model: this.defaultModel, ...options});
|
return this.memoryManager.memorize(history, memories, {model: this.defaultModel, ...options});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -355,68 +355,56 @@ ${conversation}`,
|
|||||||
return ordered.map(n => mem.find(m => m.name === n)!).filter(Boolean);
|
return ordered.map(n => mem.find(m => m.name === n)!).filter(Boolean);
|
||||||
}
|
}
|
||||||
|
|
||||||
async memorize(history: LLMMessage[], memories: Memory[] | MemoryCache, options: LLMRequest): Promise<void> {
|
async memorize(history: LLMMessage[], memories: Memory[] | MemoryCache, options: LLMRequest): Promise<Memory[]> {
|
||||||
const conversation = history
|
const conversation = history
|
||||||
.filter(h => h.role === 'user' || h.role === 'assistant')
|
.filter(h => h.role === 'user' || h.role === 'assistant')
|
||||||
.map(h => `[${h.role}]: ${h.content}`).join('\n\n').trim();
|
.map(h => `[${h.role}]: ${h.content}`).join('\n\n').trim();
|
||||||
|
if(!conversation) return [];
|
||||||
if (!conversation) return;
|
|
||||||
|
|
||||||
const trackingId = `${Date.now()}_${Math.random()}`;
|
|
||||||
|
|
||||||
// Create and insert temp memory immediately
|
// Create and insert temp memory immediately
|
||||||
|
const trackingId = `${Date.now()}_${Math.random()}`;
|
||||||
const tempMemory = await this.createTempMemory(conversation);
|
const tempMemory = await this.createTempMemory(conversation);
|
||||||
const mem = memories instanceof MemoryCache ? memories.memories : memories;
|
const mem = memories instanceof MemoryCache ? memories.memories : memories;
|
||||||
mem.push(tempMemory);
|
mem.push(tempMemory);
|
||||||
|
if (memories instanceof MemoryCache) memories.rebuild();
|
||||||
if (memories instanceof MemoryCache) {
|
|
||||||
memories.rebuild();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.pendingMemorizations.set(trackingId, {
|
this.pendingMemorizations.set(trackingId, {
|
||||||
memories,
|
memories,
|
||||||
tempMemoryName: tempMemory.name,
|
tempMemoryName: tempMemory.name,
|
||||||
timestamp: Date.now(),
|
timestamp: Date.now(),
|
||||||
});
|
});
|
||||||
|
|
||||||
this._memorizeBackground(conversation, memories, options, trackingId)
|
try {
|
||||||
.catch(err => {
|
await this._memorizeBackground(conversation, memories, options);
|
||||||
console.error('[memorize] Background memorization failed:', err);
|
// Return the final memories (excluding temp ones)
|
||||||
})
|
const finalMem = memories instanceof MemoryCache ? memories.memories : memories;
|
||||||
.finally(() => {
|
return finalMem.filter(m => !m.name.startsWith('_temp_'));
|
||||||
// Remove temp memory from the exact same memory array/cache
|
} catch (err) {
|
||||||
const pending = this.pendingMemorizations.get(trackingId);
|
throw err;
|
||||||
if (pending) {
|
} finally {
|
||||||
const cleanMem = pending.memories instanceof MemoryCache
|
// Remove temp memory from the exact same memory array/cache
|
||||||
? pending.memories.memories
|
const pending = this.pendingMemorizations.get(trackingId);
|
||||||
: pending.memories;
|
if (pending) {
|
||||||
const idx = cleanMem.findIndex(m => m.name === pending.tempMemoryName);
|
const cleanMem = pending.memories instanceof MemoryCache
|
||||||
if (idx !== -1) {
|
? pending.memories.memories
|
||||||
cleanMem.splice(idx, 1);
|
: pending.memories;
|
||||||
console.log(`[memorize] Removed temp memory: ${pending.tempMemoryName}`);
|
const idx = cleanMem.findIndex(m => m.name === pending.tempMemoryName);
|
||||||
}
|
if (idx !== -1) {
|
||||||
if (pending.memories instanceof MemoryCache) {
|
cleanMem.splice(idx, 1);
|
||||||
pending.memories.rebuild();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
this.pendingMemorizations.delete(trackingId);
|
if (pending.memories instanceof MemoryCache) {
|
||||||
});
|
pending.memories.rebuild();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.pendingMemorizations.delete(trackingId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _memorizeBackground(conversation: string, memories: Memory[] | MemoryCache, options: LLMRequest, trackingId: string): Promise<void> {
|
private async _memorizeBackground(conversation: string, memories: Memory[] | MemoryCache, options: LLMRequest): Promise<void> {
|
||||||
const mem = memories instanceof MemoryCache ? memories.memories : memories;
|
const mem = memories instanceof MemoryCache ? memories.memories : memories;
|
||||||
const monday = getWeekMonday();
|
const monday = getWeekMonday();
|
||||||
const sunday = getWeekSunday(monday);
|
const sunday = getWeekSunday(monday);
|
||||||
const weekKey = monday;
|
const buckets = await this.factAgent(conversation, mem, options, monday);
|
||||||
|
if(!buckets.length) return;
|
||||||
console.log('[memorize] Starting fact extraction...');
|
|
||||||
const buckets = await this.factAgent(conversation, mem, options, weekKey);
|
|
||||||
console.log(`[memorize] Extracted ${buckets.length} buckets:`, buckets);
|
|
||||||
|
|
||||||
if (!buckets.length) {
|
|
||||||
console.log('[memorize] No facts extracted, exiting');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const runDocAgent = (node: Memory, bucket: FactBucket, embedding?: number[], week?: {monday: string, sunday: string}) => {
|
const runDocAgent = (node: Memory, bucket: FactBucket, embedding?: number[], week?: {monday: string, sunday: string}) => {
|
||||||
if (memories instanceof MemoryCache) {
|
if (memories instanceof MemoryCache) {
|
||||||
@@ -443,11 +431,8 @@ ${conversation}`,
|
|||||||
await runDocAgent(node, bucket, embedding, week);
|
await runDocAgent(node, bucket, embedding, week);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
if (memories instanceof MemoryCache) {
|
if(memories instanceof MemoryCache)
|
||||||
memories.rebuild();
|
memories.rebuild();
|
||||||
}
|
|
||||||
|
|
||||||
console.log('[memorize] Completed successfully');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private buildHeader(node: Memory, week?: {monday: string, sunday: string}, links: string[] = [], backlinks: string[] = []): string {
|
private buildHeader(node: Memory, week?: {monday: string, sunday: string}, links: string[] = [], backlinks: string[] = []): string {
|
||||||
@@ -587,9 +572,6 @@ ${node.content || '(empty — this is a new document)'}
|
|||||||
|
|
||||||
private async factAgent(conversation: string, memories: Memory[], options: LLMRequest, weekKey: string): Promise<FactBucket[]> {
|
private async factAgent(conversation: string, memories: Memory[], options: LLMRequest, weekKey: string): Promise<FactBucket[]> {
|
||||||
const buckets: FactBucket[] = [];
|
const buckets: FactBucket[] = [];
|
||||||
|
|
||||||
console.log('[factAgent] Starting extraction...');
|
|
||||||
|
|
||||||
await this.llm.ask(conversation, {
|
await this.llm.ask(conversation, {
|
||||||
model: options.model,
|
model: options.model,
|
||||||
temperature: 0.2,
|
temperature: 0.2,
|
||||||
@@ -618,7 +600,6 @@ ${this.listNodes(memories).map(n => `- ${n.name}: ${n.description}`).join('\n')
|
|||||||
create_new: {type: 'boolean', description: 'True if this is a new node that doesn\'t exist yet', required: true},
|
create_new: {type: 'boolean', description: 'True if this is a new node that doesn\'t exist yet', required: true},
|
||||||
},
|
},
|
||||||
fn: (args: any) => {
|
fn: (args: any) => {
|
||||||
console.log('[factAgent] Tool called with:', args);
|
|
||||||
const subject = args.destination.trim().toLowerCase() === 'journal'
|
const subject = args.destination.trim().toLowerCase() === 'journal'
|
||||||
? `Journal/${weekKey}`
|
? `Journal/${weekKey}`
|
||||||
: args.destination;
|
: args.destination;
|
||||||
@@ -631,8 +612,6 @@ ${this.listNodes(memories).map(n => `- ${n.name}: ${n.description}`).join('\n')
|
|||||||
},
|
},
|
||||||
}],
|
}],
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log(`[factAgent] Extracted ${buckets.length} buckets:`, buckets);
|
|
||||||
return buckets;
|
return buckets;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user