mirror of
https://github.com/memohai/Memoh.git
synced 2026-04-25 07:00:48 +09:00
7.3 KiB
7.3 KiB
Provider 重构总结
重构目标
将 Memory 服务和 Chat 服务统一使用 internal/chat 中的 Provider 接口,实现代码复用和架构统一。
主要变更
1. 扩展 Chat Provider 接口
文件: internal/chat/types.go
-
扩展
Request结构,添加了:Temperature *float32- 温度参数ResponseFormat *ResponseFormat- 响应格式(支持 JSON 模式)MaxTokens *int- 最大 token 数
-
新增
ResponseFormat结构:type ResponseFormat struct { Type string // "json_object" 或 "text" }
2. 创建 Memory 的 LLM 接口
文件: internal/memory/types.go
-
定义了
LLM接口:type LLM interface { Extract(ctx context.Context, req ExtractRequest) (ExtractResponse, error) Decide(ctx context.Context, req DecideRequest) (DecideResponse, error) } -
这个接口被以下两个实现:
LLMClient(旧实现,向后兼容)ProviderLLMClient(新实现,使用 chat.Provider)
3. 创建 Provider-based LLM 客户端
文件: internal/memory/llm_provider_client.go (新文件)
- 实现了
ProviderLLMClient结构 - 使用
chat.Provider来执行 LLM 调用 - 支持 JSON 模式输出,确保结构化响应
- 重用了
internal/memory包中的辅助函数
关键代码:
type ProviderLLMClient struct {
provider chat.Provider
model string
}
func NewProviderLLMClient(provider chat.Provider, model string) *ProviderLLMClient
func (c *ProviderLLMClient) Extract(ctx context.Context, req ExtractRequest) (ExtractResponse, error)
func (c *ProviderLLMClient) Decide(ctx context.Context, req DecideRequest) (DecideResponse, error)
4. 更新 Memory 服务
文件: internal/memory/service.go
- 将
llm *LLMClient改为llm LLM - 现在接受任何实现
LLM接口的类型 - 保持了所有现有功能
5. 更新主程序
文件: cmd/agent/main.go
添加的函数:
-
selectMemoryModel - 选择用于 memory 操作的模型
- 优先级:memory 模型 → chat 模型 → 任何 chat 类型模型
-
fetchProviderByID - 根据 ID 获取 provider 配置
-
createChatProvider - 根据配置创建 provider 实例
- 支持 OpenAI、Anthropic、Google、Ollama
初始化流程更新:
// 1. 初始化 chat resolver(用于 chat 和 memory)
chatResolver := chat.NewResolver(modelsService, queries, 30*time.Second)
// 2. 尝试为 memory 创建 provider-based 客户端
memoryModel, memoryProvider, err := selectMemoryModel(ctx, modelsService, queries, &cfg)
if err != nil {
// 回退到旧的 LLMClient
llmClient = memory.NewLLMClient(cfg.Memory.BaseURL, cfg.Memory.APIKey, ...)
} else {
// 使用新的 provider-based 客户端
provider, _ := createChatProvider(memoryProvider, 30*time.Second)
llmClient = memory.NewProviderLLMClient(provider, memoryModel.ModelID)
}
// 3. 创建 memory 服务
memoryService = memory.NewService(llmClient, embedder, store, resolver, ...)
架构优势
1. 统一的 Provider 管理
- Chat 和 Memory 服务共享相同的 Provider 实现
- 减少代码重复
- 统一的配置和管理
2. 灵活的模型选择
- 可以为不同功能配置不同的模型
- 支持
enable_as字段来指定模型用途 - 自动回退机制
3. 向后兼容
- 保留了旧的
LLMClient实现 - 如果数据库中没有配置模型,自动回退到配置文件
- 平滑迁移路径
4. 类型安全
- 使用 Go 接口而不是运行时类型判断
- 编译时类型检查
- 更好的 IDE 支持
5. 易于扩展
- 添加新 Provider 只需实现
Provider接口 - 添加新 LLM 客户端只需实现
LLM接口 - 模块化设计
配置说明
数据库配置
为 Memory 操作配置模型:
-- 方式 1: 使用专用的 memory 模型
UPDATE models SET enable_as = 'memory'
WHERE model_id = 'gpt-4-turbo-preview';
-- 方式 2: 使用 chat 模型(如果没有专用 memory 模型)
UPDATE models SET enable_as = 'chat'
WHERE model_id = 'gpt-4';
环境变量(回退配置)
如果数据库中没有配置模型,系统会使用这些配置:
[memory]
base_url = "https://api.openai.com/v1"
api_key = "sk-..."
model = "gpt-4.1-nano"
timeout_seconds = 10
测试建议
1. Memory 操作测试
# 测试 Extract(提取事实)
curl -X POST http://localhost:8080/api/memory/add \
-H "Authorization: Bearer $TOKEN" \
-d '{
"messages": [
{"role": "user", "content": "My name is Alice and I like pizza"}
],
"user_id": "user-123"
}'
# 测试 Search(搜索记忆)
curl -X POST http://localhost:8080/api/memory/search \
-H "Authorization: Bearer $TOKEN" \
-d '{
"query": "What food do I like?",
"user_id": "user-123"
}'
2. Chat 操作测试
# 测试普通聊天
curl -X POST http://localhost:8080/api/chat \
-H "Authorization: Bearer $TOKEN" \
-d '{
"messages": [
{"role": "user", "content": "Hello, how are you?"}
]
}'
3. 验证日志
启动时应该看到:
Using memory model: gpt-4-turbo-preview (provider: openai)
或者(如果回退):
WARNING: No memory model configured, using fallback LLMClient: ...
后续工作
短期(必须)
- 实现各个 Provider 的具体逻辑(目前大部分返回 "not yet implemented")
- 添加流式响应支持
- 完善错误处理
中期(建议)
- 添加 Provider 的单元测试
- 添加 Memory 集成测试
- 实现 Provider 连接池
- 添加请求重试机制
长期(优化)
- Provider 性能监控
- 自动模型选择和负载均衡
- 模型响应缓存
- 支持更多 Provider(如 Cohere、HuggingFace)
迁移检查清单
- 扩展 Request 结构支持 JSON 模式
- 创建 LLM 接口
- 实现 ProviderLLMClient
- 更新 Memory Service 使用接口
- 更新主程序初始化流程
- 添加模型选择逻辑
- 添加 Provider 创建逻辑
- 保持向后兼容
- 添加架构文档
- 添加单元测试
- 添加集成测试
- 更新部署文档
文件清单
新增文件
internal/memory/llm_provider_client.go- Provider-based LLM 客户端internal/chat/ARCHITECTURE.md- 架构文档REFACTORING_SUMMARY.md- 本文件
修改文件
internal/chat/types.go- 扩展 Request 结构internal/memory/types.go- 添加 LLM 接口internal/memory/service.go- 使用 LLM 接口cmd/agent/main.go- 更新初始化流程
保留文件(向后兼容)
internal/memory/llm_client.go- 旧的 HTTP 客户端实现
注意事项
- JSON 模式兼容性: 不是所有模型都支持 JSON 模式,需要在实现 Provider 时处理
- 错误处理: 当前错误处理较简单,生产环境需要更详细的错误信息
- 超时设置: 不同操作可能需要不同的超时时间,可以考虑配置化
- 并发安全: Provider 实例应该是并发安全的
- 资源清理: 确保 Provider 的资源(如 HTTP 连接)正确释放
问题反馈
如果遇到问题,请检查:
- 数据库中是否有配置的 chat 模型
- Provider 配置是否正确(API key、base URL)
- 日志中的错误信息
- 是否正确初始化了 chat resolver
详细架构说明请参考:internal/chat/ARCHITECTURE.md