☰
大模型上下文工程实战:从提示词玄学到可验证的分层模板与评估闭环
2026/9/29 18:20:18 网站建设 项目流程

这些年我真正花时间最多的,其实不是调模型参数,而是研究怎么把喂给大模型的那段上下文整理明白。这个领域现在有个专门的叫法:Context Engineering,中文叫上下文工程。整套方法论说白了只有一句话:输入侧的文本组织方式,决定了输出质量的天花板。这篇内容主要讲上下文工程的完整拆解框架、实操步骤和评估方法,适合做大模型应用的开发者、做AI内容产品的运营,以及那些已经厌倦了"随机调提示词"、想走正规军路线的创作者。

我自己把这套方法论拆成四件事:目标拆解、上下文分层、模板组装、评估闭环。前两件管思路,后两件管落地。把它们连起来用,就能把"给AI写提示词"从玄学变成工程——你能说清楚每一段文字在上下文里承担什么角色、为什么放在这个位置、如何验证它真的起了作用。

1. 从"写提示词"到"搭上下文":Context Engineering到底在解决什么问题

很多人觉得上下文工程就是高级版提示词工程,这个理解对了一半。提示词工程关心的是"给模型一句什么话",上下文工程关心的是"给模型一个有结构的空间"。两者最大的区别在于视角:提示词是把文本当作指令,上下文是把文本当作环境。

1.1 上下文其实是模型的"工作内存"

现代大模型采用注意力机制,每一次生成都需要在上下文中查找和融合信息。你可以把上下文窗口想象成一个工作台,模型生成每个词的时候,都要在这个工作台上翻找相关的线索。工作台上堆的东西越乱、越无关,它的注意力就越分散,生成的输出就越容易跑偏。

这一点我是在做长篇小说生成时彻底想明白的。最初我的做法是把一整章剧情、角色设定、世界观资料全部塞进提示词,结果模型输出的内容要么人设崩塌,要么把设定名词当说明书写出来。问题不在模型,而在于上下文的空间被我浪费了——它一边要理解剧情目标,一边还要在一片无关信息里捞取关键设定,顾此失彼是必然的。

打个比方:工作台上放着一本厚词典和一张便签,便签上写着"今天要写主角在雨夜中追查线索"。模型可能更倾向于先翻词典,而不是先看便签。上下文工程要做的,就是把便签放大、加粗、放在最上方,同时把词典移到远处的架子上,只留翻到的那一页。

1.2 三个被低估的客观规律

做上下文工程之前,必须接受三个客观规律,否则后面做的所有优化都立不住。

第一,上下文窗口是有限资源,但不是越大越好。很多模型支持几十万token,你以为给得越多它就越懂你,实际上注意力是稀疏的,信息过载会造成"选择性遗忘"。检索增强技术之所以流行,靠的就是"只给模型此刻需要的那一小块知识",而不是把所有知识全lang进去。

第二,存在位置偏移效应。大量实验发现,当关键信息位于上下文文本的开头和结尾时,模型的利用效率更高,中间区域容易被忽略。这个现象在长上下文中尤其明显。如果你把角色设定放在一整篇设定集的中间,模型在续写时很可能压根没注意到它。

第三,矛盾指令会产生"上下文污染"。上下文里同时存在互相冲突的要求时,模型的输出会把两条都照顾一点,结果就是两边都不对。这种情况在多人协作维护同一份上下文时极其常见——上一版写的"不要解释"和新加的"请先说明原因"互相打架,模型就会生成一段既解释了又不解释的奇怪内容。

既然明确了这三个规律,方法论就有了方向:控制信息量、优化信息位置、消除信息冲突。下面我就按这套思路逐步展开。

2. 方法论总纲:先把目标拆干净,再把上下文分四层

我见过很多人在做上下文工程时,第一步就是改模板、堆措辞,这其实是把路走反了。正确的第一步应该是拆目标。目标没拆清,模板只是花架子。

2.1 先把目标拆干净:5W1H法

