Files
AIRegulation-DocAnalysis/docs/superpowers/specs/2026-05-20-rag-dialogue-optimization-design.md

146 lines
5.7 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.

# 法规对话模块优化设计文档
**日期**: 2026-05-20
**状态**: 已批准,实施中
---
## 背景
当前法规对话模块存在以下问题:
1. `compliance.py` `/compliance/chat/{segment_id}` 返回硬编码 Mock 数据
2. `rag.py` `/rag/chat` 返回硬编码 Mock 数据(前端实际调用 `/agent/chat/stream`,此路由可统一)
3. 前端快速问题列表硬编码在 `rag.ts`,未调用后端
4. 仅有 Dense 向量检索COSINE无 BM25 混合检索与精排
5. LLM 输出的 `[1][2]` 引用编号未在前端内联高亮
6. 会话存储仅为内存100条上限30分钟过期
---
## 方案分层优先4个阶段
### Phase 1 — 接入真实服务Week 1
**目标**:消灭所有 Mock让系统真正可用。
#### 后端变更
**`backend/app/schemas/compliance.py`**
- `ComplianceChatRequest` 新增 `segment_context: str | None = None`
**`backend/app/api/routes/compliance.py`**
- 移除 `get_mock_compliance_chat_response` 导入
- `/compliance/chat/{segment_id}` 接入 `get_agent_conversation_service().stream_chat()`
-`segment_context` 拼接到 query 前缀作为上下文
- 将 agent `content` 事件翻译为 `{"type":"chunk","text":"..."}` 格式,保持前端兼容
**`backend/app/api/routes/rag.py`**
- 移除 `get_mock_retrieval``get_mock_rag_answer` 导入
- `/rag/chat` 接入 `get_agent_conversation_service().stream_chat()`
- 翻译 agent 事件为 rag 格式(`retrieved`/`chunk`/`done`
**`backend/app/schemas/rag.py`**
- `RagChatRequest` 新增 `session_id: str | None = None``filters: str | None = None`
#### 前端变更
**`frontend/src/api/rag.ts`**
- `getQuickQuestions()` 改为真实调用 `GET /api/v1/rag/quick-questions`,失败时降级为本地数组
**`frontend/src/api/compliance.ts`**
- `complianceChat()` 新增第三个参数 `segmentContext: string | undefined`,传入 request body
**`frontend/src/pages/Compliance/CompliancePage.tsx`**
- `sendChatMessage()` 中构建 `segmentContext`intent + content 摘要 + 法规名)
- 传给 `complianceChat()`
---
### Phase 2 — 混合检索 + RerankingWeek 2-3
**目标**提升召回质量BM25 + dense RRF融合+ 精排。
#### 2a — Cross-Encoder Reranking优先无需 schema 变更)
- 新增端口 `backend/app/domain/retrieval/ports.py`: `Reranker` ABC
- 新增适配器 `backend/app/infrastructure/vectorstore/cross_encoder_reranker.py`
- 调用 OpenAI-compatible reranker APIBAAI/bge-reranker-v2-m3
- 修改 `KnowledgeRetrievalService`:先 retrieve top-20再 rerank 到 top-5
- 新增 settings: `reranker_enabled: bool = False``reranker_model: str``reranker_top_k: int = 5`
#### 2b — Milvus Sparse BM25需 schema 迁移)
- Milvus collection 新增 `sparse_embedding SPARSE_FLOAT_VECTOR` 字段
- 新增端口 `SparseEmbeddingProvider`sparse embed 接口)
- 适配器优先使用 BGE-M3 API同时输出 dense + sparse不可用时降级为 TF-IDF keyword weights
- `MilvusVectorIndex.upsert()` 同时写入 sparse 向量
- `MilvusVectorIndex.search()` 改为 hybrid search`WeightedRanker``RRFRanker`
- 提供一次性迁移脚本dump 所有 chunks → recreate collection → re-embed → re-insert
---
### Phase 3 — 引用溯源 + 筛选 UIWeek 4
**目标**:答案文本中 `[1][2]` 可点击跳转原文片段;法规类型/版本可筛选。
#### 引用内联解析
- 新增 React 组件 `CitedAnswer`:接受 `text` + `sources[]`
- 用正则 `/\[(\d+)\]/g` 拆分文本,将 `[N]` 渲染为可点击 `<cite>` 元素
- 点击高亮/滚动到来源面板对应条目
- `RagChatPage.tsx` 将 assistant 消息改用 `CitedAnswer` 组件渲染
- 来源面板各条目加 `id="source-N"` 属性
#### 法规筛选 UI
- `RagChatPage.tsx` 在输入框上方加筛选栏:`regulation_type` 下拉 + `version` 输入
- 筛选值作为 `filters` 参数传到 `/agent/chat/stream`
- `MilvusVectorIndex.search()` 解析 `filters` 字符串为 Milvus expr`regulation_type == "GB"`
#### 快速问题动态化
- 后端 `/rag/quick-questions` 改为从 settings 或配置文件加载,不硬编码
- 前端已在 Phase 1 中改为调用后端
---
### Phase 4 — 会话持久化 + 上下文压缩Week 5
**目标**:长对话不丢失;上下文过长时智能压缩。
#### PostgreSQL 会话存储
- 新增 `backend/app/infrastructure/session/postgres_conversation_store.py`
- 实现 `ConversationStore` port
- 复用现有 PostgreSQL 连接
- DDL: `conversation_sessions` + `conversation_messages` 两张表
- 新增 settings: `conversation_store_backend: str = "memory"`
- `bootstrap.py` 按 settings 切换实现
#### 上下文压缩
-`AgentConversationService` 中,当对话轮数 > N 时,将早期消息用 LLM 摘要
- 摘要替换为一条 `system` 消息 `"对话摘要:..."`
- 新增 `AnswerGenerator.summarize(messages) -> str` 方法
---
## 关键设计决策
| 决策 | 选择 | 原因 |
|------|------|------|
| BM25 实现 | Milvus sparse vectors | 不引入新服务Milvus 2.4+ 原生支持 |
| Reranking | API-based cross-encoder | 复用现有 OpenAI-compatible 接口 |
| 会话持久化 | PostgreSQL | 复用现有 PostgreSQL 基础设施 |
| 引用解析 | 前端纯客户端 | LLM 已输出 [N] 编号,无需后端改动 |
| segment_context | 前端构建传后端 | 合规结果存在前端状态,无需后端持久化 |
---
## 验证标准
- Phase 1: 合规对话面板返回真实法规检索结果,不再固定响应
- Phase 2: 相同 query 在 hybrid 模式下比 dense-only 召回更相关结果
- Phase 3: 点击答案中的 `[1]` 能跳转到来源面板第一条
- Phase 4: 刷新页面后历史对话仍可恢复