ReAct in math model

再接下来的章节中,我会用公式化的方式建模一个最基本的ReAct架构下面的agent运作流程:

我们设最终的目标$$ g = Open \;the \; WiFi $$
真实的环境状态是:
$$ s_t \in S $$
但是agent看不到完整的状态,它的观察只是基于部分事实所获得的:
$$ o_t = \Omega(s_t) $$
对于经典的ReAct模型,每一个step会生成reasoning和action,也就是:
$$ (\rho_t,a_t) $$
这个过程的产生是这样的:
$$ (\rho_t,a_t) = \pi_\theta(o_t,h_t,g) $$
即根据当前agent观测到的状态和历史context,再加上总目标g来得到下一个step的推理和动作

前面我们忽略了一个点,也就是这个$h_t$具体维护了什么?标准的历史会同时维护上文中的三个变量,公式化表达:
$$ h_t = \{(o_t,\rho_t,a_t),...(o_1,\rho_1,a_1)\} $$
接下来来看环境转移,也就是action之后会给agent什么样的变化:

首先是真实环境发生变化,然后agent的观察紧接着一块变:
$$ s_{t+1} = T(s_t,a_t)\\ o_{t+1} = \Omega(s_{t+1}) $$
重复这个循环直到完成整个过程/任务,这就是一个基本的ReAct循环的流程

大模型推理

本章节主要参考deepseek-r1的技术报告关于SFT以及RL的相关内容,加上一堆prompt engineering的部分构成,也算是一个强化学习的入门吧

DeepSeek-R1: Incentivizing Reasoning Capability in LLMs via Reinforcement Learning

原文链接:DeepSeek-R1: Incentivizing Reasoning Capability in LLMs via Reinforcement Learning

Deepseek-R1-zero:强基模下的纯强化学习

在zero版本的研究中,以deepseek-v3作为基座模型,本身就具有很强的推理能力的,然后在此基础上进行了纯粹的rl的后训练

没有任何复杂的类似于CoT这种详细推理流程的数据(without supervised data),都是类似于给一个推理问题,只告诉你对/错这种的样例

PPO

PPO的核心公式就一个,具体几个模型都是基于这个公式自然衍生出来的:
$$ L^{CLIP} = \mathbb{E}[min(r_t(\theta)A_t,clip(r_t(\theta),1+\epsilon,1-\epsilon)A_t)] $$
其中这个比率$r_t(\theta)$表示的是两个策略之间对于某一个动作的偏好,也就是高reward的决策,公式表示为:
$$ r_t(\theta) = \frac{\pi_{\theta}(a_t|s_t)}{\pi_{old}(a_t|s_t)} $$
说人话就是如果新策略相比于老策略能获得的reward更高,这个ratio的值就大于1,模型倾向于学这个策略,但是仅仅靠这个ratio是没法调整的,他只是一个衡量强化了多少的一个尺度,要想知道模型是否要优化 / 削弱模型的这一步就要靠这个$A_t$:
$$ A_t = R_t - V(s_t) $$
这里的两个参数分别是某一步实际得到的reward值和模型预测”这一步应该得到多少reward”的差值,比如说实际上这一步得到了0.9的reward,但是模型预测它只能获得0.4的reward,那么这个差值就是0.5,显然一个正的差值表明这一步需要被强化,所以在公式中体现就是一个正的loss

大致的流程就是这样,但是受限于他的训练中需要好几个roles,计算开销非常之大,现在页不太用了,我们接下来来看ds中的主角GRPO

GRPO

在PPO的基础上,GRPO提升的实际上是从绝对的优势打分($A_t$)变成一个group中的相对值,也就是说模型可能会给一个问题若干个答案,我们认为这些答案是在同一个group里面的,然后根据答案在group里面的排名来决定给多少强化/削弱

优化的目标函数:
$$ L = \frac{1}{G}\sum_{i=1}^{G}(min(r_t(\theta)A_t,clip(1+\epsilon,1-\epsilon,r_t(\theta)A_t)) - \beta KL(\pi_\theta || \pi_{ref})) $$
结合KL散度的定义,这是一个衡量信息之间的差距的函数:
$$ D_{KL}(\pi_{\theta},\pi_{ref}) = \sum_x P(x)log \frac{\pi_\theta(x)}{\pi_{ref}(x)} $$
好我们先解释清楚这个KL散度是干啥的,就是说给出两个策略,我需要衡量他们之间的差距有多大,考虑到策略$\pi$实际上是概率的累积的乘积,即:
$$ \pi_\theta = \prod_{t} \pi_\theta(s_t|a_t) $$
KL散度做了这样的一个计算,对于某一个step $t$,因为LLM是next-token的预测的,所以在不同的策略之下都会给出一个next-token的概率词表,那这个输出的token实际上在当前策略$\pi_\theta$和$\pi_{ref}$之间是不一样的,为了防止偏离的太远,于是加入这二者之间的KL散度惩罚项,在实际的GRPO当中,这个惩罚项是仅对于当前策略预测出来得token在两个策略之间的差异算入KL中的,并不是一整个词表,再把一整条rollout的误差累积起来就有了KL正则项。

