上个月有个做数据分析的朋友跟我抱怨:客户给了一批脱敏后的业务数据,想用大模型做信息抽取和摘要,但企业规定任何数据都不能发到外部 API。他试了一圈市面上的工具,要么只能在命令行里玩个小模型,要么就是绑定了云端服务,绕来绕去还是过不了合规那一关。我问他:为什么不直接在本地起一套完整的推理服务?他愣了半天。
后来我把自己在内部折腾了小半年的方案发给他看,就是我这边代号叫 IronClaw 的这套本地 AI 基础设施。它不是某个单一软件,而是把模型管理、推理引擎、API 网关、访问控制、监控日志这几个环节用开源组件拼起来的一套体系。核心思路很简单:大模型完全跑在自己的机器上,对外只暴露一个兼容 OpenAI 格式的接口,所有数据在本地闭环,谁调了哪个模型、传了多少 token,全都有日志可查。
这套方案我实际用了挺长时间,中间经历过显存爆掉、并发排队、模型答非所问、网关被人扫端口这些乱七八糟的问题,也一点点把流程理顺了。这篇东西我尽量把从选硬件、装环境、配模型、调性能到做安全加固的完整过程写出来,适合下面这几类人看:
- 公司有数据合规要求,不能把业务数据发给外部大模型 API 的人;
- 手头有一块还不错的显卡,想在家搭一个私有 AI 服务、给局域网内多个设备用的人;
- 用 Ollama 玩过一阵,但觉得单机命令行不够用、想升级成"带认证、带审计、带并发管理"的正规服务的人。
1. 先把话说清楚:IronClaw 到底是套什么方案
1.1 它不是某个软件,而是一套组合逻辑
IronClaw 这个名字是我们内部的叫法,寓意是"用爪子牢牢抓住自己的数据"。整个方案里没有一个是自研的神秘组件,全部是成熟开源项目,我做的只是把它们按照正确的姿势拼到一起。
组件分工大概是这样的:
| 层次 | 承担职责 | 我用的方案 |
|---|---|---|
| 基础设施 | 容器运行、GPU 透传 | Docker + NVIDIA Container Toolkit |
| 推理引擎 | 真正跑模型、生成 token | vLLM(主力)+ llama.cpp(备选) |
| 模型仓库 | 管理本地模型文件、版本、量化格式 | HuggingFace CLI + 本地模型目录 |
| API 网关 | 统一入口、认证、限流、审计 | FastAPI + 自研轻量 Token 中间件 |
| 前置代理 | TLS 终结、路由转发 | Nginx |
| 可观测性 | token 统计、显存监控、日志采集 | Prometheus + Grafana + Loki |
你可以把 vLLM 理解成发动机,模型是油,FastAPI 那层是车身控制系统,Nginx 是车门,Prometheus 和 Grafana 是仪表盘。平时本地自己玩,可以只用发动机和油;但一旦要让团队用、让业务系统接,车身、车门和仪表盘一个都不能少。
1.2 它解决了单机玩模型时最头疼的几个问题
我用 Ollama 也跑了挺长时间,单机自嗨确实爽,ollama run qwen2.5 一条命令就能聊起来。但真的拿来当基础设施用,问题就出来了:
- 没有统一的认证机制,局域网里谁拿到端口谁就能调用;
- 没有调用审计,出了问题不知道谁调的、调的哪个模型;
- 连续多个请求进来时,Ollama 的并发排队策略比较粗糙,一个长任务能把后面所有请求堵死;
- 模型一多,管理起来全靠记忆,没有版本概念,换模型要手动停服务。
IronClaw 这套方案要解决的,不是"怎么把模型跑起来",而是"怎么把模型跑成一个受管控的服务"。这是两个量级的事。
1.3 那些年我踩过的"伪本地"坑
我得先说一句大实话:市面上很多号称"本地部署"的产品,其实只是把客户端装在你机器上,模型推理还是在云端完成的。判断方法很简单:拔掉网线,看它还能不能用。 真正的本地 AI 服务,拔了网线照样能跑,因为它只依赖本机的 CPU、GPU 和硬盘。IronClaw 从设计上就保证这一点,所有模型权重都落在本地磁盘,推理进程只监听内网地址。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 硬件底座的三个选择题:显卡、内存与存储怎么不踩坑
2.1 显卡选型的核心不是"越大越好",是"够用且不浪费"
很多人上来就问:是不是得上 A100?其实绝大多数场景用不到。本地部署大模型,显卡选择主要看两个参数:显存容量 和 显存带宽。
显存容量决定你能跑多大参数的模型。以 Qwen2.5 系列为例,7B 模型用 4-bit 量化后大约需要 6-7GB 显存,14B 模型 4-bit 量化大约需要 11-13GB,32B 模型 4-bit 量化需要 22-26GB。如果你手头是 24GB 显存的 RTX 4090,那 14B 模型可以跑得很从容,32B 模型用 4-bit 量化也能塞进去但余量不大。
显存带宽则决定生成速度。同样一个 14B 模型,RTX 4090(带宽约 1TB/s)和 RTX 4060(带宽约 272GB/s)的出字速度能差好几倍。大模型推理是显存带宽密集型任务,这句话我在实际测试中体会特别深——同一个 GGUF 文件,放 4090 上能跑到每秒 60-80 个 token,放 4060 上可能只有每秒 10 几个。
所以我给的建议是:预算有限的话,优先保显存带宽,其次才是显存容量。二手 3090 是性价比很高的选择,24GB 显存、936GB/s 带宽,实际跑模型的表现跟 4090 差距没有价格差距那么大。
2.2 内存和存储:容易被忽视的系统性瓶颈
除了显卡,有两个地方特别多人忽略。
第一是系统内存。加载模型的时候,推理引擎通常会把模型权重先读到系统内存再拷贝到显存。如果系统内存不够,系统会走 swap,那加载速度慢到怀疑人生。我的经验是:至少要有显卡显存的 2 倍以上系统内存。比如 24GB 显存,系统内存至少 48GB,64GB 会更从容。
第二是存储。一个 14B 的模型,不量化的话光权重文件就 28GB 以上,4-bit 量化后大概 8-10GB。如果你打算多放几个模型,加上 Docker 镜像、日志、监控数据,2TB 的 NVMe SSD 是最基本的。而且务必注意:模型文件的读取速度会影响首次加载时间,也影响换模型时的体验。 用机械硬盘存模型,加载一个 14B 模型可能要等好几分钟,用 PCIe 4.0 NVMe 基本几十秒搞定。
2.3 一张关于多大显卡跑多大模型的参考表
| 模型规模 | 量化方式 | 占用显存(约) | 最低建议显卡 | 实际体验 |
|---|---|---|---|---|
| 7B | Q4_K_M | 6-7GB | 8GB 显存 | 流畅 |
| 14B | Q4_K_M | 11-13GB | 16GB 显存 | 流畅 |
| 32B | Q4_K_M | 22-26GB | 24GB 显存 | 可用,余量紧张 |
| 32B | AWQ/GPTQ 4bit | 20-24GB | 24GB 显存 | 推荐 |
| 70B | AWQ/GPTQ 4bit | 45-50GB | 双卡 48GB 或 64GB 显存 | 需要做张量并行 |
这张表是根据我实际跑过的数据整理的,量化方式不同、上下文长度不同,占用的显存都会有浮动。上下文长度特别重要——开 32K 上下文时,KV Cache 占的显存会显著增加,这点我后面在性能调优部分会再展开。
3. 安装实战:从裸机到跑通首次本地对话
3.1 操作系统的选择:Ubuntu 22.04 LTS 是省心之选
如果你问我 Windows 行不行,我会说能跑,但你要做好跟各种环境变量、路径、权限问题缠斗的心理准备。Linux 下的生态最完整,社区踩坑记录最多,遇到问题基本都能搜到答案。我在这套方案里用的是 Ubuntu 22.04 LTS,稳定、驱动支持好、Docker 支持完善。
安装操作系统本身没什么好说的,唯一要注意的是磁盘分区时给根目录和 /var/lib/docker 留足空间。Docker 默认把数据存在 /var/lib/docker,如果你的根分区只有几十 GB,几个模型镜像一放就满了。我自己是把 /var/lib/docker 单独挂了一块 2TB 的 NVMe。
3.2 驱动、CUDA 与 NVIDIA Container Toolkit:一次配到位
系统装好后,按顺序执行以下操作:
bash复制# 1. 更新系统
sudo apt update && sudo apt upgrade -y
# 2. 安装 NVIDIA 驱动 (这里装的是 535 版本,稳定性不错)
sudo apt install -y nvidia-driver-535
# 3. 重启,然后验证
nvidia-smi
看到显卡信息后,接着装 NVIDIA Container Toolkit,这是让 Docker 容器里能访问 GPU 的关键:
bash复制curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey \
| sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg
curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list \
| sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' \
| sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list
sudo apt update
sudo apt install -y nvidia-container-toolkit
sudo systemctl restart docker
很多人在这一步翻车,常见错误是容器里跑 nvidia-smi 报 could not select device driver with capabilities: gpu。这个错误 90% 是 NVIDIA Container Toolkit 没装好或者没重启 Docker,重新执行一遍安装并把 Docker 重启即可。
3.3 用 Docker Compose 把推理服务拉起来
我强烈建议用 Docker Compose 管理整套服务,好处是配置可版本化,换机器可以一键重建。先建一个目录结构:
code复制/home/ironclaw/
├── docker-compose.yml
├── models/ # 模型文件存放目录
├── gateway/ # FastAPI 网关代码
├── nginx/ # Nginx 配置
│ └── conf.d/
├── prometheus/ # 监控配置
└── grafana/
最初的 docker-compose.yml 我写的很简洁,核心就一个推理服务:
yaml复制version: "3.8"
services:
vllm:
image: vllm/vllm-openai:latest
container_name: vllm
restart: unless-stopped
ports:
- "8001:8000"
volumes:
- /home/ironclaw/models:/models
environment:
- HF_HOME=/models/huggingface
- CUDA_VISIBLE_DEVICES=0
command: >
--model /models/Qwen2.5-14B-Instruct-AWQ
--served-model-name ironclaw-qwen14b
--tensor-parallel-size 1
--max-model-len 8192
--gpu-memory-utilization 0.90
--trust-remote-code
--host 0.0.0.0
--port 8000
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: 1
capabilities: [gpu]
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
interval: 30s
timeout: 10s
retries: 3
这里解释几个关键参数:
--host 0.0.0.0:让服务监听所有网卡,这样宿主机和其他机器才能访问。但要注意,这必须在有网关和安全组保护的前提下。 vLLM 本身没有认证能力,裸奔到局域网是有风险的。--served-model-name:对外暴露的模型名。客户端请求时要用这个名字,否则会报 model not found。--gpu-memory-utilization 0.90:让 vLLM 最多使用 90% 的显存,留一点给 CUDA context 和其他进程,别满打满算。--max-model-len 8192:限制最大上下文长度,防止用户把超长文本塞进来导致 OOM。
跑起来后,验证服务是否正常:
bash复制curl http://localhost:8001/v1/models
如果能看到模型信息,说明推理服务已经就绪。再测一下真正的对话:
bash复制curl http://localhost:8001/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "ironclaw-qwen14b",
"messages": [{"role": "user", "content": "你好,介绍一下你自己"}],
"max_tokens": 256,
"temperature": 0.7
}'
到这里,一个最基本的本地 AI 推理服务就跑起来了。但注意,现在它把 HTTP 端口直接暴露在网络上,没有认证,任何人只要能访问这个端口就能调用。这就是我下一部分要解决的问题。
4. 模型选择与量化配置:让显存花在刀刃上
4.1 不要盲目追求大模型,场景决定参数规模
模型不是越大越好,这已经是老生常谈了,但实际选型的时候还是有人忍不住想上 70B。我的判断标准很简单:任务越垂直、指令越明确,小模型越够用;任务越开放、越需要推理深度,模型越大越稳。
具体来说:
- 简单的信息抽取、标题生成、关键词提取、格式转换:7B 模型足够,速度快、成本低;
- 需要一定逻辑推理的问答、代码生成、结构化数据整理:14B 是性价比很高的档位;
- 复杂 Agent 任务、长文本分析、多轮推理:32B 起步,最好 70B。
我在 IronClaw 方案里默认放了一个 14B 的 Qwen2.5 Instruct 和一个 7B 的 Qwen2.5,全部用 AWQ 4-bit 量化。日常业务中 80% 的请求走 14B,剩下 20% 的轻量任务走 7B 以换取更低延迟。
4.2 量化格式怎么选:GGUF、AWQ、GPTQ 有什么实际区别
这一块很多人搞混,我用大白话解释一下。
- GGUF:llama.cpp 生态的格式,可以在纯 CPU、CPU+GPU 混合、纯 GPU 上跑,量化等级分得很细(Q2_K 到 Q8_0)。好处是灵活,坏处是如果你主要用 GPU 跑,速度不如专门的 GPU 量化格式。
- AWQ:专门针对 GPU 推理优化的 4-bit 量化,保留了对模型推理更重要的通道的精度。vLLM 对 AWQ 支持非常好,显存占用低,速度也不错。这是我在 IronClaw 里的主力选择。
- GPTQ:另一种经典的 GPU 量化格式,生态成熟,很多开源模型直接提供 GPTQ 版本。效果跟 AWQ 各有千秋,实际跑起来差距不大。
一个很直观的对比,我在同一张 RTX 4090 上跑 Qwen2.5-14B:
| 量化格式 | 显存占用 | 生成速度(实测) | 加载方式 |
|---|---|---|---|
| 原始 BF16 | 约 30GB | 略超 24GB,跑不起来 | - |
| GPTQ 4bit | 约 11GB | 60-80 tokens/s | vLLM |
| AWQ 4bit | 约 11GB | 60-85 tokens/s | vLLM |
| GGUF Q4_K_M | 约 12GB | 55-75 tokens/s | llama.cpp |
注意这个"生成速度"是指生成阶段,首次返回 token 的延迟还跟输入长度强相关,这点后面会讲。
4.3 vLLM 还是 llama.cpp:两个引擎我都用了,说下取舍
IronClaw 的主引擎是 vLLM,因为它有两个非常关键的特性:连续批处理(continuous batching) 和 PagedAttention。通俗说,它能把多个并发请求拼到一个批次里推理,并且显存管理更精细。这意味着多人同时用时,vLLM 不容易被一个长请求卡住全局。
但 vLLM 也有它的短板:对显存的要求比较高,加载一个大模型后基本要把模型常驻显存;而且个别小众模型架构可能不支持。所以我也保留了一个用 llama.cpp 跑 GGUF 模型的后备通道,专门处理那些 vLLM 跑不了的模型。两条腿走路,稳一点。
4.4 上下文长度与 KV Cache 的显存博弈
这是最容易踩坑的地方。很多人以为模型支持 128K 上下文就可以随便往里塞 100K 的文档,结果一运行直接 OOM。原因在于:推理时每处理一个 token,都要为每一层注意力计算保存 KV Cache,这个缓存随上下文长度线性增长。
我实际算过一笔账:Qwen2.5-14B 开 8K 上下文时,KV Cache 占的显存还可以接受;但如果开到 128K,KV Cache 能吃掉 20GB 以上的显存。所以在网关层,我会强制限制每个请求的 max_tokens 和输入长度,而不是完全交给模型去限制。
我的默认配置:
- 14B 主模型:上下文峰值上限 16K,
max_tokens默认输出 2048; - 7B 次级模型:上下文峰值上限 32K,
max_tokens默认输出 4096。
如果你确实需要超长文档分析,建议走"先切块再汇总"的文档处理流程,而不是硬塞给模型。
5. 网关、认证与审计:堡垒的门禁系统不能是摆设
5.1 为什么必须在推理服务前面再套一层网关
直接裸奔 vLLM 的教训,我是实打实体会过的。有一次为了临时调试,把 vLLM 的端口映射到了 0.0.0.0,结果第二天看监控发现有一堆来自外地的 IP 在疯狂扫这个端口。虽然最后因为防火墙规则没造成实际损失,但那次之后我下定决心:任何推理服务都不允许直接暴露,前面必须有一层网关做认证、限流和审计。
网关层我用 FastAPI 写了一个轻量服务,核心职责有三个:
- 校验调用方身份(API Key);
- 记录每一次请求的调用方、模型、输入输出 token 数量、耗时、状态码;
- 把校验通过的请求转发给后端的 vLLM。
5.2 API Key 的发放与轮换机制
API Key 的管理听起来简单,实际要做的事不少:
- Key 要能区分用途。 我给不同的调用方发不同的 Key,比如
iron-ai-assistant给内部聊天机器人用,iron-data-team给数据分析平台用。这样出了问题,日志里一眼就能定位是谁。 - Key 要有最小权限。 有些调用方只允许访问 7B 模型,有些允许访问 14B,这个限制可以放在网关层做映射,而不是让调用方自己选模型。
- Key 要定期轮换。 我设置了一个程序,每 90 天自动生成新 Key 并通过内部系统分发给调用方,旧 Key 有 7 天宽限期。这个流程第一次跑的时候会有人嫌麻烦,但一旦成为惯例,安全性会好很多。
网关里的认证逻辑很简单,用 FastAPI 的依赖注入实现:
python复制from fastapi import Header, HTTPException
VALID_KEYS = {
"ak_live_abc123": {"allowed_models": ["ironclaw-qwen14b", "ironclaw-qwen7b"], "caller": "ai-assistant"},
"ak_live_def456": {"allowed_models": ["ironclaw-qwen14b"], "caller": "data-platform"},
}
def verify_api_key(x_api_key: str = Header(..., alias="X-API-Key")):
if x_api_key not in VALID_KEYS:
raise HTTPException(status_code=401, detail="Invalid API Key")
return VALID_KEYS[x_api_key]
实际生产里我用了数据库存储 Key 信息,还加了哈希处理,这里展示的是最小可运行版本。
5.3 模型白名单与调用参数约束
光有认证还不够,网关还要对请求做一层"策略校验"。核心策略包括:
- 允许使用的模型列表:根据 Key 的权限字段去过滤;
max_tokens上限:防止有人一次请求生成几十万 token;- 输入内容大小限制:防止有人把几十兆的文本直接塞进来。
这些策略可以在网关层形成一套统一的规则,而不是让每个调用方自己保证。我见过很多团队直接把 vLLM 的接口透传出去,结果有人传了一个超长 base64 文档,直接把显存打满,整个服务卡死。网关这层过滤非常必要。
5.4 审计日志与监控大盘:出问题时救命的东西
审计日志我是用 Loki 收集,Grafana 展示。每次请求会记录这样一条结构化日志:
json复制{
"timestamp": "2025-06-15T10:23:45Z",
"caller": "data-platform",
"model": "ironclaw-qwen14b",
"prompt_tokens": 1280,
"completion_tokens": 356,
"latency_ms": 4820,
"status_code": 200,
"client_ip": "192.168.2.108"
}
有了这份日志,我能回答三个关键问题:
- 谁在半夜调用模型?调了多少?
- 哪些请求失败了?为什么失败?
- 这个月模型跑了多少 token?需不需要扩容?
Grafana 上我做了几个简单的面板:QPS、平均延迟、P95 延迟、token 消耗趋势、显存使用率、GPU 温度。这些面板在排查问题和向上汇报时都非常有用。有一次团队反馈"模型变笨了",我查了监控发现是显存温度过高导致频率下降,清灰换风扇后问题立刻消失——这种事不看监控根本发现不了。
5.5 Nginx 做 TLS 终结与访问控制
网关本身跑在 8002 端口,我再用 Nginx 做一层前置,承担两个功能:
- TLS 终结:让局域网内的调用方走 HTTPS,避免明文传输;
- 访问控制:限制来源 IP,只允许公司网段访问。
Nginx 的核心配置长这样:
nginx复制server {
listen 8443 ssl;
server_name ironclaw.internal;
ssl_certificate /etc/nginx/certs/ironclaw.crt;
ssl_certificate_key /etc/nginx/certs/ironclaw.key;
allow 192.168.1.0/24; # 内网网段
allow 10.0.0.0/8; # 办公网段
deny all;
location / {
proxy_pass http://gateway:8002;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
证书我用的是内部 CA 签发的,调用方需要在代码里配置信任该 CA 或者跳过校验。如果是给内部系统用,这已经足够;如果以后要接入公网,再考虑用受信任证书。
6. 性能压测与并发治理:多用户接入时怎么不崩
6.1 压测工具与基准数据
整套服务搭好之后,我跑了一轮压测,用的是一个叫 oha 的轻量工具(也可以直接用 ApacheBench)。压测场景设计得很简单:模拟 20 个并发请求,每个请求让模型输出 256 个 token,持续跑 5 分钟。
RTX 4090 + Qwen2.5-14B-AWQ 的实测数据大概是这样的:
| 并发数 | 平均延迟(首个 token) | 平均生成速率 | 成功率 | GPU 显存占用 |
|---|---|---|---|---|
| 1 | 0.8s | 78 tokens/s | 100% | 12.5GB |
| 5 | 1.2s | 85 tokens/s | 100% | 14GB |
| 10 | 1.8s | 88 tokens/s | 100% | 15GB |
| 20 | 2.5s | 92 tokens/s | 98% | 17GB |
| 40 | 3.8s | 95 tokens/s | 92% | 20GB |
注意一个反直觉的现象:一定的并发下,生成速率反而比单请求更高。这是因为 vLLM 的 continuous batching 可以把多个请求拼成一个大 batch,GPU 利用率更高。但并发数超过某个阈值后,显存里的 KV Cache 会急剧膨胀,成功率就开始下降。
6.2 为什么"一个无限制的长请求"能拖垮全员
这个坑我印象太深了。有一次同事测试一个功能,直接把一篇几万字的文章塞给模型,要求做全文总结。max_tokens 没限制,模型就开始长达几分钟的长篇输出。由于 vLLM 的调度策略是争取公平地服务多个请求,KV Cache 一直被这个长请求占着,其他短请求的首 token 延迟大幅上升,整个服务的体验一下子变得很糟糕。
后来我在网关上加了两个硬限制:
- 单请求输出上限
max_tokens: 2048; - 输入长度超过 6000 token 的请求,必须走专门的文档分析接口,而不是直接走聊天接口。
这两个限制加上后,长请求现象基本绝迹。
6.3 队列与限流:优雅地拒绝比粗暴地崩溃强
当请求量超出服务能力时,与其让所有请求都卡住,不如直接告诉调用方"现在忙,稍后再试"。我在网关层加了一个简单的信号量限流:
python复制import asyncio
from fastapi import HTTPException
semaphore = asyncio.Semaphore(8)
async def forward_request(payload: dict):
if semaphore.locked():
raise HTTPException(status_code=429, detail="Too many concurrent requests")
async with semaphore:
return await call_vllm(payload)
同一时间最多允许 8 个请求进入推理服务,其余的直接返回 429。调用方看到 429 会做指数退避重试,这样比让他们一直等结果靠谱得多。这个设计思路是从支付系统里学来的,保护下游和限流永远比无脑堆积请求要好。
6.4 模型推理服务的多副本与热切换
如果你有两张显卡,还可以用 --tensor-parallel-size 2 把一个大模型切成两半并行跑,也可以起两个不同模型的实例,按路由规则分发。我的生产环境是这么布置的:
- 实例 A:Qwen2.5-14B-AWQ,承载常规对话和数据处理任务;
- 实例 B:Qwen2.5-72B-AWQ,承载复杂推理任务,只有当请求中带有
x-ironclaw-tier: high头时才路由到它。
这样普通任务不会被 72B 拖慢,复杂任务也能拿到足够的模型能力。网关的路由表配置好之后,调用方完全感知不到后面有几个推理实例。
7. 我这一路踩过的坑与调整记录
7.1 CUDA 版本不匹配导致的 "no kernel image" 错误
这个错误长这样:CUDA error: no kernel image is available for execution on the device。实际原因通常是 vLLM 镜像里的 CUDA 运行时和宿主机驱动的 CUDA 版本不兼容。Docker 镜像内置的是 CUDA 12.x,但你宿主机驱动太老(比如 470 系列只支持 CUDA 11.4),就会报这个错。
解决办法很简单:不要让镜像内的 CUDA 版本高于宿主机驱动的支持上限。 装驱动之前先查一下它支持的 CUDA 版本,然后选对应的镜像 tag。不要无脑拉 latest,我在生产环境固定了 vLLM 镜像的版本 tag,避免某次升级后行为突然变化。
7.2 模型下载慢到怀疑人生:换源与断点续传
从 HuggingFace 直接下载大模型,网络状况不好的时候真的是灾难。一个 14B AWQ 模型大概 8GB,下到一半断了就得重来。我的经验是:
- 优先用
hf-mirror.com这类国内镜像站; - 使用
hf download命令行工具而不是浏览器直下,它支持断点续传; - 下载后用
sha256sum校验文件完整性,避免文件损坏导致模型加载失败。
bash复制pip install -U "huggingface_hub[cli]"
export HF_ENDPOINT=https://hf-mirror.com
hf download Qwen/Qwen2.5-14B-Instruct-AWQ --local-dir /home/ironclaw/models/Qwen2.5-14B-Instruct-AWQ
7.3 服务是起来了,但模型总是答非所问:System Prompt 的魔力
刚开始我用 Qwen2.5-14B 做信息抽取,结果经常抽出一堆跟业务无关的内容。后来仔细读模型文档,才发现 Qwen2.5 系列对 System Prompt 非常敏感。在 System Prompt 里明确说明"你是数据分析助手,只从给定文本中抽取字段,不要回答无关问题"之后,效果立刻提升了不止一个档次。
这里有个通用经验:基座模型的能力上限跟你给的指令质量强相关。 把这套服务交给业务方用之前,我在每个业务场景里定制了专门的任务模板,而不是让他们自由对话。效果比换更大参数的模型还明显。
7.4 数据安全问题:日志里不要存原文
审计日志还有一个容易忽略的点:不要记录用户的输入和输出原文,尤其是涉及敏感业务数据的时候。 我只记录 token 数量、耗时、模型名等元数据,不记录 content 本身。否则日志系统一旦泄露,等于把数据泄露问题扩大到更大的攻击面。
我另外单独开了一个"安全审计"通道,只有在明确需要排查某次具体请求时,才手动开启内容包括的详细日志,且日志保留 24 小时自动清理。这套机制在合规审计的时候是很加分的。
7.5 定期做一次"断电重启"演练
最后分享一个平时大家不会多想、但关键时刻会救命的习惯:至少每个月做一次完整的断电重启演练。
不是让你真的把服务器电源拔了,而是把服务全部停掉,再按顺序启动,确认各组件能正确恢复。很多隐蔽的问题(比如某个服务没有设置 restart: unless-stopped、模型文件路径写死导致换机器失败)只会在重启时暴露出来。我第一次做这个演练时,就发现网关服务启动顺序错了,导致业务方在服务重启后的一段时间里一直连不上。后来我在 docker-compose 里加了 depends_on 条件和健康检查,才彻底解决这个问题。
写在最后的几句实在话
IronClaw 这套方案做到现在,最大的收获不是把模型跑了起来,而是把"模型服务"变成了一件像水电一样稳定可靠的事。你不需要理解矩阵乘法,也不需要会手写注意力机制,只需要把选型、部署、安全、监控这几件事做扎实,本地 AI 完全可以在团队里落地生根。
最后再分享一个小技巧:给网关加一个简单的"每周自动测试"任务,用几个固定问题去请求模型,如果返回结果不符合预期(比如状态码非 200、延迟超过阈值),就推送告警到企业微信或钉钉群。这个机制帮我在模型文件被误删、GPU 驱动被系统更新搞坏的时候第一时间发现问题,而不是等用户来投诉。
如果你也在折腾本地 AI 部署,希望这篇东西能帮你少走一些弯路。有什么问题欢迎在评论区交流,我自己也是在不断踩坑中慢慢完善这套方案的。