我自己在动手设计任何上下文方案前,都会先用一个5W1H清单把需求写下来:

  • What:这段上下文最终要让模型产出什么?是一段小说正文、一份分析报告,还是一条SQL?
  • Why:这个产出的核心评价标准是什么?比如"不需要修改就能直接用",还是"提供思路即可"?
  • Who:模型扮演什么角色?读者是谁?
  • Where:需要调用哪些外部知识?这些知识的权威范围怎么界定?
  • When:当前的任务上下文处于什么阶段?是一次性生成,还是多轮持续任务?
  • How:产出有什么格式约束?长度、风格、结构有什么硬性要求?

把这些写清楚后,你会发现90%的上下文问题都能自动暴露。比如你以为你需要的是一段小说正文,但写完5W1H后才发现,核心评价标准根本不是文笔,而是"角色行为模式不能偏离第三卷时建立的人物弧线"。于是你自然就会把角色弧线摘要放进上下文,而不是盲目堆砌修饰词。

2.2 分层上下文架构:从一层到三层

拆完目标之后,下一步就是把要放进上下文的所有信息分类。我习惯把上下文分成三层,每一层有各自的更新频率和职责。

稳定层承载几乎永远不会变的角色定义、底线规则、输出格式、任务总目标,代表"这个模型在这个场景里是谁"。业务层承载当前这一轮任务的描述、当前进度摘要、需要参考的示例,代表"现在具体要做什么"。动态层承载多轮对话里的临时状态、实时检索到的知识、用户刚刚给出的偏好,代表"此刻发生了什么"。

这个分层结构最重要的价值,是让每次迭代都有的放矢。你想改模型的长期人设,就去动稳定层;你想让这轮输出更贴近某个风格,就去动业务层;你想临时追加一个背景信息,就去动动态层。三层互不干扰,改起来不用全盘推翻。

2.3 token预算怎么分

分层之后要给三层分配预算。以8k上下文为例,我通常这样切:稳定层约256到512token,业务层约1600到2000token,动态层约1200到1600token,给模型输出预留至少2048token。剩下的零头作为缓冲,防止超长输入溢出。

数字不是死的,但两个原则必须守住。第一,稳定层能压多短就压多短,只写"绝不改变的核心",因为这部分永远占用预算,越长越浪费;第二,输出空间必须留足,如果系统提示词和参考资料已经把窗口挤到只剩几百token,模型生成到一半就直接截断,你再好的设计也白搭。

预算分好之后,才进入真正动手写上下文包的环节。

3. 实操第一步:用结构化上下文包锁住任务状态

光有分层还不够,文本的承载形式同样决定效果。我强烈建议采用结构化的上下文包,而不是一段口语化的大杂烩,原因是结构能帮助模型更快地定位信息类型,也方便程序化拼装和版本管理。

3.1 为什么非要用模板

大模型虽然能理解自然语言,但面对自然语言段落时,它需要花额外的注意力去"推断这段到底是什么意思"。而结构化的块状文本带有明确的类型标记,模型可以把注意力集中在块内部的内容上,而不是先花时间理解这个块的类型。

这里有个实际观察:同样一份角色设定,用"角色名:艾伦,性格:谨慎但易冲动,说话简短"这样的字段形式放入上下文后,角色一致性的保持效果显著优于夹在一大段散文里的同一个设定。背后的道理不难理解,结构化字段天然自带边界,不容易与上下文里其他文本混在一起被稀释。

3.2 一个能打八成的通用上下文包

下面是我自己一直在用的一个通用上下文包模板,适配小说创作、写作、分析等大部分文本生成场景。实际使用可以根据场景删减块,但关键块不要随便去掉。

