前面我的笔记完成了从宏观全景图到具体场景落地的完整思路。

也理解了大模型应用的大体开发流程,需要什么技术,哪些技术用于什么用途。

然而,如果想在大模型时代成为系统架构师,而不是工具使用者的话,仅仅停留在表面会用是不可以的。

如果,你面对生成内容偏离预期、响应速度缓慢、上下文理解混乱等情况,你选择反复调整提示词碰碰运气,还是说分析背后原因——是模型注意力机制没有捕获到关键信息?还是说位置编码导致长文本失效?还是说解码策略引入了不必要的随机性?

所以说啊,真正的掌控力,来自于对底层逻辑的理解。

我们不说复杂的数学推导,来用类比 来进行比喻类的说明。走进大模型的终究核心——神经网络架构:Transformer。它就是ChatGPT、Llama等主流大模型的技术基石。

1. RNN到Transformer

Transformer并不是一开始就出现的东西,在探究Transformer之前,我们还是要知道一些演变过程中的关键节点。

1.1 循环神经网络

业界在Transformer出现之前,主流的语言模型其实是RNN:也就是循环神经网络, 还有它的变体:LSTM(Long Short Term Memory:长短期记忆网络)和GRU(Gated Recurrent Unit:门控循环单元)。RNN的雏形可以追溯到1990年代了。

RNN的核心思维,是通过循环连接建模序列数据的时序依赖。

我们要搞懂几件事情:

1.1.1 RNN 出现的目的是什么?

因为在RNN出现以前,普通的神经网络有一个问题:

它更擅长处理”固定长度、彼此独立“的输入:

  • 一张图片
  • 一组固定维度的特征

但是语言、语音、时间序列并不是这样的。

比方说我说一句话:

我 今天 要去 公司 上班

这里每个词都和前面的词有关系。
你理解”上班”的时候,前面的“我” “今天” “要去公司” 都会影响到其含义。

所以就需要一种网络:

  • 能够按照语序处理数据
  • 能够“记住前面看到过的内容”
  • 能够把前面的信息传递给后面

这就是RNN的出发点。

1.1.2 RNN的核心思想便是:有记忆的网络

你直接把RNN理解为一个边读边记笔记的人。

它并不是一次性把整句话都给读完,而是一个词一个词的去读的:

  • 先读第一个词
  • 更新一下“脑海里的状态”
  • 再读第二个词
  • 再更新一下状态
  • 循坏。。。

这种“脑海中的状态“,我们可以称之为Hidden State(隐藏状态)

1.1.3 RNN的直观理解

假如说我的句子是:

我 喜欢 学习 AI

RNN的处理方式是:

  1. 输入: 我
    输出一个隐藏状态 h1
  2. 输入: 喜欢 + 上一个记忆h1
    输出一个隐藏状态h2
  3. 输入:学习 + h2
    输出一个h3
  4. 输入:AI + h3
    输出一个h4

也就是说! RNN每一步都依赖于:

  • 当前输入 x_t
  • 上一步记忆 h_{t-1}

然后算出:

  • 当前输出
  • 当前新的记忆 h_t

所以说,他才叫做循环神经网络,不是因为代码写了loop,而是”状态会循环传递“

1.1.4 可以理解成”滚动上下文“

RNN的本质就是

用一个不断更新的状态,去压缩之前看到过的所有的信息。

比如说你读到第四个词了,理论上h4就包含了:

  • 第一个词的信息
  • 第二个词的信息
  • 第三个词的信息
  • 当前第四个词的信息

所以说,RNN在当初很适合用来:

  • 语言模型
  • 机器翻译
  • 文本分类
  • 语音识别
  • 时间序列预测

1.1.5 简单的RNN 类比示例

你可以把RNN想象成你在听别人讲话:

对方一句一句的说,你的大脑不会每次都从头去听,而是会保留前文的印象

比如说:

  • ”小明今天没有来。。。因为。。。“
  • 听到”因为“的时候,你还记得”小明今天没有来“

这就是RNN最想模拟的东西:
当前理解 = 当前输入 + 之前记住的内容

1.1.6 那为什么RNN还不够好?

RNN优势非常明显:

  1. 天然适合序列
    它可以按照时间同步处理,很符合语言和时间序列的结构。
  2. 参数共享
    每一步都用同一套参数,不用每个位置都单独训练一套
  3. 有”上下文记忆“
    后面的计算会依赖于前面的状态

但是它还有几个问题:

