Repository Reading Site
本轮操作记录:大模型推理与服务发布概念文撰写
这一轮继续沿着第 18、19、20 课的大模型主线推进,把“训练产物之后到底如何变成线上服务”这一段讲清楚。 目标有四个: 1. 把 prefill、decode、KV cache、TTFT、ITL、吞吐这些运行时概念讲透。 2. 把 runtime package、engine config、serving deployment、service versi
本轮操作记录:大模型推理与服务发布概念文撰写
本轮目标
这一轮继续沿着第 18、19、20 课的大模型主线推进,把“训练产物之后到底如何变成线上服务”这一段讲清楚。
目标有四个:
- 把 prefill、decode、KV cache、TTFT、ITL、吞吐这些运行时概念讲透。
- 把 runtime package、engine config、serving deployment、service version 的工程边界讲透。
- 补一组可直接查看的推理与发布样例,帮助读者建立线上服务的磁盘直觉。
- 继续保持“课程正文 + 操作记录 + 示例资产”的教学结构。
Step 1:先回看第 20 课的结尾,确认第 21 课应该接哪一段
实际命令
tail -n 120 /Users/yuanjun/coding/github/k8s-lab/20-第二十课-大模型训练-SFT-LoRA-Checkpoint-Adapter与模型产物原理.md
为什么先做这一步
因为第 20 课最后已经明确收束到了:
- checkpoint
- adapter
- merged model
- runtime package
- model registry
所以第 21 课不应该重新从“什么是模型”讲起,而应该直接接着回答:
runtime package 之后,到底怎样进入线上推理服务?
这一步得到的结论
第 21 课最自然的边界就是:
- 大模型推理原理
- 量化
- KV cache
- vLLM
- 吞吐与延迟
- 部署和发布链路
这和前一课衔接最顺。
Step 2:检查仓库里现有的 ml-platform 上下文,避免新课脱离仓库实际
实际命令
find /Users/yuanjun/coding/github/k8s-lab/ml-platform -maxdepth 3 -type f | sort | sed -n '1,260p'
sed -n '1,260p' /Users/yuanjun/coding/github/k8s-lab/ml-platform/inference/main.go
sed -n '1,260p' /Users/yuanjun/coding/github/k8s-lab/ml-platform/docs/ml-pipeline.md
为什么要查这一步
虽然这一轮的重点是大模型推理概念,但我还是要确认仓库里的现有推理内容是什么。
原因是:
- 如果仓库已经有大模型推理实现,那我应该直接续写它
- 如果仓库现有推理实现还是传统 ML,那第 21 课就应该保持“概念 + 样例资产”的落盘方式,而不是硬改代码
这一步看到的结果
我确认到:
ml-platform/inference/main.go目前是传统线性回归模型的推理服务示例- 它重点在 Go 推理服务、健康检查、Prometheus 指标
- 还不是大模型推理引擎接入层
这一步的设计决策
因此我没有直接修改:
ml-platform/inference/main.go
原因不是不能改,而是当前课程主线处在:
- 概念分层
- 产物形态
- 服务边界
这个阶段。
如果现在直接把仓库硬拽进某个具体 vLLM 运行方式,反而会把“原理课”写成“框架接线课”。
所以这一轮继续采用:
- 正文解释原理
- examples 展示文件形态
这种更稳的结构。
Step 3:确定第 21 课真正要解决的问题,避免写成“推理名词表”
这一步我重点定义了什么
如果直接讲:
- vLLM 很快
- KV cache 很重要
- 量化能省显存
这种文章很容易沦为口号集合。
所以我先把第 21 课真正要解决的问题定义为:
- 推理请求在运行时到底经历了什么
- prefill 和 decode 为什么必须分开理解
- TTFT、ITL、吞吐各自在看什么
- KV cache 为什么既是加速关键,也是显存压力源
- vLLM 这类引擎到底在解决什么问题
- 量化压缩的是哪一层对象,代价是什么
- runtime package、engine config、deployment、rollout 为什么不能混
- 模型版本和服务版本为什么必须分开治理
原理解释
这一步本质上是在防止课程写成:
- 框架术语堆叠
- 参数配置手册
- “业内黑话”罗列
而是强行把主线拉回到:
- 原理
- 边界
- 工程治理
Step 4:决定不仅写正文,还要新增 ml-platform/examples/21-llm-serving
为什么不能只写文字
因为“线上推理服务”这件事如果只有概念,小白还是会继续混淆:
- runtime package 到底长什么样
- service config 和 deployment 有什么区别
- 发布单是模型版本的一部分吗
- 量化计划是训练文件还是上线文件
这些问题,不把它们拆成磁盘上的不同文件,很难真正讲透。
我新增的位置
为什么放这里
原因和第 19、20 课一致:
- 这是学习样例资产,天然属于
ml-platform/examples - 不污染根目录课程主线
- 后续如果继续写大模型评测、网关、安全策略和多模型路由,也可以继续沿这个目录扩展
Step 5:设计样例目录时,我没有只放一个 deployment,而是按“服务生命周期”拆了 9 类文件
我新增的样例文件
00-inference-service-config.yaml01-openai-chat-completions-request.json02-prefill-decode-timeline.txt03-kv-cache-layout.txt04-quantization-plan.yaml05-model-release.yaml06-serving-deployment.yaml07-runtime-metrics.txt08-canary-rollout.yaml
为什么这样拆
我故意让每个文件只承担一层职责:
00-inference-service-config.yaml
强调:
- runtime package 如何被推理引擎使用
- 引擎参数、KV cache、观测配置属于服务层
01-openai-chat-completions-request.json
强调:
- 线上调用长什么样
- prompt 是如何以消息格式进入服务的
02-prefill-decode-timeline.txt
强调:
- 一条请求在时间线上会经历哪些阶段
- TTFT 和 ITL 不是同一个东西
03-kv-cache-layout.txt
强调:
- 序列逻辑顺序和缓存物理布局可以分离
- 帮助读者理解 block / page 的工程直觉
04-quantization-plan.yaml
强调:
- 量化是一个发布决策过程
- 不是单独一个“模型文件格式”选择
05-model-release.yaml
强调:
- model version 和 service release 是两层对象
- 发布单会引用 runtime package 和 deployment
06-serving-deployment.yaml
强调:
- K8s 关心的是副本、GPU、探针、挂载和 Service
- 这层已经不是训练产物目录了
07-runtime-metrics.txt
强调:
- 线上必须同时看体验层、引擎层和 GPU 层指标
08-canary-rollout.yaml
强调:
- 金丝雀发布看的不是“权重文件对不对”
- 而是服务表现是否过关
原理解释
这一步本质上是在把“一个上线模型”拆成一组不同职责的工程对象。
只有这样,读者才不容易把:
- 模型
- 服务
- 发布
继续混成一个词。
Step 6:编写第 21 课正文时,我刻意把 prefill / decode 放到最前面
为什么不是先讲 vLLM
因为如果先讲 vLLM,读者很容易记住:
- continuous batching
- PagedAttention
- OpenAI-compatible API
但并不知道这些东西到底在优化什么。
所以我先讲:
- 推理请求链路
- prefill
- decode
- TTFT
- ITL
- 吞吐冲突
然后再引出:
- KV cache
- PagedAttention
- vLLM
- 量化
这样安排的好处
这样读者会先建立“问题是什么”,再理解“工具为什么存在”。
这比先讲框架名词,更符合架构师训练路径。
Step 7:我刻意把“KV cache 是加速关键”和“KV cache 是容量压力源”分成两章
为什么这样写
很多文章只会说:
KV cache 可以避免重复计算,所以很重要。
这句话没错,但只说了一半。
如果不继续强调:
- 它会占显存
- 它和上下文长度、并发数一起增长
- 它会反过来限制 batch 和吞吐
读者就很容易形成一个错误印象:
KV cache 只是纯收益优化。
这当然不对。
原理解释
真实工程里,很多容量瓶颈不是“权重装不下”,而是:
- 权重装得下
- 但真实流量下 KV cache 顶不住
所以我在正文里故意把这两件事拆开讲,帮助读者建立更真实的系统直觉。
Step 8:量化部分,我没有把重点放在“某个算法名字”,而是放在“压的是哪层对象”
为什么这么处理
如果直接展开讲:
- GPTQ
- AWQ
- SmoothQuant
- FP8
课程会迅速变成量化算法百科。
但这一课真正要解决的问题不是“背算法名”,而是让读者先分清:
- 是权重量化
- 还是激活量化
- 还是 KV cache 量化
- 是离线产物变化
- 还是运行时兼容性变化
原理解释
对工程决策来说,最重要的第一步不是记住算法名字,而是先知道:
我到底在压缩哪个对象,换来什么收益,又承担什么代价。
所以量化样例文件 04-quantization-plan.yaml 也故意写成:
- 目标
- 候选方案
- 约束条件
- 决策结果
而不是只放一个格式名。
Step 9:服务版本和模型版本的边界,我用单独的发布单来强调
为什么需要 05-model-release.yaml
因为上一课已经有了:
05-model-registry/model-version.yaml
它解决的是:
- 训练血缘
- 模型资产登记
- 审批状态
但这一课还必须再往前一步,让读者看到:
线上放量时,治理对象已经不是单纯的 model version,而是 service release。
所以我新增了:
05-model-release.yaml
这个文件刻意同时引用:
- model version
- runtime package
- engine config
- deployment
- rollback target
目的就是把“服务版本”从“模型版本”里强行拆出来。
Step 10:我没有修改任何真实集群资源,这一轮依然属于“概念 + 产物形态 + 工程边界”阶段
为什么不直接补真实 LLM 部署 manifests
因为仓库当前并没有现成的大模型 GPU 运行环境、镜像仓库、PVC 和 CRD 体系来承接真实部署。
如果我现在硬做“可直接 apply 的真实部署文件”,大概率会出现两类问题:
- 文件看起来很完整,但其实和当前仓库上下文脱节
- 读者把注意力转移到具体镜像和命令,而忽略这一课最核心的分层
这一步的设计决策
所以这轮只做:
- 课程正文
- 操作记录
- examples 样例资产
不做:
- 真实集群资源变更
- 现有推理代码重构
- 真实 GPU 发布链路接线
这符合当前课程节奏。
Step 11:创建文件时继续使用 apply_patch,保证改动精确、可审计
本轮编辑方式
本轮新增文件全部通过 apply_patch 完成,而不是直接用重定向覆盖文件。
为什么这样做
原因和上一轮一致:
- 变更粒度清晰
- 不容易误覆盖已有文件
- 更符合仓库级协作和回看要求
原理解释
知识仓库、代码仓库和基础设施仓库,本质上都需要:
- 可审计
- 可对比
- 可回滚
编辑方式本身也是工程习惯的一部分。
Step 12:最后做落盘核对,确认第 21 课和样例目录都已写入仓库
实际命令
find /Users/yuanjun/coding/github/k8s-lab/ml-platform/examples/21-llm-serving -type f | sort
sed -n '1,260p' /Users/yuanjun/coding/github/k8s-lab/21-第二十一课-大模型推理-量化-KV-Cache-vLLM-吞吐延迟与部署发布链路原理.md
sed -n '1,220p' /Users/yuanjun/coding/github/k8s-lab/ml-platform/examples/21-llm-serving/README.md
命令原理解释
find path -type f | sort
- 用于确认目录里实际写入了哪些文件
sort让输出稳定,方便核对
再次用 sed -n 看正文和 README,是为了确认:
- 文件已经写入
- 标题、结构、链接没有明显错误
这一步的意义
对工程化工作来说,写完并不等于完成。
落盘校验的价值在于:
- 不是“我觉得已经写进去了”
- 而是“我确认它已经按预期存在”
本轮产出
课程正文
操作记录
推理与发布样例
这一轮最重要的学习收获
如果你只能带走一句话,我希望是这句:
大模型真正上线的对象,从来不是单独一个“训练好的权重文件”,而是一整套由 runtime package、引擎配置、服务部署、观测指标和发布策略共同组成的服务版本。
你一旦把这条链看清,后面无论是做:
- 推理平台
- GPU 容量规划
- 模型发布
- 线上延迟排障
脑子里都会有一套正确的分层,而不再只是“把模型跑起来”。