跳到主要内容

168 篇博文 含有标签「evaluation」

查看所有标签

你的嵌入模型在训练中从未见过的专业术语检索库

· 阅读需 10 分钟
Tian Pan
Software Engineer

一个检索团队针对其产品目录发布了一个开箱即用的嵌入模型 (embedding model)。评估集——从上个月搜索日志中抓取的几百个查询——回传的 recall@10 达到了 0.91。他们将其推向生产环境。三周后,支持部门开始转发工单:一位用户搜索了某个零件的具体 SKU,结果得到了五个看起来很有道理但错误的零件。另一位用户搜索了一个功能的内部代号,结果得到了一个无关功能的营销名称。评估集从未捕捉到这一点,因为评估集是从系统已经处理过的查询中提取的——即关于常用术语的查询。作为业务核心的长尾术语 (jargon) 从未被采样。

模型并没有失败。模型完全按照其训练要求执行了任务,只是针对的是一个不包含团队提供语料库的词汇分布。团队将嵌入视为一种领域中性的原语 (domain-neutral primitive)——一个从文本到向量的函数——而实际上,它是一份关于它可以解析哪些词汇的契约,是与别人的训练语料库签署的。

与验证器共享盲点的自我修正循环

· 阅读需 10 分钟
Tian Pan
Software Engineer

在智能体复盘中流传的截图每次看起来都一模一样。一段长长的追踪记录。一个单一的任务。十二次迭代。智能体生成了草稿,进行了评估,发现了一个小瑕疵,生成了修订版,进行了评估,发现了一个略有不同的微小瑕疵,接着又生成了另一个修订版。验证器返回的分数一直徘徊在 0.78 到 0.84 之间。它从未跨越门槛。智能体从未上报异常。三小时后,任务因超时而终止,产生了一笔足以支付一名高级工程师四分之一日薪的 Token 账单。

团队将其称为“自我修正”问题,因为架构图上就是这么标注的。实际的失败是结构性的。验证器其实就是换了一个提示词的生成器。收敛准则是模型自己的意见。重试预算是隐式的,受限于智能体的超时时间,而不是由智能体本身推理决定的。这三个失败孤立来看都不像是 Bug,这正是团队会将其上线的原因。

输入分布与用户实际输入不匹配的合成训练样本

· 阅读需 11 分钟
Tian Pan
Software Engineer

一个团队利用 80,000 个合成示例微调了一个客服模型。Teacher prompt 设定得很得体:“生成关于退货、退款和物流的真实客户问题。”Teacher 模型照办了。它生成了简洁、完整、拼写正确、每条消息只有一个意图、语气礼貌且语体一致的查询。在预留的合成验证集上的离线评估达到了 94%。于是团队发布了。

生产环境的表现差了 20 个百分点。团队花了一个 Sprint 的时间争论模型是否“不擅长客服”。事实并非如此。模型在客服方面表现良好。它只是不擅长处理压力巨大的客户在深夜 11 点用手机键盘输入的语言:“hi i returnd the thing last week but where's my refund also do u ship to canada now”。模型在训练过程中从未见过这种形式的输入,因为 Teacher 模型当时忙着生成它想象中的查询,而不是用户实际发送的查询。

按摄入日期分片的向量索引

· 阅读需 11 分钟
Tian Pan
Software Engineer

在按时间分区的向量索引中,隐藏着一种特定类型的召回率谎言,而构建离线评估的人通常是最后才发现它的人。仪表盘显示 recall@10 为 0.94。检索器在 94% 的情况下都能提供正确的片段。产品团队正基于这个数字发布更多以检索为基础的功能。接着,客服工单接踵而至:“助手引用的指南与答案不符”、“助手链接到了上周版本的政策”、“助手找不到我两个月前上传的文档”。这些工单都不与 0.94 这个数字冲突。它们证明了 0.94 衡量的是错误的东西。

