跳到主要内容

76 篇博文 含有标签「infrastructure」

查看所有标签

批处理负载挤占了你的实时路径:GPU 预留的惨痛教训

· 阅读需 10 分钟
Tian Pan
Software Engineer

每晚的微调任务在 UTC 时间 02:00 开始。它进入共享 GPU 池,占用它能找到的每一个槽位并持续持有。到 09:30,当工作日的首波推理流量到达时,自动扩缩器(autoscaler)试图声明已被连续占用七个半小时的容量。早晨的前 90 分钟,系统运行在约为基准 p99 延迟四倍的水平上。仪表盘报告了一个“喧闹的早晨尾部(noisy morning tail)”,推理团队将其归因于用户行为,因为实际的资源争用发生在一个推理团队并不拥有的任务队列中。

这是你在容量评审的成本归因幻灯片中无法捕捉到的 GPU 共享失败模式。共享被宣传为利用率的胜利——晚上训练,白天服务,填补低谷。实际交付的却是直到池按延迟类别(而非按团队或按时间)进行分区之前,你都无法摆脱的延迟长尾。

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

· 阅读需 10 分钟
Tian Pan
Software Engineer

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

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

你增加的 Reranker:对召回率的拖累超过了对精准度的提升

· 阅读需 12 分钟
Tian Pan
Software Engineer

离线评估的结果非常明确。在向量搜索的前 50 个结果之上叠加一个交叉编码器(cross-encoder)后,nDCG@5 提升了 4 个点。团队在周二上线了该功能。到了周四,p99 检索延迟已超过 SLO(服务水平目标)700 毫秒,客户成功团队也开始转发空结果页面的截图,而这些页面在旧的流水线下本应是有内容的。真正关键的指标——用户感知的回答质量——下降了。重排序器(reranker)实际上是一个被团队冠以“改进”之名的性能退化,而评估标准则是将这种退化隐藏在众目睽睽之下的幕后黑手。

这是生产环境检索中最常见的失效模式之一,且很少被准确描述为:一个评估缺陷(evaluation bug)。重排序器完成了它的宣传任务:以更细的粒度对前 50 个结果进行了重新排序。问题在于,用于证明其合理性的指标——在无限预算下针对完整重排序列表计算的离线 nDCG——描述的是一个生产系统并不存在的理想世界。在生产环境中,最终输出的答案并非评分最高的重排序列表,而是系统在请求截止时间前所能返回的任何内容。一旦你以此方式重新定义指标,重排序器的贡献就不再是 4 个点的提升,而是一条曲线。

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

· 阅读需 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 个请求时就已经难以为继。

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

· 阅读需 11 分钟
Tian Pan
Software Engineer

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

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

那个直到触发时你才察觉的 Token 预算

· 阅读需 11 分钟
Tian Pan
Software Engineer

你的团队与推理提供商协商了月度 Token 配额。合同规定了上限。提供商门户的仪表板显示昨天的使用情况,存在一天的延迟。API 本身返回每分钟速率限制头——anthropic-ratelimit-tokens-remainingx-ratelimit-remaining-requests——而对于你实际需要规划的月度配额桶却只字未提。你的智能体集群没有机制在预算耗尽时减速,因为实时到达的唯一信号是 429 错误——而这个信号在预算已经用完后才出现,且伪装成重试逻辑通常会忽略的瞬时错误。

这是一个与速率限制(rate limiting)性质不同的问题。速率限制是一个快速波动的节流阀,消费者必须在几秒钟内做出反应;响应头告诉你桶里还剩一千个 Token,并在 40 秒内补满,一个编写良好的客户端会退避并重试。月度配额则是一个缓慢变化的预算,消费者必须以周为单位进行规划。这两者之所以容易混淆,是因为它们共享错误代码,有时甚至共享同一个仪表板,但它们需要不同的控制手段——而提供商公开的信息与消费者需求之间的差距,正是本月最严重事故的导火索。

长出胳膊和腿的缓存提示词前缀

· 阅读需 11 分钟
Tian Pan
Software Engineer

六个月前,你的提示词前缀是 4,000 tokens。它稳定、缓存预热,几乎可以摊销到不计成本——系统指令的每次调用附加费,相比每次响应的成本,只是一个舍入误差。今天那个前缀变成了 11,000 tokens,你的缓存命中率从 92% 滑到了 31%,你的推理账单上升了 4 倍。团队里没有人能指出是哪个 PR 干的。没有一条 commit message 写着"将提示词增加 7,000 tokens"。每一次修改都很小,每一次修改都有理有据,每一次修改都干干净净地合入了。

提示词前缀长出胳膊和腿,就像地下室积攒纸箱一样。一个团队需要注入用户的订阅等级,这样 agent 才能解释套餐限制。另一个团队需要用户时区的今天日期,这样"明天提醒我"才能工作。第三个团队把当前 A/B 变体名硬塞进去,这样 eval traces 才能切片。市场团队加进了当前促销 banner,这样 agent 才能适时提及它。合规团队加进了功能标志清单,这样模型才能拒绝那些不在灰度名单里的用户访问 beta 功能。每一条都是一行的添加。每一条单独看都站得住脚。但加起来摧毁了你的缓存。

AI 功能规格说明书中无人提及的碳排放项

· 阅读需 11 分钟
Tian Pan
Software Engineer

打开任何一份 AI 功能评论,你都会听到关于这三个数字的辩论:延迟、Token 成本和准确率。有人调出 P95 图表,有人计算单千次请求的成本,还有人争论评估分数 (eval score) 已经好到可以发布了。没人提到能源。没人提到碳排放。正因为没人提及,该功能的环保足迹仍然被决定了——由谁赢得了那场关于金额的争论所含蓄地决定。