这里也就是理解Transformer之前,最重要的一点!

  1. 越远的记忆越丢失

    你看这句话:

    我小时候住在上海,后来搬到北京,大学的时候去了成都,毕业之后在深圳找的工作,所以我最熟悉的城市并不是上海,反而是深圳

    当模型读到”深圳“的时候,前面”我小时候住在上海“ 以及离得很远了。

    理论上RNN可以记住前文。

    但是实际上,离得越远的信息,越容易丢失。

    这就叫做

    长距离依赖问题

    也就是说:

    • 短距离关系还行
    • 太远的关系就很难抓住了

    为什么会丢掉?

    可以先粗略地理解成“记忆被冲淡了”

    因为上面说了,RNN是一步步传递状态的:

    h1 -> h2 -> h3 -> ... -> ht

    每一步都会对旧信息做一次变化。
    变化的次数一多,前面的信息就会模糊起来

    有点像:

    • 你把一句话转述给20个人
    • 后来内容就变形了。
      这就是LSTM和GRU出现的原因。
      它们的目的就是让RNN改良,让“重要信息不要那么容易丢掉了”
  2. 训练的很慢,不能够很好的并行

    RNN是按照顺序进行计算的:

    • 先算第一个词
    • 之后才能计算第二个词
    • 再然后才可以计算第三个词

    因为第二步是依赖于第一步的hidden state的

    这也就意味着,它无法像transformer一样,在训练的时候将一整句话高效且并行地计算掉

    造成的核心问题就是:

    • 训练速度慢
    • 长序列效率差
    • GPU利用率不够理想
  3. 梯度消失/梯度爆炸
    这个有点复杂,不过问题不大。

    我们只需要知道:
    训练神经网络靠的是反向传播
    而RNN序列很长的时候,梯度就需要跨很多步才能传回去。

    于是就会出现:

    • 梯度消失: 前面的信息直接几乎就学不到了
    • 梯度爆炸:数值特别大,训练很不稳定
      综上所述,只需要记住一点:RNN在长序列训练上,数学上也不稳定

1.1.7 LSTM和GRU

简单来说就是可以理解成更高级一点的RNN

主要是因为RNN老忘东西,后来大伙做了改进版。

本质上依然是上面提到的h_t和x_t的循环。但是加上了更加复杂的门控机制

所谓的门我们现在深究,意义也不大。但是你可以这么理解:

  • 什么该记住
  • 什么该遗忘
  • 什么该继续传下去

这样一来,就比普通的RNN更加擅长处理长距离依赖的问题。

神经网络训练的发展路线说白了就是:

普通RNN > LSTM/GRU -> Transformer

1.2 解编码架构

解码——编码 (Encodr-Decoder) 架构,如图所示:这是一种新的神经架构,包括了一个编码器(Encoder)和一个解码器(Decoder),用来将源语言解码为固定长度的向量表示(包含语义和上下文信息),并且从该向量表示解码成目标语言
688
是不是有点蒙了,没事,我整理了一份口诀:

源句子:我 / 喜欢 / AI
   ↓
Embedding
   ↓
Encoder RNN 逐个读取
   ↓
得到整句语义状态
   ↓
传给 Decoder RNN
   ↓
从 <START> 开始逐词生成
   ↓
I → like → AI → <EOS>

然后我们再来看一份图:假如我们的任务是把中文翻译成英文。

源输入:我 / 喜欢 / 学习
           ↓
      [嵌入层 Embedding]
           ↓
      [编码器 Encoder]
   先读“我” → 再读“喜欢” → 再读“学习”
           ↓
   得到一句话的大概意思
      “说话的人喜欢学习”
           ↓
      [解码器 Decoder]
   从 <开始> 出发,逐步生成英文
           ↓
   第1步:I
   第2步:like
   第3步:studying
   第4步:<结束>

你可以理解成两个人合作:

  • 编码器: 一个负责听中文、理解意思的人
  • 解码器: 一个负责把这个意思用英文说出来的人

反正就是

编码器负责把源句子的意思提炼出来、解码器再根据这个意思一步步生成目标句子。

后来出现了一个叫做attention的东西。

因为大伙发现不行啊,要是一直循环神经网络,RNN最后都会压缩成一个最终状态,长句子信息容易丢失不说,压力也很大。于是改进了一下:

  • 编码器不仅仅输出最后一个状态
  • 而是把每个时间步的隐藏状态都给保留起来
  • 然后在解码生成每一个词语的时候,都去”看一眼“输入序列的所有位置
  • 决定当前应该重点关注什么地方

2017年,谷歌提出了Transformer架构,彻底就改变了这一局面。它的核心就是:抛弃循环架构,完全依赖于”注意力机制“(attention)来建模词与词之间的关系。不过要注意的是,Transformer本质上也是一种编码器—解码器架构。

然后Transformer的出现,就把这个attention进一步升级成了Self-Attention

不要只看解码器输入
序列里的每个位置,都可以直接和其他位置建立联系

比方说:

小明把书放在桌子上,因为它太重了

这里的”它“可能要去关注前面的“书”或者“桌子”
在self-attention里,“它”这个位置就可以直接去查看整句话中其他的位置。

再举一个很简单的例子:

我输入中文:

我 喜欢 苹果

输出英文:

I like apples

没有attention的话

编码器:把整句话压成一个”总体的意思“
解码器:全靠这个总意思往外生成

有一个问题:

  • 丢细节

有Attention的话

解码器生成I的时候,主要看”我“
生成like的时候,主要看”喜欢”
生成apples的时候,主要看“苹果”

如此一来,翻译效果更准。

到了Self-Attention之后