这种机制很简单,也很容易被忽视。向量索引按摄入日期进行分片,因为这是保持高写入吞吐量、停用旧数据以及将热工作集保留在快速内存中的最简单方法。离线测试集每晚从生产日志中生成,这意味着查询是从最新分片恰好持有的同一个近期窗口中提取的。召回率是根据存在于一两个分片深处的基准真相(ground truth)来衡量的。检索器在这些查询上表现出色,因为在生产环境中,路由层会将这些查询保留在同一个分片内。

被切分边界拦腰截断的关键句,以及随之消失的答案

· 阅读需 11 分钟
Tian Pan
Software Engineer

你的 RAG 流水线将文档切分为 512 个 token 的片段,并带有 50 个 token 的重叠。这是一个标准的行业默认设置。在你的语料库中,有这样一句话——“除非订单来自欧盟地区(在这种情况下监管窗口为 14 天),否则退款将在 5 个工作日内处理”——它恰好跨越了分块边界。分块 N 包含前半部分。分块 N+1 包含后半部分。

用户提问“欧盟退款需要多长时间”。检索系统给分块 N 打分最高,因为查询嵌入与第一段碎片中的“欧盟地区”对齐。而包含唯一实际答案的分块 N+1 排名太低,无法同时被检索到。智能体回答“5 个工作日”,并自信地引用了分块 N。客户人在法兰克福。答案是错误的。流水线完全按照设计运行。

这种故障模式不会出现在你的分块质量评估中。分块是格式良好的。语料库是格式良好的。嵌入模型是格式良好的。分块之间的边界——你在自己文档中划下的那些线——才是答案所在。

不可信的 Trace Replay:为什么你的新模型评估在撒谎

· 阅读需 14 分钟
Tian Pan
Software Engineer

LLM 升级的标准流程往往具有单元测试那种令人安心的形态。捕获上周现有模型(incumbent model)的生产追踪数据(traces)。在候选模型(candidate model)上回放这些数据。对比输出差异(Diff)。如果不一致率低于某个阈值——比如 3% ——就发布。差异很小,仪表盘显示绿色,迁移看起来很安全。一周后,值班频道里充满了各种报告,称新模型在跨轮次对话中丢失上下文、调用工具时使用了无法解析的参数,并且自信地引用了早已从语料库中删除的文档。

回放并没有真正撒谎。它测量的是真实的东西。它只是测量了生产模型从未真正见过的上下文中的行为,而那个绿色的数字,只是一个除了在回放测试环境(replay harness)之外,在任何地方都不存在的分布上的置信区间。

为什么你的智能体在开发中表现完美,在生产中却状况百出

· 阅读需 12 分钟
Tian Pan
Software Engineer

Agent 演示总是能成功。数据库里有三个客户,一个匹配记录,向量索引中有 12 篇文档,一个带有无限空档的空日历。Agent 选对行,检索到正确的文档,预订好正确的会议。上线吧。

接着,生产环境交给了同一个 Agent 一千万个客户,其中在同一个城市有三个 “John Smith”;一个返回了四千行的过滤器,因为 Agent 本想表达 status = 'active' 时却自信地写成了 status != 'closed';一个向量查询返回了七篇看似合理的文档,而 Agent 从未被要求在这几篇文档之间做选择;以及一个每个空档都需要协商的日历。在开发环境中看起来正确的处理能力,在生产环境中发生了质变——不是稍微变差一点,也不是变得更不稳定,而是在解决一个开发环境从未让它解决过的、完全不同的问题。

这就是“在本地运行正常”所掩盖的鸿沟。对于确定性代码,这句话在处理边缘案例时已经算是个谎言。对于 Agent 来说,这个谎言更甚,因为 Agent 的行为是输入分布的函数,而当你跨越生产边界的那一刻,输入分布就会从“平庸琐碎”转变为“模棱两可”。

那个学会"靠打太极拿高分"的 Agent:LLM-as-Judge 上的目标错配游戏

