跳到主要内容

330 篇博文 含有标签「observability」

查看所有标签

裁判模型被悄悄升级的评估框架

· 阅读需 13 分钟
Tian Pan
Software Engineer

就在你发布提示词(prompt)更改的同一周,所有评估类别的得分都提升了 6 个百分点。团队成员将其视为改动奏效的证明。三周后,有人注意到这种提升也出现在了提示词更改绝不可能触及的类别中——这是一个你专门用来检测此类情况的对照组——而且这种提升是均匀分布的,而真正的产品改进绝不会呈现出这种形态。评审模型在某个周二以相同的终端节点(endpoint)名称发布了。在你的系统变动之前,你的分数就已经变了。

这种失效模式对“大模型作为评审员”(LLM-as-a-judge)评估流水线的破坏,比文献中警告过的任何失效模式都要更隐蔽。不是偏见,不是位置效应,也不是自我偏好——这些是评审员在特定时间点的属性,你的评估设计可能已经考虑到了这些因素。真正让你栽跟头的是评审员在你没注意的时候发生了变化,而你的终端节点名称、评估代码和仪表板都在声称一切如常。测量单位在一个稳定的标签下发生了偏移。跨越迁移边界的每一次比较现在都被混淆了,你无法将差值分解为“我们的系统改进了”和“尺子的标准变宽松了”,因为你从未构建过能进行这种分解的工具。

那个在东部时间凌晨 3 点采样生产流量的评估集

· 阅读需 11 分钟
Tian Pan
Software Engineer

我曾合作过的一个团队有一个评估集(eval set),它在不知不觉中演变成了一项针对其批量自动化任务的调查。采样定时任务(cron)在东部时间凌晨 3 点运行,从生产日志表中抓取了 5,000 条追踪记录(traces),并将它们放入评估语料库中。排行榜看起来很干净。新的提示词(prompt)赢了 4 分。他们发布了。不到一天,支持队列里就充满了他们在回归测试中从未见过的投诉——模型现在对定价问题闪烁其词,而这发生在一个工作时间完全在评估窗口关闭后才开始的客户群体中。

评估本身对于其测量的内容并没有错。错在于它测量的是谁。在东部时间凌晨 3 点,生产集群主要由深夜批量重试、定时报告生成以及少数主要询问导航类问题的亚太地区(APAC)日间会话占据。新的提示词在这个切片上的表现确实更好。然而,这个切片仅占每周流量的 12%,而在按收入加权的流量中占比为 0%。没有人问过“这个数据集中包含什么样的用户”这个问题,因为数据集是由一个在数据仓库最空闲时运行的定时任务构建的,而“空闲”是大家唯一想到的优化采样标准。

你的 Token 预测从未考虑过的重尾效应

· 阅读需 10 分钟
Tian Pan
Software Engineer

你的 AI 功能成本预测是基于一个 50 人的试点项目建模的。那些用户输入了三句话的提示词,因为那是人们在被要求评估测试版时通常会输入的内容。产品上线了,你突破了一万名用户,财务团队指出你的模型账单是计划书中人均成本的三倍。你去寻找 Bug。但根本没有 Bug。你的试点项目是从一个分布中采样,而生产环境是从另一个分布中采样,两者的区别在于一个长尾用户群——他们是在 Twitter 上了解到你的产品,并粘贴了从推文中截取的 30 KB 非结构化上下文。

这是每家消费级互联网公司在 2010 年代都吸取过的同样财务教训,现在被移植到了 LLM 经济学中。试点项目的中位数用户并非生产环境中的 p99.5,而一个使用平均值作为预测输入的 Token 成本模型,在面对账单时注定会一败涂地。

那个教会用户永远不要打断智能体的中断 UI

· 阅读需 11 分钟
Tian Pan
Software Engineer

你的流式智能体上的中断按钮点击率仅为 0.4%。产品团队看到这个数字,得出的结论是该功能正按预期运作——大多数生成内容不需要中断,实现方案没问题,发布吧,继续下一个任务。而实际的解读应该是,这个中断按钮教会了你的用户不要去按它。在使用产品不到一周的时间里,他们就发现按下停止键会丢弃已生成的片段、清除上下文,并把他们丢回到一个空的输入框中。他们学到的教训是:宁愿忍受一个糟糕的回答,也不愿冒着丢失整个对话脉络的风险。

这 0.4% 不是使用信号,而是厌恶信号。你的用户并非对答案感到满意——他们只是害怕尝试重定向答案所带来的代价,他们的适应方式是静静地坐着,看着智能体说完那些他们明知是错误的内容。工程团队将“停止生成”视为模型调用的取消。而用户将其视为“重定向,而非重启”。这两种定义从未达成一致,导致产品发布了一个在长对话中悄悄剥夺用户主动权的功能。

