跳到主要内容

163 篇博文 含有标签「rag」

查看所有标签

被你的 RAG 当成工程规范引用的那张营销页

· 阅读需 10 分钟
Tian Pan
Software Engineer

一位支持工程师把客户工单粘进你内部的 AI 助手。问题很尖锐:"我们的 API 在免费层支持多区域写入吗?"助手秒回,引用了一个余弦相似度 0.91 的片段。答案是肯定的。这个片段来自 2023 年市场部为打赢竞品对比写的落地页。十八个月前,工程团队就把免费层的多区域写入功能下掉了,并发了一份没人在客户页面上链接过的、措辞简短的内部 RFC。这份 RFC 也在向量库里,只拿到了 0.74。

助手并没有幻觉。它检索到了得分最高的文档,然后忠实地把答案锚定在那段文本上。检索器尽到了职责。只是,那份职责本身就是错的。

你的 Embedding 并不知晓外包人员已离职

· 阅读需 11 分钟
Tian Pan
Software Engineer

一名外包人员在上个季度结束了为期六个月的聘期。人力资源部门执行了离职清单:禁用 SSO、擦除笔记本电脑数据、移除 GitHub 席位、归档 Slack、撤销 Notion 访问权限。合规部门签字确认。六周后,一个内部 RAG 助手在回答问题时引用了该外包人员编写的一份机密战略文档——而引用的数据块在向量数据库的白名单中仍标记着该外包人员的用户 ID。事实来源(source-of-truth)的访问日志中没有任何读取记录,因为根本没有发生读取。检索来自一份从未被纳入离职流程的数据副本。

这是没人会画在架构图上的结构性问题。你的向量索引不仅仅是一个相似度搜索引擎。它是一个权限缓存——一个关于“谁能看到什么”的派生存储,冻结在你运行嵌入任务的那一刻——而且几乎没有人像失效其他内容那样去失效它。

那个把上周 Slack 消息当成昨天消息来读的智能体

· 阅读需 11 分钟
Tian Pan
Software Engineer

你的运营 Agent 通过引用一条内容为 “我们明天发版” 的 Slack 消息,回答了一个关于即将到来的发布会的问题。Agent 将其视为当前的计划,并开始撰写沟通稿。然而,这条消息是六周前发布的。发版早就完成了。检索流水线(retrieval pipeline)根据你衡量的每一项指标——与 “发布日期” 的语义相似度、高于阈值的 top-1 置信度、与项目匹配的来源频道——抓取到了正确的文本块(chunk),而 Agent 基于一句仅在编写时的会议语境下才有意义的话制定了计划。

这里的 Bug 不在模型本身。Bug 在于,“明天” 并不是一个日期。它是一个指向时钟的指针,而该消息编写时的时钟并不是 Agent 阅读时的时钟。你的检索流水线索引了消息的正文,却丢弃了其框架(frame)。

语义过时的 Embedding:当向量不再理解当下

· 阅读需 10 分钟
Tian Pan
Software Engineer

你曾在十八个月前嵌入了知识库。模型没变。分块(chunks)没变。索引很健康,延迟也正常,召回率仪表盘是一条 0.86 的水平线。然而,客服团队正悄无声息地在工单回复中粘贴错误的文章链接,销售机器人在潜在客户询问新产品时不断翻出已弃用的 SKU,而一名内部用户刚告诉你助手“感觉变笨了”,却说不出具体原因。

一切都没坏。是你的嵌入(embeddings)老了。在你的领域中,“post”一词以前指的是博客文章;现在,语料库中有一半的地方用它指代 Slack 帖子、论坛帖子和职位发布(job posting),而你那十八个月前的向量仍将其视为同一个概念。编码这些向量的模型从未见过这些新含义,从未见过新的产品名称,从未见过品牌重塑,也从未见过引入了三个新术语的监管规定——而你的客户现在正不假思索地使用这些术语。检索系统回答了它知道如何回答的问题,但这已不再是你的用户正在提出的问题。