除了这个KL正则项之外,因为GRPO是对于一整个组而言的,所以前文提到的优势$A$也可以用组内的相对差距来衡量,也就是:
$$ A_i = \frac{r_i - mean(r_{group})}{std(r_{group}) + \epsilon} $$

以上就是基本的PPO / GRPO的算法,回到ds的技术报告看

R1-zero探究了这样的一个问题:在一个相对较强的基模上,仅通过RL能训练出推理能力吗?

基模选用deepseek-v3,RL算法采用GRPO,奖励函数只由两部分组成:答案是否正确和输出是否符合指定格式

在格式的约束上非常简单,只提供了一个如下的template:

<think>
reasoing process
</think>
<answer>
answer content
</answer>

除此之外,不加入任何具有偏好性质的规定,如”请在每一步推理后思考一下是否正确”

实验结果证明,zero的推理能力取得了巨大提升,在这个过程中实现了模型的自进化,也就是推理步数越来越长,性能比肩o1模型

顿悟时刻(aha-moment):给定的用来RL的数据全都是最后只有个结果的,并不像正经的SFT把中间过程的推理全都写的很详细,但是在RL的过程中发现,模型到了一定的step之后学会了加一些停顿反思的环节

看这里出现了”Wait!wait”的反思过程,也就是顿悟了,为啥突然会出现这个玩意呢?因为你Agent的策略$\pi$实际上是在每一步的时候从一些路径中选一条走,所有它本身就是能考虑到aha-moment的情况的,只是可能一开始的概率不大,经过RL的引导之后就会更倾向于做出这样的思考过程了

but…,虽然纯粹的RL还不错,但也产生了诸如语言混乱,可读性差等问题,接下来来看deepseek-r1的设计


Deepseek-R1 全流程训练pipeline

Part1:冷启动

用一批少量的精细化标注的CoT思维推理过程的数据喂给基模进行第一轮的训练,冷启动主要目的是实现以下两点:

  • 输出格式:使模型的输出(markdown/language)这些因素更好地进行统一,防止出现一些不可读的文字内容

具体给出的格式如下所示:

Here, we define the output format as
|special_token|<reasoning_process>|special_token|<summary>, where the reasoning
process is the CoT for the query, and the summary is used to summarize the reasoning
results
  • 更好的推理潜能

Part2:reasoing RL

大规模数据喂给基模开始RL,目的是大幅提升推理能力

与zero中的RL有一点不同的地方是reward函数加入了一个语言项,也就是用于约束和规范输出语言的统一性,比如全都用中文回复这样

$$ R_{final} = R_{acc} + R_{language} $$

其余的部分与zero中的基本饿完全一致,这里不过多赘述

Part3:拒绝采样和监督微调

用第二阶段RL收敛之后得到的这个ckpt去产生优质的数据反复喂给基模,具体的产生过程就是所谓的拒绝采样,即对于同一段prompt给出若干个回答,然后用打分器/判别器选出优质的收集起来作为本阶段SFT的数据集,这个阶段包含了推理型样本和非推理型样本共计800k个,比例约为3:1

Part4:全场景微调

为了让模型回复的时候更符合场景需求和用户要求,进行全场景微调,除了进一步使用推理型数据加强推理能力,灌入大量的general-data让他的结果更符合实际场景

这一部分非常贴合于RLHF的概念,也就是人类偏好对齐,所以在奖励函数中加入了有否有帮助和安全风险的约束项,具体不展开了

以上就是R1的完整训练pipeline了!


实验部分

各种benchmark、baseline之类的跑分证明了性能强,没啥好说的


SFT or RL? An Early Investigation into Training R1-Like Reasoning Large Vision-Language Models

原文链接:SFT or RL? An Early Investigation into Training R1-LikeReasoning Large Vision-Language Models

