Files
MemoryBear/docs/rag/evolution/future-extensions-roadmap.md
Multica PM Agent 343a5eebe3
Some checks failed
Sync to Gitee / sync (push) Has been cancelled
docs(rag): add MemoryBear RAG implementation docs v1.0
Submit the formed RAG documentation set produced across Sprint-1/2/3
(WS-12 through WS-26) under docs/rag/. Includes:

- README.md / INDEX.md: landing + total index (responsibility matrix,
  review verdicts, dual-link to source issues)
- overview/: full-pipeline architecture (4 .mmd diagrams),
  11-stage boundary contracts, doc map, source-code inventory
- pipeline/: 5 deep-dives (Loader/Parser/Chunking, Embedding,
  VDB & retrieval, GraphRAG, Rerank/Prompt/LLM)
- graphrag/, end-to-end/: v1.0 formal versions with full source
  retained as reference
- evolution/: 11 architecture-refactor proposals,
  6-direction roadmap, capability map
- review/: S3-T1 / S3-T2 final reviews, S2-T7 final summary
- _indexes/: glossary (81 terms), source->doc reverse index, chart index
- _release/: v1.0-RC1 release manifest, versioning convention,
  ops & freshness plan
- _meta/README.md: placeholder noting WS-12 governance assets gap

Aggregate review score 92.6/100 (8/8 PASS, 31/31 source-code spot
checks hit). The legacy docs/ ignore in .gitignore is narrowed to
docs/* with an explicit allowlist for docs/rag/.

Refs: WS-26
Co-authored-by: multica-agent <github@multica.ai>
2026-05-09 10:51:48 +08:00

458 lines
31 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# MemoryBear RAG · 后续迭代功能新增方式建议S3-T2
> 上游:[WS-11] 总规划、[S1-T2 全链路架构]、[S1-T3 源码盘点]、Sprint-2 各环节深度文档、[S3-T1 架构改造建议]
> 输出形态:能力地图 + 6 个重点扩展方向 + 2 条 Quick PoC + 优先级矩阵 + 落地路线图
> 设计原则:所有方向 **必须** 复用 [S3-T1] 提议的统一抽象(`Retriever / Reranker / Generator / Embedder / Loader / Chunker`),避免出现新功能 = 新一团耦合。
---
## 0. 现状速览与设计基线
### 0.1 一图看清"已有 / 可上 / 愿景"
详见附件 `capability-map.mmd`Mermaid 格式)。三色对应:
- 🟢 **已有**Sprint-2 文档已覆盖、源码可证、生产可用。
- 🟡 **近期可上**12 个 Sprint 内可落地,依赖最少。
- 🟣 **中长期愿景**36 个月,存在跨团队/外部依赖。
### 0.2 关键源码事实(用于支撑后续方案)
| 事实 | 源码定位 | 对扩展的影响 |
|------|---------|-------------|
| 多模态目前 **走文本通道** | `rag/app/picture.py:54``vision_model.describe``rag/app/audio.py:29``seq2txt_mdl.transcription``naive.py` 走 video → VLM → 文本 | 跨模态语义损失大;扩展为"原生跨模态向量"是方向 D1 |
| `MatchSparseExpr` 已声明但未接入 | `rag/utils/doc_store_conn.py:75``vdb/field.py:11(SPARSE_VECTOR)` 都已存在;`grep -r SparseVector` 仅 1 处定义、0 处调用 | SPLADE 接入是脚手架级改造不是从零开始D2 |
| 混合检索权重写死 `0.05,0.95` | `rag/nlp/search.py:439``FusionExpr("weighted_sum", topk, {"weights": "0.05,0.95"})` | 语义路由 / 自适应权重的注入点天然存在D2 |
| GraphRAG 是"一次构建"模型 | `tasks.py``build_graphrag_for_document` Celery 链;图存于 ES `knowledge_graph_kwd` 字段 | 增量演化、时间维度、Neo4j 双引擎需要在 Celery 链上加 hookD3 |
| 对话记忆与 RAG **不互通** | `core/memory/` 自成一套Ebbinghaus、ACT-R、Neo4j、langgraph 读图);`workflow/nodes/knowledge/node.py` 完全不引用 `core/memory` | 对话记忆 ↔ 检索的协同是最大产品差异化机会D4 |
| 评估只在 README 体现 | 仓内无 `eval/``ragas``F1` 类计算代码 | 反馈闭环要从 0 搭,但与 [S3-T1] 提议的"可观测性"天然合并D5 |
| Reranker 只能推理不能学 | `core/models/rerank.py:11` 包装 langchain `BaseDocumentCompressor`,仅做远程调用 | 自训练 Cross-Encoder 是一条独立、可量化收益的小路径D5 |
| 检索模式硬编码在 enum | `RetrieveType.{PARTICIPLE, SEMANTIC, HYBRID, Graph}``schemas/chunk_schema.py` | 引入"语义路由"需要把 enum 改成 strategy 模式D6 |
### 0.3 与 [S3-T1] 接口抽象的联动约定
[S3-T1] 提议把当前散落的检索/排序/生成代码抽象为协议(参考 LangChain Runnable。本路线图的所有"接口改造点"都引用以下统一协议(命名以 [S3-T1] 终稿为准,本稿先行登记):
```python
# rag/protocols.py[S3-T1] 提议)
class Retriever(Protocol):
async def retrieve(self, query: Query, ctx: RetrievalContext) -> list[ScoredChunk]: ...
class Reranker(Protocol):
async def rerank(self, query: Query, chunks: list[ScoredChunk], ctx: RerankContext) -> list[ScoredChunk]: ...
class Embedder(Protocol):
def encode(self, items: list[Embeddable]) -> EmbeddingResult: ... # Embeddable = str | Image | Audio | ...
class Generator(Protocol):
async def generate(self, system: str, history: list[Msg], ctx: GenContext) -> GenResult: ...
```
> **原则**:本文档每条扩展方向都以"新增/扩展某 Protocol 实现 + 注册到工厂"为接入方式,**不**改动调用方代码。这样可以保持 N 个扩展方向 **并行落地** 而不互相阻塞。
---
## 1. 重点扩展方向
> 共 6 个方向。第 5、6 个为前述 5 个外的延伸(自适应路由),但和"评估闭环 / 混合搜索 / 对话记忆"高度互补,建议合并审阅。
### D1. 多模态检索(原生跨模态向量空间)
#### 1.1 触发场景
- 客户问:"去年那张含 'Q3 GMV' 的 PPT 切片在哪?" — 当前只能命中 OCR 抽出的文字,**布局/图表整体语义** 丢失。
- 视频会议纪要库:用户描述"那段讲到老王说'下季度先稳住毛利'的会议",纯 ASR 文本无法绑定 **说话人 + 时间 + 屏幕共享上下文**
- 设备图谱:硬件型号识图("这块板子是哪一版"),目前只能让 VLM 描述后再走文本检索VLM 描述不稳定。
#### 1.2 技术方案
分三层逐步推进:
| 层级 | 方案 | 依赖组件 |
|------|------|---------|
| L1基线增强 | **关键帧抽样 + VLM 多次 describe**:视频每 N 秒抽帧,每帧 VLM 描述独立 chunk`frame_ts` 元数据;图片在 OCR + describe 之外再加 **结构化 VQA**"图中有什么图表/品牌/人脸?" | 现有 `cv_model.py``sequence2txt_model.py` 即可;新增 `rag/app/video.py` |
| L2跨模态检索 | 引入 **CLIP / BGE-VL / Jina-Clip-v2** 作为 `MultimodalEmbedder` Protocol 实现:图片直接编码为向量,文本 query 编码到 **同一向量空间**ES 索引增加 `vec_image_q_<dim>_vec` 列 | 新依赖 `transformers` / `sentence-transformers` 或托管 APIGPU 资源 |
| L3视听统一 | **Whisper + speaker diarization**pyannote替换当前一段式 ASR视频 chunk 同时持有 `text_vec`ASR 文本)+ `image_vec`(关键帧) + `audio_vec`(可选,用 CLAP | `pyannote.audio``open_clip`;额外存储约 +30% |
#### 1.3 接口改造点(基于 S3-T1
- 扩展 `Embedder.encode(items: list[Embeddable])``Embeddable = str | PILImage | AudioBytes | VideoFrame`,返回 `EmbeddingResult(vector, modality, dim)`
- 新增 `MultimodalRetriever(Retriever)` 实现:内部根据 query 的 `modality_hint`(文本默认)选择走 `text_vec` 还是 `image_vec` 列。
- VDB 层 schema 演进(`rag/vdb/elasticsearch/elasticsearch_vector.py:653+` 的 mapping 创建):把"硬编码单 vector 列"改造为"按 modality 多列动态注册";落地依赖 [S3-T1] 提到的 mapping 模板化改造。
- `app/picture.py` / `app/audio.py``chunk()` 函数输出 dict 中新增 `image_b64` / `audio_b64` 字段,供 Embedder 后续无损取用(避免 PIL 对象在 Celery pickle 边界丢失)。
#### 1.4 工作量估计
- L1 基线:**1.5 人周**2 个 PR视频抽帧结构化 VQA prompt
- L2 跨模态:**3 人周**(含 Embedder 抽象、ES schema 迁移、回归测试)
- L3 视听统一:**4 人周**(含 GPU 容器、speaker diarization 集成)
- 合计:**~1.5 + 3 + 4 ≈ 8.5 人周**(可分阶段产出)
#### 1.5 风险与依赖
- ⚠️ **存储膨胀**image_vec768d float32单图 3KB1M 图 ≈ 3GBES dense_vector 启用 `int8_hnsw` 量化可减 75%。
- ⚠️ **VLM 描述漂移**:同一图不同时间不同模型版本,描述差异大;需要 caption 缓存key = `sha256(image)+model_version`)。
- ⛓️ **强依赖**[S3-T1] mapping 模板化改造完成后再做 L2否则 schema 演进会成阻塞点。
- ⛓️ **GPU 依赖**L2/L3 在自建 GPU 节点或托管 API 二选一建议先走托管Jina-Clip API跑通端到端再评估自托管。
---
### D2. 混合搜索增强Sparse + Dense + Late-Interaction + 自适应路由)
#### 2.1 触发场景
- "工号 E12345 的 OKR" — 长尾标识符BM25 强、稠密向量弱,**当前 0.05/0.95 权重几乎让 BM25 失语**。
- "怎么做用户分层运营?" — 概念性问题dense 强、BM25 弱。
- "GraphRAG 和 LightRAG 的区别" — 需要 ColBERT 这类 token 级精排,单向量混淆术语。
#### 2.2 技术方案
| 子方向 | 方案 | 价值 |
|-------|------|------|
| **SPLADE 学习稀疏** | 用 `naver/splade-cocondenser-ensembledistil` 或国产 BGE-M3 sparse 输出,每个文档生成稀疏向量(含 token expansion接入 `MatchSparseExpr`**已存在但未启用** | 把 BM25 的"词形匹配"升级为"学习权重 + 自动同义扩展" |
| **ColBERT 后期交互** | 文档级向量改为 token 级(一篇文档 N 个 token vectorN≈chunk_token_num/3retrieval 时用 MaxSim可仅在 reranker 阶段使用 | 在精确匹配上比 cross-encoder 快 510×质量接近 |
| **语义路由 / 自适应权重** | 先用一个轻 LLM或 query classifier判定 query 类型lookup / concept / list / multi-hop / temporal路由到 `{BM25权重, vector权重, 是否使用 Graph, 是否使用 Rerank}` | 替代当前写死的 `0.05/0.95`可灰度query 哈希 % 100 < 5 上新策略) |
| **多向量召回融合** | 同 chunk 同时索引 BM25、dense、sparse 三类retrieval 后用 RRF (Reciprocal Rank Fusion) 融合 | 工程上 RRF 不需训练,落地最快 |
#### 2.3 接口改造点
- 新增 `SparseEmbedder(Embedder)` 实现:返回 `SparseVector(indices, values)`ES mapping 增加 `q_sparse_<vocab>_vec` 字段,使用 `rank_features`/`sparse_vector` 类型ES ≥ 8.11)。
-`rag/nlp/search.py:Dealer.search()`(第 387 行起)把 `FusionExpr` 的硬编码权重改为 `ctx.fusion_weights`,由 `Retriever` 实现的 `ctx` 参数注入。
- 新增 `RouterRetriever(Retriever)`:组合多个底层 retrieverDenseRetriever / SparseRetriever / GraphRetriever按 router 决策选择 / 融合。
- ColBERT 仅在 Reranker 层接入:新增 `ColBERTReranker(Reranker)` 实现;接 `Reranker` 协议,**完全不影响**调用方。
#### 2.4 工作量估计
- RRF 多路融合(**Quick PoC见 §2****0.5 人周**
- SPLADE 接入:**2 人周**(含 ES mapping、批量重建索引
- 语义路由:**2.5 人周**(含 router 训练数据采集、灰度框架)
- ColBERT Reranker**3 人周**GPU 部署 + 蒸馏小型化)
- 合计:**~8 人周**
#### 2.5 风险与依赖
- ⚠️ **重建索引成本**:现网 KB 数量 × chunk 数 × 维度,估算总耗时;需要提供"灰度索引切换"工具(详见 §6 路线图 P0
- ⚠️ **路由器误判**:错路由比无路由更糟;必须配 fallback路由失败回退到当前默认 0.05/0.95)。
- ⛓️ **依赖 [S3-T1]**`Retriever` Protocol 落地后才能优雅接入路由器;否则会污染 `Dealer` 类。
---
### D3. 知识图谱增强(基于 [S2-T4] GraphRAG 的延伸)
#### 3.1 触发场景
- 法务/合规库每月新增 200+ 条法规:当前必须 **重建整个图**CI 跑 1 小时;用户要求"增量入库 + 增量图更新"。
- 报错排查:"TS_001 错误码可能由哪些组件触发?" — 需要从 **错误码** 节点 N-hop 走到 **组件** 节点;当前 KGSearch 走的是文本相似度匹配实体,**不是路径推理**。
- 团队要求"为什么是这个答案" — 需要把推理路径A→关系1→B→关系2→C作为 citation 一同返回,提供 **可解释性**
#### 3.2 技术方案
| 子方向 | 方案 | 现状 → 目标 |
|-------|------|------------|
| **增量图演化** | 在 `tasks.py:build_graphrag_for_document` 链上插入 `GraphMerge` 阶段:新文档抽出的子图与全图做 **节点对齐 + 关系合并 + 冲突标记**;保留 `version_int` 字段记录每条边的"加入/失效"版本号 | 一次构建 → 增量更新 + 时间溯源 |
| **路径解释性** | KGSearch.retrieval() 输出新增 `evidence_path: list[Edge]`;在 prompt 组装时把路径作为引用源;前端渲染"由 X→Y→Z 推断" | 黑盒答案 → 带溯源链路 |
| **Neo4j 双引擎** | 当前图存在 ES 的 chunk 表里(`knowledge_graph_kwd` 字段),不能利用图算法;引入 Neo4j 作为 **算法引擎**PageRank 已在 ES 里跑过,但 Cypher 跑社区检测、最短路径远更便利ES 仍负责文本召回Neo4j 负责图算法。README 已声明 Neo4j 是组件,**只是 RAG 层没用** | 单引擎 → 检索 ES + 图算法 Neo4j 混合 |
| **温度敏感的图衰减** | 复用 `core/memory/forgetting_engine` 的 Ebbinghaus 实现到图边权重:长期未被命中的实体/关系权重衰减;与 D4 共享一套衰减逻辑 | 静态图 → 动态、有"记忆"的图 |
| **自动本体演化** | 借鉴 `core/memory/ontology_services/General_purpose_entity.ttl`,定期用 LLM 检查"这批新加的实体类型是否应该归并到已有类型?" | 类型膨胀 → 受控演化 |
#### 3.3 接口改造点
- 新增 `GraphRetriever(Retriever)` 实现,包装现有 `KGSearch`;输出 `ScoredChunk.metadata` 增加 `evidence_path``list[(from_entity, relation, to_entity, confidence)]`)。
- 新增 `GraphStore` 抽象层:`add_subgraph / merge / query_path / pagerank / community_detect`;实现两个:`ESGraphStore`(保留现状)、`Neo4jGraphStore`(新增)。`graphrag/general/index.py` 现在直接操作 `nx.Graph`,全部替换为 `GraphStore` 调用。
-`tasks.py` 的 Celery 链增加 `graph_merge_task`:依赖 `build_graphrag_for_document`,处理增量合并;需要分布式锁(已有 `redis_lock.py` 可用)。
- Prompt 层(`prompts/generator.py`)新增 `evidence_aware_citation_prompt`:把 `evidence_path` 作为额外上下文注入。
#### 3.4 工作量估计
- 增量图演化(最小可用):**3 人周**(最复杂的是合并冲突的实体消歧)
- 路径解释性:**2 人周**
- Neo4j 双引擎:**3 人周**(含 Cypher 工具集、Neo4j 数据迁移脚本)
- 图衰减 + 本体演化:**2 人周**(与 D4 共享代码)
- 合计:**~10 人周**
#### 3.5 风险与依赖
- ⚠️ **实体消歧难度**:跨文档同名异义("苹果"=公司 / 水果);建议用现有 `entity_resolution.py` 改造,但需要补全单元测试。
- ⚠️ **Neo4j 运维成本**:用户已在 README 声明依赖 Neo4j但当前 RAG 层零调用;引入意味着同时管理两个图的一致性。建议把 Neo4j 定位为"算法只读 / 异步同步",避免双写一致性。
- ⛓️ **依赖 [S3-T1]**`GraphStore``Retriever` 协议落实,否则会跨层塌方。
---
### D4. 对话记忆 ↔ RAG 协同(短期 / 长期 / 检索召回三段桥接)
> **MemoryBear 的核心特色**。当前最大产品差异化机会就在这里——`core/memory/` 与 `core/rag/` 是 **两条独立链路**,没有联动。
#### 4.1 触发场景
- 用户在第 3 轮说"我对海鲜过敏",第 7 轮问"今晚吃什么?" — 当前 RAG 层无任何记忆能力,每次只看当轮 query。
- 多 Agent 协作:售前 Agent 收集到客户预算,售后 Agent 重新询问 — 跨 Agent 记忆需要从 `core/memory` 读出 + 注入 RAG 检索 query 重写。
- 长对话上下文压缩:第 50 轮时,前 40 轮对话需要 **被遗忘但保留要点**,要点变成"用户档案 chunk"加入 KB。
#### 4.2 短期 / 长期 / 检索召回的边界(产品决策)
| 维度 | 短期记忆Working Memory | 长期记忆Episodic / Semantic | 检索召回KB |
|------|---------------------------|--------------------------------|---------------|
| 存储位置 | Redis单 session 8KB cap | Neo4j + ES`core/memory` | ES`core/rag` |
| 生命周期 | session< 24h | 永久(按 forgetting curve 衰减) | 永久(人工治理) |
| 写入触发 | 每轮 user/assistant message | reflection_engine 周期性提炼 | 文档入库流水线 |
| 召回时机 | 始终注入 prompt | LLM 重写 query 时 + 主动检索 | RetrievalNode 命中 |
| 数据契约 | `list[Msg]` | `MemoryItem(content, strength, type, ts)` | `DocumentChunk` |
| 可信度 | 高(用户原话) | 中LLM 提炼) | 高(人工审核) |
> **决策原则**"用户原话进短期,提炼事实进长期,世界知识进 KB。" 三者不能互相替代。
#### 4.3 技术方案
- **MemoryAugmentedRetriever**:在 `RouterRetriever` 之外再包一层retrieve 前用 `core/memory.read_services` 拿到当前 user 的 top-K 长期记忆条目,**改写 query**"今晚吃什么?" + 长期记忆"对海鲜过敏" → "今晚吃什么?避免海鲜")。
- **Memory Citation**:检索结果与长期记忆条目并入同一 `chunks` 列表prompt 模板区分两者来源("用户提及" vs "知识库"),避免幻觉混淆。
- **反向写入**:每轮对话产出后,让 `core/memory.write_router` 决定 是否需要把"新事实"写入长期记忆;这一步 **复用** `core/memory.agent.langgraph_graph.write_graph`(已存在)。
- **遗忘对齐**:把 `core/memory/forgetting_engine` 的 ACT-R 计算复用到 KB chunk 上D3 已提);让"很少被命中的过期 KB chunk"自动沉睡,反向触发治理团队复审。
#### 4.4 接口改造点
-`workflow/nodes/knowledge/node.py``KnowledgeRetrievalNode.execute()` 中注入 `MemoryService`:当节点配置里 `enable_memory=true` 时,先调 `memory_service.recall(user_id, query)` 拿记忆,再传给 `Retriever.retrieve(query, ctx={memory: ...})`
- 新增 `MemoryAwareRetriever(Retriever)` 实现,包装任一底层 Retriever。
- Workflow Node 配置 `KnowledgeRetrievalNodeConfig` 增加 `memory_strategy: Literal["off", "context_only", "rewrite_query", "merge_chunks"]`
- Prompt 模板新增 `<MEMORY>` 段落。
#### 4.5 工作量估计
- 单向memory → retrieval**3 人周**
- 双向retrieval 结果反写 memory**2 人周**(大部分代码已在 `core/memory` 存在)
- 遗忘对齐 + 治理触发:**2 人周**(与 D3 共享)
- 合计:**~7 人周**
#### 4.6 风险与依赖
- ⚠️ **隐私边界**:长期记忆是 **per-user**KB 是 **per-tenant**;混淆会导致跨用户泄露。设计时必须 user_id 级强隔离code review 重点。
- ⚠️ **Prompt 长度膨胀**:记忆 + KB 双源;如果未做摘要,长对话场景 token 成本翻倍;必须配合记忆摘要(已有 `summary4memory.md`)。
- ⛓️ **依赖 [S3-T1]**`Retriever / Reranker` 协议;强依赖 [S2-T6] 的 E2E 时序图明确两条链路的衔接点。
---
### D5. 评估与反馈闭环(用户反馈 → Reranker 微调)
#### 5.1 触发场景
- 答案错了 / 引用不对,用户点👎 — 当前数据 **进了日志,没人消费**
- 同一 query 在不同时段表现波动 → 需要离线 A/B 评估。
- 业务方问"再加一个 KB 之后效果到底变好还是变差?" — 没有可量化的回归指标。
- README 给的 F1/BLEU/J 在论文中实现过,**但仓内没有这套代码**,每次评估靠手工。
#### 5.2 技术方案(双轨:评估在线化 + 反馈学习)
##### 5.2.1 评估轨:离线 / 在线 / CI 三层
| 层级 | 内容 | 工具 |
|------|------|------|
| **离线评估集** | 每 KB 维护一个 `eval_cases.jsonl``{query, ideal_chunks, ideal_answer, hard_negatives}`;增量构建(每周从用户问句 + 答疑团队补充) | DSL + Excel 导入工具 |
| **在线指标** | `Hit@K / MRR / nDCG / Citation Coverage / Hallucination Rate / Latency P50/P95`;通过 OpenTelemetry 埋点写入 Prometheus | OTel + Prometheus + Grafana |
| **CI 评估** | 每个 PR 跑核心 KB 的回归集;指标低于 baseline n% 时阻塞合并 | RAGAS开源+ 自研判分 prompt |
##### 5.2.2 反馈学习轨:从👍/👎到 Reranker 微调
```
用户反馈(👍/👎/edit
↓ event log
事件清洗(同一 query 多个 chunk 评分)
形成 (query, positive_chunk, negative_chunk) 三元组
├─ 短链:在线 PairWise 调整 BM25/dense 权重D2 路由器配置)
└─ 长链:周/月一次离线训练 Cross-Encoder reranker基础模型用 bge-reranker-base 蒸馏)
新 reranker 走 D6 灰度框架上线
评估轨自动验证收益
```
#### 5.3 接口改造点
- 新增 `EvaluationProtocol``{evaluate(query, retrieved, generated, ground_truth) -> Metrics}`;在 OpenTelemetry trace 末尾自动落 Prometheus。
- `RedBearRerank` 改造:接入 `LocalCrossEncoderRerank(Reranker)` 子类,加载本地 ONNX/TorchScript 模型;可与 Jina/DashScope 并存于工厂。
- 反馈采集:复用 `core/memory` 的事件总线(如有)或新建 `feedback_event` 表;前端组件加 thumbscitation 点击行为也作为隐式反馈。
- 训练 pipeline 独立仓 / 独立服务产物ONNX通过模型注册表用现有 `ModelConfig` 表扩展即可)滚动上线。
#### 5.4 工作量估计
- 评估指标埋点 + Grafana 看板:**1.5 人周**
- 离线评估集 + RAGAS CI 集成:**2 人周**
- 反馈采集 + 三元组清洗:**1 人周**
- Cross-Encoder 蒸馏训练 pipeline**3 人周**(含数据扩充、训练脚本、产出 ONNX
- 合计:**~7.5 人周**
#### 5.5 风险与依赖
- ⚠️ **冷启动**:刚上线时反馈数据 < 1k 不足以训练;必须先用大模型 LLM-as-Judge 合成训练数据(现成 prompt 在 `prompts/generator.py` 可借鉴)。
- ⚠️ **反馈污染**:恶意 / 误点;需要置信度过滤(同一 user 短时多次相反反馈丢弃)。
- ⛓️ **依赖 [S3-T1]** 的可观测性方案,否则数据采不到。
- ⛓️ **依赖 D2 的语义路由**,否则没有"权重可调"的注入点。
---
### D6. 自适应检索路由Adaptive Retrieval Routing
> 这是 D2 中"语义路由"的工程化升级版,独立列出是因为它会**统一**所有检索能力dense / sparse / graph / memory / web是 RAG 系统的中央调度器。
#### 6.1 触发场景
- 同一用户在同一 session 内:第 1 个问题需要走 KB第 2 个问题需要走 Web 搜索("今天的新闻"),第 3 个问题需要 Graph 推理 — 当前必须用户手动切模式。
- "你刚才推荐的方案做不了"(指代消解)→ 需要先走对话记忆,再决定是否检索;当前都是无脑全检索。
#### 6.2 技术方案
| 决策类型 | 输入 | 输出 |
|---------|------|------|
| 是否需要检索 | query + 短期记忆 | `bool need_retrieval` |
| 检索来源 | query 类型 | `[KB_id, Graph_flag, Web_flag, Memory_flag]` |
| 检索策略 | query 类型 + 用户场景 | `(retriever_name, top_k, fusion_weights, rerank_id)` |
| 兜底 | 第一次检索结果差 | 触发 query rewriting + 二次检索 |
实现:
- 路由器 = 小型 LLM如 1.5B3B+ rule-based fallback输出结构化 JSON。
- 训练数据来源D5 的反馈数据 + 标注团队人工标 1k 条。
- 推理用 vllm 或 SGLang 自托管P95 延迟控制在 50ms。
#### 6.3 接口改造点
-`RetrieveType` enum 改造成 strategy与 D2 共享的 `RouterRetriever`workflow 层调用方不再选模式,而是传入 query。
- 新增 `RoutingPolicy` 配置实体:可被工作空间管理员通过 UI 编辑(默认策略 + 灰度策略)。
- 与 D5 形成闭环:评估指标决定路由器升级时机。
#### 6.4 工作量估计
- 规则+LLM 路由器最小可用:**2 人周**
- 完整训练 / 灰度 / 配置 UI**5 人周**
- 合计:**~7 人周**
#### 6.5 风险与依赖
- ⚠️ **路由器变成单点**:必须有 fallback 到当前默认策略。
- ⛓️ **强依赖 D2 + D5**;不建议独立做。
---
## 2. Quick PoC 路径(≤ 1 周可见效果)
### PoC-ARRF 多路融合检索(属 D2
**目标**:现网 KB 在不重建索引、不改 schema 的前提下,加入 BM25 + dense 各自独立 top-50 → RRF 融合 → 同一接口返回。1 周内拿到 A/B 数据。
**改动范围**(最小集):
- `rag/nlp/search.py:Dealer.search()` 拆为两步:先单独跑 BM25`emb_mdl=None`),再单独跑 dense无 BM25合并时用 RRF。
- 增加 feature flag `RETRIEVAL_FUSION_MODE = {"weighted", "rrf"}`,默认 weighted不影响现网
**预期收益**:在长尾 lookup query 上 Hit@10 +510pp参考社区数据。无负向风险因为 weighted 路径保留。
**PoC 代码草案**(伪代码,约 30 行;正式实现需走完整 PR + 评估):
```python
# rag/retrieval/rrf.py新增
def rrf_merge(rankings: list[list[ScoredChunk]], k: int = 60, top_k: int = 20) -> list[ScoredChunk]:
"""Reciprocal Rank Fusion: score = Σ 1/(k + rank_i)。
rankings: 多个独立排序结果,每个内部按相关度降序。
"""
score_map: dict[str, float] = {}
chunk_map: dict[str, ScoredChunk] = {}
for ranking in rankings:
for rank, chunk in enumerate(ranking, start=1):
cid = chunk.metadata["doc_id"]
score_map[cid] = score_map.get(cid, 0.0) + 1.0 / (k + rank)
chunk_map[cid] = chunk # 保留首次见到的对象
merged = sorted(chunk_map.values(),
key=lambda c: score_map[c.metadata["doc_id"]],
reverse=True)
for c in merged:
c.metadata["score_rrf"] = score_map[c.metadata["doc_id"]]
return merged[:top_k]
# 调用侧rag/nlp/search.py:Dealer.search 增量改造)
if os.getenv("RETRIEVAL_FUSION_MODE", "weighted") == "rrf":
bm25_hits = self._search_bm25_only(req, ...)
dense_hits = self._search_dense_only(req, ...)
return rrf_merge([bm25_hits, dense_hits], k=60, top_k=req.get("topk", 20))
# else: 走现有 weighted 路径
```
### PoC-BMemory-Augmented Query Rewrite属 D4
**目标**:把 `core/memory.read_services` 已有的"长期记忆召回"接到 `KnowledgeRetrievalNode` 之前,做 query 改写。1 周内对 1 个内部 demo 应用上线。
**改动范围**
- `KnowledgeRetrievalNode.execute()` 第一行加 5 行:拿 user_id已有 `user_ids`),调 `memory_service.get_user_summary(user_id)`,把 summary 拼到 query 前。
- 新增 feature flag `MEMORY_AUGMENT_RETRIEVAL = false`(默认关闭)。
- 不改 prompt不改 schema不改 ES。
**预期收益**:在多轮对话场景下,第 N 轮 query 的指代消解正确率提升无回归风险flag 默认关)。
```python
# workflow/nodes/knowledge/node.py:KnowledgeRetrievalNode.execute() 头部增量
if os.getenv("MEMORY_AUGMENT_RETRIEVAL") == "true" and user_ids:
from app.services.user_memory_service import get_user_summary
summary = get_user_summary(user_ids[0], ttl_sec=3600) # 已存在 / 类似函数
if summary:
query = f"[用户背景: {summary}]\n{query}"
```
> **注意**:上述两段代码均为 PoC 草案真实落地需要1完整单测2评估对比3feature flag 走配置中心4权限审查D4 涉及隐私)。
---
## 3. 优先级矩阵(用户价值 × 实现成本 × 风险)
> 评分 155 最高 / 5 最低)。建议落地顺序按"用户价值高 + 成本低 + 风险低"加权。
| 方向 | 用户价值 | 实现成本 (越低越好) | 风险 (越低越好) | 综合分V × 1/√(C×R) | 建议落地阶段 |
|------|---------|--------------------|----------------|----------------------|------------|
| **D2-PoC RRF 融合** | 4 | 5 (0.5 人周) | 5 (无回归) | 8.0 | 立即Sprint-3 内) |
| **D4-PoC Memory Rewrite** | 4 | 5 (0.5 人周) | 4 (隐私) | 7.2 | 立即Sprint-3 内) |
| **D5 评估埋点 + Grafana** | 5 | 4 (1.5 人周) | 5 | 5.6 | 短期1 月) |
| **D5 RAGAS CI** | 4 | 4 | 5 | 4.5 | 短期1 月) |
| **D2 SPLADE 接入** | 4 | 3 (2 人周) | 4 (索引重建) | 3.7 | 短期1 月) |
| **D4 完整双向集成** | 5 | 3 (5 人周) | 3 (隐私 / token) | 3.5 | 中期2 月) |
| **D5 Reranker 微调** | 4 | 3 (3 人周) | 3 (冷启动) | 2.7 | 中期2 月) |
| **D6 自适应路由** | 4 | 2 (5 人周) | 3 | 2.3 | 中期3 月) |
| **D1 多模态 L1基线** | 3 | 4 (1.5 人周) | 4 | 3.0 | 短期1 月) |
| **D1 多模态 L2 跨模态** | 5 | 2 (3 人周) | 3 (GPU) | 2.5 | 中期3 月) |
| **D3 增量图演化** | 4 | 2 (3 人周) | 2 (实体消歧) | 2.0 | 中长期34 月) |
| **D3 Neo4j 双引擎** | 3 | 2 (3 人周) | 2 (运维) | 1.5 | 长期46 月) |
| **D1 多模态 L3 视听统一** | 3 | 1 (4 人周) | 2 (GPU + diarization) | 1.1 | 长期6 月+ |
| **D3 自动本体演化** | 2 | 2 | 2 | 1.0 | 长期 (按需) |
> **维度说明**
> - 用户价值高优先级业务场景toB 客户)调研访谈得分。
> - 实现成本人周折算1 人周=1 分6 人周=2 分10 人周=1 分)。
> - 风险:含技术风险 + 数据迁移 + 上线回滚 + 安全 / 隐私。
> - 综合分用 `V / sqrt(C×R)` 倒数化,**仅作排序参考**,不取代产品/架构会判断。
---
## 4. 落地路线图Roadmap
```mermaid
gantt
title MemoryBear RAG 后续迭代 路线图
dateFormat YYYY-MM-DD
axisFormat %m/%d
section Sprint-3 (现 Sprint)
PoC-A RRF 融合 (D2) :a1, 2026-06-02, 5d
PoC-B Memory Rewrite (D4) :a2, 2026-06-02, 5d
section 短期 (1 个月)
评估埋点 + Grafana (D5) :s1, 2026-06-09, 7d
RAGAS CI (D5) :s2, after s1, 7d
SPLADE 接入 (D2) :s3, after s1, 10d
多模态 L1 基线 (D1) :s4, 2026-06-09, 7d
section 中期 (2-3 个月)
Memory ↔ RAG 双向集成 (D4) :m1, after s2, 25d
Reranker 微调 pipeline (D5) :m2, after s3, 15d
自适应路由 (D6) :m3, after m1, 25d
多模态 L2 跨模态 (D1) :m4, after s4, 15d
section 长期 (3-6 个月)
增量图演化 (D3) :l1, after m1, 20d
Neo4j 双引擎 (D3) :l2, after l1, 15d
多模态 L3 视听统一 (D1) :l3, after m4, 20d
本体演化 (D3) :l4, after l2, 10d
```
> 所有阶段分别绑定一组 OKR + 评估指标D5 提供数据),未达指标停止下阶段。
---
## 5. 风险与依赖总表
| 类型 | 风险 | 缓解策略 |
|------|------|---------|
| 架构 | [S3-T1] 接口抽象未落地,本路线图全部方向受阻 | Sprint-3 内先把 `Retriever / Reranker / Embedder / Generator` 4 个 Protocol 落地([S3-T1] 必交付项) |
| 数据 | 索引重建D1/D2/D3导致服务不可用 | 灰度索引切换工具:双写期 + 流量按租户灰度 + 一键回滚 |
| 隐私 | D4 跨用户记忆泄露 | user_id 级强隔离 + 单元测试覆盖 + 上线前安全 review |
| 资源 | D1/D6 引入 GPU 依赖 | 优先走托管 API 跑通 PoC自托管列入 long-term需要预算评审 |
| 治理 | D5 评估集质量低 → CI 阻塞误判 | 评估集双人复核 + 周复盘 + 例外白名单 |
| 运维 | D3 Neo4j 双引擎一致性 | 定位 Neo4j 为算法只读,从 ES 异步同步;不双写 |
| 业务 | 路线图与产品 PRD 脱节 | 与 [@产品需求分析师] 在 Sprint-3 启动前对齐 1 次 |
---
## 6. 与 [S3-T1] / [S3-T3] 的对齐清单
- ✅ 每个方向都标注了"接口改造点",所有改造均落到 [S3-T1] 提议的 `Retriever / Reranker / Embedder / Generator / GraphStore / Loader` Protocol不新增其它接口。
- ✅ 所有方向有"工作量、风险、依赖"三件套,可被 [S3-T3] 终审按统一模板核对。
- ✅ Quick PoC 已覆盖 D2 与 D4 各 1 条(≥ 2 条要求达成)。
- ✅ 优先级建议已按"用户价值 × 实现成本 × 风险"三维评分给出,并配有路线图甘特图。
- ✅ 多模态、混合搜索、KG 增强、对话记忆、评估闭环均覆盖5/5额外补充自适应路由作为联动方向。
— END —