第 17 章 LLM 服务专题
第 17 章 LLM 服务专题
学习目标
- 理解 LLM Serving 的完整架构:Prefill、Decode、KV Cache 管理的服务化;
- 掌握多租户隔离、配额、优先级的服务侧实现;
- 理解 Token 成本与 GPU 利用率的度量与优化;
- 掌握 RAG 服务、Agent 服务、工具调用的工程架构;
- 掌握流式输出、函数调用、结构化输出的实现。
17.1 LLM Serving 的完整请求流
第 1 章从 HTTP 视角看过一次请求,第 14 章从引擎视角看过推理。现在把完整服务链路拼起来:
%%{init: {"themeVariables": {"primaryTextColor": "#000000", "textColor": "#000000", "labelColor": "#000000", "nodeTextColor": "#000000", "labelTextColor": "#000000", "scaleLabelColor": "#000000"}}}%%
flowchart LR
A[客户端] --> B[网关
鉴权/限流/路由]
B --> C[应用编排
Prompt 组装/RAG/工具]
C --> D[推理引擎
vLLM/TGI/TensorRT-LLM]
D --> E[Prefill
compute-bound]
E --> F[KV Cache 管理
PagedAttention]
F --> G[Decode
memory-bound]
G --> H[流式返回]
D --> I[指标/日志/成本]关键认知:LLM 服务的瓶颈不在模型调用那一行,而在上下文组装(应用层)与 KV 管理(引擎层)。第 14 章已覆盖引擎层,本章聚焦应用层与运营层。
17.2 多租户隔离、配额、优先级
多租户(Multi-Tenancy)是 LLM 平台的基本形态(多个业务线/客户共享推理集群)。三个问题层层递进:
- 资源隔离:租户 A 的流量不能挤垮租户 B。隔离粒度:
- 物理隔离:每租户独立实例(贵、最稳);
- 逻辑隔离:共享实例 + 请求级限额(省、需配额治理);
- 混合:关键租户物理隔离,长尾租户逻辑共享。
- 配额(Quota):按 QPS、并发、token/min 给租户设上限(第 16 章限流的租户化)。LLM 特有:KV Cache 是共享的稀缺资源——大并发租户的 KV 可能挤占别人的,配额要含「并发与上下文」维度。
- 优先级(Priority):关键业务(P0)在资源紧张时优先获得 KV 与算力。实现:调度器里的请求优先级队列。
工程要点:多租户的隔离边界最终是「KV 显存」——一个租户的 100 个 128K 上下文请求能把整个实例的显存吃光。所以 KV 预算(每租户并发 × 上下文上限)是配额设计的核心(第 4 章的 KV 公式在这里变成配额计算器)。
17.3 Token 成本、GPU 利用率、SLA
17.3.1 Token 成本模型
LLM 的成本是「按 token 计费」的(第 5 章埋的线)。成本公式三部分:
- 输入 token(Prompt 组装、RAG 检索结果都算,且通常比用户问题大得多——系统提示几百、检索文档几千);
- 输出 token(生成长度);
- 固定成本(GPU 租金、冷启动)。
降本三板斧(贯穿第 5、15、17 章的 Token 成本主题):
- 减输入:精简系统提示、压缩对话历史(摘要旧轮次)、RAG 只取最相关块(第 15 章路由 + 第 17.4 RAG 优化);
- 减输出:控制 max_tokens、结构化输出压缩(第 17.6);
- 选模型:简单任务路由到小模型/便宜模型(第 15 章)。
17.3.2 GPU 利用率与「有效吞吐」
LLM 服务的 GPU 利用率常被误读:GPU 利用率高 ≠ 有效利用——生成的全是垃圾 token(幻觉、冗余)也是 100% 利用率。正确指标是有效吞吐(第 14 章):每秒产出「用户真正要的 token」。优化方向:质量(少生成废话)+ 效率(多复用)。
17.3.3 SLA 度量
LLM 的 SLA 指标(第 21 章会进监控体系):
- TTFT(Time to First Token):首 token 延迟——用户体验的第一印象,受 Prefill + 排队影响;
- TPOT(Time Per Output Token):每 token 延迟——受 Decode 带宽影响;
- TBT(Time Between Tokens):流式输出的 token 间隔(体验连续性);
- 吞吐:tokens/s、requests/s。
SLA 预算的分配原则:TTFT 与 TPOT 由不同因素决定,要分别设 SLO 并分别扩容(第 21 章错误预算展开)。
17.4 RAG 服务
RAG 服务的完整链路(第 6 章讲了语料,这里讲服务化):
%%{init: {"themeVariables": {"primaryTextColor": "#000000", "textColor": "#000000", "labelColor": "#000000", "nodeTextColor": "#000000", "labelTextColor": "#000000", "scaleLabelColor": "#000000"}}}%%
flowchart LR
A[Query] --> B[Query 改写
HyDE/多查询]
B --> C[向量检索
embedding + 向量库]
C --> D[重排序
reranker 精排]
D --> E[上下文组装
块选择+截断]
E --> F[LLM 生成]
F --> G[引用溯源]RAG 服务化的三个关键决策:
- 检索增强:Query 改写(把口语问题变检索友好)、HyDE(先让模型生成假设答案再检索)、多路召回(向量 + 关键词 BM25 混合)——提升召回(第 9 章分层评估的「检索层」);
- 重排序:向量召回 top-50 后,用 cross-encoder 重排取 top-5——召回看效率、重排看精度,这是 RAG 精度的大头优化;
- 上下文组装:块数、长度、顺序、去重、以及与用户问题的相关性截断——决定 token 成本与忠实度(第 9 章)。
RAG 服务化的指标监控(第 9 章分层评估 → 第 22 章落地):检索命中率、rerank 增益、忠实度、引用正确率——每个环节都能单独出指标。
17.5 Agent 服务与工具调用
Agent 服务(第 26 章是案例,这里给工程框架)在 RAG 之上再加「工具与循环」:
%%{init: {"themeVariables": {"primaryTextColor": "#000000", "textColor": "#000000", "labelColor": "#000000", "nodeTextColor": "#000000", "labelTextColor": "#000000", "scaleLabelColor": "#000000"}}}%%
flowchart LR
A[用户请求] --> B[Agent 编排
规划/记忆/反思]
B --> C{需要工具?}
C -->|是| D[函数调用
解析参数]
D --> E[执行工具
API/检索/代码]
E --> F[观察结果]
F --> B
C -->|否| G[直接生成回答]工具调用的工程要点:
- 函数调用(Function Calling):模型输出结构化「工具调用」(工具名 + 参数 JSON),由运行时校验并执行。可靠实现靠第 17.6 的结构化输出约束;
- 工具注册表:工具的描述、参数 Schema、权限、调用频率限制——工具是「可执行的外部面」,权限与安全(第 23 章)在这层做;
- 循环控制:最大迭代数、超时、死循环检测、上下文预算(每轮的工具结果都进上下文,token 成本随轮数线性涨——Agent 的 token 成本是 RAG 的几倍);
- 可靠性:工具失败要能重试/降级/告知用户,不能把异常吞成「幻觉」。
17.6 流式输出、函数调用、结构化输出
三个「输出侧」能力,是 LLM 产品化必须的:
流式输出(Streaming):第 15 章讲过 SSE。服务侧的要点:流式与连续批处理要协同(引擎边生成边吐 token);中断(用户停止生成)要能立即回收 KV 与算力;流式日志与成本统计要按「流结束」结算。
结构化输出(Structured Output):让模型输出符合 JSON Schema,程序化消费。两条路线:
| 路线 | 做法 | 可靠性 |
|---|---|---|
| 提示 + 解析重试 | Prompt 要求 JSON,解析失败重试 | 中(大模型也会乱) |
| 约束解码 | 解码时按 Schema 约束(vLLM guided、Outlines、JSON mode) | 高(语法保证) |
约束解码的原理:把 JSON Schema 编译成有限状态机,解码每个 token 时只允许「能继续满足 Schema」的候选。生产级必须用约束解码——它同时保证「格式合法」和「不用浪费重试的 token」。
函数调用(Function Calling):可以看作结构化输出的特例(输出「调用哪个工具 + 参数」的固定结构)。OpenAI 的 tools API、各大模型的 tool-use 训练,本质都是让模型学会「在需要时输出工具调用结构」。
# vLLM 的 guided decoding 示例:强制输出合法 JSON
from vllm import SamplingParams
json_schema = '{"type": "object", "properties": {"answer": {"type": "string"}, "confidence": {"type": "number"}}}'
params = SamplingParams(guided_json=json_schema)
# 输出必然是合法 JSON,格式零失败本章要点回顾
- LLM 服务链路:网关 → 编排 → 引擎 → 流式;瓶颈在上下文组装与 KV 管理。
- 多租户隔离的边界是 KV 显存;配额核心 = 并发 × 上下文上限;P0 租户用优先级队列。
- 成本公式三部分;降本三板斧:减输入(压缩上下文)、减输出(限长/结构化)、选模型(路由)。
- GPU 利用率高 ≠ 有效利用;看有效吞吐。
- SLA 分 TTFT(Prefill+排队)与 TPOT(Decode),分别设 SLO。
- RAG 服务 = 改写 + 多路召回 + 重排 + 组装;重排是精度大头。
- Agent 服务 = 编排 + 工具调用 + 循环控制;token 成本随轮数线性涨。
- 结构化输出必须用约束解码(语法保证 + 省重试 token)。
习题
- 一个 RAG 客服请求:系统提示 300 token + 检索 5 块×800 token + 历史 2000 token + 问题 50 token。输入成本是多少?给出三条减输入手段与预估收益。
- 设计多租户 KV 配额:平台有 3 个租户,集群 8×80GB,如何分配并发与上下文上限?写出配额表。
- 为什么 Agent 的 token 成本是 RAG 的几倍?画出一次 5 轮工具调用的 token 消耗分解。
- 约束解码相比「提示 + 重试」除了格式保证,还能省多少 token?估算。
- 你的 TTFT 超 SLO 但 TPOT 正常,优先扩哪个环节?为什么?
延伸阅读
- vLLM 官方文档(连续批处理、guided decoding、prefix caching)
- OpenAI Function Calling 文档
- Lewis et al., Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks, 2020
- Reimers & Gurevych, Sentence-BERT(重排序生态)
- 各模型技术报告的 Serving 部分(DeepSeek、Qwen、Llama)
下一章预告
第 6 篇「部署与发布」:第 18 章部署基础(云/边/端/混合、K8s/Helm/Operator、GPU 调度/MIG/Serverless、模型格式),第 19 章模型版本与发布工程(注册表/CI-CD-CT/环境隔离/回滚审计),第 20 章分布式部署(多副本多区域、分布式推理、服务网格、联邦推理)。