这就是 AI 可持续性中沉默的问题。并不是团队故意选择了高碳设计,而是他们根本没有做出选择。碳足迹成了成本决策的副作用,而成本与碳排放之间仅存在松散的关联。在支出仪表盘上看起来大获全胜的路由规则,可能会悄无声息地让排放量翻倍,而会议室里没人会知道,因为那个能告诉他们真相的数字从未出现在仪表盘上。

这篇文章将能源和碳排放视为它们的真实身份:AI 系统的一个可测量、可掌控的属性,与延迟和成本处于同等地位。它不是企业价值的脚注,而是一个明细项。

温池与冷真相:Serverless LLM 推理中隐藏的延迟底线

· 阅读需 10 分钟
Tian Pan
Software Engineer

将你的 GPU 推理自动缩放至零(Autoscaling to zero)看起来是显而易见的成本控制策略。GPU 是账单中最昂贵的项目,流量具有突发性,而空闲时间纯粹是浪费。所以你开启了缩放至零(scale-to-zero),看着云端账单下降,并以此自得。

然而,在一段沉寂之后,一位用户出现了,他们的第一次请求需要 60 秒才能返回一个 token。运行 Serverless LLM 推理的生产部署经常报告冷启动超过 40 秒才出现第一个 token —— 相比之下,模型预热后的每个 token 延迟大约仅为 30 毫秒。这是冷路径和热路径之间千倍的延迟差距,而这完全取决于你的流量空闲情况。

这是没有人会写在 PPT 上的权衡。缩放至零并没有消除成本;它将稳定的金钱成本转化为了突发性的延迟成本,然后将这种延迟成本隐藏在仪表盘很少关注的 p99 尾部。

智能体临时目录:无人盘点的无主文件系统 PII 暴露面

· 阅读需 11 分钟
Tian Pan
Software Engineer

一位监管人员走进你的办公室,提出了安全团队反复演练过的那个问题:“请展示客户数据存放的每一个地方。” 你的数据团队拿出了清单。主数据库在上面。分析型数据仓库在上面。对象存储、队列、搜索索引、备份目的地——统统都在上面,附带着分类标签、保留政策、加密详情和负责人姓名。接着,房间里有人提到了 Agent 工作线程池,而清单上却对此只字未提。这个线程池已经运行了九个月。每个工作线程都有一个本地磁盘。这些线程上的 Agent 一直在解析 PDF、转录音频、下载邮件附件,并在工具调用之间缓存中间 JSON,而这一切从未停止过。却没有人将这些内容放入资产登记表。

这就是“临时目录问题”(scratch directory problem)。每一个长期运行的 Agent 工作线程都会积累一个临时文件系统,随着新工具的加入而有机增长——PDF 解析器提取的文本、Whisper 步骤转录的音频、Gmail 工具下载的附件、浏览器使用步骤的截图、为下一轮对话缓存的向量搜索片段、Agent 在两次工具调用之间生成的中间 JSON(以便第二次调用不必重新推导)。与数据库、队列和存储桶不同,这个表面没有保留政策,没有静态加密标准,没有 DLP 扫描器过滤,也没有出现在数据分类电子表格中。平台团队认为 “Agent 状态”指的是推理提供商的上下文窗口。SRE 团队认为 “Agent 状态”指的是持久化数据库。而工作线程的 /tmp/agent-workspace-${session_id}/ 目录则是客户数据的第三份副本,且处于无人管理的状态。

区域模型发布的“彩票”效应:当你的产品在不同大洲表现各异时

· 阅读需 12 分钟
Tian Pan
Software Engineer

周五下午,一封客户成功(customer-success)邮件发了过来:“德国用户的模型效果变差了。”团队打开评估仪表板,评分没变,p95 延迟也很正常。配置中的模型名称还是三周前发布的那一个。一切都没变。但其实有些东西变了。上个迭代中,美国的端点悄悄上线了新一代模型,而欧洲的端点由于供应商还没完成地区性的分阶段发布,仍在使用旧版本。而位于两者之前的负载均衡器,则在团队的所有仪表板上掩盖了这一差异。

这就是所谓的区域性模型发布博弈。你的“单一模型”抽象并不是单一的。当供应商跨大洲分阶段发布时,它就开始分化了——而在大多数年份、对大多数供应商而言,这种情况在大多数时间里都在发生。当这种情况发生时,客户端 SDK 中的版本字符串并不会改变。你的追踪(traces)看起来一模一样。你与供应商签订的合同也没有做出其他承诺。而你赖以捕捉行为回归的评估套件,几乎肯定运行在某个地区的 CI 机器上,并访问地理位置最近的端点。

昼夜延迟:为什么你的 AI 功能在东部时间上午 9 点最慢

· 阅读需 10 分钟
Tian Pan
Software Engineer

在上个季度的某个时候,你团队的一名工程师在 Slack 上发了一个帖子,开头是“模型变慢了”。他们展示了一张图表:你的助手功能的 p95 延迟从早上 7 点开始稳步攀升,在东部时间上午 10 点左右达到顶峰,午餐期间处于平台期,并在下午 5 点后悄然恢复。这种形态在第二天、第三天不断重复。团队追溯了他们的部署记录,指责了分词器(tokenizer)的更改,接着是上下文长度的退化,最后发现没什么是特别确定的。修复方案从未落地,因为 Bug 根本不在你的代码里。

顶尖模型提供商运行着共享的推理集群。当你的用户醒来时,北美其他地区也醒了,再加上欧洲的下午,以及每一家购买了相同 API 的公司的每一个内部工具。提供商端的队列深度翻倍,GPU 竞争加剧,你的 p95 延迟也随之翻倍——而你的代码库没发生一行代码变更。这是你技术栈中最可预测的生产事故,但几乎没有团队会为此建立仪表板。