做AI应用这一年多,我总结出最省力的一句话:别把大模型当上帝,把它当成一台能力固定但配件丰富的发动机。所谓大模型三层架构拆解,拆的就是底座预训练层、输入组织层、输出处理层这三件事。而那些看着很热闹的AI新花样,无论是Agent、RAG、Function Calling,还是各种结构化输出、思维链提示,本质上都只在“输入什么”和“输出怎么处理”这一进一出之间做文章。这个视角对做产品原型、写工具链的开发者,以及想快速验证创意的同学特别实用——你能在不换底座模型的情况下,靠改造输入输出解决大部分效果问题,而且很多灵感也恰恰是从这个框架里长出来的。
1. 三层架构到底拆哪三层
1.1 三个层面的边界在哪里
先说清楚,这个“三层”不是指物理上的网络层或者部署架构,而是指你在使用大模型时,能控制的东西到底分几层。
第一层是底座预训练层,也就是那个经过海量语料训练出来的大模型权重本身。它决定了模型的基础语言能力、推理天赋、知识储备量以及指令遵循的底子。这一层的特点是笨重、昂贵、更新慢,平时做应用基本不会碰它。
第二层是输入组织层。模型本身不改,但你可以决定给它看什么:系统提示词怎么写、上下文里塞哪些业务数据、要不要插入工具描述、对话历史保留多少轮、是否过滤无关噪音。这是日常开发里改动最频繁的一层,我甚至觉得它才是真正体现工程师水平的地方。
第三层是输出处理层。模型生成完结果之后,你还要决定怎么接住它:是用JSON格式约束、做内容校验、重试修补、安全过滤,还是把流式输出转成前端能用的增量数据。输出层承担的是“让模型结果变成系统里可靠数据”的责任。
为了方便记,你可以把这三层类比成厨房:底座是食材和灶台,输入是你准备切什么菜、按什么顺序下锅,输出则是出锅之后怎么装盘、怎么端给不同口味的人。厨房设施和食材一般不会中途换,但厨师一天到晚都在调整备菜和上菜方式,这就是大模型应用开发的常态。
1.2 用一句话记住这套拆法
如果你只能记住一句话,那就是:底座模型提供上限,输入组织决定上限的发挥,输出处理决定发挥的落地。
这句话听起来简单,但能帮你避掉很多无效工作。比如你遇到模型回答不准确,第一反应如果是“换个更大的模型”,那就是在动底座层,成本高、周期长、还可能换完发现效果依旧不理想。但如果你先从输入组织入手,检查是不是少给了上下文、系统提示词写得含糊、检索结果里混入了噪音;再从输出处理入手,检查解析逻辑和校验规则是否合理,大概率能在不改模型的情况下把问题压下去。
再回到“所有AI新花样”这个说法。现在市面上那些玩法,放在这个框架里会显得特别清晰:思维链提示是改输入,让模型多写几步思考过程;Few-shot示例是改输入,喂几条标准样例给模型模仿;RAG是改输入,把外部知识检索后拼进上下文。而结构化输出、JSON修复、结果校验、拦截重写,都属于输出处理。你顺着这个思路去拆任何一篇在社区刷到的AI技巧,基本都能归到“输入什么”或“输出怎么处理”这两类里去。
2. 为什么新花样都挤在“输入”和“输出”两端
2.1 底座层动一次太贵了
先说个很现实的成本问题。一个底座模型从数据收集、清洗、预训练、对齐,再到安全评测,通常要消耗极大的算力和人力。这个成本不是一个普通开发者能承受的,也不是一个中等规模团队能频繁承受的。所以绝大多数AI应用开发者手里的底座模型,本质上是一个“固定参数”的黑盒。
你可能会说:那我不换底座,我用更强的商业模型接口总行吧?当然行,但那只相当于换了个性能更好的灶台和食材,依然改变不了“模型权重本身不可轻易定制”的事实。你想在底座层面做出自己的差异化,基本只有两条路:一是做领域继续预训练或微调,二是等某个新底座发布。前者成本高,后者不可控。因此,聪明的团队都把精力放到输入和输出层,因为这些地方改动便宜、反馈快、还能积累自己的数据资产。
这也就解释了为什么社区里每天都有新玩法冒出来,那些披着“革命性方法”外衣的提示词技巧、输出策略,绝大多数都是在一进一出两端做排列组合。换句话说,模型本身像一块固定的电路板,而输入输出就是你可以自由接线的两个插槽。
2.2 输入输出层更贴近真实业务
再往深一层说,底座模型的能力是通用的,但业务问题是具体的。通用模型不可能知道你们的订单表结构、客户投诉里那些暗语、表格里某个字段为什么经常为空。这些信息只能在输入阶段注入,或者靠输出阶段的规则修正。
举个我踩过的例子。早先做一个问答系统时,我总觉得模型回答得不够“懂行”,于是想微调一个专门的小模型。尝试了一周,数据准备、参数调试、评估下来发现成本高且效果还不稳定。后来换了思路,把一部分历史工单里的标准答复作为上下文示例塞进输入,再把输出结果的格式从自由文本改成固定模板加关键字段,效果立刻好了不少。这让我彻底明白:与其动底座,不如先把一两层输入输出做扎实。
业务侧的另一个特点是需求变化快,今天要支持新的表单格式,明天要换一种回复语气,后天要把结果接入某个内部系统。如果这些都要改底座模型,那产品的迭代速度基本等于零。而输入输出层本来就是为“高频变化”而存在的,你可以先调整系统提示词新增一个角色设定,再改造输出解析适配新协议,几小时内完成一次小版本迭代。
3. 底座层:能力上限到底由谁决定
3.1 底座层不必天天惦记,但要懂它的脾气
不碰底座层不代表可以完全无视它。你需要知道底座模型“擅长什么、不擅长什么”,这决定了你对输入输出的设计方案。
底座模型最擅长的是对语言做概率建模,能够基于海量语料中学习到的模式,生成流畅的文本、做常识推理、理解复杂指令。但它有几个明显的短板:**第一,知识有截止时间,**训练数据是历史快照,无法自动感知最新资讯;**第二,没有真实世界的校验能力,**你让它生成一个销售数据,它可能一本正经地给你编一个;**第三,对低频和长尾知识掌握脆弱,**冷门业务术语或者内部黑话,它经常理解不到位;**第四,存在对齐偏好和生成偏见,**同一个问题换个提问方式,答案的侧重点可能完全不同。
这些短板看起来是缺点,但放到三层架构里反而变得可控:知识更新了就靠输入侧检索补;要校验数据就靠输出侧接一个规则引擎或外部API;术语不懂就靠输入侧给术语表;对齐偏好不一致就靠系统提示词约束语气和边界。说白了,底座层负责“合理生成”,输入输出层负责“校正和落地”。
3.2 选底座模型时留意哪些事
虽然底座层不能频繁动,但选型时的一次性决策依然很重要。以我的经验,你会考虑这几个点:
模型参数大小决定了本地部署门槛和推理速度。通常来说,参数更大的模型能力更强,但也会带来成本和延迟;小参数模型在你把输入输出做好的情况下,很多任务也能胜任。你需要先跑一个基线测试,拿自己业务里的典型输入去裸测,看看问题主要出在理解能力还是知识面上。
上下文窗口长度也要关注。输入层要做的很多事,比如塞检索结果、塞历史会话,都和上下文窗口大小直接相关。窗口越大,你能组织的输入样式越多;但如果只有长度而注意力机制不够好,塞得太多反而会导致关键信息被淹没,这一点在输入设计一节会细讲。
还有,不同底座模型对指令遵循的敏感度不一样。有的模型你只要用自然语言写一句“以JSON格式输出”,它就听话;有的模型需要你给一个非常工整的schema示例才能稳定输出。选型之前最好把输出侧的约束能力也纳入评估,免得模型请回来之后发现连最基本的格式都管不住,被迫在输出加一堆后处理补丁。
4. 输入层:模型能看到什么,决定了它能答出什么
4.1 输入层常见组件与优先级
这个H2是大多数AI应用最容易出效果的地方,也是我最想展开讲的部分。输入层往里细化,大概有四个组件:
第一个是系统提示词,它定义模型的角色、任务目标、回答风格和硬性约束。第二个是用户输入,也就是用户直接发来的问题或指令,这部分通常需要清洗、改写、扩写成更明确的查询。第三个是动态上下文,包括从数据库或搜索引擎里取到的外部信息、检索结果、文档片段、表格片段等。第四个是历史会话,多轮对话时需要把前几轮关键内容带入,否则模型会失忆。
关于优先级,一定要记住:**离当前任务越近、对答案影响越直接的信息,越要靠前或靠后放。**很多研究表明,模型对上下文开头的部分和结尾的部分关注度更高,中间一大段经常被“忽略”,这种现象被大家称作“大海捞针失效”。所以我的习惯是:系统提示词和当前问题放开头或结尾,检索资料放中间并按相关度排序,历史会话只保留关键摘要,而不是原封不动地堆积所有轮次。
4.2 系统提示词不是“写得长”就好
许多新手喜欢把系统提示词写成一篇议论文,恨不得把模型的人格、价值观、所有业务规则都塞进去。但实测下来,这种写法的问题非常明显:约束太多互相冲突,模型会被搞糊涂,或者只记住最后几句话,导致规则失效。
我常用的提示词结构非常固定,大概四段式:第一段说明角色和任务背景,不超过一句话;第二段列出硬性规则,比如“只能依据提供的资料回答”“不要编造数字”“如果信息不足就明确说不知道”,每条尽量简单;第三段给一到两条输出格式要求,最好配合示例;第四段说明边界条件,比如“不要回答和加密货币无关的问题”“禁止输出代码”。别小看这种结构,它把约束拆成独立单元,模型处理和遵循起来会更稳定。
除了结构,措辞方式也很重要。你能用“如果遇到不确定的情况,请直接说无法判断”就不用“请谨慎回答”;能用“输出不要超过200字”就不用“尽量简洁一点”。前者是指令性的,后者是模糊性的。底层模型在概率生成时更依赖明确指令,这一点我反复测试过很多次,措辞明确和措辞模糊的差距往往很大。
4.3 动态上下文与RAG的本质
再来聊检索增强。很多人把RAG当成一个高大上的架构,其实从三层拆解来看,它就是输入层的一次“动态拼图”:把外部知识检索出来,然后拼接进上下文,让模型能回答原本超出它训练数据范围的问题。
做RAG的时候,核心在于拼接质量而不是拼接数量。我最初踩过一个坑:为了让模型回答更全面,把检索到的一大堆文档片段全部塞进上下文,结果反而把关键信息淹没,逻辑混乱。后来我改成先做段落去重、按相关度截断,每个检索片段控制在300字以内,再给每个片段打上来源标题和日期,模型回答的准确率提升非常明显。让模型知道“这段信息是从哪来的”,比单纯把所有内容堆进去更有用。
输入层还要处理一个问题:用户提问本身可能含糊不清。比如用户问“最近怎么样”,如果你直接把它丢给模型,它可能发挥想象力猜。更好的是在输入前做一层意图标准化:识别用户问的是产品功能、价格、还是故障报障,然后把问题改写成更明确的句子,再结合检索结果一起送入模型。这一步相当于给输入层装了“翻译官”,把用户口语翻译成系统更擅长处理的表达。
4.4 对话历史需要“摘要”而不是“搬运”
多轮对话场景里,很多人直接把最近10轮聊天记录全部塞进输入,这会让上下文变得越来越长。长上下文带来的后果:一是费用变高,二是关键信息被稀释,三是模型容易把历史里的错误认知当成当前事实。我现在的做法是,在每轮结束时让模型或规则引擎生成一个简短的对话摘要,下次只带摘要加最近一轮的原始问题。这样既保留了语境,又控制了输入长度。
另外,对话历史里如果有一轮用户问了个和当前任务无关的问题,那条轮次通常会干扰答案。过滤方法是给历史轮次打标签,比如“意图已识别”“含敏感词”“用于上下文补充”,标签之后再做取舍。输入层整体上就是一个不停做“减法”的过程,减少噪音,减少无关历史,减少冗余检索,才能让模型真正聚焦到该回答的问题上。
5. 输出层:模型说完之后,事情才刚开始
5.1 解码参数要按任务类型分开调
很多人对解码参数不敏感,觉得temperature、top_p只是玄学。实际上它们对输出层的稳定性影响巨大。简单说,temperature控制生成时的随机性:数值低,输出更确定、保守;数值高,输出更多样、跳脱。top_p控制候选词的概率累计范围,它做的事情和temperature类似,但作用机制不同。两者通常搭配使用,不需要同时猛调。
我做任务时会按类型定一组基准值。事实性任务比如“从表格里找数据”“生成JSON结构”“回答问题并附出处”,temperature给到0.1到0.3之间,top_p给到0.6到0.8之间,让模型尽量走确定性通道。创意型任务比如写文案、起名字、头脑风暴,temperature给到0.7到0.9,top_p给到0.9左右。还有一种常见套路是中高temperature生成多份候选,再用规则或模型打分挑最优,这属于把随机性和筛选结合起来,效果通常比低temperature单次生成更好。
max_tokens也不能随便设。它的作用是控制输出最大长度,但如果你设得太小,模型可能在生成过程中把输出截断,最常见的情况就是JSON输出到一半突然断了。设得太大又会让生成时间变长、成本变高。我一般会给一个比预期输出长约20%到30%的额度,并且在解析失败时把错误信息拼到输入里,让模型接着补全,而不是简单重来。
5.2 结构化输出:让模型说系统听得懂的话
自由文本很炫,但系统往往消费不了。真实业务里,你需要的是字段、是JSON、是能落到数据库的结构化数据。现在很多模型接口原生支持JSON模式,或者你可以通过提示词要求“只输出JSON,不要解释”。但请注意,提示词约束并不能做到百分百稳定,解析层依然要保留容错逻辑。
我的输出层流水线大致是这五步:先请求模型输出,要求带固定格式标记;然后解析响应,若解析失败就做轻量修补,比如补上缺失的右括号、去掉多余的逗号;如果修补不了就把解析错误信息加进输入,让模型重新生成;再对成功解析的内容做字段级校验,非空校验、类型校验、枚举值校验;最后才交给业务逻辑。这五步听起来繁琐,但真能帮你省掉大量线上问题。
结构化输出的另一个关键是让模型学会“分步表达”。我会让模型先输出一个被标记为“思考过程”的字段,再输出最终答案。这么做的好处是,模型在生成最终答案前先经历推理过程,准确率会提升,而且思考过程可以作为排查问题的日志信息。你甚至可以把思考过程从最终返回里剥掉,只把答案展示给用户。
5.3 后处理与校验:不是模型说什么就是什么
输出处理最容易被人忽略的就是校验环节。为什么必须校验?因为大模型不是数据库查询接口,它生成的所有内容都只是“看起来合理”的文本。你对它说“返回2024年3月销售额最高的地区”,它真有可能给你一个很流畅但完全不存在的地区名或数字。
我通常给输出结果接三类校验器:第一类是格式校验器,检查JSON结构、字段类型、长度限制;第二类是业务规则校验器,比如日期不能晚于今天、清单里的渠道名必须在枚举内、数值不能超过合理范围;第三类是事实一致性校验器,在涉及可查数据时,把模型输出的关键数字和检索源做一次对比。如果第三类校验失败,我会触发一次检索重试,再把对比结果作为提示词的一部分反馈给模型,让它修正。
这个思路特别重要:模型输出不是终点,而是另一个环节的输入。你能围绕它做重试、修正、提醒、转译,最终产出的是一个可信、稳定、可追溯的结果。很多AI应用给人的感觉“有时候好用有时候辣鸡”,差就差在输出层的校验和补救机制完不完善。
5.4 流式输出和稳定性并存的处理思路
流式输出是为了改善用户等待体验,但因为是一次字一个字段地往外出,中间很难做结构校验。我的处理办法是,前端先接到原始流式段落,后端起一个临时缓冲区,等完整响应结束后再做一次解析和校验;如果校验失败,走补救流程,前端再刷新对应区块。很多用户对“结果瞬间变化”的感知并不强,但他们对“卡住不动”的感知很强,所以流式体验和结果准确性需要同时考虑。
流式过程里还有一个常见问题:模型在输出过程中会自动调整说法,导致最终拼接起来的文本里出现重复语句。这种时候,输出层可以做一次去重后处理,将相邻重复片段合并。虽然有点“脏”,但确实能提升终稿质量。我是把输出层想像成“一条组装流水线”,每个环节各司其职,模型只负责产原料,后续加工才是我们真正的工程主场。
6. 一个实际案例:某报表助手Demo的改造过程
6.1 场景与原本问题
为了把这套框架串起来,我完整讲一个虚拟项目:某报表助手Demo。这个Demo的业务是让用户用自然语言查询一个公司内部的销售数据,比如“这个季度哪个地区销售额最高”“对比上个月各渠道的转化率变化”。用户希望系统返回一句简短结论和一组结构化字段,方便前端直接渲染成卡片。
一开始的做法很粗放:把用户问题原样丢给底座模型,再让模型自由发挥。结果非常不稳定,问题主要有三类:第一,模型经常编造不存在的地区名和销售额;第二,输出有时是长段落,有时是JSON,结构不统一;第三,遇到“上个月”这类相对时间时,模型无法知道具体是哪个月,答案是错的。
这些问题很明显同时涉及输入层和输出层。底座模型本身并没有错,错在它拿到了过于模糊的输入,又没有被约束输出格式,自然只能凭感觉生成。
6.2 三层分别做了什么调整
底座层不做任何变更,用的依然是那款开源底座模型(7B参数级别),因为我要验证“不动模型也能解决问题”。
输入层做了三件事。第一,在系统提示词里写清楚角色:你是销售数据分析助手,只能基于提供的表格数据回答,不能编造数字;第二,写了一个查询标准化模块,把用户问题改写成结构化意图,比如提取时间范围、地区维度、指标名称;第三,动态检索其实很简单,就是从数据库里把对应时间范围的汇总数据拼进上下文。这里我特意只放关键结果,不把整张原始表塞进去,比如给出“华东地区Q2销售额382万”“华北地区Q2销售额276万”这种摘要信息。
输出层做了四件事。第一,temperature调低到0.15;第二,提示词要求输出严格JSON,包含summary、region、value、trend四个字段;第三,后端加了JSON解析器,解析失败时把错误信息拼进一个新的提示词,让模型重新生成;第四,校验模块把解析后的value和输入上下文里的数字做对比,不一致就重试。下面是核心伪代码:
def generate_report(user_query, retrieved_data): prompt = build_input(user_query, retrieved_data) for attempt in range(2): raw = model.generate( prompt, temperature=0.15, max_tokens=512 ) payload = fix_and_parse_json(raw) if payload is None: prompt = prompt + "\n注意:上次输出不是合法JSON,请重新输出合规JSON。" continue errors = validate_fields(payload, retrieved_data) if not errors: return payload prompt = prompt + f"\n注意:字段校验失败:{errors},请对照上下文修正数字。" return fallback_result(retrieved_data)这段伪代码不算复杂,但把它加到原有流程后,Demo的可用性立刻上升了一个档次。它本质上是把输出层的重试和校验封装成了循环,弥补了模型偶尔“胡说八道”的问题。
6.3 改造前后的对比与结论
改完输入输出之后,我还跑了一组测试数据,效果对比如下:
| 评估维度 | 改造前(裸问答) | 改造后(三层优化) |
|---|---|---|
| JSON结构成功率 | 约55% | 95%以上 |
| 数字与数据源一致性 | 经常错误 | 校验后基本一致 |
| “上个月/本季度”理解 | 经常错误 | 标准化后准确 |
| 接口返回耗时 | 不稳定 | 略有增加但稳定 |
从这张表可以看出,问题没有出在底座层,而是出在使用方式上。一个7B级别的小模型,在输入输出两端被“管好”之后,完全可以在内部报表场景里做出可用效果。这给我一个很深的启发:很多业务场景“模型能力不够”的判断,往往是过早下的结论,先别急着换模型,把输入输出做精细,收益通常比你想象的大得多。
7. 常见问题与排查技巧实录
7.1 排查顺序:先输出,再输入,最后才怀疑底座
我见过很多人在调模型时一上来就怀疑底座能力不行,赶紧换模型、上微调,折腾半天问题依然在。我的排查顺序完全不同:先看输出,再看输入,最后才看底座。
为什么先看输出?因为输出结果是最直观的线索。如果返回的内容格式乱、语法错、结构残缺,那问题大概率出在输出层:解码参数设置过于激进、max_tokens太短、结构化约束不强、解析逻辑太脆弱。先把输出层稳住,再看内容对不对,这是最高效的路径。
内容对不对涉及输入层的排查:系统提示词是否把任务描述清楚?上下文里有没有足够和准确的参考资料?检索结果是否被淹没在大量无关文本里?用户输入是否经过标准化?这些检查完,如果输入输出都正常但结果还是不对,那时才需要怀疑底座模型的能力边界。这个过程能帮你省下大把调参时间,也能避免在错误层上反复试错。
7.2 三个高频坑与对应解法
第一个坑:提示词写得很长很全,但模型不听话。这通常不是提示词写作问题,而是约束太多了,模型处理不过来。解法是把强约束拆出来放前面,弱约束用示例表示,同时避免互相冲突。比如“必须少于100字”和“详细阐述背景”就是自相矛盾,模型往往会选择后一种,导致第一条失效。
第二个坑:JSON频繁被截断。这类问题的根因多半是max_tokens太小,模型没生成完就被切断。解法是调大max_tokens,同时在后处理里做修复:给未闭合的JSON补右括号、修复多余的逗号。如果你用的是流式接口,还要注意完整响应后才做解析,不要在中间状态上处理。
第三个坑:加入了大量Few-shot示例后效果反而变差。很多情况下,示例和当前任务不够匹配,或者示例里包含的细节太多,变成了另一种形式的上下文噪音。解法是只保留三到五个高质量的示例,围绕“结构相同、风格一致、关键字段可参考”这三个原则选择,而不是越多越好。
我再补充一个隐藏很深的经验:记得给输入输出的前后版本做日志记录。把每次请求的系统提示词、检索结果、原始输出、后处理结果存下来。看起来多花了一点存储成本,但对排查线上问题帮助巨大。有一次线上用户反馈回答不对,我一查日志就发现是检索结果里混了一条过期广告文案,被当成业务数据塞进了上下文。如果没有日志,这类问题排查起来会像大海捞针。
7.3 什么时候才真正需要动底座层
聊到最后,难免有人问:那底座层是不是永远不用动?也不全是。当你把输入输出都做到位了,问题仍然频繁出现,且问题集中在模型推理能力不足、领域知识严重缺失、指令遵循能力有限时,可能真的需要考虑换更强的底座,或者做领域微调。
判断标准很简单:同一类问题,在输入输出都优化过后,失败率是否仍然高于你能接受的阈值。如果是,可能是底座的问题;如果不是,那大概率还是输入输出有遗漏。我通常会拿一批困难样本做回归测试,对比不同底座的失败率,用数据说话而不是靠感觉。
8. 经验与体会:把这套框架用在下一个项目里
我个人在实际操作中的体会是,三层架构这个框架不是理论玩具,它更像一张草图,帮你快速判断问题出在哪个环节,以及哪些创新值得做。你接手一个AI项目时,先别急着写提示词,先问自己:底座选谁,输入怎么组织,输出怎么处理。把这三个问题写下来,项目的基础结构就清晰了,后面做的所有优化都可以归位。
还有一个很实用的小技巧:每次看到一个其他人分享的AI玩法,试着把它归类到输入或输出层。比如某个技巧是“把历史工单做成示例库自动注入”,那就是输入层;某个技巧是“用模型输出做二次打分再选最优”,那就是输出层。归完类之后你会发现,所谓“新花样”并没有那么多,很多只是同一套思路换了个壳。但恰恰是这种“换壳”能力,让AI应用的迭代变得异常迅速。
最后提醒一句:不要盲目相信某个技巧在当前项目里一定有效。最好的做法是快速做小实验,记录对比数据,然后决定是否采用。输入输出层的改动成本都很低,适合频繁试错;底座层的改动成本高,适合慎重评估。把精力和成本花在对的层上,整个项目的推进速度会完全不一样。