输入端自己内部也会做更强的关联建模:

  • 比方说“苹果”会结合前面的”喜欢“
  • ”我“会结合后面的内容
  • 每个词都不是孤立的理解

所以Transformer在这些attention(注意力机制)出现之后,架构就成为了这样的:


让我们用最简单的人话来讲解一下这张图:

假如我们的任务是:

把中文翻译成英文

我们输入句子:

我 喜欢 学习 AI
  1. 第一层:嵌入层
    先把每个词语都变成向量。
    比方说:

    • 我 -> 转为向量
    • 喜欢 -> 转为向量
    • 学习 -> 转为向量
    • AI -> 转为向量
      但是,这还不够,因为模型不知道顺序
  2. 加位置编码
    把“第几个词”的这个信息也加进去
    这样模型才知道:
    “我” 在第一个位置
    “喜欢”在第二个位置
    “学习”在第三个位置

    不这么做的话,Transformer会把句子看成一堆无序的Token

  3. 进入编码器
    主要做两个核心的事情

    1. 多头自注意力
      让句子里面每个词语都可以看到其他的词
      比如说“学习”可以关注:

      • 谁在学习? “我”
      • 喜欢什么? “学习 AI”
        这样每个词语的表示就不是孤立无援的,而是带动上下文的。
    2. 前馈网络
      对于每个位置的表示再做一次非线性的加工,增强表达能力

      最后中间的位置加上:

      • 残差连接
      • 层归一化
        倒也不用了解这些是干嘛的,只需要知道,这些都是为了训练更加稳定。
        最后编码器输出的就是:对整句话输入的上下文化表示
        这不是一个词典式的向量,而是一组“已经理解过上下文”的表示。
  4. 进入解码器
    解码器开始生成英文。
    比方说从<START>开始:

    第一层:掩蔽多头自注意力
    解码器先看“自己已经生成了什么”。
    比如说现在已经生成了:

    • I
    • like
      那么,它在生成下一个词语的时候,只能看前面这两个,不能看未来的东西。
      “掩蔽”的作用就是这个了

    第二层:编码器-解码器注意力
    然后解码器去看编码器输出的中文信息
    比如说:

    • 现在要生成like
    • 它现在就会重点关注中文里的“喜欢”

    这一步就相当于:
    一边看自己已经说了什么,一边回头看原文

    第三层:前馈网络
    再进一步地进行加工与表示
    最后再经过全连接层(里面其实还有线性层、softmax之类的),不过主要还是生成输出下一个词语的概率。然后选择一个高概率的词语进行输出。比如:

    1. I:0.65
    2. He:0.12
    3. She:0.23

编码器的核心组件就是多头自注意力机制(Multi-Head Self-Attention)。

解码器的核心组件则是掩蔽多头自注意力和编码器-解码器注意力机制(Cross-Attention)

这其中,自注意力机制使得序列中每个位置的表示,都可以直接与其他位置建立联系,并根据相关性聚合信息,从而显著提升了序列内部的信息交互能力。

而多头注意力机制则更进一步:
它通过并行地使用多个注意力头,从不同子空间、不同角度去建模词与词之间的关系,因此能够捕获更加丰富、多样的依赖模式。

这种设计带来了几个重要优势:

  • 并行化训练更强:相比 RNN 按时间步顺序计算,Transformer 可以对序列中的各个位置并行计算,训练效率大幅提升。
  • 全局依赖建模能力更强:任意两个位置之间都可以直接建立联系,无论它们在序列中相距多远。
  • 可扩展性更好:模型结构更适合堆叠和扩展,为大规模预训练模型的发展奠定了基础。

没有Transformer,就没有如今的AI大模型时代浪潮。

2. Transformer 架构的全景图

Transformer实际上整体采用的就是“编码器——解码器(Encoder-Decoder)”的结构:

用机器翻译为例,Encoder(编码器)负责理解输入句子(比如说Hello !world!),提取语义特征之后。Decoder负责根据编码结果,逐词生成目标语言(你好!世界!)

不过也有一些模型,比如ChatGPT这种,只用到了decoder部分,因为它不需要翻译或者编码输入,直接基于上下文预测下一个词语。

2.1 输入表示:词语是如何被“数字化”的?

模型是无法处理文字的,必须要把它处理成向量。这个过程实际上被分成了三部分:

  1. Tokenization(分词)
    首先,将句子切成基本单元(Token)。

    例如:“我喜欢学习AI.” -> 分词结果:["我", "喜欢", "学习", "AI", "。"]

    每个Token会被映射到一个唯一的ID,比如 “AI” -> 1024

  2. 词嵌入(Word Embedding)
    每个Token ID通过查表转换为一个高维向量,这个向量蕴含语义信息。例如,“国王“和”王后“的向量距离比较近。
  3. 位置编码(Positional Encoding)
    由于Transformer没有顺序处理机制,不像RNN那样,天然有顺序机制。所以必须显示地告诉模型:这个词语在第几个位置。于是引入了位置编码——这是一种基于正弦函数的固定模式,加到词向量上面,让模型可以感知词序。

    举个例子:
    你想象一下,你在听一个脱口秀,演员说了10句话。如果这些话被打乱播放,这个脱口秀的笑点就完全get不到了。位置编码就像是给每句话贴上时间戳,让模型知道”哪一句话先说,哪一句话后说。“

