一个LLM请求的九步解剖:从点击到响应的全链路

LLM请求九步中仅两步属模型,七步是工程契约,验证与预算才是成败关键。
一位资深前端工程师系统拆解了LLM应用的完整请求链路,将其分为九个步骤,并指出只有prefill和decode两步属于模型内部,其余七步——客户端转发、入参验证、提示词拼接、token预算、流式传输、输出验证和重试日志——全是工程契约。文章强调API密钥必须留在服务端,Pydantic验证是最便宜的止损点,模型API默认无状态导致历史token重复计费,流式输出中错误可能藏在200状态码之后,429可能代表限流也可能代表配额耗尽。核心心法是:把模型当作不可靠、按量计费的远程依赖,在它两侧都放上验证。
大多数开发者第一次接入LLM时,只关心一件事:调API、拿结果。但一个前端工程师在系统梳理LLM应用请求链路后发现,真正决定成败的往往不是模型本身——九个步骤里只有两步属于模型,其余七步全是工程契约。

为什么要拆解一个LLM请求
作者有8年以上React/TypeScript前端经验,正在公开学习应用AI,目标是成为AI工程师乃至AI前向部署工程师(FDE)。在深入token、RAG、agent之前,他先画了一张地图:当用户点击"Summarize"按钮时,系统里到底发生了什么。
这个视角切换很重要。对前端工程师来说,LLM功能看起来只是"把文本发给后端、等结果回来",但中间隐藏着验证、预算、流式传输、错误处理等一系列工程决策。把这些拆开看,能帮助团队在接入AI时少踩坑。
调用前:步骤1-4
客户端发请求,密钥必须留在服务端
从浏览器视角看,LLM功能就是一次普通的HTTP调用:POST /summarize,带上用户文本,聊天场景再加会话id。OpenAI官方文档明确要求绝不能在客户端代码中暴露API密钥,所以密钥放在服务器上,只有服务器与模型提供商通信。

入参验证是最便宜的止损点
FastAPI用Pydantic模型校验请求体。数据不合法根本到不了业务处理函数:FastAPI抛出RequestValidationError,默认处理器返回HTTP 422。一旦验证通过,Pydantic保证字段类型符合声明。这是拦截坏输入成本最低的位置——此时还没有消耗任何token。
提示词拼接:无状态是默认设定
模型只能看到你发过去的内容。Anthropic的Messages API是无状态的,每次都要重发完整历史;OpenAI同样将每个请求视为独立无状态,虽然提供可选的会话状态管理,但明确指出链条中较早的输入token在每一轮仍然计费。

token计数与预算检查
模型读的是token而非字符,且分词器与模型绑定,不同模型的计数结果不同。系统提示、工具定义、历史记录和输出共享同一个上下文窗口。如果仅输入就超限,请求直接失败(Anthropic返回400,提示"prompt is too long")。发送前估算token数量,并设置最大输出长度,是控制成本的基本功。

模型内部:步骤5-6
Prefill:并行读入全部输入
推理分两个阶段。Prefill阶段模型并行处理所有输入token,计算密集,是模型侧决定首token延迟(TTFT)的主要因素。网络传输和提供商排队时间会叠加在这段停顿上。

KV缓存(Key-Value Cache)是理解Decode阶段性能的关键机制。在Transformer的自注意力计算中,每个token都会生成对应的Key和Value向量,而这些向量在后续生成新token时需要被反复使用。如果每一步都重新计算所有历史token的K和V,计算量会随序列长度呈平方级增长。KV缓存的做法是把已计算的K和V矩阵保存在显存中,生成新token时只计算当前token的K和V并追加到缓存,从而使每步解码的计算量近似恒定。代价是显存占用随上下文长度线性增长,这也是长上下文请求成本更高的原因之一。Prefill阶段正是填充这份缓存的时刻,因此它计算密集;Decode阶段则因缓存的存在而变得相对轻量,但受限于显存带宽。
Decode:逐token自回归生成
随后模型自回归生成:对词表中每个token打分、选一个、追加、重复。KV缓存保留先前计算,避免每步从头开始,每步的节奏就是每个输出token的耗时。遇到结束符、停止序列或token上限时停止。

