大模型的热度这两年一直没降过,但真正把 AI 落到业务里的人都知道,赛道再热闹,最后拼的还是工程细节。这里头有两件事最容易被低估:一是把模型真正部署起来、稳定跑通的功夫,二是从模型能力到产品能力之间的那层“胶水”,也就是 Agent 应用、提示词工程和质量测试。这篇文章我打算把这几年折腾大模型部署、应用开发和测试排障的流程完整梳理一遍,覆盖本地模型部署、Agent 架构、提示词工程、自动化评估与常见故障,适合正在做 AI 应用开发的后端工程师、测试工程师,以及想自己搭一套 AI 应用但又不知道怎么下手的技术爱好者。
我见过太多项目死在“模型很强但我们集成不起来”这一步,也见过不少团队把 80% 的时间花在调提示词、补异常、改接口上。AI 落地这件事,模型选型只占很小一部分,真正决定成败的,是你有没有一套稳定的工程闭环。
1. 模型部署方式选型:本地跑还是调 API
1.1 三条路线各自的优劣势
先说选型。开始做 AI 应用,第一个绕不开的问题就是模型从哪里来。目前主流路线无非三条:本地部署开源模型、直接调用云端 API、本地云端混合。没有绝对的好坏,只有适不适合当前业务。
本地部署最大的优点有三个:数据不出内网、推理成本随用量可控、模型行为可定制。医疗、金融、政务这类对数据边界要求极高的场景,数据根本不允许出内网,那本地部署就成了唯一选择。但缺点也很明显,硬件成本高,GPU 一台动辄好几万,而且模型版本更新、环境维护、推理性能优化都得自己搞,小团队很容易被运维拖死。
云端 API 正好相反,接入简单、模型迭代不用自己操心、按量付费,前期几乎零门槛。适合做原型验证、内容生成类应用、低频工具类产品。最大的顾虑是敏感数据出网,以及长期跑下来 token 费用可能远超预期。有些模型调用量一上来,一个月账单能到几万甚至几十万,那时候再想迁移到本地,前期的架构耦合会让你非常痛苦。
混合路线是目前中型团队比较常见的选择。把高频、低延迟、敏感的核心链路放在本地,把长尾、多样化、对延迟不敏感的任务丢给云端。比如客服系统里,意图识别和敏感词过滤走本地小模型,复杂问答走云端大模型,这样既能控成本,也能保证核心体验。
我给你的选型建议很简单:先想清楚数据能不能出网,再算财务账,最后才看模型效果。很多团队一上来就对比模型效果,却忘了业务约束条件,结果技术选型全被数据安全策略推翻,白做一轮。
1.2 模型量级和硬件配置怎么匹配
确定部署方式后,选多大的模型又是一个麻烦事。开源模型现在从 0.5B 到 70B 甚至更大都有,但并不是越大越好。参数规模直接决定显存占用和推理速度。
这里需要学会估算显存。一个经验公式是:FP16 精度下,大约每 10 亿参数占 2GB 显存;INT8 量化大约占 1GB 多一点;INT4 量化大约占 0.6GB 左右。以 7B 模型为例,FP16 大概需要 14GB 显存,单张 24GB 的显卡勉强能跑;INT4 量化后大约 5GB 到 6GB,消费级显卡和部分大内存笔记本都能带得动。70B 模型 FP16 需要 140GB 以上,常规单卡基本没戏,要么多卡并行,要么配合 CPU offload,体验通常不会太好。
所以我的建议是,个人开发者或者小团队起步,优先考虑 7B 到 14B 的量化模型。这类模型在代码生成、文本摘要、结构化信息抽取上已经能打,显存要求 16GB 到 24GB 之间,硬件门槛可控。如果任务是复杂推理、长文档理解,再考虑 32B 或 70B,但那时候就不是一两张显卡能解决的事了,你得有专门的推理集群预算。
还要提醒一句,不要只看显存够不够,要看“显存 + 内存 + 带宽”的整体表现。有些模型虽然能塞进显存,但算力不够,响应慢到没法用。所以做压力测试时,不要只测一个并发,要测 P95 延迟,那个数字才是用户真实感受到的卡顿程度。
1.3 一张表帮你做部署决策
| 维度 | 本地私有化部署 | 云端 API | 本地云端混合 |
|---|---|---|---|
| 数据私密性 | 高 | 低 | 中 |
| 初期成本 | 高(硬件采购) | 低(按量付费) | 中 |
| 长期成本 | 相对可控 | 随用量线性增长 | 需动态调度 |
| 延迟稳定性 | 受自身集群影响 | 受网络和限流影响 | 可优化 |
| 维护成本 | 高 | 低 | 中 |
| 适合阶段 | 业务稳定、数据敏感 | 验证期、轻量使用 | 中大规模生产 |
如果你看完还是不知道怎么选,就用一个笨办法:先接云端 API 把业务跑通,验证产品价值和用户需求。等日调用量稳定到一定量级,再把高频链路迁移到本地。这个顺序风险最低,也是我经历过的项目里最稳的一条路。
2. 本地大模型部署配置完全指南
2.1 环境准备:GPU、驱动、CUDA、容器
本地部署最怕的不是模型太大,而是环境一团乱麻。我见过不少人在裸机上装了 Python、CUDA、PyTorch,结果版本互相打架,模型跑起来各种报错。所以第一步,先统一环境。
如果你是 Linux 服务器,推荐直接用 Docker 容器。把 NVIDIA 驱动装好,然后安装 NVIDIA Container Toolkit,让容器能访问 GPU。这个步骤做完,后面换模型、换框架都很干净,不用在一台机器上反复“考古”。如果你是 Windows 本机,优先用 WSL2 模式,别直接在原生 Windows 上折腾 CUDA,坑太多了。
装好驱动后,可以用 nvidia-smi 确认 GPU 状态,重点看显存大小、驱动版本和 CUDA 版本。一般来说,驱动版本不要太旧,CUDA 版本决定你后面能不能跑最新的推理框架。不用纠结于把 CUDA 装到多新,很多框架自带的运行环境已经够用,你只需要保证驱动支持到位就行。
2.2 用 Ollama 五分钟跑起第一个模型
如果只是想快速验证和本地调试,没有比 Ollama 更省事的工具了。它把模型下载、模型管理、API 服务打包成了一体,对新手极其友好。
在 Linux 或 macOS 上执行:
curl -fsSL https://ollama.com/install.sh | sh安装完就能拉取模型:
ollama pull qwen2.5:7b-instruct ollama run qwen2.5:7b-instruct跑起来后,我们可以测试一下:
curl http://localhost:11434/api/chat \ -H "Content-Type: application/json" \ -d '{ "model": "qwen2.5:7b-instruct", "messages": [{"role": "user", "content": "用一句话解释什么是Agent"}], "stream": false }'Ollama 默认监听本地 11434 端口,而且提供了 OpenAI 兼容的接口,路径是 /v1/chat/completions。这意味着你后端代码里原来对接 OpenAI SDK 的逻辑,只需要把 base_url 改成 http://localhost:11434/v1,几乎不用改业务代码就能切换到本地模型。这个兼容性设计是我觉得最值钱的地方,省掉了大量集成成本。
比如用 Python 调本地模型:
from openai import OpenAI client = OpenAI( base_url="http://localhost:11434/v1", api_key="ollama" ) resp = client.chat.completions.create( model="qwen2.5:7b-instruct", messages=[{"role": "user", "content": "写一段Python代码,读取CSV文件并统计每列均值"}], temperature=0.3 ) print(resp.choices[0].message.content)2.3 用 vLLM 搭建高并发推理服务
Ollama 适合个人调试和低并发场景,但如果你的服务要对生产环境开放,并发一高,Ollama 的性能和显存管理就容易拖后腿。这时候更推荐上 vLLM,它是目前开源社区里做高并发推理的主流方案,通过 PagedAttention 等技术把显存利用率和吞吐量拉高了很多。
安装和启动也比较直接:
pip install vllm vllm serve Qwen/Qwen2.5-7B-Instruct \ --tensor-parallel-size 1 \ --gpu-memory-utilization 0.9 \ --max-model-len 8192启动后同样暴露 OpenAI 兼容接口,端口默认 8000。几个关键参数我得解释一下。tensor-parallel-size 表示用几张 GPU 并行切分模型,单卡就写 1,多卡按实际数量写。gpu-memory-utilization 是控制预留给模型和 KV Cache 的显存比例,0.9 意味着最多用 90% 显存,留一部分给系统和其他进程。max-model-len 控制最大上下文长度,越长越吃显存,要根据业务实际需求来设,不是越大越好。
之前有同事问,为什么 vLLM 的返回速度和 Ollama 差不多,但 QPS 高很多。因为 vLLM 的核心优势是连续批处理,它能动态合并多个推理请求到一个 batch 里,大幅提高 GPU 利用率。服务线程模型也经过优化。所以在生产环境,只要不是超小规模,我都建议直接上 vLLM。
生产部署时我习惯在前面挂一层 Nginx 或网关,做请求转发和限流。vLLM 本身不提供用户认证,直接把 8000 端口暴露到公网是很危险的,至少也要加个 API Key 验证,避免别人白嫖你的算力。
2.4 推理参数调优:温度、Top-p、max_tokens
模型部署起来不代表就完事了,推理参数不调好,效果和成本都会出问题。最关键的是 temperature、top_p、max_tokens 三个参数。
temperature 控制随机性,值越高输出越发散,越低越稳定。代码生成、信息抽取、分类这类任务我一般设 0.1 到 0.3,追求稳定性和可复现性;开放式的文案创作可以调高到 0.7 到 0.9,让语言更生动。top_p 是核采样,控制候选 token 的累计概率范围,通常和 temperature 配合使用,二选一微调就行,不要两个同时大改,否则输出会失控。max_tokens 则是硬性限制,防止模型无限生成,既保护成本也保护接口响应时间。
注意:并不是所有模型对 temperature 的响应都一样。有些模型在温度调高以后很容易开始“自说自话”,编造没有根据的内容。所以在生产环境里,宁可用低温度、多轮追问的方式提升输出质量,也不要用高温度赌它发挥。
3. 从模型到产品:Agent 应用开发与提示词工程
3.1 Agent 的本质:感知、记忆、行动三步循环
模型部署好之后,怎么把它变成真正解决问题的产品?这就是 Agent 的舞台了。我理解的 Agent,不是简单套壳 API,而是一个能自主拆解任务、调用工具、根据反馈连续调整的智能体系统。
最简单的 Agent 核心是个循环:接收用户请求,让大模型判断需要什么工具,调用工具拿到结果,再把结果回传给模型,模型决定下一步是继续调用还是给出最终回答。这个循环至少要跑一到五轮。没有这个循环,模型就是个单次问答机器;有了循环,模型才能真正去查数据库、发请求、查天气、算公式,成为能改变外部状态的系统。
在实践中,Agent 框架通常会抽象出几个模块:任务规划、记忆管理、工具注册、执行器。任务规划负责把复杂需求拆成子任务;记忆管理负责保存上下文、历史结果、用户偏好;工具注册则告诉模型“当前环境里你能调什么”;执行器负责真正调用外部系统并处理返回结果。这四个模块不用一开始就做得特别复杂,但边界要清晰。
3.2 手写一个最小可用的 Agent 循环
很多人一上来就上 LangChain 这类重框架,结果被抽象层绕晕。我建议先把底层逻辑自己写一遍,跑通后再决定要不要引入框架。下面这个最小循环,是理解 Agent 最好的入门代码:
import json def run_agent(user_input, tools, max_steps=5): messages = [{"role": "user", "content": user_input}] for step in range(max_steps): resp = chat_model(messages, tools=tools) if not resp.tool_calls: return resp.content for call in resp.tool_calls: result = execute_tool(call.function.name, call.function.arguments, tools) messages.append({ "role": "tool", "tool_call_id": call.id, "content": json.dumps(result) }) raise TimeoutError("Agent 超过最大执行步数")这段代码虽然短,但已经把 Agent 的骨架都包含进来了。chat_model 负责和模型交互,并把模型返回的工具调用请求解析出来;execute_tool 根据函数名找到对应实现,执行后把结果以 tool 消息回传。最关键的是防御机制,max_steps 限制,防止模型陷入无限循环,这在生产环境几乎必备。
真实项目里,工具返回结果可能非常长,直接塞进上下文会污染模型注意力。一个常见优化是,把工具返回先做摘要或者结构化提取,只把关键信息传给模型。比如查数据库后返回几百行记录,可以先算好汇总指标再丢给模型,而不是把原始数据全量塞进去。
3.3 在 Java 微服务里用 Spring AI Alibaba 接入 Agent
如果是 Java 技术栈的团队,人工造轮子会比较辛苦,直接用 Spring AI 这类框架更合适。Spring AI Alibaba 在 Spring AI 基础上做了大量生产化适配,对国内主流云模型有很好的兼容,也支持本地模型接口。
一个最简单调用示例:
ChatClient chatClient = ChatClient.builder(chatModel).build(); String answer = chatClient.prompt() .user("今天杭州适合穿短袖吗?请结合当前天气回答") .call() .content();但这只是单轮问答。真实应用里要结合 Spring AI 的 Advisor、Memory、Tool 机制去构建完整链路。我比较推荐先把模型调用封装成独立的 Service 层,不要让 Controller 直接依赖 ChatClient,方便后续加日志、限流、缓存和灰度。
在 Java 体系里做 Agent 有个容易被忽略的好处:链路追踪。老项目里通常已经有 SkyWalking、Micrometer 这类监控体系,AI 调用也可以接入到同一个 trace 里,出了问题能直接定位是模型层、工具层还是业务层的问题。这一点是 Python 原型项目比较难立刻补齐的运维优势。
3.4 提示词工程:一套可复用的 Agent 提示词模板
提示词看着简单,实际是回报率最高的优化点。我总结了适合 Agent 场景的结构化模板,大概长这样:
你是{角色},负责帮助用户完成{目标}。 可用工具:{工具列表,每个工具包含名称、描述、参数格式} 约束条件: 1. 必须基于工具返回结果作答,禁止编造数据。 2. 当工具返回为空或异常时,明确告知用户无法回答。 3. 每轮最多调用{数量}次工具。 4. 最终回答要简洁,控制在{字数}字以内。模板背后的逻辑是:显式告诉模型边界,减少它自由发挥的空间。很多人写提示词喜欢堆形容词,比如“请你以专业专家的身份”,这种话对模型的影响非常有限。真正有用的是给模型提供格式约束、示例和明确的判断标准。
少样本示例的威力远大于规则描述。比如你想让模型从合同里抽取甲方乙方,与其写一堆“请正确识别合同双方”,不如给两个标注好的输入输出对,模型马上就能学会你的格式。在 Agent 场景里,工具返回的解析规则也要用示例固定下来,否则模型每次输出的字段风格可能都不一样,后续解析代码会被迫写得很脏。
注意:提示词不是一成不变的,模型升级后行为可能会变,原来效果很好的提示词可能突然失灵。所以提示词必须纳入版本管理,并配合自动化测试持续回归。
4. AI 测试与质量保障:被低估的关键环节
4.1 AI 应用到底要测什么
很多团队把模型一接,功能一跑,就以为万事大吉。直到某天线上某个回答突然开始胡说八道,用户投诉雪花一样飘过来,才发现原来 AI 应用也要被测试。但 AI 应用的测试和传统软件测试很不相同,传统测试断言明确,比如“输入 1+1 输出 2”,但生成式模型的输出是开放式、概率性的,很难用固定断言去验证。
我在实际项目里,会把 AI 测试拆成五个维度。第一是功能正确性,检查答案是否准确、格式是否符合预期;第二是稳定性,同一个问题多跑几次,看结果波动是否在可接受范围;第三是回归质量,模型升级或提示词调整后,之前测过的好用例是否还正常;第四是性能,包括首 token 延迟、总响应时间、并发下的 P95 延迟;第五是内容规范性,检查生成内容里是否出现不适用的表述、敏感信息或诱导性内容。
内容规范这块尤其要重视。大模型本身没有主观判断能力,它的训练数据里什么样的话都有,如果不加护栏,很容易在业务场景里产出违规或带偏见的文本。很多大厂在做的是“红队测试”,也就是用大量恶意或边缘输入去攻击模型,找出防御薄弱点,再针对性加过滤规则或调整提示词。个人团队虽然做不到那么大规模,但至少要把高危场景的输入输出都录下来做回归集。
4.2 自动化回归测试:用数据驱动的方式评估 Prompt
回归测试最让我头疼的,就是“怎么判断这次输出算对”。我的解决方案是构建一个带标注的评测集,然后用一个强模型当裁判,给当前模型的输出打分。
评测集的基本格式是一组 JSONL 数据,每条包含输入、期望结果和评估维度。比如:
{"id": "case_001", "input": "帮我写一段Python读取CSV的代码", "expected": "包含read_csv", "dimension": "keyword"} {"id": "case_002", "input": "解释什么是KV Cache", "expected": "包含显存、复用、计算优化", "dimension": "keyword"}然后写一个简单的评测脚本,把当前模型的输出和期望结果一起发给裁判模型,让它输出 1 到 5 分,低于 3 分视为失败。跑一遍评测集后统计通过率和平均分,这个指标就可以作为后续每次模型或提示词改动的验收依据。
import json def eval_prompt(prompt, eval_set): failures = [] for case in eval_set: output = get_model_output(prompt, case["input"]) score = judge_model_score(case["input"], output, case["expected"]) if score < 3: failures.append(case["id"]) return len(failures) / len(eval_set)用模型评价模型的做法并不完美,裁判模型也会有偏好和偏差,但它至少能提供一个相对稳定、低成本的基准线。你可以把通过的评测集里的用例全部缓存起来,在日常开发中跑回归,只要出现大面积分数下滑,立刻能定位到是哪次改动导致的。
4.3 测试工程师在 AI 项目里怎么发挥作用
我接触过很多测试工程师,面对 AI 项目时第一反应是焦虑,觉得“模型输出不可控,我还能测什么”。实际上 AI 让测试工作更重要了,只是测的内容变了。
测试工程师最该做的三件事:搭建回归测试框架、沉淀评测数据集、建立线上监控大盘。回归测试框架能保证每次迭代不把旧功能搞坏;评测数据集是团队的核心资产,数据越丰富,回归能力越强;线上监控则是最后的防线,通过采集线上请求的成功率、无效回答率、用户反馈等数据,快速发现问题并回滚。
要特别强调的是,AI 应用必须具备“无效回答率”这个概念。传统接口要么成功要么失败,生成式模型可能返回一个 200 状态码,但内容完全是废话,这在用户侧依然是不可用。所以测试阶段要把“逻辑是否成立”“格式是否满足”“信息是否完整”这些软性判断纳入监控指标,而不是只看 HTTP 状态码。
4.4 监控指标怎么定
| 指标 | 说明 | 建议阈值 |
|---|---|---|
| 首 token 延迟 | 从请求到第一个 token 的时间 | P95 < 2s |
| 总响应时间 | 完整生成时间 | 视业务而定 |
| token 消耗 | 每次会话平均 token 数 | 持续观察成本 |
| 工具调用失败率 | Agent 调工具失败占比 | < 5% |
| 无效回答率 | 语义上无意义的输出占比 | < 3% |
| 评测集通过率 | 恢复自动回归通过比例 | > 95% |
监控不是为了让数据好看,而是为了能提前发现异常。我见过很多系统在线上跑得很顺,直到某天模型服务悄悄升级了版本,生成质量整体下滑,但业务方浑然不觉。如果当时有跑评测集做定期回归,这种问题半小时内就能发现。
5. 常见问题与排查技巧实录
5.1 部署环节的典型报错
先说显存溢出,这是本地部署最常见的坑。启动模型时报 CUDA out of memory,第一反应不应该是换更大的卡,而是先检查当前的并发和上下文长度。如果只是单卡 24GB 跑 7B FP16,还有余量,但如果你在 vLLM 里把 max-model-len 开到几万,几个请求进来显存直接爆掉。优先调整 gpu-memory-utilization 和 max-model-len,再考虑换量化模型。
还有一个高频问题是“模型下载慢”。不管是 Ollama 还是 huggingface,都需要连外部模型仓库,网络波动时很容易中途失败。解决思路是用断点续传,或者把模型文件先下载到本地再导入。Ollama 的话可以用 ollama pull 反复重试,它本身有断点恢复机制;HuggingFace 的话建议用 hf 命令行工具配合镜像配置,但具体镜像地址要根据你所在网络环境来选。
再说一个玄学问题:同样的模型,在自己电脑上跑和服务器上跑,输出结果不一样。这其实不玄学,根源可能是推理框架的算子实现差异,也可能是 float 精度差异。解决方法是把 temperature 设成 0,并把随机种子固定,这样可以缩小偏差。但别指望完全一致,模型服务之间做到可复现本来就是个伪需求,关键是语义质量稳定。
5.2 Agent 开发中的常见陷阱
Agent 最常见的翻车现场是“死循环”。模型反复调同一个工具,拿不到有效结果就再调一次,最后把 token 打光。除了设 max_steps,还要在工具层做结果去重和缓存,如果工具输入和上次完全一样,直接返回上次的结果,避免模型重复劳动。
第二个陷阱是“上下文爆炸”。每轮工具返回结果都塞进 messages,几轮之后上下文就接近窗口上限,模型开始遗忘早期的用户意图。常规思路是引入滑动窗口或摘要压缩,把早期对话做一个 summary,替换掉原始长文本。还有更细的做法:对不同工具的结果做字段裁剪,只保留模型决策真正需要的字段。
第三个陷阱是“工具权限过大”。有些开发者在 Agent 里放一个万能 execute_code 工具,让模型想执行什么代码就执行什么。这在原型阶段很爽,但生产环境里等于把一个没有安全检查的远程执行器交给模型,很容易出事故。实际项目中,工具命令应该是白名单制、细粒度的,比如“查定时任务”“重启某个服务”分开注册,而不是给一个“执行任意 shell 命令”的万能入口。
注意:Agent 的工具调用一定要有审计日志。模型在什么时候调了什么工具、传了什么参数、工具返回了什么,这些全部要留痕。否则线上出问题你连回放都做不到,排查就跟大海捞针一样。
5.3 测试环节自查清单
如果你现在要上线一个 AI 功能,可以对照下面这个清单做一遍自查。
- 是否有一个至少 50 条用例的评测集,覆盖正常场景、边界场景和异常输入?
- 是否做过稳定性测试,同一个 prompt 跑 10 次,结果波动是否可接受?
- 是否记录了模型版本、提示词版本、评测通过率的变化历史?
- 是否对工具调用失败、模型超时、API 限流等重要异常做了兜底文案?
- 是否验证过高并发下的表现,而不是只在单并发下测过?
- 是否对用户上传的内容做了必要的输入校验和输出过滤?
这套清单是我每次上线前必过的,虽然不能保证万无一失,但能把绝大多数低级问题挡在上线之前。
6. 我从这些实践中踩出来的几条经验
项目做得越多,越能体会到,AI 应用的很多问题都不是模型本身造成的,而是工程前置条件没做好。比如模型明明能力很强,但因为部署时显存参数没调好,导致响应太慢,最后被业务方判定为“模型不行”。又比如 Agent 明明逻辑设计得好,但因为工具接口不稳定,结果整个流程频繁失败,体验一落千丈。
我现在的习惯是,接到新的 AI 需求,先问五个问题:数据能不能出网?并发量大概多少?预期的响应延迟是多少?容错要求多高?预算上限在哪?这五个问题问完,技术方案基本就浮出水面了,剩下的都是执行细节。
如果让我给正在入门的人一个建议,我会说:先别急着上复杂框架,用最小代码把“模型调用-工具执行-结果回填”这条路走通,再逐步加模块。本地部署先用 Ollama 跑通,再做 vLLM 优化;Agent 先手写循环,再考虑框架;测试先积累一个 50 条左右的评测集,再考虑自动化平台。每一步都不难,难点只在于你有没有沉下心把链路里的每一环都亲手摸一遍。
还有一点不得不提,做 AI 应用不要迷信“大模型万能”。模型只是决策引擎,它需要靠工程系统来约束行为、提供工具、管理状态。真正值钱的,是你围绕模型搭建的那套完整闭环,而不是模型本身。把你的评测集、提示词版本、工具规范、监控指标当成项目资产一样持续打磨,比换更强的模型更早见效。