2.2 核心引擎:自注意力机制

上面提到的self-attention,是的,这里再细讲一下。

这玩意儿可以说是Transformer最革命性的设计,大模型理解上下文的关键所在。

2.2.1 自注意力机制到底是啥啊?

这是一种让每个词都根据上下文来动态调整它的自身表示(向量)的机制。对于每个词而言,会根据与上下文其他词的相关性来重新计算,从而得到新的向量表示。

这样可以帮助神经网络模型更好地捕捉到词和词之间的动态紧密关系,从而实现精确的预测输出。

简单来说,就是让句子里的每个词语去关注其他的词语,根据相关性来分配”注意力权重“

如:

”猫咪坐在垫子上,它挺舒服的“。 大模型处理”它“的时候,会自动计算”它“和”猫咪“ ”垫子“ ”舒服“ 等词语的相关性,最后发现”它“最有可能指代的就是”猫“,于是给”猫“分配了更高的注意力权重。

2.2.2 自注意力怎么工作的?(三步)

也就是老是被提及的 QKV框架。

简单来说,QKV就是“我该关注谁?我该拿走什么信息”的三套向量

  1. Query(查询):我想找什么?
  2. Key(键):我这里有什么信息标签,别人可以拿我来匹配?
  3. Value(值):我真正想要拿走的内容

然后用Q与K做点积,得到匹配度(也就是分数),最后通过Softmax(是的,上面的流程里面我提到了的东西)归一化得到概率分布。

加权重求和Value。上述权重对所有Value加权求和之后,就得到了该词语的新的表示——这个新的向量融合了上下文里面最相关的信息

就比如说:我在会议室里听五个人发言。我想了解“这个项目”的进展,于是乎:我对每个人的发言内容打分(谁提到了关键信息?)给讲的最清楚的最相关的同事最高的权重 综合他们的观点,最后形成了一套自己的理解 这就叫做自注意力的过程。

而多头自注意力,就是为了捕捉不同类型的依赖关系(语义,语法,指代等等),Transformer会并行运行多个注意力头,最后把结果拼起来。就像,我从“商业角度”,"技术角度“,”用户角度“思考一个业务问题。

2.2.3 前馈神经网络和残差连接

之前我们提到了这两个东西,这里再次进行一次强调:

在每个注意力层之后,都有一个前馈神经网络(FFN),它负责进行进一步非线性变换,增强模型表达的能力。

而残次网络(ResNet)就是深度学习模型的一种。核心目标就是让网络的每一层不要直接学习预期的输出,而是学习和输入之间的残差关系,它可以有利于拥有多层的深度学习模型更加易于训练,增加模型深度的同事还可以保持甚至提高精准度。

Transformer 大量使用残差连接和归一化的目的也是为了提高稳定性,防止深层网络训练崩溃。

冷门知识: GPT-3的模型有96层Transformer块,如果没有残差连接,连训练都办不到了。

2.2.4 掩蔽多头自注意力——解码器的独特设计

再次强调,在自注意力机制中,这里的掩码(Mask)的作用就是确保模型在处理序列数据的时候,只需要关注到当前位置之前的元素,不能看到当前位置之后的元素。这种机制非常重要;对于保持模型的合理性与预测的精准度有着至关重要的作用。

解码器也有自注意力层,所以这就是掩蔽多头自注意力产生的原因,不许偷看未来,确保生成过程是自回归的。

另外,之前我们还提到:解码器还有一个“编码器-解码器注意力”层,用于关注输入句子的关键信息(在对话模型中作用较小)。

3. 文本生成机制

好,上面说一堆,我们大概知道了模型怎么理解输入的了,下面我们来看看:它是怎么写出一句话的?

这个过程就叫做自回归生成,说人话就是”一个字一个字地猜测“

3.1 生成流程

根据上面我们了解到的流程,总结一个过程的话,其实是下面这样的👇🏻

  1. Prompt(输入)
  2. Tokenization(词元化)
  3. Embeddings(向量化) + 位置编码
  4. 多层Transformer blocks:Masked Self-Attention(掩蔽多头自注意力)+feed-forward Network(信息处理网络)+残差连接与归一化
  5. 输出一个概率分布
  6. 根据概率 Decoding/Sampling(选择一个词语)
  7. 将这个新词语加入输入序列
  8. 重复这个循环
  9. 直到生成结束符,达到最大长度,或者外部终止。