Token 预算是产品决策,而非配置值

· 阅读需 12 分钟
Tian Pan
Software Engineer

在你的代码库某处,有一行代码看起来像 retriever.search(query, top_k=8)。某位工程师在某个下午写下了那个 8。它从未被团队以外的任何人评审过,从未出现在规范文档中,也从未被重新审视。这一个整数决定了你的上下文窗口中有多少配额分配给了检索到的文档而非对话历史,决定了每次请求的成本,决定了响应速度的感官体验,并且——由于语言模型在长文本下的实际表现——还决定了答案的准确性。

这是一个产品决策。它却被硬编码在一个 f-string 里。

当 RAG 本该是一次 JOIN 时

· 阅读需 10 分钟
Tian Pan
Software Engineer

一个支持团队向他们的新 AI 助手提了一个简单的问题:“上周有哪些企业客户提交了工单?”助手给出了一个自信、流利的回答,列出了六个账户。其中五个是正确的。有一个客户在两个月前就已经流失了,而另一个提交了三个工单的企业账户却完全遗漏了。直到一次续约会议谈崩了,才有人发现这个问题。

错误不在于模型,而在于架构。在设计评审的某个环节,一个带有硬性谓词(如方案层级、日期范围、工单计数)的问题被路由到了向量索引。团队因为拥有检索系统,所以就选择了检索。他们将工单记录向量化,将问题向量化,然后试图让余弦相似度(cosine similarity)来完成 WHERE 子句的工作。它做不到,也从来都做不到。

这是生产环境 AI 系统中最常见且讨论最少的故障模式之一:当真正的查询是关系型时,却动用了语义搜索。数据明明整齐地存储在带有外键的行中,答案本可以通过一个 JOIN 轻松获得。结果却经过了嵌入模型,导致精度化为乌有。

那些在悄无声息中重新排列你整个语料库的嵌入模型升级

· 阅读需 11 分钟
Tian Pan
Software Engineer

一个新的嵌入模型登上了排行榜。它比你 18 个月前发布的模型得分更高,API 只需更改一行代码,甚至维度也一致。有人提了一个工单:“升级嵌入模型”。这看起来就像更换一个日志库一样简单。

事实并非如此。嵌入模型并不是你检索系统的一个普通组件——它就是你检索系统所处的坐标系。更换它并不会改进你的索引,而是会让索引失效。而最残酷的地方在于,系统并不会崩溃。没有异常,没有失败的健康检查。你的搜索只是开始返回微妙不同的结果,而在 RAG 管道中,“微妙不同”意味着不同的文档被喂给了模型,也就意味着不同的答案最终传达给用户。

自信地返回错误答案的语义缓存

· 阅读需 11 分钟
Tian Pan
Software Engineer

两个支持用户在短短一分钟内向你的智能体提出了几乎相同的问题。第一个用户问:“我们针对 EU 订单的退款期限是多久?”第二个用户问:“我们针对 US 订单的退款期限是多久?”这两个句子的嵌入向量(embeddings)仅有一丝之差——长度相同,结构相同,只有一个两字母 token 的区别。你的语义缓存经过了相似度阈值的微调(在演示中看起来非常合理),将它们判定为匹配。于是,第二个用户得到了第一个用户的答案。EU 的 14 天冷静期被当作事实,以流利的文字呈现给了一位 US 客户,且没有任何补充说明。

没有人会因此收到报警。缓存返回了 200。延迟表现优异。成本看板显示了一次命中,这正是每个人想要的结果。唯一能说明出了问题的信号是客户根据一项不适用于他们的政策行事——而这个信号在几天后才会通过退款纠纷传来,而不是通过你的监控系统。

正是这种故障模式,让语义缓存与你之前构建过的任何缓存都截然不同。精确匹配缓存可能会过期,但它永远不会 错误——key 要么匹配,要么不匹配。语义缓存则是有意放弃了这种保证。它被设计为能针对从未见过的 key 返回答案,而这种延迟优势的代价是正确性风险,大多数团队从未对这一风险进行过量化。

