跳到主要内容

18 篇博文 含有标签「llm-infrastructure」

查看所有标签

代理墙钟预算:一场与工具超时机制的赛跑

· 阅读需 12 分钟
Tian Pan
Software Engineer

有一种 Agent 漏洞,当你孤立地观察任何单个组件时,它都不会出现。模型没问题,工具没问题,重试策略也没问题。纸面上的超时值甚至可以说很慷慨。然而,一个通常在 8 秒内完成的工具,却总是在一个已经在 7.9 秒时将其宣告为失败的 Agent 面前折戟。Agent 围绕一个从未发生过的“错误”重新规划,并启动了第二次调用,而第一次调用的结果即将与其发生碰撞。

漏洞不在任何一个框框里。它存在于两个没人同意应该同步的时钟之间的缝隙中。

你的 Agent 每一轮都在重新生成对话摘要,只因缓存键包含了一个时间戳

· 阅读需 12 分钟
Tian Pan
Software Engineer

一个只被写入却从未被读取的缓存算不上缓存。它只是一个增加了额外延迟、按 KB 计费的日志系统。而这种失效模式最残酷的版本是,从每个角度看缓存都是健康的:set 调用成功,get 调用返回迅速,键(key)格式正确,值(value)有效,TTL 设置合理。唯一的问题是,没有任何一次 get 调用能找到之前 set 调用写入的键,因为键中的一个字段在每次计算时都会发生变化。

这是一个关于调试过程的故事:为了“能分辨出我正在看的是哪条缓存记录”,一位工程师在缓存键中添加了一个时间戳。结果,在没人察觉的两个星期里,系统悄悄地为每场对话多支付了 14 次额外的 LLM 调用费用。

RAG 去重环节的隐蔽失效:当近重复数据占满 Top-K 检索结果时

· 阅读需 12 分钟
Tian Pan
Software Engineer

一个检索增强生成(RAG)管道可能会连续数周出现性能退化,而没有任何指标能察觉到。相关性评分看起来正常,检索延迟没有变化。触及受损主题的评估切片(eval slice)向错误方向移动了 0.25 个点,而你的每周审查将其归因于噪声。直到有人阅读了模型为某个客户工单实际接收到的上下文窗口,发现同一个段落出现了三次——一次是标题格式,一次是小写格式,一次是去除了标点的格式——你才意识到,一个月以来,你的前五名(top-five)在暗地里其实只是前二名。

这类故障的特点是:系统完全在按照指令行事。检索器正在返回与查询最相似的向量。这些向量中的每一个都确实与正确的主题相关。索引根本不知道其中三个向量来自同一个段落(只是以三种方式索引了三次),因为原本应该捕获这种情况的入库阶段去重环节正在静默跳过它。

云厂商负载均衡器悄然忽略的会话亲和性

· 阅读需 12 分钟
Tian Pan
Software Engineer

你的仪表盘显示缓存命中率为 71%。你的财务伙伴很满意。你的 p50 延迟也表现正常。然而,一个来自长时间运行的智能体(agent)会话的客户支持工单传了过来:第 14 轮对话花了 11 秒才产生首个 token,第 15 轮花了 8 秒,第 16 轮花了 9 秒。你调出链路数据(trace)。每一轮对话报告的 cache_read_input_tokens 值都是 0。系统提示词有 1.6 万个 token。用户认为智能体坏了,你认为你的供应商坏了。你们两个都不对。总体的命中率是一个幸存者统计数据 —— 它平均了那些容易命中缓存的短对话,并悄悄吸收了那些在会话中期崩溃为“首轮冷启动”的长对话。

这是任何供应商的复盘报告都不会向你描述的故障模式,因为从他们的遥测数据来看,系统正在按设计运行。负载均衡器正在做出它被要求做出的路由决策。缓存正按照它被要求遵循的时间表进行填充和置换。你传递的提示 —— prompt_cache_key、会话 ID、用户 ID,或者你序列化到该字段中的任何字符串 —— 始终都只是建议性的,而“建议性”意味着“在方便时会被忽略”。在负载压力下、发生扩缩容事件时、上游节点(pod)正在排空时,或者亲和性感知层饱和时,你的提示会悄无声息地降级为均匀的路由决策。请求落在一个冷启动的节点上。原本可以以亚毫秒级成本提供服务的前缀 KV 张量就在 16 英尺外的兄弟机架上,却无法访问。你的对话再次支付了全额前缀成本,而你仪表盘上的标题数字纹丝不动,因为另外 2000 个只有一轮的对话都正常命中了缓存。

你的数据驻留政策中遗漏的推理区域锁定

· 阅读需 10 分钟
Tian Pan
Software Engineer