VERSION = "2.3.1" ROLE = 你是本任务的执行引擎。只输出任务要求的正文内容,不解释、不提问、不输出与任务无关的内容。 TASK = 根据【当前状态】和【本轮目标】完成本节内容。 输出要求:正文约350字,以主角视角推进,保持场景连续性。 CONSTRAINTS = - 禁止直接陈述设定名词,设定只能通过行为和对话体现。 - 对话节奏快,内心独白不超过两句。 - 如果规则冲突,以CONSTRAINTS块为准,忽略指令正文内的其他要求。 STATE = - 当前场景:第三章·灯塔之下 - 最近三幕进度摘要:主角追踪线索至灯塔,发现灯塔看守人隐瞒了关键信息。 - 在场角色:艾伦(紧张),露丝(冷静) KNOWLEDGE = - 世界观条目:灯塔地下室存在第二扇门,只有潮汐低于某个水位时才显露。 - 角色卡:艾伦,容易过度谨慎但行动力强;露丝,擅长观察细节。 STYLE_ANCHOR = - 视角固定在主角身上。 - 段落以动作推进为主,环境描写不超过两段。 FEW_SHOT = - 上一幕结尾示例:他推开门,潮水的声音突然消失了。台阶向下延伸,尽头是一面湿漉漉的石墙。

模板有几个容易被忽略的设计点。CONSTRAINTS块里那句"如果规则冲突,以CONSTRAINTS块为准",是为了给自己的上下文加防冲突保险,防止工作流里其他环节注入的指令喧宾夺主。STATE块只保留"最近三幕摘要"而不是全量剧情,这能从根本上抑制token消耗。STYLE_ANCHOR和FEW_SHOT双管齐下,让模型既知道"要什么文风",又有了可模仿的具体样本,比单纯说"写得好一点"有效得多。

3.3 让规则真正生效的正反绑写法

写约束时有一条很重要的经验:规则要正着说加反着说一起上。只写"不要直白输出设定",模型经常照犯,因为负面指令限制的是行为,但模型不知道替代方案是什么。我一般会在负面指令之后补一条正面指令:"设定通过行为和对话体现",再配一个正面示例。这一步能补齐模型缺失的行为空间,减少顾此失彼的情况。

同样,在写角色约束时,不要只写"艾伦是个谨慎的人",而要连补一个行为模式:"做决定前会反复确认环境细节,但一旦确定就立刻行动",这样模型才有可演绎的行为素材。角色卡的本质不是标签集合,而是行为生成器。

4. 实操第二步:检索、压缩与位置安排——长文场景的上下文组装

模板解决的是单轮生成的结构问题。但如果你做的是连载小说、多轮对话助手、长文档分析这类持续任务,还有一个关键问题必须先解决:上下文窗口里根本没有空间放下所有历史信息,怎么办。

4.1 工程级AI小说场景的上下文组装

我实际做过一个连载性的AI小说协作项目,最初版本天真地把全部世界观设定、全部角色卡、全部历史章节一起塞进上下文,结果跑到二十章左右,输出质量断崖式下跌。后来改用了一套四步组装流程,才彻底解决。

第一步,设定知识库化。把世界观、角色、势力关系、伏笔线索全部拆成条目标记,存到向量库或者带标签的数据库里。第二步,按当前剧情窗口召回,只召回当前场景中出现的角色卡、地点条目、时间线条目和已经触发的伏笔,每个条目先用摘要形式呈现,全文仅在必要时保留。第三步,将所有召回内容进行二次压缩,把长条目改写为"关键词+一句话摘要+触发条件",保证每条不超过一两行。第四步,按优先级重排位置,当前场景直接相关的状态信息放在上下文的前部,背景性知识放在后部,关键约束放在开头和结尾区域。

这套流程的核心思路,是把无限的设定空间压缩进有限的上下文空间,保留的是"用于当前决策的关键摘要",而不是"全部原始材料"。很多人在这一步舍不得丢弃信息,总想着万一后面用到呢,结果就是上下文被低概率信息占满,高优信息反而被挤出了注意力范围。

4.2 对抗位置偏移:锚点与重排

位置偏移规律给上下文组装带来的直接指导是:把当前最重要的指令放到上下文靠近开头的位置,把必须遵守的格式约束放到靠近结尾的位置,把参考资料放在两者之间。但参考资料内部也要排序,与当前任务最相关、最不可遗漏的条目应该排在参考资料的最前和最后,中间放次要条目。

