跳到主要内容

778 篇博文 含有标签「llm」

查看所有标签

Tokenizer 税:除了英语,你的 AI 功能在所有其他语言中成本更高且表现更差

· 阅读需 12 分钟
Tian Pan
Software Engineer

你的定价页面显示每个用户支付的费用相同。但你的成本仪表板却给出了不同的答案。同样的 AI 功能 —— 同样的提示词模板、同样的模型、同样的特性标志(feature flag) —— 为西班牙语用户提供服务的成本要高出 55%,日语用户大约翻倍,而阿拉伯语或孟加拉语用户则超过 3 倍。与此同时,这些用户获得的质量也明显更差:在翻译成不同语言的相同基准测试问题上,当前沿模型脱离英语分布时,其表现会下降 13 到 24 个百分点。

大多数在全球范围内发布 AI 功能的团队从未衡量过这两项数据。他们拥有分地区的定价、分地区的支持 SLA、分地区的法律审查 —— 却只用一套英语评估测试集来代表全球每个用户的体验。

这就是分词器税(tokenizer tax),它与仅靠规模无法弥补的质量差距相互叠加。在你按语言维度拆分数据之前,这两者在仪表板上都是不可见的。而且这两者早在你写下第一个提示词的几年前,就由你无法控制的分词器训练语料库决定了。

谁在为 Token 买单?内部 LLM 平台的费用分摊与结算设计

· 阅读需 12 分钟
Tian Pan
Software Engineer

每一个内部 LLM 平台都会经历同样的曲线。在第一个月,推理是免费的:平台团队买单,产品团队疯狂实验,每个人都在为增长曲线欢呼。到了第六个月,账单增长了 10 倍,财务部门开始提出尖锐的问题,平台团队发现 80% 的支出由三个团队产生——其中一个团队还在运行一个没人记得批准过的夜间批处理作业。本能的反应是安装计量器并开始收费。这种本能如果应用得过于幼稚,正是你毁掉平台的方式。

这是一个令人不安的事实:按 Token 计费的分摊机制(Chargeback)恰恰惩罚了你构建平台所鼓励的行为。正在原型化可能改变支持流程的智能体(Agent)团队消耗 Token 就像熔炉一样——智能体工作负载每个任务消耗的 Token 是简单聊天补全(Chat Completion)的 5 到 30 倍。如果从第一天起就按原价向他们收费,他们就会停止原型开发。与此同时,运行成熟且经过优化的功能的团队只需支付微薄的费用,看起来非常“节俭”。你构建了一个对学习征税、对停滞奖励的定价系统。

为什么你无法为智能体设置进度条

· 阅读需 11 分钟
Tian Pan
Software Engineer

你发布过的每一个进度条都建立在一个假设之上:你知道分母。上传一个 40 MB 的文件?分母就是 40 MB。安装 212 个包?分母就是 212。进度条是诚实的,因为在工作开始之前,总工作量是已知的。

智能体(Agent)从根本上打破了这个假设。它执行的不是预定的步骤列表——它在执行过程中不断发现剩余的工作。它读取一个文件,结果发现了另外三个值得读取的文件。它运行测试,测试失败了,于是引发了一个谁也没计划过的调试分支。原来的第 4/7 步变成了第 4/19 步,偶尔又会变成第 4/4 步,因为最后三步被证明是不必要的。对于智能体来说,计算完成百分比(Percent-complete)并不难,而是“未定义”。在工作完成之前没有分母,而一旦完成,答案永远是 100%。

然而看看我们发布的产品:预示即将完成的加载动画(spinners)、爬到 90% 就卡住的进度条、在原本需要 8 分钟的任务进行到第 2 分钟时显示“即将完成……”的标签。这些都是小小的谎言,而且用户能识破它们。有趣的交互设计问题不是如何更逼真地伪造进度,而是当工作的持续时间在结构上无法预知时,诚实的安抚(honest reassurance)应该是什么样子的。

你的智能体是一个“话唠”客户端:数据引力开始影响工具循环

· 阅读需 11 分钟
Tian Pan
Software Engineer

15 年前,我们学会了畏惧 N+1 查询:一个在代码审查中看起来人畜无害的 ORM,会针对列表发起一次查询,然后为每一行数据再发起一次查询。一个本该只需要两次数据库调用的页面,最终却发起了两百次。我们通过预加载 (eager loading)、批处理 (batching) 和一代又一代的 Linter 解决了这个问题。然而,现在我们构建了 AI Agent,却在昂贵得多的层级上重犯了同样的错误。