就比方说,我现在用提示词”写一个关于日本辉夜姬传说的故事“,(都给我去看超时空辉夜姬)我们来梳理一下生成的过程:

  1. 处理当前上下文

    模型先接收提示词“写一个关于日本辉夜姬传说的故事”,并将其进行 tokenization、embedding、位置编码,然后经过多层 Transformer blocks 处理,得到当前上下文的内部表示。

  2. 预测下一个 token

    基于当前上下文,模型输出词表上“下一个 token”的概率分布,表示接下来最可能出现哪些 token。

  3. 采样或解码选择一个 token

    模型根据解码策略,从这个概率分布中选出一个 token 作为当前输出。

  4. 把新 token 拼回上下文

    新生成的 token 会被加入到已有上下文中。

  5. 重复以上过程

    模型基于更新后的整个上下文,再次预测下一个 token,如此循环,直到遇到结束符或达到最大生成长度。

总的来说,输入:

写一个关于日本辉夜姬传说的故事

模型不会先”想完整个故事再一次性写出来:,更像是:

  • 读懂你的提示词
  • 猜下一个token最可能是什么
  • 选一个
  • 把这个结果拼回去
  • 基于“原提示+已经写出来的内容”继续猜下一个

说白了更像是:

边写边续,边续边重新参考前文。

并不是在脑海里”先把全文写完“

这个过程像是在一张巨大的概率地图里前进:模型每走一步,都会根据“当前已经走过的路径”重新判断下一步最可能往哪走

3.2 解码策略:这是决定生成风格的关键

为了让生成内容更加具备创造性和多样性,我们则会在概率分布里面加入随机性,比方说下面这两种采样策略:

  1. Top-K采样。所有的词元里,只考虑概率最高的K个,然后在这K个词元里按照它们的相对概率进行随机采样。优点是限制了采样的范围,避免了选中那些不靠谱的低概率词元
  2. Top-P(Nucleus)采样,这则是一种更为动态的采样策略。从概率最高的词元开始,不断累加它们的概率,直到总和超过一个预设的阈值(P,比如说0.95)。之后,模型就会只从这个概率总和超过P的核心词元(Nucleus)里面进行采样。优点是采样集合的大小是动态的。当模型非常确定下一个词语的时候(“I love”之后很可能是“you”),这个集合就会很小;当模型不确定的时候(一个开放式问题的开头),集合就会很大,允许更多的探索。所以Top-P通常会被认为是最好的采样策略之一。

就用我们上面说的竹取物语来举例:

现在经过模型的预测,下一个token的概率分别是:

  • 竹取物语:0.30
  • 月亮:0.25
  • 公主:0.20
  • 老翁:0.10
  • 发光:0.08
  • 竹子:0.04
  • 帝王:0.02
  • 其他:0.01

那么如果看Top-K,设置K=3 。那就只会保留概率最高的前三个,也就是(竹取物语,月亮和公主),其他的全部丢掉,然后再重新归一化,再随机采样或者按照策略选一个。

如果看Top-P,设置P的阈值为80%,那么就从高往低逐个累加,直到概率大于0.8为止,也就是(竹取物语,月亮,公主和老翁)。到这里已经超过80%了,所以保留这四个。最后再在这几个里面随机采样。

我只是挑这两个策略来说道说道,但是并不代表着就只有这两个策略,如下表所示,再多举几个例子,不同的采样策略可以带来截然不同的输出风格:

策略原理特点适用场景
贪婪搜索(Greedy Search)每次选概率最高的词快速且稳定,但是容易重复简单问答,摘要
束搜索(Beam Search)保留top-K条路径,全局最优连贯,缺乏创意机器翻译
随机采样(Sampling)按照概率随机选词多样性强,可能不合理创意写作
Top-K/Top-P(Nucleus)采样只从高概率的词语中采样平衡多样性和质量对话,诗歌
实际使用中,例如情感聊天机器人这种,推荐使用的是Top-P,P设置为0.9,然后 temperature(温度)设置为0.7,既可以保持自然流畅,又可以避免过于机械或者出现胡言乱语。

3.3 temperature (温度)的作用

温度采样,是一个调节参数,高温(>1)就会让原始概率分布变得更加平缓,使得低概率词元更容易被选中,结果也就会更具有创造性与随机性,但是也会导致出现更多的错误以及更多的胡言乱语。低温(<1)则会让概率分布更加的尖锐,高概率词元更容易被选中,结果就更接近于贪婪搜索,更加保守与确定。temperature = 0的时候,实际上就是贪婪搜索了。

温度参数控制了输出的”随机性“程度。

  • 低温(0.5):模型更加的保守,倾向于选择最高概率词 —— 输出很稳定,但是很呆板。
  • 高温(1.5):模型大胆,低概率词也会有机会被选中 —— 输出有创意,但是有可能会出错。
简单来说,低温有点像比较死板的人写论文,严谨,但是有点枯燥。 高温就像是诗人即兴创作,惊艳但是可能会跑题。

4. 作为开发者该如何利用这些知识?

理解Transformer和生成机制,其实主要还是为了要更加聪明地使用大模型

4.1 优化提示词工程

提示词工程的核心,不是写“神奇咒语”,而是把任务讲清楚。

一个好的提示词,通常需要明确任务目标、输出格式、目标受众和边界条件,并尽量提供足够的上下文,减少模型猜测空间。