还有一个具体技巧:锚点句。锚点是指在上下文包的多个关键位置重复出现的短句,比如"主角目前的目标是找到第二扇门",开头业务层出现一次,状态块的摘要里再出现一次,结尾约束块里又带一句。重复不是浪费,而是故意利用模型对高权重位置的敏感度,确保这个关键状态在长上下文里也始终在线。

4.3 滚动摘要:长任务不崩塌的秘密

多轮任务做到后期,历史信息必然膨胀。我用的方案是基于摘要压缩的滚动记忆:每完成一个阶段,就调用模型把当前阶段摘要压缩成几条结构化短句,替代原文进入下一轮上下文。上一阶段的原文详细内容存储在外置知识库中,只有需要深挖时才被检索回来。

这里的取舍在工程上很关键。滚动摘要追求的是高密度、可组合,而不是文学性,每一条摘要都必须保留"事件结果+角色状态变化+悬而未决的线索"。同时摘要里要显式标记哪些线索还没回收,避免模型在后续续写时把这些线索彻底遗忘。

5. 用evaluation智能体把上下文工程做成闭环

做上下文工程的人最常犯的错,是永远在改进、永远不验证。改一句提示词,看一次输出,"好像好一点了",然后继续改下一句,根本不知道自己离目标还有多远。正确的做法是建立评估闭环。

5.1 没有评价就没有工程

上下文工程里有一个反复出现的现象:改动确实生效了,但影响是负面的。没有评估体系时,你只能凭感觉判断"这次输出对不对",完全无法区分是哪里出了问题。所以我后来做任何上下文工程项目,第一步就是写下评估维度,第二步才写模板。

评估维度要可操作、可打分。以长篇小说场景为例,我会拆成指令遵循度、信息忠实度、角色一致性、叙事连贯性、风格匹配度这么几项。指令遵循度考察输出有没有执行任务与约束;信息忠实度考察有没有篡改设定、遗忘状态;角色一致性考察行为决策符不符合角色卡;叙事连贯性考察与上一幕衔接是否自然;风格匹配度考察文风与风格锚是否一致。

5.2 把评价员做成智能体

人工评估太慢,没法支撑频繁的模板迭代,所以我干脆把评价员本身也做成一个AI智能体。这个智能体不看"人觉得好不好",只看预设维度里的具体表现,然后给出结构化分数和修改建议。下面是我常用的评估智能体系统提示词:

你是严格但公正的文本评估官。 你会收到三份材料:任务描述、上下文包、模型输出。 第一步:先列出输出中最重要的三个缺陷(违反了什么约束、哪里不连贯、哪里失真)。 第二步:按维度打分,1到5分,3分代表及格: - A 指令遵循度:输出是否执行了上下文包中的任务与约束。 - B 信息忠实度:是否出现幻觉、篡改设定、遗忘关键状态。 - C 角色一致性:行为、语气、决策是否符合角色卡。 - D 叙事连贯性:与当前场景和最近进度衔接是否自然。 - E 风格匹配度:是否符合STYLE_ANCHOR中的文风要求。 第三步:输出JSON格式结果,不要输出其他文字: {"defects":[],"scores":{"A":0,"B":0,"C":0,"D":0,"E":0},"suggestion":""}

这里有一个我踩过的坑:评估智能体很容易对输出心慈手软。如果提示词里只是笼统地写"请评估输出质量",它给出的分数通常偏高,因为大模型倾向输出温和的评价。解决办法就是上面模板里的两个关键设计:先列缺陷再打分,以及用结构化分数格式强制它逐项给出具体判断。评估维度的描述也需要尽量具体,比如"信息忠实度"要明确写"是否篡改设定、遗忘状态",而不是空泛的"信息准确度"。

5.3 评测集:迭代的"回归测试"

