当大模型不再稀缺,这个判断正在改变 AI 产业的实际竞争方式。两年前,一个团队考虑引入 AI 时,第一步是追问有没有可用的开源模型,或者哪个商业 API 的智力水平足够强;今天,市面上的大模型选择已经非常多,开源模型、商业 API、本地部署方案都趋于成熟,真正难的是把模型嵌入具体业务之后,效果、成本、数据安全和运维体验还能不能稳定达标。这篇文章不讨论某一家公司的模型排名,而是站在 AI 应用开发者和技术负责人的角度,拆解当模型供给变得越来越充分时,AI 产业究竟在拼什么:模型选型、数据工程、推理部署、微调与 RAG、Agent 流程、安全合规,以及一套可执行的排查方法。适合正在做大模型应用、想评估开源模型落地,或者被线上效果和稳定性问题困扰的团队参考。
1. 大模型不再稀缺,稀缺的是稳定可用的落地系统
1.1 模型供给正在从“有没有”变成“怎么选”
大模型的获取渠道已经很成熟。想用商业能力,可以接入云厂商提供的模型 API,按 Token 计费,几分钟就能跑通;想把模型部署在自己环境里,社区里也有大量开源模型,配合推理框架、量化工具和部署脚本,可以在一张消费级显卡甚至 CPU 上做起实验。多模态大模型、行业模型、垂直领域开源模型不断出现,比如农业领域把土壤、气象、物联网数据接入模型,医疗健康领域也有开源的中医和临床知识模型,这都说明“找到一个可用的模型”已经不再是主要矛盾。
真正的矛盾变成了“怎么选”。不同模型在上下文长度、指令遵循、结构化输出、多语言、延迟、许可证、生态支持上差异很大。选型错误往往不会在 Demo 阶段暴露,而是在接入真实业务后出现:格式不稳定、幻觉率高、工具调用不兼容、推理成本超出预算。因此,团队需要一套围绕业务场景的选型方法,而不是凭榜单或宣传做决定。
1.2 产业竞争重心从模型能力迁移到场景工程能力
当所有团队都能拿到相近的模型能力时,竞争力转移到模型之外的工程细节。可以简单梳理为五个方向:
- 场景数据:有没有高质量、可更新、可追溯的业务数据来构建上下文和评测集。
- 数据管线:关系数据库、日志、文档、图片这些分散数据能不能被稳定加工成模型可读的结构。
- 推理成本:同样的效果,能不能用更小的模型、更长的缓存、更合理的批处理把单次调用成本压下来。
- 安全合规:内容安全、数据隐私、输出审计、权限隔离,不是上线后的补丁,而是必须预先设计。
- 反馈闭环:线上 badcase 能不能被记录、归因、回流到提示词、检索或微调流程中,形成持续改进。
所以“大模型不再稀缺”并不是说模型不重要,而是说模型只是整个系统里的一层。真正决定 AI 项目成败的,是围绕这层模型建立的数据工程、推理工程、评测工程和安全工程。
1.3 本文的技术主线
后面的内容会按照一条可落地的链路展开:先做模型选型和任务定义,再加工数据,然后部署推理,再针对效果做 RAG、微调和 Agent 化改造,最后补上安全合规和线上排查能力。整条链路可以对应到一个大模型应用从 Demo 走向生产的过程。对于学习阶段,可以先用最小案例跑通局部;对于生产环境,每部分都需要额外的日志、监控、回滚和权限控制。
2. 模型选型与场景匹配:先定义任务类型、效果指标和部署约束
2.1 先把任务拆成模型真正能处理的问题类型
选模型之前,先不要问“哪个模型最强”,而要问“我的业务到底属于哪类任务”。同一个模型在不同任务上的表现差异很大,任务定义不清,后面所有评测都无从谈起。常见的大模型任务类型如下:
| 任务类型 | 典型场景 | 模型最需要的能力 |
|---|---|---|
| 文本生成 | 营销文案、摘要、报告 | 指令遵循、内容连贯性、风格控制 |
| 知识问答 | 客服、内部知识库、文档问答 | 检索上下文理解、引用忠实度 |
| 信息抽取 | 合同字段抽取、工单结构化 | 严格格式输出、长文档理解 |
| 代码生成 | 代码补全、代码解释、测试生成 | 编程语言理解、上下文窗口 |
| 多模态理解 | 图片描述、票据识别、图文问答 | 视觉与文本对齐、OCR 稳定性 |
| Agent 决策 | 调用工具、查询订单、编排流程 | 函数调用、多步推理、错误恢复 |
场景越具体,越容易设计出合适的验证集。比如做客服问答,就不需要为一个写诗能力强的模型额外付费;做多模态票据识别,就要重点测表格、模糊图片、手写体,而不是只测文本。
2.2 评估维度:效果、延迟、成本、数据安全、可控性
选型至少要从五个维度同时看。只看效果,会把系统设计成“大炮打蚊子”;只看成本,可能上线后才发现输出质量无法满足业务要求。
| 评估维度 | 需要关注指标 | 测试方式 | 选型倾向 |
|---|---|---|---|
| 效果 | 准确率、召回率、忠实度、badcase 比例 | 准备 30 到 100 条真实业务样本人工盲评 | 优先选择通过率更高的模型 |
| 延迟 | 首 Token 延迟、单次完整响应时间 | 用同样的 Prompt 多次压测 | 对实时交互要求高时避免过重模型 |
| 成本 | 单 Token 价格、输入输出比例、缓存成本 | 按真实请求分布估算月成本 | 高频场景优先可本地部署的中小模型 |
| 数据安全 | 数据是否会离开企业内网、是否可审计 | 查看服务协议、部署方式、日志留存 | 敏感数据优先本地部署 |
| 可控性 | 输出格式、JSON 合规率、工具调用成功率 | 构造固定格式请求,统计解析失败率 | 金融、政务等场景需要更强的格式约束 |
在评估阶段,最好把候选模型限定在 2 到 3 个。太多了,人工评测成本会失控;太少了,又看不到差异。
2.3 一个可执行的选型流程
建议按照下面这个顺序收敛:
- 收集 30 到 100 条真实业务请求,覆盖正常、边界、拒答三类情况。
- 为每个任务编写一套标准 Prompt,尽量固定,避免同时改多个变量。
- 让至少两名熟悉业务的人对输出盲评,记录“可用”“需修改”“不可用”。
- 对通过率最高的 2 个模型做延迟和成本压测。
- 对候选模型做安全测试,包括敏感信息、越权、诱导输出。
- 选择最合适的模型进行小流量灰度,而不是直接全量上线。
评测样本可以用 JSON 文件维护,方便后续复用。下面是一个最小结构示例:
[ { "id": "case_001", "task": "客服问答", "question": "我的订单超过三天还没有发货,应该怎么处理?", "reference": "先确认用户订单号,再查询仓库状态,若超时则给出补偿方案。", "pass_if": "answer_contains_order_id" }, { "id": "case_002", "task": "信息抽取", "question": "从合同里抽取甲方、乙方、合同金额和签署日期。", "reference": "结构化字段必须完整且可被 JSON 解析。", "pass_if": "json_valid_and_fields_not_empty" } ]这个文件可以成为模型升级时的回归测试集。每次候选模型变化,就用同样数据重新跑一遍,避免“换模型后老问题解决了,新问题出现了”的失控状态。
3. 数据工程:把关系数据库加工成大模型能读懂的上下文
3.1 数据质量决定效果上限,模型不擅长直接读原始表
大模型训练时见过大量自然语言、代码和文档,但它不会自动理解你业务库里的表结构。让模型直接面对一张多表 JOIN 的数据库,它既不知道哪些字段重要,也不知道字段之间是什么关系。因此,数据工程的核心任务是:把业务数据转换成模型能高效理解的语义单元,比如结构化文本、Markdown 文档、JSON 片段、向量索引或知识图谱。
常见做法是根据业务场景构建“模型上下文文档”。对于商品百科、订单查询、内部制度问答,可以从关系数据库或数仓中查询关键字段,拼成一段描述文本;对于长文档,则切成合适大小的 chunk,再做向量化。这个阶段的输出质量,会直接决定 RAG 和微调的上限。
3.2 一个最小实现:SQL 查询、文本化、Embedding、写入向量库
假设业务库里有一张商品表,字段包括商品 ID、名称、类目、价格、库存和描述。为了让大模型在问答时能准确引用商品信息,我们可以先把这些数据导成一段段可检索的文本,再写入向量库。
先看 SQL 查询部分:
SELECT product_id, product_name, category, price, stock, description FROM products WHERE is_active = 1 LIMIT 1000;然后在同步脚本里把每一行商品数据拼成一段结构化文本:
import json import csv rows = [ { "product_id": "P1001", "product_name": "无线机械键盘", "category": "办公外设", "price": "399.00", "stock": "128", "description": "支持蓝牙和 2.4G 双模连接,键帽为 PBT 材质。" } ] output_path = "products_docs.jsonl" with open(output_path, "w", encoding="utf-8") as f: for row in rows: doc = ( f"商品ID:{row['product_id']}\n" f"商品名称:{row['product_name']}\n" f"类目:{row['category']}\n" f"价格:{row['price']}\n" f"库存:{row['stock']}\n" f"描述:{row['description']}" ) record = { "id": row["product_id"], "text": doc, "metadata": { "category": row["category"], "price": row["price"] } } f.write(json.dumps(record, ensure_ascii=False) + "\n")这段代码把数据库行转成了模型能读的文档。接下来可以把每条text传给 Embedding 模型生成向量,再写入向量数据库。真正落地时,需要额外考虑三点:
- 增量同步:商品价格、库存变化后,要能及时更新向量库,删除过期数据。
- 权限标注:在
metadata中写入权限字段,检索后根据用户身份过滤,不能把全量数据无差别暴露给所有用户。 - 上下文长度:单条文档不要太长,超过模型上下文窗口或检索 chunk 限制时要拆分。
3.3 数据加工的常见坑
数据加工看起来简单,但线上项目很多问题都出在这一层。
| 常见坑 | 现象 | 为什么错 | 推荐做法 |
|---|---|---|---|
| 字段拼接没有分隔符 | 模型回答里商品名称和价格连在一起,信息混乱 | 文本语义边界不清晰 | 用明确的字段名和换行分隔 |
| 数据更新滞后 | 用户问库存时,模型回答的是昨天甚至上周的数据 | 同步任务失败或没有做增量更新 | 对同步任务做日志、告警和版本号管理 |
| 权限字段缺失 | 普通用户能问到内部成本价或供应商信息 | 向量库只做了文本化,没做权限隔离 | 在 metadata 里标注可见范围,检索后过滤 |
| 隐私数据直接进入上下文 | 手机号、身份证号出现在模型回复中 | 拼接字段时没有做脱敏 | 在写入前统一脱敏,只保留业务必要信息 |
数据加工不是一次性任务。随着业务变化、文档更新、权限调整,这条数据管线需要持续维护。建议为每次同步生成一个数据版本号,比如products_v20250601,出现线上问题时可以快速定位模型到底用的是哪一批数据。
4. 部署与推理:本地模型、API、成本与性能调优
4.1 本地部署还是云端 API:从数据边界和成本结构来决定
部署方式不是二选一,而要根据任务性质和阶段选择。对于快速原型,直接调用商业 API 或云厂商的免费额度最省事;对于数据敏感、调用量大、需要深度定制的场景,本地部署开源模型往往更合适。
| 对比维度 | 云端 API | 本地部署开源模型 |
|---|---|---|
| 接入速度 | 快,注册后即可调用 | 需要准备显卡、模型文件、推理服务 |
| 数据边界 | 数据会发送到服务提供方 | 数据可以完全留在内网 |
| 单次成本 | 按 Token 付费,高频场景成本上升快 | 前期资源投入高,边际成本低 |
| 运维复杂度 | 低,服务商负责升级和可用性 | 高,需要自己处理版本、并发、监控 |
| 可控性 | 受服务商接口和模型更新节奏影响 | 可以固定模型版本,自行灰度 |
这里并不是说本地部署一定更好。很多团队本地部署后才发现运维成本远超预期,GPU 利用率低、推理框架版本不兼容、模型更新困难。生产环境建议以“能不能满足数据安全要求”和“单位请求成本是否可控”作为主要判断依据。
4.2 本地推理的最小启动链路
如果只是想在本机验证模型效果,可以用 Ollama 这类工具快速启动。以常见开源模型为例,命令可能是:
ollama pull qwen2.5:7b ollama run qwen2.5:7b注意模型标签要以你使用的模型仓库为准。Ollama 适合本地实验和轻量服务,但高并发、高吞吐的线上服务通常需要更正式的推理框架。vLLM 是常见选择,它支持 OpenAI 兼容接口,部署后可以直接复用很多 API 调用工具,启动命令类似:
python -m vllm.entrypoints.openai.api_server \ --model /models/qwen2.5-7b-instruct \ --served-model-name my-model \ --port 8000对于显存非常有限的环境,也可以尝试 AirLLM 等方案,在单卡或低显存机器上运行大模型,但速度通常较慢,适合实验和离线任务,不适合高并发在线服务。不管用哪个框架,生产环境都要确认模型格式、量化方式和推理框架是否兼容。
4.3 推理参数和并发调优
同样的模型,参数设置不同,效果和成本差异很大。常见参数如下:
| 参数 | 含义 | 常见值 | 调大影响 | 调小影响 |
|---|---|---|---|---|
| temperature | 采样随机性 | 0.2 到 0.7 | 回答更多样,但更容易不稳定 | 更稳定,但可能更机械 |
| top_p | 核采样概率阈值 | 0.8 到 0.9 | 输出更多样 | 输出更集中 |
| max_tokens | 最大输出长度 | 512 到 2048 | 支持长回答,但延迟和成本上升 | 回答可能被截断 |
| frequency_penalty | 对重复内容的惩罚 | 0 到 1 | 减少重复,但可能改变风格 | 更容易重复 |
| batch_size | 推理批大小 | 依显存而定 | 吞吐更高,但显存占用更大 | 吞吐降低,更稳定 |
需要特别提醒的是:只调参数并不能解决根本质量问题。如果背景资料没有给到模型,或者检索结果本身就是错的,降低温度只会让错误回答更稳定。参数调优应该放在数据和 Prompt 之后,而不是之前。
上线前至少要做一轮功能验证,用 curl 检查接口是否可用:
curl http://localhost:8000/v1/chat/completions \ -H "Content-Type: application/json" \ -d '{ "model": "my-model", "messages": [{"role": "user", "content": "你好"}], "temperature": 0.2, "max_tokens": 512 }'正常返回后,再继续做性能压测。生产环境还需要关注 GPU 利用率、排队请求数、错误率、首 Token 延迟和 P95 延迟。
注意:本地部署跑通接口只是起点,不能代表生产可用。必须用真实请求分布做压测,并保留回滚能力,否则模型变更或推理框架升级时容易出现线上事故。
5. 微调、RAG 与 Agent:提升效果的三种主流手段
5.1 先选手段:提示词工程、RAG、微调分别解决什么问题
模型效果不好时,第一反应不应该是微调。多数问题可以用提示词工程和 RAG 解决,微调成本更高,也更容易引入负面效果。
| 手段 | 解决什么问题 | 优点 | 缺点 |
|---|---|---|---|
| 提示词工程 | 指令理解、输出格式、风格控制 | 成本低、见效快、易回滚 | 对复杂知识更新无能为力 |
| RAG | 知识更新、私有数据、引用溯源 | 数据实时可更新,可解释性强 | 依赖检索质量,上下文拼接复杂 |
| 微调 | 语气改写、格式纪律、特定任务能力 | 能改变模型行为,降低延迟 | 成本高,过拟合和遗忘风险大 |
推荐顺序是:先用提示词工程,再尝试 RAG,最后才考虑微调。只有当你发现“模型在特定格式、特定语气、特定技能上始终无法通过 Prompt 约束”时,微调才值得投入。
5.2 RAG 最小链路:检索、重排、生成、引用
RAG 的核心思想是从外部知识库中检索出和问题最相关的片段,把它拼到 Prompt 里,让模型基于这些片段回答。这样知识更新不需要重新训练模型。
最小链路可以写成:
def answer_with_rag(question): query_vec = embed(question) docs = vector_db.search(query_vec, top_k=5) docs = rerank(docs, question) context = build_context(docs) prompt = f"请仅根据以下资料回答问题,并在回答末尾列出资料来源编号:\n{context}\n\n问题:{question}" reply = llm.chat(prompt) return reply, docs这个链路里有三个关键点。第一,检索质量必须被单独评估,不能只看最终回答,如果前 5 条结果里没有正确答案,生成效果一定差。第二,重排可以用更小的模型对候选文档打分,把最相关的文档排到前面。第三,Prompt 里要明确限制模型不要编造来源,回答必须能溯源到具体文档。
“怎么连互联网搜索”也可以归入 RAG 的外部检索源,但联网内容噪声更大。建议对搜索 API 返回的域名、标题、摘要做过滤和评分,不要直接把未经校验的内容交给模型输出。
5.3 微调的最小闭环:数据集、训练、评估、回滚
微调不是把一堆问答丢给模型随便训练,而是要有清晰的目标和验证集。以对话模型为例,常见的数据格式如下:
{"messages": [{"role": "system", "content": "你是某电商平台的客服助手。"}, {"role": "user", "content": "订单超时未发货怎么办?"}, {"role": "assistant", "content": "请提供订单号,我会帮你查询仓库状态。如果确实超时,会按平台规则申请补偿。"}]}用开源训练框架做 LoRA 微调时,命令大概长这样:
llamafactory-cli train \ --model_name_or_path /models/base-model \ --dataset_path ./data/train.jsonl \ --template chatml \ --finetuning_type lora \ --output_dir ./output/lora-ckpt这只是示例命令,实际要按你使用的框架版本和数据集格式调整。微调之后必须完成三件事:
- 在预留验证集上跑评测,看目标 badcase 是否减少。
- 和基线模型做对比,防止其他问题变差。
- 保留基线模型权重,用灰度发布控制风险。
5.4 Agent 的本质是可控流程,不只是模型自动调用工具
Agent 让模型可以调用外部工具,完成查询订单、创建工单、访问数据库等操作。但 Agent 工程的核心不是“让模型自由发挥”,而是把工具调用限制在一个可控流程里。
第一步是向模型描述工具,让模型学会输出符合格式的函数调用。一个查询订单的工具定义可能是:
{ "name": "query_order", "description": "查询订单状态", "parameters": { "type": "object", "properties": { "order_id": {"type": "string"} }, "required": ["order_id"] } }第二步是校验模型的调用结果。不能直接信任模型返回的参数,需要对 order_id 做格式校验、权限校验、是否存在校验。第三步是设置最大步数和超时时间,避免模型陷入循环调用。第四步是把每次工具调用的入参、出参、耗时记录下来,方便事后回放。
推荐做法:面向生产的 Agent 必须把所有工具当作外部系统来对待。模型只负责生成工具参数,真正的权限校验、幂等控制、异常处理要放在代码层完成。
6. 产业落地必须回答的安全、合规与可观测性问题
6.1 内容安全不能靠模型自觉
大模型在开放对话中可能出现违规内容、诱导输出、泄露隐私等风险。生产环境需要建立多层防护,而不是只依赖系统提示词。
一个简化的思路是:
def safe_reply(request): if input_filter.is_unsafe(request.user_input): return "抱歉,我无法处理这个请求。" output = model.chat(request) if output_filter.is_unsafe(output): return "抱歉,我无法回答这个问题。" return output输入侧可以检测恶意指令和敏感信息,输出侧可以检查是否包含违规内容、是否泄露手机号或身份证号。更完整的安全体系还包括人工抽检、定期安全评测、告警和审计日志。安全测试应该以防御为目标,在隔离环境进行,不断发现边界问题并修复,而不是只在线上出事后再补救。
6.2 数据隐私与权限隔离
大模型项目里同时存在三种数据:训练数据、知识库检索数据、线上推理日志。它们不能混在一起管理。
| 数据类别 | 主要风险 | 控制方式 |
|---|---|---|
| 训练数据 | 数据来源不明、隐私泄露、数据投毒 | 记录来源、抽样审计、清洗脱敏 |
| 检索数据 | 权限缺失导致越权访问 | 检索后按用户身份过滤 |
| 推理日志 | 用户输入和模型输出包含敏感信息 | 脱敏存储、按角色控制访问、定期清理 |
尤其要注意:用户输入不能直接拼到系统提示词里作为最高指令。外部输入要放在“用户内容”边界内,不能让它修改系统角色、工具描述或权限判定。
6.3 用日志和指标支撑可观测性
大模型应用的黑盒感很强,如果日志不完整,线上问题很难定位。每次请求至少要记录以下内容:
| 字段 | 作用 |
|---|---|
| request_id | 串联整个调用链 |
| 模型名称和版本 | 定位是模型升级导致还是数据问题导致 |
| Prompt 版本 | 确认线上使用的是哪一套模板 |
| 检索到的文档 ID | 判断 RAG 是否检索到正确资料 |
| 工具调用入参和出参 | 定位 Agent 流程出错环节 |
| 输入和输出 Token 数 | 成本核算与异常发现 |
| 延迟和错误码 | 性能问题定位 |
有了这些字段,当用户反馈“答案错了”时,可以快速回放:输入是什么、检索到了什么、模型输出了什么、中间有没有调用工具、哪一步偏离了预期。可观测性不是锦上添花,而是大模型系统上线的基本条件。
7. 当效果不好或系统不稳时,从哪条链路开始排查
7.1 排查顺序:输入、数据、链路、模型、资源
大模型应用出问题时,不要一上来就怀疑模型能力不够。建议按下面的顺序排查:
- 输入是否正确:用户问题是否被截断?参数是否传错?系统提示词是否被意外修改?
- 数据和上下文是否完整:RAG 检索结果是否命中?向量库是否更新?权限过滤是否误删了内容?
- 链路是否正确:工具调用、函数参数校验、超时、重试逻辑有没有问题?
- 模型参数和版本:temperature 是否过高?max_tokens 是否截断?线上模型版本是否和评测版本一致?
- 资源和依赖:GPU 是否打满?推理服务是否排队?外部 API 是否限流?向量库连接是否正常?
很多线上问题都是因为“输入变了而系统不知道”。比如用户提交了一个超长文档,前端截断了;或者知识库同步任务失败,模型还在用旧数据回答。这类问题不查链路是看不出来的。
7.2 典型问题对照表
| 问题现象 | 常见原因 | 检查方式 | 处理建议 |
|---|---|---|---|
| 回答内容明显错误 | 检索结果不相关、上下文不完整 | 查看日志中检索到的文档 ID,检查 Prompt 拼接内容 | 优化检索和重排,增加引用校验 |
| 同样问题多次回答不一致 | temperature 过高、Prompt 不稳定 | 固定 temperature,多次调用观察差异 | 降低 temperature,固定 Prompt 版本 |
| 响应很慢 | 模型过大、GPU 不足、并发排队、max_tokens 过长 | 看首 Token 延迟和 P95 延迟,检查 GPU 利用率 | 量化模型、增大批处理、必要时换小模型 |
| 输出 JSON 解析失败 | 格式约束不够、模型不支持 JSON 模式 | 统计解析失败率,查看报错日志 | 使用 JSON mode 或输出后校验重试 |
| 微调后其他能力变差 | 过拟合、数据分布单一 | 用基线评测集对比微调前后效果 | 增加数据多样性,保留基线模型灰度 |
| 本地部署 OOM | 显存不足、批量太大、未量化 | 查看显存占用和模型大小 | 减小 batch、开启量化、选用更小模型 |
7.3 生产环境的 AI 应用检查清单
在发布前,可以对照这份清单逐项确认:
- 是否验证了输入边界:超长输入、空输入、恶意输入、非中文输入。
- 是否准备好了评测集:至少覆盖正常场景、边界场景、拒答场景。
- 是否检查了 RAG 的检索质量:能定位到错误的文档并回放。
- 是否记录了模型版本、Prompt 版本、数据版本。
- 是否对输出做了格式校验、内容过滤、隐私脱敏。
- 是否对工具调用做了权限校验、参数校验、超时限制。
- 是否保留上一版本模型或配置,支持快速回滚。
- 是否设置了关键指标告警:错误率、延迟、Token 成本、检索命中率。
- 是否有人工抽检和 badcase 回流机制。
这份清单不需要一开始就全部满足,但进入生产环境前,缺哪一项都意味着风险。学习环境可以先把功能跑通,生产环境必须逐步补齐。
当大模型不再稀缺,团队的竞争力会体现在更小颗粒度的工程决策里:数据管线是否干净,推理成本是否可控,badcase 是否能被追踪和修复,安全风险是否被提前评估。对于刚起步的团队,最值得投入的不是继续追新模型,而是把一条业务场景走成闭环,并建立自己的评测数据和反馈回路。把这条链路做扎实后,模型迭代、领域微调、Agent 扩展都会更有底气。