feat(memory): add LLM-driven memory extraction from conversations

- memory/extractor: async LLM-based memory extraction from chat history
- Parses JSON lines from LLM response as memory entries
- Wire into orchestrator pipeline via PostProcess hook
- Non-blocking: runs in goroutine with 30s timeout
- Automatic dedup via existing keyword overlap logic
This commit is contained in:
Aska committed 2026-08-12 18:43:04 +08:00
1 parent 886fcf2216
commit 47047c903c
5 files changed
+263 -6

No files matched your search

@@ -15,14 +15,20 @@ import (
"git.yeij.top/AskaEth/Cyrene_v2/services/ai-core/subsession"
)
// MemoryExtractor is the interface for async memory extraction.
type MemoryExtractor interface {
ExtractFromConversation(ctx context.Context, userID string, conversation []model.Message)
}
// Pipeline orchestrates the full dialogue flow.
type Pipeline struct {
llmSelector *llm.ModelSelector
cache *llm.SemanticCache
ctxStore *ctxpkg.Store
ctxBuilder *ctxpkg.Builder
subMgr *subsession.Manager
personaInjector *persona.Injector
llmSelector *llm.ModelSelector
cache *llm.SemanticCache
ctxStore *ctxpkg.Store
ctxBuilder *ctxpkg.Builder
subMgr *subsession.Manager
personaInjector *persona.Injector
memoryExtractor MemoryExtractor
}
// NewPipeline creates a new dialogue pipeline.
@@ -43,6 +49,11 @@ func NewPipeline(
}
}
// SetMemoryExtractor injects the memory extraction capability.
func (p *Pipeline) SetMemoryExtractor(e MemoryExtractor) {
p.memoryExtractor = e
}
// ProcessInput processes a user message through the full pipeline.
// Returns a channel of StreamToken for the LLM response.
func (p *Pipeline) ProcessInput(ctx context.Context, sessionID, userMessage string) (<-chan model.StreamToken, *model.Intent, error) {
@@ -87,6 +98,14 @@ func (p *Pipeline) ProcessInput(ctx context.Context, sessionID, userMessage stri
return tokenCh, intent, nil
}
// PostProcess triggers async memory extraction after a conversation round completes.
func (p *Pipeline) PostProcess(sessionID, userID string) {
if p.memoryExtractor == nil { return }
history := p.ctxStore.Get(sessionID)
if len(history) == 0 { return }
p.memoryExtractor.ExtractFromConversation(nil, userID, history)
}
// --- Intent Analysis ---
// controlWords are common IoT control verbs.