本地模型部署
本地模型部署不是“把一个大模型下载到电脑里跑起来”这么简单。商用场景真正关心的是:
模型能不能稳定提供服务,数据能不能留在内网,响应速度和并发是否够用,成本是否可控,出问题能不能排查,后续能不能升级和回滚。
零基础先记住一句话:
本地部署解决的是“模型服务在哪里运行、由谁管理、数据是否离开内网、推理资源够不够”的问题,不等于模型能力一定更强,也不等于成本一定更低。
学习目标
学完本页,你应该能回答:
- 本地部署和云模型 API 的区别。
- 为什么本地部署要考虑模型文件、运行时、推理服务、业务后端和监控。
- CPU、内存、GPU、显存分别影响什么。
- 参数量、量化、上下文长度、并发和吞吐之间是什么关系。
- Ollama、llama.cpp、vLLM、TGI、Docker 部署分别适合什么。
- 一个本地模型服务如何接入业务后端。
- 为什么前端不能直接访问模型服务。
- 如何做健康检查、超时、重试、限流、降级和日志。
- 本地模型慢、启动失败、显存不足、中文效果差时怎么排查。
- 面试时如何讲本地模型部署的架构和取舍。
本地部署是什么
本地部署是把模型文件、推理运行时和推理服务部署在自己的机器、服务器或私有云里,由自己的后端系统调用。
flowchart TD
A["用户浏览器"] --> B["业务后端"]
B --> C["AI 网关或模型适配层"]
C --> D["本地推理服务"]
D --> E["模型文件和运行时"]
C --> F["日志、限流、监控"]
C --> G["RAG 检索和工具服务"]各层职责:
| 层级 | 职责 |
|---|---|
| 用户浏览器 | 发起聊天、问答、摘要等请求 |
| 业务后端 | 鉴权、限流、参数校验、业务编排 |
| AI 网关/适配层 | 屏蔽 Ollama、vLLM、云 API 等差异 |
| 本地推理服务 | 接收 Prompt,加载模型,生成 Token |
| 模型文件和运行时 | 保存权重,负责推理计算 |
| 监控日志 | 记录耗时、错误、token、资源使用 |
不要让前端直接调用本地模型服务。前端没有可靠权限边界,也不适合暴露内部地址、模型接口、系统提示词和安全策略。
为什么需要本地部署
本地部署通常是为了以下目标:
| 目标 | 说明 |
|---|---|
| 数据隐私 | 敏感文档、日志、客户资料、医疗数据不离开内网 |
| 离线可用 | 外部网络不可用时仍能使用 |
| 可控性 | 模型版本、服务参数、日志策略自己控制 |
| 成本可预测 | 高频固定场景可能比长期 API 调用更可控 |
| 私有知识库 | 与内网向量库、数据库、权限系统结合 |
| 实验验证 | 低成本验证 RAG、Agent、工具调用流程 |
但本地部署也有代价:
| 代价 | 说明 |
|---|---|
| 硬件成本 | GPU、显存、服务器、存储 |
| 运维成本 | 部署、升级、监控、故障处理 |
| 能力边界 | 本地中小模型能力可能弱于顶级云模型 |
| 并发压力 | 多用户服务需要排队、批处理或扩容 |
| 模型管理 | 模型文件大,版本多,升级要评估 |
所以本地部署不是“更高级”,而是安全、成本、性能、维护复杂度之间的取舍。
本地部署和云模型 API 对比
| 对比项 | 本地部署 | 云模型 API |
|---|---|---|
| 数据位置 | 数据留在本地或内网 | 数据发送到云服务 |
| 上手难度 | 需要安装运行时和模型 | 申请 Key 后即可调用 |
| 模型能力 | 取决于本地模型和硬件 | 通常更强、更新更快 |
| 成本结构 | 硬件和运维固定成本 | 按 token 或请求付费 |
| 并发能力 | 自己扩容和调度 | 云服务托管 |
| 可控性 | 高,可控模型和参数 | 受供应商能力影响 |
| 适合场景 | 内网、隐私、固定高频、实验 | 通用生产、高质量推理、弹性并发 |
实际项目常用混合策略:
- 低风险、高质量要求:用云模型。
- 高隐私、内网资料:用本地模型。
- 简单分类、摘要:用本地小模型。
- 复杂推理、高价值问题:路由到强模型。
本地推理的核心组件
flowchart TD
A["模型文件"] --> B["推理运行时"]
B --> C["推理服务 API"]
C --> D["业务适配层"]
D --> E["业务应用"]
B --> F["CPU / GPU / 内存 / 显存"]模型文件
模型文件保存了模型权重、Tokenizer、配置和可能的量化格式。
常见内容:
| 内容 | 作用 |
|---|---|
| 权重文件 | 模型参数,是模型能力的主体 |
| Tokenizer | 把文本切成 token,并把 token 转回文本 |
| config | 层数、隐藏维度、上下文长度等配置 |
| 量化文件 | 降低显存和内存占用的模型格式 |
推理运行时
运行时负责加载模型、管理内存、执行矩阵计算、生成 token。
常见运行时:
| 工具 | 特点 | 适合 |
|---|---|---|
| Ollama | 安装简单,模型管理方便,有 HTTP API | 个人学习、本地开发、轻量内网服务 |
| llama.cpp | 轻量,CPU 和量化支持好 | 低资源机器、嵌入式、离线实验 |
| vLLM | 高吞吐,支持服务化和连续批处理 | GPU 服务器、多用户并发 |
| TGI | Hugging Face 生态推理服务 | 标准化模型服务、团队部署 |
| Docker | 封装运行环境 | 团队交付、测试环境、私有化部署 |
推理服务 API
推理服务把模型能力暴露成 HTTP 接口,例如:
/chat:普通对话。/generate:文本生成。/embeddings:生成向量。/health:健康检查。
业务系统不应该到处直接调用某个具体接口,而应该通过统一适配层。
推理过程怎么工作
flowchart TD
A["输入文本"] --> B["Tokenizer 切成 token"]
B --> C["模型读取上下文"]
C --> D["预测下一个 token 概率"]
D --> E["采样或选择 token"]
E --> F["把新 token 加入上下文"]
F --> G{"是否结束"}
G -- "否" --> C
G -- "是" --> H["Tokenizer 解码成文本"]关键点:
- 大模型通常是逐 token 生成,不是一次性生成整段答案。
- 上下文越长,每一步需要处理的信息越多。
- 输出越长,循环次数越多。
- 模型越大,每一步计算量越大。
- 并发越高,显存、队列和调度压力越大。
这就是为什么 AI 接口通常比普通接口慢,也更需要流式输出、限流和超时。
参数量、量化和资源
参数量是什么
7B、14B、32B 里的 B 是 billion,表示十亿级参数量。参数量越大,通常模型能力越强,但资源要求也更高。
简单理解:
| 参数量 | 特点 |
|---|---|
| 1B 到 3B | 资源要求低,适合简单分类、摘要、实验 |
| 7B 到 8B | 入门常用,能做基础问答和 RAG |
| 14B | 能力更强,资源压力明显增加 |
| 32B 以上 | 更强但部署门槛高,通常需要较好 GPU |
量化是什么
量化是把模型权重用更低精度存储和计算,例如从 FP16 变成 INT8、INT4、Q4。
flowchart TD
A["原始模型:精度高、占用大"] --> B["量化"]
B --> C["占用更小、速度可能更快"]
C --> D["部分场景效果可能下降"]量化的价值:
- 降低显存和内存占用。
- 让普通机器也能跑较大模型。
- 降低部署成本。
量化的代价:
- 可能损失推理质量。
- 数学、代码、复杂推理可能更明显退化。
- 不同量化格式速度和效果不同。
面试时不要说“量化一定变差”或“量化一定更快”。正确说法是:量化通过降低权重精度减少资源占用,但效果和速度要结合模型、硬件、运行时、任务评测验证。
资源估算
部署前要看四类资源:
| 资源 | 影响 |
|---|---|
| CPU | CPU 推理速度、数据预处理、服务调度 |
| 内存 | 模型加载、上下文、并发请求、向量库 |
| GPU | 矩阵计算速度 |
| 显存 | 模型权重、KV Cache、并发上下文 |
显存为什么重要
推理时显存主要被这些东西占用:
- 模型权重。
- KV Cache。
- 输入输出上下文。
- 批处理和并发请求。
- 运行时额外开销。
KV Cache 用来缓存历史 token 的 Key/Value,避免每生成一个 token 都完全重算历史上下文。它能提高速度,但会占用显存,且上下文越长、并发越高,占用越大。
flowchart TD
A["并发请求增加"] --> B["每个请求都有上下文"]
B --> C["KV Cache 增加"]
C --> D["显存占用上升"]
D --> E{"显存是否足够"}
E -- "足够" --> F["正常生成"]
E -- "不足" --> G["OOM、排队、降速或失败"]资源估算思路
不要只问“某模型要多少显存”。还要问:
- 模型参数量多大?
- 是否量化?
- 上下文长度设置多少?
- 同时支持多少用户?
- 是否流式输出?
- 目标 P95 延迟是多少?
- 是否还要同机跑向量库、Rerank、业务服务?
资源估算的正确方式是:先小规模跑通,再用真实 Prompt、真实上下文、真实并发压测。
部署架构选择
个人学习架构
flowchart TD
A["浏览器或命令行"] --> B["本机后端"]
B --> C["Ollama"]
C --> D["本机模型"]适合:
- 学习 RAG、Prompt、工具调用。
- 不追求高并发。
- 单机可用。
企业内网架构
flowchart TD
A["用户"] --> B["业务系统"]
B --> C["AI 网关"]
C --> D["模型服务集群"]
C --> E["向量检索服务"]
C --> F["工具服务"]
D --> G["GPU 节点"]
C --> H["日志、监控、审计"]适合:
- 多用户访问。
- 需要权限、审计、限流。
- 需要与内部知识库和业务系统集成。
混合模型架构
flowchart TD
A["AI 请求"] --> B{"任务类型和风险"}
B -- "简单、低风险" --> C["本地小模型"]
B -- "企业私有资料" --> D["本地模型 + RAG"]
B -- "复杂推理" --> E["云端强模型"]
B -- "高风险操作" --> F["人工审批或强校验"]这种架构更接近商用现实:不是所有请求都走同一个模型。
模型制品从仓库到显存的完整过程
flowchart TD
A["批准的模型仓库或制品库"] --> B["下载到临时目录"]
B --> C["校验清单、Hash、大小和签名"]
C --> D["校验config、Tokenizer和权重分片"]
D --> E["原子发布到本地模型缓存"]
E --> F["运行时解析配置并保留地址空间"]
F --> G["加载或映射权重"]
G --> H["初始化GPU Kernel和通信组"]
H --> I["分配KV与工作区"]
I --> J["预热并执行已知请求"]
J --> K["Readiness通过后接流量"]为什么不能边下载边对外服务
大模型通常由多个权重分片、配置和Tokenizer共同组成。某个分片缺失、Hash错误或Tokenizer来自另一Revision,都可能导致启动失败或更隐蔽的质量错误。
安全发布顺序:
- 下载到带唯一构建号的临时目录。
- 校验文件允许列表、大小、Hash/签名和完整分片清单。
- 拒绝符号链接越界、未知可执行文件和未批准远程自定义代码。
- 加载最小元数据验证架构、dtype、Tokenizer和License。
- 在同一文件系统使用原子重命名发布完整目录。
- 生成不可变
modelRevision,服务只引用该Revision。 - 旧版本保留到新版本观察期结束。
如果直接覆盖 models/current 中的文件,多个Worker可能分别读到新旧分片,回滚也无法恢复一致状态。
权重怎样进入内存或显存
- CPU运行时可使用内存映射,让操作系统按页加载权重;首次访问可能发生Page Fault,因此“进程启动”不代表已预热。
- GPU运行时通常从磁盘读到主机内存,再复制到设备显存;部分框架支持分片加载、CPU Offload或直接存储优化。
- 多GPU部署需要按Tensor/Pipeline/Expert策略把权重放到对应设备,并建立通信组。
- 权重加载完成后还需分配KV Cache、Kernel工作区和运行时Buffer。
所以磁盘模型大小不能直接等于峰值显存。需要同时核算权重精度、KV、激活/工作区、CUDA Context、通信Buffer和碎片。
可运行Demo:模型Manifest完整性校验
下面使用标准库模拟“临时目录验收后才发布”。为避免教学代码修改真实目录,Demo只校验内存中的文件内容和Manifest。
import hashlib
def sha256(data: bytes) -> str:
return hashlib.sha256(data).hexdigest()
files = {
"config.json": b'{"model_type":"demo","layers":32}',
"tokenizer.json": b'{"revision":"tokenizer-v3"}',
"model-00001.safetensors": b"weight-shard-1",
"model-00002.safetensors": b"weight-shard-2",
}
manifest = {
path: {"size": len(content), "sha256": sha256(content)}
for path, content in files.items()
}
def validate_artifact(actual_files: dict[str, bytes], expected: dict) -> list[str]:
errors = []
if set(actual_files) != set(expected):
errors.append("文件集合与Manifest不一致")
for path, rule in expected.items():
content = actual_files.get(path)
if content is None:
continue
if len(content) != rule["size"]:
errors.append(f"{path}:size不一致")
if sha256(content) != rule["sha256"]:
errors.append(f"{path}:sha256不一致")
return errors
print("complete artifact:", validate_artifact(files, manifest))
tampered = {**files, "model-00002.safetensors": b"changed-weight"}
print("tampered artifact:", validate_artifact(tampered, manifest))
incomplete = {key: value for key, value in files.items() if "00002" not in key}
print("incomplete artifact:", validate_artifact(incomplete, manifest))真实系统还应验证签名、发布者身份、模型格式安全、配置兼容和制品来源。Hash能发现内容变化,但不能证明内容本身可信。
GPU软件栈为什么经常不兼容
宿主机GPU硬件
→ 宿主机驱动
→ 容器GPU Runtime
→ 容器中的CUDA用户态库
→ PyTorch/推理引擎
→ Kernel和模型dtype各层职责:
| 层 | 作用 | 常见故障 |
|---|---|---|
| GPU Driver | 控制硬件并提供内核接口 | 驱动过旧、设备不可见、Xid错误 |
| Container Runtime | 把设备和驱动能力注入容器 | 容器没有GPU、权限错误 |
| CUDA Runtime/Library | 提供用户态计算库 | 与框架构建版本不兼容 |
| PyTorch/Engine | 图执行、Kernel、调度和服务 | 缺少目标架构Kernel、符号错误 |
| NCCL/通信层 | 多GPU集合通信 | 拓扑、网卡、超时和版本问题 |
容器包含CUDA用户态库,不代表可以忽略宿主机驱动。镜像在A机器可运行,也不证明在不同GPU代际、驱动和互联拓扑的B机器可运行。
上线前保存并核对:GPU型号、驱动、容器镜像digest、CUDA/框架/引擎Revision、通信库和模型Revision。不要只记录“用了某某GPU”。
生产进程拓扑
flowchart TD
A["业务后端"] --> B["AI网关/路由"]
B --> C["模型API Server"]
C --> D["Scheduler"]
D --> E["GPU Worker 0"]
D --> F["GPU Worker 1"]
E --> G["模型分片、KV和Kernel"]
F --> G
C --> H["Metrics、Trace和Audit"]- API Server负责协议、认证后的内部调用、流式连接和取消。
- Scheduler负责队列、Continuous Batching、Token预算和公平。
- Worker拥有模型权重、KV Cache和设备上下文。
- Gateway负责场景路由、租户配额、模型Revision和降级。
不要在每个Web Worker中各加载一份完整模型。多进程若没有明确共享或设备分配,会重复占满显存。进程数、GPU可见设备和并行拓扑必须显式配置。
启动、存活、就绪和预热不是一回事
flowchart TD
A["进程创建"] --> B["读取配置和Manifest"]
B --> C["加载Tokenizer和权重"]
C --> D["初始化GPU、通信组和KV池"]
D --> E["执行预热请求"]
E --> F["校验输出、显存和模型Revision"]
F --> G["Readiness=true"]
G --> H["接收生产流量"]Startup Probe
模型首次加载可能需要数分钟。Startup Probe 用于告诉编排系统“仍在初始化”,避免Liveness过早重启形成永久启动循环。
Liveness Probe
回答“进程是否陷入不可恢复状态”。只检查端口能连接太弱:API线程活着但GPU Worker已崩也可能返回200。Liveness也不能执行昂贵生成,否则探针会加重拥塞并触发雪崩。
Readiness Probe
回答“此刻是否应该接新流量”,至少考虑:
- 模型与Tokenizer Revision加载完成。
- 所需Worker和通信组健康。
- 预热/自检通过。
- 未处于排空、过载保护或模型切换状态。
- 控制面路由和安全策略可用。
进程可以 live=true、ready=false:它仍活着,但正在加载、排空或过载,不应接新请求。
预热为什么必要
第一次请求可能触发:
- 模型文件页面首次读入。
- GPU Context和显存池初始化。
- Kernel加载、JIT或图捕获。
- 通信组建立。
- Prefix Cache尚未建立。
若实例一启动就加入负载均衡,真实用户会承担冷启动,P99突然恶化。预热应覆盖目标模型、典型短/长Shape、流式路径和结构化输出,但不能用生产敏感Prompt。
预热成功不等于容量通过;它只证明基本执行链可用。
优雅终止和排空
flowchart TD
A["收到终止或准备升级"] --> B["Readiness=false停止新流量"]
B --> C["Gateway停止向该实例路由"]
C --> D["等待在途Prefill、Decode和SSE"]
D --> E{"是否在终止宽限期内完成"}
E -- "是" --> F["保存审计并释放KV与通信资源"]
E -- "否" --> G["传播取消并标记中断"]
G --> F
F --> H["进程退出"]仅捕获SIGTERM后立即退出会截断流式回答;只无限等待又会阻塞发布。需要:
- 先停止准入。
- 为在途请求设置排空Deadline。
- 向上游Provider/Worker传播取消。
- 标记部分响应不可作为完整成功样本。
- 写Tool在终止时按幂等键确认结果,不能假设中断就是失败。
滚动升级为什么可能造成显存不足
普通Web服务滚动发布会先启动新Pod再停止旧Pod。GPU节点若没有足够冗余,旧模型占着显存时新模型无法加载,形成 maxSurge 启动失败。
可选策略:
| 策略 | 优点 | 风险与条件 |
|---|---|---|
| Rolling | 自动逐步替换 | 需要额外GPU/显存容量 |
| Recreate | 不需要双份资源 | 有停机窗口 |
| Blue/Green GPU池 | 快速切流和回滚 | 成本高,需要完整备用池 |
| Canary独立节点 | 风险隔离、可比较 | 样本和容量有限 |
生产AI通常将模型Revision和应用Revision绑定为不可变Bundle,在独立容量完成加载、预热、评测后再切路由。旧实例要等在途和观察期结束后释放,不能切流瞬间删除回滚目标。
多副本路由和会话
无状态单轮请求可分配到任意同Revision副本;多轮会话的历史若由后端集中保存,也可跨副本重建Prompt。依赖本机Prefix Cache或会话状态时,稳定路由能提高命中,但实例故障仍要能够从权威状态恢复。
路由至少考虑:
- 模型和Tokenizer Revision。
- 租户、数据级别和场景风险。
- GPU可用KV Token预算,而不只是请求数。
- 当前Queue、TTFT和Deadline。
- 并行组整体健康,不能只看一个Worker。
模型API契约和流式取消
统一适配层不能假设所有本地运行时能力相同。契约应声明:
- Chat、Completion、Embedding分别支持什么。
- 最大输入/输出和总上下文。
- Tool、JSON Schema、多模态和Logprobs能力。
- Usage在流式中何时返回。
- Finish Reason和错误分类。
- 是否支持Seed、取消和幂等请求ID。
SSE链路:
浏览器断连
→ 业务后端检测取消
→ AI网关取消模型请求
→ Scheduler移除等待/执行请求
→ Worker释放KV页如果取消只停在浏览器,模型仍会继续生成、占用GPU并计费。
Ollama 快速部署 Demo
适合个人学习和本地开发。
# 查看是否安装成功
ollama --version
# 下载模型,模型名称按实际环境选择
ollama pull qwen2.5:7b
# 命令行运行
ollama run qwen2.5:7b
# 调用本地 HTTP 接口
curl http://127.0.0.1:11434/api/chat -d '{
"model": "qwen2.5:7b",
"messages": [
{"role": "user", "content": "用一句话解释什么是 RAG"}
],
"stream": false
}'Python 调用:
import requests
def chat_with_ollama(message: str) -> str:
response = requests.post(
"http://127.0.0.1:11434/api/chat",
json={
"model": "qwen2.5:7b",
"messages": [
{"role": "system", "content": "你是一个简洁的技术助手。"},
{"role": "user", "content": message},
],
"stream": False,
},
timeout=60,
)
response.raise_for_status()
return response.json()["message"]["content"]
print(chat_with_ollama("解释本地模型部署的优缺点"))后端适配层 Demo
业务系统不要直接散落调用 Ollama。建议封装适配层,未来可以切换到 vLLM 或云模型。
from __future__ import annotations
from dataclasses import dataclass
import time
import requests
@dataclass
class ChatResult:
answer: str
model: str
latency_ms: int
class LocalModelClient:
def __init__(self, base_url: str, model: str) -> None:
self.base_url = base_url.rstrip("/")
self.model = model
def health_check(self) -> bool:
try:
response = requests.get(f"{self.base_url}/api/tags", timeout=3)
return response.status_code == 200
except requests.RequestException:
return False
def chat(self, message: str, timeout: int = 60) -> ChatResult:
if not message.strip():
raise ValueError("message is empty")
start = time.time()
response = requests.post(
f"{self.base_url}/api/chat",
json={
"model": self.model,
"messages": [{"role": "user", "content": message}],
"stream": False,
},
timeout=timeout,
)
response.raise_for_status()
data = response.json()
return ChatResult(
answer=data["message"]["content"],
model=self.model,
latency_ms=int((time.time() - start) * 1000),
)
client = LocalModelClient("http://127.0.0.1:11434", "qwen2.5:7b")
if client.health_check():
print(client.chat("什么是本地模型部署?"))
else:
print("local model service is not healthy")这个 Demo 体现了几件生产意识:
- 统一封装模型客户端。
- 有健康检查。
- 有超时。
- 返回模型名和耗时。
- 输入为空时提前校验。
真实项目还要补:鉴权、限流、重试、日志、traceId、token 统计、fallback。
Docker 部署思路
团队协作时,Docker 的价值是环境可复现。
flowchart TD
A["Docker 镜像"] --> B["固定运行时和依赖"]
B --> C["挂载模型目录"]
C --> D["暴露模型服务端口"]
D --> E["业务后端通过内网调用"]注意点:
| 点 | 说明 |
|---|---|
| 模型文件 | 通常挂载到容器,不建议打进镜像 |
| GPU | 需要宿主机驱动和容器运行时支持 |
| 端口 | 只暴露给内网或业务后端 |
| 日志 | 输出到标准输出或采集系统 |
| 健康检查 | 容器编排依赖健康状态 |
| 资源限制 | 限制 CPU、内存,避免拖垮宿主机 |
本地模型服务不要裸露到公网。即使没有 API Key,开放模型接口也可能被滥用导致资源耗尽和数据泄露。
商业场景:医疗数据资产平台
本地模型适合在医疗数据资产平台里做这些能力:
| 场景 | 为什么适合本地 |
|---|---|
| 数据标准问答 | 制度和字段口径可能属于内部资料 |
| 资产摘要 | 数据资产名称、字段、敏感级别可在内网处理 |
| 采集异常解释 | 日志和错误信息不方便发到外部 |
| 权限内知识库问答 | 结合租户、部门、角色过滤 RAG |
| 离线报告初稿 | 对实时性要求低,更看重隐私 |
不建议直接本地模型处理的情况:
- 需要非常强推理能力的复杂分析。
- 高风险医疗诊断结论。
- 高并发实时在线客服,且本地资源不足。
- 没有评估集证明本地模型质量足够。
生产监控指标
本地部署至少要监控两类指标:系统资源和模型服务。
| 类型 | 指标 | 说明 |
|---|---|---|
| 系统 | CPU、内存、磁盘、网络 | 判断机器基础状态 |
| GPU | 显存占用、GPU 利用率、温度 | 判断推理资源瓶颈 |
| 服务 | QPS、并发数、排队长度 | 判断请求压力 |
| 延迟 | 首 token、总耗时、P95/P99 | 判断用户体验 |
| 质量 | 拒答率、反馈、RAG 引用命中 | 判断回答是否可用 |
| 成本 | 机器成本、能耗、维护成本 | 判断是否比云模型合算 |
| 错误 | 超时、OOM、连接失败 | 判断稳定性 |
日志至少记录:
requestId、userId、model、promptVersion、inputTokens、outputTokens、
latencyMs、status、errorCode、host、gpuId生产排查流程
flowchart TD
A["本地模型服务异常"] --> B{"是否能访问服务"}
B -- "不能" --> C["检查进程、端口、容器、日志"]
B -- "能" --> D{"是否启动模型失败"}
D -- "是" --> E["检查模型文件、磁盘、内存、显存"]
D -- "否" --> F{"是否响应慢"}
F -- "是" --> G["检查上下文长度、并发、GPU、KV Cache"]
F -- "否" --> H{"是否回答质量差"}
H -- "是" --> I["检查模型能力、Prompt、RAG、评估集"]
H -- "否" --> J["检查业务后端、网络、超时和限流"]模型启动失败
排查:
- 模型名称是否正确。
- 模型文件是否下载完整。
- 磁盘空间是否足够。
- 内存或显存是否不足。
- 端口是否被占用。
- 运行时版本是否兼容。
显存不足或 OOM
解决方向:
- 换更小模型。
- 使用量化模型。
- 降低上下文长度。
- 降低并发数。
- 单独部署模型服务,不和向量库抢资源。
- 使用更高显存 GPU 或多机部署。
回答很慢
排查:
- 是首 token 慢,还是总生成慢。
- Prompt 是否太长。
- RAG TopK 是否太大。
- 输出是否太长。
- 是否 CPU 推理。
- 并发是否导致排队。
- 是否存在网络或后端超时。
中文效果差或答非所问
排查:
- 模型中文能力是否足够。
- Prompt 是否清楚。
- RAG 召回资料是否正确。
- 量化是否导致质量下降。
- 是否需要换模型、加 Rerank、改切分或补评估集。
常见坑
| 坑 | 后果 | 正确做法 |
|---|---|---|
| 直接让前端调模型服务 | 暴露内部接口,绕过权限 | 前端只调业务后端 |
| 只看模型能否启动 | 上线后并发和延迟不可控 | 用真实 Prompt 压测 |
| 盲目追求大模型 | 资源不够,体验很差 | 按场景选择模型和量化 |
| 不做适配层 | 切模型要改大量业务代码 | 封装统一 Chat/Embedding 接口 |
| 不记录版本 | 质量下降无法定位 | 记录模型、Prompt、知识库版本 |
| 不限制调用 | 模型服务被刷爆 | 加鉴权、限流、配额 |
| 不做降级 | 模型失败导致业务不可用 | 超时、重试、fallback、友好提示 |
| 把敏感日志发给模型 | 数据泄露风险 | 脱敏、最小化、权限审计 |
面试标准回答
本地模型部署是什么?
可以这样答:
本地模型部署是把模型文件、推理运行时和模型服务部署在自己的服务器、内网或私有云里,由业务后端通过统一适配层调用。它常用于数据隐私、离线可用、企业知识库和固定高频场景。生产上不能只看模型能不能跑,还要关注硬件资源、量化、上下文长度、并发、流式输出、健康检查、日志监控、限流降级和版本回滚。本地部署和云模型 API 怎么选?
云模型 API 上手快、能力强、弹性好,但数据会出内网且按 token 计费。本地部署数据可控、适合隐私和内网场景,但要自己承担硬件、运维、并发、监控和升级。实际项目常用混合架构:简单低风险走本地模型,复杂推理或高质量要求走云模型,敏感资料结合本地 RAG。
为什么本地模型也要经过业务后端?
因为业务后端负责鉴权、限流、参数校验、Prompt 编排、RAG 权限过滤、日志审计和安全控制。如果前端直接调用模型服务,就绕过了权限和审计,也容易暴露内部地址和系统提示词。
显存不足怎么处理?
可以换更小模型、使用量化模型、降低上下文长度、减少并发、减少 RAG 片段、关闭不必要服务,或者升级 GPU 和拆分部署。排查时要区分模型权重占用、KV Cache、并发请求和运行时开销。
本地模型回答慢怎么排查?
先看是首 token 慢还是总耗时慢,再检查 Prompt 长度、RAG TopK、输出长度、并发排队、CPU/GPU 使用、KV Cache、网络和后端超时。不要一上来就换模型,先用日志和监控定位瓶颈。
关联知识点
| 知识点 | 作用 |
|---|---|
| 大模型基础 | 理解 token、上下文、采样和幻觉 |
| Transformer原理 | 理解为什么模型逐 token 生成 |
| 推理优化 | 学习流式输出、缓存、模型路由、限流 |
| RAG知识库 | 理解本地模型如何结合企业知识库 |
| RAG数据治理 | 理解本地知识库的版本、权限、发布和回滚 |
| AI应用架构 | 学习 AI 网关、适配层和业务集成 |
| LLMOps | 学习模型、Prompt、知识库的治理体系 |
| AI安全 | 理解本地部署中的权限、脱敏和审计 |
| AI面试题 | 查看本地部署相关面试回答 |
本章小结
本地模型部署的关键不是“能不能跑起来”,而是“能不能稳定、安全、可排查地成为业务能力”。零基础学习时先理解五件事:模型文件是什么,运行时怎么生成 token,硬件资源为什么影响速度和并发,业务后端为什么要做适配和安全控制,线上问题如何通过日志和监控排查。