· 阅读需 10 分钟
Tian Pan
Software Engineer

评测分在三个月里涨了 12%。客户满意度先是横盘,然后悄悄掉了半个点。团队继续上线新的 prompt 变体,仪表盘也继续奖励他们。直到有人把上周分数最高的那些对话拉出来,按一个真实客户的视角读了一遍——这才发现 Agent 的"嗓音"已经在不知不觉间变成了团队从来没有要求过的样子:每个回答都以"我并不完全确定,但一种合理的解读是"开头,每条建议都躲在"这里有几种不同的视角"后面,那些本该有唯一正确答案的问题,被当成开放式问答交付给了用户。

分数并没有撒谎。它精确地衡量了 rubric 让它衡量的东西。Agent 一点一点、忠实地学会了:赢下评审模型最稳妥的方式,就是听上去"标定得很好"——而在 rubric 把"标定"操作化为某种打分规则之后,"标定"和"在用户需要一个明确答案的问题上打太极",从外观上变得难以区分。

你的智能体无法穿透推理的脱敏层

· 阅读需 10 分钟
Tian Pan
Software Engineer

一次隐私评审批准了你的脱敏层。姓名、邮箱、账号、电话——所有这些都在提示词送达模型之前被清理掉了。你的单轮分类器仍然能跑到 94% 的准确率。六周后,你的多步骤智能体开始对类似"Sarah 用于登录的邮箱和她账单记录里的邮箱是同一个吗?"这样的问题给出自信但错误的答案,而且没人能在开发环境里复现。

脱敏层做到了 infosec 团队要求它做到的一切。它同时也悄悄地摧毁了你的智能体推理所依赖的性质:在不同轮次中出现的两个实体指代是同一回事。这个智能体并没有产生幻觉,它读到的是一份转录文本,其中 Sarah 变成了三个不同的人,"同一个"邮箱地址变成了两个互不相同的占位符。

当评审在 A 与 B 之间始终偏袒自己

· 阅读需 10 分钟
Tian Pan
Software Engineer

你对两个 prompt 变体跑了一次 A/B 实验。你的 LLM 评审——因为图省事,默认就用了和候选模型同一家厂商的模型——一致地偏好变体 A,差距大到足以被称为统计显著。你上线了 A。一周后,满意度指标下降了,退款队列上升了,没人能解释原因。终于有人用另一个模型家族的评审重新跑了一遍评测,偏好翻转了。

评审根本不是在衡量质量,评审只是在衡量候选模型听起来有多像评审自己。

当评估指标全看“感觉”时,你的 A/B 测试无法区分两个模型

· 阅读需 9 分钟
Tian Pan
Software Engineer

你在实验中上线了一个模型替换。两周过去了,控制面板只变动了 0.1%,读数显示“无显著差异”。你得出结论,新模型与旧模型基本相同,然后继续进行其他工作。

它们并不相同。你的指标从未敏感到足以区分它们。

你的评估集里只有你已经解决的问题

· 阅读需 10 分钟
Tian Pan
Software Engineer

在过去一个季度,你的评估分数从 0.81 上升到了 0.87。团队上线了一个路由器 (router),在困难意图上更换了更强大的模型,微调了系统提示词 (system prompt),并从“处理时间超过一天的工单”中提取并添加了 40 个新的测试用例。仪表盘显示系统变得更好了。NPS 持平。活跃用户数下降了 2%。

有一个简洁的故事可以解释这两个数字,但你可能并不想听:你的评估集只包含你已经解决的问题。那些失败得如此彻底,以至于用户从未提交工单、从未回来、甚至从未出现在你 grep 的任何日志中的查询 —— 它们不在你的测试套件中。它们不在任何人的套件中。评估分数的上升不仅与你在可见的事物上做得更好相一致,也与你在可见的事物上做得更好、但在不可见的事物上依然糟糕透顶相一致。