Files
2026Technology-Competition/docs/rag-layer-design.md
T
lhl 3decdfc31c feat(rag): v1 rerank 精排 + bge-m3 多语言切换(T6/T11 架构审查整改)
- T6 (Issue6): RerankConfig(enabled/model=BAAI/bge-reranker-v2-m3/device)
  - rag-layer-design §6.3 Rerank 精排:窗口=RRF top-10、候选≤top_k 跳过、
    故障降级 RRF 原序;原 §6.3-6.6 顺延 6.4-6.7
  - config-design §5 新增 rerank 段;design §5.5 检索策略加 rerank
- T11 (OV2): EmbeddingConfig.model 默认 bge-small-zh-v1.5 → BAAI/bge-m3(日文语料)
  - rag-layer-design 选型表/依赖表/manifest/流程图同步 + 新增 §2.3 日文样本验证
  - design.md / implementation-plan 4.3 / config-design embedding 同步
- 新增 test_rag_design_consistency.py 一致性门禁(6 用例防文档漂移)
- TDD: RED(默认模型仍旧 + rerank 字段不存在)→ GREEN → 全量 198 passed / 100.00%(996 stmts/252 br)
2026-08-12 11:32:28 +08:00

712 lines
25 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.
# RAG 基础设施层详细设计
> 版本: v1.0 | 日期: 2026-07-30 | 状态: 初版
>
> 本文档是 `docs/design.md` 第5章(RAG 基础设施层)的详细展开。
---
## 目录
1. [定位与职责](#1-定位与职责)
2. [技术选型](#2-技术选型)
3. [文档分割策略](#3-文档分割策略)
4. [存储架构](#4-存储架构)
5. [版本管理](#5-版本管理)
6. [检索引擎](#6-检索引擎)
7. [规则冲突处理](#7-规则冲突处理)
8. [集成接口](#8-集成接口)
9. [存储适配层(Storage Adapter](#9-存储适配层storage-adapter)
10. [降级与容错](#10-降级与容错)
11. [v2 迭代预留](#11-v2-迭代预留)
12. [与 design.md 的关系](#12-与-designmd-的关系)
---
## 1. 定位与职责
RAG 不是独立 Agent,而是 **Parser 与 Writer/Impact/QA 之间的基础设施层**。它负责:
- 接收 Parser 解析后的规则文档,构建**规则手册**(持久化存储)
- 为 Writer / Impact / QA 提供**统一规则检索入口**
- 管理规则手册的**版本生命周期**(更新、回退、追溯)
### 1.1 存储内容分类
RAG 层存储三类内容,分类在 Parser 解析时完成:
| 类型 | 内容 | 检索方 |
|------|------|--------|
| **Type A: 写入规则** | 记入规则、图表规则、字体/格式规范 | Writer Agent(每章生成时) |
| **Type B: 设计规则** | 架构约束、安全要求、设计方针 | Impact Agent(关联推理时)+ Writer |
| **Type C: 参考设计文档**(可选)| 过往概要设计书、设计决策记录 | Impact Agent(改修场景参考)|
> 说明:Type C 为**可选增强**,初期聚焦 Type A + Type B。Type C 文档若纳入,由用户显式上传到「参考文档」分类。
---
## 2. 技术选型
| 选型点 | 决策 | 说明 |
|--------|------|------|
| 向量数据库 | **Chromav1 唯一)** | 初期用 Chroma(轻量本地,嵌入进程,Docker 部署最简);通过 Storage Adapter 抽象保留接口,Qdrant 切换为 v2 预留(Scope 缩减裁定,T5 整改)|
| Embedding 模型 | **bge-m3**(本地运行) | 多语言模型(中/日/英),适配实际日文语料(OV2/T11);统一配置 `config/rag.yaml``embedding.model`(见 docs/config-design.md §5);稠密向量 1024 维,CPU 可跑 |
| Rerank 模型 | **bge-reranker-v2-m3**(v1 引入,I6/T6) | 精排阶段使用;统一配置 `config/rag.yaml``rerank.model`;默认启用,可通过 `rerank.enabled=false` 关闭降级为纯 RRF 结果 |
| 实现方式 | **手写实现**(不引入 LangChain/LlamaIndex | chromadb + rank_bm25 + sentence-transformers 直接实现;依赖轻、可控性强、与现有轻量技术栈一致 |
### 2.1 为什么手写而非框架
| 维度 | 分析 |
|------|------|
| 检索效果 | 相同(Embedding + BM25 + RRF 为标准算法,框架也调用同样的库)|
| 分割质量 | 本项目需要「按格式适配分割」(Word标题层级/Excel规则块/PPT页),框架无现成方案,仍需自写 |
| 可追溯性 | 手写可完美对接 Provenance 体系(source_uri / headings|
| 依赖负担 | 轻(3 个库);框架引入 langchain 全家桶 ~100+ 传递依赖 |
| 调试维护 | 手写直接可控;框架封装层级深,出问题难定位 |
| 代码量 | 向量+BM25+RRF 约 100~200 行,不值得为此引入重框架 |
### 2.2 关键依赖
```
chromadb # 向量存储(Chroma
sentence-transformers # Embedding 编码(bge-m3+ Rerank 精排(bge-reranker-v2-m3
rank_bm25 # BM25 关键词检索
pydantic # 数据模型(RuleChunk 等)
```
### 2.3 多语言与日文样本验证(OV2/T11)
实际规则语料为**日文**(要件定义/概要设计/记入规则),因此:
- Embedding 采用多语言模型 **bge-m3**(支持中/日/英,稠密向量 1024 维)
- Rerank 采用多语言精排模型 **bge-reranker-v2-m3**Cross-Encoderquery×chunk 打分)
- **日文样本验证**(Phase4 实施时执行):用真实日文规则片段(如「見出しは「1.1」形式で記述する」)构造检索用例,断言:
1. 语义近义日文 query 能召回对应规则(top-5 命中)
2. rerank 后相关片段排位不低于 RRF 原始排位(不劣化)
3. 日英混合/片假名术语 query 不空召回
---
## 3. 文档分割策略
### 3.1 按格式适配分割(业界最佳实践)
规则文档为多格式(Word / Excel / PPT),分割器需感知格式:
```
规则文档(多格式)
├── 📄 Word (.docx) — 标题结构最清晰
│ 分割单位: Heading 1/2/3 层级 → 每个小节一个 chunk
│ 表格处理: 表格整体作为一个 chunk(标题 + 表格内容)
│ 列表处理: 列表项随所属小节
├── 📊 Excel (.xlsx) — 表格型规则
│ 分割单位: 每个 Sheet 的「规则块」为 chunk
│ (规则块 = 表头 + 数据行组,按语义分组切分)
│ 例: 记入规则的「表头行 + 5条规则行」作为一个 chunk
└── 📽 PPT (.pptx) — 幻灯片要点型
分割单位: 每 1~2 页幻灯片作为一个 chunk
(单页内容少时合并,保证 chunk 有意义)
标题+正文分别作为 chunk 文本的一部分
```
### 3.2 统一 Chunk 结构
```python
@dataclass
class RuleChunk:
chunk_id: str # 形如 rules-write_v3_001
doc_id: str # 源文档名
doc_type: str # "word" | "excel" | "ppt"
content: str # 纯文本内容(含结构标记)
headings: list[str] # 所属标题路径,如 ["3. 記入規則", "3.2 表の書き方"]
source_uri: str # 可追溯来源
position: int # 文档内顺序
token_count: int # token 数(用于后续优化)
```
### 3.3 分割器实现
```
Chunking Pipeline
├── WordChunker # 遍历 python-docx 段落,按 Heading 样式切分
├── ExcelChunker # 遍历 openpyxl 行,按「表头+数据行组」切分
└── PPTChunker # 遍历 pptx 幻灯片,1~2页合并为一个 chunk
```
分割规则:
- **chunk 上限**:默认 max_tokens=512,超出时按语义段落追加切分
- **chunk 下限**:内容过短(< 30 tokens)时与相邻 chunk 合并(PPT 场景)
- **保留结构**:headings 记录标题路径,供检索后的上下文组装
---
## 4. 存储架构
### 4.1 目录结构
```
/data/shared/rules-handbook/ # 规则手册(全用户共享)
├── chroma/ # Chroma 持久化数据目录
│ ├── v1/
│ │ ├── rules-write/ # Collection: 写入规则 v1
│ │ ├── rules-design/ # Collection: 设计规则 v1
│ │ └── ref-docs/ # Collection: 参考设计文档 v1(可选)
│ └── v2/
│ ├── rules-write/
│ ├── rules-design/
│ └── ref-docs/
├── chunks/ # 分割后的文本(JSON,可追溯)
│ ├── v1/
│ │ ├── rules-write/
│ │ │ ├── chunk_001.json
│ │ │ └── ...
│ │ └── rules-design/
│ └── v2/
└── manifests/ # 版本清单(元数据)
├── v1.json
└── v2.json
```
### 4.2 Collection 命名规范
```
格式: {content_type}-v{version}
例:
rules-write-v3 # 写入规则 v3
rules-design-v3 # 设计规则 v3
ref-docs-v3 # 参考设计文档 v3(可选)
```
### 4.3 版本清单 manifest.json
```json
{
"version": "v3",
"created_at": "2026-07-30",
"active": true,
"source_files": [
{"name": "记入规则.docx", "hash": "sha256:...", "type": "write", "built": "reuse_from_v2"},
{"name": "图表规则.xlsx", "hash": "sha256:...", "type": "write", "built": "rebuilt"},
{"name": "设计方针.docx", "hash": "sha256:...", "type": "design", "built": "reuse_from_v2"}
],
"collections": {
"rules-write": {"chunk_count": 130, "embedding_model": "bge-m3", "rerank_model": "bge-reranker-v2-m3"},
"rules-design": {"chunk_count": 45, "embedding_model": "bge-m3", "rerank_model": "bge-reranker-v2-m3"}
},
"active_previous": "v2"
}
```
> 说明:`collections[*].embedding_model` 为版本清单的**记录字段**,记录该版本实际使用的模型名;其值来源于统一配置 `config/rag.yaml` 的 `embedding.model`(见 docs/config-design.md),两者保持一致,不再单独配置。
### 4.4 Chunk 持久化(JSON
> 说明:示例 content 为模拟日文规则文档的原始文本(技术必要保留)。
```json
{
"chunk_id": "rules-write_v3_001",
"doc_id": "记入规则.docx",
"doc_type": "word",
"content": "見出しは「1.1」形式…",
"headings": ["3. 記入規則", "3.2 見出しの書き方"],
"source_uri": "记入规则.docx#見出し!3.2",
"position": 15,
"token_count": 240
}
```
---
## 5. 版本管理
### 5.1 文档级增量 + 版本组合
规则手册 = 多个文档(记入规则、图表规则、设计方针…)。当**只更改其中一个文档**时,避免全量重建。
```
更新时流程:
1. 计算所有上传文档的内容 hash(sha256
2. 与当前激活版本的 manifest 对比
3. 识别出「变化/新增/删除」的文档
4. 只对变化的文档重新解析 → 分割 → embedding
5. 未变化的文档直接复用上一版本的 chunks + embeddings
6. 生成新版本 Collection
```
### 5.2 示例场景
用户上传 3 个规则文档,**只修改了「图表规则.xlsx」**:
```
更新前(handbook-v2:
记入规则.docx hash=A → 100 chunks
图表规则.xlsx hash=B → 30 chunks
设计方针.docx hash=C → 45 chunks
用户更新「图表规则.xlsx」→ hash=B'(内容变了)
更新后(handbook-v3:
记入规则.docx hash=A → 100 chunks 【复用 v2,不重新 embedding】
图表规则.xlsx hash=B' → 32 chunks 【重新构建】
设计方针.docx hash=C → 45 chunks 【复用 v2,不重新 embedding】
```
### 5.3 变化类型处理
| 场景 | 处理方式 |
|------|---------|
| 文档内容变化 | 只重建该文档 |
| 新增文档 | 只构建新增文档 |
| 删除文档 | 新版本不含该文档,旧版本仍保留 |
| 所有文档未变化 | 不创建新版本(提示用户「无变化」)|
### 5.4 会话锁版本
- **会话开始**(用户上传要件定义时)锁定当时激活的规则版本
- 整个生成过程固定用该版本,避免生成中途规则更新导致前后不一致
- 设计书元数据记录「使用的规则版本号 + 冲突决策列表」,可完全追溯
### 5.5 回退策略
```
回退到 v2:
manifest v2 的 active 字段 → true
会话锁版本逻辑不变(新会话锁 v2)
v3 保留不删除(可再回退)
```
### 5.6 存储冗余说明
v3 会复制未变化文档的 embeddings。对规则文档几 MB 的量级,冗余可接受,且换来逻辑简单与完全可追溯。
---
## 6. 检索引擎
### 6.1 检索请求流程
```
调用方(Writer/Impact/QA
│ 传入: 检索意图 + 查询文本 + 约束
┌──────────────────────────────────────────┐
│ Retrieval Engine │
│ │
│ Intent Router(意图路由) │
│ ├── Writer → 检索 rules-write Collection
│ ├── Impact → 检索 rules-design Collection
│ └── QA → 双 Collection 都检索
│ │
│ 查询构造: │
│ ├── 查询文本 = 用户提供的 query 文本 │
│ ├── 上下文增强 = 当前章节/要素信息 │
│ └── 过滤条件 = version + category │
│ │
│ 双通道检索: │
│ ├── VectorRetriever(向量语义检索 top-10
│ │ 使用 bge-m3 编码查询 │
│ └── BM25Retriever(关键词检索 top-10
│ │
│ RRF Fusion(结果融合) │
│ └── 合并两通道结果,按 RRF 公式排序 │
│ │
│ Rerank 精排(v1 新增,I6/T6
│ └── bge-reranker-v2-m3 对候选重打分 │
│ └── 输出 top-N 个 RuleChunk │
└──────────────────────────────────────────┘
```
### 6.2 RRF 融合
```
RRF_score(d) = Σ 1 / (k + rank(d)) # k=60 常用值
示例(k=60:
向量通道排名第2: 1/(60+2) = 0.0161
BM25通道排名第5: 1/(60+5) = 0.0154
总分 = 0.0315(两通道都命中的文档分数更高)
参数:
通道 top-k = 10(各自取 top-10,扩大召回窗口)
融合后 top-k = 调用方传参(默认 5)
```
### 6.3 Rerank 精排(v1 新增,I6/T6
RRF 融合后、注入 LLM prompt 前,对候选做 **Cross-Encoder 精排**2026 主流实践:向量→rerank→精排):
```
RRF 候选(默认 top-10 窗口)
bge-reranker-v2-m3Cross-Encoder
│ 对每对 (query, chunk) 打分,输出相关性分数
按分数降序重排 → 截取最终 top_k(默认 5)
```
| 项目 | 决策 |
|------|------|
| 模型 | `BAAI/bge-reranker-v2-m3`(多语言 Cross-Encoder,与日文语料匹配) |
| 开关 | `rerank.enabled`(默认 true);false 时跳过精排,直接取 RRF 前 top_k |
| 打分窗口 | RRF 融合后 top-10 候选(与通道 top-k 一致,避免重排成本随全文增长) |
| 候选过少 | 候选 ≤ top_k 时跳过 rerank(无重排必要,节省推理) |
| 故障降级 | rerank 推理异常 → 降级为 RRF 原始顺序,不阻断检索(同 §10 容错策略) |
### 6.4 上下文增强(Contextual Enrichment
检索时不仅用 query 文本,还拼入当前上下文:
| 调用方 | 查询上下文增强 |
|--------|--------------|
| Writer | 「第3章 機能一覧」的生成 → query + 章名 + 相关要素ID |
| Impact | 「要素 F001 与 TB001 的关系」推理 → query + 要素类型 + 要素描述 |
| QA | 「校验某段内容的规则遵守」→ query + 待校验段落 |
### 6.5 各 Agent 查询构造规范
| 调用方 | query 构造方式 |
|--------|--------------|
| Writer | query = 章目标题 + 相关要素 ID + 生成意图描述 |
| Impact | query = 要素类型 + 要素描述 + 待推论的关联方向 |
| QA | query = 待校验段落内容 + 所属章 |
### 6.6 top_k 配置
`top_k` 由调用方传参,允许按章差异配置:
| 章节类型 | 建议 top_k |
|---------|-----------|
| 概要章 | 3 |
| DB 设计章 | 8 |
| 其余章 | 5 |
### 6.7 检索结果上下文组装
检索出的 chunk 注入 LLM prompt 时,保留结构信息:
> 说明:以下示例模拟日文规则文档的原始内容(规则文档本身为日文,技术必要保留)。
```
--- 适用的记入规则(来自规则手册 v3)---
【3.2 見出しの書き方】
見出しは「1.1」「1.2」形式で記述する。
(来源: 记入规则.docx#見出し!3.2
【5.1 表の書き方】
表のヘッダー行は太字で記載する。
(来源: 记入规则.docx#表!5.1
```
---
## 7. 规则冲突处理
### 7.1 冲突检测时机
在**检索引擎返回结果后、注入 LLM prompt 前**执行:
```
检索返回 top-N chunks
┌────────────────────────────────┐
│ Conflict Detector(冲突检测器)│
│ 1. 按「内容主题」对 chunks 分组 │
│ 2. 同一主题下,检测规则约束是否矛盾│
│ └ 对比: 格式(字体/字号/边距) │
│ 结构(标题层级/编号) │
│ 内容(必填项/禁止项) │
│ 3. 发现矛盾 → 标记为冲突组 │
└────────────────────────────────┘
有冲突? ──否──→ 正常注入 prompt,继续生成
用户确认介入(不阻塞整章,只阻塞该章)
```
### 7.2 冲突检测示例
> 说明:以下示例模拟日文规则文档的原始规则文本(技术必要保留)。
```
主题: 「表のヘッダー行」格式
[记入规则.docx #5.1] 表ヘッダーは太字+下線で記載する
[图表规则.xlsx #2.3] 表ヘッダーは太字のみ(下線なし)
→ 检测到矛盾:下線の有無
```
### 7.3 用户确认界面
```
─────────────────────────────────────────
⚠ 检测到规则冲突(第3章 機能一覧)
主题: 表ヘッダー行のフォーマット
┌────────────┬────────────┬──────────────┐
│ 来源文档 │ 规则内容 │ 章节出处 │
├────────────┼────────────┼──────────────┤
│ 记入规则.docx│ 太字+下線 │ 5.1 │
│ 图表规则.xlsx│ 太字のみ │ 2.3 │
└────────────┴────────────┴──────────────┘
[采用「记入规则」] [采用「图表规则」] [两规则都标注给人工]
─────────────────────────────────────────
```
### 7.4 冲突决策记录
```json
{
"conflict_id": "c-001",
"session_id": "genesis-xxx",
"chapter": "機能一覧",
"topic": "表ヘッダー行のフォーマット",
"conflicting_chunks": [
{"chunk_id": "rules-write_v3_012", "doc": "记入规则.docx", "rule": "太字+下線"},
{"chunk_id": "rules-write_v3_045", "doc": "图表规则.xlsx", "rule": "太字のみ"}
],
"user_decision": "adopt_记入规则",
"decided_at": "2026-07-30 12:00",
"resolution_uri": "generated_doc#章3"
}
```
### 7.5 冲突决策的后续影响
- 决策结果存入会话(session),**同会话内相同主题冲突不再重复询问**
- 决策记录写入设计书元数据(可追溯「本设计书如何处理了规则冲突」)
- QA 校验时,以**已决策的规则**为准,不再对已决冲突告警
---
## 8. 集成接口
### 8.1 各 Agent 的调用场景
```
Parser ──→ RAG: 构建规则手册(首次上传 / 规则更新)
调用: build_handbook(file_list, category)
返回: version_id
Writer ──→ RAG: 每章生成前检索该章相关写入规则
调用: search(session_id, query, category="write", top_k=章配置)
返回: list[RuleChunk](含冲突标记)
Impact ──→ RAG: 关联推理时参考设计规则
调用: search(session_id, query, category="design", top_k=5)
返回: list[RuleChunk]
QA ──────→ RAG: 校验时检查规则遵守(双 Collection
调用: search(session_id, query, category="write"|"design", top_k=5)
返回: list[RuleChunk]
Orchestrator ──→ RAG: 创建会话时锁定版本
调用: lock_version(session_id)
get_latest_version()
```
### 8.2 RAG Service 公开 API 一览
```python
# 构建与版本管理
class RuleHandbookManager:
def build_handbook(self, files: list[UploadedFile], categories: dict) -> str
# 增量构建,返回新版本号(无变化则返回 None)
def get_latest_version(self) -> str
def get_version(self, version_id: str) -> Manifest
def list_versions(self) -> list[Manifest]
def rollback_to(self, version_id: str) -> None
# 回退 = 重新激活指定版本(不删除任何版本)
# 会话版本锁定
class SessionVersion:
def lock_version(self, session_id: str, version_id: str | None = None) -> None
# version_id 为空时锁定当前最新版本
def get_locked_version(self, session_id: str) -> str
# 检索
class RagService:
def search(
self, *,
session_id: str,
query: str,
category: Literal["write", "design"],
top_k: int = 5,
agent: str,
) -> SearchResult
# SearchResult = {chunks: list[RuleChunk], conflicts: list[ConflictGroup]}
# 冲突决策
class ConflictHandler:
def get_pending_conflicts(self, session_id: str) -> list[ConflictGroup]
def resolve_conflict(self, conflict_id: str, decision: str) -> None
# 决策: 采用哪条规则 / 标注给人工
```
### 8.3 会话生命周期中的版本管理
```
① 创建会话 → 锁定当前最新版本 v3
② 用户上传要件定义+模板(不含规则文档)
→ Writer/Impact 检索时自动使用锁定的 v3
③ 规则手册更新为 v4
→ 已存在的会话仍用 v3(会话锁版本)
→ 新会话自动锁定 v4
④ 设计书完成
→ 元数据记录: 使用规则版本 v3 + 冲突决策列表
```
---
## 9. 存储适配层(Storage Adapter
### 9.1 定位
向量存储访问的**统一抽象层**。RAG 业务逻辑(分割/检索/融合)不直接依赖具体向量数据库,而是通过 Storage Adapter 访问。v1 仅实现 **ChromaAdapter**(本地持久化,零外部依赖)。(T5 架构审查整改:Scope 缩减裁定移除 Qdrant 可切换抽象,QdrantAdapter 为 v2 预留。)
### 9.2 接口定义
```python
class VectorStoreAdapter(ABC):
"""向量存储统一接口"""
@abstractmethod
def create_collection(self, name: str) -> None: ...
@abstractmethod
def delete_collection(self, name: str) -> None: ...
@abstractmethod
def upsert(
self,
collection: str,
ids: list[str],
embeddings: list[list[float]],
documents: list[str],
metadatas: list[dict],
) -> None: ...
@abstractmethod
def query(
self,
collection: str,
query_embedding: list[float],
top_k: int,
where: dict | None = None, # metadata 过滤条件
) -> list[VectorHit]: ...
@abstractmethod
def count(self, collection: str) -> int: ...
@dataclass
class VectorHit:
id: str
document: str
metadata: dict
score: float
```
### 9.3 实现类
| 实现 | 说明 | 使用场景 |
|------|------|---------|
| **ChromaAdapter** | v1 唯一实现,chromadb 本地持久化(`/data/shared/rules-handbook/chroma/`| 默认 |
| **QdrantAdapter** | v2 预留(不实现)| Scope 缩减裁定移除;接口保留供 v2 扩展 |
### 9.4 配置
```yaml
# config/inference.yaml 或 config/rag.yaml
vector_store:
adapter: chroma # v1 仅 "chroma"Scope 缩减裁定)
chroma:
persist_dir: /data/shared/rules-handbook/chroma
```
### 9.5 工厂与依赖注入
```python
class StorageAdapterFactory:
@staticmethod
def create(config: dict) -> VectorStoreAdapter:
# v1 仅 ChromaAdapterQdrant 分支 v2 预留)
return ChromaAdapter(config["vector_store"]["chroma"])
# 使用: RagService / RuleHandbookManager 通过构造注入 adapter
rag_service = RagService(
adapter=StorageAdapterFactory.create(config),
...
)
```
### 9.6 一致性保证
- v1 仅 ChromaAdapter(无跨实现一致性要求;v2 新增实现时需保证对同一数据的操作结果一致)
- 单元测试中可注入 **MockAdapter**(内存实现),使检索逻辑测试不依赖真实向量库
---
## 10. 降级与容错
### 10.1 无规则手册时的降级
```
场景1: 用户完全没上传规则文档
→ 系统内置「默认最小规则集」(硬编码基础规范,如「内容可追溯」)
→ search() 返回空时,Writer 正常生成但标记「无规则约束」
场景2: 规则手册构建失败(解析失败/LLM不可用)
→ 返回错误给用户,提示重试
→ 不影响已锁定的旧版本使用
```
### 10.2 Embedding 服务故障
```
Embedding 编码失败:
→ 降级为仅 BM25 检索(单通道)
→ 提示用户「语义检索暂不可用,已降级为关键词检索」
```
---
## 11. v2 迭代预留
以下内容**v1 不实现**,记入设计文档避免遗漏,v2 迭代:
### 11.1 检索质量反馈回路
```
v2: QA → 检索调优的反馈回路
├── QA 发现「规则未被遵守」
├── 判断根因: 「生成了但违规」 vs 「规则未被检索到」
├── 后者 → 记录 (query, 期望规则, 实际召回)
└── 定期分析 → 优化 query 重写策略 / top_k / 关键词扩展
```
### 11.2 检索延迟优化
```
v2: 缓存与批量
├── 同类 query 的 embedding 结果缓存
└── 按章批量检索(一次检索多主题)
```
---
## 12. 与 design.md 的关系
- 本文档是 `docs/design.md` 第5章(RAG 基础设施层)的详细展开
- `docs/design.md` 第5章保留概要,并指向本文档