本地大模型完整指南:从编译部署到 12GB 跑通 27B
本地大模型完整指南:从编译部署到 12GB 跑通 27B
环境 A(部署篇):Jetson AGX Thor / Ubuntu,Docker + CUDA 环境 B(调优篇):llama.cpp b10184(Clang 20.1.8 win-x64),GPU RTX 4070 SUPER 12GB 模型:Qwen3.8-27B-Uncensored,IQ2_M 量化
AI 越来越火,token 越来越贵,于是我想本地化部署一个大模型,顺便把 Agent 也跑起来,这样就能无限使用。真正动手之后才发现,「装上能跑」和「跑得好用」完全是两件事——前者是编译部署的体力活,后者是 KV 缓存和上下文的精细调优。
这篇把两个阶段合在一起:第一部分讲怎么装(编译、模型下载、systemd 常驻、Agent 部署),第二部分讲怎么调(为什么 12GB 能跑 27B、上下文甜点在哪、长对话怎么压缩)。
第一部分:部署——把 llama.cpp 跑起来
一、前置条件
- 安装 Docker
- 安装 docker-compose
- 安装 CUDA
- 设备示例:Jetson AGX Thor
二、安装编译依赖
sudo apt update && sudo apt install -y build-essential git libopenblas-dev三、拉取 llama.cpp 源码(国内加速克隆)
# 加速克隆源码git clone https://ghproxy.com/https://github.com/ggml-org/llama.cpp.git# 进入项目目录cd llama.cpp四、编译 llama.cpp
# 编译(带 CUDA 支持)make clean && CUDA=1 make -j$(nproc)五、下载模型
1. 量化版本选择
Q4_K_P:显存占用低,适合小显存设备Q8_K_P:输出精度更高,显存占用更大- 多模态模型额外下载配套
mmproj视觉文件
2. HuggingFace 镜像替换规则
原地址: https://huggingface.co/xxx/模型仓库名加速地址:https://hf-mirror.com/xxx/模型仓库名3. 路径统一
将下载完成的 .gguf 模型放入项目内 models/ 文件夹,统一路径避免读取报错。
六、测试推理(验证编译与模型可用)
./main \ -m models/你的模型.gguf \ --flash-attn \ --mlock \ -np $(nproc) \ -c 8192参数说明:
| 参数 | 作用 |
|---|---|
--flash-attn | 注意力计算加速,降低显存占用 |
--mlock | 锁定内存,防止系统交换分区卡顿 |
-np | 并行推理线程数,默认 1 |
-c | 上下文长度,默认 8192 |
七、配置 systemd 常驻后台服务
实现开机自启、崩溃自动重启:
[Unit]Description=Llama.cpp Local LLM ServiceAfter=network.target
[Service]User=你的用户名WorkingDirectory=/home/你的用户名/llama.cppExecStart=/home/你的用户名/llama.cpp/server -m models/你的模型.gguf --flash-attn --mlock -c 8192Restart=alwaysRestartSec=5
[Install]WantedBy=multi-user.target加载并启动:
sudo systemctl daemon-reload # 重载系统服务配置sudo systemctl enable llama # 设置开机自启sudo systemctl start llama # 启动推理服务journalctl -u llama -f # 实时查看运行日志八、部署 AstrBot(Agent 侧)
mkdir astrbot && cd astrbotsudo docker run -itd -p 6185:6185 -p 6199:6199 \ -v $PWD/data:/AstrBot/data \ -v /etc/localtime:/etc/localtime:ro \ -v /etc/timezone:/etc/timezone:ro \ --name astrbot \ m.daocloud.io/docker.io/soulter/astrbot:latest到这一步,一个能跑、能自启、带 Agent 的本地推理环境就搭好了。但它能跑多长的上下文、能跑多大的模型,取决于下面这部分。
第二部分:调优——12GB 单卡跑通 27B
很多人听到「12GB 显存跑 27B」第一反应是「不可能」。我之前也这么想,直到手撕了一眼 GGUF 头——这个 27B 根本不是 dense 模型,KV 缓存比按层全注意力估算的小了 3~4 倍。
九、关键发现:它不是 dense 模型
用十六进制编辑器(或 strings + 头解析)看 GGUF 元数据,关键两行:
general.architecture = qwen35qwen35.block_full_attention_interval = 4qwen35 是混合架构:65 层里每 4 层才有 1 层全注意力,也就是只有 16 层需要存 KV 缓存;其余 49 层是 SSM(线性注意力),状态复杂度是 O(1),几乎不随上下文长度增长。
按 dense(65 层全注意力)去估 KV 显存,会高估 3~4 倍。我一开始算的上下文档位直接砍半就对了。
这也是为什么很多「27B 需要 XX GB」的经验公式在混合架构上会严重失准。
十、上下文甜点与断崖(实测 prefill 吞吐)
光看「能不能启动」没用——KV 溢出时它不报错,只会静默变慢。真正要看的是 prefill 吞吐曲线:
上下文 -c | KV 精度 | prefill 吞吐 | 判定 |
|---|---|---|---|
| 32768 | q8_0 | 1106 tok/s | 显存内 ✓ |
| 65536 | q4_0 | 970 tok/s | 显存内 ✓(甜点) |
| 98304 | q4_0 | ~103 tok/s | 落内存 ✗ |
| 131072 | q4_0 | ~105 tok/s | 落内存 ✗ |
断崖清晰地落在 65536 与 98304 之间。我现在的默认:
-c 65536 -ctk q4_0 -ctv q4_0 -np 1KVBUDGET=1200 MiB中文 token 密度按文体取:连续自然语言约 0.595 字/token,编号条目式 0.654~0.747 字/token,估算可用上下文长度时别用 1<1>1>。
前缀缓存默认开启:同一段系统提示词第二轮起几乎不用重算,每轮省 6~7 秒。
十一、上下文压缩代理 ctx-proxy
单卡 27B 的上下文再怎么抠也有限,长对话还是会顶到上限。我在客户端和推理服务之间加了一层零第三方依赖的压缩代理(ctx-proxy.py),客户端把 API 地址从 8080 改成 8787 即可,其余配置不动。
压缩策略按代价递增分四级:
- L0 原样透传
- L1 截断超长单条
- L2 滚动摘要(把早期对话压成摘要)
- L3 硬丢弃早期内容
事后若上游仍报超限,则激进压缩重试。
两个关键坑:
- Qwen3 默认 thinking 会把
content掏空——答案写进reasoning_content,content是空的。代理默认注入enable_thinking=False并剔除历史里的 reasoning;需要思考链时再用think参数开。 KV_SAFE_CAP = 42000:不必把-c顶到 65536,光是对话逼近上限就够让 KV 挤出显存、prefill 暴跌十几倍。提前压缩比撞墙再救更稳。
十二、写 .bat / 代理时的踩坑清单
.bat必须 CRLF,中文必须存 GBK/CP936(chcp 65001也救不了),可靠写回路径只有 PowerShellGetEncoding(936)并回环校验。llama-server --list-devices会永久污染控制台代码页(改成 65001),导致后续中文乱码 → 每次调用后立刻chcp 936;注意chcp会覆盖errorlevel,要先存退出码。- 代理窗口中文乱码修了三版才对:最终用控制台
WriteConsoleW写 UTF-16,由系统转码,不要在 Python 里猜代码页。 - 单实例守卫:一张 12GB 卡只能跑一个 27B-IQ2_M 实例;端口自动顺延会造出「僵尸实例」(
/health正常但补全 502)。 --tools有 7 个内置工具,schema 约 800 token;--agent/-ag≈--tools all --ui-mcp-proxy。
小结
本地大模型的落地可以拆成两条线,顺序不能反:
第一条线是「装得上」——装依赖、编译 llama.cpp、下载量化模型、systemd 常驻、再挂上 Agent。这部分是确定性工作,照着做就能成,卡点主要在镜像加速和路径统一。
第二条线是「跑得好」——命门不是「模型装不装得下」,而是 KV 缓存随上下文的膨胀。而混合架构让这件事比直觉乐观得多。核心三件事:
- 手撕 GGUF 头确认架构,按真实注意力层数算 KV,别套 dense 的经验公式;
- 用吞吐曲线找上下文甜点(我这里是 65536),别信「能启动 = 够用」;
- 长对话交给分级压缩代理,并主动设
KV_SAFE_CAP防止静默掉速。
如果你也在单卡上折腾大模型,欢迎交流你的甜点参数。
文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!



