何时检索,何时生成?Self-DC:自我分治解决复合问题
现有的工作非常关注大模型本身的知识边界,以达成对于大模型known和unknown的问题能够进行不同的处理。简单来说,有四大类主要的问题
- Single known: 简单的通过大模型内部的知识即可解决,比如常见的generate-then-read方法
- Single unknown: 需要调用外部工具如搜索引擎等获取外部知识进行解决,比如retrieve-then-read方法
- Compositional known: 需要进行复杂推理,比如compositional reasoning将问题进行分解
- Compositional unknown: 这个问题是其中最为复杂的,因为一个compositional unknown 问题包括其他所有可能性,比如一个compositional known和single unknown的结合等。
对于一个复合问题,我们什么时候利用外部检索,什么时候促使大模型产生已知的知识,以回答当前的问题?
为了解决这个问题,可以不加区分地使用外部检索方法,也就是朴素RAG,也可以首先评估关于该问题的大型语言模的确定性或不确定性,随后根据评估调用生成-读取或检索-读取。
例如,《Can llms express their uncertainty? an empirical evaluation of confi-dence elicitation in llm》,这个工作列举了多种方式,基于语言的Verbalized,基于一致性的Consistency-based,以及它们的混合方法Hybrid。
这两种方法都有自己的局限性,例如,简单地对每个问题调用外部检索并不能保证更好的性能,而且会浪费大量已知知识浪费,而且在存在迭代检索的情况下,也会带来严重的效率问题。此外,将问题分为已知和未知的二元对立过于简化了问题的复杂性,在某些情况下并不可行以及效果并不佳。
例如,如图1所示,一个组合未知问题由已知和未知子问题组成。因此,它将退化为简单地自动调用每个问题的检索,因为未知的组成仍然是llm的未知问题。
“先检索后读取”和“再生成后读取”是开放域问答中处理未知和已知问题的两种典型解决方案,前者检索需要的外部知识,后者提示大语言模型生成编码在参数中的内部已知知识,但也存在一些由已知或未知的子问题组成的未知问题。
此外,简单的二元分类(已知或未知)变得次优且效率低下,因为它会对每个组成未知问题过多地调用外部检索。
为此,《Self-DC: When to retrieve and When to generate? Self Divide-and-Conquer for Compositional Unknown Questions》提出了第一个组合未知问答数据集(CuQA),并引入了一个自分而治(Self-dc)框架,使llm能够自适应地按需调用不同的方法,从而提高了性能和效率。
论文题目:
Self-DC: When to retrieve and When to generate? Self Divide-and-Conquer for Compositional Unknown Questions
论文链接:
一、主要实现思路
Self-DC主要采用的是自我分而治之的思路,如图2所示:
一般来说,给定一个问题,首先得到大模型对该问题的置信度分数,然后可以相应地选择处理当前问题的方式。具体地,其将置信度评分分为 [0,α-β],(α-β,α+β),[α+β,1] 三个范围,其中 α 和 β 是超参数。因此,当置信度分数落在左侧 ([0,α−β]) 或右侧 ([α+β,1]) 时,可以分别调用检索-读取或生成-读取来回答。
此外,当遇到不确定或令人困惑的问题时,将问题分解成几个子问题,旨在减少不确定性。为了保证迭代不溢出,设置了几个终止条件:1)子问题数为1,即可能是单个问题;2)迭代深度的次数小于一个预定义的 t ,在这种情况下,简单地将当前子问题视为未知问题,然后调用retrieve-then-read。然后,将所有子问题的答案结合起来,以提示大模型获得原始问题的最终答案。
对应的伪代码如下:
二、关于回复置信度的估计
使用两种类型的方法来提示LLM本身获得置信度分数来回答问题。
一种是基于语言化的方法verbalize-based,直接指示llm在问题的答案之后输出从0到100的置信水平,置信水平表示确定性的程度,然后将置信度分数重新映射到区间[0,1]。提示如下:
另一种是基于概率probability-based的方法,还利用概率信息来计算置信分数。首先使用几个单词提示llm生成答案,然后得到生成内容中第 i 个token的概率 pi ,根据如下公式获取序列中概率的平均值作为置信度分数。
这个思路很有意思,启发来自于 《A stitch in time saves nine: Detecting and mitigating hallucinations of llms by validating low-confidence generation.》,这个工作也是一个幻觉缓解框架,其思想在于:给定输入,迭代地从模型中生成句子,并主动检测和减轻幻觉。在检测阶段,首先识别重要概念,计算模型在其上的不确定性,然后通过检索相关知识验证不确定性概念的正确性。在缓解阶段,使用检索到的知识作为证据来修复幻觉句子。最后,将修复后的句子附加到输入(以及之前生成的句子)上,并继续生成下一个句子。
其中的不确定估计是我们在这里要讨论的重点,该工作认为,GPT-3等模型也在其预测中提供logit输出值,因此可以采用这些logit输出值来检测幻觉。这个logit输出值可以通过对每个标记位置的logit值应用softmax函数来获得这些概率。例如,记为 p1, p2, p3,…,pn 分别表示 n 个token的位置。
可以取平均值(Average of Token Probabilities)
概率的归一化积(Normalized Product of Token Probabilities)
取概率的最小值作为分数(Minimum of Token Probabilities)
为此,还加入 α 和 β 两个参数来控制不确定性的范围以提高Self-DC的鲁棒性和灵活度。
三、针对问题的不同操作
根据不同的置信度,精心设计了几个功能来完成组合性问答任务,包括几个模块
先生成后阅读generate-then-read: 首先提示大模型从维基百科生成背景文档来回答给定的问题,然后要求大模型通过引用生成的段落来回答问题。对应的prompt如下:
先检索后阅读retrieve-then-read: 在第一步使用检索器检索外部知识,然后要求LLM根据检索到的文章来回答问题,对应的prompt如下:
问题分解decompose: 提示大模型将总体问题分解为几个较小的子问题,这些子问题的答案共同有助于得出原始总体问题的答案,类似于Press等人(2023)和Xu等人(2023),这种用法很常见,其实就是query-expansion的处理。
这块对应的prompt如下:
典型的分析工作,可以参考 《Measuring and Narrowing the Compositionality Gap in Language Models》,如下所示,通过提示大模型,针对某个问题进行分解,可以得到一些细分问题,从而提升性能。
迭代问答combine-sub-qas:分解后,调用main函数进入下一个迭代,为了得到每个子问题的答案,可以将所有子问题的答案合并得到原始问题的答案,对因的prompt如下:
四、总结
RAG个大系统,就像当时KG一样,都说要替代掉,但其本身是个大系统,依旧是要往前走的,要有工程观和落地观念。
本文主要关注RAG的一个工作,也重新温习了使用大模型对自身生成内容置信度估计的方案,与之前介绍内容不同的是,除了使用verblized based方案之外,还可以利用token的预测概率,如均值等,这些都是很好玩的思路。
此外,self-DC这套方案,前置要求大模型的置信准确性,也融合了问题扩展等思路,但也存在一些问题,例如,简单问题和难问题之间存在着很大的差距,如该工作所说的, 对大模型的依赖性太强,当使用verblized based方法时,在gpt-3.5-turbo-1106上,发现超过65%的情况下置信度得分为0,大约20%的情况下置信度得分超过0.9。但当使用gpt-3.5-turbo-instruct,趋势相反,给出0.9更高的频率(≈45%),也就是说,大模型似乎要么高估了正确性,要么直接承认不确定性并拒绝回答。此外,细粒度置信分数(即0.82,0.61)相当罕见,使得β的细粒度选择毫无意义。
另一方面,当使用probb方法时,有更多的细粒度置信信号,并且大多数落在<0.5部分(≈90%)。结果表明,gpt-3.5-turbo-1106在不确定性估计方面优于gpt-3.5-turbo-instruct,prob方法优于动词方法,获得了更准确的置信度分数,分解次数受置信度分数的影响很大,这可能又会落入到一个阈值的调节怪圈里。
所以说,在NLP领域,并不存在一个放之四海而皆准的防范,都是需要特事特办,都是一堆补丁,即便有了长文本,也有一堆RAG的补丁要做。
Illustration From IconScout By Delesign Graphics