Files
SuperBizAgent-java/interview/archive/2026-07-24-legacy/rag-refactor-story.md
zhuyongxin de5a5b09d9 docs(interview): refresh materials for single-agent harness narrative
Archive pre-refactor interview notes and add current deep-dives on
architecture evolution, issue-derived stories, and evidence gates.
2026-07-24 18:14:49 +08:00

4.9 KiB
Raw Permalink Blame History

RAG 重构故事

1. 起点

原始 RAG 实现已经能支撑 MVP:

  • 文档可以上传、切片、向量化,并写入 Milvus/Zilliz。
  • Agent 可以显式调用 lookup_knowledge。
  • AIOps 诊断能在告警流程里检索排障知识。
  • 工具调用会落到 tool_invocation,检索步骤可见。

但它有几个工程问题:

  • 检索实现过于依赖 Milvus SDK,业务代码承担了太多底层搜索细节。
  • L0 和 L1 职责不清,L0 关键词命中容易被当作最终召回决策。
  • chunk 级检索容易丢失章节上下文。
  • breadcrumb 存在 metadata 中,但没有充分参与 embedding、filter 和上下文重建。
  • 检索质量主要靠手工接口和日志判断,缺少可重复的 golden cases。

所以重构目标不是“全盘替换成框架”,而是:

通用 RAG 基础设施交给 Spring AI,
业务可观测链路保留在项目里。

2. 我如何拆解问题

我把迁移拆成几个阶段,因为 RAG 同时影响 Agent 工具层、AIOps、向量检索、证据打包和 Trace。

第一步是建立 baseline。eval/rag-retrieval/ 中的 golden cases 用来对比后续改动,而不是只靠直觉判断检索有没有变好。

第二步是明确职责:

L0 = domain/entity hint
L1 = semantic retrieval
postprocess = evidence shaping + trace-friendly output

L0 仍然有价值,但不再默认绕过语义检索。它更适合提取服务名、告警名、错误码、领域和 metadata filter。

第三步是增强 evidence 输出。Agent 不应该只拿到 raw chunk,而应该拿到带 source、title、breadcrumb、score、hit reason 的证据块。

最后,我把 Spring AI VectorStore 接入为读取主路径,同时保留原 Milvus SDK 作为 fallback。

3. 当前架构

Agent / API
  -> lookup_knowledge or /api/search/similar
      -> L0 domain/entity hint
      -> VectorSearchService
          -> Spring AI VectorStore
          -> Milvus SDK fallback
      -> relevance normalization
      -> tool_invocation trace

VectorSearchService 仍然是公共检索门面。Agent 工具层不需要知道底层是 SDK 还是 Spring AI。

支持三种模式:

auto      -> 优先 Spring AI VectorStore,失败后 fallback 到 SDK
spring-ai -> 强制 Spring AI VectorStore
sdk       -> 强制 Milvus SDK

4. 关键取舍

保留显式工具

我没有把检索藏进 Spring AI Advisor。原因是这个项目强调 Agent 执行可见性:lookup_knowledge 的 query、命中文档、相关性和证据预览都要进入 Trace。

保留 SDK fallback

SDK fallback 不是废代码,而是迁移安全网。实际验证时,第一次 VectorStore 指向了错误 collection,auto 模式 fallback 到 SDK 后仍能返回结果。修正 collection 后,Spring AI 路径成为主路径。

L0 降权

生产事故中经常有精确标识:错误码、告警名、服务名、指标名。L0 适合做 hint,但不应该做最终裁判。

分数语义拆开

SDK 使用 L2 distance,Spring AI 暴露 similarity。混在一个字段里会让 relevance normalization 出错。

当前拆成:

score      -> 兼容旧逻辑的距离型分数
rawScore   -> 底层原始分数
scoreLabel -> rawScore 的语义

暂不迁移写入

写入和索引仍走 SDK。这是有意分阶段:先验证读路径,再评估 VectorStore.add(...) 是否适合现有 metadata 和 chunk 模型。

5. 验证方式

我用了三层验证:

  • 单元测试:SDK mode、Spring AI mode、auto fallback、category filter、distance metadata mapping。
  • Live API:GET /api/search/similar?query=ERR_TIMEOUT&topK=3。
  • 代表性 query 对比:错误码、支付超时、MySQL 连接池、AIOps 告警式 query、抽象 RAG 设计问题。

核心排障和 AIOps query 在 SDK 与 VectorStore 下 top3 一致。差异主要集中在抽象设计类问题和 metadata taxonomy,这些被记录为后续质量工作。

6. 面试短版

这个 RAG 系统最初是基于 Milvus SDK 的自研 MVP。它能跑,但底层检索细节过多地散落在业务代码里,L0/L1 职责也不够清晰。
我按阶段重构:先加 retrieval baseline,再把 L0 降级为 domain/entity hint,再增强 evidence postprocess,最后把读取主路径切到 Spring AI VectorStore,并保留 SDK fallback。
我没有把 lookup_knowledge 替换成隐式 Advisor,因为这个项目的核心是可追踪 Agent:面试官可以看到什么时候检索、检索了什么、证据如何支撑诊断。

7. 可主动承认的不足

  • metadata taxonomy 还需要清理,例如 database 与 infrastructure。
  • 抽象设计问题可能需要 query rewrite 或更好的文档索引。
  • 邻居 chunk / 同章节上下文扩展还不完整。
  • rerank、RRF、BM25、hybrid retrieval 还没有接入。
  • 写入路径仍使用 SDK。

这些不是当前迁移阻塞项,而是后续检索质量优化方向。