外观
待优化清单
已识别的优化方向,按优先级排列。每完成一项,移到
04-优化迭代记录.md并标记完成。
高优先级(快速见效,面试加分明显)
H10. 离线评测框架(Naive vs Hybrid vs Rerank vs Full 对照) ✅ 已完成(2026-05-04)
- 详见 04-优化迭代记录.md #10 与 09-评测体系建设.md
- 后续工作:
- 数据集从 10 条扩到 50+ 条(按真实 KB 内容补 expectedDocNames)
- 跑完一次完整评测后把数字回填到 #10 与 09-doc
- 加 V0(无 RAG 直答 baseline)+ V5(V4 + Query Decomposition)两档对照
H1. VectorRetriever 向量化失败降级修复 ✅ 已完成(2026-04-27)
H2. Agent 各步骤耗时统计 ✅ 已完成(2026-04-27)
- 升级为 Langfuse + OpenTelemetry 全链路追踪,详见 04-优化迭代记录.md #2
H3. RRF/BM25/TextChunker 核心算法单元测试
- 问题:核心算法没有测试覆盖,边界情况(空输入、单条输入、超长输入)未验证
- 方案:参数化测试验证 RRF 融合公式、BM25 评分、文本切分逻辑
- 面试价值:展示测试驱动的工程素养
H4. Self-Reflection 置信度标记 ✅ 已完成(2026-04-27)
H5. Query Decomposition 多跳检索 ✅ 已完成(2026-04-28)
- 复杂查询拆解为子问题并行检索,跨子问题保底分配 + 全局补齐合并
- 详见 04-优化迭代记录.md #4
H6. Query-Aware Adaptive Retrieval ✅ 已完成(2026-04-28)
- 查询感知自适应检索参数:Complexity × Specificity 二维画像 → 8 套参数预设 + RRF 加权融合
- 详见 04-优化迭代记录.md #5
H7. 双执行路径合并 + Query Decomposition 接入主路径 ✅ 已完成(2026-04-28)
- 删除 RagPipeline 旧路径与 ChatController + Med* 实体重复映射
- Query Decomposition 升级为 DocMindAgent 主路径能力
- 详见 04-优化迭代记录.md #6
H8. 链路成本/延迟 Tier 1 优化 ✅ 已完成(2026-04-28)
- SelfReflection 高分短路 + 双模型策略(qwen-plus / qwen-turbo)+ 缓存阈值 3→2 + stream_complete SSE 事件
- 预期单查询成本 -50%、p50 延迟 -25%
- 详见 04-优化迭代记录.md #7
H9. 全格式统一通过 MinerU 入库 —— PDF / PPT / 图片 / 网页 → Markdown ✅ 已完成(2026-04-28)
- PDFBox 行交错 + 丢图丢表 + 不支持 PPT / 图片 / 网页:接 MinerU 云端 API(一个外部依赖解决多模态文档入库)
- 文件流程(PDF/PPT/图片)+ URL 流程(MinerU-HTML)共享轮询主循环,通过
stateExtractor函数抽象屏蔽 batch / task 两类响应差异 - 降级分级:PDF 失败降级 PDFBox;PPT / 图片 / URL fail-fast 不静默降级
- 双层闸门:env 静态开关 + sys_ai_config 动态开关
- 详见 04-优化迭代记录.md #8
中优先级(功能完善,体现系统性思考)
M1. 检索结果置信度评分 ✅ 已完成(2026-05-07,Phase 5 Step 13)
- 实际方案落点比原计划更深入:参考 CRAG 论文(Yan et al. 2024)做了三档评估器(HIGH / AMBIGUOUS / LOW),灰区四种仲裁模式(cross_encoder 默认 / llm / heuristic / disabled)
- 不是简单的"低于阈值就标记",而是分档触发不同后续动作:HIGH 直接生成,AMBIGUOUS 进入仲裁,LOW 让现有 fallback 接管
- 详见 04-优化迭代记录.md #16
M2. Micrometer 指标监控 ✅ 已被 Langfuse 方案覆盖(Phase 6 增强)
- Phase 6 升级为完整 OTel 集成:TracedOp 消除 span 样板代码 + RootNameFilteringSpanProcessor 白名单过滤 + ChatModelObservationFilter 自动采集 LLM 调用
- 详见 04-优化迭代记录.md #19
M3. QueryRouter 意图识别增强 → 已被 Phase 2 SupervisorAgent 架构取代,Phase 5 进一步加上范畴判定层
- 原方案:增强 QueryRouter 正则 or 改用 few-shot LLM 分类
- Phase 2 演进:引入
QueryClassification(intent + complexity + specificity 三维分类)+SupervisorAgent多策略编排 +ObservationEvaluator动态降级链,原 QueryRouter 的职责被拆解到更精细的组件中。详见 04-优化迭代记录.md #13 - Phase 5 补强:在三维分类之上加最外层"范畴判定层",区分四种处理路径(元对话 / 闲聊 / 知识查询 / 任务执行 / 越界)。原五类 intent 都默认要查知识库,Phase 5 解决了"总结上面的对话"被错误送入检索的问题。详见 04-优化迭代记录.md #16
M5. Markdown-aware Chunker(MinerU 后续) ✅ 已完成(2026-04-30)
- 详见 04-优化迭代记录.md #9
- 同步落地了增量索引(content_hash diff + vector_id 1:1 链接)
M4. ContextCompressor 去重粒度参数化
- 问题:去重用固定的前 50 字比较,不够灵活
- 方案:将去重阈值移到 sys_ai_config,支持运行时调整
- 面试价值:展示参数化设计思维
低优先级(锦上添花)
L1. MCP 工具调用统计竞态修复
- 问题:查询+更新之间有竞态窗口
- 方案:数据库 INSERT ON DUPLICATE KEY UPDATE
L2. MemoryTool 并发写入保护
- 问题:无乐观锁,并发写入丢失更新
- 方案:Redis WATCH/MULTI 或版本号
L3. 超长 Query 截断处理
- 问题:用户输入 10000 字没有限制
- 方案:入口处截断到 500 字,日志记录原始长度
L4. 文档提取编码检测
- 问题:固定 UTF-8,旧 PDF 可能是 GBK
- 方案:使用 ICU4J 或 juniversalchardet 自动检测编码
链路成本/延迟优化 Tier 2-3(迭代 #7 后续)
Tier 1(短路 + 双模型 + 缓存阈值)已落地。下面是延伸方向,按 ROI 排。详见 04-优化迭代记录.md #7 末尾的 Tier 2-3 列表。
T2-1. 拆解路径 Reranker 批量化(中 ROI)
- 问题:3 子问题各调 1 次 rerank,3× 网络往返
- 方案:合并候选集 → 1 次 rerank(query 用 originalQuery)→ SubQueryMerger 用合并分数
- 预期:拆解路径 rerank API 调用 -67%
T2-2. Prompt 模板瘦身(中 ROI)
- 问题:主回答 input ~4000 tokens 里模板 + 元信息占 ~1000+
- 方案:审
src/main/resources/prompts/,删冗余前言、用更紧凑的 YAML 风格 - 预期:主回答 input -15%
T2-3. 历史上下文摘要(中 ROI)
- 问题:
buildConversationHistory取近 6 条原始拼接,长会话膨胀 - 方案:超过 N 条时把更早内容用小模型摘要为 1 段
- 预期:长会话主回答 input -20-40%
T2-4. WebSearch 提前并行启动(低 ROI)
- 问题:Tavily 1-3s 阻塞主流程
- 方案:QueryProfiler 标
timeAware=true时 Decomp 阶段就异步启动,最后 join
T2-5. Reranker 候选数自适应下调(低 ROI)
- 问题:当前固定 25-40 候选,简单查询过度
- 方案:
QueryProfiler.RetrievalParams增rerankCandidates字段
T2-6. DashScope Context Cache(Prompt Cache)接入(中-高 ROI)
概念区分:语义答案缓存 vs Prompt Cache
项目当前已有的 SemanticCacheService 不是 Prompt Cache,二者是不同层的优化,可叠加使用。
| 维度 | 语义答案缓存(已有) | Prompt Cache(待接入) |
|---|---|---|
| 缓存对象 | 完整 RAG 答案 + sources | LLM 输入侧的稳定前缀(系统提示、工具 schema) |
| 命中条件 | query embedding cosine ≥ 0.92 且 KB 版本一致 | 输入前缀逐字节相同(provider 侧 KV cache) |
| 节省的成本 | 整次 RAG 调用(embedding + 检索 + rerank + LLM) | 仅 LLM 输入 token 计费 + 首 token 延迟 |
| 失效粒度 | KB 任一变更全失效 | 前缀任意 token 变更即失效 |
| 实现层 | 应用层 Redis | LLM Provider(DashScope Context Cache) |
| 适用场景 | 高频重复问题 | 每次都跑的 agent 循环(工具描述、系统模板) |
关键洞察:当前命中率 ~45% 的语义缓存解决的是"重复问题",但剩下 55% 不命中的请求每次都把 ~1000+ token 的稳定前缀(工具 schema + 系统模板)原样发给 LLM,这部分才是 Prompt Cache 的目标。
改造方案
- 问题:每次 agent 循环都把工具 schema(~600 token)+ 系统模板(~400 token)+ 反思模板(~300 token)原样发给 qwen,前缀稳定却未复用
- 方案:
- 调用 DashScope
/services/aigc/text-generation/generation时按context-cache文档加cache: { enable: true }参数(具体字段以 DashScope 当时文档为准) - 在 PromptAssembler 把 prompt 重组为
[稳定前缀] + [动态 chunks] + [用户问题]三段式,前缀放在最前 - 工具调用路径(
ChatClient+ToolCallbackProvider)确认 Spring AI 是否透传 cache 参数;不行则降级到自建 OkHttp 客户端走原生 API AiConfigHolder加cache.prompt_cache_enabled开关,便于 A/B
- 调用 DashScope
- 预期:
- 主回答 input token 计费 -25~40%(前缀命中 50% 折扣,按 DashScope 现价)
- TTFT 延迟 -15~30%(命中前缀不重新跑 attention)
- 工具选择 / 反思的小模型路径收益更高(前缀占比更大)
- 风险:
- DashScope Context Cache 有最小前缀长度门槛(通常 ≥256 token),短模板可能不命中
- 前缀里任何动态字段(时间戳、用户 ID、随机 nonce)都会破坏命中,需审一遍模板
- 面试 talking point:
"项目里语义缓存解决的是'同一个问题不要再跑一遍',但 agent 每次循环里工具 schema 和系统模板都是稳定的,那部分输入 token 还是每次都付钱。所以下一步是接 DashScope 的 Context Cache,把 prompt 重排成'稳定前缀 + 动态 chunks + 用户问题'三段,让 LLM provider 在 KV cache 层复用稳定前缀——和应用层语义缓存是叠加关系,一个省整次调用、一个省每次的输入 token。"