一个很有意思的研究工作,在Deepseek-R1的成功之后,大家往往认为在大规模RL之前,高质量的SFT数据是有益的,甚至于可以成为后训练的一个范式,然而对于小模型(SLM)而言却是恰恰相反的

VLAA-Thinking Dataset

本文专门构建的一个多模态推理数据集,主要目的是服务于后面探究SFT / RL的训练效果的,其实不用太在意

Findings

  • SFT数据越多,效果越差,甚至不如裸模型!

我们在DS-R1的报告中发现了SFT能够很好地规范模型的输出格式,并给出更好的推理潜能。但是小模型呢?本身的参数量就小,SFT即使标注好了整条rollout的细节和一步一步该怎么推,SLM并不能很好的学到,一方面,模型一直在模仿固定的格式,而不是产生本质性的思考

我们好好想一下这个问题,SFT的本质是一个最大似然:
$$ \max \limits_{\theta} log p_\theta(y | x) $$

所以你SFT是在模仿人家推理,学到的只是往格式上去凑合,但中间怎么推理怎么分析的完全不管

另一个方面,SLM的参数量本身就是严重不够的,你学了新的这些模仿的内容之后,肯定要拿出一部分参数更新吧,这些参数原来可能是负责视觉辨析或者推理的,现在没法了也会导致正经推理变差

其实还有很多可能的原因,上面这两个比较主要

  • SFT数据越多,性能越差劲!

emm我认为和上面的分析差不多,简单来说就是SLM的参数量德不配位,更多的数据也全是对于长CoT的模仿,so效果只会更差


SFT Memorizes, RL Generalizes:A Comparative Study of Foundation Model Post-training

原文链接:SFT Memorizes, RL Generalizes:A Comparative Study of Foundation Model Post-training

这个工作探究了一个问题,SFT和RL作为后训练的两种范式,到底是让模型真正学会了规则迁移,还是仅仅懂了模仿

结论:纯粹的SFT让任务的成功率全都降低了,RL都提升了

实验选用的基座模型为:Llama-3.2-Vision-11B

说实话是个意料之中的结果,跟前面的工作出现的现象较为贴近,SFT由于它的最大似然的训练目的,导致了很多情况下都是teacher模型教什么它学什么,一碰到泛化的任务马上坠机,RL则是根据reward的值到逼着自己学出真东西来

有一组实验设置的特别好,是一个衍生的24点游戏,在post-training的时候采用的是正常的24点的案例作为训练数据,但是test集用了一版新的规则:JQK全都算作10点,在此情况下,两种后训练的差异就拉开了,而且很明显


关注到一位非常高能的博主和她的博客,从中学习一下 23~26(算是最近几年的 LLM / agent / RL)的一些衍化和技术

博客链接:Lil’Log

以下内容均参考了 Lil 的博客以及 GPT 回答中的拓展


Prompt Engineering

zero-shot:零样本提示,相当于直白的问 agent 问题,只有你的 prompt 作为提示

Text: i’ll bet the video game is a lot more fun than the film.
Sentiment:

与之对应的是少样本提示,也就是给出少量的几个样本作为提示,让他更好的完成任务,这就是我们所说的few-shot

Text: (lawrence bounces) all over the stage, dancing, running,sweating, mopping his face and generally displaying the wacky talent that brought him fame in the first place.
Sentiment: positive

Text: despite all evidence to the contrary, this clunker has somehow managed to pose as an actual feature movie, the kind that charges full admission and gets hyped on tv and purports to amuse small children and ostensible adults.
Sentiment: negative

Text: for the first time in years, de niro digs deep emotionally, perhaps because he’s been stirred by the powerful work of his co-stars.
Sentiment: positive

Text: i’ll bet the video game is a lot more fun than the film.
Sentiment:

few-shot 通过给定的少量样本作为提示,很好的让 agent 了解到了人类的意图偏好以及预期得到的回答的格式

but 这样做会增加上下文长度并且得到这样的优质 shot 成本并不低

21 年的一项研究表明 prompt 会在三个层次下产生偏差,以下所有例子通过情感的二分类标注举例:

  • 多数偏差:比如在 few-shot 里面给出了 4 个正面和 1 个负面的标注,agent 在接下来的输出中就会偏向于产生”正面”的输出
  • 顺序偏差:简单来说,越靠后出现的标注越容易被 agent 当做输出,比如前 4 个都是正面的标注,最后一个是负面的,那模型有可能由于最后看到的是”负面”而更倾向于输出”负面”
  • 频数偏差:在给定的 few-shot 中出险次数越多的答案越有可能最终被 agent 所采纳,感觉跟多数偏差在本上是类似的

