import { createOpenAI } from "@ai-sdk/openai"
import { generateText } from "ai"
import type { UnifiedSession } from "../types/unified"
/** Model used for memory extraction (fast, cheap, sufficient for extraction) */
const EXTRACTION_MODEL = "gpt-4o-mini"
/**
* Build an extraction prompt that instructs the LLM to extract structured
* memories from a conversation session. Produces MEMORY.md-style markdown
* with categorized facts, events, preferences, and relationships.
*/
export function buildExtractionPrompt(session: UnifiedSession): string {
const speakerA = (session.metadata?.speakerA as string) || "Speaker A"
const speakerB = (session.metadata?.speakerB as string) || "Speaker B"
const date =
(session.metadata?.formattedDate as string) ||
(session.metadata?.date as string) ||
"Unknown date"
const conversation = session.messages
.map((m) => {
const speaker = m.speaker || m.role
const ts = m.timestamp ? ` [${m.timestamp}]` : ""
return `${speaker}${ts}: ${m.content}`
})
.join("\n")
return `You are a memory extraction system. Read the following conversation and extract all important, memorable information into structured markdown. This will be stored as a memory file for later retrieval.
Conversation Date: ${date}
Participants: ${speakerA}, ${speakerB}
${conversation}
Extract memories into the following structured markdown format. Only include sections that have content. Be specific and include names, dates, and details.
## Key Facts
- [Personal details, biographical information, skills, jobs, locations, ages, physical descriptions, etc.]
## Preferences
- [Likes, dislikes, preferences, opinions, favorites, etc.]
## Events
- [${date}]: [Things that happened or were discussed, plans made, activities described]
## Relationships
- [Relationships between people, pets, family members, friends, colleagues, etc.]
## Decisions & Plans
- [Decisions made, future plans, goals, commitments, scheduled events, etc.]
Rules:
- Extract ONLY from what was explicitly stated in the conversation
- Use the speakers' actual names when known, never "the user" or "the assistant"
- Include specific dates, numbers, and proper nouns when mentioned
- Each bullet point should be a self-contained fact (understandable without context)
- For events, always prefix with the date in [brackets]
- Do not invent or infer information that was not stated
- If a section would be empty, omit it entirely
- Keep each bullet concise but complete (one line per fact)
- Resolve relative date references ("yesterday", "last week") to absolute dates using the conversation date when possible`
}
/**
* Call LLM to extract structured memories from a conversation session.
* Returns MEMORY.md-style markdown with categorized facts, events, preferences.
*/
export async function extractMemories(
openai: ReturnType,
session: UnifiedSession
): Promise {
const prompt = buildExtractionPrompt(session)
const params: Record = {
model: openai(EXTRACTION_MODEL),
prompt,
maxTokens: 2000,
temperature: 0,
}
const { text } = await generateText(params as Parameters[0])
return text.trim()
}