与其只说“帮我总结这篇文章”,不如明确告诉模型:它扮演什么角色、总结给谁看、要分成几部分、语言风格如何、长度控制多少、哪些内容不能乱补。任务越清楚,输出通常越稳定。

在进阶层面,可以通过 one-shot / few-shot 示例,让模型更快学会你想要的格式或风格;也可以明确规定“如果信息不足,就直接说不知道”,从而减少幻觉。对于复杂任务,最好拆成多个步骤,让模型按顺序完成,而不是试图用一句话让它一次做完所有事。

对于开发者来说,最实用的优化方向通常是:结构化上下文、限制输出格式、加入示例、明确边界条件,并通过真实 bad case 持续迭代。真正优秀的提示词工程,不是一次写出来的,而是不断测试、修改和沉淀出来的。

比方说下面有四个例子:

4.1.1 实例1:摘要

NG:

总结一下

Better:

请把下面的文章总结成三个部分:
1. 核心观点
2. 适用场景
3. 常见误区

要求:
- 面向初学者
- 使用中文
- 每部分不要超过80个字
- 不要补充原文没有的信息

4.1.2 实例2: 信息提取

NG:

提取用户信息

Better:

请从下面的文本里提取用户信息,并且严格输出为JSON:
{
    "name": "",
    "phone": "",
    "order_id": ""
}

如果某个项目不存在,直接返回空字符串。
不要输出额外的说明

4.1.3 实例3:客服回答

NG:

回答客户问题

Better:

请严格根据提供的知识库回答用户的问题。
如果知识库里没有答案,请回答:“抱歉,当前问题我们暂未有方案处理,请联系我司电话热线”,并且回答知识库里的电话热线号码,不要自行进行猜测
语气要礼貌,简洁。

4.1.4 实例4:改写文案

NG:

帮我改的更好一点

Better:

请在不改变原意的前提下,优化下面的商品文案。
要求:
- 更适合电商详情页
- 语言更加自然
- 不要增加原文没有的卖点
- 不要虚购数据

4.2 合理管理上下文

在构建基于大语言模型的智能体或者对话系统的时候,上下文管理已经成为决定性能和可靠性的关键环节。尽管现代模型的上下文窗口已经显著扩大,但是“注意力预算”是有限的长上下文检索能力衰减、计算成本高等问题还是存在的。因而,如何在有限资源下高效组织和利用上下文信息,成为了上下文工程(Context Engineering)的核心课题。

4.2.1 上下文裁剪:精准舍弃冗余的信息

当历史对话或者输入文本逼近模型token的上限之时,最直接的办法就是直接裁剪掉。但是,简单地裁剪开头或者结尾,会把关键信息直接给弄没了。

所以我们的优化做法有下面几种:

  • 优先保留最近几轮的交互(因为最新的几轮里面往往保留了最新的意图)
  • 识别并且保留包含任务目标、约束条件或者用户身份的关键语句。
  • 避免删除工具调用结果或者错误反馈等对后续决策至关重要的内容。

裁剪并不是粗暴地删除,而是在“保真“和”精简“之间寻找平衡点。

4.2.2 滑动窗口:动态维护近期的上下文

滑动窗口策略通过维护一个固定长度的上下文”窗口“,随着对话推进,不断地更新内容。这种方法特别适合用于实时对话场景。

典型的做法就是:

  • 保留最近N轮对话。(比如最后五轮)
  • 结合时间戳或者对话轮次编号,确保逻辑连贯性。

局限和应对:

  • 可能会丢失早期设定的目标(比如:帮我写一篇关于气候变化的科普文章)
  • 建议将初始任务描述单独缓存,并且在每一轮提示中显式重申。

滑动窗口虽然很简单,但是需要辅以任务锚点机制,防止”记忆漂移”。

滑动窗口可以视为上下文裁剪中最简单的一种实现方式,但它只根据“新旧”来保留内容,而不判断信息的重要性。因此在复杂任务中,通常需要与任务锚点、摘要记忆或结构化状态一起配合使用

4.2.3 摘要压缩:用高密度信息替代原始记录

当上下文过长的时候,可引入 摘要压缩(Summarization) 技术,将多轮对话或者长文档提炼为简洁语义表示。

应用场景:

  • 将十轮客服对话总结为:"用户反馈订单#666 没有收到,要求加急处理,偏好电话联系”
  • 在代码Agent里,将之前的调试过程压缩成:“已尝试方案A失败,错误为Timeout;当前聚焦于优化数据库连接池”

实施建议:

  • 使用专门的压缩提示词,要求模型保留决策依据、未解决问题和关键结论。
  • 先追求高召回率(不漏信息),再迭代提高精准性(去除冗余)
  • 压缩后的新上下文应该作为“记忆锚点”,与最新交互共同构成完整的状态。
摘要压缩本质上是一种可控的有损压缩:它牺牲部分细节,换取更高的信息密度和更低的上下文占用。

4.2.4 关键信息提取:结构化存储核心要素