研究者提出了一个减轻这些误差的方法,就是给原始的文本标签N/A一个基准值,然后类似于打分的方式给二分类的这两个东西打分,然后根据相对基准的偏差选出来一个最终采纳的,这里的基准相当于是一个校正的环节了

instruction prompt:在输入 prompt的时候约定好一个三元 tuple包括任务指令,输入和 gt 的输出,这种方式一般是结合着few-shot出现的,就是给几个有 gt 答案的样本和整体的任务描述最后让 agent 输出一个答案

Self-Consistency Sampling:自一致性采样,从一个模型中采样多组输出结果(需要保证temperauture > 0的前提),然后选取最好的一个答案

一个比较通用的实现的方式是多数投票

对于像是编程任务这种非常容易被验证的问题(代码扔编译器里面跑就能出结果的)

ok 这里我们稍微聊聊这个多数投票,一般而言这个指的就是一个 agent,针对于非开放性问题,采样 n 次之后计算出现频率最多的答案,作为最终输出的答案

这个方法的好处就是强制 agent 从不同的 CoT 上进行思考推导最后统计出一个最合理的答案来,缺点是贵,采样多次的成本并不小,而且一定是不能对开放性答案的问题做多数投票的

多智能体系统中的投票稍稍不太一样,对于某一个 step,可以让若干个 agent 都只输出一个 action,然后进行动作的语义归一化,再算出出现频率最高的一个并采用

CoT:大名鼎鼎的思维链,让 agent 在推理过程中有逻辑化的思维历程

这个也是分为zero-shot和few-shot的分类,非常容易想到是什么样的,这里不具体举例了

一个非常经典的 prompt 是Let's think step by step

有关 CoT 的一些 Tips & Extensions

  • 自一致性采样提高正确率

  • 集成学习随机性:在 few-shot 的例子中,我们前面提到更改这个 prompt 的输入顺序会对 agent 的判断推理之类的产生影响,所以这个方法就是给 prompt 的例子的顺序,再加上改每个 sample 里面的 CoT 的过程从而引入多样性

  • STaR(自我训练推理器):有的时候我们拿不到完整的 CoT,只有QA,那怎么扩展这些数据用于训练呢?这就是 STaR 的作用,它的工作流程是:
    拿到 QA 之后,使用 LLM 为这些 QA pairs 扩写 CoT 思维推导过程,并保留下来得到正确答案的 CoT,其余舍弃,然后把这些 CoT 当做数据扔回 agent 做后训练。重复这个过程让 agent 越来越强,有点自进化那味了

  • 复杂的 prompt 能够提高 CoT 的效用,可以认为推理的步数越多推的越好,而且研究发现使用\n作为换行符比step i 以及其他相似表述效果更好,同理,使用Question代替Q 也是有帮助的,这与 LLM 对格式的敏感性相关

  • top-k 选择,即采样出的多条 CoT 路径,选取推理步数最长的 k 条 rollout 作为可用的数据并适当的采取多数投票的方式

  • 研究发现使用这种长的 CoT rollout 会导致复杂任务的解决变强很多,但会造成简单任务的成功率下降

Self-Ask:从纯粹的对话 LLM 迈向可交互得 xx-agent 的重要一步,可以按照 react 的推理范式去理解,核心在于让模型自动学着调用外部工具去解决问题辅助推理

ToT & GoT:ToT 是将一个问题构建多条推理路径,然后从若干条路径当中去采样出合理 / 优质的一或多条,GoT 则是将多条 path 中的一些可复用的建成图里面的点,连边表示路径的推理这个关系(大概这样,但衍化出来的方法很多后面可以具体讲)

自动化 prompt 设计

往往人来设计 prompt 是十分耗费精力的,所以我们要考虑如何自动化设计 / 优化 / 迭代提示词

先来介绍一下 APE,一种优化提示词的方法

他做的事情就是从一堆的候选里面选出来最好的一个,具体方法是:比方说我一开始有三个 prompt,用他们同时在一个 benchmark 上面去测试,然后选出得到正确率最高的那一个(这里的指标有的时候是正确率,有的时候是执行准确率,根据场景不同进行切换)

接下来看 APS,主要分为以下的三个阶段:

  • 扩增,先给模型一个问题,让他自己生成多条推理链,但这些并不都是我们想要的,于是记作”伪 CoT”,得到${\rho_1,\rho_2,...,\rho_n}$
  • 剪枝,根据答案的正确性排除伪推理链,就是这些 CoT 里面得到的最终答案不正确的 CoT 被排除
  • 选择,经过前两步可能剩下 1000 个 sample,但是我们需要的可能就是只有10 个,那就需要选择,因为这个选择更类似于 Rl 里面的策略,所以也是用 RL 的思路去训练选择模型,也就是根据原始的概率分布计算总得分的期望并作为 reward 迭代优化模型(具体细节略过了)

