🚨 文档明明检索到了,为什么 RAG 还是会把过期接口当成标准答案
很多团队把 OpenAPI、SDK 文档和变更公告接进 RAG 后,前几周体验往往不错。真正上线一段时间后,新的问题才会冒出来。⚠️ 回答引用的 URL 看似正规,代码块也像那么回事,但字段已经废弃,返回结构早就换版。📌 对调用方来说,这类错误比“答不上来”更危险,因为它会直接把旧实现写回生产系统。
问题通常不在“没召回到文档”,而在“召回到了不该再信的版本”。🧠 API 文档天然带版本、发布日期、废弃说明和迁移路径,如果索引时只把正文切成 chunk,再按语义相似度做召回,旧版示例和新版说明就会混在一起。🔍 一旦生成层只看到“意义相近的文本”,却看不到api_version、deprecated_at和replacement_endpoint,模型就很容易把旧接口说成当前推荐方案。
🔍 真正失控的,不只是召回排序,而是版本边界、废弃语义和引用链路被拆开了
这类错误一般会在三处发生。第一处是索引阶段没有 version pinning,v1、v2、beta 文档和迁移公告被一起切块,只留下正文相似度。第二处是 rerank 不理解废弃语义,deprecated、sunset和use /v2/files instead这些关键信号没有被提到足够高的权重。第三处是回答展示只回填文档链接,不回填精确版本和段落锚点。📎 结果就是:答案看似有出处,实际却把“旧方案”和“现方案”缝成了一句。
一组 API 助手灰度数据很典型。📊 只做普通语义召回时,人工抽检的stale_endpoint_answer_rate达到12.1%;在索引里补上api_version、released_at、deprecated_at和replacement_endpoint后,比例降到4.7%;再加上 Deprecation-Aware Retrieval 与引用门禁,可以压到1.5%。✅ 真正起作用的不是召回更多文档,而是先挡住不该再被回答成“当前推荐”的历史片段。
| 方案 | 过期接口误答率 | 当前版本命中率 | 检索 P95 | 主要缺陷 |
|---|---|---|---|---|
| 普通语义召回 | 12.1% | 76.4% | 142 ms | 旧版 chunk 混进 top k |
| 加版本元数据过滤 | 4.7% | 90.2% | 151 ms | 废弃说明仍可能被忽略 |
| Deprecation-Aware Retrieval | 1.5% | 96.1% | 163 ms | 需要维护版本规则 |
🛠️ 更稳的做法,是把 Version Pinning、废弃门禁和替代路径写进检索主链路
更稳的工程做法,是把“当前有效版本”从文档属性变成检索约束。🛠️ 每个 chunk 除正文外,至少要带上product、api_version、released_at、deprecated_at、sunset_at、replacement_endpoint和doc_priority。🔒 如果查询上下文里已经包含 SDK 版本、环境代号或租户启用的 API epoch,就直接做 version pinning;如果没有,也要优先选择未废弃、发布时间更新且来自正式 reference 的片段。
生成前还需要补一道废弃门禁。🧪 候选证据里只要出现deprecated或“将于某日期下线”,系统就不该继续把它包装成标准调用方式,而应该显式提示替代接口与迁移条件。🔁 Deprecation-Aware Retrieval 的关键,不是让模型更会总结旧文档,而是让它在“当前还能不能用”这件事上先过规则,再出语言。🚦
defretrieve_api_evidence(query,ctx):docs=retriever.search(query,top_k=16)pinned=[dfordindocsifd.meta["product"]==ctx.productandd.meta["api_version"]inallowed_versions(ctx)]ranked=sorted(pinned,key=lambdad:(d.meta["deprecated_at"]isNone,d.meta["doc_priority"],d.meta["released_at"],d.score,),reverse=True,)returnranked[:6]📈 接下来 3 到 6 个月,API 助手的分水岭会从“能回答”转向“能避开旧答案”
接下来3到6个月,API 文档型 RAG 的差距不会主要体现在谁把接口说明写得更顺,而是谁能稳定避开过期答案。📈 团队至少要把stale_endpoint_answer_rate、deprecated_chunk_recall_rate、replacement_link_coverage和version_mismatch_citation_rate放进看板。📉 如果这些指标不看,系统很容易在 Demo 里表现聪明,在生产里持续把旧代码重新教给用户。
笔者认为,API 知识库里最不该被当成普通语义文本处理的,就是“版本”和“废弃”。💡 一旦版本边界不能被审计,再强的模型也只是在把历史接口描述得更像当前规范。🙂 你们在做 API 文档问答时,更常见的问题是旧 SDK 示例混进召回,还是废弃接口没有被明确挡掉?欢迎交流。