init: 昔涟项目骨架
This commit is contained in:
@@ -0,0 +1,103 @@
|
||||
package orchestrator
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/yourname/cyrene-ai/ai-core/internal/persona"
|
||||
"github.com/yourname/cyrene-ai/ai-core/internal/context"
|
||||
"github.com/yourname/cyrene-ai/ai-core/internal/llm"
|
||||
"github.com/yourname/cyrene-ai/ai-core/internal/memory"
|
||||
)
|
||||
|
||||
// Orchestrator 对话编排器 —— 核心组件
|
||||
type Orchestrator struct {
|
||||
personaInjector *persona.Injector
|
||||
contextBuilder *context.Builder
|
||||
llmAdapter *llm.Adapter
|
||||
memoryExtractor *memory.Extractor
|
||||
memoryRetriever *memory.Retriever
|
||||
}
|
||||
|
||||
// ProcessInput 处理用户输入的主流程
|
||||
func (o *Orchestrator) ProcessInput(
|
||||
ctx context.Context,
|
||||
userID string,
|
||||
sessionID string,
|
||||
userMessage string,
|
||||
mode string, // text / voice_msg / voice_assistant
|
||||
) (*Response, error) {
|
||||
|
||||
// 步骤1: 检索相关记忆
|
||||
memories, err := o.memoryRetriever.Retrieve(ctx, userID, userMessage)
|
||||
if err != nil {
|
||||
// 记忆检索失败不阻断对话
|
||||
memories = nil
|
||||
}
|
||||
|
||||
// 步骤2: 加载人格配置
|
||||
personaConfig, err := o.personaInjector.LoadPersona("cyrene", userID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("加载人格配置失败: %w", err)
|
||||
}
|
||||
|
||||
// 步骤3: 构建对话上下文
|
||||
llmMessages, err := o.contextBuilder.Build(ctx, context.BuildParams{
|
||||
UserID: userID,
|
||||
SessionID: sessionID,
|
||||
UserMessage: userMessage,
|
||||
Persona: personaConfig,
|
||||
Memories: memories,
|
||||
HistoryLimit: 20, // 最近20轮
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("构建上下文失败: %w", err)
|
||||
}
|
||||
|
||||
// 步骤4: 调用LLM生成回复
|
||||
llmResponse, err := o.llmAdapter.Chat(ctx, llmMessages)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("LLM调用失败: %w", err)
|
||||
}
|
||||
|
||||
// 步骤5: 提取并存储新的记忆
|
||||
go o.memoryExtractor.ExtractAndStore(
|
||||
context.Background(),
|
||||
userID, sessionID,
|
||||
userMessage, llmResponse.Content,
|
||||
)
|
||||
|
||||
// 步骤6: 构建响应
|
||||
response := &Response{
|
||||
Text: llmResponse.Content,
|
||||
ResponseMode: mode,
|
||||
}
|
||||
|
||||
// 步骤7: 如果是语音助手模式,进行断句处理
|
||||
if mode == "voice_assistant" {
|
||||
response.Segments = splitIntoSegments(llmResponse.Content)
|
||||
}
|
||||
|
||||
return response, nil
|
||||
}
|
||||
|
||||
// Response 回复结构
|
||||
type Response struct {
|
||||
Text string
|
||||
Segments []Segment
|
||||
ResponseMode string
|
||||
ToolCalls []ToolCall
|
||||
}
|
||||
|
||||
type Segment struct {
|
||||
Index int
|
||||
Text string
|
||||
}
|
||||
|
||||
// splitIntoSegments 按句号断句
|
||||
func splitIntoSegments(text string) []Segment {
|
||||
// 实现按。!?等标点断句
|
||||
// 首句优先:第一个句号前的内容作为第一个segment
|
||||
// 保证低延迟首句播放
|
||||
// ...
|
||||
}
|
||||
Reference in New Issue
Block a user