再来看聚类采样法,这个方法旨在收集多种 LLM / agent 的推理模式,简单来说就是希望有多种错误的理解方式,我们知道相似的错误类型在 embedding 空间中趋于聚合在一起,那么可以从每一个团中选一个样例代表一种错误类型从而收集到多种。这样的好处就是你最后训练的就是都是高质量的 rollout 了


增强语言模型

这一章的内容真的是迈向 agent 时代了,开始介绍有关 retrival 的部分,也就是在一个预训练完成的模型基础上,完成实际任务需要借用外界信息检索的过程

RAG 主要聚焦于一个问题:
$$ 给定问题 q,如何利用检索到的资料 p,判断候选答案 a 可信程度 $$

RAG 检索出来的资料拼接在给 LLM 的 prompt 当中辅助找出更好的答案

一个典型的 RAG 分成两个主要部分,检索器和生成器

检索器 Retriever
负责$$ q \rightarrow p $$

也就是在给定问题的前提下决定使用什么资料作为提示

生成器 Generator

负责$$ (q,p) \rightarrow a $$

根据问题和资料生成答案

ok 接下来我们看计算答案概率的几种方式

  • RAG style,$p(a_i | q) = \sum_{i=1}^n p_{tf-idf}(p_i | q) \cdot p_{LM}(a_i | q,p_i)$
  • Noisy channel inference,$p(a_i | q) = \frac{p_{LM}(q | a_i,p_i) \cdot p_{LM}(a_i | p_i)}{p_{LM}(q | p_i)}$
  • PoE,多专家判断,$p(a|q) \propto \prod_j Expert_j(a)$

看着非常复杂,接下来补一下相关知识并解释清楚这几个计算

RAG style:看着很复杂,实际上这个公式非常好理解,对于一个问题$q$,模型输出的不同答案$a_1,a_2,...,a_n$的概率有两部分组成,检索到的文档/资料 + 根据原始问题和查询生成出来该答案的共同作用,其中$tf-idf$相似度就是两段文本之间的相似程度(具体算法比较复杂不展开了,反正这个意思就这样)。接下来由于 LLM 输出的不确定性,即使在确定了查询的资料之后还有一个输出概率问题,也就是公式后半部分

Noisy channel inference:可以将其理解成一种反向验证的方法,这个东西起源于通信理论:

假设原始的信息是$a$,但经过一个带有噪声的信道之后观察到的是$q$

现在我们只能看到$q$,如何反推回这个$a$

在形式上采用:
$$ p(a | q) \propto p(q | a)p(a) $$

迁移到 RAG 里面,实际上就是加上了一个查询出来的资料$p$,也就是:
$$ p(a | p, q) \propto p(q | a, p)p(a | p) $$

然后加上分母上的归一化因子,算出来一个分数再去选最高的

PoE:多专家评判,也就是对于同一个答案$a$,经由$n$各专家的打分综合选出来一个:
$$ E_1(a),E_2(a),...,E_n(a) $$
每一个专家的打分最后去取总乘积(实际为了避免数值溢出,我们采取的是全部取对数累加的策略),为什么不能简单的加和平均呢?如果前$n-1$个专家都非常认同,但有一个专家强烈拒绝,那你做求和平均是看不出来的,而乘积就很明显,就是这个原因。在后续应用中,拓展出来了专家加权的衍化,其实差不多就是每个专家的分数加了一个权重$\lambda_i$

在后续的研究中证明了另外两件事,一是三种打分机制的效果为:
$$ PoE > Noisy\;channel > RAG-style $$

此外,相比之下$p(q | a,p)$和$p(a|p,q)$是”informative”的,就是说把这两个概率作为打分依据会让模型更容易判断

另外一个现象是内外部资料的冲突,由于模型训练结束后会冻结参数,相当于某些知识这个 LLM 是内部知道的,但是外部知识库给的是新的,这样会导致产生矛盾,最终导致回答出一个贼离谱的神秘答案

此外,模型的内部检索也能提高其能力,这种情况的限制就是无法处理过时信息的时限,它能提高效果是类似于知识的提炼总结,让模型更关注相关领域的知识罢了,这个理解起来还是蛮简单的

