1. 为什么 DeepSeek V3.1 的推理链路值得单独拆一遍很多人第一次接触 DeepSeek V3.1会把它当成“又一个开源大模型”但真正跑过本地部署或者压过 API 并发的人会发现它的推理行为和早期 Dense Transformer 完全不是一回事。你如果拿以前调 Llama 2 那套经验去估显存、算首字延迟大概率会翻车。原因就在于 DeepSeek V3.1 在架构上做了三件互相咬合的事FFN 从 Dense 换成 MoE 稀疏激活、Attention 从 MHA 换成 MLA 压缩 KV、系统层把 Prefill 和 Decode 拆成两个独立子系统。这三件事单独看都不新鲜但叠在一起之后推理链路的瓶颈位置就变了。这篇面向的是已经在本地跑模型或者通过 API 调 DeepSeek V3.1 的开发者尤其是那种“模型能起来但不知道慢在哪”的场景。我会把 MoE 路由、MLA 注意力、Prefill/Decode 两阶段的耗时来源拆开讲然后给一份可复制的 config.toml 骨架配合 TaoToken 统一 Key 的配置示例最后用一组 Prefill/Decode 耗时对比动作帮你定位瓶颈到底在计算、在内存带宽、还是在调度。先给一个整体判断DeepSeek V3.1 的推理优化本质是“用计算换内存、用调度换吞吐”。MoE 用稀疏激活把每 token 的计算量压下来MLA 用潜在向量压缩把 KV Cache 的内存占用压下来Prefill/Decode 解耦则让两个资源画像完全不同的阶段各跑各的。你理解了这三条主线再看任何推理引擎的日志都不会懵。2. TaoToken 前置统一 Key 与接入准备在讲配置之前先把调用入口理清楚。不管你是本地部署还是走 API最终都要落到一个能发请求的 Key 上。TaoToken 在这里的角色是统一入口官网是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 端点是 https://taotoken.net/api 注意 API 地址不带 UTM 参数别拼错了。你需要先拿到 Key入口在 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite 。拿到之后本地部署场景下它用于对齐模型版本和推理引擎参数API 调用场景下它就是你请求头里的凭证。接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 里面有针对 DeepSeek V3.1 的模型标识和参数说明建议先扫一遍再动手。这里要强调一点TaoToken 不是让你跳过推理引擎它解决的是“多个模型、多个 Key、多个端点”的管理问题。你本地该装的 vLLM、SGLang 一个都不能少TaoToken 只是让你在切换模型和压测时不用反复改环境变量。3. 可复制配置config.toml 骨架与 MoE/MLA 参数下面这份 config.toml 骨架是我按 DeepSeek V3.1 的架构特点整理的覆盖了 MoE 路由、MLA 注意力、Prefill/Decode 分离三块关键参数。你可以直接拿去改但要注意每个参数背后的含义不然调错了反而更慢。[model] name deepseek-v3.1 dtype bf16 # 权重主精度FP8 量化版可改 fp8 num_hidden_layers 61 # 总层数前 3 层为 Dense MLP first_k_dense_replace 3 # 前 3 层不走 MoE走 Dense FFN [moe] num_experts 256 # 路由专家总数 num_shared_experts 1 # 共享专家所有 token 都过 top_k 8 # 每个 token 激活的路由专家数 moe_intermediate_size 2048 # 单专家中间维度 norm_topk_prob true # 对 top-k 权重做归一化 [attention] type mla # 多头潜在注意力 kv_lora_rank 512 # KV 压缩后的 latent 维度 q_lora_rank 1536 # Q 压缩维度 rope_theta 10000.0 max_position_embeddings 163840 [prefill] max_batch_tokens 8192 # 单批 prefill token 上限 chunked_prefill true # 分块 prefill降低首字延迟 schedule_policy fcfs # 先到先服务追求吞吐 [decode] max_num_seqs 256 # 并发序列数 block_size 64 # paged KV cache 块大小 schedule_policy low_latency [quant] weight_quant fp8 # 权重 FP8 activation_quant bf16 # 激活 BF16 kv_cache_dtype bf16 # KV Cache 保持 BF16几个关键点解释一下。first_k_dense_replace 3对应 DeepSeek V3.1 前 3 层用 Dense MLP 的设计目的是先给所有 token 打一个统一的高层表示再交给后面的 MoE 做细分。你如果把它改成 0全部走 MoE短 prompt 场景下质量可能反而下降。kv_lora_rank 512是 MLA 的核心它决定了 KV 压缩后的潜在向量维度这个值越小内存越省但解压时的计算开销越大512 是官方比较平衡的取值。block_size 64对应 FlashMLA 的 paged KV cachevLLM 和 SGLang 都支持这个粒度。TaoToken 的 Key 配置放在环境变量里不要写进 config.tomlexport TAOTOKEN_API_KEY你的Key export TAOTOKEN_BASE_URLhttps://taotoken.net/api如果你用的是 OpenAI 兼容客户端直接这样初始化from openai import OpenAI client OpenAI( api_key你的Key, base_urlhttps://taotoken.net/api ) resp client.chat.completions.create( modeldeepseek-v3.1, messages[{role: user, content: 解释一下 MLA 的 KV 压缩原理}], max_tokens256 ) print(resp.choices[0].message.content)4. 验证请求与 Prefill/Decode 耗时对比配置写完下一步是验证。我建议分两步走先确认请求能通再做 Prefill/Decode 的耗时对比。第一步发一个最小请求确认链路curl https://taotoken.net/api/v1/chat/completions \ -H Authorization: Bearer $TAOTOKEN_API_KEY \ -H Content-Type: application/json \ -d { model: deepseek-v3.1, messages: [{role: user, content: 你好}], max_tokens: 16 }返回里如果有choices和usage字段说明 Key 和端点都没问题。注意usage里的prompt_tokens和completion_tokens这两个数后面做耗时对比要用。第二步做 Prefill/Decode 耗时对比。核心思路是构造两个请求一个长 prompt 短输出一个短 prompt 长输出。长 prompt 短输出主要压 Prefill短 prompt 长输出主要压 Decode。import time from openai import OpenAI client OpenAI(api_key你的Key, base_urlhttps://taotoken.net/api) def measure(prompt, max_tokens): start time.time() resp client.chat.completions.create( modeldeepseek-v3.1, messages[{role: user, content: prompt}], max_tokensmax_tokens ) elapsed time.time() - start usage resp.usage return { elapsed: round(elapsed, 3), prompt_tokens: usage.prompt_tokens, completion_tokens: usage.completion_tokens, tps: round(usage.completion_tokens / elapsed, 2) } long_prompt 请阅读以下文本并总结 这是一段测试文本。 * 500 short_prompt 请写一段关于机器学习的介绍。 print(Prefill 压测:, measure(long_prompt, 32)) print(Decode 压测:, measure(short_prompt, 512))实测下来Prefill 压测的elapsed主要花在首字延迟上tps会偏低因为输出 token 少Decode 压测的elapsed主要花在逐 token 生成上tps更能反映解码吞吐。你把两组数据放一起看如果 Prefill 的 elapsed 远大于 Decode 的 elapsed 按 token 折算后的值说明瓶颈在 Prefill 的计算或调度反过来则瓶颈在 Decode 的内存带宽。这里有个细节DeepSeek V3.1 的 MLA 在 Decode 阶段会把 KV Cache 从几百 KB 压到 70 KB 左右降低约 6 倍。所以你如果看到 Decode 的 tps 比同规模 Dense 模型高不少这是正常的不是测错了。5. 本篇常见错排查第一个坑MoE 路由参数配错导致专家负载不均。如果你在本地部署时发现某些 GPU 利用率明显偏低检查num_experts和top_k是否和模型权重匹配。DeepSeek V3.1 是 256 专家选 8你如果写成 128 选 8路由会直接报错或者静默走错分支。第二个坑MLA 的kv_lora_rank和推理引擎不匹配。vLLM 和 SGLang 对 MLA 的支持版本不同老版本可能不支持kv_lora_rank参数会回退到 MHA这时候 KV Cache 内存会暴涨。排查方法是看启动日志里有没有Using MLA字样没有就是没生效。第三个坑Prefill/Decode 没解耦两个阶段抢资源。如果你用的是单实例部署Prefill 的长请求会把 Decode 的短请求堵住表现为首字延迟和 token 吞吐同时变差。解决办法是开chunked_prefill或者直接上双实例Prefill 一个、Decode 一个。第四个坑FP8 量化版和 BF16 版混用。权重是 FP8但kv_cache_dtype写成了 FP8某些推理引擎会在 Decode 阶段做额外的类型转换反而拖慢速度。建议 KV Cache 保持 BF16权重用 FP8。第五个坑TaoToken 的 base_url 拼错。API 地址是 https://taotoken.net/api 不要加 UTM 参数也不要漏掉/api。如果你用的是 OpenAI SDKbase_url 要写到/api这一层SDK 会自动补/v1/chat/completions。6. 继续深入模型对话与 Coding Plan如果你想把 DeepSeek V3.1 的推理链路验证得更细比如对比不同top_k下的 MoE 路由耗时或者测 MLA 在不同kv_lora_rank下的 Decode 吞吐可以直接在模型对话里做小规模实验入口在 https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentmodel_chatutm_campaignrewrite 。它适合快速验证参数改动对输出的影响不用每次都起本地实例。如果你是要把 DeepSeek V3.1 接进长期编码或者 Agent 工作流那重点就不在单次推理耗时而在并发调度和 Key 管理。Coding Plan 的入口在 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite 里面有针对代码补全和 Agent 调用的配额与并发说明。控制台在 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite 可以看实时的 token 消耗和请求分布。最后补一句实操经验调 DeepSeek V3.1 的推理参数时先固定top_k和kv_lora_rank只动max_batch_tokens和max_num_seqs这样你能清楚看到 Prefill 和 Decode 各自的瓶颈怎么随并发变化。等这两个稳定了再去动 MoE 和 MLA 的压缩参数不然变量太多根本定位不到问题。