合规审计总是从同一个问题开始,而你的团队也总是以同样的方式回答:“客户数据在哪里处理?”在欧盟(EU)地区。幻灯片是这么说的,SDK 配置截图证实了这一点,DPA(数据处理协议)也做出了承诺。接着,审计员提取了上个季度的请求日志样本,将其与服务商的每请求区域头信息(per-request region header)进行比对,房间里顿时安静了下来。在大约 40 分钟的容量事件期间,大约 4% 的欧盟企业 Prompt 由美国区域的推理节点提供服务,而团队对此一无所知。保存可重用前缀(prefixes)的缓存位于全球池中。支持团队查询的追踪存储(trace store)位于 us-east。DPA 成了幻灯片。合同成了一个路由提示(routing hint)。

这种事件不会出现在事后分析(postmortem)中,因为没有任何服务降级。模型返回了答案,用户得到了响应,延迟图表保持平稳。出故障的是仪表盘从未监测到的东西:请求穿过服务商基础设施的地理路径。那些绝不会将 us-east-1 的 URL 与“请求实际上在 us-east-1 执行”混为一谈的工程师,在 LLM API 层级却经常犯同样的错误,因为服务商的区域参数看起来像 AWS 的参数,在正常路径(happy path)下表现也像 AWS,但一旦首选区域的 GPU 耗尽,它就会静默降级为“尽力而为(best effort)”模式。

推理服务提供商拒绝发送的背压信号

· 阅读需 10 分钟
Tian Pan
Software Engineer

你的重试逻辑在遇到 429 时会退避。当延迟上升时,你的队列深度告警会触发。在这两个信号之间,存在一个供应商负载区间,此时正确的做法是“减速 20%”——而供应商唯一会告诉你的是那个姗姗来迟的二进制限流信号。对于智能体集群协作来说,最有用的信号恰恰是没有任何推理 API 真正公开的那个。

429 是墓碑,而不是警告。当你收到它时,供应商已经认定你的流量过载,你已经浪费了一次请求的 Token 计数,而且——如果你与其他消费者共享租户——他们可能也收到了。有趣的故障模式不是 429 本身;而是它发生前的几秒钟,那时全世界的客户端都在“一切正常”和“你被切断”之间盲目飞行。

当每个请求的思考成本各不相同时的容量规划

· 阅读需 11 分钟
Tian Pan
Software Engineer

传统的容量规划(capacity planning)建立在一个默认的假设之上:请求在大体上是可以互换的。Web 服务器处理登录、搜索、结账 —— 尽管这些操作有所不同,但它们的差异都在一个范围之内。你衡量每秒请求数(RPS),观察 p50 和 p99 延迟,乘以安全系数,然后进行资源配置。这个模型之所以有效,是因为工作的基本单位 —— 单个请求 —— 具有稳定的成本。

Agent(智能体)的工作负载从根本上打破了这个假设。你对 Agent 的一个查询可能通过一次简单的生成就解决了:300 个 token 输入,200 个输出,两秒钟搞定。但下一个查询,表面上看起来一模一样,却可能触发一个规划步骤,分发出 40 个工具调用(tool calls),在每一轮对话中重新读取不断增长的上下文,并在四分钟内消耗掉 120 万个 token。同样的端点(endpoint),同一个用户,同一条代码路径。单个请求的成本差异可能达到三个数量级,而且请求中没有任何信息能预先告诉你接下来会遇到哪种情况。

自研还是购买 AI 网关:锁定你未来 18 个月的关键决策

· 阅读需 12 分钟
Tian Pan
Software Engineer

关于 AI 网关是自研还是购买的决策,几乎从来不是基于某种决策框架做出的。它往往在第一周由一位对该问题感兴趣的工程师凭直觉决定,然后在第九个月由一位厌倦了账单的总监重新审视。这两个时刻都不是做决策的最佳时机,而且双方都没有站在未来 18 个月的关键维度上来衡量这一选择。

自研路径的诱人之处在于第一个月非常便宜。在 OpenAI 前面加一个 200 行代码的代理,写一个 switch 语句将“claude”请求路由到 Anthropic,再加上一个重试循环,团队就交付了一个看起来像网关的东西。到了第九个月,那个代理变成了 1.2 万行代码,充斥着写了一半的重试逻辑、失效机制混乱的 Prompt 缓存、没人敢相信的成本统计、在上次事故中触发方式错误的备用路由、与技术栈其他部分脱节的可观测性模式,以及在第一个企业客户提出要求后强行加入的租户限流。每一个功能都是“购买路径”在第一天就能交付的功能的拙劣复制。而当初写那 200 行代码的工程师已经离职了。

AI 网关:那个没人点名的单点故障 (SPOF)