Programming Language

调用程序化的语言(python…)辅助任务,尤其是复杂的计算的场景中

我们先看一个简单的例子,对比 CoT 和 PoT,看看程序化语言如何辅助任务完成的

在上面的例子当中,能发现用 Python 脚本计算斐波那契数列的值远远强于 CoT 一点一点推,他的问题在于某一步出现一丁点错都会由于错误累计无穷的方法

另一种方法PALPoT较为相似,不展开探讨了

External APIs

现代 Tool Use 的雏形,依旧为迈向通用 agent 做出的贡献

TALM是通过调用外部 API 工具增强语言模型的方法,在此前的基础纯语言 LLM 的基础上,通过输出格式中加入与外部 API 调用相关的部分让模型学会什么时候什么情况要自己找什么 API,以下是一个例子:

显然的这里面加入了一些新的字段,跟 API 调用相关:

  • |tool-call
  • tool input text
  • |result
    类似于 ds-r1 那里面训练出来\<think>的推理格式,至少我觉得有点像

TALM采用了一种自博弈(self-play)的方法构建数据集,可以理解成一个loose-RL,它的核心是每次给现在的模型加一些 API 调用,然后检查效果有没有变好

在工程落实层面,通过设计好的 prompt 以及 few-shot 高质量标注的样本先训出来基本的 tool-use 能力,接下来让这个模型在普通标注的数据集上面进行随机采样,依据打分微调策略,进行迭代

ps:这个过程非常像我们之前提到的STaR和 ds-r1 里面的拒绝采样

Toolformer是更进一步的工具调用的学习方法,它旨在让模型学会四件事:调用什么工具、什么时候调用、传什么参数、拿到结果如何辅助生成

与 TALM 相比,Toolformer 的监督信号是预测下一个 token 的 loss,也就是看是否更容易生成出来后面的内容

由于他是纯文本训练的(训练数据都是普通文本),所以要把 API 调用进行格式化:
$$ e(c,r) = <API>a_c(i_c) \rightarrow r</API> $$
里面是 API 的名称和参数,最终的格式就是类似[Calculator(400/1400)->0.29]这样

另一个精华的点在于这个监督信号,具体来说,他要看未来 token 的 loss,假设 API 调用插入在第$i$个位置,那么定义:
$$ L_i(z) = - \sum_{j=i}^{n}w_{j-i}log_{PM}(x_j | z,x_{1:j-1}) $$
这里:

  • $x_j$:原文本中第$j$个 token
  • $z$:额外的工具信息
  • $w_{j-i}$:位置权重

这个损失诠释了插入公式后,从插入位置到结束的这一段预测未来 token 的偏差

!完结,从一个只会对话的 LLM 逐步迈向通用的 agent,这是 3 年之前的研究,到现在许多直觉和建模上的东西还是可以借鉴,非常好的文章!


LLM Powered Autonomous Agents

来系统的再学一遍 Agent!虽然之前零零碎碎看了不少了

Overview

一个现代的 LLM-driven 的 agent 分为以下的三个主要部分,也是三种关键核心能力:

  • planning:把大、复杂任务拆解成若干小、简单任务,便于 agent 解决;反思改进,从过去的经验历史中吸取并自我进化
  • memory:短期记忆(prompt engineering),实际上所有上下文问题都是短期的;长期记忆,无限的 retain and recall,通常用外部向量储存与检索
  • tool use:通过外部 API 补齐当前无法做到的事情

Planning

CoT,ToT 前面都有讲过,这里跳过了

LLM + P:只让 LLM 负责理解自然语言和构造形式化问题,所有的规划部分交给一个成熟的 Planner

PDDL:规划领域专用语言,即描述”可规划问题”所需属性的一种 language

整个流程可以用下面的流程图来概括:
$$ NL \xrightarrow{LLM} PDDL \xrightarrow{Planner} Plan \xrightarrow{LLM} NL $$

Self-Reflection

自进化的鼻祖是大名鼎鼎的ReAct模型,对于其推理过程已非常了解,下面再贴个图

CoH:事后反馈链,它所希望的是训练模型怎么从初始回答一步一步走到人类倾向出现的回答的,流程如下:

对于一组数据,定义如下:
$$ D_h = \{ (x,y_i,z_i,r_i)\}_{i=1}^{n} $$
其中参数的含义是:

  • $x$:输入的 prompt
  • $y_i$:第$i$次采样得到的 answer
  • $z_i$:对于第$i$次打分结果的解释
  • $r_i$:第$i$次回答的打分

