ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

8GB显存跑35B大模型:量化、卸载与本地Agent部署实战

2026/9/26 9:48:24 拓冰建站 浏览量
8GB显存跑35B大模型:量化、卸载与本地Agent部署实战 先交代一下实验条件省得大家以为我在瞎编一个跑分神话一台两年前的笔记本独显 8GB 显存NVIDIA 或 AMD 都行内存 32GB系统装的 Linux和 Windows 做了双启动。上面跑的是 Qwen3.6 35B 的 GGUF 量化版用一键安装包配好之后实测生成速度 42.3 token/s上下文能开到 128K图片丢进来能识别内容开启 Thinking 模式会先推理再作答最后还通过一个 OpenAI 兼容接口顺利接进了本地 Agent。这篇文章就把这套环境从原理到落地完整拆一遍。它适合两类人一是手头只有 8GB 显存老本、还想在本地跑大模型的二是想把本地模型接到 Agent / 工具调用工作流里的开发者。你不需要有数据中心级的硬件但需要理解一个问题为什么 35B 这种体量的模型能在一小块显存上跑出四十多的速度。这个为什么就是整套方案的真正价值。1. 8GB 显存跑 35B听着离谱但账能算平先说最让人怀疑的地方35B 的模型光是权重就二十多 GB8GB 显存连个零头都装不下。任何第一次听到这个组合的人都会先入为主地觉得不可能。实际上这里面的逻辑不是把 35B 装进 8GB而是让 35B 每跑一步只需要从显存里读一小部分。先说模型本身的体量问题。Qwen3.6 35B 这一档走了稀疏激活的架构路线也就是说 35B 是总参数量但每次生成一个 token实际参与计算的活跃参数远小于这个数。你可以把模型理解成一个大公司35B 是全体员工花名册但具体处理一条工单只需要抽调对应部门的几个人不需要全公司的人都停下来看这条工单。这种结构的典型表现就是 Mixture of Experts混合专家不同 token 路由到不同的专家子网络调用哪几个专家哪几个才算真正吃了算力。然后是量化。安装包里默认用的是 4-bit 量化后的 GGUF 格式权重从 FP16 的 2 字节压到每参数大约 0.55 字节。35B 全参数量化完大约 20GB 左右。所以关键点就来了这 20GB 的文件不是放在了 8GB 显存里而是放在了系统内存里GPU 只是以 1 到 N 层的粒度做分层卸载layer offload显存里能塞几层塞几层。这里有个很多人忽略的事实大模型生成时的速度瓶颈通常不是显存大小而是每生成一个 token要从内存里搬多少字节。显存只影响你能同时装下多大的权重和数据而生成速度由显存 系统内存的传输带宽 活跃参数量共同决定。8GB 显存的笔记本跑 35B 稀疏激活模型只要活跃参数量小、量化够狠、CPU 内存带宽够宽速度照样可以很好看。用一个生活化的类比你去图书馆查资料不需要把整个图书馆扛回家每次只需要借阅当前章节要用的那一本书。显存是你身上能背的包内存是图书馆的书架读写速度取决于图书馆管理员内存带宽递书的速度。只要管理员手速快你每次只要背出最新的一两本书整个图书馆照样能用起来。所以这套方案的三大支柱是稀疏激活架构活跃参数只有 3~4B 级别每次解码只读这部分权重4-bit 量化权重文件体积缩小约 3.6 倍系统内存完全能扛GPU CPU NPU 协同卸载显存装不下的部分交给内存和 NPU各干各的活理解了这三根柱子再看 42.3 token/s 就不会觉得是玄学了。2. 42.3 token/s 这个数字到底怎么来的2.1 一个简单的带宽公式解码速度理论上可以这样估算token/s 约等于内存传输带宽 ÷ 每 token 需要搬移的字节数。以这台笔记本为例DDR5 双通道内存带宽大约 80GB/s。如果活跃参数按 3.4B 算4-bit 量化后每参数占 0.55 字节那么每个 token 需要从内存搬约 1.9GB。80 除以 1.9大约是 42 token/s。测出来的 42.3 和这个理论值几乎贴在一起说明系统瓶颈确实在内存带宽而量化、卸载策略和显存分配都没拖后腿。这是很典型的算力有余、带宽为王的场景——GPU 计算单元大部分时间是在等参数从内存送过来而不是在忙着算。2.2 量化档位的取舍不是所有 GGUF 文件跑起来都一样快也不是越小的量化越好。安装包里提供三个档位实测结果如下量化档位文件体积约生成速度回复质量适用场景Q4_K_M20GB38~42 token/s较好损失很小默认推荐Q3_K_M17GB40~45 token/s略有损失复杂逻辑偶尔飘显存和内存都紧的时候Q5_K_M23GB34~38 token/s更接近原版内存 32GB 以上且追求质量我个人的建议是优先 Q4_K_M。Q3 在某些中文长难句和代码生成场景里会出现逻辑断层Q5 又会让内存带宽压力变大速度掉到 35 左右。中间档就是甜点位这也是安装包默认选它的原因。2.3 卸载策略和三路并行安装包启动时会用类似下面的参数把模型拆分到不同计算单元上llama-server \ --model qwen3.6-35b.Q4_K_M.gguf \ --n-gpu-layers 20 \ --threads 12 \ --ctx-size 32768 \ --n-gpu-layers 20 \ --no-mmap这里--n-gpu-layers控制多少层放 GPU20 层左右能把 8GB 显存吃到 85% 左右。剩下的层留在内存里由 CPU 计算同时 OpenCL / Vulkan 后端会把部分算子分流到核显或 NPU 上。三路并行不是说三块硬件同时算同一个 token而是不同模块各自承担一部分注意力计算可能在 GPUFFN 低层可能在 CPU视觉编码和 Token 嵌入可能走 NPU。提示这里的前后两个--n-gpu-layers是同一个参数命令行里写一次就行我写两遍只是为了强调它决定整个方案的成败。如果设得太高比如一次给 30 层显存立刻溢出服务直接崩溃设得太低GPU 闲置速度掉回 15 token/s。第一次调这个数字的时候我用了最笨的二分法先给 30 层看会不会崩崩了减半到 15稳定后在 15 到 30 之间每次加 3 层反复测直到显存占用达到 90% 又不会在生成过程中触发 OOM。这个值通常是 18~22 之间具体取决于你的显卡型号和 CUDA 驱动版本没有通用答案只有实测结果。3. 128K 上下文不爆显存的账本KV 缓存压缩与容量规划上下文从 2K 开到 128K显存的压力不只是权重更大的风险是 KV 缓存。所谓 KV 缓存就是模型在生成时把前面所有 token 的 Key 和 Value 向量缓存下来供后面每个 token 做注意力计算时查询。上下文越长缓存越大而且是线性增长的。以 35B 这档常见的 48 层、GQA 分组注意力为例做一个粗略估算每层有几个 KV 头每个头带一个 head_dim比如 128 维那么每个 token 对应的 KV 体积大概是层数 × KV 头数 × 头维度 × 2Key 和 Value。假设 KV 头数为 4每个 token 的 KV 原始大小在 48 层下约 49KB。128K 上下文全部以原始精度缓存那就是 6GB 以上。这个量级对 8GB 显存来说等于直接把剩余空间吃掉大半更别提模型权重还要占地方。安装包处理这个问题的思路是压缩 外置双管齐下KV 缓存量化默认把 KV 缓存压到 Q8每元素 1 字节体积减半以上如果极端情况还嫌不够可以降到 Q4但过长上下文中会有细微的质量损失。KV 缓存外置当上下文超出显存能容纳的 KV 总量时把缓存的一部分放到系统内存。代价是每个 token 生成时要多走一步内存交换速度会随着上下文长度慢慢下滑。所以你在 8K 上下文的短对话里能稳定跑 40 token/s但到了 100K 以上速度会掉到 20 以下。这是物理账不是 bug。上下文分段与滚动窗口如果只是做 128K 的长文档分析建议配合上下文滚动context shift把注意力范围限制在最近 N 个 token 内老内容隔一段距离就做压缩摘要。这样显存账本可以一直控制在安全水位。我的实测数据是这样的32K 上下文以内速度基本稳定在 40 上下64K 时大约 32 token/s真跑到 120K速度会降到 18 左右但内存占用 32GB 里还剩接近 10GB不会崩。也就是说128K 是能跑的不是跑得飞快的。你在做长文档任务时要有预期管理要么接受慢速要么配合滚动窗口做分段摘要。提示很多人在开 128K 上下文后发现速度慢第一反应是模型不行其实先看一眼--ctx-size和 KV 缓存量化档位。如果 KV 填充率常年不到 20%完全可以把 ctx-size 降到 16K 或 32K速度立刻回升。上下文长度不是一个越大越好的参数是按需分配的预算。4. 多模态输入与 Thinking 模式是怎么轻量化落地的4.1 多模态视觉编码器和图像 token 的开销多模态能力在这套方案里不等于把一个大视觉模型塞进笔记本而是借用了类似 CLIP 的视觉编码器做前置处理图片先被切成小块patch每个 patch 被编码成一个或多个视觉 token拼在文本 token 序列前面交给语言模型统一处理。视觉编码器本身只有几百 M 参数在 8GB 显存方案里可以很从容地放在显存也可以在图像输入时临时占用显存处理完就释放。真正吃显存的是图像 token 数量一张 336x336 的图通常产生 256 个视觉 token如果开了高分辨率切片tiling一张图可能膨胀到 1000 多个 token这些 token 会直接计入 KV 缓存挤占文本上下文的空间。所以安装包的默认配置里图像分辨率被限制在 512 以内并关闭了切片。实测下来图表、截图、文档照片识别都没有问题但如果你的使用场景是从超清卫星图里找细节那 8GB 方案确实力不从心建议在 Agent 侧把大图先做一次压缩预处理再喂给模型。4.2 Thinking 模式先想后答代价是 token 翻倍Thinking 模式其实就是让模型生成一个内部推理轨迹reasoning trace想清楚再给最终答案。开启后模型会先输出一段思维链再输出正式回复。好处是复杂逻辑、数学题、代码调试的正确率明显提升代价是同样的一个问题可能要消耗 3 到 10 倍的 token 才能给出答复。在 API 层面这个模式通常通过特殊的 chat template 开关或请求参数控制。我在实测中发现几条规律数学和逻辑题开启 Thinking正确率能从 55% 拉到 85% 以上日常闲聊、简单的工具调用关掉 Thinking延迟少一半长文档总结开着 Thinking 会让本来就不宽裕的上下文更快填满多数场景建议关闭接 Agent 的时候我一般把 Thinking 的开关做成动态的需要规划的任务比如先查数据库再决定调哪个接口自动开纯查询类的任务今天天气怎么样自动关。这比全局统一设置聪明得多。5. 一键安装包拆包它替你干了哪些脏活累活所谓一键安装不是变魔术而是把整个过程中最容易出错、最繁琐的操作全部收敛成了几个默认决策。下面把这个包实际做的事情拆开给你看哪怕你不用这个包照着流程手动走一遍也能复现。5.1 安装包做的事检测硬件识别 GPU 型号、显存大小、内存大小、CPU 核心数决定初始的--n-gpu-layers值和线程数安装推理后端自动下载 llama.cpp 预编译包按需选用 CUDA / Vulkan / OpenCL 后端拉取模型文件从国内可直连的模型镜像站下载 Qwen3.6 35B 的 Q4_K_M GGUF 文件校验 SHA256生成启动脚本根据第一步检测到的硬件参数生成start.sh或start.bat写入服务端口、API Key、KV 缓存量化方式等启动和自检拉起 llama-server然后自动请求一次/v1/models和一次最小生成请求确认模型加载成功、速度正常把测速结果打印在终端里配置 Agent 入口在本地启动一个兼容 OpenAI 格式的 127.0.0.1 服务端口并给出对接 Dify、FastGPT 或自研 Agent 框架的配置文件模板5.2 核心启动参数解读安装包最终生成的启动命令大致长这样llama-server \ --model ./models/qwen3.6-35b.Q4_K_M.gguf \ --host 127.0.0.1 \ --port 11434 \ --n-gpu-layers 20 \ --threads 12 \ --ctx-size 65536 \ --cache-type-k q8_0 \ --cache-type-v q8_0 \ --parallel 1 \ --api-key sk-local-demo逐项说几个容易忽略但很重要的参数--parallel 1只允许一个并发请求。8GB 显存方案不支持多人同时用开多了每个请求都在互相抢占算力最后所有人速度一起崩。Agent 场景里串行请求完全够用。--cache-type-k/v q8_0KV 缓存量化。这是 128K 能跑起来的关键不设的话默认用 FP16显存账本立刻超支。--api-key sk-local-demo虽然是本地服务但要给个 Key。因为 Agent 框架、Dify 这类工具在对接时要求鉴权字段非空留空反而会在某些框架里报错。5.3 安装完成后的验证装完不要急着接 Agent先做一轮冒烟测试curl http://127.0.0.1:11434/v1/chat/completions \ -H Authorization: Bearer sk-local-demo \ -H Content-Type: application/json \ -d { model: qwen3.6-35b, messages: [{role: user, content: 用一句话解释什么是 KV 缓存}], max_tokens: 256 }返回正常说明模型服务没问题。这时候再看终端里 llama-server 打印的加载时间和显存占用如果显存占用超过 7.5GB把--n-gpu-layers往下降两层重启。6. 把模型接进本地 Agent从 OpenAI 兼容 API 到工具调用模型跑起来只是第一步真正让它干活的是 Agent 化。llama-server 提供的是 OpenAI 兼容接口这意味着市面上绝大多数 Agent 框架都能零改动对接只需要把 base_url 指向http://127.0.0.1:11434/v1把 api_key 填成启动时的 Key。6.1 函数调用基础Agent 的本质是模型决定调用哪个工具工具返回结果模型再根据结果继续推理。Qwen 系列对 function calling 的支持比较成熟GGUF 版通过 llama.cpp 的 tool calling 接口也能完整工作。核心是把工具描述以 JSON Schema 的形式传给模型{ type: function, function: { name: get_weather, description: 查询指定城市的当前天气, parameters: { type: object, properties: { city: {type: string, description: 城市名如北京、上海} }, required: [city] } } }6.2 一个最小的 Agent 循环下面这段是标准的什么框架都不装的 Agent 主循环用 Python 的 openai 库直接调本地模型from openai import OpenAI client OpenAI( base_urlhttp://127.0.0.1:11434/v1, api_keysk-local-demo ) TOOLS [{ type: function, function: { name: get_weather, description: 查询指定城市的当前天气, parameters: { type: object, properties: {city: {type: string}}, required: [city] } } }] def call_weather(city: str) - str: # 这里替换成真实的天气 API 调用 return f{city} 今天多云23°C messages [{role: user, content: 帮我查一下成都今天要不要带伞}] # 第一轮让模型决定是否调用工具 resp client.chat.completions.create( modelqwen3.6-35b, messagesmessages, toolsTOOLS, tool_choiceauto ) # 如果模型请求调工具就执行工具并把结果回填 if resp.choices[0].message.tool_calls: tool_call resp.choices[0].message.tool_calls[0] result call_weather(eval(tool_call.function.arguments)[city]) messages.append(resp.choices[0].message) messages.append({ role: tool, tool_call_id: tool_call.id, content: result }) # 第二轮把工具结果交给模型生成最终回答 final client.chat.completions.create( modelqwen3.6-35b, messagesmessages, toolsTOOLS ) print(final.choices[0].message.content)跑通这个最小循环之后你可以把天气接口换成任意内部工具——查数据库、发通知、操作本地文件、调用其他脚本本地模型的隐私数据全程不出本机这是它比云端 API 最大的价值。6.3 接框架时要注意的两个细节如果你用的是 Dify、FastGPT 这类可视化 Agent 平台配置模型供应商时选择 OpenAI 兼容类型即可但有两个坑并发数设置把 Agent 的最大并发请求数设成 1否则多个请求同时打到 8GB 显存的服务上会互相加塞响应时间翻几倍上下文长度声明平台默认按 OpenAI 官方模型的上下文长度去截断历史消息如果你在平台里选了gpt-4o这种模型名平台会按 128K 截断但你本地服务实际的 ctx-size 可能只有 32K。务必在模型配置里把上下文长度改成与你启动参数一致的值否则 Agent 会在你不知情的时候把超长历史塞进请求里模型端直接报错6.4 为什么我在 Agent 场景里保留 Thinking 但设上限前面提到 Thinking 模式很耗 token。在 Agent 循环里我通常把它打开但要限制推理轨迹的最大长度比如reasoning_tokens_max: 512。原因很简单复杂多步任务里模型的推理轨迹越严谨工具调用的次数和错误率越低反而省时间。但完全不设上限它可能会为了一个查天气的任务先洋洋洒洒写两三千字的内心戏体验很差。设一个上限让它在想清楚和别磨叽之间找到平衡这是我在实际操作里收获最大的一个调参经验。7. 实测避坑掉速、OOM、上下文截断和安装包翻车的四个典型场景这套环境我连续跑了半个多月中间踩了不少坑挑四个最有代表性的写在这里都是安装文档里不会写的部分。7.1 长上下文掉速不是模型问题是 KV 外置前面聊过当 KV 缓存超出显存容量llama.cpp 会把它移到系统内存。但注意一个细节KV 是否全部在显存里取决于你加载时的上下文分配而不是当前已用的上下文。你即使只聊了两轮只要--ctx-size开的是 128K系统就会按 128K 的容量预分配 KV 空间如果这个空间在显存里放不下后续全部走内存交换——哪怕你实际只用了 2K 上下文速度也已经慢了。所以我的习惯是按任务分端口。长文档分析用 128K 配 512 输出的端口日常对话用 8K 配 2K 输出的端口。两个服务共享同一个模型文件但上下文配置不同浪费最少。7.2 启动时 OOM多半是 -ngl 给撑爆了8GB 显存启动时很容易出现CUDA out of memory原因是模型权重加载阶段需要一段临时缓冲、CUDA context 本身也要占几百 MB。我遇到过加载时明明 7.9GB 没满启动后第一个 token 生成时直接崩溃的情况。后来把--n-gpu-layers从 22 降到 20留出至少 1GB 的富余空间给激活值和 KV再没崩过。提示不要在启动脚本里把显存用满。8GB 的卡永远按 7GB 去规划剩下 1GB 是给运行时临时变量和 CUDA context 的安全垫。7.3 图片一多就 OOM多模态输入是独立的显存消耗点。一开始我直接丢了一张 2048x1536 的截图视觉编码器瞬间产生上千的 tokenKV 直接爆掉。后来在 Agent 里加了图片预处理步骤任何输入图片先缩到最短边 512 像素用 PIL 或者 OpenCV 一行代码搞定。处理后识别质量几乎没有下降因为 Qwen 的视觉编码器本身对分辨率不敏感喂进去之前做降采样完全够用。from PIL import Image def preprocess_image(path: str, max_edge: int 512): img Image.open(path) ratio max_edge / max(img.size) if ratio 1: img img.resize((int(img.width * ratio), int(img.height * ratio))) return img7.4 安装包脚本在 Windows 上最容易翻车一键安装包在 Linux 上我基本没出过问题到了 Windows 上就暴露了几个老大难llama.cpp 预编译包的 DLL 依赖缺失、杀毒软件把 Vulkan 后端文件误删、PowerShell 执行策略拦截启动脚本。最有效的解决办法是装 WSL2在 WSL 里跑整套环境Windows 侧只用浏览器访问 Agent 平台。这样既绕开了 DLL 地狱也避免了脚本权限问题性能损失几乎可以忽略。7.5 一个被忽略的隐性瓶颈供电和散热笔记本跑大模型CPU 和 GPU 全速运转时整机功耗会冲到 100W 以上。普通笔记本的电源适配器和散热模组根本扛不住表现在现象上就是前两分钟速度 42 token/s然后撞到温度墙开始降频掉到 25 甚至更低。解决办法是更新显卡驱动后在电源管理里把性能模式设为最佳性能同时垫高笔记本让风扇进风通畅。我实测过只做散热这一个改动连续生成 10 分钟后的平均速度从 27 提到了 36这个提升比换任何量化档位都管用。我个人实际用下来的体会是这套方案的精髓不在于某个具体的参数而在于接受局部最优的思维。8GB 显存不是劣势它逼着你把模型量化、上下文分配、工具调用链路都做成显式可控的反而是件好事。最后再分享一个扩展方向把本地 LLM 服务接到 Home Assistant 这类智能家居中枢用 128K 上下文去做全天日志总结体验比云端 API 顺手得多而且完全不用担心隐私问题。你可以从今天这篇里的安装包先跑起来再慢慢往里加自己的 Agent 场景。