大模型这个圈子待久了,你会发现一个现象:各家发布的“新能力”看着一个比一个花哨,可真把那些Demo拆开,底层模型没换,训练方式没变,变的只是“喂进去的内容怎么组织”和“吐出来的结果怎么使用”。这句话说重一点,几乎所有 AI 应用侧的新花样,本质上都是在「输入什么」和「输出怎么处理」这两端上做文章。这套三层架构的思路,我做项目用了大半年,越用越觉得值得好好写一篇。
这篇文章把这三层拆开聊:底座能力层、输入编排层、输出处理层。不涉及训练和微调,只看应用落地。适合刚接触大模型开发的工程师,也适合那些已经调了一堆 prompt 但总觉得效果不稳定的同学。读完你会发现,很多“灵光一现”的玩法,背后都是同一套逻辑。
1. 三层架构到底在拆什么——先别急着背概念
1.1 一次普通调用背后的旅程
我先带你走一遍大模型应用中最常见的一次调用流程。假设你在做一个客服问答系统,用户问了一句“我上个月的账单为什么多了二十块”。这句话到达后端之后,实际被处理成了一段比这句话长得多、结构也复杂得多的文本,通常包含系统指令、历史对话、检索到的账单规则、用户问题原文,最后拼成完整的请求,送到模型推理接口。
模型推理完成后返回的也不是一段“答案”,而是一连串 token,附带各自概率。你的代码要收下这串 token,把它拼接成文本,再丢给一个解析方法,提取出“用户要的东西”,甚至还要判断是否要调用一个查账接口。整条链路走下来,你会发现模型只参与了中间那一小段:吃进拼接好的文本,吐出原始 token。
这个视角特别重要。它把大模型应用拆成了一个熟悉的架构:输入侧负责“给它什么”,模型本身负责“理解与生成”,输出侧负责“拿生成结果怎么办”。我习惯把这三块叫底座能力层、输入编排层、输出处理层。项目里几乎所有有意思的迭代,都发生在第一层和第三层。
1.2 三层各自的边界
底座能力层,是模型发布那一刻就定死的部分。比如它有没有数学推理能力,代码能力强不强,中文表达是否自然,能支持多长的上下文。这部分你换不了,只能在选型时做权衡。选一个强模型,后续输入输出处理会轻松很多;选一个弱模型,你就必须在输入和输出两端用更多工程手段去补。
输入编排层,指的是你在把问题交给模型之前做的所有加工。写系统提示词、拼接历史对话、加入检索到的参考资料、给出 few-shot 示例、把工具说明塞进去,都属于这一层。这里做的事情,本质上是“控制模型的信息边界”:告诉它任务是什么,能用到哪些材料,回答时要注意什么。
输出处理层,指你拿到原始输出之后做的所有工作。设置解码参数(温度、top_p、max_tokens),要求模型输出 JSON,解析它的返回结果,判断是否触发工具调用,把调用结果再次塞回输入,甚至设计 Agent 循环让它多次思考后再给结果,这些都是输出侧的事。
1.3 为什么这个拆分有用
很多开发者的痛苦在于:“我给提示词写了八百字,效果还是不行。”拆成三层之后你会立刻发现,问题可能根本不在提示词上。你的 context 里塞了一堆不相关的文档,模型自然被带偏;你的输出解析脚本只处理了“完美 JSON”,模型一旦多输出一个标记,整个流程就崩了。这些都不是“再写两句话”能解决的。
这个架构还有一个直接好处:排查问题时,你能快速定位故障发生在哪一层。效果差,先看输入侧有没有给足信息;效果飘,先看输出侧解码参数和结构化约束;上下文长了反而乱,先看底座能力层的窗口是不是真的适合这个场景。下面两章,我会把输入和输出这两端分别拆细,这也是整个架构里最值得花时间的地方。
2. 输入端怎么玩:把“信息边界”管好
2.1 提示词本质上是“给地图”,不是“改大脑”
你先要建立一个基本认知:提示词不会提高模型的真实智力水平,它只是把模型已有的能力引导到正确方向。这就像你给一个本地人指路,你说得再详细,他也不可能突然变成一个建筑工程师;但你能帮他绕过那条最容易走错的路口。
所以在设计输入时,我习惯先问几个问题:模型需要知道哪些事实才能回答这个问题?哪些信息加了反而会造成干扰?任务边界是“直接答”还是“先查再答”?输出格式有没有硬性要求?把这三个问题想清楚,再动手写提示词,成功率比上来就编一大段人设话术高得多。
比如在事实问答场景里,一个可靠的系统提示词框架是这样:先说明自己是什么系统,再告诉模型“只基于参考资料回答”,然后明确“如果资料里没有,就直接说不知道”,最后附上输出格式要求。这四件事做好,比写三百字“你是一个博学多才的助手”管用得多。
2.2 context 窗口是输入侧最值钱的资源
大模型在推理时能看到的全部信息,就是你塞进上下文的内容。很多人的误区是“窗口越大越好,那我把所有文档都丢进去”。实测下来,上下文过长,模型对中部信息的注意力会下降,回答质量不升反降。
你可以在项目里做一个小实验:同样一个问题,分别用“全文检索塞正文”和“只塞相关片段”两种方式跑,后者往往明显更稳。原因很简单,模型需要聚焦在关键证据上,而不是在几十页无关内容里自己找重点。所以不要把 context 当硬盘用,它应该被当成“作战室里的白板”:只放这次任务需要用到的材料。
2.3 RAG 的本质是在输入端“定点投喂”
RAG(检索增强生成)这几年很火,拆到三层架构里,它其实完全活在输入编排层。你先把知识库切成小块,用户提问后用向量检索找出最相关的几块,再把这些块连同问题一起拼进 context。模型本身没有新增任何知识,它只是在回答时“开卷考试”,看到你投喂的材料。
我做资料问答助手的经验是,检索质量比生成质量更影响最终效果。你辛辛苦苦把提示词清得很干净,结果召回的片段根本不对,那模型再强也白搭。chunk 切多长、用哪种向量模型、要不要加重排,这些才是 RAG 场景下真正的胜负手。当你发现回答“总是少了点关键信息”时,别急着改 prompt,先去查召回结果。
2.4 few-shot 是“给格式样板”,但小心副作用
少样本示例在输入侧的作用,不是教模型新知识,而是告诉它“回答长什么样”。模型对格式有极强的模仿能力,给它两个合规示例,它大概率会照着这个格式走。这是最便宜的格式化手段。
不过这事有副作用。示例里的语言风格会被模型学走,示例太长会挤占上下文空间,示例太特殊还会把模型“带偏”到那个特例里。我的习惯是:示例数量控制在两到三个,每个尽量短,覆盖常见但不同的情况,而不是贴一个冗长的标准答案让模型去背。说到底,输入端的设计原则永远是“精确、克制、够用”。
3. 输出端怎么玩:从“一串 token”到“能用的结果”
3.1 解码参数决定了模型“胆子”有多大
模型返回的是概率分布,而你设置的解码参数,直接决定它敢不敢“冒险”。温度就是最典型的开关:温度接近 0,模型基本只会选概率最高的 token,回答稳定、可预测性强,适合事实问答、信息抽取;温度调到 0.7 以上,模型会开始选一些概率没那么高的词,回答更有创意,但也会天马行空。
你可以在同一个提示词下做对照:产科问答系统把温度调到 0.1,连续问十个问题,答案几乎不重样且稳定;调到 0.9,同一个问题可能给出风格完全不同的几版回答。写营销文案则反过来,温度太低生成的内容像在念说明书。所以调参的第一课不是“背参数表”,而是先想清楚你要的是“偶尔惊人”还是“始终可靠”。
top_p 是第二位玩家,它控制的是“从累计概率多少的候选词里采样”。我用的时候一般只调两者之一,很少同时大改,不然很难解释效果变化到底是哪个参数的功劳。
3.2 结构化输出:让模型对机器“说人话”
普通聊天场景里,模型直接吐一段散文没问题,但系统要处理它,就得让它按约定好的格式输出。最常见的做法是叫模型只输出一个 JSON 对象,并且字段名称、类型事先约定。工程上我会在系统提示词里放一段 schema 说明,有时甚至直接给模型一个“参考 JSON 结构”的模板。
但模型不是数据库,它偶尔会“手滑”:多输出一个逗号、漏掉一个引号、或者忍不住在 JSON 外面包一个json 代码块。这类问题如果只靠提示词,永远治不干净。更稳的做法是在代码里加一层“宽容解析”:先尝试直接 parse,失败后把json 标签剥掉再 parse,再失败就用正则把可疑区域抠出来修复。这层兜底逻辑,能把结构化输出的稳定率从九成拉到九成九。
3.3 CoT 要不要开,得看业务接不接受“碎碎念”
思维链(CoT)让模型在给出结论前先展示推理步骤,很多复杂任务在这个模式下准确率明显提升。原因是它强制模型把“中间结果”写出来,相当于把黑盒推理拆成了一段可检查的逻辑链。
但代价也很具体:输出变长、响应变慢、费用变高,而且有些模型在“想太多”之后反而会过度怀疑自己。我常用的折中方案是告诉模型:“先自己思考,但只在最终回复里输出结论和关键理由,不要输出完整推理过程。”这样既拿到了 CoT 的准确率红利,又不会让用户等半天看模型内心戏。
3.4 工具调用:输出端真正的“放大器”
如果说前几项还是在文本范围内做文章,工具调用则让输出直接“变成动作”。模型不需要真的去执行什么,它只在输出端生成一个结构化指令:函数名、参数列表。代码收到这个指令后,自己去调外部 API、读写数据库、执行计算,再把结果塞回输入侧,让模型基于新信息继续回答。
这个闭环是 Agent 的核心,拆开看就是“输入-输出-再输入”。你会发现问题又回到了两层:输入侧要写清楚工具是什么、什么时候用、参数怎么填;输出侧要可靠地解析模型选择的函数名和参数。我在实战中的关键体验是:把工具描述写得像给新人看的说明文档,模型调用工具的准确率会明显提升。很多人反复强调“你必须使用工具”,但模型真正需要的是知道这个工具能干什么、每个参数代表什么。
4. 一个完整项目的调参实录:三层架构的实战组合
4.1 模拟项目:做一个资料问答小助手
为了让这套东西更落地,我给你看一个我最近做的模拟项目 X:一个面向内部资料库的问答助手,用户用自然语言查制度、查流程、查历史记录。
最初版本非常简单:把用户问题直接发给模型,让它凭感觉回答。结果是效果完全不可控,有时候答得很准,有时候一本正经地编制度条款。我没有一味加提示词,而是用三层架构重新梳理了一遍:底座层面确认模型窗口不适合一次性吞全部制度文档;输入层面接入了检索模块,只投喂相关片段;输出层面要求纯 JSON 返回,字段里明确标注“答案、引用章节、置信度”。一个下午改完,效果明显换了副面孔。
4.2 输入端我具体做了什么
我先写了一段系统提示词,只保留三部分:角色限定为“资料库问答助手”;硬性规则“只能依据参考资料回答,没有依据就回复不知道”;输出必须是一个 JSON。
然后我接入了检索链路。制度文档按章节切块,每块控制在几百字以内,用户提问后先召回最相关的三到五块,再把这些块拼到提示词里。相比之下,最初版本把整个 PDF 的纯文本塞进去的做法,既慢又容易串味。
再补一招:把规则里的几个高频措辞做成 few-shot 模板。这个动作不是为了教模型制度内容,而是告诉它“遇到有冲突的说法时,以最新修订版本为准”这种输出风格。整个过程下来,输入侧的结构已经非常清晰,后面所有优化都是在这个地基上做增量。
4.3 输出端我调了哪些参数
输出侧的改动比输入侧更直接。第一件事,温度从默认值调到 0.2,因为我要的是稳定事实回答,不是创意写作。测试下来,同一个问题连续问五次,答案主体基本一致,偶尔出现的措辞差异也不会影响后续解析。
第二件事是强制 JSON 输出。我在提示词里附了返回格式说明,并且在代码里做了宽容解析。实测没有加解析兜底前,偶尔会出现“多一个逗号”导致整个链路失败的情况;加了兜底后,解析失败率基本归零。
第三件事是对“不知道”场景的兜底。模型如果回答不了,我让它输出 confidence 字段为低,前端拿到后自动展示“资料库中未找到相关内容”,而不是硬着头皮瞎编。这一步把幻觉问题从“晚点被用户骂”变成了“提前被系统拦住”。
4.4 最终效果和数据对比
改完这套组合拳之后,我做了个小范围评测。参考数据集里准备了五十个问题,包括二十个有标准答案的、二十个资料库没覆盖的、十个存在相似条款容易混淆的。
改版前,标准答案准确率大约六成,未覆盖问题的“硬编率”接近一半,用户体验很差。改版后,标准答案准确率提高到九成,未覆盖问题的拒绝率提升到九成以上,相似条款的区分能力也明显改善。这个项目最打动我的不是某个单一技巧,而是三层架构带来的可解释性:每次效果波动,我都能立刻判断是哪一层出了问题,而不是像以前一样病急乱投医。
5. 常见问题与排查心得速查
5.1 输出格式漂移怎么修
现象:要求输出 JSON,偶尔多出几行解释文字,或者字段名换了个叫法。
排查思路:先看温度是不是偏高,温度越低越容易遵守格式要求。再看 few-shot 示例是不是统一用了 target 字段,而系统提示词里写的是 result,这种不一致很容易让模型犯迷糊。最后确认解析层有没有容错,最好保留一份成功样本作为 golden test。
我的解法:把 schema 直接写在提示词里,并附一个真实输出的示例。这比反复强调“不要输出多余内容”更有效。
5.2 改了提示词但效果没变,为什么
这是很多人最常踩的坑。你的修改很可能根本没体现在模型看见的内容里:缓存命中导致请求压根没变化,或者你改的是 system prompt 但代码里实际拼的是老模板。先查日志原文,确认模型真实收到的输入是什么样的,再做判断。
如果输入确实是新的,但效果依旧,那问题大概率不在提示词层面。去检查检索链路、知识库内容、输出解析逻辑。
5.3 工具调用失败的排查链
工具调用失败,一定要按顺序排查:模型有没有输出正确的函数名?参数名和参数类型是否匹配 schema?代码里有没有把 assistant 的输出误当成 user 的内容?工具返回结果有没有正确塞回上下文?大部分失败原因都是“参数类型不匹配”或“返回结果没有回填”,而不是模型本身太笨。
我给团队定的规矩是:工具描述必须包含参数示例、类型说明、使用场景。实测这个习惯能大幅降低调用失败率。
5.4 上下文太长导致回答变差
症状:塞入的资料越多,回答反而越差。
原因通常有两个:一是模型对超长上下文的注意力确实有衰减,尤其对中间部分的内容关注度更低;二是塞入了大量无关信息,模型被噪声干扰,不知道应该依据哪一段。
解法不是无脑扩大窗口,而是提高检索精度、限制投喂片段数量、按相关度排序。把最相关的信息放在开头和结尾,模型会更“看得到”。上下文管理是输入侧的基本功,值得花精力做好。
5.5 个人经验:三层架构让“智能系统”可维护
用了三层架构一段时间后,我做项目的状态变化很大。以前所有问题都诉诸“改提示词”,现在会先分诊:是底座能力不够、输入没给够支撑,还是输出处理不兼容。大部分问题在输入和输出两层就能解决,底座要换模型的情况反而是少数。建议你把当前项目画成一张链路图,标清楚每一层做了什么,后续每次调优,都带着“我在改哪一层”的意识,少走弯路。
最后分享一个小习惯:每次调完输入或输出,至少保留一份变更前后的对比记录。这个习惯会在两周后救你一命。