得到$n$个采样结果之后,按照打分结果进行一个由大到小的排序,也就是:
$$ r_n > r_{n-1} > ... > r_1 $$

重新组织$D = \{ (x,y_1,z_1,y_2,z_2,...,y_n,z_n) \}$,即按照打分结果从小到大的顺序重新组织了$(y,z)$这个 tuple,这样做的目的是什么呢?我们会发现这样调整顺序之后形成了一条链,并且越往后走越是人所希望出现的回答,那顺着这个链一步一步推会比从头开始一步生成想要的结果更容易、更自然,纳闷只需要训练模型推这个链的能力即可

训练的目标就是预测$y_n$,在给定一个条件$C = (x,z_1,y_1,...,z_n)$的前提下去看这个$y_n$,损失函数可记作:
$$ L_{CoH} = -log \sum p_{\theta}(y_n | C) $$

同时为了防止过拟合,一般训练的时候会加入正则化项,具体的做法是加入在普通文本/数据上面的交叉熵,防止模型学出来一个只会$CoH$的分布
$$ L_{regular} = -log \sum p_{\theta}(w | w_{< t}) $$

算法蒸馏(AD):前面我们讲到了 CoH,AD 同样遵循着学习改善过程的核心思路,将任务从同一静态问题多次采样转向了同一条 rollout 反复采样来造数据

假设对于一个任务分布:
$$ M \sim p(M) $$

先从这个任务分布中采样大量任务:
$$ M_1,M_2,...,M_n \sim p_{train}(M) $$

在每个任务上都运行 RL 算法,记$\phi_i^{(0)} \sim p(\phi_0)$,这里$\phi$为源 agent 的状态参数

整个 AD 的 pipeline 分成以下几个 step:
$$ \tau_i^{(1)} = \{o_1^{(1)},a_1^{(1)},r_1^{(1)},...,o_n^{(1)},a_n^{(1)},r_n^{(1)} \} \\ \phi_i^{(1)} = U(\phi_i^{(0)},\tau_i^{(1)}) $$

简单来讲就是每一步在上一个参数状态下完成这个任务,并将这次的 rollout 的结果作为参数回传更新,重复这个流程,同时保证跨 episode 学习历史

Tool Use

承接上一篇 blog 有关 tool use 的部分(TALM & toolformer),本章更为系统

MRKL:神经符号结合的 Agent 架构,神经方法擅长理解自然语言,符号方法擅长精密的计算,二者相结合。笼统来讲,一个任务交由 agent 执行之后由神经方法进行感知和理解,将需要推理和计算的部分给符号方法去执行

在结构上,MRKL 由路由器作为对问题/任务初步判断和转发路由的模块,专家模块特定的完成某一部分任务,结果整合模块来整合结果

(神经符号学习是一个挺新挺大的方向,这里先不展开了)

Hugging-GPT:让 GPT(或其他 LLM 作为大脑理解规划调度),让 Hugging Face 上面的其他模型作为各种专家帮着干活,大概的过程就是让主 LLM 先规划,把总任务拆分成若干个小任务,根据每个子任务的要求去选择适合的专家模型,执行,将结果交付 LLM 整合分析最后生成相应用户的结果

API-Bank;关于 API 调用的 benchmark,不太关心,略过

Generative Agents Simulation:一个超级有意思的话题!我决定之后单开一篇玩这个,经典的社会学模拟实验,感觉这个 topic 适合玩出很多花来


Extrinsic Hallucinations in LLMs

在这篇文章中,我们将 LLM 的幻觉定义为”模型输出为捏造,缺乏上下文或世界知识支撑”

幻觉主要分成内在和外在两种,内在幻觉主要是由于上下文信息缺失/错误导致的,外在幻觉主要是由于 LLM 的预训练环节中数据是有限的且冻结参数之后没法更新新的世界知识,那我们需要保障 LLM 输出的事实能够被外部世界知识所验证,同样重要的是 LLM 要在不知道的时候说”不”

What causes hallucinations

这一小节我们来看幻觉产生的原因

Pre-training:在预训练环节,LLM 会从互联网上海量的爬取数据并使用,难以避免爬出来过时错误缺失的信息,而最大对数似然的方式会让这些”负收益”数据污染模型影响其认知

Fine-tuning:后训练的两种经典方式:SFT 和 RLHF,往往会在这个阶段引入新知识,研究表明:(1)在后训练中新引入的知识,相比于预训练中灌入过的知识,模型难学也学的慢 (2)即使模型真的学到了新知识,模型产生幻觉的风险更大了

