mirror of
https://github.com/memohai/Memoh.git
synced 2026-04-27 07:16:19 +09:00
274 lines
7.3 KiB
Markdown
274 lines
7.3 KiB
Markdown
# Provider 重构总结
|
||
|
||
## 重构目标
|
||
|
||
将 Memory 服务和 Chat 服务统一使用 `internal/chat` 中的 Provider 接口,实现代码复用和架构统一。
|
||
|
||
## 主要变更
|
||
|
||
### 1. 扩展 Chat Provider 接口
|
||
|
||
**文件**: `internal/chat/types.go`
|
||
|
||
- 扩展 `Request` 结构,添加了:
|
||
- `Temperature *float32` - 温度参数
|
||
- `ResponseFormat *ResponseFormat` - 响应格式(支持 JSON 模式)
|
||
- `MaxTokens *int` - 最大 token 数
|
||
|
||
- 新增 `ResponseFormat` 结构:
|
||
```go
|
||
type ResponseFormat struct {
|
||
Type string // "json_object" 或 "text"
|
||
}
|
||
```
|
||
|
||
### 2. 创建 Memory 的 LLM 接口
|
||
|
||
**文件**: `internal/memory/types.go`
|
||
|
||
- 定义了 `LLM` 接口:
|
||
```go
|
||
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` 包中的辅助函数
|
||
|
||
关键代码:
|
||
```go
|
||
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`
|
||
|
||
#### 添加的函数:
|
||
|
||
1. **selectMemoryModel** - 选择用于 memory 操作的模型
|
||
- 优先级:memory 模型 → chat 模型 → 任何 chat 类型模型
|
||
|
||
2. **fetchProviderByID** - 根据 ID 获取 provider 配置
|
||
|
||
3. **createChatProvider** - 根据配置创建 provider 实例
|
||
- 支持 OpenAI、Anthropic、Google、Ollama
|
||
|
||
#### 初始化流程更新:
|
||
|
||
```go
|
||
// 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 操作配置模型:
|
||
|
||
```sql
|
||
-- 方式 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';
|
||
```
|
||
|
||
### 环境变量(回退配置)
|
||
|
||
如果数据库中没有配置模型,系统会使用这些配置:
|
||
|
||
```toml
|
||
[memory]
|
||
base_url = "https://api.openai.com/v1"
|
||
api_key = "sk-..."
|
||
model = "gpt-4.1-nano"
|
||
timeout_seconds = 10
|
||
```
|
||
|
||
## 测试建议
|
||
|
||
### 1. Memory 操作测试
|
||
```bash
|
||
# 测试 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 操作测试
|
||
```bash
|
||
# 测试普通聊天
|
||
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)
|
||
|
||
## 迁移检查清单
|
||
|
||
- [x] 扩展 Request 结构支持 JSON 模式
|
||
- [x] 创建 LLM 接口
|
||
- [x] 实现 ProviderLLMClient
|
||
- [x] 更新 Memory Service 使用接口
|
||
- [x] 更新主程序初始化流程
|
||
- [x] 添加模型选择逻辑
|
||
- [x] 添加 Provider 创建逻辑
|
||
- [x] 保持向后兼容
|
||
- [x] 添加架构文档
|
||
- [ ] 添加单元测试
|
||
- [ ] 添加集成测试
|
||
- [ ] 更新部署文档
|
||
|
||
## 文件清单
|
||
|
||
### 新增文件
|
||
- `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 客户端实现
|
||
|
||
## 注意事项
|
||
|
||
1. **JSON 模式兼容性**: 不是所有模型都支持 JSON 模式,需要在实现 Provider 时处理
|
||
2. **错误处理**: 当前错误处理较简单,生产环境需要更详细的错误信息
|
||
3. **超时设置**: 不同操作可能需要不同的超时时间,可以考虑配置化
|
||
4. **并发安全**: Provider 实例应该是并发安全的
|
||
5. **资源清理**: 确保 Provider 的资源(如 HTTP 连接)正确释放
|
||
|
||
## 问题反馈
|
||
|
||
如果遇到问题,请检查:
|
||
1. 数据库中是否有配置的 chat 模型
|
||
2. Provider 配置是否正确(API key、base URL)
|
||
3. 日志中的错误信息
|
||
4. 是否正确初始化了 chat resolver
|
||
|
||
详细架构说明请参考:`internal/chat/ARCHITECTURE.md`
|
||
|