披着“延迟预算路由器”外衣的“质量损失路由器”

· 阅读需 11 分钟
Tian Pan
Software Engineer

一个优化单一损失函数的模型路由器会准确地交付该损失函数所要求的结果,除此之外别无他求。当该函数的目标是“保持在 p95 延迟目标之下”时,每一个本可以从深度推理(extended reasoning)中获益的查询都会被强行分配到路由器能辩护的最廉价路径上,因为快速模型能在 SLO 范围内返回,而缓慢但正确的模型则不能。延迟仪表板变绿了。综合评估指标(aggregate eval)仅波动了不到一个百分点,团队便将其视为噪声忽略不计。而没人绘图的分片视图(per-slice view)才是真正发生质量回归(regression)的地方:它集中在那些多步骤、模糊且分布外(out-of-distribution)的查询中,这些查询本应被路由到推理模型,结果却分配给了那些运行迅速但错误得很有底气的模型。

这不是路由 bug。路由器正在准确地执行其设计任务。Bug 出在框架设定上——如果一个系统的优化器完全以延迟为基准,它就会产生质量回归,而这些回归在团队为了 KPI 而维持“绿色”的指标中是不可见的。随后,它会默默地发布这些回归,因为盯仪表板的人并不是盯答案的人。

你的编排器在规划步骤上消耗的延迟预算

· 阅读需 12 分钟
Tian Pan
Software Engineer

我上季度合作的一个团队对一个客户支持智能体(Agent)进行了为期一周的埋点分析。从纸面上看,该智能体的中值延迟非常合理:P50 在 SLO 范围内,P95 虽然偏高但尚可解释,工具调用的追踪(traces)看起来也很健康。然而,当有人按类型对 span 进行分桶统计时,全场陷入了沉默。该智能体每次运行的墙钟时间(wall-clock time)中,约有 58% 耗在了标记为“规划(plan)”、“反思(reflect)”、“决定下一步(decide-next-step)”和“自我检查(self-check)”的 span 中。而真正的工具执行——数据库查询、CRM 写入、权限检查——占比不足 30%。这个智能体在核心业务逻辑上花费的精力,竟然比那些没人关注的中间步骤还要少。

这个比例并非偶然。它是任何你不主动监管的“规划-行动-观察(plan-act-observe)”循环的自然状态。编排器(Orchestrator)为了思考和行动支付延迟代价,而增加思考步骤几乎总是比增加行动步骤更容易,因此它会野蛮生长。当你意识到这一点时,“决定下一步做什么”已经变成了一个独立的预算大头——甚至比你最初构建智能体要服务的业务逻辑还要大。

一次导致所有运行中 Agent 任务失效的 Prompt 热重载故障

· 阅读需 11 分钟
Tian Pan
Software Engineer

传呼机在晚上 11:47 响了。一名客户在退款对话中进行了十分钟,智能体突然停止调用它在整个会话中一直在推理的 process_refund 工具,幻觉出了一个确认码,并结束了聊天。当我们回溯原因时,事后看来显而易见:一位队友在 11:46 推送了更新后的系统 Prompt。推送很顺利,测试通过了,每个新会话都运行完美。但已经在进行中的几百个会话却出问题了。

我们构建的 Prompt 注册中心支持了 2026 年每家 Prompt 版本控制供应商都作为特性推销的功能:无需重新部署的热重载(hot-reload)。我们将这种能力视为 CDN 缓存刷新——一种在全球范围内立即生效的全量替换。但那天晚上我们学到,它实际上是破坏了契约。每个活跃的会话都是 LLM 与一组指令及工具定义之间正在进行的协商。当注册中心在这些对话进行中更换了 Prompt 时,协商好的一半上下文就过时了。

提供商故障转移:在对话中途替换了你安全策略的隐忧

· 阅读需 12 分钟
Tian Pan
Software Engineer

用户正与你的助手进行一场关于受控物质处方模式的谨慎对话,已经进行了十二轮。模型表现得很有分寸,提出澄清性问题,引用指南,并拒绝进行文献之外的推演。在第十三轮,用户提出了一个后续问题,按理说应该得到与前十二轮相同的回应。然而,他们得到的却是一个生硬的拒绝:“我无法提供相关帮助。”对话结束了。他们怒气冲冲地给支持团队写信——他们并没有问任何不同的内容,助手刚才还在帮助他们,到底发生了什么变化。