接下来看一个很有启发的探究,给定 closed-book dataset(闭卷数据集测试),其中$D = \{ (q,a)\}$,然后我们定义模型$M$在输出解码温度为$T$的前提下,并且多次不同的 few-shot 随机构成提问,对于问题$q$生成的答案$a$的正确率$P_{Correct} (q,a,M,T)$,并用四种标签划定对知识的掌握程度

先来对这几种定义做一个直观的解释:

  • HighlyKnown:贪心解码 100% 得到正确答案,可以认为是完全掌握了这个知识
  • MaybeKnown:贪心解码有时能得到正确答案
  • WeaklyKnown:贪心解码永远得不到正解,T > 0 情况下有概率”抽出”正确答案
  • Unknown:无论贪心或 T > 0 的随机采样都永远得不到正解

(在以上的生成答案过程中,贪心解码只选择 next-token 概率最大的answer,温度采样 $T > 0$会在所有可能的 next-token 中随机选取)

ok 来看研究人员的发现,在微调中,他们使用的数据集由一半的Known和一半的Unknown组成,并分别记录随着轮数增多二者的准确率变化

这个表说明了几件事:

(1)Unknown类型的 QA 拟合速度上明显慢于Known类型,证明了强化已知知识比学完全不会的更容易

(2)独立的测试中,在中途到达了峰值随之下降,在Unknown上面过拟合,这一点主要是由于新旧知识的参数是共享的,在学习新/旧知识上面作用于参数的梯度下降方面,二者会造成梯度冲突从而导致效果持续走弱

(3)MaybeKnown样本带来的效果好于HighlyKnown样本,很好理解,学本来就会的东西肯定不如学那些模糊的知识有用

Hallucination Detection

在生成答案之后,如何判断是否是幻觉呢?

Retrieval-Augmented Evaluation

把模型生成的内容拿去直接查 wiki 之类的资料,外部资料核验,它的核心流程就是从回答中提取事实,接着检索证据,判断证据是否支持/反驳/不足

下面是几种经典的方法,在此不一一展开了,只对我觉得比较好的聊一聊:

  • FactualityPrompt
  • FActScore

这个还不错,它的做法是把一个长回答拆解成多个atomic facts,并进行逐条的验证,对于一个回答$a$,记$FActScore$的值为正确的 assert / 总 assert,相当于这个指标是准确率指标,那么对于纯文本的问答有下面几种计算方式:直接问模型(很神秘,不知道这么做真有用吗)、检索外部资料再让模型判断(类似 RAG)、算平均似然是否符合分布(但这样也会有些知识错误)。对于更多模态的任务和 QA,应该有更贴合的标准和计算方式,后续我们会探究!

  • SAFE:搜索增强事实评估器,它的目标是自动评测 LLM 生成的长回答中有多少能得到公开资料认定

给定用户提示$x$和模型生成长回答$y$,$SAFE$大致执行以下四个流程:
$$ y \xrightarrow{事实分解} F \xrightarrow{相关性过滤} F_{rel}\xrightarrow{搜索、推理} \{ v_i \} \xrightarrow{聚合} Score $$

原子事实一般要满足:单一assert,自包含和可验证三个角度特征,单一断言指的是最好只包含一个主要关系$(subject,relation,object)$,自包含就是别出现he这种指代不明的词,可验证就是尽可能客观不含主观因素(比如 xx 好这种)

接下来进行相关性过滤,也就是把和这个问题无关的原子回答剔除掉,只保留和问题相关的回答,过滤之后对于每一条原子事实$f_i$,构造搜索查询:
$$ q_i^{(1)} = QueryGen(f_i) $$

但往往一轮搜索是不够的,那就需要多轮搜索,如果搜出来的证据不足以支撑判断,那么将之前搜出来的证据连同源事实一并给 agent 继续搜,即:
$$ q_i^{(t+1)} = \pi_{search}(f_i, E_i^{(1:t)}) $$
直到搜出来足够的证据$E_i$,给出最终判断$supported / unsupported$,给一个0/1 分数,最后用来算平均正确率评估

在实际使用途中,由于难以并发而且 LLM 调用次数多,所有一般拿来离线构造数据使用

  • SelfGPT:依旧是构造离线数据的方法,核心是对于一个 QA 采样多次回答并计算回答之间的相似度相关性,打分

Calibration of Unknown Knowledge

对”未知知识”的校准,即模型能不能知道对某个 QA 他的知识库是明确不知道的,并且能说出来而不是瞎编


Give it time, let it pass.