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

5.7 KiB
Raw Permalink Blame History

法规对话模块优化设计文档

日期: 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_retrievalget_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 = Nonefilters: 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() 中构建 segmentContextintent + 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 = Falsereranker_model: strreranker_top_k: int = 5

2b — Milvus Sparse BM25需 schema 迁移)

  • Milvus collection 新增 sparse_embedding SPARSE_FLOAT_VECTOR 字段
  • 新增端口 SparseEmbeddingProvidersparse embed 接口)
  • 适配器优先使用 BGE-M3 API同时输出 dense + sparse不可用时降级为 TF-IDF keyword weights
  • MilvusVectorIndex.upsert() 同时写入 sparse 向量
  • MilvusVectorIndex.search() 改为 hybrid searchWeightedRankerRRFRanker
  • 提供一次性迁移脚本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 exprregulation_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: 刷新页面后历史对话仍可恢复