Skip to content

Commit 06c663c

Browse files
committed
Improved Chat with Memories
1 parent 2f0df81 commit 06c663c

File tree

3 files changed

+2458
-120
lines changed

3 files changed

+2458
-120
lines changed

dashboard/app/chat/page.tsx

Lines changed: 18 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import { useState, useEffect, useRef } from "react"
44
import { API_BASE_URL, getHeaders } from "@/lib/api"
5+
import { MemoryAIEngine, type MemoryReference as AIMemoryRef } from "@/lib/memory-ai-engine"
56

67
interface ChatMessage {
78
role: "user" | "assistant"
@@ -15,6 +16,7 @@ interface MemoryReference {
1516
content: string
1617
salience: number
1718
title: string
19+
last_seen_at?: number
1820
}
1921

2022
export default function ChatPage() {
@@ -47,131 +49,33 @@ export default function ChatPage() {
4749
}
4850

4951
const data = await response.json()
50-
return data.matches.map((match: any) => ({
52+
const raw: MemoryReference[] = data.matches.map((match: any) => ({
5153
id: match.id,
5254
sector: match.primary_sector || "semantic",
5355
content: match.content,
54-
salience: match.salience || match.score,
55-
title: match.content.substring(0, 50) + (match.content.length > 50 ? "..." : "")
56+
salience: match.salience || match.score || 0,
57+
title: match.content.substring(0, 50) + (match.content.length > 50 ? "..." : ""),
58+
last_seen_at: match.last_seen_at
5659
}))
60+
return raw
5761
} catch (error) {
5862
console.error("Error querying memories:", error)
5963
return []
6064
}
6165
}
6266

6367
const generateResponse = async (userQuery: string, relevantMemories: MemoryReference[]): Promise<string> => {
64-
if (relevantMemories.length === 0) {
65-
return "I don't have any memories that directly relate to your question. Try asking about topics you've previously stored in your memory system, or add more memories to help me answer better."
66-
}
67-
68-
const queryLower = userQuery.toLowerCase()
69-
const isQuestion = queryLower.includes('?') ||
70-
queryLower.startsWith('what') ||
71-
queryLower.startsWith('how') ||
72-
queryLower.startsWith('why') ||
73-
queryLower.startsWith('when') ||
74-
queryLower.startsWith('where') ||
75-
queryLower.startsWith('who') ||
76-
queryLower.startsWith('can') ||
77-
queryLower.startsWith('is') ||
78-
queryLower.startsWith('do') ||
79-
queryLower.startsWith('does')
80-
81-
const sectorGroups: Record<string, MemoryReference[]> = {}
82-
relevantMemories.forEach(mem => {
83-
if (!sectorGroups[mem.sector]) {
84-
sectorGroups[mem.sector] = []
85-
}
86-
sectorGroups[mem.sector].push(mem)
87-
})
88-
89-
const hasSemantic = sectorGroups['semantic']?.length > 0
90-
const hasEpisodic = sectorGroups['episodic']?.length > 0
91-
const hasProcedural = sectorGroups['procedural']?.length > 0
92-
const hasEmotional = sectorGroups['emotional']?.length > 0
93-
const hasReflective = sectorGroups['reflective']?.length > 0
94-
95-
let response = ""
96-
97-
if (isQuestion) {
98-
if (hasSemantic) {
99-
response += "Based on what I know:\n\n"
100-
const topSemantic = sectorGroups['semantic'].slice(0, 3)
101-
topSemantic.forEach((mem, idx) => {
102-
response += `${mem.content}`
103-
if (idx < topSemantic.length - 1) response += "\n\n"
104-
})
105-
} else if (hasEpisodic) {
106-
response += "From your past experiences:\n\n"
107-
const topEpisodic = sectorGroups['episodic'].slice(0, 2)
108-
topEpisodic.forEach((mem, idx) => {
109-
response += `${mem.content}`
110-
if (idx < topEpisodic.length - 1) response += "\n\n"
111-
})
112-
} else if (hasProcedural) {
113-
response += "Here's what I remember about the process:\n\n"
114-
const topProcedural = sectorGroups['procedural'].slice(0, 2)
115-
topProcedural.forEach((mem, idx) => {
116-
response += `${mem.content}`
117-
if (idx < topProcedural.length - 1) response += "\n\n"
118-
})
119-
}
120-
121-
if (hasEpisodic && hasSemantic) {
122-
response += "\n\n**Related experience:**\n"
123-
response += sectorGroups['episodic'][0].content
124-
}
125-
126-
if (hasProcedural && (hasSemantic || hasEpisodic)) {
127-
response += "\n\n**How to apply this:**\n"
128-
response += sectorGroups['procedural'][0].content
129-
}
130-
131-
if (hasEmotional) {
132-
response += "\n\n**Emotional context:**\n"
133-
response += sectorGroups['emotional'][0].content
134-
}
135-
136-
if (hasReflective) {
137-
response += "\n\n**Insight:**\n"
138-
response += sectorGroups['reflective'][0].content
139-
}
140-
} else {
141-
const allMemories = relevantMemories.slice(0, 5)
142-
143-
if (hasSemantic && hasEpisodic) {
144-
response += `${sectorGroups['semantic'][0].content}\n\n`
145-
response += `This connects to when ${sectorGroups['episodic'][0].content.toLowerCase()}`
146-
} else if (hasSemantic) {
147-
response += sectorGroups['semantic'].slice(0, 2).map(m => m.content).join('\n\n')
148-
} else if (hasEpisodic) {
149-
response += "Based on your experiences:\n\n"
150-
response += sectorGroups['episodic'].slice(0, 3).map(m => m.content).join('\n\n')
151-
} else {
152-
response += allMemories.map(m => m.content).join('\n\n')
153-
}
154-
155-
if (hasProcedural && response.length < 500) {
156-
response += "\n\n**Steps involved:**\n"
157-
response += sectorGroups['procedural'][0].content
158-
}
159-
160-
if (hasReflective && response.length < 600) {
161-
response += "\n\n**Reflection:**\n"
162-
response += sectorGroups['reflective'][0].content
163-
}
164-
}
165-
166-
const avgSalience = relevantMemories.reduce((sum, m) => sum + m.salience, 0) / relevantMemories.length
167-
const confidence = avgSalience > 0.7 ? "high" : avgSalience > 0.4 ? "moderate" : "low"
168-
169-
const memoryCount = relevantMemories.length
170-
const sectorCount = Object.keys(sectorGroups).length
171-
172-
response += `\n\n---\n*Retrieved ${memoryCount} ${memoryCount === 1 ? 'memory' : 'memories'} from ${sectorCount} ${sectorCount === 1 ? 'sector' : 'sectors'} • Confidence: ${confidence}*`
173-
174-
return response
68+
const aiMemories: AIMemoryRef[] = relevantMemories.map(m => ({
69+
id: m.id,
70+
sector: m.sector,
71+
content: m.content,
72+
salience: m.salience,
73+
title: m.title,
74+
last_seen_at: m.last_seen_at,
75+
score: (m as any).score
76+
}))
77+
78+
return await MemoryAIEngine.generateResponse(userQuery, aiMemories)
17579
}
17680

17781
const sendMessage = async () => {
@@ -190,11 +94,8 @@ export default function ChatPage() {
19094
setBusy(true)
19195

19296
try {
193-
// Query memories from backend
19497
const relevantMemories = await queryMemories(currentInput)
19598
setMemories(relevantMemories)
196-
197-
// Generate response based on memories
19899
const responseContent = await generateResponse(currentInput, relevantMemories)
199100

200101
const assistantMessage: ChatMessage = {
@@ -219,7 +120,6 @@ export default function ChatPage() {
219120

220121
const addMemoryToBag = async (memory: MemoryReference) => {
221122
try {
222-
// Reinforce the memory by increasing its salience
223123
await fetch(`${API_BASE_URL}/memory/reinforce`, {
224124
method: "POST",
225125
headers: getHeaders(),

0 commit comments

Comments
 (0)