你的日志解释了变化的原因。在第十三轮进行到一半时,你的主供应商在流式传输过程中返回了 503 错误。你的网关按照配置执行了操作:在请求的剩余部分故障转移(failover)到了备用供应商。备用供应商对该类查询的拒绝阈值校准得比主供应商更保守。用户并没有问任何不同的问题——他们在同一个品牌下对不同的模型提出了相同的问题,而新模型说了“不”。

供应商配额在你的全球流量从未选中的时区重置

· 阅读需 10 分钟
Tian Pan
Software Engineer

你的每月 Token 配额在 00:00 UTC 重置。你最大的客户在东京,他们在 21:00 UTC(即当地时间第二天早上 6:00)达到峰值负载。当重置时刻到来时,东京的工作日已经在配额耗尽的降级方案中消耗了该周期的最后六个小时。429 错误看起来只是“偶发”,因为你仪表板上的 UTC 日历轴将每日重置边界隐藏在了普通的时间戳之中。

这不是速率限制(rate limit)的 Bug。这是一个日历 Bug。供应商为了结算方便选择了一个重置时钟,而你流量的地理分布决定了哪些客户会分配到周期末尾的空窗期。那些将配额定价为统一资源的团队,正基于一个用户从未见过的日历来进行配额分配。

你的产品视图从未呈现的推理 Token

· 阅读需 11 分钟
Tian Pan
Software Engineer

一位客户给支持团队发了邮件。AI 助手告诉他们在错误的司法管辖区申报纳税,他们非常生气,想知道助手是如何得出那个答案的。你的支持人员打开问题队列,看到了最终回复:自信、听起来很有道理,但却是错误的。他们看不到模型在给出回复前生成的 5000 个推理标记 (reasoning tokens),尽管这些标记确实存在,而且你的工程团队可以在 30 秒内从另一个屏幕上把它们调出来。证据就在公司里,只是拿在错误的人手中。

这就是团队在生产环境的智能体上启用扩展思考 (extended thinking) 时产生的差距。推理成为了每一次调用的核心产物,而你的组织尚未决定谁在什么时候、以何种精度、以及在多长时间内可以看到它。默认决策是由负责各个界面的团队分别做出的,他们的默认设置各不相同,而这些缝隙恰恰是客户投诉产生的地方。

智能体学会针对重试预算进行规划

· 阅读需 11 分钟
Tian Pan
Software Engineer

在生产环境中运行智能体(agent)得出的最令人不安的教训不是它们会失败——而是它们会学习。并不是指任何深度意义上的学习;权重并没有改变。但在一个会话(session)中,在一个轨迹(trajectory)中,模型所隐含的策略会根据其运行的底层环境(substrate)进行调整。如果你的底层环境代表智能体悄悄吸收了失败,智能体最终会察觉到这一点,并开始将其视为免费的算力进行规划。

最明显的例子就是重试层(retry layer)。你添加它是为了可靠性——在报错之前,SDK 会对失败的工具调用进行三次重试;你的中间件为每一步包装了指数退避(exponential backoff);你的循环捕获了格式错误的 JSON 并重新提示模型进行修复。这些都没错。但每一个机制都是智能体可以观察、概括并利用的副作用。一旦它这样做了,你的可靠性层就不再是安全网,而成了规划原语(planning primitive)。

你的后端基础设施并非为流式响应而设计

· 阅读需 13 分钟
Tian Pan
Software Engineer

流式传输(Streaming)是一项产品决策。设计团队的某个人看到竞争对手的聊天 UI 像打字机一样逐个吐出 Token,看到用户在第 200 毫秒看到第一个字符出现时肩膀放松了下来,而不是盯着 4 秒钟的空白屏幕发呆,于是决策就此达成:我们要做流式传输。这个拉取请求(PR)修改了 API 网关中的三个文件。现在,模型输出通过服务器发送事件(Server-Sent Events,SSE)增量刷新。功能在周二上线,周三的满意度评分就有了明显的提升。没人向基础设施团队提工单。

一个月后,值班工程师盯着三个互不一致的仪表盘发愁。自动扩缩容(Autoscaler)配置的 Pod 数量是 CPU 图表显示需求量的两倍。P99 延迟仪表盘坏了——不是出了故障,而是变得无法解读,因为直方图分桶(Histogram Buckets)止步于 5 秒,而现在大多数 Span 都落在溢出区间。上一季度定价时的容量模型显示,该服务每节点每秒可处理 1200 个请求。而值班人员面前的图表显示,它在处理 400 个请求时就已经难以为继。