主题
第10章 大模型应用架构设计
大模型给了所有人一种错觉——它什么都能干。随便装一个框架,跑一段 Demo,聊两句天,一切看起来都很完美。但一旦把它放进真实业务中,"一看就会,一用就废"的尴尬就来了。大模型领域昙花一现的技术、框架、应用比其他任何技术领域都多。这有点违反常识,因为大模型是如此的厉害。但是又是冷酷的现实,这是为什么?这个问题我也想了很久,很多人也想了很久。其实,这个问题不难回答,因为大模型的本质还是个应用程序,是应用程序就要按照软件工程的规律来,而软件工程最重要的组成部分就是架构的设计,所以我们用整整一章的内容来介绍如何对大模型的应用进行架构的设计。
10.1 六大子架构:任务架构
在大模型领域有一个非常有趣的现象:Demo 和落地之间存在着巨大的落差。因为 Demo 不需要回答这些问题:
- 这个任务到底适不适合用大模型解决?
- 大模型要替代的是哪一段流程?替代之后上下游怎么衔接?
- 做完了怎么衡量效果?比原来快了多少?省了多少人?花了多少钱?
这些问题不是写代码的时候才冒出来的——它们应该在项目启动前就被认真回答。而回答这些问题的过程,就是任务架构设计。
10.1.1 任务架构要回答的四个核心问题
在项目的调研阶段,任务架构设计必须给出四个明确答案:
第一,用大模型解决什么问题?
这不是一个随便就能回答的问题。大模型擅长的事情有边界——它能理解非结构化文本,能生成自然语言,能做推理和归纳,但它的计算精确度不如一段 SQL,它的确定性不如一个 if-else。你需要判断:你的问题落在它擅长的那一侧,还是不那么擅长的那一侧。
举个例子:用大模型写一份周报总结——擅长。用大模型做精确的财务计算到小数点后四位——不擅长,也不应该这么用。
第二,大模型要替代什么样的流程?
这比"解决什么问题"更进一步。解决问题可以是一个点,但替代流程意味着你要理解这个点在整个工作流中的上下游关系。
比如你要用大模型做客服工单的自动分类。这不只是"调用模型输出一个分类标签"这么简单——你需要搞清楚:工单从哪个系统来?分类结果要写回哪个系统?分错了怎么办?谁来兜底?人类客服的原有流程会被打乱吗?
第三,预期提高多少倍的效率?
效率提升是大模型项目的核心价值主张。但这个数字不能拍脑袋——它必须在项目启动前就有一个合理的预估,并且这个预估要拆到可验证的维度。我们会在 10.1.3 节详细讨论三个维度:时间、人力和成本。
第四,大模型在整个系统中占据什么位置?
大模型不是系统的全部,它只是系统中的一个推理引擎。你需要明确:它是一个独立的微服务?还是嵌在某个已有的业务模块里?它和哪些外部系统交互?它的输入从哪里来、输出到哪里去?这些问题回答清楚了,后面的架构设计才有地基。
把这四个问题串起来,你会发现任务架构设计本质上是在做一件事:把"用大模型"从一个模糊的想法,变成一个边界清晰、目标明确、可验证的工程任务。
10.1.2 确认任务模式:大模型能帮你做什么
任务模式的选择决定了你和大模型交互的基本范式。根据目前(2026 年)的工程实践,大模型在应用层主要承担四类任务。
10.1.2.1 问答型任务
最经典的模式:用户提问,模型回答。但落到工程中,这远不止"一问一答"那么简单。
python
# 简单的问答:一问一答(依赖:pip install openai,并设置 OPENAI_API_KEY)
from openai import OpenAI
client = OpenAI()
response = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": "大模型的上下文窗口最大能到多少?"}]
).choices[0].message.content真实的问答型任务需要处理的问题是:模型怎么知道自己该用哪些知识回答问题?如果它的答案错了,用户怎么发现?
这个问题的标准解法是 RAG(检索增强生成)——在模型回答之前,先帮它找到相关的文档、手册、历史工单,把"背景知识"注入进去。本书第 5 章已经详细讨论过 RAG 的原理和实现,这里不再展开。在任务架构阶段,你只需要确认:这个任务属于问答型,后续需要在知识架构层规划检索策略。
10.1.2.2 生成型任务
让模型从无到有产出内容:写文章、写代码、生成海报文案、翻译文档。生成型任务的关键挑战不在"能不能生成",而在"生成的东西能不能用"。
比如你让大模型写一封商务邮件——它肯定能写出一些东西。但这封邮件的收件人是谁?语气应该正式还是随意?需不需要附上具体的报价数字?这些约束条件如果不在任务架构阶段定义清楚,模型就只能在"什么都行"的表象下给出"什么都不够好"的结果。
python
# 生成型任务:关键是约束条件的注入
from openai import OpenAI
client = OpenAI()
response = client.chat.completions.create(
model="gpt-4o",
messages=[
{
"role": "system",
"content": (
"你是一名资深客户成功经理。请根据以下信息撰写一封客户回访邮件:\n"
"- 客户名称:某科技公司\n"
"- 合作时长:6个月\n"
"- 最近问题:API 调用超时频繁\n"
"- 语气:专业但不生硬,表达关切但不焦虑\n"
"- 结构:问候 → 问题回顾 → 改善措施说明 → 后续支持承诺"
)
},
{"role": "user", "content": "写邮件"}
]
).choices[0].message.content设计要点:在任务架构阶段,你需要明确生成物的质量门禁——谁来验收?验收标准是什么?模型生成的初稿需要人工修改的比例预期是多少?这些指标会成为后续架构设计中说"够不够好"的依据。
10.1.2.3 分析型任务
让模型阅读大量信息,从中提取结构化结论:舆情分析、合同审查、日志异常检测、竞品对比。这是大模型最有价值的任务类型之一,因为它直接替代了人类"读材料→找规律→下判断"的认知劳动。
分析型任务的特点是:输入量大、推理链长、结论需要证据支撑。不是"给我一个答案",而是"给出答案的同时告诉我为什么"。
python
# 分析型任务:要求结论附带依据
from openai import OpenAI
client = OpenAI()
response = client.chat.completions.create(
model="gpt-4o",
messages=[
{
"role": "system",
"content": (
"你是一名技术尽调分析师。请阅读以下日志文件,分析系统异常的根因。\n"
"要求:\n"
"1. 列出所有异常事件的时间点和类型\n"
"2. 判断异常之间的因果关系(标注置信度:高/中/低)\n"
"3. 指出最可能的根因,附引用原文作为证据\n"
"4. 如果无法确定,请明确说明不确定的原因"
)
},
{"role": "user", "content": "[500行系统日志内容]"}
]
).choices[0].message.content设计要点:分析型任务对提示词的结构化要求极高——你需要在任务架构阶段就明确输出的 schema(格式规范)、证据引用规则和置信度表示方式。这些约定会直接影响下游模块如何消费分析结果。
10.1.2.4 操作型任务
操作型任务是让模型执行具体动作:发邮件、调用 API、操作数据库、触发工单系统的状态变更。它和分析型任务的本质区别是:分析型只"说"不"做",操作型要真的动系统。
这是最需要谨慎对待的任务类型。因为模型一旦开始操作外部系统,错误的代价就不再是"一句错误的回答",而是"一笔错误的转账"或"一封发给全公司的错误邮件"。
python
# 操作型任务:必须设计安全护栏
from openai import OpenAI
client = OpenAI() # 需先设置环境变量 OPENAI_API_KEY
def agent_operation(user_request: str) -> dict:
# 第一步:理解意图(分析)
plan = client.chat.completions.create(
model="gpt-4o",
messages=[
{"role": "system", "content": "分析用户请求,拆解为操作步骤。只分析,不执行。"},
{"role": "user", "content": user_request},
],
)
steps = parse_steps(plan.choices[0].message.content)
# 第二步:风险检查(安全护栏)
for step in steps:
if step.action in ["send_email", "delete_record", "transfer_funds"]:
if not human_approval(step):
return {"status": "rejected", "step": step, "reason": "人工审核未通过"}
# 第三步:执行
results = []
for step in steps:
result = execute_action(step)
results.append(result)
return {"status": "done", "results": results}设计要点:在任务架构阶段,你需要标注哪些操作是"高危"的、必须有人工确认;哪些是"低危"的、可以自动执行。这个分类会直接影响后续 10.6 节推理架构中"安全护栏"的设计。
四类任务的对比
| 类型 | 核心动作 | 关键挑战 | 典型场景 |
|---|---|---|---|
| 问答型 | 理解问题→检索知识→生成答案 | 知识覆盖率和准确性 | 客服机器人、内部知识库 |
| 生成型 | 理解约束→产出内容 | 生成质量的可控性 | 文案创作、代码生成 |
| 分析型 | 阅读→推理→结构化输出 | 推理链的可解释性 | 舆情监控、合同审查 |
| 操作型 | 理解→规划→执行→验证 | 执行的安全边界 | 自动化工单、邮件触发 |
实践提醒:现实中一个任务很少只属于单一类型——比如"合同审查"既需要分析文字内容(分析型),又可能触发审批流(操作型)。我们的做法是以主导需求分类:判断哪个任务模式是本次的核心价值主张,其余为支撑。例如合同审查的核心是分析,操作只是附属动作——因此归档为"分析型",但在架构设计时把操作部分的安全护栏也一并规划进去。同样,问答型和生成型的边界也看主导需求:如果你的系统是"用户问一个问题,模型根据知识库回答",那就是问答型,即使模型生成了一段完整文字;如果你的系统是"用户给一个主题,模型写一篇文章",那就是生成型,即使文章里包含了回答式的内容。
10.1.3 确认输入/输出的信息类型
大模型的输入输出早已不只是文本了。2024 年以后,主流模型普遍支持图像、音频和视频的输入输出,多模态已经成为标配而非卖点。
在任务架构设计阶段,你需要回答的问题是:我的任务需要哪些类型的信息进出模型? 这听上去简单,但实际上决定了你要用什么样的模型、以及信息在进入模型之前需要经过怎样的预处理管线。
一个常见的陷阱是:业务需求是多模态的,但产品经理只按文本来规划。比如用户说要做一个"语音对话助手",很多人第一反应是"接一个语音识别转文字,然后让大模型聊"。但如果你在任务架构阶段就明确输入输出链路是 语音 → 文字 → 文字 → 语音,你就会发现这里涉及三个模型:ASR(语音识别)、LLM(大语言模型)、TTS(语音合成)。而且它们之间的延迟叠加、错误传递、上下文衔接都是需要提前规划的问题。
python
# 多模态管线示意:语音对话助手
# 这不是一段可直接运行的代码,而是管线规划的伪代码表达
# (只有 LLM 那一环用真实 SDK 写法;asr_model / tts_model 由你自行接入)
from openai import OpenAI
client = OpenAI()
class VoiceAssistant:
def handle(self, audio_input: bytes) -> bytes:
# 环节1:ASR — 语音→文字
text = asr_model.transcribe(audio_input)
# 环节2:LLM — 文字→文字(核心推理)
response_text = client.chat.completions.create(
model="gpt-4o",
messages=[
{"role": "system", "content": "你是语音助手,回答简洁、口语化。"},
{"role": "user", "content": text},
],
).choices[0].message.content
# 环节3:TTS — 文字→语音
audio_output = tts_model.synthesize(response_text)
return audio_output当然,如果你的业务场景比较简单,可以用支持端到端多模态的模型(如 GPT-4o 直接接收音频输入并输出语音),那管线会简化很多。但问题的关键不在于是用"三个模型"还是"一个模型",而在于:你在任务架构阶段就必须做出这个选择,而不是等开发到一半才发现"这个模型不支持语音输出"。
输入/输出类型确认清单:
| 信息类型 | 输入 | 输出 | 对应模型要求 |
|---|---|---|---|
| 文本 | ✅ | ✅ | 所有 LLM 支持 |
| 图像 | ✅ | ✅ | 需多模态模型(如 GPT-4o、Gemini)或专用图像生成模型 |
| 音频 | ✅ | ✅ | 需 ASR/TTS 模型或多模态语音模型 |
| 视频 | ✅ | 部分支持 | 需视频理解模型(如 Gemini 2.5 Pro),输出视频尚不成熟 |
| 结构化数据 | ✅ | ✅ | 所有 LLM 支持 JSON/XML 格式化输出 |
实践提醒:如果你的任务需求中包含"输出视频"——比如"根据脚本自动生成演示视频"——那么在 2026 年的技术水平下,这通常不是一个"模型直接输出"的问题,而是一个"模型生成脚本 + 传统视频渲染管线"的工程问题。在任务架构阶段就识别出这类"当前技术边界",能帮你避免不切实际的预期。
10.1.4 确认输入/输出的信息格式
明确了信息的类型,下一步要确认的是:这些信息的格式是什么样的? 类型告诉你"这是图片还是文字",格式告诉你"这张图片的要求是什么"。
输入格式的约束
不同模型对输入格式有不同的要求。以图片为例:
python
# 图片预处理:适配模型输入要求(依赖:pip install pillow)
import io
from PIL import Image
def preprocess_image_for_model(image_path: str, target_model: str) -> dict:
"""
不同模型对图片输入有不同要求,
在任务架构阶段就需要明确这些约束。
"""
img = Image.open(image_path)
requirements = {
"gpt-4o": {"max_size": (2048, 2048), "format": "PNG", "max_mb": 20},
"gemini-2.5": {"max_size": (3072, 3072), "format": "JPEG/PNG", "max_mb": 30},
"claude-4": {"max_size": (8000, 8000), "format": "JPEG/PNG/WEBP", "max_mb": 100},
}
req = requirements.get(target_model)
if not req:
raise ValueError(f"未知模型的格式要求: {target_model}")
# 尺寸调整
if img.width > req["max_size"][0] or img.height > req["max_size"][1]:
img.thumbnail(req["max_size"])
fmt = req["format"].split("/")[0]
if fmt == "JPEG":
img = img.convert("RGB") # JPEG 不支持 alpha 通道,RGBA 直接存会 OSError
# 文件大小检查
buffer = io.BytesIO()
img.save(buffer, format=fmt)
size_mb = len(buffer.getvalue()) / (1024 * 1024)
if size_mb > req["max_mb"]:
# 压缩或降分辨率(quality 只对 JPEG 生效,PNG 会忽略该参数)
quality = int(req["max_mb"] / size_mb * 90)
buffer = io.BytesIO()
img.save(buffer, format=fmt, quality=quality)
return {"image": buffer.getvalue(), "format": req["format"]}
# 用法
result = preprocess_image_for_model("contract_scan.png", "gpt-4o")这些不是"开发时再看"的细节。如果你的业务需要批量处理竖屏手机照片(比如餐饮点评的菜品图),但目标模型只支持 2048×2048 以内的输入,你必须在任务架构阶段就确认:原图是否需要裁剪?裁掉的部分会不会影响模型判断?要不要在上游先跑一个目标检测来辅助裁剪?这些问题如果留到开发中期才发现,代价就大了。
输出格式的对接
输出格式的挑战不在模型内部,而在模型和业务系统的接口上。两个典型问题:
问题一:格式不匹配。 模型能输出的格式和业务需要的格式不一致。比如业务要求严格符合 ISO 8601 的日期时间(如 2026-06-29T12:00:00+08:00),但模型的 JSON 输出里写的是 "2026年6月29日中午12点"。这不是模型的错——是你没在提示词里约束输出格式。但工程中不能只靠"写好提示词"来保证一致性,还需要在输出和业务对接之间设计一个格式校验层。最简单的做法是:用 JSON Schema 或正则做第一道拦截,不通过则触发模型重试或回退到默认值。
问题二:多模型协同。 一个模型搞不定,需要多模型协同输出。比如"产品详情页自动生成":A 模型写商品描述(文本),B 模型生成商品主图(图像),C 模型检查图文是否一致。
python
# 多模型协同输出示意
from openai import OpenAI
client = OpenAI()
def generate_product_page(product_info: dict) -> dict:
# 并行:文本和图像同时生成(互不依赖)
text_future = async_llm.call(
model="gpt-4o",
system="你是电商文案,根据产品信息撰写详情页文案。",
message=f"产品:{product_info}"
)
image_future = async_image_model.call(
model="dall-e-3",
prompt=f"产品主图:{product_info['name']},{product_info['style']}"
)
text = text_future.get() # 获取文本结果
image = image_future.get() # 获取图像结果
# 串联:验证图文一致性
quality_check = client.chat.completions.create(
model="gpt-4o",
messages=[
{
"role": "system",
"content": (
"你是质检员。检查文案和图片是否一致。\n"
"返回 JSON: {\"pass\": bool, \"issues\": [\"问题1\", ...]}"
)
},
{
"role": "user",
"content": f"文案:{text}\n图片描述:{image.description}"
}
],
)
check_result = json.loads(quality_check.choices[0].message.content)
if not check_result["pass"]:
# 修正逻辑:回退重试或人工介入
text = revise_with_issues(text, check_result["issues"])
return {"text": text, "image": image, "quality_check": check_result}设计要点:在任务架构阶段,你需要画出一张"信息流转图"——数据从哪里进入,经过哪些模型,产生什么格式的输出,最终去向哪个系统。这张图不需要精确到代码级别,但它必须能回答一个问题:如果某一个环节的输出格式变了,会影响到哪些下游模块?
10.1.5 核心目标的评估与确认
任务架构设计的最后一步,也是最容易被跳过的一步:我们怎么知道这个任务做成了?
大模型项目的效果评估和传统软件不一样。传统软件的功能可以写测试用例验证,但大模型产出的是"非确定性"的结果——你没法用"期望输出等于实际输出"来判断对错。因此,你需要从时间、人力、成本三个维度来设定可验证的效率指标。这些指标不只是"事后复盘"用的,它们要在项目启动前就定下来,成为后续所有架构决策的准绳。
时间维度
大模型最大的确定性优势,是它可以 7×24 小时连续工作。一个人类客服一天处理 200 张工单已经是极限,但一个大模型推理服务在 GPU 充足的情况下可以同时处理几百个并发请求,理论吞吐是人类的数十倍。
但要注意一个陷阱:单个模型的延迟可能比人类还慢。 比如一个复杂的法律合同审查任务,大模型可能需要 30 秒到 1 分钟才能完成一轮推理——这个单次速度比熟练的法务人员慢得多。但大模型的真正优势不在单次速度,而在并发能力。
python
# 并发 vs 串行:大模型效率的真正来源
import asyncio
import time
async def process_tickets_serial(tickets: list) -> list:
"""串行处理:一次一张工单"""
results = []
for ticket in tickets:
result = await llm.chat_async(ticket) # 每张 30 秒
results.append(result)
return results
async def process_tickets_parallel(tickets: list, concurrency: int = 10) -> list:
"""并行处理:用信号量把并发压在 10(不限并发会把上游打爆,也更容易 OOM)"""
sem = asyncio.Semaphore(concurrency)
async def one(ticket):
async with sem:
return await llm.chat_async(ticket)
return await asyncio.gather(*[one(t) for t in tickets])
# 100 张工单(按"单张约 30s"估算;30s 是这批工单的观测值,不是通例——
# 换模型、换输入长度都会变,务必先测你自己的样本):
# 串行:100 × 30s = 3000s(50分钟)
# 并行(10并发):(100 / 10) × 30s = 300s(5分钟)设计要点:设定时间指标时,要区分"单任务延迟"和"整体吞吐量"。单任务延迟决定了用户体验(用户等 2 秒和等 30 秒的感受完全不同),整体吞吐量决定了系统的处理能力。如果你的场景对延迟敏感(比如实时对话),那单任务延迟是硬约束;如果你的场景是批量处理(比如每天凌晨跑一次全量合同审查),那吞吐量才是核心指标。
人力维度
大模型对人力的影响有两个方向:一是替代——原本需要人做的事,现在模型可以做了;二是增强——人还在,但借助模型做得更快、更好。
在任务架构阶段,你需要明确定义"人机边界"在哪里。这不是一个哲学问题,而是一个工程问题:人负责什么、模型负责什么、边界上的交接协议是什么。
一个经典的模式是预标注 + 人工复核,在数据标注、内容审核、代码审查等场景中广泛使用:
python
# 人机协作模式:模型预处理 + 人工精修
def human_ai_annotation_pipeline(items: list) -> list:
"""
模型做第一轮标注,人工只复核低置信度样本。
相比纯人工标注,效率可提升 3-5 倍。
"""
# 第一步:模型批量预标注
pre_annotated = []
for item in items:
label, confidence = llm.classify_with_confidence(item)
pre_annotated.append({
"item": item,
"label": label,
"confidence": confidence
})
# 第二步:分流 — 高置信度直接通过,低置信度送人工
auto_pass = [p for p in pre_annotated if p["confidence"] > 0.85]
need_review = [p for p in pre_annotated if p["confidence"] <= 0.85]
# 第三步:人工只处理低置信度样本
human_reviewed = human_review(need_review)
return auto_pass + human_reviewed设计要点:设定人力指标时,要同时关注"替代率"和"增强率"。估算替代率的一个实用方法是将目标任务拆解为原子步骤,逐一判断每步可被大模型替代的置信度,加权平均后得到一个量级参考。替代率告诉你多少人力的工作可以被模型接管,增强率告诉你留下来的那部分人的工作效率提升了多少。这两个数字合在一起,才是大模型对人力投入的真实影响。同时,人机边界的设计要提前考虑"兜底机制"——当模型连续出错时,人能不能、怎么介入?人机边界的另一面是安全边界:当模型出错时系统如何自保、如何优雅降级——我们将在第 10.6 节详细讨论推理架构中的熔断和兜底设计。
成本维度
成本是最容易被"大模型很便宜"这个印象误导的一块。确实,API 调用价格在持续下降——2024 年初 GPT-4 的每百万 Token 价格还在几十美元,到 2026 年已经降到几美元。但总成本不等于单价乘以调用量。隐形成本有三块:
1. 准确性的成本。 为了让模型输出更准确,你需要投资于提示词工程、RAG 检索库的建设、Few-shot 示例的整理、输出格式校验层的开发。这些"让模型变好"的工作消耗的是工程师的时间——而工程师的时间比 API 调用费贵得多。
2. Token 消耗的成本。 很多任务不是一轮调用就能完成的。一个复杂的分析可能需要模型先分解问题、再逐步推理、再交叉验证、最后汇总结论——这个过程可能触发几十次 API 调用。而且每次调用都要把前面的对话历史全部传回去(因为模型无状态),Token 消耗会随着推理链增长而指数级上升。
以当下热门的 OpenClaw 等多智能体框架为例,一个看似简单的任务有时会触发数万甚至数十万 Token 的消耗。这个数字在单次实验中看起来不大,但在日均处理上千次请求的生产环境中,就是一笔不容忽视的账单。
3. 法律合规的成本。 大模型的训练数据中包含哪些版权材料?模型生成的内容如果公开发布,是否存在著作权纠纷的风险?如果你用大模型处理用户数据,是否符合 GDPR(欧盟《通用数据保护条例》)或中国的《个人信息保护法》的要求?这些问题如果不在项目启动前做功课,事后补救的成本会高很多。
任务架构设计完成之后,你应该产出一份不超过两页纸的文档,包含以下内容:
| 要素 | 说明 | 示例 |
|---|---|---|
| 任务模式 | 问答/生成/分析/操作(可多选) | 分析 + 操作(合同审查并触发审批流) |
| 输入类型 | 文本/图像/音频/视频/结构化数据 | 文本(合同原文)+ 图像(签章页扫描) |
| 输出类型 | 同上 | 结构化 JSON(审查结论)+ 文本(修改建议) |
| 输入格式约束 | 各类型的具体要求 | PDF 文本层可提取,图片 2048px 以内 |
| 输出格式规范 | schema 定义和质量门禁 | JSON schema v1.2,关键字段准确率 ≥ 95% |
| 时间指标 | 单任务延迟 + 整体吞吐 | 单合同审查 ≤ 60s,日处理 ≥ 500 份 |
| 人力指标 | 替代率 + 增强率 | 替代 70% 的初审工作量,法务复核效率提升 3× |
| 成本预算 | 月度 Token 预算 + 工程投入 | Token ≤ $500/月,前置工程投入 2 人月 |
这份文档不是用来"归档"的。它是后续所有架构设计的输入——知识架构需要根据任务模式来确定知识库的构建方向,模型架构需要根据输入输出类型来选型,推理架构需要根据安全需求来设计熔断和兜底。一句话:任务架构定义了"做什么",后面的五个子架构解决的是"怎么做"。
下一节:10.2 六大子架构:知识架构 —— 明确了任务目标之后,大模型从哪里获取完成任务所需的知识?
10.2 六大子架构:知识架构
在上一节我们谈到,大模型应用的起点是明确任务目标。任务一旦确定,紧接着要问的一个问题是:要让大模型完成这个任务,它需要知道什么?
大模型在预训练阶段已经接触了海量资料,参数规模越大的模型,"见过"的东西越多。但再大的模型,面对人类知识的总量依然是九牛一毛。预训练数据能覆盖的主要是通用知识——那些在互联网上高频出现的事实和模式。而你的业务场景中真正关键的东西,往往是预训练数据里少有的:内部业务流程、私有术语体系、行业经验、产品规格说明、安全规范……
这就是为什么在任务架构之后,你需要做的第二件事是知识架构设计。它的核心问题是:
我的应用需要哪些知识?这些知识在哪?怎么把它们交到模型手里?
大模型时代知识工程的本质已经变了。过去知识工程的载体是"自然语言文档"——知识沉淀为 Wiki、手册、SOP 文档,然后靠人类阅读和记忆来使用。现在知识工程的载体正在转向"可执行的语义逻辑"——知识需要被结构化为模型可以直接检索、理解和运用的形式。这不是一个简单的"把文档丢给模型"的过程,而是一个需要系统化设计的过程。
10.2.1 知识的收集
知识收集是大模型应用启动后第一项"容易做但不容易做好"的工作。它不难理解——就是找资料——但真正做起来,你会发现你到底需要什么、去哪找、找到以后怎么判断质量,每一个环节都有门道。
有形知识:为你准备好的数字化资源
大模型诞生于数据基础设施高度成熟的时代。企业多年的信息化建设已经积累了大量的数字化资产——数据库、日志、文档系统、接口服务。这些都是"有形知识",它们已经以某种结构化或半结构化的形式存在。
整理有形知识时,最容易被忽略的一步是:先查有没有已经服务化的知识。
这句话的意思是:别一上来就想着自己扒数据、写解析器。今天围绕大模型已经形成了一个活跃的工具生态。MCP(Model Context Protocol)平台上有大量现成的数据连接器,SKILL 平台上有封装好的专业能力模块。这些"加工好的知识"可以直接接入你的应用。你花半天调研 MCP 市场上有没有可用的连接器,可能比你花两周自己写一个 PDF 解析器更划算。
无形知识:藏在人身上的经验
比有形知识更难处理的,是那些还没有被数字化的经验——我们称之为"无形知识"。
我亲身参与过一个防溺水监控项目,这个案例很能说明无形知识的挑战有多棘手。项目的核心问题是:
溺水者在水里是什么样子?
你看,这个问题听起来简单,但答案是:没有现成的数据。 溺水是小概率事件,没有哪个泳池会积累大量溺水视频。而且真正的溺水不像影视剧里那样挣扎呼救——溺水者往往悄无声息,嘴巴在水平面上下交替,手臂本能地横展,整个过程非常隐蔽。这种特征只存在于见过溺水、并成功实施过救援的救生员的经验之中。更麻烦的是,救援过程高度紧张,救生员事后甚至无法完整回忆当时看到的关键信号。
这种场景下,知识的收集就不再是"找人要资料",而是需要一套专门的方法来从人的经验中提取可用信息。这往往需要技术人员和领域专家密切配合,通过深度访谈、场景还原、反复细化等方式,把隐性的经验转化为可以规则化的知识。
无形知识的收集考验的不是技术功底,而是和人打交道的能力。这在本书第 11 章 11.1 节会以溺水识别项目为例,详细讨论与领域专家协作的系统方法。
10.2.2 知识载体的识别与处理
收集到了什么知识是一回事,这些知识以什么形态存在是另一回事。载体的不同直接决定你需要准备什么样的处理工具链。提前识别知识载体,可以避免"数据拿回来才发现根本没工具能读"的尴尬。
大模型应用中常见的知识载体及其处理方式:
| 载体类型 | 典型场景 | 处理方式 |
|---|---|---|
| 纯文本 | Word 文档、Markdown 文件、TXT 日志 | 直接可读,无需额外处理,但需要清洗格式和去除噪音 |
| 技术手册、合同文件、研究报告 | 详见 10.2.4 的数据化转换流水线 | |
| 图片 | 扫描件、现场照片、设计图纸 | 通过 OCR 提取文字;如涉及图像语义(如"这张图显示管路破损"),需要多模态模型直接理解 |
| 音频 | 会议录音、客服对话、培训讲解 | 使用语音识别模型(ASR)转录为文本 |
| 视频 | 操作演示、监控录像、教学视频 | 同时涉及语音转文字和关键帧提取,通常需要多模态模型辅助 |
| 结构化数据 | 数据库表、API 返回的 JSON、CSV 报表 | 可直接编入提示词或用于生成微调数据,处理成本最低 |
这个表的意义不在于罗列——它提醒你,在知识收集阶段就同步进行载体盘点,可以让后续的数据架构设计更有针对性。举例来说,如果你的核心知识大量存在于会议录音和手写笔记中,你就知道 ASR 和 OCR 是必须准备的环节,而不是等数据到了以后再临时找工具。
10.2.3 知识分类:按可数字化程度分层
将收集到的所有知识摊开看,自然浮现一个问题:这些知识的"可用性"是不一样的。有的可以直接喂给模型,有的需要处理,有的甚至需要重新建模。我们可以按可数字化程度将知识分为三层:
第一层:可直接数字化的知识。
这类知识天生就是数字化形式——数据库里的记录、已有的 API 接口、结构化的配置信息。你只需要选择、清洗、组装即可。这是"成本最低"的知识,应该优先利用。判断标准很简单:你能否 5 分钟内写出一条查询或导出命令拿到它?
第二层:需要工具辅助才能数字化的知识。
包括扫描版 PDF、会议录音、手写笔记、监控视频等。它们记录着信息,但信息的格式不能被模型直接消费。你需要准备对应的工具链——OCR、ASR、文档解析器等——把它们变成可读的文本或结构化数据。判断标准:数据确实存在,但格式不对——你需要跑一个转换工具才能用。
第三层:需要建立模型才能数字化的知识。
这是最高层级的挑战。这类知识以"经验""直觉""判断力"的形式存在于人的头脑中,没有现成的文字记录。比如老工程师"一听声音就知道电机有问题"的直觉,或者资深医生看影像的"第六感"。要数字化这类知识,你需要设计专门的知识提取流程——专家访谈、病例复盘、对抗性测试等——本身就在"建立一个模型"。判断标准:你需要找一个人坐下来聊完,才能把规则写成可以执行的条件。
这三层的划分直接影响你的资源投入。如果你花了大量精力去做"需要建立模型"的知识数字化,但第一层第二层的知识还没整理好,那就是典型的投入错配。
10.2.4 知识的数据化转换
知识不会自动变成模型能消费的数据。在收集和分类之后,需要执行数据化转换——将知识整理成标准化的、可被检索和使用的数据形态。
对于已经数字化的知识(第一层),这一步的重点是格式统一和语义清洗。不同来源的数据格式各异、质量参差不齐,需要你制定统一的规范。比如所有文档统一为 Markdown 格式,所有表格统一字段命名规则,所有接口数据去除冗余字段。
对于需要工具辅助的知识(第二层),工具选型已在 10.2.2 节覆盖。这里强调的是一个容易被忽略的环节:质量验证和流水线设计——不是"跑一遍工具就完事了",而是要建立从原始数据到可用数据的完整流程。
具体来说,你需要关注两点:
质量验证:OCR、ASR 等工具的识别精度受实际数据质量影响很大。比如同一个 OCR 引擎,处理清晰扫描件和模糊手写体的准确率可能相差 30% 以上。在投入全部数据前,必须做小样本质量抽检——选取有代表性的样本跑一遍,人工核对准确率,确认达到下游任务的容错标准后再全量处理。
流水线设计:数据化转换通常不是一步完成的,而是一条多节点流水线。以扫描版 PDF 为例,实际的流水线可能是:PDF 拆页 → 图像预处理(去噪、纠偏)→ OCR → 文本后处理(纠错、分段还原)→ 结构化标注。你对每个节点的质量标准和异常处理要心中有数。
对于需要建模的知识(第三层),数据化转换本身就是一个复杂的工程过程——你需要的不是"转换工具",而是"知识提取流程"的完整设计。这涉及:
- 访谈协议设计:你怎么问,以什么方式记录专家的判断过程。
- 标注规范:将专家的判断转化为可标注的标签体系。
- 验证机制:如何确认提取出来的规则与专家真实判断一致。
这里不妨举一个具体的例子:以溺水识别项目来说,访谈协议的关键问题之一可能是——"救生员,从你注意到一个异常情况到决定跳下水,你看到的关键信号按时间顺序是什么?"这比泛泛地问"你怎么判断有人溺水"能提取出更精细、更可规则化的行为特征序列。这部分的具体方法将在第 11 章 11.1 节以溺水项目为例详细展开。
一句话总结:数据化转换不是一个"找工具"的问题,而是一个"设计流水线"的问题。你要把知识从原始形态,经过一系列有明确标准和检验节点的流程,最终变成能进入模型的数据。
10.2.5 领域专家的协调
知识架构的很多环节离不开一个关键角色:领域专家——那些掌握核心知识和经验的人(也即 10.2.1 节中提到的"领域专家",在本节中我们也曾以"知识专家"称呼,它们是同一类角色)。如何高效地与专家合作,是知识架构设计中的一个非技术但至关重要的技能。
人类专家:合作不只是"问"
和人类专家打交道,很多技术人员的默认做法是"约个会,问几个问题,记下来"。但实际效果往往很差:
- 专家的回答是零散的、碎片化的,需要你来拼接
- 专家说出来的和他们实际做的可能不一致——因为很多判断已经内化为本能
- 专家不一定能用你需要的术语描述知识
高效的专家合作需要你做好三件事:
- 提前准备结构化问题清单。 不是"请介绍一下您的工作",而是"在处理 X 类情况时,您的第一步判断依据是什么?如果 Y 信号出现,您会排除还是保留初始判断?" 好的问题本身就是知识提取的工具。
- 提供友好的协作界面。 专家不是程序员,你需要为他们设计低门槛的知识输入工具——比如交互式表格、标注工具、甚至语音输入。
- 做自己的功课。 约专家之前,你已经把能自学的部分吃透。专家时间宝贵,不要让专家回答"Google 能回答的问题"。
关于与人类专家打交道的系统方法,本书第 11 章 11.1 节会以溺水识别项目为例,进行更深入的讨论。
数字专家:大模型作为知识来源
除了人类领域专家,你还有另一个"专家":超大模型本身。
"知识蒸馏"这个词你可能不陌生,但这里想强调的是:把超大模型当作知识来源是一个投入产出比极高的策略。如果你需要整理某个领域的知识体系(比如"光伏组件的常见故障类型和排查步骤"),你可以:
- 先让 Claude 或 GPT-4 级别的模型生成一个初版知识框架
- 然后拿这个框架去和人类领域专家确认、修正、补充
这比你从零开始问专家"光伏组件有哪些故障类型"要高效得多。超大模型给出的答案可能不够精准、需要交叉验证,但它在建立知识骨架上是超过人类速度的。
10.2.6 知识的生命周期管理
知识不是一块石头——有些知识常年不变,有些知识每个月都在更新。在知识架构设计阶段,你必须把知识的时效性纳入考量,因为这直接决定你怎么把知识注入到模型中。
知识可以分为两大类:
静态知识——不会随时间变化的知识。典型的例子:
- 公式和定理(如欧姆定律、热力学公式)
- 语法规则和标准协议规范
- 已完结事件的描述(如"2023年某产品线的最终决算数据")
静态知识的处理策略相对简单:通过模型微调固化到模型中。 微调让模型把这些知识"内化"为自身参数的一部分,后续使用时不需要额外检索,推理效率最高。
动态知识——会周期性变化的知识。典型的例子:
- 产品价格和促销规则(变化周期:天级)
- 法律法规的修订(变化周期:月级到年级)
- 行业标准和最佳实践(变化周期:月级到年级)
- 组织架构和人员信息(变化周期:周级到月级)
动态知识的处理要分策略:
短更新周期(天级/周级)的知识:采用提示词注入的方式提交给模型。每次推理时将最新知识嵌入到提示词上下文中,查询完成后知识即被"消费"。当这类知识在较长时间内被高频稳定使用后,可以将其中常用且已稳定的部分提取出来,通过微调固化——这样就避免了每次推理都反复传递,提高了效率。
长周期但重要的知识(月级/年级):可以定期微调。比如每季度将最新版本的知识融入微调数据集,重新训练模型。这种方式在保证知识时效性的同时,也兼顾了推理性能。
这里的关键判断是:按变化频率来决定注入方式,而不是二选一。 检索增强的方案(如通过外部知识库检索将最新信息嵌入提示词)和微调不是互斥的选项——它们服务于不同生命周期的知识,在工程实践中往往是"两者都要,各司其职"。
10.2.7 知识的保密性:决定架构的一票
最后一个经常被低估但影响深远的问题:你的知识有没有保密要求?
这个看似简单的分类,实际上对大模型应用的架构有"一票否决"级别的决定力。
如果你的知识不含保密属性,你可以在架构选择上走最轻量的路线:使用公共模型推理 API(如 OpenAI、DeepSeek 的 API),使用云服务商的 RAG 服务,数据流转路径简单,建设成本低。
但如果你的知识具有严格的保密属性(如银行内部风控规则、军事领域的操作规程、企业的核心工艺参数),情况就完全不同了:
- 你不能使用公共模型推理服务——数据不能在服务商的服务器上停留
- 你不能使用公共 RAG 平台——知识片段不能上传到第三方向量数据库
- 你可能需要私有化部署模型,自己搭建推理服务
- 你可能需要自己实现完整的 RAG 管线——从文档处理、向量嵌入到检索生成,每一层都必须在自己控制的环境中运行
这意味着什么?意味着知识的保密性不是一个"后续再考虑"的出入问题,而是在架构设计阶段就必须回答的问题。 因为"需要私有化部署"这件事一旦确定,你的应用架构会比"使用公共 API"的方案复杂一到两个数量级。
建议你在知识架构设计的最后一步,为所有涉密知识建一张简单的清单:
| 知识项 | 保密等级 | 影响 |
|---|---|---|
| 用户个人信息 | 高 | 不能使用第三方推理服务,需要数据脱敏 |
| 核心工艺流程 | 极高 | 必须全链路私有化部署 |
| 公开行业标准 | 无 | 无限制 |
这张清单会成为后续模型架构、推理架构选型的基础输入。
知识架构设计完成了。你知道了需要什么知识、它们在哪、以什么形式存在、怎么变成数据、谁来提供、它们会变化多久、以及有没有保密要求。但收集到的知识本身不能直接被模型使用——你需要把它们组织成一种模型能高效消费的格式。这就是下一节"数据架构"要解决的问题。
10.3 六大子架构:数据架构
知识架构解决了"知识从哪里来、怎么管"的问题,但光有知识还不够——大模型不能直接消化你的 MySQL 表、PDF 文档或 Markdown 笔记。数据架构要做的,就是把已经整理好的知识,转化成大模型能够理解、能够学习、能够使用的数据形态。同时,大模型吐出来的结果也不一定是你最终要交付给用户的样子——数据架构还要负责输出端的格式化和合成。
简单说,数据架构管两条线:进模型之前的数据准备,和出模型之后的数据处理。
本节核心问题:什么样的数据可以喂给大模型?喂进去的数据应该长什么样子?大模型输出的数据又该怎么加工成最终结果?
10.3.1 设计数据格式
第 10.2 节产出的知识,虽然已经有了结构,但通常是面向人类阅读或数据库存储的,不是面向大模型消费的。在数据架构中,你要做的第一件事就是为知识设计适合大模型的"数据格式"。
这个过程不是简单的格式转换,而是一个包含清洗、存储、管理和接入的完整工程链条。
数据清洗:剔除噪音,保留信号
知识库里不是每一条信息都有用。过时的记录、冗余的描述、不一致的标注,这些东西喂给大模型不仅浪费上下文窗口,还可能导致模型产生错误的关联。数据清洗的目标很明确:把无用的部分剔除,把有用的部分精炼。
举个例子:假设你在给一个客服系统做 RAG(检索增强生成),知识库里有十年的工单数据。十年前的产品早就下线了,相关的工单记录不仅没用,还可能在检索时被命中,干扰模型的回答。清洗这一步就要把这些过期数据清理掉。
存储工具的选择:SQL 还是 NoSQL?
清洗后的数据需要存起来。传统应用架构里的 SQL 和 NoSQL 数据库在这里都可以用,但选型逻辑不太一样——你的决策不是"哪种数据库更快",而是"哪种存储方式更适合大模型的消费模式"。
- 结构化知识(如产品参数表、用户画像特征):适合放在关系型数据库里,通过 SQL 精确查询。比如你要让模型回答"这款手机的内存是多少",从
product_specs表里查一行就能拿到。 - 半结构化/非结构化知识(如文档片段、FAQ 条目):更适合放在向量数据库或文档数据库里。因为模型不是通过精确字段名来检索的,而是通过语义相似度——"这款手机配置怎么样"和"这款手机内存是多少"在语义上是相关的,但 SQL 查不出来。
存储格式的设计:为检索而优化
同样的知识,存成不同的格式,检索效果天差地别。以 RAG 为例,你把一整篇文档切成 512 token 的 chunk 还是 1024 token 的 chunk,检索命中率可能差 20% 以上。这不是随便切的——长短 chunk 各有利弊:长 chunk 保留了更完整的上下文,但引入的噪音也更多,检索精度会下降;短 chunk 语义聚焦、检索更精准,但如果切到了句子中间,完整语义就被打断了。你需要根据文档的结构(段落、标题、列表)和模型的最佳编码窗口来设计分块策略,在完整性和精准性之间找到平衡。
此外,每条数据的元信息(metadata)也非常关键。metadata 不只是"这条数据是干什么的",它还是检索时的过滤器和排序依据。比如:
- 时间戳:优先检索最新的文档
- 来源:可信来源加权更高
- 标签:按主题范围筛选
数据管理工具:知识是活的
知识不是写一次就完事的。产品更新了,FAQ 要改;法规变了,政策文档要更新。你需要一套数据管理工具来做增、删、改、查——这里的"管理"不是指数据库自带的 SQL 客户端,而是面向知识运营人员的界面或 API。好的数据管理工具让运营人员改一条 FAQ 就能立刻生效——更新的文本自动向量化,新向量替换旧向量,用户下次提问得到的就是最新的答案——不需要重新跑一遍整个 pipeline。
数据接口:推还是拉?
如果你的知识已经存在于现有的业务系统中(比如 CRM、工单系统、产品数据库),那你不需要把数据复制一份——可以通过数据接口从这些系统中抽取。根据数据的更新频率,有两种策略:
- 预先采集:对低更新频率的数据(如产品目录、公司介绍),可以定时批量导入向量库。这种方式实现简单,成本低。
- 需要时采集:对高更新频率的数据(如实时库存、最新公告),则在模型需要时通过接口实时拉取。这种方式保证数据新鲜,但对接口的响应速度和可用性要求高。
10.3.2 提交给模型的数据
数据准备好了,接下来要决定怎么提交给模型。总的来说,提交给模型的数据走两条路:微调数据和提示词中的数据。这两条路的选择,本质上取决于一个核心决策变量——数据的更新频率。
微调用数据:把知识"写进"模型
微调(Fine-tuning)是在预训练模型的基础上,用特定领域的数据继续训练,让模型"内化"这些知识。它适合的是低更新频率、高使用频率的数据。
为什么是这个组合?因为微调是有成本的:你需要准备数据集、跑训练、评估效果、部署新模型。如果数据三天两头变,你微调的频率跟不上数据的变化。但如果数据稳定(比如公司内部的技术规范、行业术语、标准回复话术),而模型在这些问题上频繁被调用,那微调就非常划算——把知识写进模型权重里,每次推理时不需要额外检索,速度快且结果一致。
微调的成本量级:一次典型的领域微调通常需要数百到数千条高质量标注样本,以及数小时的 GPU 训练时间——这与"零成本的提示词注入"有本质区别。如果你的数据每季度才更新一次,这个成本是完全可以接受的;但如果每周都在变,微调就追不上了。
举个例子:一家律师事务所把内部的法律文书写作规范通过微调注入模型,之后律师用这个模型起草文书时,格式、措辞、引用规范自动对齐内部标准——不需要在每次调用时把规范塞进提示词。
提示词中的数据:把知识"带在身边"
提示词中直接注入数据(也称为 In-Context Learning),适合的是高更新频率数据、以及需要检索的预制数据。
具体来说,有三类:
动态数据:数据更新频繁,微调跟不上。比如当天的股价、最新的新闻、正在进行的活动信息。这些数据必须在每次调用时实时拉取,直接写入提示词。
预制数据(向量化数据):数据量太大,全部塞进提示词不现实。通过向量化 + 相似度检索,只把最相关的那几条放进提示词。RAG 就是这个模式最典型的实现。
外部 MCP 数据:如果数据本来就在某个外部系统里,并且这个系统提供了标准化的接口(如 MCP 协议),那模型可以在推理过程中动态调用这些接口获取数据——甚至连提示词里都不需要写进去。
一个关键判断:微调和提示词注入不是二选一。实际项目中,高频运行的稳定知识走微调,需要动态更新的知识走提示词注入,两者配合使用才是最优解。
10.3.3 数据的服务化封装
上一节提到 MCP 数据引入,这里展开说清楚:数据的服务化封装是什么,为什么重要。
跨章提示:MCP 的完整机制见第 7 章「MCP 协议:大模型的"神经突触"」,这里快速回顾核心要点。MCP 本质上是标准化的工具调用协议——大模型通过 MCP 客户端向服务端发起请求,服务端执行业务逻辑后返回结构化结果。将数据资源包装成 MCP 工具(如
query_orders封装 MySQL 查询、get_cache封装 Redis 读取),模型在推理时就能自主决定调用什么数据。下面我们聚焦它在数据架构中的实际应用。
设想这样一个场景:你的大模型应用需要查用户的订单状态。订单数据存在 MySQL 里,订单表结构复杂,表之间有外键关联。你当然可以在每次调用时把所有相关表的数据都查出来,拼成文本塞进提示词——但这会带来两个问题:第一,数据量可能很大,超出上下文窗口;第二,模型可能需要的不是"所有数据",而是在推理中动态决定的某种特定查询(比如"查该用户最近三笔已完成的订单")。
更好的方式是:把数据封装成一个服务,让模型自己去"调用"。
与传统 API 调用的区别:传统模式下,后端代码决定"查什么、什么时候查"——模型回答问题的过程中,后端预先写好 SQL 逻辑,查完数据拼进提示词,再让模型回答。MCP 模式下,模型在推理过程中自主决定要调用什么工具来拿什么数据——后端不预设查询逻辑,只提供工具。
这也是为什么数据架构的设计要走在推理架构前面:你先定义好有哪些数据资源、怎么封装成服务,推理架构才能设计模型如何编排调用这些服务。实际上,前文 10.3.2 提到的 MCP 方式就是这种服务化封装的实例——query_orders 工具封装的正是在 MySQL 中的订单查询逻辑,模型在推理过程中自主决定是否调用它、什么时候调用它。
10.3.4 大模型输出数据的处理
很多团队把精力都花在"怎么把数据喂进模型"上,却忽略了另一头——模型吐出来的结果怎么处理。实际上,输出端的数据处理同样关键,因为它直接决定了用户看到什么。
输出格式的约束
大模型的输出本质上是概率性的文本生成。即使你在提示词里写了"输出 JSON 格式",模型也不一定每次都严格遵守——少个引号、多个逗号、字段名拼错,这些在生产环境中都是真实发生过的问题。
因此,输出格式的处理通常需要两层保障:
- 软约束:在提示词中明确格式要求,包括字段定义、数据类型、示例。这一层解决 80% 的问题。
- 硬约束:在代码层对输出做格式校验和修复。以下是一个典型的防御层实现:
python
import json
class OutputFormatError(Exception):
"""模型输出不符合约定格式,抛给上层触发重试"""
def parse_model_output(raw: str) -> dict:
try:
return json.loads(raw)
except json.JSONDecodeError:
# 常见修复:去除代码块标记、尾随逗号
cleaned = raw.strip().removeprefix("```json").removesuffix("```").strip()
try:
return json.loads(cleaned)
except json.JSONDecodeError:
raise OutputFormatError("模型输出无法解析为 JSON,触发重试")这不是唯一方案,但它展示了硬约束的核心思路:不是假设模型输出一定合法,而是准备好它不合法的兜底策略。
输出数据的合成与转换
有时候,最终交付给用户的结果不是一次模型调用就能产出的。常见的复杂场景包括:
- 多个模型输出需要合并(比如一个模型做意图识别,另一个做内容生成,最后要把两者的结果组合起来)
- 中间步骤需要缓存(多步推理中,上一步的结果作为下一步的输入,需要一个临时存储点)
- 最终结果需要格式转换(比如模型输出 JSON,用户需要 Markdown 表格)
这些需求意味着你在做数据架构设计时,不能只考虑"输入端的数据长什么样",还要规划输出端的数据处理流水线。
一个经验法则:在系统设计初期就把输出处理纳入数据架构的考量。见过太多项目上线后才发现,模型返回的 JSON 在 95% 的情况下合法,剩下 5% 导致线上报错——而这个问题如果在架构设计阶段就规划了格式校验层,根本不会出现。
数据架构的职责可以总结为一句话:让知识以模型能消费的形式进入,让结果以用户能使用的方式出来。 下一节,我们将进入六大子架构中的模型架构——当数据准备好了,该选择什么样的模型来承载这些数据?
10.4 六大子架构:能力架构
数据架构解决了"数据怎么进、怎么出"的问题,模型架构解决的是"谁来消费这些数据"的问题。但在这两者之间,还藏着一个容易被忽略的环节——大模型不是在一个封闭世界里运行,它需要跟外部系统打交道。
比如,用户问"帮我查一下今天北京的天气",模型只有维基百科断在 2024 年的知识是不够的,它需要去调一个天气 API。用户说"帮我把这段内容存到我的笔记里",模型得知道笔记系统在哪里、怎么往里写东西。用户说"帮我发一封邮件给张三",模型要把一段自然语言指令转换成 SMTP 协议的调用。
能力架构要解决的就是这个问题:大模型如何操作外部系统?
能力架构是六个子架构中的"可选项"——如果你的大模型应用只是做纯文本问答(比如一个离线文档问答机器人),可能不需要这一层。但只要你的应用需要跟数据库、API、文件系统、消息系统等外部系统交互,就必须设计能力架构。
本节核心问题:模型怎么知道要操作哪个外部系统?操作的参数谁来填?模型输出的结果怎么转成外部系统能执行的动作?
10.4.1 能力架构的两条主线
能力架构的设计,本质上是在回答两个问题:
- 外部系统的操作接口:外部系统(数据库、API、文件系统等)怎么暴露给模型?模型怎么"看到"这些接口并知道什么时候调用它们?
- 模型输出到指令的转换:模型输出的自然语言结果,怎么变成外部系统可以执行的具体指令?
这两个问题不是各自独立的——它们像齿轮一样啮合在一起。接口设计决定了模型能"看见"什么操作,而指令转换决定了模型"说了"之后谁来执行、怎么执行。
用类比来理解:如果把大模型应用比作一个人在下命令,能力架构就是这个人的"手和脚"。模型是大脑,负责思考和决策;能力架构是执行系统,负责把决策变成对真实世界的作用。没有手脚的大脑,只能想,不能做。
10.4.2 外部系统的操作接口:让模型"看见"世界
先看第一件事:外部系统怎么暴露给模型。现在业界主要有两条技术路线:MCP 化和提示词约束。两条路线各有优劣,我们逐一分析。
10.4.2.1 MCP 化:把外部系统封装成标准工具
MCP(Model Context Protocol,模型上下文协议)是一种将外部系统标准化封装为"工具"的协议。它的核心思想是:每一类外部操作(查数据库、调 API、读文件)都被封装成一个标准化的工具描述,包括工具名称、功能说明、参数 schema、返回值格式。模型在推理过程中自主决定"我现在需要调用哪个工具,用什么参数",然后执行方去实际调用并把结果返回给模型。
MCP 带来的好处是结构化的:
第一,描述与实现分离。 你不需要在提示词里反复写"你可以调用 get_weather 函数,参数是 city 和 date"。工具的元信息(名称、参数、类型约束)以结构化的 JSON Schema 定义,模型能精确理解每个参数的类型和约束,不会出现"city 写成了 ctiy"这种拼写错误导致的调用失败。
第二,参数类型校验前置。 MCP 定义的参数 schema 在调用前就可以做类型校验——参数类型不对?必填参数缺失?在请求发出去之前就能拦截,不用等到 API 返回 400 才知道出错了。这种"前置校验"在生产环境中非常关键,因为每次无效调用都是在浪费推理 token 和接口延迟。
第三,工具复用和生态效应。 一个封装好的 MCP 服务可以被多个应用共享。比如你用 MCP 封装了一个"企业微信消息发送"的工具,你的客服系统可以用它给用户发消息,你的告警系统也可以用同一个工具给运维发通知。这种复用性降低的是整体的开发成本,不是某个单点应用的。
第四,安全边界清晰。 因为工具是显式定义和注册的,你可以精确控制模型能操作哪些外部系统、不能操作哪些。模型只能调用你注册的工具,不存在"模型自己猜了一个 API 地址然后去调用"的可能。
一个简化的 MCP 工具描述示例:
json
{
"name": "send_email",
"description": "发送一封邮件",
"parameters": {
"type": "object",
"properties": {
"to": {
"type": "string",
"description": "收件人邮箱地址"
},
"subject": {
"type": "string",
"description": "邮件主题"
},
"body": {
"type": "string",
"description": "邮件正文"
}
},
"required": ["to", "subject", "body"]
}
}模型看到这个工具描述后,当用户说"帮我给张三发一封邮件说明天会议取消",模型会自动判断出需要调用 send_email 工具,参数 to 需要从上下文(可能是联系人数据库)获取张三的邮箱,subject 提取为"会议取消通知"或类似的主题,body 基于用户原文生成正式邮件正文。
10.4.2.2 提示词约束:用自然语言定义边界
另一种思路更直接:不引入 MCP 协议层,而是通过提示词告诉模型"你的输出应该满足什么格式",然后由应用层代码解析模型的输出并执行对应的操作。我把这种方式称为提示词约束模式。
提示词约束的做法通常是:
- 在系统提示词中描述所有可用的操作、参数格式
- 要求模型按照约定的格式(如 JSON)输出操作指令
- 应用层代码解析这个 JSON,执行操作
举个例子,系统提示词可以这样写:
你可以执行以下操作。当你需要执行某个操作时,在回复末尾以 JSON 格式输出:
{
"action": "send_email" | "query_database" | "call_api",
"params": { ... }
}
可用的操作:
- send_email: 发送邮件。参数:to(收件人), subject(主题), body(正文)
- query_database: 查询数据库。参数:sql(SQL 语句)
- call_api: 调用 HTTP API。参数:url(接口地址), method(GET/POST), body(请求体,可选)应用层代码流程:
python
import json
def handle_model_output(raw_output: str) -> str:
"""解析模型输出,提取操作指令并执行"""
# 尝试提取末尾的 JSON 操作指令
try:
# 假设模型按约定在最后一段输出 JSON
# 实际实现中需要更鲁棒的提取逻辑
if "```json" in raw_output:
json_str = raw_output.split("```json")[-1].split("```")[0]
action = json.loads(json_str)
else:
# 尝试直接解析最后一段
lines = raw_output.strip().split("\n")
action = json.loads(lines[-1])
except (json.JSONDecodeError, IndexError):
# 没有操作指令,直接返回模型的文本回复
return raw_output
# 根据 action 类型分发执行
if action.get("action") == "send_email":
result = send_email(**action.get("params", {}))
return f"邮件发送结果:{result}"
elif action.get("action") == "query_database":
result = query_database(action.get("params", {}).get("sql"))
return f"查询结果:{result}"
elif action.get("action") == "call_api":
result = call_api(**action.get("params", {}))
return f"API 调用结果:{result}"
return raw_output这种方式的优势很直观:极低的接入成本。不需要搭建 MCP 服务端、不需要理解 MCP 协议规范、不需要额外的中间件。你只需要在现有的应用代码里加一层 JSON 解析逻辑,就能让模型"操作"外部系统。
对于功能简单、操作类型有限的场景(比如只有一两个外部调用),提示词约束模式确实比引入完整的 MCP 体系更轻量、更快上线。没有那么重的工程负担,出问题了也容易排查——你直接看模型输出的 JSON 长什么样就行。
10.4.2.3 MCP 化 vs 提示词约束:怎么选?
两种路线没有绝对的好坏,选哪种取决于你的场景。我用一个对比表来梳理关键差异:
| 维度 | MCP 化 | 提示词约束 |
|---|---|---|
| 接入成本 | 需要搭建 MCP 服务端,定义工具 schema | 只需要写提示词 + 应用层解析代码 |
| 操作可靠性 | 参数类型前置校验,调用失败率低 | 依赖模型的输出格式稳定性,可能输出 JSON 解析错误 |
| 工具数量 | 适合多工具场景(5+),标准化管理 | 适合 1-3 个简单操作,多了提示词臃肿 |
| 参数复杂度 | 支持嵌套对象、数组、枚举等复杂类型 | 复杂参数在提示词中描述困难,模型容易出错 |
| 安全性 | 白名单式工具注册,模型只能调用已注册工具 | 依赖应用层代码做权限控制,容易遗漏 |
| 多应用复用 | 一次封装,多个应用共享 | 每个应用独立维护提示词和解析逻辑 |
| 生态兼容性 | 与支持 MCP 的平台(如 Claude Desktop、Cursor 等)直接对接 | 完全自定义,无生态兼容需求 |
| 调试难度 | 问题可能在协议层、传输层、执行层,排查链长 | 模型输出直接可见,排查简单 |
选择建议:
- 先上提示词约束的情况:你的应用只有 1-2 个简单的操作需求,团队里没有 MCP 经验,希望快速验证想法。先用提示词把东西跑起来,确认方向对了再考虑是否 MCP 化。
- 可以考虑走向 MCP 化的情况:
- 操作数量增长到 5 个以上,提示词越来越长,维护成本开始上升
- 参数结构复杂(嵌套对象、条件必填等),模型频繁输出格式错误
- 同一个工具需要在多个应用间复用
- 对接 MCP 兼容平台(比如你想让动作在 Claude Desktop 里也能用)
一个重要的事实是:提示词约束和 MCP 化不是互斥的。在同一个应用里,核心的高频操作可以用 MCP 封装(保证稳定性和复用性),临时的低频操作仍可以用提示词约束实现(成本最低)。架构设计不需要追求"全 MCP 化",需要的是一种务实的组合策略。
10.4.3 模型输出到指令的转换:谁说"做什么"变成"怎么做"
接口设计回答了"模型怎么看到外部系统",但还有一个重要的环节:模型输出的结果,怎么变成外部系统可以执行的指令?
这个问题比看起来更复杂。因为模型输出的是一段自然语言或结构化 JSON,而外部系统需要的是一段具体的程序调用。这中间存在一个"翻译层"。
翻译层要做三件事:
第一,意图确认。 模型说"我需要查天气",翻译层需要确认:查哪个城市的天气?查今天还是未来七天?温度单位用摄氏度还是华氏度?这些信息可能在模型输出的参数里有,也可能不全——不全的时候,翻译层不能瞎填,也不能直接报错崩溃,而是需要有一套补全或追问机制。
第二,参数映射。 模型输出的参数名和外部 API 期望的参数名可能不一样。模型可能输出 {"city": "北京"},但天气 API 的接口要求 {"location": "Beijing", "country": "CN"}。翻译层需要做映射,甚至做值的转换("北京" → "Beijing"、"摄氏度" → "metric")。
第三,执行编排。 一个用户请求可能需要多次外部调用才能完成。"帮我把最近的订单汇总一下发邮件给老板"——首先调订单系统查最近订单,然后把订单列表格式化,最后调邮件系统发送。翻译层需要知道这三步的顺序和依赖关系,而不是把所有调用一起扔出去。
10.4.3.1 意图确认:参数不全怎么办?
最朴素的想法是:参数不全就报错。但这在实际场景中行不通。用户说"帮我查一下天气",你回复"缺少城市参数,请重新输入"——两次下来用户就放弃了。
更合理的设计是分层处理:
模型层面:提示词中明确要求,遇到参数缺失时,模型应该基于上下文推理或主动询问。比如系统提示词可以加一条:"如果用户指令中的操作缺少必要的参数,请主动询问用户需要哪些信息,不要猜测。"
执行层面:对于确实可以安全默认的参数(如天气查询默认查"今天"、默认使用公制单位),翻译层在执行时自动补全,并在返回结果中标注"已使用默认参数"。
多轮对话:对于无法补全的关键参数(如"发邮件"却不知道收件人是谁),翻译层应该触发模型的追问机制——把问题返回给模型,让模型生成一个追问句子发给用户。
10.4.3.2 参数映射:不要写死,用适配器
参数映射不应该写死在业务逻辑里。今天天气 API 的参数叫 location,明天换成另一个天气服务商可能叫 cityName——如果你把映射硬编码在代码里,换一次 API 就要改一次代码。
更好的做法是引入适配器层(Adapter Layer):
python
# 参数映射配置 — 独立于业务逻辑
TOOL_PARAM_MAP = {
"get_weather": {
"city": "location", # 模型输出 city → API 参数 location
"date": "date",
"unit": {
"摄氏度": "metric",
"华氏度": "imperial"
}
}
}
def adapt_params(tool_name: str, model_params: dict) -> dict:
"""将模型输出的参数映射为 API 所需的参数"""
mapping = TOOL_PARAM_MAP.get(tool_name, {})
adapted = {}
for key, value in model_params.items():
target = mapping.get(key, key)
# 枚举映射:key 不变,只翻译值
if isinstance(target, dict):
adapted[key] = target.get(value, value)
else:
adapted[target] = value
return adapted适配器层的好处是:底层 API 换了,只改配置,不改业务逻辑。而且这段配置可以被多个工具调用方复用。
10.4.3.3 执行编排:串行调用还是并行调用?
回到"查订单、汇总、发邮件"的例子。三步之间存在依赖关系:第二步依赖第一步的结果,第三步依赖第二步的结果。翻译层需要用串行编排——一步一步来。
但在另一些场景下,多个外部调用之间没有依赖关系。"帮我查一下北京的天气和今天的 A 股大盘"——查天气和查股市互相独立,可以用并行编排,同时调用两个接口,总延迟取决于最慢的那个,而不是两个延迟之和。
翻译层需要具备编排能力。在 MCP 体系中,这个能力通常由支持 function calling 的推理引擎提供——模型在一次推理中输出多个工具调用,引擎判断依赖关系后自动编排。在提示词约束模式中,这个编排逻辑需要你手动实现。
一个简单的并行编排示例:
python
import concurrent.futures
def execute_operations(operations: list[dict]) -> list[dict]:
"""并行执行无依赖关系的多个操作
注意:call_tool 为假设已实现的工具调用函数。
实际项目中替换为真实的工具调用逻辑。
"""
def execute_one(op):
tool_name = op["action"]
params = adapt_params(tool_name, op["params"])
return call_tool(tool_name, params) # 假设已实现
with concurrent.futures.ThreadPoolExecutor() as executor:
futures = [executor.submit(execute_one, op) for op in operations]
return [f.result() for f in futures]10.4.4 能力架构的设计清单
总结一下,当你需要设计能力架构时,可以按照以下清单逐一确认:
- 操作识别:你的应用需要操作哪些外部系统?(数据库、API、文件系统、消息系统、邮件系统……)
- 接口策略:每个外部系统用什么方式暴露给模型?MCP 封装还是提示词约束?
- 参数设计:每个操作的参数有哪些?哪些是必填的?哪些有默认值?参数类型和约束是什么?
- 转换层:模型输出的参数和外部系统的参数之间怎么映射?映射逻辑放在哪里?
- 编排逻辑:当一次请求需要多次外部调用时,调用的顺序和依赖关系是什么?
- 容错设计:外部调用失败时怎么办?重试几次?超时多久?给用户展示什么?
- 安全边界:哪些操作是模型绝对不能触发的?权限控制在哪个层面(工具注册层、参数校验层、执行层)?
这个清单不是要你在项目初期就全部填满——事实上,你完全可以从最简单的场景开始(一个操作、提示词约束、最基本容错),然后随着应用复杂度增长,逐步丰富能力架构的设计。一个不完美的能力架构胜过没有能力架构,后者意味着你的模型"想到但做不到",对用户的承诺无法兑现。
10.4.5 能力架构与其他子架构的关系
最后,能力架构不是孤立存在的。它与其余四个子架构之间有着紧密的协作关系:
- 与任务架构的关系:任务架构定义了"要做什么",能力架构定义了"能做什么"。如果任务架构要求"发送通知",但能力架构中没有消息系统的操作接口,任务就无法完成。两者需要在设计阶段对齐——任务覆盖的操作,能力架构都要有对应的接口。
- 与知识架构的关系:能力架构需要的操作知识(比如"企微消息发送需要 robot_key 和 chat_id")应该记录在知识架构中。模型在调用工具时可能需要从知识架构获取参数值(比如从联系人知识库中获取收件人的 chat_id)。
- 与数据架构的关系:外部系统操作返回的数据,往往需要经过数据架构的处理(格式化、筛选、合成)才能提交回模型或直接返回给用户。
- 与模型架构的关系:不是所有模型都支持 function calling / 工具调用。你在设计能力架构时,接口策略(MCP vs 提示词约束)会受到所选模型能力的影响。如果模型原生支持 function calling,MCP 化的体验会更好;如果模型只支持纯文本,提示词约束可能是更务实的选择。
能力架构是承上启下的枢纽——它连接着"模型的大脑"和"外部系统的手脚"。设计得好,你的应用行动自如;设计不当,模型处处碰壁。
下一节将聚焦模型架构:在明确了知识、数据、能力之后,我们来选择谁来消费这一切——如何为应用匹配合适的模型(或多模型组合),以及它们以什么方式部署和运行。
10.5 六大子架构:模型架构
前面的知识架构和数据架构,解决的都是"大模型要消费什么"的问题——知识从哪来、怎么整理成数据、数据怎么喂给模型。但还有一个问题我们一直没有正面回答:谁来消费这些数据?(能力架构讨论的是大模型"能调用什么工具",而模型架构要回答的是:这些能力跑在什么模型上。)
不是所有的模型都一样。不同的模型有不同的"知识结构"——有的擅长语言理解,有的擅长图像识别,有的擅长代码生成。即使是同一类模型,不同厂商、不同规模的版本,在处理同一份知识时的表现也可能完全不同。上一节讨论的数据提交策略(微调还是提示词注入)告诉我们,不同的知识需要不同的提交方式——但策略的选择不仅取决于知识本身,还取决于你手头有什么模型可供使用。
这就是模型架构要解决的问题。
本节核心问题:我的应用需要什么类型的模型?这些模型之间的关系是什么?它们以什么形式部署和运行?
模型架构不是什么
在展开模型架构的具体内容之前,有必要先澄清一个常见的误解。
模型架构不是"选一个最好的模型"。如果你只有一个任务,你可以去各模型厂商的排行榜上找出最高分的那一个,选它就行了。但大模型应用很少只有一个任务。一个完整的应用往往需要多个模型协作——一个用来理解用户意图,一个用来检索知识,一个用来生成最终回复,可能还要一个做安全检查。
模型架构设计的本质,是设计一个多模型的"协作系统"。
你要决定的不是"买哪个模型",而是:这个系统里需要几个模型?每个模型负责什么?它们怎么配合?运行在什么地方?
为什么需要多模型协作?
先说一个反直觉的事实:在工程实践中,用一个大模型包揽所有事情,往往是性价比最差的选择。
原因有三:
第一,没有模型是全能的。 大语言模型在文本理解和生成上很强,但遇到图像、音频、视频时,你需要多模态模型——或者专门的视觉/语音模型。即使是纯文本任务,一个模型在格式严谨的代码生成上表现好,不代表它在需要创造力的文案撰写上也同样出色。模型之间天然存在"偏科",就像人类有不同专长一样。
第二,成本不是线性的。 一个大语言模型在处理简单任务时可能"杀鸡用牛刀"——一条"今天天气怎么样"的查询,GPT-4 和 GPT-4o-mini 给出的答案差不多,但成本可能差十倍。如果你的应用流量很大,这种差异会变成真金白银的账单。理性的策略是:简单任务用小模型,复杂任务用大模型,专有任务用专有模型。
第三,不同的任务需要不同的知识基底。 回顾第 10.2 节的知识分类:有些知识是通用的(语言能力、常识推理),这些能力大模型在预训练阶段已经具备了;有些知识是领域专属的(内部的业务规则、行业术语),这些需要通过微调注入模型。如果你用一个通用大模型去处理需要深度领域知识的任务,你不得不在每次调用时通过提示词"临时教育"它——这不仅浪费上下文窗口,还不可靠。更好的做法是:为那些高频的领域专属任务准备一个经过微调的专用模型。
用一个简单的类比:你不会让一个全科医生去做心脏手术,也不会让心脏外科医生去回答普通感冒。医院里有很多科室,每个科室有不同专长的医生,急症先去急诊分诊,然后根据情况转到对应科室。模型架构,就是给你的大模型应用建一个"科室系统"。
模型架构的核心任务
模型架构设计要完成的,大致可以分为四个层次的工作:模型选型、组合策略、运行环境、和演进路径。
模型选型:把需求翻译成模型能力要求
模型选型不是翻排行榜,而是从你的任务需求出发,提取出对模型的能力要求清单。
举个例子,假设你在做一个智能客服系统。拆解一下它的任务链:
| 任务环节 | 需要的能力 | 可能的模型要求 |
|---|---|---|
| 用户意图识别 | 语义理解、意图分类 | 大语言模型(embedding + 分类能力) |
| 知识检索 | 语义匹配、上下文关联 | 大语言模型(embedding 能力) |
| 回答生成 | 自然语言生成、语气控制 | 大语言模型(生成能力) |
| 违规内容检测 | 文本分类、异常检测 | 轻量级专用分类模型或安全检测器 |
你可以看到,四个环节都需要语言模型,但对能力侧重点的要求不一样:意图识别更看重分类精度而不是语言丰富度;回答生成更看重语言流畅度和风格控制;违规检测更看重准确率和低误报——实践中通常采用轻量级专用分类模型(如基于 BERT 的安全检测器),准确性更高、延迟更低。
这意味着你可以为不同环节选择不同的模型,而不是用一个最强大的模型统一处理。意图识别和违规检测可以用规模较小但针对性强的模型,回答生成用规模更大的模型以保证体验。最终的效果可能比用一个大模型统一处理好,而成本更低。
组合策略:模型之间怎么配合
选好了模型,接下来要设计它们怎么配合。组合策略主要有两种模式:
路由模式(Router Pattern)
把不同的任务分发给不同的模型。用户在消息框里输入一句话,系统先判断这是一个闲聊问题还是一个专业问题——闲聊问题交给轻量级模型,专业问题交给重量级模型。路由判断本身可能由另一个轻量级模型完成。
路由模式的核心是分类准确率。如果闲聊问题和专业问题被分错了,用户体验会显著下降——你总不希望问一个技术问题被一个只会寒暄的小模型敷衍。
编排模式(Orchestration Pattern)
多个模型按顺序或条件依次调用,形成一条处理流水线。比如上一节的客服例子:
- 用户输入进入系统
- 模型 A 提取查询意图
- 基于意图,系统检索相关知识(这一步可能是 RAG,不需要模型干预)
- 模型 B 基于检索结果生成回答
- 模型 C 对回答做安全审查
- 通过审查的回答返回给用户
编排模式的关键是错误传播。流水线上每一步的输出是下一步的输入,如果早期环节出错,错误会被放大传播。比如意图识别错了,后续的检索和生成都基于错误的前提,最终的答案很可能完全跑偏。
两种模式不是互斥的——实际项目中往往是混用的:在编排模式的流水线中,某些环节内部使用路由模式做模型分发。换句话说,路由模式解决"谁来处理这个问题",编排模式解决"一个任务怎么接力完成"。
运行环境:模型跑在哪?
在第 10.2 节中我们讨论过保密性对架构的影响。这个问题在模型架构中变成了一个具体的工程决策:
公共推理服务(API 调用):将请求发送到模型提供商的服务器。零运维成本,按量付费。适合数据不涉密、对延迟要求合理的场景。
私有化部署:模型运行在你自己控制的服务器上。需要投入 GPU 算力和运维人力,但数据不离开你的控制范围。如果你在第 10.2 节的知识保密清单中有"高保密等级"的知识项,这就是必须走的路。
两者混合:大部分企业的实际情况。通用场景用公共 API(成本低),敏感场景用自己的部署(数据安全)。比如客服系统对外回复用公共模型,但涉及内部业务流程的诊断工具走私有化部署。
三种方式的具体技术选型,会在 10.5.1 节(模型底座的选择)和 10.5.2 节(模型推理服务模式)中详细展开。
演进路径:模型不是一次性选定的
模型架构设计中最容易被忽视的,是时间维度。
你今天选的模型,半年后可能已经被更新的模型超越了。你今天架构的应用,半年后可能需要接入新的模型类型(比如多模态模型的能力增强了,你希望客服系统也能处理用户发来的截图)。
因此,在模型架构设计时需要考虑切换和升级的成本:
接口抽象:不要让你的应用直接依赖特定模型的 API。在应用层和模型层之间加一层抽象——不管底层是 OpenAI 的 GPT-4 还是开源的 Llama,应用层调用的是统一接口。这样切换模型时只需要改底层适配器,不需要动应用逻辑。
效果基线:在选定模型的同时,建立一套效果测试集。每次考虑替换模型时,跑一遍测试集看效果变化。没有基线的模型切换是盲目的——你不知道新模型是更好还是更差,可能只是"看起来不错"。
微调策略:有些领域的知识是相对稳定的,长期来看通过微调固化到模型中比每次都靠提示词注入更高效。微调的时机、数据准备、评估标准需要提前规划。这一点在 10.5.3 节(模型微调)中会详细讨论。
模型架构与其他子架构的关系
最后,模型架构不是孤立的。它跟前面讨论的四个子架构之间有紧密的咬合关系:
任务架构 → 模型架构:任务架构定义了"要做什么",模型架构要根据是什么,设计相应的模型组合。"先梳理清楚任务和流程,再决定用什么模型" —— 这是基本顺序。
知识架构 → 模型架构:知识架构梳理出了知识的分类和保密要求,模型架构据此决定模型的部署方式。"第 10.2.7 节的知识保密清单('知识的保密性:决定架构的一票'),就是模型架构中部署方式的关键输入。"
数据架构 → 模型架构:数据架构确定了数据的提交策略(微调 vs 提示词注入 vs MCP调用),模型架构根据这些策略来选择和匹配模型。"不是先选好模型再决定怎么喂数据,而是数据怎么喂,决定了需要什么模型。"
能力架构 → 模型架构:能力架构定义了模型能调用哪些外部工具,模型架构需要确保选用的模型具备工具调用能力,并且工具调用的延迟和成本在模型组合的整体预算之内。
这种依赖关系意味着,如果你在模型架构设计过程中发现某些假定站不住脚(比如发现某个关键知识无法通过提示词注入有效传递),你可能需要回溯到前面的子架构进行调整。这是正常的——子架构之间就是迭代咬合的,不是一次写完就定型。
模型架构的总体框架到这里就梳理完了。接下来三节将逐一展开模型架构中三个具体的工程决策:10.5.1 节讨论如何选择模型底座,10.5.2 节分析模型推理服务模式的选择,10.5.3 节深入模型微调的时机和方法。
10.5.1 模型底座的选择
上一节我们讨论了模型架构的整体框架——一个大模型应用往往需要多种模型协同工作。但"选哪些模型"这个问题,在实际工程中比想象中要棘手得多。市面上每天都有新模型发布,评测榜单眼花缭乱,如果跟着热点跑,三个月后你的技术栈可能已经换了三轮。
所以本节不打算罗列"十大最火模型",而是帮你建立一套选型的思考框架。等你面对下一个模型时,可以自己做出判断,而不是等别人告诉你该不该用。
从能力维度看模型分类
大模型发展到 2026 年,形态已经相当多样。从能力维度看,可以大致分为四类:
**大语言模型(LLM)**是最核心的一类。它们以文本为输入输出,能力覆盖理解、推理、生成、代码编写等。代表性模型包括 GPT-4o、Claude 4、DeepSeek-V3、通义千问 Qwen3、GLM-4 等。绝大多数大模型应用的第一步,就是选一个靠谱的 LLM 做底座。
值得注意的一个趋势是"强推理模型"的崛起。以 OpenAI o3/o4、DeepSeek-R1 为代表的推理模型,不再追求"一句话出答案",而是在回答前进行长时间的链式思考(Chain-of-Thought)。这类模型在数学证明、复杂编程、逻辑推理等任务上表现出色,但响应延迟高、成本也显著更贵。如果你的应用以对话生成为主,普通的 LLM 就够了;如果你要处理需要多步推理的复杂任务,推理模型才是正确的选择。
多模态模型可以同时理解文本和图像(部分还支持音频和视频)。GPT-4o、Claude 4、Gemini 2.5、通义千问 Qwen2.5-VL 都属于这一类。它们的典型应用场景包括:文档 OCR 理解(把扫描版 PDF 变成结构化数据)、UI 截图分析、医学影像辅助诊断。一个实用的经验法则是:如果输入中图像信息的占比超过 20%,用多模态模型通常比"图转文再喂 LLM"的方案效果更好,延迟也更低。
图像/视频生成模型的用途是创造视觉内容,而非理解。Midjourney、Stable Diffusion 3、可灵(Kling)、Sora 等都是这一类。在应用架构中,它们通常作为 LLM 的"下游插件"——由 LLM 生成提示词(prompt),交给图像/视频模型生成最终内容。比如一个营销素材生成系统:LLM 理解用户需求并撰写画面描述,然后将描述传给图像/视频模型生成海报或短视频。
语音模型处理语音到文本(ASR)、文本到语音(TTS)和语音到语音的转换。Whisper、CosyVoice、GPT-4o 的语音模式都是代表。如果你的应用涉及语音交互(比如智能客服的语音通话、播客内容生成),语音模型就是必选项。
下表直观展示了这几类模型的关系和适用场景:
表 10-1 大模型能力矩阵
| 语言与推理 | 多模态与语音 | 生成 |
|---|---|---|
| 大语言模型(LLM) · 文本理解 · 推理 · 代码 · 对话 | 多模态模型(Multimodal) · 图文理解 · 视频理解 · 跨模态检索 | 图像 / 视频生成模型 · 图像生成 · 视频生成 · 风格迁移 |
| 强推理模型(Reasoning) · 链式思考 · 数学证明 · 复杂编程 | 语音模型(Voice) · ASR · TTS · 语音对话 | — |
选择模型底座的核心考量
知道有哪些类型的模型还不够,选型时的决策因素才是关键。以下是四个在实际工程中绕不开的维度:
(1)任务匹配度
不是越强的模型越好。你需要根据任务特点来选择。比如:
- 对话生成 → 选对话能力强的 LLM(如 GPT-4o、Claude 4)
- 长文本分析 → 选上下文窗口大的模型(如 Gemini 2.5 的 100 万 Token,或 Qwen3 的 128K)
- 代码生成 → 选代码训练充分的模型(如 Claude 4、DeepSeek-Coder-V2)
- 多语言翻译 → 选多语言对齐做得好或专注于翻译的模型
一个常见的误区是"一刀切"——一个模型从头用到尾。实际上,不同环节用不同模型往往效果更好、成本更低。比如一个智能合同审核系统:先用多模态模型识别扫描件内容,再用推理模型分析条款风险,最后用普通 LLM 生成审核报告。三个模型各司其职,比一个模型硬扛所有环节更靠谱。
(2)性能与延迟的权衡
模型的参数量越大,通常推理能力越强,但响应也越慢。对于实时交互的应用(如聊天机器人、语音助手),用户能容忍的等待时间通常不超过 2-3 秒。这时候你需要在模型能力和响应速度之间做取舍。
一个实用的策略是"双模型路由":用一个小模型处理简单请求(如问候、常见 FAQ),当小模型判断自己处理不了时,再把请求转发给大模型。OpenAI 的 GPT-4o-mini 和 GPT-4o 的搭配就是这种思路——mini 处理 80% 的简单流量,4o 处理 20% 的复杂请求,整体成本降低 60% 以上,用户体验几乎不受影响。
(3)成本结构
模型服务主要有两种计费方式:按 Token 计费和按调用次数计费。2026 年 LLM 的价格已经大幅下降——DeepSeek-V3 的 API 价格约为 GPT-4o 的 1/10,开源模型自建推理的成本更低。但要注意的是,推理模型因为内部思考过程也会消耗 Token,实际花费可能是普通 LLM 的 5-10 倍。举个例子:同样是一次法律合同分析任务,普通 LLM 可能花费 $0.02,而推理模型在内部反复推敲条款逻辑后,单次调用可能在 $0.10-$0.20——对日均处理数百份合同的企业来说,这个差距意味着每月数千到数万美元的成本差异。
如果你自己部署开源模型,还需要考虑 GPU 算力的成本。一张 NVIDIA A100 的云租用价格约为每小时 2-3 美元,一张 H100 约为 4-5 美元。部署一个 70B 参数量的模型,如果要做高吞吐的在线服务,可能至少需要 2-4 张 A100/H100。这笔固定开支对于小团队来说是不小的负担。
(4)数据隐私与合规
如果你的应用处理的是金融、医疗、法律等敏感数据,模型的选择会受到严格约束。使用公有云 API 意味着数据会离开你的服务器,这在某些行业(如欧洲的 GDPR 监管下的医疗数据)是违规的。此时,自建推理或使用私有部署方案就是必选项。国内的一些大模型厂商(如阿里云、百度智能云)也提供 VPC 内部署的 API 方案,数据不出企业网络,可以作为折中选择。
开源 vs 闭源:不止是价格问题
2026 年的开源大模型生态已经非常成熟。Meta 的 Llama 4、DeepSeek-V3、阿里的 Qwen3、智谱的 GLM-4 都提供了完整的开源权重。开源模型的核心优势不只是免费——更关键的是可控性:
- 可定制:你可以微调模型以适应特定领域(见 10.5.3 节),闭源 API 通常只能做 prompt 层面的调优。
- 可审计:你可以检查模型的行为、评估安全性,而不是信任厂商的承诺。
- 稳定性:API 厂商可能随时调整模型版本、更改定价策略甚至下线服务。开源模型部署在你的服务器上,只要服务器不关,服务就不会停。
- 延迟可控:调用公有云 API 有网络延迟、限流等不可控因素。自建推理可以优化到毫秒级,对于延迟敏感的场景(如高频交易信号生成)至关重要。
但开源模型也不是银弹。你需要承担部署、运维、版本升级的成本。70B 级别的模型部署不是"装个 Docker 就能跑"这么简单——你需要懂推理引擎(vLLM、SGLang)、懂显存规划、懂量化技术(详见 10.5.2 节)。这些技能有学习成本,但一旦掌握,带来的灵活性和成本优势是闭源 API 无法替代的。
一个常见的实战策略是"开源为主、闭源为辅":核心业务链路用开源模型自建推理,保证稳定性和数据安全;非核心或探索性任务用闭源 API,降低开发成本。比如一个电商客服系统:FAQ 和工单分类用自建的 Qwen3-8B(微调版),复杂投诉处理调用 GPT-4o API——这样既控制了成本,又在关键环节保持了高质量的体验。
模型评估:别只看榜单
选模型时,很多人第一反应是看评测榜单(如 LMSYS Chatbot Arena、Open LLM Leaderboard)。榜单确实有参考价值,但它的局限性也很明显:
- 榜单的测试集可能与你的业务场景不匹配。一个在 GSM8K(Grade School Math 8K,小学数学题评测集)上得分高的模型,不一定能写好客服回复。
- 部分模型可能存在"刷榜"行为——针对公开测试集做过训练或优化。
- 榜单反映的是通用能力,不是专项能力。你的应用可能更需要法律知识、医学知识或特定代码库的理解。
真正靠谱的做法是建立你自己的评估基准(Eval Set)。从你的业务场景中抽取 50-100 个真实案例,人工标注标准答案,然后用候选模型分别跑一遍,对比结果。这比看任何榜单都更有说服力。
评估时建议从以下几个维度分别考察:
- 准确性:模型输出的信息是否正确
- 相关性:回答是否切题,不跑偏
- 格式遵循:是否能按照要求的 JSON/Schema 格式输出(这对工程集成至关重要)
- 指令跟随:是否严格遵循 prompt 中的约束条件
- 稳定性:多次运行同一输入,输出质量是否稳定
工程建议:不要相信任何模型的"一次惊艳表现"。同一个 prompt 跑 20 次,观察失败率和错误模式的分布,这才是工程上可以信赖的评估数据。
模型底座的选择不是一次性的工作,而是伴随应用生命周期持续迭代的过程。核心原则有三条:先匹配任务,再权衡成本——不要一上来就追求最贵最强的模型;不同环节用不同模型——单一模型的组合往往比多模型配合的成本更高、效果更差;建立自己的评估体系——榜单只是参考,你自己的数据才是最终裁判。
下一节我们将讨论模型选好之后的下一个问题:这些模型要怎么跑起来——是买 API 服务,还是自己搭推理集群?
10.5.2 模型推理服务模式选择
在 10.5.1 节中,你已经完成了模型底座的选型——确定了要用大语言模型、多模态模型还是语音模型。选好"发动机"之后,下一个问题就是:这台发动机怎么运行?是自己买一台装到车里,还是买成品车的年卡服务?至于你选的"发动机"具体是多模态大模型还是纯文本模型——这个决定来自 10.5.1 节,现在我们默认你已经有了答案。
这就是模型推理服务模式选择要回答的问题。在大模型应用的实践中,推理服务的部署模式直接影响开发节奏、运行成本和后续的定制灵活性。目前主流的模式可以归纳为三种,而这三种模式并非互斥——大多数生产级应用会在不同阶段、不同场景下组合使用它们。
10.5.2.1 直接购买第三方模型推理服务
这是门槛最低、上手最快的模式。你不需要 GPU、不需要部署推理引擎、不需要关注显存占用——只需要一个 API Key,就能调用世界顶级的模型能力。目前主流的商业推理服务包括 OpenAI API、Anthropic Claude API、Google Gemini API、国内的通义千问、文心一言等。
这种模式的核心优势是零运维成本。你不需要关心模型版本升级、负载均衡、弹性扩容这些运维问题——服务商帮你搞定了。另一个容易被忽视的优势是超大模型的接入能力。商业推理服务背后往往是千亿甚至万亿参数的超大规模模型(如 GPT-4、Claude 4),这些模型对算力的要求极高,单张 H100 甚至一台 8×H100 集群都难以承载其完整推理(显存需求可达数百 GB)——自建的成本对大多数团队来说是不现实的。购买 API 服务,等于你用"批发价"用上了个人无法承担的算力。
但这种模式的代价也很明显。首先是费用。假设你的应用每天需要处理 10 万次推理请求,每次平均消耗 2000 Token 输入 + 500 Token 输出,以 GPT-4o 的定价(输入 $2.5/1M Token,输出 $10/1M Token)计算,单日费用约为 $100。如果业务量持续增长,年成本将轻松突破 30 万元人民币(按汇率 7.3 估算)。其次是数据隐私问题——你的数据需要经过第三方服务器,对有严格合规要求的金融、医疗等领域来说,这是一个硬伤。最后是可定制性受限:你无法微调模型(那是 10.5.3 节要讨论的),只能在提示词层面做文章。
务实建议:第三方推理服务的最佳使用场景是项目的早期验证阶段。用最低的成本快速跑通核心流程,验证大模型在业务中的可行性。等需求稳定、成本模型清晰之后,再评估是否需要切换到自建模式。
10.5.2.2 自建推理服务
自建推理服务意味着你需要在自有或租用的 GPU 服务器上部署开源模型(如 Qwen3、DeepSeek-V3、Llama 4 等),并通过推理引擎将模型封装为可供应用调用的 HTTP/gRPC 服务。
算力环境的选择是第一步。目前的选项有三种:
| 算力环境 | 投入成本 | 灵活性 | 适用场景 |
|---|---|---|---|
| 自建机房 | 一次性投入大(8×A100 约 80-120 万元,2025 年价格参考) | 低 | 有硬性数据安全要求、长期大规模推理 |
| GPU 云租赁 | 按需付费(A100-80G ≈5-8 元/小时) | 高 | 弹性伸缩需求、验证期、波峰期补充 |
| 混合部署 | 固定投入 + 弹性扩容 | 中高 | 成本与可用性的平衡——核心负载跑自建集群,波峰自动扩展到云端 |
选定算力环境之后,需要选择推理引擎。推理引擎是将模型文件转化为可调用服务的核心组件,它负责内存管理、批量调度、KV Cache 优化等。如果把模型比作汽车发动机本体,推理引擎就是它的供油系统、点火装置和控制单元——没有它,模型文件只是硬盘上的一堆参数。目前主流的开源推理引擎有以下几个:
| 推理引擎 | 特点 | 适用场景 |
|---|---|---|
| vLLM | PagedAttention 机制,显存利用率高,吞吐量大 | 高并发在线推理 |
| SGLang | 结构化生成能力强,RadixAttention 优化前缀缓存 | 需要结构化输出的场景 |
| Ollama | 部署极其简单,一条命令启动 | 本地开发和测试 |
| llama.cpp | CPU 推理为核心优势,支持 GGUF 量化,也可使用 GPU 加速 | 边缘/端侧部署及资源受限环境(如树莓派、笔记本本地运行) |
| TensorRT-LLM | NVIDIA 官方优化,极致性能 | 对延迟有严苛要求的生产环境 |
大多数团队的路径是:开发验证用 Ollama,生产部署上 vLLM(或 NVIDIA 显卡用户的 TensorRT-LLM),边缘场景用 llama.cpp。
以 Ollama 为例,启动一个 DeepSeek-R1 蒸馏小模型(如 7B)的推理服务只需一条命令:
bash
# 安装 Ollama(macOS)
brew install ollama
# 拉取模型(约 4.7GB,首次下载可能需要几分钟到几十分钟,取决于网络速度)
ollama pull deepseek-r1:7b
# 启动服务
ollama serve服务启动后,Ollama 默认监听 http://localhost:11434,你可以通过标准 REST API 调用:
python
import requests
response = requests.post(
"http://localhost:11434/api/generate",
json={
"model": "deepseek-r1:7b",
"prompt": "请用一句话解释什么是推理服务",
"stream": False
}
)
print(response.json()["response"])而对于生产环境的高并发场景,vLLM 是更务实的选择。首先在命令行启动 vLLM 服务:
bash
# 单卡直接起;要用张量并行再加 --tensor-parallel-size 2(卡数需 ≥ 该值)
vllm serve Qwen/Qwen3-8B \
--max-model-len 8192 \
--port 8000模型尺寸以官方文档为准(本书其他章节里 Qwen3 用的是 8B/14B/32B;若你的显存只够更小尺寸,把模型名换成对应型号即可,参数写法不变)。
vLLM 提供标准的 OpenAI 兼容 API,调用方式与调用 GPT-4 完全一致:
python
from openai import OpenAI
client = OpenAI(
base_url="http://localhost:8000/v1",
api_key="not-needed" # 本地服务不需要真实 key
)
response = client.chat.completions.create(
model="Qwen/Qwen3-8B",
messages=[
{"role": "user", "content": "请用一句话解释什么是推理服务"}
]
)
print(response.choices[0].message.content)自建推理服务的代价是运维复杂度。你需要关注 GPU 驱动版本兼容、显存溢出(OOM)、推理引擎版本升级、模型热加载等问题。但换来的是完全的数据自主权和可控的成本模型——对于日均推理量超过百万 Token 的应用,自建方案通常在 3-6 个月内就能收回硬件投资。
10.5.2.3 混合模式:商业推理 + 自建推理的协同
还记得 10.5.2.1 中的务实建议吗?验证期用 API 快速跑通后,进入规模化阶段就该把那些高频重复任务"外溢"到自建服务了——这正是分层推理的逻辑起点。现实中的大模型应用很少只用一种模式。更常见的是分层推理:将不同类型的任务分配给不同成本和能力等级的模型。
一个典型的混合架构是这样运作的:
高难度任务交给商业超大模型。比如复杂的多步推理、需要深度领域知识的分析——这些任务对模型能力要求极高,开源的中小模型往往力不从心。你调用 GPT-4 或 Claude 完成这些"重活",哪怕单次调用贵一点,但量不大,总成本可控。
高频简单任务交给自建中小模型。比如意图识别、文本分类、格式转换——这些任务的难度不高,但调用频次可能占到总量的 70%-80%。用 Qwen3-8B、Llama 3-8B 等中小开源模型自建服务处理,单次成本可以降到商业 API 的 1/10 甚至更低。
知识蒸馏打通两条链路。你还可以更进一步:先用商业超大模型生成高质量的训练数据(比如用 GPT-4 标注 5000 条意图分类样本),然后用这些数据微调 10.5.3 节将要讨论的自建模型。这样,你就把超大模型的"智力"蒸馏进了自己的中小模型中,实现了**"大模型训练,小模型推理"**的成本优化闭环。
以下是一个简单的知识蒸馏调用示例:
python
# 第一阶段:用商业大模型生成训练数据
from openai import OpenAI
commercial_client = OpenAI(api_key="sk-your-key")
def generate_training_sample(user_input: str) -> dict:
"""用 GPT-4 为意图分类任务生成高质量标注"""
response = commercial_client.chat.completions.create(
model="gpt-4o",
messages=[
{"role": "system", "content": "你是一个意图分类专家。将用户输入分类为以下之一:查询/投诉/购买/闲聊。只输出类别名称。"},
{"role": "user", "content": user_input}
],
temperature=0.1
)
intent = response.choices[0].message.content.strip()
return {"input": user_input, "label": intent}
# 示例数据——实际使用时替换为你业务系统的用户日志或历史对话记录
raw_user_inputs = [
"请帮我查一下订单状态",
"你们的产品质量太差了,我要投诉",
"这个笔记本电脑多少钱?",
"今天天气真好,你觉得呢?",
"我想买你们最新款的手表",
"上次买的耳机有杂音,能换吗",
"谢谢你的帮助",
"有没有适合学生用的平板推荐",
"我的快递怎么还没到",
"你们周末上班吗"
]
import json
import time
def gen_safe(user_input: str, retries: int = 3):
"""单条失败退避重试;最终失败返回 None(不静默吞掉)"""
for attempt in range(retries):
try:
return generate_training_sample(user_input)
except Exception as e:
last_error = e
time.sleep(2 ** attempt) # 1s / 2s / 4s
print(f"[跳过] {user_input[:20]}… 失败:{last_error}")
return None
# 分批 + 边跑边写:进程被杀也不丢已完成的部分;先跑一小批算单价再决定规模
BATCH, ok = 50, 0
with open("intent_training.jsonl", "a", encoding="utf-8") as f:
for start in range(0, len(raw_user_inputs), BATCH):
for user_input in raw_user_inputs[start:start + BATCH]:
item = gen_safe(user_input)
if item is None:
continue
f.write(json.dumps({"messages": [
{"role": "system", "content": "将用户输入分类为:查询/投诉/购买/闲聊"},
{"role": "user", "content": item["input"]},
{"role": "assistant", "content": item["label"]}
]}, ensure_ascii=False) + "\n")
ok += 1
f.flush() # 每批落盘
print(f"进度 {min(start + BATCH, len(raw_user_inputs))}/{len(raw_user_inputs)},成功 {ok} 条")具体的微调流程会在 10.5.3 节详细讲解。本节的重点是理解这个模式的决策逻辑:不是"要么全买API、要么全自建",而是"根据任务的难度和频次,把不同的任务分配给合适的模型"——这就是模型推理服务的架构思维。
10.5.2.4 不同模型组合使用的考量
除了同一类型模型的分层使用,大模型应用还可能涉及不同类型模型的组合。比如一个智能客服系统,可能需要同时调用:
- 语音识别模型(ASR):将用户语音转为文字
- 大语言模型(LLM):理解文字内容并生成回复
- 语音合成模型(TTS):将文字回复转为语音
在架构设计阶段,需要明确每种模型的推理服务模式。语音识别和合成通常适合用商业 API(如 OpenAI Whisper API、Azure Speech),因为这类模型的技术迭代快、自建性价比低;多模态模型(如视觉理解、视频分析)也以商业 API 为首选——它们的参数量大、服务端优化复杂,自建门槛高且难以跟上开源社区的技术迭代节奏。而大语言模型作为核心推理环节,可能选择自建以获得更好的成本控制和定制能力。
另一个需要警惕的是多模型组合带来的延迟累积。如果链路中有 3 个模型串行调用,每个模型推理 500ms,总延迟就是 1.5 秒——在实时对话场景中,用户已经能明显感觉到"机器人反应慢"了。解决方案包括:并行调用无依赖关系的模型、对非关键环节采用更小更快的模型、在推理架构层设计异步流水线(这会在 10.6 节深入讨论)。
本节要点:模型推理服务有三种基本模式——购买商业 API、自建推理、混合使用。选择不是非此即彼的单选题,而是根据任务的难度分层、频次分布和隐私要求来分配的资源配置策略。下一节,我们将深入在自建模式下提升模型能力的核心技术——模型微调。
10.5.3 模型微调
选好了模型底座,也确定了推理服务的部署模式,接下来就面临一个更具体的问题:这个模型能不能按我自己的业务数据来定制?
选型时你拿到的基座模型是「通用选手」——能写诗、能翻译、能答常识题,但当你把它塞进一个具体的业务场景——比如客服工单分类、金融合同审查、医疗报告生成——它的表现往往差强人意。它不了解你们行业的术语,不理解你业务特有的格式,更不知道你希望以什么样的风格输出。这时候,模型微调(Fine-tuning)就该上场了。
注意:微调最灵活的方式是自己搭建推理服务(不管是自建机房、租用 GPU 实例还是使用云厂商的模型训练平台)。如果你使用的是 API 模式直接购买第三方的在线推理服务,OpenAI、Anthropic 等厂商也提供了托管微调功能,但这类方案受限于模型选择范围、参数可控性和数据规模,深度定制仍以自建方案为准。
10.5.3.1 微调的判断原则
微调不是万能药。不少团队一发现模型输出不满意,第一反应就是「我得微调一个」。但实际上,很多时候问题出在 prompt 上,出在上下文组织上,甚至出在对模型能力的错误预期上。在决定投入微调之前,不妨先问自己三个问题:
- 这个问题能通过改进 prompt 解决吗? 大模型对指令的遵循能力在持续提升。如果只是一个简单的格式规范或语气调整,写一个更精细的 system prompt 往往就够了。
- 我手上有足够的标注数据吗? 微调本质上是一种有监督学习,你需要一批「输入→期望输出」的数据对。如果训练数据少于几百条,微调效果大概率不理想。
- 这个任务是「知识密集型」还是「风格/格式密集型」? 如果是前者(比如需要记住大量专业知识),RAG + 基座模型可能是更好的选择;如果是后者(比如统一输出格式、模仿特定写作风格),微调会更直接有效。
那什么场景下微调真正值得投入呢?可以参考下面这张表:
| 场景 | 推荐方案 | 说明 |
|---|---|---|
| 统一输出格式(JSON、表格等) | 微调 | prompt 可以做到 80%,微调能做到 95% 以上 |
| 特定领域术语/风格 | 微调 | 如法律文书、医疗报告——基座模型没见过的专业表达 |
| 小模型做专项任务 | 微调 | 降低推理成本:用 7B 微调版替代 70B 通用版 |
| 海量专业知识问答 | RAG 优先 | 专业知识应在检索环节解决,而非「背」进模型权重 |
| 临时性任务 | prompt only | 不值得为一次性需求做微调 |
| 数据严重不足(<100 条) | prompt only | 样本太少,微调可能过拟合反而降低泛化能力 |
一个实用的判断原则是:先用最强的 prompt 工程手段试一遍,把它当作你微调数据的 baseline。如果 prompt 优化后的结果已经在可接受范围内,就不必微调;如果始终差一口气,那这口气就是微调的价值所在。
10.5.3.2 微调工具链
决定微调之后,第一步是选工具。2025-2026 年,大模型微调的工具链生态已经相对成熟,主要可以分为以下几类:
1. 模型厂商官方工具
如果你使用的是开源模型(如 Llama、Qwen、DeepSeek 等),各家厂商通常提供配套的微调框架:
- LLaMA-Factory:目前社区最主流的微调框架之一,支持 Llama、Qwen、ChatGLM 等数十种模型,封装了 LoRA、QLoRA、全量微调等多种方法,Web UI 降低了上手门槛。对于大多数中小团队的微调需求,LLaMA-Factory 是性价比最高的起点。
- Unsloth:专攻「速度」和「显存优化」的微调框架,在消费级 GPU 上也能跑得动 7B 级别的模型。如果你用 Colab 或单张 RTX 4090 做实验,Unsloth 能让原本跑不起来的微调变成可行。
- Hugging Face 生态(Transformers + PEFT + TRL):最灵活的方案,也是大量研究工作的基础设施。灵活性强但需要自己写训练脚本,适合有深度学习经验的团队做定制化需求。
2. 云厂商托管平台
如果你想微调但不想手搭 GPU 环境——第 10.5.2 节选了自建推理,可运维 GPU 集群仍然有门槛——云厂商的托管平台提供了一个中间选择。你上传数据,平台自动完成训练、评估和部署:
- 阿里云 PAI(含 DSW 交互式建模和 DLC 分布式训练)
- AWS SageMaker(JumpStart 支持一键微调主流开源模型)
- Google Vertex AI(支持 Gemini 和开源模型的微调)
- AutoDL / 矩池云 等 GPU 算力平台(提供预装环境的 Jupyter 实例)
选择云厂商平台的好处是省去了环境搭建和运维的心智负担,代价是灵活度下降——你只能在平台支持的模型和方法范围内操作。
3. 微调方法的选择
工具链选好之后,还要决定微调到什么程度。目前主流的微调方法按「侵入性」从低到高排列:
- LoRA(Low-Rank Adaptation):不修改原模型的权重,而是在模型旁边附加一组可训练的「低秩矩阵」。训练参数量只占原模型的 0.1%~1%,显存需求大幅降低(全量微调 7B 需 60GB+,LoRA 仅需约 8GB),训练速度快。对于大多数领域适配任务,LoRA 已经足够。
- QLoRA(Quantized LoRA):在 LoRA 的基础上,将基座模型量化到 4-bit,进一步降低显存需求。单张 24GB 显存的消费级显卡就能微调 7B 模型。
- 全量微调(Full Fine-tuning):更新模型所有参数。效果上限最高,但需要大量 GPU 显存(微调 7B 模型需要约 60GB+),成本是 LoRA 的数十倍。仅在 LoRA 效果明显不够时考虑。
实际建议:绝大多数团队从 LLaMA-Factory / Unsloth + QLoRA 起步即可。先用少量数据快速验证方法可行性,确认效果 OK 后再上更大的数据量和更多的训练 epoch。不要一上来就追求全量微调——你的时间和算力预算大概率耗不起。
10.5.3.3 微调数据工程
很多团队在微调上栽跟头,不是因为模型选得不好,也不是因为超参没调对,而是训练数据质量不过关。微调数据(即「训练数据」,本书中两个词等价使用)的准备可以分为三个环节:收集、清洗、格式化。
1. 数据收集
你需要收集一批「输入→期望输出」的数据对,具体格式取决于任务类型:
- 指令微调(Instruction Tuning):每条数据包含
instruction(用户指令)+output(期望回答)。比如:
json
{
"instruction": "将以下客服工单归类为'退款'、'投诉'或'咨询'",
"input": "我的订单三天没发货了",
"output": "投诉"
}📝
instruction中列出分类标签的枚举值(退款/投诉/咨询),目的是让模型在推理时知道可选范围,避免生成超出预定义标签的结果。
- 多轮对话微调:每条数据是一个完整的对话历史,格式为
[{"role": "user", "content": "..."}, {"role": "assistant", "content": "..."}]的数组。用在需要模型保持多轮对话上下文一致性的场景。
数据从哪里来?常见来源有三种:
- 人工标注:质量最高,成本也最高。适用于数据量不大(几百到几千条)但质量要求极高的场景。
- 从生产日志中筛选:如果你已经有在线模型在跑,可以从历史对话中挑选高质量的用户-AI 交互,经人工审核后作为训练数据。
- 用更强的模型生成:用 GPT-4 或 Claude 生成一批回复作为「教师信号」,再用它们来训练小模型。也就是知识蒸馏(distillation)。
2. 数据清洗
拿到原始数据后,至少要检查以下几个方面:
- 去重:重复的训练样本会让模型在该样本上过拟合。简单的语义去重(如 MinHash)就能过滤掉大部分重复。
- 格式校验:检查 JSON 结构是否完整,特殊字符是否转义,对话轮次是否奇数(以 user 开头,assistant 结尾)。
- 质量筛选:人工抽查 5%~10% 的样本,剔除明显错误的(如分类标签错误、回复逻辑矛盾)。
- 长度控制:超长文本(>4096 tokens)在微调时消耗大量显存且训练效率低。可以截断或拆分为多条样本。
3. 数据格式化
不同工具链要求的训练数据格式略有不同。以 LLaMA-Factory 为例,它支持 Alpaca 格式和 ShareGPT 格式两种。Alpaca 格式适合指令微调任务,ShareGPT 格式适合多轮对话任务。你的清洗脚本需要根据选定的工具链,将数据转换为对应的 JSON 结构。
一条容易踩的坑:训练数据要与实际使用场景对齐。如果你微调的目的是让模型以 JSON 格式输出,那么训练数据中的 output 字段也必须是 JSON 字符串。如果训练数据里混入了自然语言描述的输出而推理时又要求 JSON,模型会困惑。
4. 数据标注工具
数据量大的团队,可以借助标注工具来管理标注流程。Label Studio 是开源社区最主流的标注平台,支持文本分类、序列标注等多种任务类型,有丰富的协作功能。Dify 也提供了内嵌的标注界面,适合标注和推理在同一个平台完成的场景。如果以上工具不满足需求,还可以在 Gradio 或 Streamlit 上快速搭建定制化的标注工具。核心原则是让标注流程贴近业务专家的日常习惯——如果标注门槛太高,数据量永远上不去。
10.5.3.4 实验管理与可复现
微调不是一次就能搞定的事。通常你会跑多轮实验——换不同参数组合、换不同数据集切分、换不同验证策略——然后对比结果。没有一套好的实验管理习惯,两周后你根本记不起来第三轮的 learning rate 是 2e-4 还是 5e-5。
至少需要记录以下信息:
| 记录项 | 说明 |
|---|---|
| 基座模型 | 模型名称 + 版本号(如 Qwen2.5-7B-Instruct) |
| 微调方法 | LoRA/QLoRA/全量,LoRA rank、alpha 等关键参数 |
| 训练数据 | 样本量、数据来源、版本标识 |
| 超参配置 | learning rate、batch size、epoch 数、warmup 步数 |
| 训练环境 | GPU 型号/数量、框架版本 |
| 评估指标 | 验证集 loss、具体任务指标(准确率、BLEU 等) |
| 训练时间与成本 | 耗时、GPU 时费用(如果用云平台) |
可以简单用 Excel 或 Notion 表格来维护,也可以用专业的实验管理工具:
- MLflow:最主流的开源实验跟踪工具,能自动记录参数、指标和模型产物。几行代码集成到训练脚本中。如果你只选一个入门工具,MLflow 是最轻量的起点。
- Weights & Biases(W&B):功能更丰富的商业平台,提供可视化面板和团队协作功能。面向个人使用者免费。如果团队已有 W&B 使用习惯,优先复用它。
- TensorBoard:PyTorch/TensorFlow 生态自带的轻量方案,适合快速本地查看训练曲线。
无论用什么工具,核心原则只有一条:保证每一轮实验都是可复现的。这意味着你的训练脚本、数据版本、随机种子、环境配置必须完整保存。否则当三个月后需要重新训练时,你只能从头摸索。
10.5.3.5 微调周期与模型漂移
微调不是「做完就完了」的事。模型的效果会随着数据分布的变化而退化——这被称为模型漂移(Model Drift)。业务需求在变,用户提问方式在变,甚至你们内部的术语都可能调整。因此微调是一个需要周期性维护的工作。
常见的微调迭代节奏:
- 初始微调:项目启动时,用已有历史数据完成第一版微调,建立 baseline。
- 定期重训:每 1~3 个月,用新增的高质量训练数据(可以从生产日志中筛选)对模型做增量训练或全量重训。前提是新数据累积到原有训练集的 10%~20% 以上量级,否则重训的收益有限。
- 事件驱动微调:当业务逻辑发生重大变更(如新增产品线、政策法规更新)时,立即触发微调。
增量微调(Continual Fine-tuning)有一个需要注意的问题——灾难性遗忘(Catastrophic Forgetting)。如果你只喂新数据而不混入旧数据,模型可能在学会新知识的同时「忘掉」旧知识。常见的应对策略是:重训时把新旧数据按一定比例混合(如 7:3),或者对旧数据中模型表现较差的样本做 up-sampling。
10.5.3.6 基础设施与环境
最后说说微调运行环境。你不用一上来就建一套完整的 MLOps 平台,但有些基础设施是跑不掉的。
GPU 环境:
- 个人实验:单张 RTX 4090(24GB)可以通过 QLoRA 微调 7B 模型
- 小团队生产:2~4 张 A100 或 H100(或等价租用算力)
- 最小可行方案:AutoDL / Colab Pro 按小时租,跑一次微调 7B 模型大概几十到几百元
数据存储与版本控制:
- 训练数据放 Git 仓库不合适——数据量大且频繁变更。推荐对象存储(S3/MinIO)加数据版本管理工具(如 DVC),每次数据集变更都有版本标识,便于追溯和复现。
- 模型产物用 Hugging Face Hub 或私有的模型仓库(如 Ollama 模型目录 + NFS 共享存储)。建议模型文件名中包含训练时间戳和关键参数,避免混淆。
环境一致性:
- 用 Docker 镜像固化训练环境。训练脚本里加一行
pip freeze > requirements.txt——版本差异是微调调试中最令人抓狂的问题之一。如果有条件,用 Docker Compose 或 Kubernetes Job 管理训练任务,确保每次运行的环境完全一致。 - 如果用云平台,优先选择它们预置好 CUDA/PyTorch 的官方镜像,避免手动配置驱动兼容性问题的坑。
最低预算参考:
- 0 元起步:Colab 免费版 T4 GPU(16GB),配合 Unsloth + QLoRA 可微调 7B 模型(注:免费版 Colab 单次运行时长约 2 小时限制,数据量较大时可能被中断,建议升级 Colab Pro 或使用 AutoDL 等替代方案)
- 每月几百元:租用 AutoDL 等平台的 A100,按月计费,适合不频繁但有周期的微调需求
- 小团队自建:一张二手 RTX 4090(约 1.5 万元),足以覆盖 7B 模型的日常微调实验
小结:模型微调是大模型应用「最后一公里」的定制手段——它让通用模型学会你特有的业务语言。但微调的前提是数据质量和实验纪律。工具链从 LLaMA-Factory 起步,数据从高质量样本开始(无论来源是人工标注、生产筛选还是知识蒸馏),实验管理从一张记录表做起。这些基础做扎实了,微调才能真正产生价值,而不是变成一场消耗算力却收效甚微的折腾。
10.6 六大子架构:推理架构
前面的模型架构解决了"谁来消费数据"的问题——我们选好了模型、设计了它们之间的协作关系。但还有一个关键问题悬而未决:模型选定之后,怎么让它把活干出来?
你有了知识,整理好了数据,选好了模型。把数据往模型面前一放,它就能自动给出你想要的答案吗?在简单场景下,是的。比如"把这段英文翻译成中文",一句话提示词 + 一段文本,模型直接返回结果。但大模型应用的现实远比这个复杂——你的任务可能是:"分析这 50 页财报,找出其中的财务风险信号,生成一份结构化的风险报告,并在关键数据点上标注信息来源。"
这不是一个"问→答"就能解决的任务。你需要设计一个推理过程——多次调用模型,每一步有明确的输入输出,步骤之间有逻辑依赖,中间结果需要管理,参数需要调控。
这就是推理架构要解决的问题。
本节核心问题:我要设计一个什么样的推理过程,让模型从接收任务到产出最终结果,每一步都是可控、可调、可复现的?
10.6.1 推理步骤设计
大模型单次推理的上下文窗口有限——即使 2026 年的主流模型已经支持 128K 甚至 1M token 的上下文,但这不意味着你应该把所有东西都塞进一次调用里。上下文越长,推理越慢、成本越高、模型对中间信息的注意力越分散。更重要的是,复杂任务的逻辑本身就不是线性的——它需要分支判断、需要回顾前序结果、需要在中间步骤做质量检查。
因此,对于有一定复杂度的任务,你需要把它拆成多个推理步骤。
10.6.1.1 判断任务复杂度:单步还是多步?
设计推理步骤的第一步,不是直接开始拆,而是先判断这个任务到底需不需要拆。
一个实用的判断框架:从三个维度审视你的任务。
维度一:信息量。 一次推理需要的上下文总量是否超过了模型有效处理的范围?这里的"有效处理"不是指上下文窗口的硬上限,而是指模型的"有效注意力范围"——有研究表明(参见 Liu et al. 2024 "Lost in the Middle",该研究发现在多文档 QA 任务中,模型对中间位置信息的召回准确率显著低于首尾位置),即使模型支持 128K 上下文,它对中间位置信息的召回准确率也显著低于开头和结尾位置。如果你的任务涉及的信息量(提示词 + 参考资料 + 预期输出)超过 20K-30K token,就应该认真考虑拆分。
维度二:逻辑复杂度。 任务的推理链路是否包含分支、循环或多层嵌套?"翻译一段文本"是单链路的;"分析财报并判断是否值得投资"涉及多维度分析(营收、利润、现金流、行业对比)→ 综合判断 → 生成报告,每一步的输出影响下一步的方向——这种逻辑结构天然需要拆成多步。
维度三:质量要求。 最终结果的质量要求是否需要中间验证?如果你的任务"查一下北京到上海的航班"——錯了也就錯了,用户自己会判断。但如果你的任务是"生成一份提交给监管机构的合规报告"——你需要中间检查准确性、完整性、格式合规性。这种情况下,即使任务本身逻辑不复杂,也应该拆出专门的验证步骤。
一个简洁的决策逻辑:
if 上下文量 > 20K token:
→ 信息拆分
elif 推理链路有分支/循环:
→ 逻辑拆分
elif 输出质量需要中间验证:
→ 质量拆分(引入验证步骤)
else:
→ 单步推理即可10.6.1.2 推理步骤的分解
确定了需要多步推理后,接下来就是把大任务拆成小步骤。这一步考验的是你对任务本身的理解——你在设计推理架构之前,应该已经在任务架构(10.1 节)中把业务流程梳理清楚了。推理步骤的分解,本质上是把业务流程映射为模型的推理动作。
一个有效的拆分应该满足三个原则:
原则一:每步有明确的输入输出。 每一步的输入是什么(前一步的输出?外部查询结果?用户原始输入?),输出是什么(一段文本?一个结构化 JSON?一个布尔判断?),必须清楚定义。模糊的步骤定义会导致后续的流程调度无法实现。
原则二:每步是单一职责。 一步只做一件事。如果一步既要"提取关键信息"又要"判断情感倾向"还要"生成摘要",你应该拆成三步。单一职责不仅让每一步更容易调试(哪步出问题一目了然),也让你可以为不同步骤选择不同的模型参数——提取信息可能用低温度,生成摘要可能需要稍高温度来保证语言流畅。
原则三:步骤之间有清晰的数据依赖。 步骤不是孤立的——步骤 B 依赖步骤 A 的哪个输出字段?步骤 C 是否同时依赖 A 和 B?画一张步骤间的数据流图,后续的调度体系设计就有了依据。
举个例子,一个"财报风险分析"任务可能拆成:
步骤1: 财报文本预处理(分章节、识别表格)
输入: 原始财报 PDF(或已提取的文本)
输出: 结构化的章节 + 表格数据
步骤2: 逐章节关键指标提取
输入: 步骤1的结构化文本
输出: 各章节的财务指标 JSON(营收、利润、负债、现金流...)
步骤3: 跨章节关联分析
输入: 步骤2的财务指标 JSON
输出: 异常关联标记(如"营收增长但经营现金流下降")
步骤4: 风险综合判断
输入: 步骤3的异常标记 + 步骤2的指标
输出: 风险等级 + 风险点列表
步骤5: 报告生成
输入: 步骤4的风险判断 + 步骤2的原始指标
输出: 结构化风险报告你可以看到,每个步骤只有一件事情,输入输出明确,依赖关系清晰。步骤3 出错了不会影响步骤2——你可以单独调试步骤3。
10.6.1.3 推理流程的规划
步骤拆好了,接下来要规划它们之间的执行顺序。最常见的执行模式有三种:
顺序链(Sequential Chain)
最简单的模式:A → B → C → D,一步一步来。每一步的输出直接成为下一步的输入。适合任务逻辑本身就是线性的场景——比如上面的财报分析,步骤之间有前后依赖,必须按顺序执行。
顺序链的优点是实现简单、容易调试。缺点是没有并行能力——如果某些步骤之间其实没有数据依赖,顺序执行浪费了等待时间。
有向无环图(DAG)
当步骤之间存在并行可能性时,你可以设计为 DAG 结构。比如:
步骤1(预处理)
/ \
步骤2a(营收分析) 步骤2b(负债分析)
\ /
步骤3(综合判断)
|
步骤4(报告生成)步骤2a 和步骤2b 分别分析营收和负债,它们只依赖步骤1 的输出,彼此之间没有依赖——所以可以并行执行。DAG 模式充分利用了并行能力,适合步骤多、有独立子任务的大型推理任务。
循环/迭代(Loop / Iterative)
有些任务需要反复迭代才能达到预期质量。比如代码生成任务:"写一个函数"→ 跑测试 → 报错了 → 把错误信息和原代码一起反馈给模型 → "修复这个错误"→ 再跑测试 → ... 直到测试通过,或者达到最大迭代次数。
循环模式的关键在于设计退出条件。退出条件可以是:
- 自动判断:通过一个独立的验证步骤检查结果是否达标
- 计数器上限:最多迭代 3 次,仍不达标则标记为人工介入
- 质量递减检测:如果新一轮的结果比上一轮更差,立即停止
注意:循环模式的成本是线性增长的——每次迭代都是一次模型调用。在设计循环上限时要结合成本考量。如果你发现一个任务经常需要 5+ 次迭代才能出好结果,可能需要反思:是不是步骤拆分不够细?是不是提示词设计不够精准?是不是应该通过微调而不是提示词来解决?
10.6.1.4 流程调度体系的设计
推理流程规范好之后,需要一个"调度器"来按照流程图的指示按序调用大模型、处理步骤间数据的传递、处理异常。这就是流程调度体系。
调度体系的核心职责是三条:
第一条:按计划触发模型调用。 调度器根据你定义的执行图,在正确的时机触发正确的模型调用。如果是 DAG 模式,调度器识别哪些步骤的数据依赖已经满足,可以并行发起;如果是循环模式,调度器判断退出条件是否达到。
第二条:管理步骤间的数据传递。 步骤 A 的输出可能包含 20 个字段,但步骤 B 只需要其中的 3 个。调度器负责提取、转换、传递数据。这种转换逻辑如果散落在各个步骤的实现代码中,维护起来会非常痛苦——集中在一个调度层,改起来只需要改一处。
第三条:异常处理和重试。 模型调用可能失败——API 超时、返回格式不合法、内容质量不达标。调度器需要定义明确的异常处理策略:重试几次?重试时要不要换模型?什么情况下跳过该步骤继续?什么情况下终止整个流程并通知人工?
目前常见的调度实现方式有两种:
基于框架:LangChain 的 Chain/Agent、LangGraph 的状态图、Dify 的工作流编排等。这些框架提供了现成的调度能力,你只需要定义步骤和执行图。适合大多数项目。
自建调度:在框架能力不足或你有特殊需求时,自己实现调度逻辑。通常是基于任务队列(如 Celery、BullMQ)+ 状态机。灵活性高,但开发和维护成本也高。
选择哪种方式,取决于你的项目的复杂度和团队的技术偏好。原则上,如果不是特别复杂的需求,优先使用现成框架——调度逻辑本身不是你的业务核心,不值得花大量时间手写。
10.6.2 推理前的准备
拆好了推理步骤、设计好了调度流程,在真正开始调用模型之前,还有一件容易被跳过的关键工作:推理前的数据准备。
这一步的核心任务是:把推理过程中每一步需要的数据,在调用模型之前准备好——不是提前全部查出来放在那里,而是让调度器在每步调用之前,能够自动、准确、高效地拿到这一步所需的上下文数据。
推理前的数据准备主要包含三个方面:知识检索、工具注册、和上下文预组包。
10.6.2.1 知识检索:找到这一步需要的东西
在第 10.2 节(知识架构)和第 10.3 节(数据架构)中,你已经梳理了知识来源和数据的格式与服务化封装。推理前的准备要做的,是根据当前推理步骤的需求,从这些知识源中精确检索出相关数据。
具体来说,这一步要做的是:
查询改写:用户的原始提问不一定就是最优的检索查询。比如用户问"这公司最近是不是不太行了?",你需要把它改写为更精准的检索查询:"XX 公司 2025 年 Q4 财务数据 营收 利润 负债 变化趋势"。查询改写本身可能需要一个模型调用来完成——在 LangChain 或 LlamaIndex 中,这通常称为 Query Rewriting 或 HyDE(Hypothetical Document Embeddings)。
多路召回:从不同数据源同时检索相关数据。结构化数据走 SQL,非结构化数据走向量检索,外部数据走 API 或 MCP 调用。多路召回可以提高覆盖率——向量检索可能漏掉的精确匹配,SQL 查询能补上;SQL 查不到的语义相关内容,向量检索能补上。
结果融合和排序:多路召回的结果需要去重、排序、截断。常用的策略是按相关性分数排序后取 top-N,但不同召回源的评分体系不同,不能直接比较——需要用 RRF(Reciprocal Rank Fusion)或类似方法做分数融合。
以财报分析为例,步骤2"逐章节关键指标提取"可能需要检索:
- 公司所处行业的标准财务指标定义(向量检索)
- 同行业公司的对标数据(SQL 查询)
- 最新的会计准则变更说明(实时 API 查询)
这些数据在步骤2 开始时才去检索,而不是在流程启动时全部加载——按需检索,节省上下文窗口。
10.6.2.2 工具注册:让模型知道"你能用什么"
如果推理过程中模型需要通过 MCP 协议或其他工具协议访问外部系统(如查数据库、调 API、执行代码),你需要在推理开始前注册这些工具。
工具注册的核心是把工具的声明(工具名、描述、参数 schema)统一管理,在调用模型时注入到提示词或系统消息中,让模型知道它可以调用哪些工具。
注册时需要考虑几个关键决策:
权限分级:不是所有步骤都应该看到所有工具。步骤1 可能只需要只读查询工具,步骤4 可能需要写操作工具。为不同步骤注册不同的工具集,既安全又减少了提示词中无关工具的噪音。
工具调用的副作用:有些工具的调用是不可逆的(如发送邮件、创建工单)。这类工具应该只暴露给经过验证的结果生成步骤,而不是在信息收集步骤中就可以被触发。
人工兜底:对于高风险的写操作工具(如修改数据库、发送通知),建议在工具声明中加入
require_human_approval标记。模型调用此工具时不直接执行,而是进入待审批队列,人工确认后执行。
10.6.2.3 上下文预组包:把数据组装成模型能消费的格式
检索完成、工具注册好之后,最后一步是把检索到的数据、工具声明、系统指令组合成一次模型调用的完整提示词。这个过程看起来简单——不就是拼字符串吗?实际上细节不少。
首先是顺序问题。提示词中不同信息的摆放顺序会影响模型的注意力分布。常见的最佳实践是:
系统指令(角色 + 任务描述)
↓
可用工具声明
↓
检索到的参考数据
↓
对话历史(如果有)
↓
用户的当前提问把系统指令放在最前面,确保模型建立角色认知;把参考数据放在用户提问之前,模型在生成回答时会优先关注这些数据。
其次是引用管理。检索到的参考数据需要带上来源标记,以便模型在生成回答时可以标注信息来源。比如:
参考资料1(来源:2025年报·第42页):
2025年公司实现营业收入156.8亿元,同比增长12.3%...
参考资料2(来源:行业数据库·2025Q4):
同行业平均营收增速为8.7%...这不仅是给模型看的——这些引用标记最终会传递到输出中,让用户可以追溯信息来源。
最后是 token 预算管理。每一段塞进提示词的内容都在消耗上下文窗口。你需要为不同内容分配 token 预算——系统指令占多少、工具声明占多少、参考数据占多少、预留多少给模型的输出。如果检索到的数据超过了预算,需要按相关性排序截断,而不是无脑全部塞进去。
10.6.3 模型参数的设定
数据准备好了,提示词也组好了,接下来要调用模型了。但在调用之前,还有一组关键的"旋钮"需要调——模型推理参数。
很多人把参数调校视为"玄学"——凭感觉调一个 Temperature,看看输出好不好,不行再调。但实际上,参数设定的逻辑是清晰的,只是需要你理解每个参数在数学上做了什么,以及它如何影响你想要的输出。
本节侧重参数的选择原则和设计时的决策逻辑。各参数在 API 调用层面的具体配置方式,请参见第 4 章 OpenAI 接口的相关内容。
10.6.3.1 Temperature:控制"随机性"而非"创造力"
Temperature 可能是最常被误解的参数。很多文章把它描述为"创造力的开关"——调高就更有创造力,调低就更严谨。这个说法不算错,但容易误导人。
从数学上说,Temperature 是在 Softmax 函数中引入的一个缩放因子。模型推理时,对每个位置会算出一个概率分布(每个候选 token 的概率)。Softmax 公式为:
其中
- 当 T < 1(低温度)时:概率分布的差异被放大。高概率的 token 概率变得极高,低概率的 token 概率变得极低。模型倾向于反复选那一个"最稳妥"的答案。
- 当 T > 1(高温度)时:概率分布的差异被抹平。原本排名靠后的 token 也获得了可观的选择概率——这就是所谓的"多样性",但也意味着模型更容易输出不合理的、错误的内容。
- 当 T = 1 时:就是标准的 Softmax,不缩放。
所以更准确的描述是:Temperature 控制的是模型输出的随机性程度,而非"创造力"本身。 低随机性的输出不等于"高质量"——它只是更"确定"、更"可复现"。如果模型本身对正确答案的信念就很弱(即正确答案的原始 logit 并不显著高于错误答案),低温度不会让它变聪明,只会让它固执地重复错误。
选择原则:
| 任务特性 | 推荐 Temperature | 原因 |
|---|---|---|
| 提取事实、计算数学、代码生成 | 0.0 - 0.3 | 输出需要唯一且准确,随机性是噪音 |
| 分类、结构化抽取、信息提取 | 0.1 - 0.5 | 结果需要一致性,但允许轻微的变化 |
| 通用问答、摘要、翻译 | 0.5 - 0.8 | 语言需要自然流畅,适度的多样性有助于可读性 |
| 创意写作、头脑风暴、广告文案 | 0.8 - 1.2 | 多样性是目标,随机性是创意的来源 |
| 探索性实验、发散思考 | 1.2 - 1.5 | 你需要"不按常理出牌",但要做好后处理(筛选、去谬) |
经验建议:如果你对输出的期待是"绝对准确、逻辑严谨、拒绝废话",把 Temperature 调低。如果你希望模型"给点不一样的思路",把 Temperature 调高——但一定要配合后处理机制过滤掉胡说八道的内容。
10.6.3.2 Top-P 与 Top-K:设置"候选池"
Temperature 控制了概率分布的"陡峭程度",但它并不能阻止模型选到一个极度不靠谱的词——即使概率极低,理论上每个 token 都有被选中的机会。Top-P 和 Top-K 的作用,是在这个概率分布上做硬截断——直接把某些候选 token 排除出选择范围。
Top-K:只从概率排名前 K 的候选 token 中采样。比如 K=10,模型只考虑排名前 10 的词。就算第 11 名的词在某些语境下很合理,也强制不选。
- 优点:简单直接,推理速度快。
- 缺点:K 是固定的,不随具体上下文调整。在某些场景下前 10 个词覆盖了 99% 的概率(K 太大),在另一些场景下前 10 个词可能只覆盖了 30%(K 太小),导致输出重复、缺乏变化。
Top-P(核采样 / Nucleus Sampling):只从累积概率达到 P 的最小候选集里采样。比如 P=0.9,模型把词按概率从高到低排列,累加概率,直到总和 ≥ 90%,剩下的词(那 10% 的边缘词)直接丢弃。
- 优点:动态适应——候选池的大小随概率分布自动调整。集中分布时候选池小(保证质量),平坦分布时候选池大(保持多样性)。
- 缺点:比 Top-K 多了一点计算开销,但在工程实践中这个差异可以忽略。
选择原则:
Top-P 和 Top-K 不是互斥的——很多模型接口允许你同时设置两者(先 Top-K 截断,再 Top-P 截断)。推荐的策略是:
- 当你需要严格的准确性(代码生成、事实提取):Top-P 调低(0.1-0.3),或只用 Top-K 且 K 很小(如 K=5)。
- 当你需要语言的流畅性(对话、摘要):Top-P 设 0.8-0.95,可以不设 Top-K。
- 当你想全面收紧以控制质量:同时设 Top-P=0.3 和 Top-K=20,双重截断。
10.6.3.3 其他重要参数
除了 Temperature 和 Top-P/Top-K,还有几个在特定场景下很关键的参数:
Max Tokens(最大输出长度):这是成本控制的硬上限,也是防止"模型跑偏"的护栏。如果模型在中间某个环节开始"胡言乱语",低 Max Tokens 至少保证了它不会无限制地消耗 token。在多步推理流程中,为每一步设定合理的 Max Tokens 上限,是最简单也最有效的成本控制手段。
Frequency Penalty 和 Presence Penalty:这两个参数控制模型的"重复倾向"。
- Frequency Penalty:降低模型重复已出现 token 的概率。值越高,模型越不喜欢重复自己刚说过的话。
- Presence Penalty:降低模型重复已出现过任何 token 的概率。区别在于 Frequency 看"出现次数",Presence 看"是否出现过"。
如果你的推理流程中有多轮对话或生成长篇内容,适度调高这两个参数可以避免模型陷入"车轱辘话来回说"的模式。但注意,在需要精确术语一致性(如法律文书、技术规范)的场景中,过高的惩罚可能导致模型用不同的词描述同一个概念,反而造成混淆。
Stop Sequences(停止序列):预定义的停止字符串。模型在生成过程中遇到这些字符串时立即停止输出。在设计推理步骤时,你可以利用 Stop Sequences 来控制输出边界——比如当模型的输出格式为"分析结论:xxx\nEND",你可以把 \nEND 设为停止序列,这样模型生成完结论后不会继续产生无用的后续文本。
10.6.4 推理结果的处理
模型调完了,拿到输出了。但原始输出通常不是最终要交付给用户的结果——你需要对推理结果做进一步处理。这包括三个层面:格式校验与修复、多结果合成、和质量检查。
10.6.4.1 格式校验与修复
大模型的输出本质上是概率性的文本生成,不保证每次都严格遵循你要求的格式。即使你在提示词里反复强调"输出 JSON 格式",在 100 次调用中可能有 3-5 次出现格式问题:多了个逗号、少了个引号、在 JSON 外面多写了一句解释性文字。
这就是为什么在系统设计层面需要格式校验与修复。
校验层:对模型输出做格式检查。如果期望的是 JSON,就用 JSON 解析器验证;如果期望的是特定 Schema,就用 JSON Schema 验证。校验失败触发修复流程。
修复策略(按优先级):
自动修复:很多格式错误是可以自动修复的。JSON 多了尾部逗号 → 去掉;JSON 外面有多余文字 → 用正则提取 JSON 部分;字段名拼写错误 → 模糊匹配纠正。这些修复逻辑可以用规则实现,不需要再调模型。
模型重试(修正提示词):自动修复失败的,把错误信息反馈给模型,让它重新生成。修正提示词的写法很关键——不是笼统地说"格式不对,重新来",而是具体告诉模型哪里出了问题:"你输出的 JSON 在第 23 行多了个逗号,在
summary字段外多写了一句话'以上就是分析结果'。请确保只输出纯 JSON。"降级处理:重试 2-3 次仍然失败,启用降级策略——可能用更保守的参数再试一次(如 Temperature 降到 0),或者用备用模型重新生成,或者将这一环节标记为失败并通知人工介入。
10.6.4.2 多结果合成
在多步推理流程中,最终交付给用户的结果往往不是某一步的直接输出,而是多个步骤产出的合成结果。
合成的难点在于:不同步骤的输出格式不同(有的是 JSON,有的是自然语言,有的是结构化表格),你需要把它们整合成一个统一、连贯的输出。这个过程通常需要一次额外的模型调用来完成——把各步骤的结果作为输入,让模型生成最终的合成文本。
合成调用的提示词设计要点:
- 明确每个来源的用途:"下面是三个来源的信息——来源A 是财务指标数据,来源B 是异常检测结果,来源C 是行业对比数据。请综合这三个来源,生成一份风险分析报告。"
- 标注来源指令:"报告中涉及具体数据时,请使用
[来源:XXX]标注数据来源。" - 给出输出格式范例:不只是描述格式,要给一个完整的输出范例。模型对格式的理解,从范例中得到的信号远强于从规则描述中得到的信号。
10.6.4.3 质量检查
在将最终结果交付给用户之前,应该有一个独立的质量检查步骤。这个步骤的核心是回答三个问题:
- 结果是否完整? 是否覆盖了用户请求的所有方面?有没有遗漏的关键信息?
- 结果是否准确? 引用的数据是否正确?逻辑推导是否有漏洞?可以对比原始数据源做抽查。
- 结果是否符合输出标准? 格式、语气、风格、长度是否符合要求?
质量检查可以由模型自己来做(用一个独立的验证步骤),也可以由规则引擎来做(格式检查、长度检查、关键词检查),或者两者结合——规则引擎做硬性检查,模型做软性质量判断。
如果质量检查不通过,有两种处理路径:
- 自动回退:如果问题具体且可修复(如缺少某个章节),补充生成缺失的部分,然后重新合成。
- 人工兜底:如果问题复杂或质量检查反复不通过(比如 3 次修复仍不达标——3 次是工程实践中常用的重试上限,你可以根据任务的容错率和成本预算自行调整),将任务标记为"需要人工审核",附带所有中间结果和质检报告,转交人工处理。
设计建议:不要把质检环节放在路径末梢时才想到它。在设计推理步骤时就应该规划——哪几步的输出需要质检?质检标准是什么?不通过时怎么办?质检不是"事后补救",而是推理架构的一部分。
10.6.5 推理过程上下文管理
前面一直在讲"怎么把推理流程串起来",但有一个伴随整个流程的基础问题没有展开:上下文怎么管?
多步推理意味着多个模型调用,每个调用都需要上下文。有些上下文是跨步骤共享的(如用户的原始请求、已检索到的知识),有些是步骤独有的(如上一步的输出)。随着推理步骤的推移,上下文会持续膨胀——每步的输出都变成后续步骤的输入。如果不加管理,上下文很快就会超出窗口或者模型对中间信息失焦。
上下文管理的三个核心课题:存储、压缩、和知识提取。
10.6.5.1 上下文存储
多步推理流程中,每一步产生的上下文需要有一个"暂存区"。这个暂存区的设计要点:
按步骤组织的结构化存储。不是把所有上下文堆在一起,而是按照推理步骤组织:
推理上下文:
├── 步骤1(预处理):
│ ├── 输入: 原始财报文本
│ ├── 输出: {章节名: 文本} 映射
│ └── 元信息: 耗时、token数、模型
├── 步骤2(指标提取):
│ ├── 输入: 步骤1的输出
│ ├── 输出: {指标名: 值} JSON
│ └── 元信息: ...
└── ...这种结构化的存储方式有几个好处:后续步骤可以精确引用特定步骤的输出(而不是把所有步骤的输出都混杂在一起传进去);调试时可以快速定位哪个步骤出了问题;步骤重跑时只需要覆盖该步骤之后的数据,不影响前面的结果。
存储介质的选择可以很简单——对于大多数场景,内存中的字典结构就够了。如果推理流程很长或者需要在流程中断后恢复继续,可以把上下文序列化到 Redis 或数据库中,实现上下文的持久化和断点续跑。
10.6.5.2 上下文压缩
随着推理步骤增多,上下文总量会快速膨胀。如果每次模型调用都把整个历史上下文传进去,不仅成本高昂,模型对关键信息的注意力也会被稀释。
上下文压缩的核心思路是:传给模型的,不应该是全部历史,而应该是"历史中最关键的那部分"。
常用的压缩策略:
摘要压缩。用一次额外的模型调用,对历史上下文做摘要——保留关键结论、决策和未解决的问题,丢掉中间的推理过程、已完成步骤的细节。这是最灵活的方式,但注意摘要过程本身也消耗一次模型调用和 token。
假设步骤1-3 产生了 8000 token 的上下文,但对步骤4 来说,其中大部分是中间推理细节。你可以让模型对这 8000 token 做摘要,压缩到 500 token 的关键信息,然后只将摘要传给步骤4。
结构化压缩。不依赖模型做摘要,而是通过代码按结构提取关键字段。如果你的推理步骤产出的都是结构化 JSON,那提取关键字段是简单的——只传步骤输出的 conclusion 和 anomalies 字段,不传中间的 raw_data 和 analysis_log。
这种方法的好处是零额外 LLM 调用成本、结果确定,但要求你提前定义好每个步骤中哪些字段是"关键上下文"。如果你在做推理步骤设计时就把这个定义好(在步骤输出规格中标明"哪些字段传递到后续步骤"),后续实现会省很多事。
滑动窗口。在需要保留完整历史细节的场景中(如多轮对话),可以使用滑动窗口——只保留最近的 N 条消息或 N 个步骤的上下文。窗口之外的内容做摘要保留,窗口之内的保留完整内容。
10.6.5.3 上下文知识提取
上下文不只是要让模型"看到"——它还应该变成可被索引、可被检索的知识。这一点在长期的、持续性的大模型应用中尤其重要。
举个例子:一个持续运行的智能客服系统,每天处理上千条对话。昨天的对话中可能产生了一些新的 FAQ 答案,这些答案应该被提取出来,存入知识库,供今天的新对话使用。而不是每次回答类似问题时,都依赖于模型从零重新推理。
这是推理架构和知识架构之间的一个循环反馈链路:
推理过程 → 产生上下文 → 从上下文中提取新知识 → 存入知识库 → 下一次推理时作为参考数据使用在第 10.2 节中我们讨论了知识的来源(人工整理、自动挖掘、模型生成)。这里的"上下文知识提取"就是模型生成知识的一个重要管道。提取出来的知识需要经过人工审核才能正式入库(避免模型产出的错误被固化),但至少你有了一个自动化的知识积累机制。
注意:上下文知识提取是有成本的——一次额外的模型调用 + 人工审核。所以它更适合高频重复的场景(如客服系统),以及知识本身有长期价值的场景(如行业术语定义、标准操作流程)。如果你的应用是低频的、每次任务互不相关的,这个环节可以跳过。
10.6.6 推理管理平台
前面的 10.6.1 到 10.6.5 讲的都是推理架构设计的"方法论"——怎么拆分步骤、怎么准备数据、怎么调参数、怎么处理结果、怎么管上下文。但方法论要落地,需要工具支撑。这就是推理管理平台的角色。
推理管理平台不是一个独立的"产品",而是你项目中支撑推理架构运行的那一套工具和基础设施。它涵盖三个层面:开发调试、运行监控、和实验迭代。
10.6.6.1 开发调试
在设计推理流程的阶段,你需要一个可以快速构建、调试、修改推理步骤的环境。这个环境应该具备以下能力:
- 可视化流程编排:通过拖拽或配置的方式定义推理步骤和执行图(DAG),而不是写在代码里反复编译。Dify 的 Workflow、LangGraph Studio 就是这类工具的典型代表。
- 步骤级调试:能够单独运行某个推理步骤,查看它的输入和输出,而不是必须从头跑完整个流程。这在你调试"步骤2 为什么输出不对"时节省大量时间。
- 提示词版本管理:每次修改提示词都应该有记录,可以回退到之前的版本。提示词的修改效果常常是"薛定谔的猫"——你以为改好了,实际上在某些 corner case 下更差了。版本管理让你可以回溯和对比。
10.6.6.2 运行监控
推理流程上线后,你需要知道它在生产环境中运行得怎么样。运行监控关注的关键指标:
- 成功率:多少推理流程成功完成了所有步骤?按步骤维度的成功率是多少?
- 平均耗时:整个推理流程以及每个步骤的平均耗时和 P99 耗时。如果某个步骤突然变慢,可能是模型服务端出现了变动。
- token 消耗:每个推理流程和每步的 token 消耗。这直接关联成本——如果你发现某个步骤的 token 消耗持续上升(比如因为上下文逐渐膨胀),需要及时介入。
- 异常分布:哪些类型的任务更常触发异常?异常的原因是格式问题、超时、还是内容质量问题?异常分布的统计可以帮助你找到需要优化的薄弱环节。
这些指标应该在统一的仪表盘上呈现,并设置告警——比如"步骤2 成功率低于 95%"或"P99 耗时超过 30 秒"时自动通知。
10.6.6.3 实验迭代
推理架构不是一次设计就定型的。你会不断尝试改进它——换个参数组合、改个步骤拆分方式、试试新的提示词策略。但这些改进不能"凭感觉"——你需要实验平台来支持 A/B 测试或影子测试。
A/B 测试:同时运行推理流程的两个版本(如当前的 v1 和实验性的 v2),将一部分流量分配给 v2,比较两个版本在核心指标上的表现(成功率、用户满意度、token 消耗)。在统计置信度足够高之后,决定是推广 v2 还是回退 v1。
影子测试:新版本不直接对用户生效,而是在真实流量上"影子运行"——用真实输入跑 v2 的推理流程,但输出不返回给用户(返回给用户的依然是 v1 的结果)。比较两个版本的输出差异。这种模式零风险(不好不会影响用户),适合验证重大架构变更。
回归测试集:维护一组固定测试用例,每次修改推理架构后跑一遍,对比结果变化。这个测试集应该覆盖你之前遇到过的各种边界情况——那些曾经过错了的 case,确保不会再次出现。
下一节我们来看这些方法论在真实工具中的落地(见 10.6.7 节)。
推理架构是大模型应用设计中逻辑最密集的一个子架构——它离代码最近,也离用户体验最近。任务架构定义了"做什么",知识架构和数据架构解决了"用什么",模型架构选择了"谁来干",而推理架构决定了"怎么干"。从步骤拆分到参数调校,从结果处理到上下文管理,每一步的设计都直接影响最终输出的质量和成本。
下一节,我们将分析几个经典的智能体推理工具架构(如 Claude Code、OpenClaw 等),用具体的工具案例来验证本节讨论的推理架构设计理念——看它们在实现中是如何体现这些设计原则的。
10.6.7 经典推理工具架构分析
前面几节我们分别讨论了推理步骤设计、推理前准备、参数设定、结果处理和上下文管理——这些构成了推理架构的理论框架。你可能会有一个很自然的疑问:这些理论在真实的工具中是如何落地的?现有的主流智能体框架,它们的推理架构长什么样?
这一节,我们以 Claude Code 和 OpenClaw 两个代表性工具为样本,拆解它们的推理架构,看一看理论与实践之间的对应关系。选择这两个工具的理由很简单:Claude Code 是目前应用最广泛的 AI 编程助手之一,OpenClaw 则是开源智能体框架中增长最快的项目——它们代表了当前智能体推理架构的两条主线:封闭式深度集成和开放式插件生态。
10.6.7.1 Claude Code 的推理架构
Claude Code 是 Anthropic 推出的 AI 编程工具,能够自主执行 Shell 命令、读写文件、调用外部服务。2026 年初的一次 npm 包配置失误意外暴露了其约 50 万行 TypeScript 源码,让我们得以一窥其内部架构的全貌。而其中最核心的发现是:驱动这一切的,是一个极其简洁的主循环(master loop)。
主循环:一个简单的 while-loop
Claude Code 的核心推理架构可以概括为四行伪代码:
while (model返回了工具调用):
执行工具调用
将工具执行结果追加到对话历史
再次调用模型
// 模型返回纯文本(无工具调用)时,循环终止这个循环被称为 "master agent loop"。它运行在单线程中,维护一个扁平的消息列表,没有复杂的多 Agent 竞争、没有嵌套子任务树。Anthropic 的设计哲学在这件事上非常明确:用最简单的控制流实现可控的自主性。
但"简单"不等于"简陋"。在这个主循环之上,Claude Code 构建了一套丰富的支撑系统。
工具层:Claude Code 提供了约十几个内置工具——View(读文件)、Glob(通配符搜索)、GrepTool(正则搜索)、Edit(精确打补丁)、Write(覆写文件)、Bash(Shell 执行)、WebFetch(URL 获取)、NotebookRead/Edit(Jupyter 处理)、TodoWrite(任务规划)等。值得一提的是,在搜索能力上,Anthropic 选择了正则表达式而非向量数据库——工程师认为模型本身已经足够理解代码结构、能构造高质量的 regex 模式,引入向量索引反而增加了不必要的复杂性。
规划层:当面对多步骤任务时,Claude Code 会首先调用 TodoWrite,生成一个结构化的 JSON 任务列表,包含 ID、内容、状态和优先级。任务列表在 CLI 界面中渲染为交互式清单,用户可以实时看到智能体的执行计划进展。这实际上构成了推理架构中的任务分解与流程规划。
上下文管理:Claude Code 实现了一套五层压缩管线。关键机制包括一个自动触发的压缩器(内部代号 wU2),它在上下文窗口使用率约 92% 时自动启动,对对话历史进行摘要并将关键信息持久化到一个 Markdown 文件中,作为项目的"长期记忆"。这对应着推理架构中的上下文压缩与存储(五层压缩管线具体包括摘要、截断、优先级排序、去重和归档)。
子 Agent 机制:Claude Code 支持子 Agent 委派,但设计上刻意限制了并发——同一时间最多一个子 Agent 分支。这是为了防止 Agent 数量失控带来的不可预测性,体现了"安全优先于性能"的设计取向。
实时干预:通过一个名为 h2A 的异步双缓冲队列,用户可以在任务执行中途注入新指令,Claude Code 会在当前步骤完成后无缝调整计划。这个机制让 Claude Code 从"批处理器"变成了真正的"编码伙伴"。
对照六大子架构
如果把我们前面讨论的六大子架构映射到 Claude Code 的设计上,你会发现一个很有意思的现象:
| 子架构 | Claude Code 中的对应 |
|---|---|
| 任务架构 | TodoWrite 的任务分解 + 主循环的调度执行 |
| 知识架构 | 压缩器持久化的 Markdown 长记忆 + 模型内化知识 |
| 数据架构 | 文件系统读写 + WebFetch + Grep 搜索 |
| 模型架构 | Anthropic 模型后端(可通过 API Key 或云服务接入) |
| 推理架构 | 主循环 + 工具路由 + 上下文管理 + 子 Agent |
Claude Code 并没有"跳过"这些架构设计——它只是在一个精心设计的 Harness 层中将其全部封装了。用户看到的是"给一个指令,智能体自动完成",但内部的每一步——为什么先搜索再读文件再编辑——都经过了架构层面的权衡。
Claude Code 的架构选择背后有一个清晰的工程判断:对于编程任务这个特定领域,单线程的顺序执行已经足够有效,引入复杂的并行调度和多 Agent 协调反而增加了不稳定因素。这不是架构设计的缺失,而是一种有意识的"克制"——知道什么不需要做,和知道什么需要做,同样重要。
10.6.7.2 OpenClaw 的推理架构
OpenClaw 是一个开源的个人 AI 助手框架,据 GitHub 公开数据显示,截至 2026 年 3 月已获得约 24.7 万 GitHub Star。与 Claude Code 专注于编程场景不同,OpenClaw 的定位更宽泛:让一个 AI Agent 通过 20 多种聊天渠道(WhatsApp、Telegram、Slack、Discord、iMessage 等)与用户交互,同时具备 Shell 执行、浏览器自动化、文件管理、日程控制等能力。
如果说 Claude Code 代表的是"封闭式深度集成",那么 OpenClaw 代表的就是"开放式插件生态"。这两种设计路径在推理架构上有着截然不同的取舍。
四层架构
OpenClaw 的架构分为四个层次:
Layer 1 — 渠道适配层:将 20+ 聊天平台的消息统一转换为标准 Schema,处理各平台的认证机制(OAuth、Bot Token、二维码等),并执行访问控制(白名单、DM 配对、群组 @提及门控)。
Layer 2 — 网关控制平面:一个 Node.js WebSocket 服务器,默认绑定 127.0.0.1:18789。它负责消息路由——接入控制 → 会话解析 → Agent 调度——并协调系统状态(会话管理、定时任务、Webhook、健康监控)。
Layer 3 — Agent 运行时:这是推理架构的核心。它使用 Pi Agent Core 库进行会话解析和上下文组装:加载会话历史 → 构建动态系统提示词 → 执行语义记忆搜索(基于向量嵌入) → 进入推理循环。推理循环的流程与 Claude Code 类似:流式调用模型 → 拦截工具调用 → 执行工具 → 持久化结果 → 继续循环。同时支持模型故障转移——检测到限速时自动切换提供商。
Layer 4 — 工具与执行层:提供数十个内置工具,包括 Shell 执行、浏览器自动化(基于 CDP 协议)、文件操作、定时任务等。工具可用性受 allow/deny 策略和沙箱设置控制。此外还支持插件系统扩展自定义工具,以及可选的 Docker 沙箱隔离。
两个关键机制:MCP 与 SKILL
OpenClaw 的推理架构中,两个扩展机制值得特别关注。
MCP(Model Context Protocol) 是大模型与外部工具的连接协议。OpenClaw 作为一个 MCP 宿主,可以接入任何实现了 MCP 协议的外部服务——数据库查询、文件操作、搜索、API 调用等。这让 OpenClaw 的工具能力可以无限扩展,不需要框架开发者为每一种工具写适配代码。从推理架构的角度看,MCP 解决的是"推理过程中如何获取外部数据"的问题——它本质上是数据和知识架构的标准化管道。比如接入一个 MySQL MCP 服务后,Agent 就能直接回答"上个月卖了多少",而不需要开发者单独写数据库查询代码。
SKILL 机制 则是另一种思路。一个 SKILL 就是一个 SKILL.md 文件(包含 YAML 头部和 Markdown 正文),定义了特定领域的工作流程和可用的工具组合。SKILL 可以被动态加载,让 Agent 瞬间拥有该领域的处理能力。从推理架构的角度看,SKILL 解决的是"推理过程中如何装载领域知识和方法论"的问题——它是知识架构的模块化实现。比如一个 PDF 处理 SKILL 加载后,Agent 就能理解"提取第 3 页表格"这种指令,自动选择合适的 PDF 解析工具。
对照六大子架构
OpenClaw 与六大子架构的映射关系如下:
| 子架构 | OpenClaw 中的对应 |
|---|---|
| 任务架构 | Agent 队列机制 + 消息路由 + 定时任务调度 |
| 知识架构 | SKILL 文件(领域知识) + 语义记忆搜索(向量嵌入) |
| 数据架构 | MCP 服务连接(外部数据) + 浏览器自动化 + 文件系统 |
| 模型架构 | 多模型支持 + 故障转移(对外可配置) |
| 推理架构 | Agent 运行时主循环 + 工具拦截执行 + 上下文组装 |
OpenClaw 的架构设计体现了另一种取舍:与其像 Claude Code 那样为目标场景做深度优化,不如构建一个开放平台,让社区通过 MCP 和 SKILL 来定义各种场景下的推理逻辑。这种"平台化"策略的好处是极大的灵活性,代价则是推理质量的"天花板"取决于社区贡献的 MCP 服务和 SKILL 的质量。
10.6.7.3 两种架构范式的对比
把 Claude Code 和 OpenClaw 放在一起看,你会发现它们背后反映的是智能体推理架构设计的两种基本范式:
| 维度 | Claude Code(深度集成) | OpenClaw(开放生态) |
|---|---|---|
| 核心循环 | 单线程 while-loop | 多 Agent 队列 + 事件驱动 |
| 任务分解 | TodoWrite 结构化规划 | Agent 调度 + 计划执行 |
| 工具接入 | 内置工具集(约 15 个) | MCP 协议 + 插件(可无限扩展) |
| 知识管理 | 压缩器持久化 + Markdown 记忆 | SKILL 文件 + 向量语义搜索 |
| 上下文策略 | 五层压缩管线 | 会话历史 + 动态提示词组装 |
| 安全模型 | 权限模式 + ML 分类器 | allow/deny 策略 + Docker 沙箱 |
| 并发策略 | 严格限制子 Agent 并发 | 多 Agent 独立队列 |
| 设计哲学 | 少即是多,克制优于灵活 | 开放平台,生态优于集成 |
但无论哪种范式,有一个结论是相同的:它们都没有"跳过"推理架构——只是以不同的方式实现了它。
Claude Code 的实现方式是"隐式架构":架构决策已固化在代码中,用户不需要理解、也无法改变。OpenClaw 的实现方式更接近"显式架构":用户可以配置哪些 MCP 服务可用、加载哪些 SKILL、调度哪些 Agent、使用什么模型——架构是可见且可调的。
10.6.7.4 从工具分析看推理架构的普适性
回到本章的主题——六大子架构中的推理架构。通过分析 Claude Code 和 OpenClaw 这两个当前最具代表性的智能体框架,我们可以得出三个关键观察:
第一,推理架构的核心要素是通用的。 不论你用的是商业闭源工具还是开源框架,推理架构始终包含这几个关键环节:接收输入 → 理解意图 → 匹配工具/知识 → 执行 → 评估结果 → 决定下一步。差别仅在于每个环节的实现策略和优化深度。
第二,架构设计的取舍决定了工具的边界。 Claude Code 的单线程主循环让它非常可靠,但也限制了它在需要大规模并行处理的场景下的效率。OpenClaw 的开放生态让它几乎能接入任何能力,但 MCP 和 SKILL 的质量参差不齐意味着推理稳定性高度依赖外部。没有"最好的架构",只有"最适合你场景的架构"。
第三,集成工具的架构也是架构。 很多人用着 Claude Code 就觉得"不需要做架构设计",但 Claude Code 本身就是一个高度优化的架构产物。它帮你做了决策,不等于不存在决策。了解这些工具的架构原理,不是为了重复造轮子,而是为了在需要的时候知道——工具的默认架构在什么地方可能不够用,以及你应该在哪个环节"插手"。
下一节,我们将从这些具体的工具分析中抽身出来,讨论一个更基础的问题:架构设计到底是不是必须的?在什么情况下你可以完全依赖集成工具,在什么情况下必须自己动手设计?
10.7 架构设计是必须的吗?
前面用了九个小节遍历了六大子架构的设计要点,你可能会有一个很自然的疑问:这些设计真的都必须做吗?2026 年的今天,Claude Code、OpenClaw 这类智能体框架已经有了极大的发展,MCP 生态中各种开源服务层出不穷,SKILL 模式也在日益壮大,很多功能似乎直接用现成工具就能完成。在这样的技术环境下,传统意义上的"架构设计"到底还有没有价值?
这个问题的答案取决于你站的角度。
10.7.1 微观视角:架构设计不是必须的
从"让一个大模型完成一件事情"的角度看,架构设计确实不是必须的。
一个典型的例子:打开 Claude Code,用自然语言描述"帮我分析这份数据并生成报表",Claude Code 会自动规划步骤、调用工具、读取文件、执行代码、输出结果。整个过程你不需要关心知识架构、不需要设计推理管线、不需要考虑任务编排——工具已经帮你把这些事情做完了。类似地,在 OpenClaw 中配置一个 Agent,描述它的角色和能用的工具,启动后它就能自主执行。一个熟练的开发者用这些工具,可以在几小时内搭出一个能跑的原型。
这种"低门槛"得益于三个关键因素:
智能体框架的能力跃升。 以 Claude Code 和 OpenClaw 为代表的新一代智能体框架,已经将任务规划、工具调用、上下文管理、多轮对话等能力打包封装。它们内置了一套隐式的"架构"——任务分解、工具路由、记忆管理——只不过这个架构对使用者是透明的。你不需要自己设计,框架替你做了默认决策。
MCP 服务的网络效应。 MCP(Model Context Protocol)作为大模型与外部工具的连接协议,已经形成了相当丰富的生态。数据库查询、文件操作、搜索服务、API 调用——你能想到的能力,基本上都有对应的 MCP 服务。这种"插拔式"的工具接入方式,大幅降低了构建大模型应用的工程成本。
SKILL 模式降低了重复性工作。 SKILL(可复用的领域指令集)让特定领域的专业能力可以像"插件"一样被加载和组合。你不用从头设计知识架构,直接找一个合适的 SKILL 就能让模型拥有那个领域的处理能力。这对于路径清晰、知识高度结构化的场景尤其有效。
所以,如果你的需求简单、路径清晰、领域知识已经标准化,直接用集成框架可能就够了。
10.7.2 宏观视角:架构设计仍然必要
但如果把视野拉到"解决真实业务问题"的层面看,架构设计不仅是必要的,而且决定了应用能走多远。
首要理由是工具不是应用。 不论是用商业大模型的推理 API,还是自建推理框架,这些都属于"基础设施"层面,而不是"应用"本身。大模型应用的核心目标是解决业务问题,而解决业务问题意味着你需要把推理能力嵌入一个完整的闭环中——输入从哪里来、中间经过哪些处理节点、输出到哪里去、异常怎么处理、效果如何衡量。这些就是架构设计要解决的问题。工具只能提供组件,架构才能把这些组件串联成可运转的系统。
更深一层来看,大模型应用的本质依然是软件系统。 经典软件工程关于架构设计的原则并没有因为大模型的出现而失效——关注点分离、接口定义、错误处理、性能优化、可维护性,这些仍然是决定系统质量的关键因素。事实上,大模型应用的非确定性特征让架构设计变得更重要了,因为你需要在不稳定的推理行为之上构建稳定的业务保证。一个好的架构可以让开发团队清楚地知道哪些环节可控、哪些环节需要容错、哪些环节需要人工兜底。
第三个理由涉及应用框架的发展节奏。 这是一个容易被忽视的事实:大模型的能力已经很强了,但"如何用好大模型"的工程实践还远未成熟。历史上每一次技术浪潮都是如此——技术先跑出来,应用框架和最佳实践需要时间来沉淀。在框架尚未稳定的阶段,深入理解架构设计意味着你可以做出更好的技术判断,而不是被动地跟随工具的默认行为。
10.7.3 集成框架也有架构,只是被封装了
实际上,哪怕你只用了 Claude Code 或 OpenClaw,架构设计也并没有"消失",只是被工具内置了。我们可以分析一下这些框架在运行时做了什么:
当你给 Claude Code 一个复杂任务,它会自动完成以下步骤:
- 理解意图——解析你的需求,识别核心目标和约束条件
- 任务分解——将大目标拆分为可执行的子任务序列
- 工具匹配——根据每个子任务的需求,选择合适的工具(文件读写、代码执行、搜索等)
- 执行与反馈——逐步执行子任务,根据中间结果调整后续步骤
- 整合输出——将各步骤的结果整合为最终交付
对照一下我们前面讨论的各子架构,六大子架构在集成框架中都有对应的映射:任务分解对应任务架构,工具匹配对应推理架构,文件操作和搜索对应知识架构的数据通道。剩下的三个同样能找到落点——能力架构体现在框架的工具抽象与编排机制中:每一个接入的 MCP 服务就是一个可组合的能力单元,框架负责能力发现、选择和串联;模型架构反映在框架对模型的选择、切换和配置管理上:你可以指定任务用哪些模型跑、什么条件下切换,框架帮你做了一层统一的模型接入抽象;数据架构则隐藏在上下文窗口管理、中间结果缓存和工具间数据流转的机制里:框架负责在长对话中维护状态、在工具间传递数据、在输出中整合多源结果。
你会发现,Claude Code 并没有"跳过"架构设计——它只是在一个预先定义好的架构框架内自动化执行了这些步骤。同理,OpenClaw 的 Agent 队列机制、MCP 服务的注册与路由、SKILL 的加载与组合,这些本身就是一套架构选择的产物。
换句话说,集成工具不是替代了架构,而是固化了一种特定的架构范式。这种范式在以下场景中表现良好:
- 任务路径相对清晰,可以被分解为线性或树状的子步骤
- 领域知识高度标准化,存在成熟的工具和 SKILL 可以覆盖
- 容错要求不高,模型推断的误差在可接受范围内
但如果你的场景超出了这些条件——比如业务流程涉及多个异构系统的复杂协调、知识无法用现有 SKILL 覆盖、对结果准确性有严格度量要求——那就需要回到架构设计层面来解决问题了。
10.7.4 一个务实的策略:三步走
那在实践中到底该怎么判断?本节尝试将前面的讨论归纳为一个可操作的判断框架。
在讨论三步走之前,有一个前提:先想清楚你要用大模型做什么。 这听起来像一句正确的废话,但仔细想想——很多时候架构过度设计或者设计不足,根源都在于对"要在哪个环节用大模型"这个问题的回答不够清晰。大模型适合做推理、总结、分类、生成,但不一定适合做精确计算、高频事务处理、需要严格时序保证的操作。先划定大模型在业务流程中的位置,再决定用什么方式实现它。如果你不确定从哪里开始,一个实用的切入方法是:把业务流程拆到具体任务粒度,逐一问"这一步大模型能不能比规则引擎做得更好"——答案出来的地方,就是大模型应该进入的地方。
明确了目标之后,可以按以下顺序尝试:
第一步:直接在集成框架中尝试。
从 Claude Code、OpenClaw 等工具入手,前往 SKILL 生态(如 SkillHub[41])中搜索是否存在适合你需求的功能模块。如果你的需求恰好落在一个已有的 SKILL 覆盖范围内——比如代码审查、文档生成、数据摘要——那么直接使用集成工具可能就足够了。
这一步的关键是"快速验证":花一个下午的时间,用一个真实的小场景跑通整个流程。如果工具能完成 80% 以上的工作,且剩下的 20% 可以用简单的规则或人工补充,这个方案就是可行的。
第二步:补充知识架构。
如果第一步不够,说明问题不在于"工具能不能做",而在于"模型缺知识"。这时候你需要引入知识架构的设计:梳理大模型完成任务所需的知识、将这些知识整理成大模型可以高效使用的数据形式(提示词模板、结构化文档、向量索引等),然后把这些知识数据叠加在第一步的集成框架之上,再次尝试。例如,一个法律咨询工具在第一步可以调用通用 LLM 回答问题,但要想准确引用具体法条和判例,就需要把相关法律文档整理成向量索引作为知识底座——这就是第二步的典型场景。
这一步的本质是:工具提供了"做事的能力",知识架构提供了"做对事的判断依据"。两者结合,可以解决很多单纯依赖工具无法覆盖的场景。需要说明的是,知识架构不是只有"向量索引"一种形式——根据场景的复杂程度,你可以从最简单的提示词模板(几行规则即可)到结构化文档(JSON/YAML 格式的知识条目)再到向量索引(需要检索的非结构化知识),选择合适的形式来组织知识。
第三步:引入推理架构。
如果前两步还是不够——例如业务流程需要多步推理且每一步的结果影响后续决策,或者需要在多个模型/工具之间做动态路由——这时候就需要进行推理架构的设计了。通过显式定义推理管线(Planner → Executor → Evaluator → …),在集成框架之上补充决策逻辑和流程控制,完成从"让模型做一件事"到"让模型系统性地解决问题"的跃迁。
需要说明的是,这三个步骤不是互斥的。在实际项目中,你可能会发现有些子任务第一步就能搞定,另一些子任务需要走到第三步。分层、组合、因地制宜,才是架构设计的真正智慧。
一个实用的判断标准:如果你的业务流程中规中矩——输入→处理→输出,中间没有多轮"根据上一步结果决定下一步"的分支逻辑,那么第一步或第二步通常就足够了。只有当你的决策链超过三步、且每步决策依赖上一步的输出时,推理架构才真正派上用场。换句话说,推理架构的价值不取决于任务的"大小",而取决于任务决策链的"深度"。
10.7.5 两个需要权衡的额外维度
以上讨论聚焦在"架构要还是不要"的二元选择上。但在实际工程中,还有两个无法回避的维度常常与架构决策交织在一起,需要单独拎出来权衡。
其一,公有模型 vs 私有模型。 如果你依赖的公有模型推理服务在性能、延迟或数据合规方面遇到了瓶颈,是否应该引入私有模型?这是一个需要测试才能回答的问题。私有模型虽然在数据安全和定制化方面有优势,但推理性能和运维成本是现实挑战。实践中的常见做法是"混合部署":高频、低延迟的任务走公有模型 API,敏感数据和领域特定任务走私有模型。但这个选择应该在架构设计阶段就做评估,而不是在生产环境出问题后才被动应对。
其二,推理成本的管理。 这是另一个容易被忽视但影响深远的维度。大模型推理不是免费的,尤其在规模化部署时,Token 消耗会迅速攀升。如果你的应用依赖频繁的模型调用,那么推理架构中应该包含成本控制策略——比如缓存高频查询结果、引入结果评估机制避免无效重试、用小型模型预处理后再由大模型精调。架构设计不仅是"让系统能工作",更是"让系统可持续地工作"。
回到最初的问题:架构设计是必须的吗?
如果你只是想把玩大模型、做几个 Demo 或者完成一个路径清晰的单次任务——不需要。集成框架已经足够好,不要让架构设计成为"过早优化"。
但如果你面对的是一个需要长期维护、涉及多个子系统、对结果质量有明确要求的业务场景——不做架构设计,短期内可能更快,长期来看一定会付出更高的维护成本。
务实的做法是:先想清楚大模型在你的业务中的位置,然后用"三步走"策略逐步验证——从现有工具开始,知识不够补知识,流程不够补推理。大多数场景下,走到第二步就足够了。少数高复杂度的项目才需要完整的推理架构设计。但无论你最终走到哪一步,一个最基本的原则不变:带着架构意识去使用工具,而不是被工具的默认行为牵着走。
下一节预告:在明确了架构设计的必要性之后,我们将通过几个真实的工程案例,看看这些架构原则在实践中是如何落地和演进的。
10.8 大模型架构实践参考
假设你读完了前面十六个小节,理解了六大子架构各自的设计要点,也接受了"架构设计在宏观层面是必须的"这个观点,下一个问题几乎是不可避免的:具体怎么落地?
不同的应用类型,六个子架构的"权重"和"形态"差异很大。一个知识问答系统和一个硬件控制系统,在架构上的侧重几乎完全不同。本节不打算泛泛地说"根据情况灵活处理"——那等于没说。我们会选择四种最常见的应用类型,逐类分析六大子架构各自需要做什么、侧重什么、可以简化什么,并给出一个可操作的设计流程。
10.8.1 知识问答类应用
知识问答是大模型最"本分"的应用场景。严格来说,大模型本身就是被设计来"看文字、回答问题"的。所以这类应用在六大子架构上的特点是:任务架构最简单,知识架构是核心,推理架构需要精细设计,模型架构和数据架构居中。
任务架构:目标清晰,边界容易划定
知识问答类应用的任务定义通常很直接——用户问一个问题,系统给出一个准确的答案。复杂的地方在于问题来源和答案交付形式。
问题的来源大致有三类:结构化查询(用户用固定表单提交问题)、自然语言查询(用户自由输入)、上下文延续(多轮对话中的追问)。答案的交付形式可能是纯文本、带引用的结构化答案、甚至带图表的多模态结果。
在任务架构设计阶段,需要明确的核心问题:
- 问题域的范围。是开放域(问什么都行)还是封闭域(只回答特定领域的知识)?封闭域对知识架构的要求更高,但答案质量更容易控制。开放域对模型的通用能力依赖更强,需要更完善的兜底策略(如"不知道"的声明机制)。
- 多轮对话的支持程度。单轮问答只需要处理一轮输入的上下文;多轮对话需要管理对话历史,处理指代消解("它"指什么)、话题追踪(从问题A自然过渡到问题B的追问)等问题。
- 答案质量标准。用户期望的是"一句回答"还是"附带引用来源和分析过程"?如果是医疗、法律等高风险领域,答案可追溯性是必选项。
可以简化的部分:任务分解和流程调度。问答是典型的"输入→推理→输出"线性模式,不需要复杂的多步骤编排。任务架构这块,一张流程图基本就能说清楚。
知识架构:整类应用的核心
知识问答的本质挑战不是"怎么答",而是"答什么"。如果你只靠模型参数中存储的通用知识,在专业场景下几乎一定会出问题——模型可能不知道,更危险的是不知道自己不知道,从而给出一个"听起来合理但完全错误"的答案(即所谓"幻觉")。
知识架构设计需要覆盖以下几个关键环节:
知识来源的梳理。 你需要问自己:这个问答系统需要的知识存在于哪里?是已经被文档化的(产品手册、制度文件、学术论文),还是存在于专家头脑中的经验判断?是公开知识还是内部机密?知识来源决定了知识收集和整理的方式。
知识的可持续更新。 知识不是静态的。产品功能会升级、政策法规会变化、行业术语会演化。知识架构中需要定义更新周期和更新机制——哪些知识需要实时同步(如库存数据)、哪些可以按月更新(如产品手册)、哪些适合用微调固化(如核心领域的术语定义和关联关系)。
检索增强生成(RAG)的设计。 对于大多数知识问答场景,RAG 是当前最成熟的方案。但"把文档切块、向量化、检索"只是 RAG 的骨架,真正的工程挑战在细节上:
- 切分策略:按段落切还是按语义切?粒度太粗检索精度不够,太细则上下文碎片化。实践中通常需要混合粒度——先粗检索定位文档段落,再细检索定位具体句群。
- 检索方式:单纯的关键词匹配在高专业度的领域经常不够用,需要结合同义词扩展、领域词典、甚至让大模型先改写用户问题再检索(Query Rewriting)。
- 答案融合:检索到的文档片段可能相互矛盾(同一问题的不同版本回答),也可能相互补充。让大模型基于多个来源片段综合生成答案,而不是简单拼接,是 RAG 工程的重点。
知识架构中常见的可以跳过的坑:
- 不要一开始就做全量微调。 很多团队上来就想"我们把这行业的知识全部微调进模型",这在实践中有两个问题:第一,知识是动态的,微调一次的成本不低,频繁微调不现实;第二,微调更适合让模型"掌握模式"而非"记住事实",纯知识注入用 RAG 效率更高。先跑通 RAG 管线,确认精度瓶颈在哪里,再针对性选择微调的子集。
- 不要迷信向量检索的精度。 向量检索(Embedding)在"找语义相似的文档"上很强,但在"精确匹配专业名词"上经常不如简单的关键词搜索。好的检索系统通常是向量+关键字的混排(Hybrid Search),而不是只用一种方式。
- 不要忽略检索的"排序后处理"。 检索召回了 10 段候选,但你只能塞给模型 3 段(受上下文窗口限制)。如何从 10 段中选出最相关的 3 段?这需要重排序(Reranker)——用一个小而快的模型对候选片段做二次评分。这个环节经常被忽略,但它对最终答案质量的影响非常大。
数据架构:为检索服务
知识问答的数据架构把精力主要放在数据格式化和检索索引的构建上。
知识数据需要被处理成适合检索的形态。结构化数据(数据库中的表)可以直接查询,非结构化数据(文档、PDF、网页)需要被切分、清洗、嵌入向量化。这里需要注意"检索友好"的数据格式设计——比如每段文档附带元数据(来源、更新时间、作者、分类标签),这些元数据可以用于过滤和重排序。
一个常见的误区是把所有数据一股脑塞进向量数据库中。实际上,知识问答中有些问题更适合用结构化查询("上季度销售额是多少?"),有些适合语义检索("退货率高的主要原因是什么?")。数据架构需要根据问题类型,设计多路检索(SQL + Embedding + 关键字)的数据通路。
模型架构:推理优先,微调有选择
知识问答对模型的推理能力(理解问题、综合多源信息、逻辑判断)要求高,对创造性要求低。模型选择时通常偏好"温度低、指令遵循强"的模型。
如果领域知识足够小众(比如特定企业的内部系统、特定行业的专属术语),光靠通用模型的零样本能力可能不够。此时可以考虑"轻量微调"——不是把所有知识灌进去,而是用少量高质量的问答对训练模型学会"这个领域的答案长什么样"和"这个领域的术语怎么用"。这种微调的目标不是"记知识",而是"学会说话方式"。
推理架构:从简单到复杂
简单的知识问答是"用户问→RAG 检索→模型生成→返回"。但如果你要做一个真正好用的问答系统,推理架构通常需要多步设计:
输入预处理。 用户的问题可能含糊、带有错别字、或缺少关键信息。在送入检索之前,可以先用一个轻量级模型做"问题澄清"——改写问题、补充上下文、甚至判断问题是否属于系统能回答的范围(意图识别)。
检索-生成循环。 单轮检索可能不够。如果模型在生成答案时发现关键信息缺失("这个文档没提到XX的条件"),可以触发补充检索——用模型生成的中间判断反向查询知识库。这种"检索→生成→再检索"的循环模式,是高质量问答系统的常见架构。
答案后处理。 模型生成的答案可能存在事实错误或信息遗漏。后处理环节可以用规则(如数据字典校验数值范围)或二次推理(让模型自我检查)来降低错误率。对于高风险场景,还可以引入"人工审核节点"——模型的答案先进入审核队列,确认后才能返回给用户。
知识问答架构设计流程总结
- 明确问题域 → 决定知识范围,划定答案质量标准
- 梳理知识来源 → 文档化知识、专家经验、实时数据各自在哪儿
- 确定知识更新机制 → 什么频率更新,用什么方式(实时 / 批处理 / 微调)
- 设计数据通路 → 多路检索(向量+关键字+结构化),Reranker 重排序
- 选择模型 → 低温度推理优先,按需做轻量微调
- 设计推理管线 → 问题预处理 → 检索 → 生成 → 补充检索(按需)→ 后处理
- 设置兜底策略 → 不知道就说不知道,不要让系统"强行回答"
10.8.2 内容生成类应用
内容生成是最近两年大模型最"出圈"的场景——写文章、写代码、写邮件、写营销文案、生成图片、生成视频……种类繁多,共性也明显:输入是需求描述,输出是创作内容。
与知识问答不同,内容生成在架构上的特点是:任务架构需要精细定义"好内容"的标准,知识架构以"风格和范例"为主而非"事实",推理架构更关注迭代优化而非一步到位,模型架构是选型的重头戏。
任务架构:定义"好"是关键
内容生成最大的挑战不是"能不能生成",而是"生成的内容够不够好"。而"好"是一个主观标准,你需要在任务架构阶段把这个主观标准尽可能拆成可衡量、可验证的指标。
通常可以从以下几个维度定义内容质量标准:
- 准确性:不包含事实错误(对技术文档、新闻报道类尤其重要)
- 风格匹配:语气、用词、句式符合目标受众和品牌调性
- 结构清晰:逻辑通顺,段落层次合理
- 原创性:不是简单复制训练数据中的内容
- 合规性:内容不违反法律法规和平台规则
这些标准不能停留在"心里有数"。在实际工程中,你需要把它们变成可执行的评估规则——例如"每个技术声明必须附引用来源""营销文案不能使用绝对化用语""代码示例必须通过运行验证"。这些规则既是提示词工程的约束条件,也是后续内容审核的检查清单。
知识架构:风格即知识
内容生成需要"知识",但这个知识和知识问答中的知识不太一样。后者是"事实",前者更偏向"范例"和"风格"。
范例(Few-shot Examples) 是内容生成最实用的一种"知识注入"方式。你不需要告诉模型"好的技术文档长什么样",你只需要在提示词中附上 2-3 个高质量的例子,模型就能学会风格。范例的选择有讲究:应该覆盖内容类型的"典型情况"和"边界情况"(比如不同难度、不同长度的稿件),而不是塞一堆雷同的样本。
风格约束 是对内容调性的明确限定。比如"请用平实、理性的语气,避免感叹号和夸张修辞,技术术语在首次出现时附简要解释"——这本质上是一种结构化知识,可以固化在提示词模板中。
领域知识 依然重要,但它的作用是"保证内容准确"而非"回答问题"。比如生成一篇关于新能源汽车电池的技术文章,模型需要了解电池的类型、核心参数、行业术语——这些知识的注入方式和知识问答中的 RAG 类似,但检索触发时机不同:不是等用户"问",而是在内容生成过程中作为"参考材料"预加载。
模型架构:质量 vs 成本的双重考量
内容生成对模型的质量比知识问答更敏感。一篇语句不通、逻辑混乱的文章和一篇流畅清晰的文章,用户感受天差地别。但高质量的模型通常费用更高、推理更慢。
实践中常见的策略是"模型分级":
- 草稿模型:用快速、廉价的中等规模模型生成初稿。这一步的核心目标是"把框架和主要信息点拉出来",不需要完美。
- 精修模型:用高质量模型做内容润色、逻辑修正、风格优化。很多时候你不是让精修模型"从零写",而是让它"改进草稿",这比让它独立创作更可控。
- 专项模型:特定类型的内容可能需要特定优化的模型。比如代码生成用代码专项模型,图像生成用扩散模型或多模态生成模型。
对于需要多模态输出的场景(图文混排、视频等),模型架构还需要解决"不同模态之间的协调"——文字描述谁来写、图片谁能生成、两者的承接关系如何管理。
推理架构:迭代生成是主旋律
内容生成很少"一次通过"。更常见的模式是:
生成 → 检查 → 修改 → 再检查 → 定稿
这个迭代循环中,每个环节都可以借助大模型本身的能力:
- 检查环节:用另一个模型(或同一个模型以不同角色)扮演"编辑",对草稿做事实核查、风格评审、合规检查。
- 修改环节:模型根据编辑反馈针对性地修正内容,而不是全部推倒重来。这需要推理架构设计"增量修改"的能力——让模型理解"第3段的数据有问题,请只修改这一段,保持其余部分不变"。
- 终止条件:迭代不是无限进行的。你需要设定一个明确的"定稿标准"(如编辑评分>X分、或人工确认通过、或迭代次数达到上限),防止系统在某一段文字上无限循环。
数据架构:范例库和模板的管理
内容生成的数据架构相对轻量。核心管理的两类数据是:
- 范例库:高质量的内容范例,按类型、风格、难度打标签,供生成时动态选择装配。
- 模板库:结构化的提示词模板,封装了不同内容类型的标准框架、风格约束和质量检查清单。
这些数据不需要复杂的向量检索——大多数场景下,按标签分级匹配就够了。
内容生成架构设计流程总结
- 定义内容质量标准 → 拆解为可检查的规则
- 确定风格和范例 → 准备 Few-shot 样本和风格约束卡片
- 建立模板和范例库 → 结构化存储,按需调用
- 设计模型分级策略 → 草稿模型→精修模型,按需补充专项模型
- 设计审查-修改循环 → 自动审查+定向修改+明确终止条件
- 设置合规检查 → 内容发布前的自动化筛查
可以避免的过度设计:
- 不需要为内容生成建复杂的知识图谱或向量检索系统(除非内容涉及大量实时事实核查)
- 不需要复杂的任务编排——内容生成通常是单目标线性任务,过度分拆步骤反而降低连贯性
10.8.3 数据分析类应用
数据分析类大模型应用是一个相对特殊的类别。它的核心不是"回答问题"或"生成内容",而是**"理解数据的含义,发现数据中的规律,并把发现的结果用人类可以理解的方式表达出来"**。
这意味着在六大子架构中,数据架构和推理架构是这类应用的两个重头戏,任务架构居中,模型架构和知识架构相对轻量。
任务架构:明确分析目标和交互模式
数据分析不像问答那样有明确的"输入-输出"模型。你需要先定义清楚"分析什么"和"怎么交互"。
分析范围:是单表分析还是跨表关联?是描述性统计("过去一个月的趋势如何")还是根因分析("为什么销售额下降了")?是探索式分析("帮我看看数据里有什么值得注意的")还是预设分析("每天生成营收日报")?
交互模式:数据分析类应用通常有两种交互方式——对话式(用户用自然语言提问,系统实时返回分析结果)和报表式(预设分析流程,定期自动执行)。对话式的推理架构需要更强的"意图理解→工具路由→结果解释"能力,报表式的任务架构更强调稳定性和可调度性。
交付形式:纯文本摘要、带图表的分析报告、可交互的数据看板、还是 Excel/CSV 文件下载?交付形式决定了推理输出的形态,也影响后续的数据架构设计。
数据架构:此类应用的核心战场
数据分析类应用的数据架构设计,比前面两类复杂得多。它不是"把知识文档向量化",而是"让大模型能够理解、查询、操作真实的数据"。
数据接入层。分析对象可能是数据库(MySQL, PostgreSQL)、数据仓库(ClickHouse, Snowflake)、数据湖(Parquet 文件)、实时流(Kafka 消息)。数据架构需要抽象一层"数据接入"——让上层推理逻辑不需要关心底层数据在哪、是什么格式。
Schema 认知。大模型本身不知道你的数据库里有哪些表、每个表有哪些字段、字段之间有什么关联。数据架构中的一个关键设计是"Schema 注入"——把数据库的表结构、字段说明、表间关系以结构化的方式提供给模型,让它在生成 SQL 或选择数据源时"知道有什么、能查什么"。
查询生成与安全。如果你让大模型直接生成 SQL 并执行,安全是你必须面对的问题。至少需要两层保护:
- 只读限制:数据分析场景中,大模型生成的查询应该被限制为 SELECT 类操作。任何写操作(INSERT, UPDATE, DELETE)都应该被明确拦截。
- 查询审核:在开发阶段,可以让模型生成的 SQL 先进入审核节点,确认正确性后再执行。在生产环境中,更安全的做法是让模型生成"查询意图描述"(我要查什么),由预定义的查询模板或中间层翻译为实际 SQL。
中间结果的缓存和管理。数据分经常涉及多步操作——第一步查总趋势,第二步钻取异常点,第三步关联用户数据进行归因。每一步都会产生中间结果数据。数据架构需要管理这些中间结果的生命周期(何时缓存、何时清理),避免重复计算和资源浪费。
推理架构:多步推理和工具调用
数据分析的推理链路通常比问答和内容生成更长。一个典型的对话式数据分析流程是:
- 意图解析 — 理解用户问的是什么("趋势"还是"异常"还是"对比")
- Schema 匹配 — 将分析意图映射到具体的表和字段
- 查询生成 — 生成数据分析查询(SQL、Python pandas 代码等)
- 结果解释 — 将查询返回的数字/表格转化为自然语言解读
- 可视化 — 按需生成图表(结合图表生成工具)
- 追问处理 — 支持对上一次分析结果的钻取、过滤、关联
这六个步骤不是每轮对话都要全部走一遍,但推理架构需要支持这种"步骤组合"的能力。实践中通常采用 Planner-Executor 模式:
- Planner(规划器):理解用户意图,决定接下来应该执行哪个步骤
- Executor(执行器):调用具体工具(SQL 查询、Python 计算、图表生成),返回结果
Planner 和 Executor 可以是同一个模型的不同角色,也可以分别使用不同的模型——Planner 需要更强的推理和规划能力,Executor 更需要准确的格式输出和工具调用能力。
模型架构:选型侧重逻辑推理
数据分析对模型的"逻辑推理"和"数学能力"要求高,对"知识面"和"语言流畅度"要求相对低。模型选型时应该关注其在代码生成(特别是 SQL/Python)和数值推理基准上的表现。
可以简化的部分:知识架构。除非你的分析场景需要特定的行业知识来解释数据含义(比如"这个指标在医疗行业的标准阈值是XX"),否则数据分析类应用通常不需要复杂的知识架构。数据本身就是"知识"——你不需要另外建一个知识库。
可以避免的坑:
- 不要用大模型做它能做但"不该由它做"的计算。大模型可以生成 SUM/AVG 查询,但不应该让它直接"算"——把计算交给数据库引擎,大模型只负责翻译"自然语言→查询→解释结果"。让模型直接处理原始数据行会是低效且容易出错的。
- 不要忽略 Schema 的"教学"成本。如果你的数据库有 50 张表、每张表 20 个字段,全部塞进提示词会让上下文撑满。需要设计 Schema 的选择机制——根据用户的提问,只注入相关的表和字段定义。这个机制本身就是推理架构的一部分。
- 不要把所有分析都交给模型。 有些分析——比如同比、环比、移动平均——直接用 SQL 或预聚合表计算比让模型推导更准确、更快速。数据分析架构的目标是"模型理解意图+引擎执行计算",不是"模型包揽一切"。
数据分析架构设计流程总结
- 定义分析范围和交互模式 → 探索式/报表式,对话式/定时式
- 设计数据接入和 Schema 注入机制 → 让模型知道有什么数据、怎么查
- 设计查询生成和安全控制 → 只读限制+查询审核
- 设计中间结果管理 → 缓存策略,避免重复计算
- 设计 Planner-Executor 推理管线 → 意图→查询→执行→解释→可视化
- 配置计算引擎与模型的职责分工 → 模型做"理解",引擎做"计算"
10.8.4 硬件控制类应用
这是四种应用类型中最"不典型"的一种,也是发展最快的一种。大模型控制硬件——从智能家居的语音指令到工业机器人的操作规划——正在从 Demo 走向实用。
硬件控制类应用在六大子架构上的特点是:任务架构必须是"安全第一",推理架构必须处理"指令精度的不可逆",知识架构以操作手册和约束规则为主,模型架构需要处理实时性挑战。
任务架构:安全是压倒一切的前提
与其他三类应用不同,硬件控制类应用存在不可逆的物理后果。一段错误的回答可以撤回,一篇糟糕的文章可以修改,但一个错误发送给机械臂的指令可能导致设备损坏甚至人员伤害。所以任务架构设计的起点不是"怎么让模型控制硬件",而是"什么情况下模型不应该控制硬件"。
指令分级。不是所有控制指令的风险是一样的。可以设计一个分级体系:
- 安全指令:不会产生物理后果的操作(如查询设备状态、获取传感器读数)
- 可逆指令:有物理后果但可以回退(如调整灯光亮度、切换显示页面)
- 不可逆指令:一旦执行无法回退或回退成本很高(如启动发动机、关闭产线、调节压力阀)
不同级别的指令要有不同的安全机制——安全指令可以由模型自主执行,可逆指令需要确认,不可逆指令必须经过人工审核或双重验证。
安全熔断。大模型不是确定性的——同一段提示词在两次推理中可能产生不同的输出。在硬件控制场景中,必须设计"安全熔断"机制——当模型的输出超出了预设的安全范围(如指令参数超过阈值、目标设备不在白名单中),系统自动拦截并回退到安全状态。
知识架构:操作手册和约束规则
硬件控制类应用的知识架构相对明确——主要包含以下三类知识:
操作手册知识。设备的使用说明书、操作流程、故障处理方案。这些和知识问答中的文档知识类似,需要被结构化处理。不同之处在于:硬件控制场景中,知识的作用不是"回答用户问题",而是"为模型的操作决策提供依据"。
物理约束规则。每个硬件设备都有操作边界——最大转速、安全温度范围、工作电压区间。这些硬性约束需要被转化为"不可违反的规则",嵌入在推理链路的决策节点中。例如:"如果目标温度超过上限,所有升温指令必须被拦截"。
环境感知知识。硬件控制的上下文不只是"文本",还包括实时传感器数据。知识架构需要定义传感器数据的接入方式、解读规则和时效性要求——温度读数 5 分钟前的"旧数据"可能已经失去了参考意义。
推理架构:从意图到指令的多层转换
硬件控制的推理链路通常有一个关键特征——多步转换。
自然语言意图 → 操作意图。用户说"把房间调暖一点",模型需要把"暖一点"转换为可量化的操作目标——"设定温度从 22°C 提高到 24°C"。
操作意图 → 设备指令。"设定温度 24°C" 这个操作目标需要被翻译为具体设备的控制指令——可能是通过 MQTT 协议发送 {"device":"ac_01", "cmd":"set_temp", "value":24},也可能是调用 Modbus 写寄存器地址 0x0020。
指令执行 → 状态验证。指令发出后,推理架构需要验证执行结果——设备是否确实进入了目标状态?如果传感器反馈显示温度没有变化,系统应该触发重试还是报警?
这其中的每一步都存在"翻译错误"的风险。所以硬件控制推理架构的一个核心设计是:在每一步转换后添加验证节点。转换结果在被执行前,经过安全规则引擎(不是大模型,而是确定性的规则系统)的合法性校验。
模型架构:实时性与可靠性的取舍
硬件控制对实时性有要求——一个语音指令输入后,用户期望在 1-2 秒内得到响应。但大模型的推理延迟通常在几百毫秒到几秒不等,如果推理链路还涉及多步转换和验证,总延迟很容易超预期。
这里的策略通常是"模型分层":
- 意图识别层:用轻量级快速模型做意图分类(是"调温"还是"开灯"还是"查询状态"),延迟控制在 100ms 以内
- 指令生成层:用更大的模型做操作规划和指令翻译,这是延迟的主要来源
- 规则执行层:用确定性的规则引擎做安全检查、指令发送和状态验证
另一个需要考虑的问题是离线能力。如果你的硬件设备处在网络不稳定的环境中,依赖云端的模型推理是不可靠的。在一些场景中,需要在本地部署小型模型(如量化后的 1B-3B 参数模型)作为"基本意图处理器",在离线状态下至少能处理安全关键指令。
可以避免的过度设计
- 不要试图让大模型直接生成底层控制协议。让模型输出"操作意图"(JSON 格式的结构化指令),由中间层翻译为具体的设备协议。这样既降低了模型出错的风险,也使得设备层的变更(换一个品牌的空调)不影响模型侧的逻辑。
- 不要忽略"人机切换"接口。硬件控制类应用应该设计清晰的人机边界——当模型不确定、安全规则触发、或连续重试超过预设次数时,应该无缝切换到人工控制,而不是在模型自动和人工接管之间留下操作"空窗期"。
硬件控制架构设计流程总结
- 划定安全边界和执行分级 → 什么指令模型能做,什么必须人工确认
- 设计安全熔断机制 → 参数超限自动拦截,异常状态自动回退
- 整理操作手册和约束规则 → 结构化存储,注入推理链路
- 设计多层转换链路 → 意图→操作目标→设备指令→执行→验证
- 模型分层选型 → 轻量模型快响应+大模型做规划+规则引擎做安全
- 设计离线回退策略 → 网络不可用时的本地最小化处理能力
- 设计人机切换接口 → 无缝从自动切换到人工,不留空窗
10.8.5 四种应用类型的架构对比
把这四类的架构要点放在一张表里,差异一目了然:
| 子架构 | 知识问答 | 内容生成 | 数据分析 | 硬件控制 |
|---|---|---|---|---|
| 任务架构 | ★★ 目标清晰,线性流程 | ★★★ 需精细定义质量标准 | ★★★ 需明确分析范围和交互模式 | ★★★★★ 安全分级,指令划分 |
| 知识架构 | ★★★★★ RAG 为核心,知识可持续更新 | ★★ 风格+范例为主 | ★ "数据即知识",通常不需要外置知识库 | ★★★ 操作手册+约束规则 |
| 数据架构 | ★★★ 为多路检索服务 | ★★ 范例库和模板管理 | ★★★★★ Schema 注入,查询安全,中间结果管理 | ★★ 传感器数据接入 |
| 模型架构 | ★★★ 低温度推理优先,选择性微调 | ★★★★ 模型分级(草稿→精修→专项) | ★★★ 关注逻辑推理和代码能力 | ★★★★ 实时性分层,考虑离线 |
| 推理架构 | ★★★ 多步检索→生成循环 | ★★★★ 生成→审查→修改迭代 | ★★★★★ Planner-Executor,多步工具调用 | ★★★★★ 多层转换+安全验证节点 |
这张表的精读方式不是"看谁的星星多",而是看每一行星星的分布。如果你的应用类型在某个子架构上星星很低,那就意味着你可以把精力省下来,投入星星高的那些环节上。架构设计的智慧不在于"面面俱到",而在于知道在什么地方用力。
10.8.6 从分类到实践
最后需要说明的一点是:现实中的应用往往不是纯粹的某一类。一个客服系统可能同时涉及知识问答(回答用户对产品的疑问)和硬件控制(远程协助用户调试设备)。一个数据产品可能同时需要数据分析(生成洞察)和内容生成(撰写分析报告)。
这种情况下你不需要另起炉灶设计一套"混合架构",而是:
- 把应用按功能拆解为子模块,判断每个子模块更接近哪种类型
- 每个子模块按对应类型的架构流程走
- 在模块之间的接口处设计清晰的"数据传递"和"状态共享"机制
六大子架构的价值不在于它是一张必须逐项填写的检查清单,而在于它给了你一个系统化思考的框架。当你面对一个复杂的大模型应用需求时,不需要从头摸索,只需要依次问自己5个问题:
- 任务是什么 — 要解决什么问题,成功的标准是什么?
- 需要什么知识 — 模型完成这个任务需要了解什么?
- 数据怎么组织 — 知识以什么形式交付给模型?
- 用什么模型 — 哪个模型最适合,需要多少个模型协作?
- 怎么推理 — 单步还是多步,需要哪些工具,链路怎么设计?
这五个问题的答案,就是你架构设计的第一版。后续的迭代和改进,都是在这个框架之内的细化——这可能是整本书最核心的方法论之一。
本章完。 从第1章的焦虑与期待,到第10章的六大子架构和四类实践参考,我们完成了一个闭环:理解大模型→选型模型→设计架构→落地实践。技术会演进,工具会迭代,但架构意识和方法论是长效的。希望这本书能帮你在大模型的工程实践中少走一些弯路,做出真正有效的系统。