
int8 量化上线后精度掉了你分不清是 weight 的锅还是 KV cache 的锅。打开 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_content 注册并创建一把 API Key把 Codex 的 Base URL 填成 https://taotoken.net/api剩下的事只有一件把你的量化配置、原始文章里 attention/MLP 与 KV cache 读写那几段描述一起丢给 Codex 做对照让它输出一份「掉点来自哪一路」的归因清单。这件事很容易被带偏。很多人一看到掉点就先回退 weight 量化结果显存立刻涨回去问题还在也有人先把 KV cache 切回 fp16长序列确实稳了但承载能力又回到原点。那篇讲推理性能优化的原文把量化拆成五条路线Weight-int8 加 KV_cache_int8、Activation int8、W4 加 KV4、通信 int8、Attention QKV int8其中只有第一条同时动了 weight 和 KV cache 这两块显存大头。要排查精度损失就得先把这两块分开开关而不是整体回退。下面这套流程是把「读代码和读配置」交给 Codex把「跑实验和看日志」留在你自己的机器上。1. W8 加 KV8 一开就掉点先在 attention/MLP 流程里分清谁动了1.1 weight 和 KV cache 是两笔不同的显存账原文里那张计算流程图说得很清楚模型前向会经过attention和MLP两个阶段其中 attention 会读写 KV cacheMLP 不碰它。这句话就是排障的分界线。weight 量化是离线做的量化的是模型参数本身。它的误差与你喂进去的输入无关一句「你好」和一段 8k 的长文受到的影响是同一量级的。也就是说如果 weight 那一路校准得不好短输入也会掉点。KV cache 量化是在线做的量化的是每层 attention 在 decode 阶段反复读写的那个缓存。它的误差会随着序列长度、随着 decode 步数不断累积短输入几乎看不出来越长越明显多轮会话叠加 session cache 之后更明显。这就是为什么很多团队上线后第一反馈是「短问答没问题长文档摘要开始胡说」。不是模型突然变笨是误差跟着序列长度走了一条不同的增长曲线。把这两条曲线分开排障就成功了一半。1.2 三种掉点「指纹」先对号入座在你还没开始配工具之前先拿手头已有的评测结果做个粗略分类这能省掉一半瞎试的时间短输入就掉、长输入掉得一样多优先怀疑 weight int8 的离线校准集与实际业务分布不一致或者某些层尤其是 embedding 附近和最后一层不适合 int8。短输入正常、4k 以上开始糊优先怀疑 KV cache int8。原文里 KV cache 是「显存大头」之一量化收益大但误差随步数累积天然是长序列敏感项。单轮无感、多轮越聊越崩同样偏 KV cache而且要考虑原文提到的 session cache 策略——缓存下来的历史 KV 如果本身是 int8 的误差会跨轮次继承。batch 一大就漂要看是不是叠加了激活量化动态范围大的那几层会被放大。提示这三条只是分诊不是确诊。下一步要把描述和配置交给 Codex 做逐条对照目的是把「我猜」变成「我有判据」。2. 把 Codex 接到 https://taotoken.net/apiconfig.toml 里只要四行2.1 ~/.codex/config.toml 写清楚 provider 和 base_urlCodex 用的是自己的 TOML 配置别把 Claude Code 那套ANTHROPIC_*环境变量套过来两者不通用。你要改的是~/.codex/config.toml# ~/.codex/config.toml model YOUR_MODEL_ID model_provider taotoken [model_providers.taotoken] name TaoToken base_url https://taotoken.net/api env_key TAOTOKEN_API_KEY wire_api chat三个点必须对齐base_url填https://taotoken.net/api末尾不要加/v1env_key写的是环境变量的名字不是 Key 本身model里的模型 ID 以官网模型广场当时列表为准不要凭记忆写带日期后缀的字符串写错了会直接报模型不存在。2.2 Key 从落地页创建环境变量 export 一次打开 TaoToken注册登录后在控制台创建 API Key然后在 shell 里导出名字要和配置里的env_key一致export TAOTOKEN_API_KEYYOUR_API_KEYYOUR_API_KEY是占位符实际值只在你本地环境变量里出现别写进 config.toml更别提交进仓库。如果你同时在这台机器上用 Claude Code两套配置互不影响各走各的文件。2.3 先发一条空请求确认通道通了再说别的配置改完不要直接上量化实验先做一次最小验证启动 Codex问一句和量化无关的话比如让它复述一个简单函数的签名。能正常回复说明 Key、Base URL、模型 ID 三件套是对的如果这一步就报错后面的归因全是噪音。这一步跑通的意义在于之后所有异常都能被归到「量化本身」而不是「通道没接好」。排障最怕两种问题混在一起。3. 让 Codex 做归因而不是替你跑实验3.1 一份可以直接抄的 prompt 模板把原文里 attention/MLP 计算流程、KV cache 读写、以及 W8 加 KV8 那几段描述连同你自己的量化配置哪一路开了 int8、校准集大概什么分布、有没有开 session cache一起贴给 Codex。用这个模板以下是某推理框架的量化说明片段含 attention/MLP 计算流程、KV cache 读写、W8KV8 配置 以及我当前的量化配置。 不要执行任何命令不要访问网络不要假设你能连到我的机器。 请只做四件事 1. 按我的配置把显存与计算开销分别归到 weight 和 KV cache 两类列出各自影响的输入范围 2. 列出「掉点主要来自 weight」与「掉点主要来自 KV cache」各自的可观测差异 3. 输出一份归因清单每行包含假设 / 需要的观测量 / 判据 / 什么结果会推翻它 4. 给出我需要在本地跑的最小对照实验矩阵只给命令和要看的指标由我自己执行。重点在最后一句「由我自己执行」。Codex 在这条链路里负责的是读文档、读配置、给判据它不会也不该替你运行推理服务、改 GPU 参数或连你任何一台机器。3.2 归因清单怎么读才有用Codex 返回的清单通常会有六七行假设别急着全试。先看「需要的观测量」这一列——凡是要求你跑长序列或多轮会话才能拿到的指标对应的假设基本都指向 KV cache凡是短序列就能复现的基本指向 weight。再看「什么结果会推翻它」这一列。这一列写不出反例的假设直接删掉它只会浪费你一天的实验机时。原文里强调 KV cache 之所以在 attention 阶段被读写是因为它要在 decode 的每一步被反复取用所以一个合格的判据应该能区分「误差一次性引入」和「误差随步数累积」这两种模式而不是笼统地说「掉点了」。最后提醒一句Codex 给的是假设清单不是结论。它没有你的日志也不该有你的生产数据。4. 三组对照实验weight_int8 与 KV_cache_int8 分开开关4.1 实验矩阵一次只动一个变量按下面这个矩阵做四组就能定位到方向。每组只改一个开关其他全部固定实验组weightKV cache主要观察结果倾向A 基线fp16fp16短序列与长序列指标作为对照基准B 只动 weightint8fp16短序列是否已掉掉了就是 weight 嫌疑C 只动 KVfp16int84k 以上是否开始掉掉了就是 KV 嫌疑D 双开int8int8是否比 B、C 更差判断是否误差叠加如果 A 与 B 在短序列上几乎无差而 C 在 4k 之后明显劣化那答案就很清楚了显存收益主要该从 KV cache 那一路继续拿weight 那一路别乱动。反过来如果 B 在短句上就已经不准你该回去查校准集而不是去调 KV cache。注意原文中提到的成本下降、首 token 耗时下降这些数字是整条链路量化、投机采样、chunk prefill、通信 overlap 等叠加后的结果不能拿来当作「int8 精度没问题」的证明。精度必须用你自己的评测集重新测。4.2 观测指标要分家别把 TTFT 混进精度判断原文把TTFT首 token 响应时间和TPOT每个输出 token 的时间单独列成一节其中一个重要原因是这两者是体验指标不是精度指标。Activation int8 的收益主要落在 GEMM 运算耗时上表现为首 token 更快PD 分离、chunk prefill、通信 overlap 的收益落在 decode 间隔上。这些优化跑通之后你不该因为它们快了就认为量化精度也更好了。测精度得用固定评测集、固定解码参数尤其是温度别乱调分别记录短序列和长序列的表现。多轮一致性可以用一个笨办法同一段上下文问三次同样的问题看三次答案是否漂移。weight 出问题时漂移通常在第一次就出现KV cache 出问题时漂移往往从第三轮开始积累。4.3 误差叠加时别一次改两处D 组如果明显比 B、C 都差说明两路的误差在叠加这时不要急着把两路一起降级。正确顺序是先把明显更差的那一路单独回退重测确认余下的劣化能不能被业务接受再决定另一路要不要动。一次改两处你永远不知道是哪一处起了作用。5. Activation int8 与 W4/KV4 的掉点长得不一样5.1 A8 的误差走的是激活路径原文里 Activation int8 被描述为在 W8 与 KV8 的基础上对 GEMM 相关计算的输入激活做量化。注意这个位置——它动的是计算输入不是权重本身也不是缓存。所以 A8 的掉点特征和前两路都不同它更依赖当前输入的数值分布。一段数值范围特别夸张的输入例如某些异常长的重复片段、某些特殊符号密集的文本可能让激活的动态范围放大量化误差跟着放大。排查方式是构造几段极端输入看是否是特定输入触发的偶发掉点而不是全量均匀劣化。顺带说一句原文中 Attention QKV int8 那条路线写的是Q(int8)*K(int8)-softmax(fp32)-V(int8)中间那一步 softmax 保留 fp32 是个关键信号误差会在 QK 点积里累积然后在 softmax 之前被截断成 fp32。如果你的掉点特征集中在 attention 相关的长程依赖上可以顺着这条线去核对。5.2 W4 加 KV4 是另一档风险别混着改原文把 Weight-int4 加 KV_cache-int4 单独列为一条路线目标是把显存压到更低。从 fp16 到 int8 是一档风险从 int8 到 int4 是另一档两者不该在一次实验里同时发生。如果你的现状是「W8 加 KV8 已经掉点了」此时把任意一路改成 int4 只会让归因更困难。先把 int8 这一档的账算清楚再考虑要不要往下压。5.3 通信 int8 基本不影响生成质量原文里 Communication int8 是通信量化收益在首 token 耗时上它不改变参与计算的数值本身。也就是说如果你在排查精度通信这一路可以暂时从怀疑名单里划掉除非你把通信侧的溢出处理写错了。把怀疑范围收窄这件事本身就值半天时间。6. Codex 侧的报错对照401、模型名、base_url 后缀6.1 三步验证时最常见的三个错现象常见原因处理401 / 未授权TAOTOKEN_API_KEY没导出或 shell 重启后丢了重新export确认变量名与env_key一致模型不存在model写了记忆里的字符串以官网模型广场当时列表为准复制粘贴路径重复 / 404base_url末尾多写了/v1改成https://taotoken.net/api这三个错的共同点是它们和量化没有任何关系但会让你误判成「int8 把模型弄坏了」。所以第 2 章那一步空请求验证不能省。6.2 边界Codex 只生成与解释执行交给本地再强调一次这条边界。Codex 可以帮你做的读懂原文里 attention/MLP 与 KV cache 的描述、比对你的量化配置、生成对照实验用的脚本骨架、解释报错日志的含义、把归因清单整理成表格。它不该做的直接连上你的推理服务或机器去改配置、替你执行量化脚本、替你跑 benchmark。所有命令都由你在本地终端执行执行结果和报错原文再贴回对话里。这不是流程繁琐而是保证你的实验环境可控、可复现。按这个分工走一轮你会得到一份有判据的归因结论而不是一堆「试过好像好了点」的模糊印象。7. 对照实验跑完回控制台对一次账配好的通道跑起来之后建议先在 TaoToken 模型对话 里用同一把 Key 发一条测试消息确认模型 ID 和 Base URL 都没写错再回到 Codex 里跑归因那几轮对话。这样你能分清「是配置问题还是量化问题」。后面如果你打算把短序列、长序列、多轮这三类评测各跑几遍调用量会比平时调试高不少可以先在 Coding Plan 看一下套餐是否够用Key 统一在 控制台 API Keys 创建和管理。回到量化本身如果最终确认掉点主要来自 KV cache就把那一路单独回退接受一部分显存上涨换回长序列的稳定性如果主要来自 weight回去重做校准集别在推理侧继续加补丁。这个判断做完比多试十组参数都值钱。