Version: 0.9.13.dev.260410
后端: 1. Memory Day1 链路打通(chat_history -> outbox -> memory_jobs) - 更新 service/events/chat_history_persist.go:聊天消息落库同事务追加 memory.extract.requested 事件(仅 user 消息,失败回滚后由 outbox 重试) - 新建 service/events/memory_extract_requested.go:消费 memory.extract.requested 并幂等入队 memory_jobs,补齐 payload 校验、文本截断与 idempotency key - 更新 cmd/start.go:注册 RegisterMemoryExtractRequestedHandler 2. Memory 模块骨架落地(先跑通状态机,再接入真实抽取) - 新建 memory/model、repo、service、orchestrator、worker、utils 目录与 Day1 mock 抽取执行链 - 新建 model/memory.go:补齐 memory_items / memory_jobs / memory_audit_logs / memory_user_settings 与事件 payload 模型 - 更新 inits/mysql.go:接入 4 张 memory 相关表 AutoMigrate 3. RAG 复用基础设施预埋(依赖可替换) - 新建 infra/rag:core pipeline + chunk/embed/retrieve/rerank/store/corpus/config 分层实现 - 默认接入 MockEmbedder + InMemoryStore,预留 Milvus / Eino 适配实现 - 新增 infra/rag/RAG复用接口实施计划.md 4. 本地依赖与交接文档同步 - 更新 docker-compose.yml:新增 etcd / minio / milvus / attu 服务与数据卷 - 删除 newAgent/HANDOFF_工具研究与运行态重置.md、newAgent/阶段3_上下文瘦身设计.md - 新增 newAgent/HANDOFF_WebSearch两阶段实施计划.md、memory/HANDOFF-RAG复用后续实施计划.md、memory/README.md 前端:无 仓库:无
This commit is contained in:
191
backend/infra/rag/RAG复用接口实施计划.md
Normal file
191
backend/infra/rag/RAG复用接口实施计划.md
Normal file
@@ -0,0 +1,191 @@
|
||||
# RAG 复用接口实施计划(Memory + WebSearch 统一底座)
|
||||
|
||||
## 1. 目标与原则
|
||||
|
||||
1. 在 `backend/infra/rag` 抽离共享 RAG Core,统一 `chunk/embed/retrieve/rerank` 能力。
|
||||
2. 先接入 `MemoryCorpus` 与 `WebCorpus` 两个适配器,避免后续重复造轮子。
|
||||
3. 保持“并行迁移”策略:新老链路并存,先接入、再灰度、再切流、最后删除旧实现。
|
||||
4. 不阻塞现有主链路;任何 RAG 子能力失败都必须可降级。
|
||||
|
||||
## 2. 本轮范围与非目标
|
||||
|
||||
### 2.1 本轮范围
|
||||
|
||||
1. 定义 RAG Core 接口、标准数据结构、错误码和回退语义。
|
||||
2. 提供 `MemoryCorpus` 与 `WebCorpus` 适配层设计。
|
||||
3. 给出分阶段落地步骤、验收标准、风险控制。
|
||||
|
||||
### 2.2 本轮非目标
|
||||
|
||||
1. 不在本轮实现完整生产级向量检索细节(Milvus 连接器可先占位)。
|
||||
2. 不在本轮统一改造所有调用方,只做首批接入点。
|
||||
3. 不在本轮引入多 Provider 工厂(先保证单 Provider 可替换)。
|
||||
|
||||
## 3. 目录与模块规划
|
||||
|
||||
建议目录(先建骨架,逐轮填实):
|
||||
|
||||
```text
|
||||
backend/infra/rag/
|
||||
core/
|
||||
types.go
|
||||
interfaces.go
|
||||
pipeline.go
|
||||
errors.go
|
||||
chunk/
|
||||
text_chunker.go
|
||||
embed/
|
||||
eino_embedder.go
|
||||
retrieve/
|
||||
vector_retriever.go
|
||||
rerank/
|
||||
eino_reranker.go
|
||||
store/
|
||||
vector_store.go
|
||||
milvus_store.go
|
||||
corpus/
|
||||
memory_corpus.go
|
||||
web_corpus.go
|
||||
config/
|
||||
config.go
|
||||
```
|
||||
|
||||
## 4. 核心接口设计(建议签名)
|
||||
|
||||
```go
|
||||
type Chunker interface {
|
||||
Chunk(ctx context.Context, doc SourceDocument, opt ChunkOption) ([]Chunk, error)
|
||||
}
|
||||
|
||||
type Embedder interface {
|
||||
Embed(ctx context.Context, texts []string, action string) ([][]float32, error)
|
||||
}
|
||||
|
||||
type Retriever interface {
|
||||
Retrieve(ctx context.Context, req RetrieveRequest) ([]ScoredChunk, error)
|
||||
}
|
||||
|
||||
type Reranker interface {
|
||||
Rerank(ctx context.Context, query string, candidates []ScoredChunk, topK int) ([]ScoredChunk, error)
|
||||
}
|
||||
|
||||
type VectorStore interface {
|
||||
Upsert(ctx context.Context, rows []VectorRow) error
|
||||
Search(ctx context.Context, req VectorSearchRequest) ([]ScoredVectorRow, error)
|
||||
Delete(ctx context.Context, ids []string) error
|
||||
Get(ctx context.Context, ids []string) ([]VectorRow, error)
|
||||
}
|
||||
|
||||
type CorpusAdapter interface {
|
||||
Name() string
|
||||
BuildIngestDocuments(ctx context.Context, input any) ([]SourceDocument, error)
|
||||
BuildRetrieveFilter(ctx context.Context, req any) (map[string]any, error)
|
||||
}
|
||||
```
|
||||
|
||||
## 5. 统一流程约定
|
||||
|
||||
### 5.1 Ingest 流程
|
||||
|
||||
1. `CorpusAdapter.BuildIngestDocuments` 生成标准文档。
|
||||
2. `Chunker.Chunk` 切块(固定 chunk_size + overlap)。
|
||||
3. `Embedder.Embed(action=add/update)` 生成向量。
|
||||
4. `VectorStore.Upsert` 写入。
|
||||
5. 任一步失败按“可补偿”记录状态,不影响主业务成功返回。
|
||||
|
||||
### 5.2 Retrieve 流程
|
||||
|
||||
1. `CorpusAdapter.BuildRetrieveFilter` 构建过滤条件。
|
||||
2. `Embedder.Embed(action=search)` 向量化 query。
|
||||
3. `VectorStore.Search` 召回候选。
|
||||
4. `threshold` 过滤。
|
||||
5. 可选 `Reranker` 重排;失败则 fallback 到原排序并记录原因码。
|
||||
|
||||
## 6. 两类 Corpus 适配器设计
|
||||
|
||||
### 6.1 MemoryCorpus
|
||||
|
||||
1. 数据源:`memory_items`(结构化记忆事实)。
|
||||
2. 强约束过滤:`user_id + assistant_id + conversation_id`。
|
||||
3. 元数据:`memory_type/confidence/sensitivity_level/ttl_at/source_event_id`。
|
||||
4. 注入优先级:`constraint/preference` 高于 `fact/todo_hint`。
|
||||
|
||||
### 6.2 WebCorpus
|
||||
|
||||
1. 数据源:websearch 抓取结果(`url/title/snippet/content`)。
|
||||
2. 强约束过滤:`query_id/session_id`,避免跨问题污染。
|
||||
3. 元数据:`domain/published_at/fetched_at/language/source_rank`。
|
||||
4. 检索策略:先向量召回,再结合域名可信度做轻量加权。
|
||||
|
||||
## 7. 与 Eino 的集成方式
|
||||
|
||||
1. `embed/eino_embedder.go`:封装 Eino embedding 调用。
|
||||
2. `rerank/eino_reranker.go`:封装 Eino 重排调用。
|
||||
3. 统一配置入口:`rag.enabled/top_k/threshold/reranker_enabled/timeout`。
|
||||
4. 统一日志字段:`trace_id/corpus/action/fallback_reason/latency_ms/hit_count`。
|
||||
|
||||
## 8. 分阶段实施(建议 4 轮)
|
||||
|
||||
### Round 1:基础骨架(不切流)
|
||||
|
||||
1. 建 `infra/rag` 目录与接口、类型、错误码。
|
||||
2. 提供 `NoopReranker`、`MockEmbedder` 兜底实现。
|
||||
3. 验收:编译通过,主链路行为不变。
|
||||
|
||||
### Round 2:MemoryCorpus 接入(灰度)
|
||||
|
||||
1. 把记忆检索从“模块内直连”改为调用 RAG Core。
|
||||
2. 保留旧路径开关 `memory.rag.enabled`,默认关闭。
|
||||
3. 验收:开启开关后功能等价,失败可自动降级旧链路。
|
||||
|
||||
### Round 3:WebCorpus 接入(灰度)
|
||||
|
||||
1. websearch 召回改走 RAG Core。
|
||||
2. 加入 `web.rag.enabled` 灰度开关。
|
||||
3. 验收:检索可复用同一 pipeline,质量不低于旧实现。
|
||||
|
||||
### Round 4:统一切流与清理
|
||||
|
||||
1. 默认开启 RAG Core,旧链路保留一段观察窗口。
|
||||
2. 指标稳定后删除旧实现。
|
||||
3. 验收:两条业务链路均通过统一接口,文档与监控齐全。
|
||||
|
||||
## 9. 配置建议
|
||||
|
||||
```yaml
|
||||
rag:
|
||||
enabled: true
|
||||
topK: 8
|
||||
threshold: 0.55
|
||||
reranker:
|
||||
enabled: true
|
||||
timeoutMs: 1200
|
||||
ingest:
|
||||
chunkSize: 400
|
||||
chunkOverlap: 80
|
||||
retrieve:
|
||||
timeoutMs: 1500
|
||||
```
|
||||
|
||||
## 10. 验收标准(DoD)
|
||||
|
||||
1. 同一套 Core 能同时服务 Memory 与 WebSearch。
|
||||
2. `rerank` 异常时可观测地降级,不影响主功能可用性。
|
||||
3. 支持按 corpus 维度查看命中率、耗时、降级率。
|
||||
4. 新老链路可开关切换,回滚路径明确。
|
||||
|
||||
## 11. 风险与应对
|
||||
|
||||
1. 风险:一次性切流影响面大。
|
||||
应对:按 corpus 分轮灰度,先 Memory 后 Web。
|
||||
2. 风险:向量检索延迟波动。
|
||||
应对:超时控制 + fallback + 本地缓存热点 query。
|
||||
3. 风险:跨域检索串数据。
|
||||
应对:强制 filter 校验,不满足维度直接拒绝检索。
|
||||
|
||||
## 12. 下一步执行清单(紧接实现)
|
||||
|
||||
1. 先补 `core/interfaces.go + core/types.go + core/pipeline.go`。
|
||||
2. 再补 `corpus/memory_corpus.go`(首个适配器)。
|
||||
3. 然后给 websearch 接 `corpus/web_corpus.go` 占位适配器。
|
||||
4. 最后补 `store/milvus_store.go` 与配置接线(当前 docker compose 已准备 Milvus 依赖)。
|
||||
Reference in New Issue
Block a user