你的向量索引是一个没有失效策略的缓存

· 阅读需 11 分钟
Tian Pan
Software Engineer

向量索引感觉就像一个数据库。你向其中写入文档,查询它,它返回结果。但它并不是数据库——它是存储在其他地方的数据的“派生、非规范化副本”。你的事实来源是 wiki、工单系统、CRM 或 PDF 文件夹。嵌入 (embeddings) 是这些事实的投影,冻结在你运行摄取任务 (ingestion job) 的那一刻。

这使得你的向量索引变成了一个缓存。就像所有缓存一样,它会失效。不同之处在于,大多数团队是有意识地构建缓存层,带有 TTL 和失效钩子 (invalidation hook),而几乎没有人会有意识地将向量索引作为缓存来构建。他们将其构建为“知识库”,然后在它提供三周前就已经过时的知识时感到惊讶。

向量索引存在一个没人定义的陈旧度 SLO

· 阅读需 11 分钟
Tian Pan
Software Engineer

一个用户询问你的智能体(agent)企业版的当前价格档位。智能体检索了一个分块(chunk),读取并回答:“每月 2,000 美元。” 信心满满,来源明确,格式优美。问题在于价格在四天前已经变了。智能体引用的数字在上周是真实的。它检索到的分块是在变更之前嵌入的,而索引还没有赶上进度。

没人决定让这种情况发生。没有设计评审说“智能体可以根据长达四天前的数据进行回答”。只是有一个每晚或每周运行的重新索引任务,以及一个随心所欲编辑内容的团队,而这两个时钟之间存在一个没人衡量的缺口。那个缺口就是一个服务等级目标(SLO)。无论你是否写下来,它都存在。唯一的问题是你是有意设定它的,还是由于意外继承下来的。

针对幻影库存的 RAG:当你的语料库描述产品已删除的功能时

· 阅读需 12 分钟
Tian Pan
Software Engineer

一位客户询问你的支持代理如何执行某项操作。代理检索到了三个相关性评分很高的文档分块,合成了一个自信的答案,并引导客户完成一个五步操作流程。然而,这个流程的最后一步是一个在四个月前就已经不存在的按钮。客户提交了工单。值班工程师调出评估套件,发现结果是绿色的;调出检索追踪,发现结果也是绿色的——模型没有产生幻觉,它忠实地引用了描述产品团队在上个季度发布中重命名的功能的文档。

这就是我想命名的失败模式:不是幻觉,也不是检索未命中,而是幻影库存 (phantom inventory) 问题。你的检索语料库是已不存在的产品界面的快照。向量存储不知道产品发生了变化。评估套件也不知道。唯一能持续捕捉到这一点的系统是支持工单队列,而当工单提交时,客户已经被告知去点击一个并不存在的按钮了。

检索引用税:为什么合规性会增加 30% 的 RAG Token 账单

· 阅读需 12 分钟
Tian Pan
Software Engineer

我最近交流过的一个团队向一家财富 500 强公司的内部法务办公室出售了他们的法律 AI 产品,并在系统提示词中增加了一行:“每一个事实性陈述必须包含对检索源的内联引用。”产品路线图为这种新行为分配了 5% 的 Token 预算缓冲。在该受监管租户上线 60 天后,财务部门标记了每月推理支出激增了 34%。没有人搞坏产品。没有人发布新功能。这项促成交易的合规要求,也悄然改写了其背后的单位经济效益。

这就是检索引用税,几乎每个服务于受监管行业——法律、医疗、金融、有审计约束的企业——的 RAG 系统最终都要支付这笔费用。这笔税收是结构性的,而不是 Bug。它源于引用纪律迫使模型进入了一种不同的生成模式,而且它在客户签署的采购规范中无处可寻。