模型在开发机上跑通了,演示也过了,接下来团队最常问的一句话是:要不要把它搬进内网自己部署?这个问题很容易被带偏成架构讨论——用什么推理框架、上不上向量库、要不要搞多机。但真正决定成败的,往往是几个很土的问题:显存够不够撑住真实并发、拔掉网线还能不能跑完整条链路、出事之后能不能查到是哪一次工具调用闯的祸。所以别急着画架构图,先拿一张上线检查清单过一遍。以下四项里如果有两项以上答不上来,本地部署大概率只是花钱买了个安心。

先问一句:本地部署到底买到了什么
本地部署本质上是用钱和人力,换三样东西:数据不出域、延迟和可用性自己说了算、权限边界可以按自己的规矩画。如果这三样你一样都不需要——数据本来就可以走公网、调用量稀疏、权限用云厂商的密钥体系就够——那本地部署只会给你增加一个需要人值守的 GPU 盒子。反过来,只要“数据绝对不能出内网”是硬约束,那后面的清单就不是可选项,而是能不能上线的前提。
一、算力:先算显存,再算并发
评估算力最常见的错误是拿“能跑多大模型”当结论。Agent 场景和聊天场景的负载完全不同:系统提示词里有工具定义、每轮要带历史、还要塞检索到的文档,上下文长度上去了,KV cache 会按“并发数 × 上下文长度”成倍吃显存。很多机器单条对话很流畅,一上五路并发就开始排队甚至 OOM。
所以算力检查要落到四个具体问题上:
- 在你的真实上下文长度下,单卡显存能撑几路并发?
- 量化到 4bit 之后,工具调用的 JSON 格式还稳不稳?(省显存是真的,格式崩了也是真的,必须用你自己的任务测,别只看榜单)
- 显存带宽和散热够不够?边缘设备常见的问题不是算力不足,而是长时间满载降频。
- 峰值时 CPU 和内存是否还有余量?推理服务之外的检索、解析、日志组件也在抢资源。
| 检查项 | 要回答的问题 | 参考判定 |
|---|---|---|
| 显存余量 | 峰值并发下显存占用多少 | 留出 15% 以上余量 |
| 上下文长度 | 工具定义 + 历史 + 检索结果的实际 token 数 | 按最坏情况配置 |
| 量化等级 | 降精度后任务成功率变化 | 用真实任务回归,不看榜单 |
| 长时稳定性 | 连续满载 2 小时后是否降频 | 观察吞吐是否明显下滑 |
具体型号和平台的算力参数,一律以厂商文档和自己的压测结果为准,不要拿别人的实测数字直接套。
二、模型与数据隔离:断网才算验过
“我们部署在内网”这句话,只有做过断网验证才成立。真实的泄漏路径往往很隐蔽:推理框架启动时尝试拉取模型清单、依赖包在构建时访问外网源、日志组件默认开启遥测、时间同步失败导致服务反复重启。这些东西在联网环境下一点症状都没有,一断网全冒出来。
隔离检查建议按这几条走:
- 模型权重从哪来、用什么校验完整性,有没有版本记录。
- 推理服务进程本身有没有出网权限,容器或主机层面是否做了出站限制。
- 日志、指标、崩溃报告是否落在外发通道上。
- 知识库和向量库的访问控制,是不是和现有文档权限对齐——不能出现 A 部门文档被 B 部门会话检索到的情况。
- 工具调用的数据边界:Agent 能读哪些目录、能写哪些接口、参数范围是否被白名单约束。
还有一点容易被忽略:本地部署不等于安全。内网文档里同样可能有诱导性内容,检索回来就进了上下文。OWASP 的 Agentic 安全清单里把提示注入、工具滥用、权限提升列为核心风险,对应的做法是工具白名单、参数范围校验、以及在负载下可靠可用的急停开关。急停开关要真的按一次,确认多步任务执行到一半也能停下来。

