深入思考LLM的”思维链提示“技巧,以及它在自动翻译中的应用
ray306 opened this issue · 0 comments
语言模型的推理能力
语言模型(Language Model; LM)已经成了我们的问答工具。但如果训练语言模型的语料库中没有直接包含我们的问题和它的答案,语言模型其实很难将问题直接转化为一个答案,因为这实际需要一个复杂的推理过程,而语言模型的本质是复制和预测,而不是推理。
虽然语言模型不擅长复杂推理,但我们可以把复杂推理分解成许多简单的推理。而这些简单的推理大概率是语言模型在训练过程中已经在语料库中看到过的,所以语言模型常常能够完成简单的推理。把这些简单推理一步步组合,就能完成复杂推理。
顺便一提,模型不是真的在做数学化的推理,只是在提取自己的记忆,但只要完成任务就好。而且,人脑也常常这样。
思维链提示
思维链(Chain of Thought; CoT)技巧就是在提示词(prompt)中主动要求语言模型把一个需要复杂推理的问题分解成很多中间步骤,然后对每个步骤分别回答,最后再结合这些步骤的回答就可以获得最终答案。
例子(摘录自https://zhuanlan.zhihu.com/p/629087587 ):
深入分析思维链提示为什么有效
相对于直接问答复杂问题,把复杂的问题分解称一连串简单的问题本身是个更简单的任务,回答简单的问题更不必说。这个解决方案的本质就是要让任务变得简单、具体。
什么样的任务是简单、具体的?对于语言模型来说,就是它见过的任务,也就是它的训练语料库里已经有了任务介绍和解决方案的任务。
实际任务和训练过程的记忆越相似,语言模型需要改动、推理的部分越少,它的准确率和效率就越高。
总结一下,思维链提示技巧的本质就是把困难任务的那个未知的解决方案转换为已有记忆的组合。这样一来,应用思维链提示的关键就浮现了:怎样做这个转换?
拟合和泛化
- Any sufficiently advanced technology is indistinguishable from magic (任何足够先进的技术都与魔法没有什么区别). ---Arthur C. Clarke
- 在足够规模的数据上的成功拟合与泛化没有什么区别 --- 沃·兹基硕德
上面那个转换有两个要点:
- “已有记忆”要多。模型的训练数据要足够多,涵盖尽量多的简单任务。不过我们作为用户,没资本自己炼出更大的模型,只能用脚投票那个尽量大的模型。
- “任务分解”要准确。模型仍然是在套用之前的关于“分解任务”的记忆,但这一步套用往往变量很多,模板太抽象。这就导致模型自己找出的那个分解逻辑未必合理,分解的粒度也未必足够细。这时候我们就要想办法协助它做分解(这也是下面要讨论的点)。
怎样做任务分解?
零样本思维链(上面例子里的第3个)
最简单粗暴的办法就是用零样本思维链,直接在问题后加上“let's think step by step”。这句prompt可以说是pua了语言模型:模型本来想直接上个差不多的答案糊弄下,但这句话一出,模型只好把问题分步骤考虑。
技术上说,这个prompt的有效性也是和生成式语言模型的根本原理息息相关。
生成式语言模型的根本原理就是根据前文生成下一个词,然后新词加入前文,重复上一步....。这个过程其实是非常短视的,所以在没有这个prompt的情况下,语言模型容易生成一些局部看似合理、放一起看就是胡言乱语的文字。
反之,“let's think step by step”会迫使语言模型紧接着它生成一句描述第一步的文字。然后,前文有了第一步,下文自然有第二步、第三步...,直到某一步显示问题解决。这个技巧其实是超级巧妙地利用了语言模型的短视特性,把短视的生成变成了实质上长久规划的生成。
上下文学习(上面例子里的第2个)
零样本思维链胜在简单通用(我分析ChatGPT应该是在后台自动添加了这个技巧或它的变种),但如果语言模型自己找不出合适的任务分解方案,零样本思维链也要抓瞎。这时候更适合明确给出例子的上下文学习(In-context learning)。
上下文学习就是直接给语言模型看个模板,让模型照这个套路回答。所以这个技巧避免了语言模型在自己的数据库里找不到合适的模板,最后就拿个似是而非的模板瞎扯的尴尬。
这个技巧的缺点很明显,就是要自己写context(给的模板),模板写错了反而有副作用;但优点也很明显,在你很清楚步骤是什么、又能写清楚的情况下,可以严格控制模型的输出(思考)过程。
结构化提示
如果说零样本思维链是让语言模型自己分解任务,上下文学习是给语言模型看几个分解任务的例子后让它模仿,那结构化提示就是直接告诉语言模型怎样分解任务。
比如给我一个健康的一周饮食计划。
这个提示的结构化版本或许是这样的(由GPT生成):
制定一周的健康饮食计划,遵循以下步骤:
1. **营养目标**:确保每日包含蛋白质、碳水化合物、健康脂肪。
2. **日常菜单**:
- 早餐:高蛋白,高纤维。
- 午餐:轻盈,营养均衡。
- 晚餐:低脂,多样化。
- 零食:两种健康选项。
3. **烹饪简介**:简述每餐建议的烹饪方法。
4. **食材清单**:列出每日所需食材。
可以看出,结构化提示中,输入给模型的信息不仅仅是简单的问题或者命令,而是以一种特定的、有组织的格式来表达。这种方法有助于模型理解复杂的指令, 减少误解,同时也使得模型的回应更加贴合用户的实际需求。
同时,结构化提示也可以被看作思维链。如果我们精心设计、明确描述任务的步骤,就可以控制住各种子任务的完成次序,从而妥善处理复杂任务的每个环节,最终得到更好的输出。
下面这几个具体流程可以说明合理安排任务步骤的优势:
-
由总到分(再到总):
- 要求语言模型先对问题提供初步的整体视角或答案,随后一步步完善细节。最后还可以再让语言模型对之前的细节做一次总结归纳。(这个过程接近一般的写作过程,也和ChatGPT的回答风格类似。)
- (由GPT生成的)例子:
对于气候变化,首先给出一个概览,然后深入讨论其几个关键影响领域。最后,综合这些领域,总结气候变化的整体意义。
-
由浅入深:
- 要求语言模型先从问题中最容易回答或最基本的部分开始,然后逐步深入,最终接触到问题的本质。
- (由GPT生成的)例子:
描述区块链技术,从其最基础的概念开始,逐步探讨其在不同领域的应用,最终讨论其可能带来的长期影响。
-
对比论证:
- 要求语言模型自己描述问题的正反两面,或其它不同的视角,然后通过对比不同视角,评估应采用哪种立场或保持中立。
- (由GPT生成的)例子:
分析可再生能源和化石燃料,从各自的基本特性开始,然后比较它们在不同方面的优缺点,最后得出关于未来能源选择的综合见解。
这几个例子的本质都是迫使语言模型逐步探索问题,有助于让模型逐渐构建起对复杂问题的全面、深入的理解。
角色扮演
结构化提示往往结合了让语言模型角色扮演的指令。比如说告诉语言模型”你是一个医生“,可以让语言模型在后面的输出中以专业的口吻、格式回答问题,避免它逃避问题。用专业口吻回答问题也可以约束它的输出内容,迫使它调取记忆中更多的专业知识。就像是从一个博而不精的科普者变成了严肃认真的专家,细节更充沛、推理更严格、避免为了提高可读性牺牲一些正确性。
...TODO