# RAG 重构故事 ## 1. 起点 原始 RAG 实现已经能支撑 MVP: - 文档可以上传、切片、向量化,并写入 Milvus/Zilliz。 - Agent 可以显式调用 `lookup_knowledge`。 - AIOps 诊断能在告警流程里检索排障知识。 - 工具调用会落到 `tool_invocation`,检索步骤可见。 但它有几个工程问题: - 检索实现过于依赖 Milvus SDK,业务代码承担了太多底层搜索细节。 - L0 和 L1 职责不清,L0 关键词命中容易被当作最终召回决策。 - chunk 级检索容易丢失章节上下文。 - `breadcrumb` 存在 metadata 中,但没有充分参与 embedding、filter 和上下文重建。 - 检索质量主要靠手工接口和日志判断,缺少可重复的 golden cases。 所以重构目标不是“全盘替换成框架”,而是: ```text 通用 RAG 基础设施交给 Spring AI, 业务可观测链路保留在项目里。 ``` ## 2. 我如何拆解问题 我把迁移拆成几个阶段,因为 RAG 同时影响 Agent 工具层、AIOps、向量检索、证据打包和 Trace。 第一步是建立 baseline。`eval/rag-retrieval/` 中的 golden cases 用来对比后续改动,而不是只靠直觉判断检索有没有变好。 第二步是明确职责: ```text 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. 当前架构 ```text 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。 支持三种模式: ```text 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 出错。 当前拆成: ```text 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. 面试短版 ```text 这个 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。 这些不是当前迁移阻塞项,而是后续检索质量优化方向。