Architecture
A memory-enabled chatbot typically follows this flow:
- User sends a message
- Recall relevant memories for context
- Generate response with memory context
- Extract and store new memories
- Return response to user
Basic Implementation
import { Trix } from '@trixdb/client';
import OpenAI from 'openai';
const trix = new Trix({ apiKey: process.env.TRIX_API_KEY });
const openai = new OpenAI();
async function handleMessage(userId: string, message: string) {
// 1. Recall relevant context
const results = await trix.memories.list({
q: message,
spaceId: userId,
limit: 10
});
// 2. Build system prompt with memories
const systemPrompt = `You are a helpful assistant.
What you know about this user:
${results.data.map(m => `- ${m.content}`).join('\n') || 'Nothing yet'}
Remember to be personalized based on what you know.`;
// 3. Generate response
const response = await openai.chat.completions.create({
model: 'gpt-4',
messages: [
{ role: 'system', content: systemPrompt },
{ role: 'user', content: message }
]
});
return response.choices[0].message.content;
}Automatic Memory Extraction
Use the AI to decide what's worth remembering:
async function extractMemories(userId: string, conversation: Message[]) {
const extraction = await openai.chat.completions.create({
model: 'gpt-4',
messages: [
{
role: 'system',
content: `Extract key facts about the user from this conversation.
Return a JSON array of strings, each being a distinct fact.
Only include meaningful, personal information.`
},
{ role: 'user', content: JSON.stringify(conversation) }
],
response_format: { type: 'json_object' }
});
const { facts } = JSON.parse(extraction.choices[0].message.content);
// Store each extracted fact
for (const fact of facts) {
await trix.memories.create({ content: fact, spaceId: userId });
}
}Run memory extraction asynchronously after each conversation to avoid adding latency.
Best Practices
- Use a similarity threshold (0.6-0.8) to avoid irrelevant memories
- Limit recalled memories to prevent context overflow
- Extract memories asynchronously for better response times
- Deduplicate similar memories periodically
- Use contexts to separate different types of information