相比于全文保留,更有效的方法是从上下文提取结构化关键信息,比如说实体、意图、偏好、状态变量等等。

实现路径一般有以下几种:

  • 利用命名实体识别(NER)或者小模型(比如说主模型用GPT5.2,小模型可以用更便宜的Deepseek或者qwen本地大模型)抽取时间、地点、任务、金额等等信息。
  • 将用户偏好(“只看飞机经济舱” “避免节假日出行”) 存入外部状态变量
  • 在每次调用LLM之前,把这些结构化数据注入系统提示词。

这样做的优势就是可以非常大程度上的节约token的消耗,提升模型对约束条件的理解一致性,并且这样也可以和业务系统进行集成(CRM、订单系统)

这种“语义蒸馏” 策略,让上下文从“文本堆砌“变成了”知识驱动“。

值得一提的是: 这个关键信息提取和摘要还有点像,不过我们可以将其分为 给模型看的上下文摘要与给系统用的状态记忆。 摘要适合偏短期和中期;结构化提取更像是长期保存的,不过也可以用于保存短期任务状态

举个例子,用户说:

以后请尽量用中文回答,解释的时候多用示例。我这周在准备AI Agent 面试,重点项目是补充Prompt Engineering和RAG方面的知识。

summary的话会总结成:

用户偏好中文,喜欢举例,目前在准备AI Agent面试,重点学习的是Prompt Engineering和RAG

结构化存储记忆则会变为:

{
    "preferred_language": "zh",
    "likes_examples": true,
    "current_goal": "AI Agent interview prep",
    "focus_topics": ["Prompt Engineering", "RAG"]
}

这其中,preferred_language,likes_examples就适合长期保存
current_goal、focus_topics是中期有效

4.2.5 分层记忆机制:短期 + 长期协同工作

为了支持长时间、多阶段的任务(代码重构、研究报告撰写),我们还需要构建多层记忆架构

  • 短期记忆:当前会话的上下文,直接放入Prompt
  • 长期记忆:通过向量数据库、关系型存储、KV、文件系统或笔记文件等方式持久化保存的历史知识、用户画像和任务状态。

典型模式:

  • Agent 定期生成NOTES.md 文件,记录待办事项、架构决策或者实验性结果
  • 下次启动的时候,通过检索相关笔记重新加载上下文
  • 支持“渐进式信息披露” —— Agent需要按需查询记忆,而不是一次性全部加载

Claude Code就采用的这个办法,它不加载整个代码库,而是通过grep、head等工具动态检索所需文件,然后把关键结论写入笔记以供后续使用。

分层记忆不仅仅突破了token的限制,还模拟了人类“按需回忆”的那种机制。

综上所述,无论是裁剪、摘要,提取,还是分层记忆,这些策略全部都是为了一个核心原则:有限的注意力预算内,最大化上下文的信息密度和相关性。随着模型能力的不断提升,未来,Agent或许可以更加自主管理上下文——什么时候可以压缩,什么时候可以检索,有没有必要遗忘什么东西。但是如今,深思熟虑的上下文工程依然是构建可靠、有效、可以拓展的AI系统的基石。开发者的我们,应该把上下文当成一种战略资源,而不是无限的容器。这样做,才可以让LLM在复杂的任务里,输出你最想要的结果。

4.3 调优生成参数

  • 客服机器人:通过低温 + 贪婪搜索 确保精准性和一致性
  • 创意助手:利用高温 + Top-p 采样组合,激发灵感
  • 教育陪练:利用中等温度 + Beam Search(束搜索)的组合来平衡规范和引导。

    4.4 诊断生成问题

使用大语言模型用户经常会遇到两种典型问题:输出重复和内容偏离了主题。这些问题不仅影响了生成文本的质量,还可能会降低模型在实际应用里的可靠性。

4.4.1 输出重复:注意力分散或者解码策略不当

当模型生成的文本,出现了连续重复的短语,句子,甚至于说是段落的时候。

比如这样:
Prompt:

你介绍一下RAG的优点

生成的时候是这个样子:

RAG的优点有很多。RAG的优点主要体现在多个方面。首先,RAG的优点是可以提升效果...

这很显然就在打转了!!

通常就反映了下面的潜在原因:

  • 注意力机制失效或者分散了,在长序列生成的过程中,模型可能没有有效聚焦于关键的上下文信息,导致了反复的回溯并且复述已经有的内容
  • 解码策略参数设置的不合理。 比如你如果在使用采样(sampling)方法时,温度设置的过低,模型倾向于选择高概率词,缺乏了探索能力;同时,还缺乏重复惩罚的机制,就容易在局部高概率路径上反复循环,导致输出重复。

优化怎么做?

  • 降低温度:可以让模型输出更加确定性和连贯,减少随机跳跃带来的重复。
  • 启用重复惩罚机制:大多数现代推理框架支持 repetition_penalty或者no_repeat_ngram_size等参数。启用这些功能可有效阻止模型重复生成相同n-gram片段。
  • 结合束搜索(Beam Search)和惩罚策略:在需要高质量输出的场景中,可采用带有重复惩罚的束搜索,平衡多样性和一致性。