至于"怎么选",属于采样设置:贪心,或带temperature、top-k、top-p的采样。别假设这些参数在所有模型上都可用——Anthropic文档说明Claude 4.7及以后版本,若将这些参数设为非默认值会返回400。
SSE(Server-Sent Events)是一种基于HTTP的服务器推送技术,允许服务器在单个连接上持续向客户端发送文本事件流。与WebSocket不同,SSE是单向的(服务器到客户端),使用普通HTTP协议,天然兼容现有基础设施和代理。在LLM场景中,提供商将每个生成的token封装为一个data:事件逐步推送,客户端通过EventSource或流式fetch读取。文章提到的两个坑正源于SSE的协议特性:一旦响应头以200发出,后续错误只能作为流内事件传递,HTTP状态码已无法反映;同时,流式输出意味着用户和审核系统在生成完成前就看到了部分内容,给内容安全审核带来时序上的挑战。
调用后:步骤7-9
流式返回:错误可能藏在200之后
OpenAI和Anthropic都在解码过程中以SSE流式推送token,所以步骤6和7是重叠的。文档里有两个容易忽略的坑:错误可能在流中途到达,此时状态码已经是200;以及部分输出比完整响应更难审核。

输出也要验证
结构化输出能约束模型遵循你提供的JSON Schema(OpenAI支持其中一部分),但其指南也承认仍可能出错,并列出两种必须处理的情况:拒绝响应和因token上限被截断的响应。如果采用流式,要等流结束后再验证。FastAPI的response_model是第二道检查:类型不匹配会变成服务器错误,而不是返回错误数据。但要记住,格式合法不等于答案正确——正确性评估是后续话题。

重试要分情况,日志要记全
同样的状态码含义可能不同:429通常是限流,但Anthropic在你触达月度支出上限时也会返回429,所以重试前先读错误体。配额或计费错误绝不重试。对于瞬时错误,有Retry-After就遵守,否则用带抖动的指数退避,并限制重试次数和总时长。官方SDK本身已会重试部分错误(Anthropic默认两次),设定自己的重试上限时要把它算进去,而不是层层嵌套循环。
最后,记下输入/输出token用量、延迟和提供商的request id。这些记录支撑调试、成本追踪,最终也支撑评估体系。

指数退避(Exponential Backoff)与抖动(Jitter)是分布式系统中处理瞬时故障的标准策略。基本思路是每次重试的等待时间按指数增长(如1秒、2秒、4秒、8秒),避免在服务端过载时持续高频冲击。但纯指数退避有一个隐患:多个客户端可能在同一时刻发起重试,形成“惊群”效应,再次压垮服务。抖动通过在退避时间上叠加随机量来打散重试时刻,常见形式有全抖动(在0到计算值之间随机)和等抖动(在计算值的一半到全值之间随机)。结合Retry-After响应头使用时,应优先遵循服务端给出的等待建议,仅在缺失时回退到自己的退避策略,并始终设置最大重试次数和总超时,防止无限重试拖垮请求链路。
核心心法:把模型当作不可靠的、计费的远程依赖
作为前端工程师,作者觉得这套流程意外地熟悉:这就是一个请求生命周期,只是中间换了个不寻常的后端。九个步骤中只有两步属于模型,其余七步是契约、预算、流和失败处理——这些恰恰是工程师能掌控的部分。
他的工作准则由此而来:把模型当作一个不可靠、按量计费的远程依赖,在它的两侧都放上验证。
这个判断对正在接入LLM的团队有现实意义。许多项目把精力集中在提示词调优上,却在入参验证、token预算、流式错误处理和重试策略上栽跟头。模型能力会持续进化,但请求链路的工程约束不会消失。
作者的学习路线图将这一篇归入基础模块:Python类型与异步、FastAPI与Pydantic、LLM机制(token、上下文、推理)。下一篇将聚焦"面向AI后端的Python:TypeScript工程师的复习课"。他也向读者抛出一个问题:你构建的第一个LLM功能,这九步里最先崩的是哪一步?
相关推荐

大厂AI工程化面试:前端监控到Agent全链路可观测性
从PerformanceObserver采集性能指标、onerror与unhandledrejection捕获异常,到RAG链路重排优化、上下文压缩控制token成本,再到对标LangSmith与Sentry的全站AI全链路可观测性体系设计,拆解大厂AI工程化面试的三层递进考点。

WorkBuddy保姆级教程:手把手搭建专属AI Agent工作助理
WorkBuddy保姆级教程:从豆包等聊天模型的局限讲起,手把手教你搭建专属AI Agent工作助理,实现本地文件批量处理与自动化操作,非程序员也能轻松上手。

Windows下用LangChain-Chatchat+DeepSeek搭建本地知识库
本文整理B站教程,详解Windows下用LangChain-Chatchat与DeepSeek搭建本地知识库的全流程,包括Anaconda环境配置、Ollama模型管理、镜像源加速及常见报错解决,助你快速实现RAG问答。