三、权限与审计:出事之后能还原现场
Agent 和普通服务最大的差别是它会自己决定调哪个工具。这意味着安全决策发生在调用点上,而不是部署前。上线前至少要确认三件事:
第一,每个 Agent 用独立的服务账号,只给最小权限,不要复用运维账号。第二,所有写操作走白名单加参数校验,删文件、发邮件、写数据库这类动作要么二次确认,要么先 dry-run。第三,审计日志能还原一次完整调用:谁发起的、Agent 选了哪个工具、传了什么参数、返回了什么、最终输出是什么。
验证方法很朴素:撤掉一个测试账号的权限,看 Agent 是否立刻失去对应能力;再翻日志,看能不能独立还原出这次失败的原因。如果这两步做不到,后面所有“出问题再说”的承诺都是空的。
四、监控运维:指标、回滚、值班
监控不需要一开始就上全套,但这几个指标得有:首字延迟、端到端时延、P95/P99、错误率、显存占用、请求队列长度、工具调用失败率,以及循环检测——Agent 反复调同一个工具是典型故障。腾讯云 ADP 的公开检查清单给出的参考值是首字 ≤1.5 秒、简单任务端到端 ≤5 秒、P99 不超过均值的 2 倍,这些数值可以当起点,最终标准还得按你的业务容忍度定。
运维侧要提前准备好三样东西:模型版本、提示词版本、配置版本都能一键回退;有明确的降级策略(模型不可用时走规则、走小模型还是转人工);以及谁在什么时候看告警。
五、用一个最小任务做验收
清单看得再多,不如跑一个真实任务。选一个可重复、判据明确的活儿,比如“读取内网共享盘里的一张工单截图或 PDF,抽出设备编号、故障现象、紧急程度,调用内部接口写入工单系统”。然后跑 20 次,量四个数:成功率、首字与端到端时延分布、并发翻倍时的错误率、以及推理服务被杀掉后的恢复时间。
下面这段脚本可以直接改改就用,前提是你的推理服务兼容 OpenAI 风格的 /v1/chat/completions 接口:
import json, time, statistics, requests
BASE = "http://127.0.0.1:8000/v1/chat/completions"
TASK = "从下面的工单文本中抽取设备编号、故障现象、紧急程度,只输出 JSON。"
def one_round(text):
t0 = time.perf_counter()
ttft, chunks = None, []
payload = {
"model": "local-agent-model",
"messages": [{"role": "user", "content": TASK + "nn" + text}],
"stream": True, # 必须开流式,否则测不到首字延迟
"temperature": 0, # 降低输出波动,方便比较
}
with requests.post(BASE, json=payload, stream=True, timeout=120) as r:
r.raise_for_status()
for line in r.iter_lines():
if not line or not line.startswith(b"data: "):
continue
data = line[6:]
if data == b"[DONE]":
break
delta = json.loads(data)["choices"][0]["delta"].get("content", "")
if delta and ttft is None:
ttft = time.perf_counter() - t0
chunks.append(delta)
return ttft, time.perf_counter() - t0, "".join(chunks)
rows = [one_round(sample) for sample in samples] # samples 换成你的真实工单
ttfts = [r[0] for r in rows]
totals = [r[1] for r in rows]
p95 = lambda xs: sorted(xs)[max(0, int(len(xs) * 0.95) - 1)]
print("首字 P50/P95: %.2fs / %.2fs" % (statistics.median(ttfts), p95(ttfts)))
print("端到端 P50/P95: %.2fs / %.2fs" % (statistics.median(totals), p95(totals)))
关键字段就三个:stream 决定你能不能测到首字,temperature 决定多次结果可比性,TASK 必须是你的真实任务而不是“你好”——闲聊测出来的延迟对 Agent 没有参考价值。
并发测试用两倍预期峰值去打,观察错误率是否超过 1%;故障恢复测试则是在压测中途直接 kill 推理进程,看三件事:Agent 是否优雅报错而不是卡死、能否自动重连、从重启到重新可用花了多久。最后别忘了检查有没有留下脏状态,比如半截的工具调用记录或残留会话。

这些情况,建议别本地部署
- 数据本身不敏感、合规也没要求:云 API 更便宜,模型更强,升级不用你操心。
- 调用稀疏、峰值很低:一张卡常年闲置的成本,通常高于按量付费。
- 团队里没有人能处理驱动、CUDA、推理框架这类底层故障:一次版本错配就可能停两天。
- 业务强依赖最新模型能力:本地开源模型的能力和工具调用稳定性需要你重新验证一遍。
- 需求其实只是“内部知识问答”:检索加重排加商用模型,往往比自建 Agent 更省事。
验收标准与下一步
把上面的内容收敛成一句话:最小任务成功率达标、P95 延迟在业务可接受范围内、两倍并发不崩、故障后能在约定时间内恢复、审计日志能独立还原一次完整调用——五条都过了再谈上线。如果有两条不达标,优先回去调工具定义、上下文裁剪和并发限流,而不是先加一张卡。算力不够通常是最后才确认的原因,前面几个才是常见病。

评论列表 (3条):
加载更多评论 Loading...