一个单一的 Agent 任务——比如“核对这些发票”或“处理此故障”——通常会进行几十次串行的工具调用。每一次调用都是一次完整的网络往返:从 Agent 到工具,从工具到数据存储,数据返回工具,结果序列化到模型的上下文中,再进行一次推理以决定下一步操作。如果你的推理运行在一个云端,而数据存在于另一个云端,那么每一次跳转都会跨越一个计费且高延迟的边界。此时,Agent 系统成本的主要项不再是模型,而是地理位置。

没有人把这笔账算清楚。延迟预算是按次调用的,出网流量 (Egress) 只是存储账单中的舍入误差,而模型发票则受到了所有的关注。与此同时,工具循环悄然成为了你的基础设施所服务的通信最频繁 (chattiest) 的客户端。

你的智能体内存需要垃圾回收机制

· 阅读需 11 分钟
Tian Pan
Software Engineer

持久化记忆是每个人都会给自己的智能体添加、但几乎没人维护的功能。这个提议令人无法抗拒:智能体会记住你的模式、你的偏好、上周二的决定,并且每一次会话都比上一次更聪明。而失败模式则更加隐蔽:默认情况下,记忆呈单调增长,而一个关于不断变化的世界的“仅追加”事实存储库,无异于一种缓慢的投毒。被迁移的 API、被重组的团队、被推翻的架构决策 —— 所有这些都与新鲜事实并排存在于存储库中,以同样的权威性被检索,并以同样的自信心被注入到上下文中。

无状态的智能体会犯下孤立的错误。而配备了记忆的智能体可以将一个错误变成重复性的错误,因为它存储了该错误,随后又将其作为证据检索出来。一个被自信写下的错误记忆 —— “支付服务拥有退款逻辑” —— 会污染未来每一个召回它的运行过程,而每一个基于它执行的运行过程又可能写下源自它的新记忆。这不仅仅是一个存储问题。这是一个垃圾回收问题,而大多数智能体记忆系统在发布时都没有配备回收器。

你的 AI 工作负载也有“夜晚”:批处理折扣是对架构的考验

· 阅读需 11 分钟
Tian Pan
Software Engineer

每一个主流模型提供商都在以半价向你出售同样的 Token。OpenAI、Anthropic 和 Google 都提供 Batch API,其收费仅为同步请求费率的 50% —— 模型相同、提示词相同、输出也相同 —— 唯一需要你做出的让步是:接受 24 小时的完成窗口,而不是在几秒钟内获得答案。对于一个每月在推理上花费 50,000 美元的团队来说,这意味着有 25,000 美元摆在桌面上,无需更改任何一行提示词即可领取。

大多数团队从未领取过这笔钱。并不是因为折扣被隐藏了 —— 它就在每一个定价页面上 —— 而是因为领取它需要回答一个组织内从未有人问过的问题:我们的推理调用中,哪些真正需要立即得到答案? 事实证明,这是一个架构问题,而大多数公司的诚实回答是:“我们从未对它们进行过分类,所以默认情况下所有任务都运行在交互式通道中。” Batch 折扣并不是一个定价脚注。它是一场测试,考验你的系统是否了解自身的延迟需求 —— 而大多数系统都未能通过测试。

你的数据 Agent 需要一个统一的营收定义

· 阅读需 10 分钟
Tian Pan
Software Engineer

Text-to-SQL 演示从不会因为语法而失败。模型生成的 SQL 非常流畅 —— 说实话,比大多数初级分析师写得都好 —— 查询可以运行,并且返回了一个数字。演示在三周后的生产环境中宣告失败,因为 CFO 注意到智能体的 “Q2 营收” 与董事会报告不符。这不是因为 SQL 格式错误,而是因为数据仓库中有三种说得通的营收定义 —— 预订额 (bookings)、已确认营收 (recognized) 和扣除退款后的净值 (net-of-refunds) —— 而模型自信地选择了其中一个。恰恰不是财务部门使用的那一个。

这是最关键的失效模式,而且在你见过的每一个基准测试中都是不可见的。解决方案不是更好的模型或更长的提示词。而是一项大多数数据团队已经构建了一半然后放弃的基础设施:语义层 (semantic layer)。你为 BI 仪表板编写的指标定义 —— dbt metrics、LookML、Cube 定义 —— 事实证明是数据智能体缺失的工具契约。交付可靠智能体的团队意识到,构建顺序与大家的假设恰恰相反:语义层优先,智能体随后。

你的微调模型是一个你需要维护的分支

· 阅读需 12 分钟
Tian Pan
Software Engineer

微调项目的预算会议总是估错了重点。团队估算的是数据流水线、训练运行和评估轮次——一项有着明确终点的一次性投资。随后模型发布,准确率图表节节攀升,然后大家就转向下一个项目了。六个月后,一封邮件寄达:你的适配器(adapter)所绑定的基础模型有了退役日期。你的系统本身没有任何变化,但它的根基全变了。