· 阅读需 12 分钟
Tian Pan
Software Engineer

这种说辞听起来很负责任。“我们别在各处硬编码 OpenAI —— 我们在前面加一层薄薄的抽象,这样以后如果需要,我们可以随时更换供应商。”两年后,那个“薄薄的抽象”变成了一项拥有自己部署流水线、SRE 值班表、拦截糟糕 Prompt 的评估门控、每年节省七位数资金的语义缓存、带有针对特定供应商退避机制的重试策略、所有仪表盘都依赖的可观测性架构,以及一个存放着六家模型厂商凭证的密钥库的服务。公司里的每一个 AI 功能最终都汇聚于此。

它也几乎是在无意间,成为了整个技术栈中爆炸半径最大的单点故障(SPOF)。当主要 LLM 供应商宕机时 —— 2025 年,OpenAI 自 1 月以来被记录了 294 次停机事件,而 Anthropic 仅在 12 月就记录了 184.5 小时的总客户影响 —— 网关会自动绕过它,大多数用户甚至察觉不到。而当网关本身挂掉时,每个产品中的每个 AI 功能都会同时停止工作,原本应该触发的故障转移根本没有机会执行,复盘报告的开头往往是:“我们为了隔离供应商宕机影响而构建的抽象层,本身成了那场宕机。”

Prompt Cache 作为隐蔽信道:TTFT 探测泄露跨租户 Prompt

· 阅读需 13 分钟
Tian Pan
Software Engineer

提示词缓存(Prompt caching)是一种只要开启就能立即获益的优化手段。长系统提示词仅需哈希一次,KV 状态驻留在 GPU 显存中,随后任何复用该前缀的请求都能跳过预填充(prefill)成本。供应商报告称,对于缓存的请求,延迟降低了 80%,输入成本降低了 90%。在大规模应用中,这种经济效益是无法抗拒的:摊销到数百万次调用中的单一共享前缀,将一项支出变成了几乎可以忽略不计的尾差。

实现这种节省的机制本质上是一种共享资源,其命中或未命中的状态可以通过延迟来观察。这种可观察性就是侧信道(side channel)。在网络外部可以清晰分辨缓存命中与缓存未命中,这种差异巨大且具有确定性。这项在成本看板上占有一席之地的优化方案,还兼任了一份无人预料的工作:泄露同一供应商下其他租户当前正在进行的活动信息。

首个Token在撒谎:为什么上下文加载——而非推理——才是AI功能延迟的真正瓶颈

· 阅读需 11 分钟
Tian Pan
Software Engineer

大多数关于AI延迟的讨论都搞错了方向。团队痴迷于GPU利用率、模型量化和批处理大小。与此同时,真正让用户感到烦躁的延迟——AI开口说话前的那段停顿——几乎完全由推理开始前发生的事情决定。瓶颈在于上下文,而非算力。

首Token时间(TTFT)是决定AI功能感觉灵敏还是迟钝的关键指标。而TTFT主要由预填充阶段主导:在生成任何输出Token之前,处理完整输入上下文所需的时间。对于128K Token的上下文,预填充可能耗时数秒。GPU在努力工作,但用户什么也看不到。

解决方案不是更好的GPU,而是在用户提问之前就预先加载好上下文。

单租户推理隔离:当共享缓存、微调模型和嵌入在客户间泄露时

· 阅读需 15 分钟
Tian Pan
Software Engineer

多租户 SaaS 在十年前就解决了数据隔离问题。Postgres 中的行级安全性(Row-level security)、每个租户的加密密钥、范围限定为租户前缀的 S3 存储桶策略——到 2018 年,这套方案已经非常成熟,以至于当审计员询问“向我展示客户 A 的数据如何无法触及客户 B 的数据”时,只需要提供一份一页纸的回答,并在每一层附上引用即可。AI 功能悄然重新引入了这个问题,而现在的答案不再只有一页纸。

有趣的部分并不是 AI 破坏了隔离。有趣的是它在 哪里 破坏了隔离:不是审计团队守卫了十年的数据层,而是没有人画在图表上的四个新层级。提示词缓存前缀(Prompt cache prefixes)以跨请求共享 KV 状态的方式,将首字生成时间(time-to-first-token)变成了一个侧信道。在聚合客户数据上训练的微调模型会记住特定租户的措辞,并将其反馈给错误的客户。当威胁模型要求物理分离时,嵌入索引(Embedding indexes)却通过查询过滤器进行逻辑分区。跨请求的 KV 缓存重用创建了时间信道,而当“共享推理没问题”被视为一种合理的捷径时,没有人对此进行过威胁建模。

本篇文章讨论了发生了哪些变化,以及当你认真对待这个问题时,这种规范看起来是什么样子的。