4.4.2 内容偏离主题:上下文过载或者关键信息没有被关注

当生成内容逐渐偏离原始话题,甚至引入无关信息的时候,往往说明模型未能准确捕捉用户意图或者上下文重点。

诱因:

  • 输入上下文过长了: 随着上下文长度的增加,模型的注意力可能会被稀释,难以识别核心指令或者关键的实体
  • 提示结构不清晰:模糊,冗长或者缺乏明确目标的提示会让模型难以聚焦,从而自由发挥导致跑题。

优化建议:

  • 重构提示:采用”角色+任务+约束“的结构化提示方式,比如:”你是一个动画制作者,请用300字总结seedance2.0带给动画行业的冲击,避免提及敏感信息,务必理性客观“
  • 缩短或者分段输入:对于超长对话或者文档摘要的任务,可以把上下文切分为逻辑段落,分布引导模型生成,避免一次性输入太多的信息。
  • 显式强调关键信息:在提示中使用加粗、引号、或者重复关键词等方式,突出核心的主题,帮助模型锚定焦点。

LLM虽然很厉害。但是在生成质量高度依赖于输入设计和解码配置。面对重复或者偏题的问题时,用户不应该仅仅视为模型缺陷,而应该视为人机协作的调优契机。通过合理调整解码参数、优化提示工程,我们可以显著提高生成内容的相关性、连贯性、实用性,充分发挥大模型的潜力。

4.4.3 总结

综合来说,当你发现模型输出的内容不对劲的时候,不要立刻怀疑模型的智商

先按照顺序排查

  1. 看你的Prompt是不是清楚

    • 任务是否明确?
    • 输出格式是否明确?
    • 有没有规定”不要做什么“的约束?
  2. 看上下文是否太乱

    • 是否有太多的无关内容
    • 是否关键信息被埋没了
    • 是否历史对话太长了
  3. 参数是否合适

    • 温度是不是太高,或者太低了?
    • Top-P是否太松了?
    • 是否缺乏了重复惩罚?
  4. 看任务是不是本来就该拆分

    • 是否一次性要多太多了?
    • 是不是应该多轮或者多步骤来完成?

思考

比如说现在我在开发一个基于大模型的长篇小说创作助手,随着故事的不断推进,我发现出现了下面的问题:

  1. 角色设定偏移:前期设定为”冷静理智的侦探“主角,第五章之后,莫名没有铺垫的情绪化,冲动,甚至做出了不符合人设的决策
  2. 关键线索遗失:第一章埋下的伏笔(比如一个陌生的女人叫他安可),在后续情节里,这个伏笔被完全忽略了。
  3. 生成内容重复:某些场景或者对话模式反复出现,比如每一章开头都在用”月光落在他的肩膀上“

从我们学习的内容来看

问题1:注意力机制在长上下文的信息稀释以及自回归生成的累积误差有关系。Transformer架构虽然可以处理长序列,但是随着故事的推进,前期的人设未必始终会被模型高权重关注;一旦模型在某一章生成了一些轻微偏移设定的内容,那么这个误差就会被后续持续生成的过程中继承与放大。

问题2:关键线索遗失主要还是和长距离依赖建模不稳定有关系。理论上Self-Attention可以捕获到远距离关系,但是在实际上的生成文本的过程中,早期信息容易被后续大量的内容给稀释掉,从而导致线索无法被召回

问题3:重复内容就和自回归生成机制与解码策略有关系了。模型在每一步都是基于上下文预测的下一个token,如果某些表达式在训练语料或者前文中属于是高概率,安全事件,就会被重复选择;如果采样策略更偏于保守,或者说没有重复惩罚机制,这个现象就会更加明显。

不重新训练模型,从工程化角度出发,策略有三,分别对应三个问题:

  1. 构建角色设定卡/世界观卡 :就像玩游戏一样,我在发动一个效果之前我得先把这些牛逼的设定卡放出来,这样我才会发动我想要的效果。 这些设定和世界观,都会在每次生成新的章节的时候,显式地注入。反复提醒模型主角人设,风格,为注意力提供稳定的锚点,减少角色偏移
  2. 构建剧情摘要+关键的检索表+检索式回填机制。 也就是说,把每一章节的内容压缩成摘要,并且把重要的伏笔以结构化的方式进行保存;在生成新的章节之前,根据当前情节检索线索并且回填相关线索。这种方式相当于用外部记忆来增强模型的长期记忆能力。
  3. 优化解码策略和生成之后的处理。 例如调整温度和top-p,启用重复惩罚机制,增加重复句式检测和重写。 这样就可以降低模型陷入局部高概率重复模式的风险,还可以提高表达的多样性。

    Transformer 能生成长文本,但不等于它天然擅长“长期一致性管理”;真正让长篇创作助手可用的,往往不是只靠模型本身,而是靠外部上下文工程、记忆机制和解码控制。
最后修改:2026 年 03 月 16 日
收款不要了,给孩子补充点点赞数吧