把评估智能体准备好之后,还要建一个评测集,收集10到20个典型任务样本,覆盖正常场景和边界场景。我通常会在项目启动时直接用上下文包生成一批样本,再人工挑出其中难度高的作为基准集,每次改版后统统跑一遍,记录分数变化。

如果某次修改让常规样本的分数涨了,但一个特殊样本分数掉了,你就能立刻定位到改动带来的副作用,决定是保留还是回退。这套机制本质上是软件工程里的回归测试,只不过被测对象从代码变成了上下文方案。它最大的价值在于终结了"凭感觉调prompt"的循环,让每次改动都有据可依。

6. 踩坑实录:上下文工程最常见的六个翻车现场

在做了大量上下文工程项目之后,我把高频问题汇总成了一份速查表,适合遇到症状时直接对照排查。

6.1 六个典型翻车现场

下表列出的是我实际遇到过的六类典型问题,以及对应最关键的处理动作。

症状关键原因立即动作
改了规则但输出没变化新指令优先级不够或被旧指令覆盖把规则提到稳定层顶部,同时加"规则冲突以本块为准"
角色越写越不像角色卡被长上下文稀释每轮把在场角色摘要重新注入,并把角色行为锚点放在信息前部
设定名词被写进正文模型把知识直接当素材在约束区补正面指令"设定通过行为和对话体现",加一段反面示例
上下文窗口溢出且输出变差塞了太多低优先级的全量信息对历史做滚动摘要,只保留当前相关的知识条目
评估智能体分数虚高评估标准太软、没有先挑错改成"先列三个缺陷再打分"的强制流程
输出风格一会像A一会像B上下文里存在互相矛盾的风格指令逐块检查STYLE_ANCHOR、FEW_SHOT和上一层系统提示,删除冲突项

实践中最难察觉的是第二类问题。角色一致性崩塌往往不是一蹴而就的,而是一步一步漂移的:刚开始只是语气细微变化,到三十轮之后已经完全变成另一个人。排查时不要只盯当前输出,要看上下文包里角色卡信息的相对位置是否在长对话中不断被后移,以及是否被其他新增信息压到了低权重区域。

6.2 排查思路:从输出反推上下文

大多数上下文问题都可以用一条反向排查链解决:先看输出哪里不对,再倒推是哪一类信息缺失或冲突导致了这个不对。比如输出内容有事实性错误,先检查检索召回的知识条目是否过于陈旧,再看STATE快照里关于最新状态的信息是否被截断;输出内容干瘪平庸,先检查FEW_SHOT示例是否具有代表性,再看TASK块里有没有给出足够具体的产出目标。

还有一种隐藏得很深的坑:业务层里的指令被动态层里的用户输入覆盖。如果你的程序会自动把用户说的话追加到上下文末尾,那么用户可能无意间用"随便写"或者"你自由发挥吧"这种话覆盖掉TASK块的严肃指令。解决办法是在上下文包的CONSTRAINTS块里明确标注动态输入的最高优先级上限,或者用编程方式把用户输入限制在特定字段内,禁止它进入指令区。

收尾:一个小技巧和一条底线

在这个领域摸爬滚打这么久,最后分享一个非常实用的小习惯:给上下文包加版本号,就是前面模板里的VERSION字段。别小看这一行字,它能让你在模型输出突然异常时迅速判断是模板改出了问题,还是模型本身发生了更新,也能让团队协作时明确知道当前哪份上下文包是权威版本。这个习惯我至今还在用,几乎所有长期项目都靠它兜底。

另一条底线建议是:上下文工程没有银弹,任何一次调整都尽量只改一个变量。同时改动了三个约束和两个示例,你根本不知道是哪个改动让输出变好的,下一次迭代就失去了依据。保持单一变量的节奏也许慢,但它让每一步优化都变得可以解释、可以复现,这才是方法论和"随手调prompt"之间最本质的差别。能用一句规则解决的,就不要堆十句;能在评估里验证的,就不要靠感觉拍板。做到这两点,你的上下文方案就已经超过绝大多数停留在玄学阶段的实践者了。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询