这是没人算进成本的部分:微调不是一个你已经完成的产品。它是别人代码库的一个分叉(fork),而每一次基础模型的发布都是一次你并未计划的上游变基(rebase)。任何曾在快速更迭的开源项目中维护私有补丁(patches)的人都清楚个中滋味——分叉的创建成本很低,但维护成本极高。

护栏也是模型:那个没人放进仪表盘的隐藏依赖

· 阅读需 13 分钟
Tian Pan
Software Engineer

这是一个正在演变成一种典型的故障复盘(postmortem)模式。主模型整晚运行良好。延迟平稳,Token 吞吐量正常,服务商状态页显示正常。然而,整整 40 分钟内,每一个用户请求都失败了——因为位于模型前端的安全分类器(safety classifier)超时了,中间件将该超时封装为一个通用异常,而异常处理程序返回了拒绝响应。你的模型并没有宕机。是你的“门禁”宕机了,而这扇门被一名从未将其视为决策选项的工程师配置成了“故障即关闭”(fail closed)。

令人不安的事实是,大多数团队在生产环境中运行着第二个机器学习系统,却不愿承认。内容审核分类器、越狱检测器、PII 清洗器、主题过滤器——每一个都是模型,拥有各自的延迟分布、错误率、在漂移中悄然腐烂的训练数据假设,以及各自的故障模式。但因为它被称为“护栏”,它就被当作配置文件来对待:设置一次,从不监控,在仪表盘上缺席,也不在值班手册中。你绝不会在没有 SLO 的情况下发布主模型。但大多数团队发布护栏时,甚至连健康检查都没有。

你的内部框架是一种低资源语言

· 阅读需 10 分钟
Tian Pan
Software Engineer

让编程智能体(coding agent)构建一个 React 组件,它第一次尝试就能写出地道的、基于 Hook 的、带有无障碍标注的代码。让同一个智能体使用你公司的内部 ORM —— 那个平台团队维护了六年、拥有出色文档和上百个内部用户的框架 —— 它就会幻觉出不存在的方法,从其他库里发明配置选项,并自信地交付出基于它臆造的 API 编写的代码,而这些代码根本无法通过编译。

这种差异并非源于质量。你的 ORM 可能比模型能完美处理的一半开源库设计得都要好。差异在于训练数据。React 背后有数百万个公开仓库;而你的框架则一个都没有。在自然语言处理(NLP)的术语中,你的内部框架是一种低资源语言(low-resource language) —— NLP 研究人员针对低资源语言记录的每一个后果,现在都适用于你的代码库。

你的模型认为你的技术栈已过时 2 年

· 阅读需 12 分钟
Tian Pan
Software Engineer

有一类 AI 生成的 Bug 几乎每次都能通过代码审查,它既不是幻觉函数,也不是捏造的包。它是完美的地道代码——地道到符合模型训练数据冻结时你的技术栈版本。模型为运行 Tailwind v4 的项目编写 tailwind.config.js,在 Hooks 代码库中调用类组件的生命周期方法,或者调用一个在三个小版本前就被弃用、并在你的 lockfile 实际锁定的版本中已被删除的 API。代码看起来毫无破绽。它看起来就像出自某个备受推崇的教程。只是那个教程来自 2024 年。

称之为“训练截止日期 Bug”:这类缺陷的存在并非因为模型推理能力差,而是因为模型对你依赖项的了解带有时间戳,而你的 lockfile 并不在意。一项 ICSE 2025 对 8 个常用 Python 库、7 个代码模型的研究发现,在看似合理的补全代码中,弃用 API 的使用率高达 25–38%——当周围代码已包含过时模式时,这一比例会攀升至 70–90%。这些并非罕见的边缘情况。它们是要求一个冻结的产物为不断变化的目标编写代码时的默认失败模式。

在你的智能体能够自我重试之前,精确一次性处理(Exactly-Once)曾是一件难事

· 阅读需 10 分钟
Tian Pan
Software Engineer

我们花了二十年的时间来教导服务如何安全地进行重试。这个方案已经非常成熟了:客户端生成一个唯一的幂等键 (idempotency key),将其附加到请求中,服务器在执行工作的同一个事务中记录该键及其结果。掉线、超时、500 错误 —— 客户端使用相同的键进行重试,服务器识别出该键,并返回记录的结果,而不是再次扣款。Stripe 多年前就推出了这种模式,它已成为任何涉及资金业务的 API 的基本要求。

整个设计都基于一个无人提及的假设:调用者会逐字节地重复其请求。 重试携带相同的键,是因为重试是同一段代码路径使用相同的变量重新执行。一旦打破这个假设,整个方案就会悄无声息地失效。