
最近在帮一家制造企业做内部知识库问答平台的底层模型部署整个项目从模型选型到上线用了三周左右。最后落地的方案是 Qwen3.5-Plus核心推理模型用的是 Qwen3.5 LLM 系列里的 Qwen3.5-397B-A17B。这个案例比较有代表性业务方要求数据绝对不能出内网并发要求不低运维团队又没有专职的大模型工程师。今天把整个过程拆开来讲包括为什么选这个模型、显存怎么算、推理服务怎么调、有哪些坑必须避开。不管你是刚要评估私有化大模型还是已经在部署途中这份实操记录应该都能用上。1. 部署需求与方案选型为什么最终锁定 Qwen3.5-Plus1.1 项目背景与核心诉求先说背景。某制造企业要做企业知识库问答产线技术文档、维修手册、质量报告散落在多个系统。业务侧想做一个统一入口让一线工程师可以直接用自然语言问 SOP、查故障代码。数据安全要求很硬所有语料只能在内网流转不能碰外网 API。所以私有化部署是必选项不是可选项。业务侧还给了几个硬指标。高峰期大约同时 50 个人在用回答要能引用来源不能凭空编工艺参数。换句话说模型的“知识容量”和“检索跟随能力”比单条回答的华丽程度更重要。团队评估下来决定不再纠结更小的 7B/14B 模型直接看能支撑生产级效果的 MoE 大模型。另外团队里只有两三个后端工程师没有专职算法人员所以方案必须足够成熟、可维护不能搞成一次性实验。1.2 模型选型对比稠密模型、MoE 模型与 Qwen3.5-397B-A17B选型时我们列过几个方向。7B/14B 稠密模型部署成本低但在需要翻长文档、理解复杂故障树时幻觉率偏高经常找不到关键参数一句话里出现多个错误数字业务方很难接受。70B 级别稠密模型效果好一些可每一个 token 的前向计算量都很大在 50 并发下想扛住同样的吞吐需要堆更多卡成本并不便宜。方案部署成本单Token推理成本长文档能力结论7B/14B 稠密低低弱易丢细节不适合生产问答70B 稠密高高中上成本偏高Qwen3.5-397B-A17B中高低激活17B强本次选定最后我们把重点放在 MoE 架构上。Qwen3.5-397B-A17B 总参数量是 397B但每次推理只激活约 17B 参数。打个比方它像一个大型专家团队平时所有专家都在“备勤”真正接到一个问题时只叫相关领域的几个人上场。这样既保留了接近大参数模型的知识容量又把单 token 的推理成本压到了接近 17B 稠密模型的水平。我们还比对了同系列里的一些稠密版本。在代码理解、多轮工具调用、长文档抽取这几个内部测试集上Qwen3.5-397B-A17B 属于明显靠前的一档。企业场景里经常出现几百行日志、几十页技术规范的大上下文小模型会“看了后面忘前面”这个 MoE 模型在长文本上的表现能撑住我们的 RAG 方案。最终选它不是因为它参数最大而是在算力、效果、运维复杂度之间找到了平衡点。1.3 私有化部署与 API 调用的成本账为什么不上 API最直接的原因是数据合规。客户内部的工艺参数和故障代码属于核心生产信息明文发送到外部接口早就被安全团队否决了。从成本角度算API 模式适合调用量起伏不大、对延迟不敏感的场景而私有化部署是一次性算力投入加固定电费请求量越大边际成本越低。我们当时做了一个简单估算。假设高峰期每月调用 500 万 token 左右包括检索增强后的长输入和输出走外部 API 的月度费用是数千元起步再叠加网络延迟和数据出域风险长期看并不便宜。私有化部署要买加速卡、准备机房、养运维看起来门槛高但模型能力、数据权和响应延迟都握在自己手里。对于要把大模型当核心生产力工具的企业这笔账通常越算越划算。2. 硬件规划与环境准备把显存和算力算清楚再动手2.1 从参数量到显存需求一张表算明白部署大模型的第一步不是拉镜像而是算显存。Qwen3.5-397B-A17B 虽然激活参数只有 17B但权重是 397B 的完整集合GPU 显存必须装得下所有权重。这就是很多人忽略的“激活参数不等于总参数量”。权重显存很好算。BF16 格式下每个参数占 2 字节397B 参数大约是 794GB如果转成 FP8每个参数 1 字节大约 397GB。而 KV Cache 是另一笔大开销取决于层数、隐藏维度、batch 大小、上下文长度和缓存精度。一个常用的估算式是2 × 层数 × 每层KV维度 × 并发序列数 × 上下文长度 × 每元素字节数实际部署时可以用模型 config 里的参数代入。配置权重显存KV Cache预留总显存需求推荐卡数BF16权重~794GB~160GB~954GB12-16卡FP8权重~397GB~160GB~557GB8卡FP8短上下文~397GB~80GB~477GB8卡可用以我们最后的生产配置为例FP8 权重约 400GBKV Cache 预留 160GB 左右再加上临时激活值和框架缓冲整份模型在 8 张 80GB 显存的加速卡上基本占满 640GB。如果坚持 BF16 权重就需要双节点 16 卡。显存规划的核心结论是能用 FP8 尽量用 FP8把省下来的显存留给 Context比盲目上 BF16 要实用得多。2.2 算力集群规划与节点拓扑确定了“FP8 8卡”的大方向后选型时重点看三样东西单卡显存容量、显存带宽、卡间互联。当时评估的市场主流 80GB 级加速卡都有不错的显存带宽但真正影响 MoE 模型吞吐的往往是卡间通信。专家并行的 All-to-All 通信非常频繁节点内部如果走普通 PCIe多卡并行后通信会成为明显短板。比较保守的方案是单机 8 卡节点内使用厂商自带的高速互联避免跨节点做张量并行。如果后续业务上下文长度继续涨再考虑双节点 16 卡并配高速远程直接内存访问网络但那是后话。我们最终部署在单机 8 卡上主机配了 512GB 内存和 2 块 NVMe 固态盘。CPU 内存主要用来加载权重和做分片缓存512GB 能给运行留足余量。2.3 基础软件栈部署容器、驱动与内核参数环境部分不要做过多的手工编译否则后期升级会很痛苦。操作系统用的标准 Linux 发行版内核参数按 GPU 推理常见要求调整共享内存调大、打开文件数调大、内存映射数量限制调高。这些不调好模型一启动就可能莫名其妙报错。驱动和运行时我们直接用容器方案解决。Docker 加 GPU 容器运行时后宿主机只需要装好显卡驱动CUDA 和加速库都锁在镜像里。镜像统一维护团队可以用同一套镜像在测试环境、预发环境和生产环境之间流转版本可控。容器启动时记得给足共享内存PyTorch 的并行加载器非常依赖/dev/shm实测给 1GB 经常不够我们直接给到 32GB。3. 模型获取、格式转换与推理框架选型3.1 原始权重下载与完整性校验模型权重的体积不小FP8 版本也有接近 400GB下载环节很容易在最后发现文件损坏。我们内部定了一个土规矩先把所有权重的 SHA256 校验和拉下来单个大文件下载完立刻校验不合格就重下绝不让坏文件进入后续流程。仓库里的模型通常按分片存放单个分片从几 GB 到几十 GB 都有如果下载工具支持并发分片速度能快不少。实操上我最常用“先验证再并行”的流程先单独下载一个中等大小的分片跑通加载流程确认路径、权限、校验都正常再启动并发下载。不要一上来就开几十个线程全量拉免得中途报错找不到是哪一步出了问题。下载完成后把权重目录固定在一个纯路径下尽量不要用中文目录或带空格的路径很多推理框架对这类路径处理得很脆弱踩过一次坑就不想再踩第二次。3.2 格式转换Safetensors、FP8 与低比特量化怎么选从开源社区拿到的原始权重一般是 BF16 的 Safetensors 分片这种格式加载快、安全性好直接作为标准分发格式没有问题。可进入生产后通常需要把权重切成更省显存的版本。FP8 权重只有 BF16 的一半在当前主流加速卡上又有硬件级支持精度损失很小是企业部署的第一选择。如果显存资源更紧张还可以做 4bit AWQ 之类的低比特量化。但量化是有代价的。我们内部用一千条业务问答做过 AB 测试FP8 对比 BF16 在答案正确率上几乎没有差异而 4bit 量化在需要精确引用长文数字的场景下错误率明显上升了几个百分点。所以建议把低比特量化当成显存不够时的兜底方案而不是默认选项。量化校准集也要尽量贴近业务数据别用通用的新闻语料去校准一个制造知识库模型效果会偏。3.3 推理框架选型vLLM 与 SGLang 的取舍现在企业部署基本不会直接用原生加载权重的方式跑推理那样并发一高吞吐就崩。主流的两个开源推理框架是 vLLM 和 SGLang。vLLM 的 PagedAttention 解决了 KV Cache 碎片问题continuous batching 可以让多个请求交错生成尾延迟控制得不错生态也成熟。SGLang 的 RadixAttention 则在长上下文和复杂多轮对话的缓存复用上有优势当一个请求前缀被大量重复使用时效果特别明显。我们这次选 vLLM主要考虑生产生态。它和 Kubernetes、Prometheus 的集成资料多问题好搜社区迭代快。业务里大量请求会共用系统提示词和检索前缀vLLM 的 prefix caching 也够用。如果是做复杂 Agent 工作流频繁切换不同的 prompt 前缀SGLang 的缓存策略会更舒服。框架没有绝对的好匹配业务特征才重要。4. 推理服务部署与性能调优实录4.1 服务启动的核心参数与含义部署时我们用一个 Docker 镜像跑服务启动命令的核心参数大致长这样docker run --gpus all --shm-size32g \ -v /data/qwen3.5:/models \ -p 8000:8000 \ vllm-prod:latest \ --model /models/Qwen3.5-397B-A17B \ --tensor-parallel-size 8 \ --max-model-len 32768 \ --gpu-memory-utilization 0.87 \ --max-num-seqs 32 \ --dtype auto \ --quantization fp8 \ --enable-prefix-caching \ --trust-remote-code这里每个参数都不是随便填的。--tensor-parallel-size 8表示把模型切到 8 张卡上并行单卡显存放不下完整的 397B 权重必须切。--max-model-len 32768直接决定了 KV Cache 的上限开得越大显存占用越高我们按业务请求长度的 P99 来设不是越大越好。--gpu-memory-utilization 0.87是给框架分配显存的比例一开始填 0.95 看着很爽实际跑起来碎片一多就 OOM降到 0.87 反而稳定。--max-num-seqs 32是同时处理的序列数量。这个值调大能提高吞吐但超过一定限度后每个请求分到的 KV Cache 变少反而会阻塞所以最优值要靠压测找。--enable-prefix-caching会把相同前缀的 KV Cache 缓存下来对 RAG 场景非常划算。如果加载的是原始 BF16 权重把--quantization fp8去掉--dtype改成bfloat16即可。4.2 压测结果与调优记录服务起来以后我们先用一个内部脚本模拟真实问答请求并发从 10 慢慢加到 100记录三个核心指标首 token 延迟、单 token 生成时间、整体吞吐。初始配置跑出来的数据很有参考价值。并发 10 时首 token 延迟约 0.37 秒整体吞吐约 800 tokens/s并发 50 时首 token 延迟约 1.25 秒吞吐约 1400 tokens/s并发 100 时首 token 延迟已经涨到 3.8 秒吞吐只比 50 并发时高一点说明瓶颈出现了。顺着瓶颈做了两处调整。第一把--gpu-memory-utilization从 0.95 降到 0.87避免系统在 KV Cache 接近上限时频繁抖动。第二把--max-num-seqs从 64 降到 32表面上看并发处理能力变低了实际上一批请求不再互相争抢显存每个请求的 TTFT 反而更稳定。这是压测最能带来价值的地方不要只看单点最高吞吐要看生产水位下的延迟方差。4.3 生成质量与性能的平衡性能调完不能忘了质量。同样的模型解码参数不同业务结果可能天差地别。企业内部知识库问答不追求“文采”追求“可核对”。温度设置得比较保守top_p 也收窄长回答限制在 512 token 以内尽量让模型直接给出结论和引用来源而不是展开长篇论述。另外量化版本需要在业务集上复测。我们留下了一套固定的评测集每次调整量化方案或解码参数都会跑一遍。这也是为什么建议把模型版本和解码参数一起纳入版本管理不然性能优化和效果优化会互相牵制最后说不清是哪次改动导致回答变差。5. 高可用与运维体系企业级部署的另外一半5.1 多副本、负载均衡与优雅启停单节点推理服务再快也不是高可用。我们的做法是同一套模型权重启动至少两个推理实例前端用四层负载均衡做 TCP 转发避免七层网关额外解析开销。负载均衡只按连接数分发不感知请求内容配置简单也足够应付企业内网流量。更关键的是滚动重启。大模型推理实例启动很慢加载 400GB 权重需要好几分钟直接 kill 会造成服务闪断。我们要先在负载均衡中摘掉实例的流量等正在处理的请求跑完再触发优雅退出。在容器平台里可以配置一段缓冲时间保证新实例拉完权重、注册到负载均衡之后旧实例才完全下线。5.2 监控告警GPU、显存与请求延迟推理服务的监控和普通 Web 服务不一样。除了要看 GPU 利用率和显存使用率更要看 KV Cache 的占用率、当前排队请求数、TTFT 和 TPOT。我们用的 vLLM 自带 Prometheus 指标可以直接采集请求运行数和等待数、KV Cache 使用情况等数据再配合硬件厂商的 exporter 拿到算力层指标。告警规则我们设了三条都比较保守。显存使用率超过 95% 持续 5 分钟要告警因为随时可能 OOM等待队列超过 20 个请求要告警说明容量不足TTFT 的 P95 超过 3 秒要告警业务方对这个延迟非常敏感。日志统一打成 JSON每条请求带上唯一 request_id出问题可以直接把从负载均衡到推理框架再到最终响应的全链路日志串起来。5.3 模型更新与灰度发布大模型不是部署完就一劳永逸权重升级、量化方案调整、解码参数变更都需要灰度。我们给模型目录带上了版本号每次新版权重先放到灰度副本上负载均衡只放 5% 流量进去。用固定评测集对比新旧版本的回答质量跑半天没有明显劣化再逐步放量。如果新版本表现不好回滚也很直接把负载均衡里新版本的权重调回 0流量全部回到旧版本不需要重新部署整套服务。这个流程看着简单但很重要因为大模型行为不可穷举测试线上回滚能力就是最后的安全网。任何模型升级都别跳过灰度哪怕只是改一个解码参数。6. 常见问题与排查技巧实录6.1 显存不足和启动崩溃企业部署最常见的报错是 OOM。症状很简单服务起来没多久就退出日志里出现显存分配失败。不要急着加卡先查三个地方--max-model-len是不是设得太大--max-num-seqs是不是设得太高--gpu-memory-utilization是不是太高导致碎片。绝大多数 OOM 是这三个参数的组合问题而不是物理显存不够。现象常见原因处理方式启动即OOMmax-model-len过大按P99限长调低到业务真实水位运行中OOM并发峰值超过KV Cache预算降低max-num-seqs或扩容偶发OOM显存碎片化gpu-memory-utilization降到0.85-0.9我们的经验值是让 GPU 内存使用率保持在 0.85 到 0.9 之间留出一点弹性。如果业务必须支持 64K 上下文KV Cache 会陡然增加这时再考虑 KV Cache 量化或单独拆一个长文本服务而不是把生产实例的参数一起拉高。6.2 推理速度慢、响应卡顿排查请求一多就响应变慢先看等待队列长度。如果排队请求数一直在涨说明并发容量到顶了要么扩容要么调大max-num-seqs但后者可能引发显存不足。如果队列不长但 TTFT 很高问题多半出在 prefill 阶段尤其是 RAG 请求把大量检索内容拼进 prompt前缀很长首 token 计算量大。这时候前缀缓存的价值就体现出来了。把系统提示词、固定工具说明、知识库检索模板这些不变内容放在 prompt 前面开启 prefix caching 后大量重复计算会被跳过。我们还遇到过一种情况某个请求的输入特别长把整批请求都拖慢了因为 prefill 和 decode 混在一个批次里。后来在业务层面对超长输入做了限制和拆分问题明显缓解。6.3 长文本上下文与 KV Cache 爆炸长文本是显存杀手。同一份显存上下文长度从 8K 翻到 32KKV Cache 本身涨四倍各种临时激活值和调度开销也会同步上涨整体显存压力会明显放大。所以生产环境一定要按业务真实分布去设置max-model-len而不是照着一百多 K 的最大能力去配。我们的做法是统计一段时间内的请求长度画出分布曲线取 P99 作为上限。剩余极少数超长请求走离线任务或降级通道。这样既保证绝大多数请求体验正常又不会为了极少数大输入让所有人都承担显存成本。6.4 多机集群的网卡与拓扑踩坑最后说一个最容易忽视的坑跨节点并行。我们一开始评估过双机 16 卡跑 BF16 权重结果发现普通万兆网卡做张量并行根本扛不住节点间通信每生成一个 token 都要跨节点同步多次延迟增加非常明显。后来改成单机 8 卡 FP8速度反而快了一截。如果你不得不跨节点建议优先考虑流水线并行或专家并行而不是把同一层拆到两台机器上做张量并行。同一批 GPU 尽量保证在同一个高速互联域内。检查物理拓扑时用显卡驱动自带的拓扑信息看一眼加速卡之间的互联方式避免卡组里混着跨 PCIe 交换机的链路那对吞吐的影响比想象中更大。这次部署下来我最大的感受是MoE 大模型的企业级落地本质不是把模型跑起来而是把显存、带宽、并发和业务特征当成一个整体来设计。Qwen3.5-397B-A17B 给了很高的能力上限但真正决定生产体验的往往是max-model-len、max-num-seqs、gpu-memory-utilization这些不起眼的数字以及你为故障场景留了多少余量。建议准备做类似部署的朋友先把自己业务的请求长度分布、并发峰值和可接受延迟统计清楚再动手。别急着上 128K 上下文也别把 GPU 利用率压到 99%给系统留一点喘息的余地企业级系统才能真正站得住。