动手点关注
干货不迷路
本文旨在让无大模型开发背景的工程师或者技术爱好者无痛理解大语言模型应用开发的理论和主流工具,因此会先从与LLM应用开发相关的基础概念谈起,并不刻意追求极致的严谨和完备,而是从直觉和本质入手,结合笔者调研整理及消化理解,帮助大家能够更容易的理解LLM技术全貌,大家可以基于本文衍生展开,结合自己感兴趣的领域深入研究。若有不准确或者错误的地方也希望大家能够留言指正。
本文体系完整,内容丰富,由于内容比较多,分多次连载 。
第一部分 基础概念
1.机器学习场景类别
2.机器学习类型(LLM相关)
3.深度学习的兴起
4.基础模型
第二部分 应用挑战
1.问题定义与基本思路
2.基本流程与相关技术
1)Tokenization与Embbeding
2)向量数据库
3)finetune(微调)
4)模型部署与推理
5)prompt
6)编排与集成
7)预训练
第三部分 场景案例
常用参考
2.基本流程与相关技术
4)Prompt
在前面的内容里,我们提到过要使用模型完成下游任务,有两种方式,一种是通过收集标记样本针对不同的任务进行指令微调,另一种方式便是大模型特有的,可以通过将指令以对话的方式提供给模型,期待模型能够给我们返回预期的结果。相较于前者,后者具有更高的灵活性,使用成本也更低,因此,这一方式成了如今大语言模型区别于传统NLP模型的重要标志。
在本章你将学习到:
1)Prompt,In-Context-Learning,Prompt engineering等相关概念
2)如何写好一个Prompt及相关Prompt调试工具
3)基于Prompt催生的一些新的编程范式
prompt enginering
前面看到了简单传入一些文本就能够操纵大模型完成原来需要finetune才能做到的任务,让大家感受到了“智能”。这也吸引了越来越多的研究者及开发者开始探索通过Prompt 来提升大模型的效果,这也催生了一门新的工程科学——prompt enginering(提示工程)。随着研究不断深入,发现了越来越多的Prompt编写技巧,大模型的潜力也得到越来越深入的挖掘。由于大模型本身运行机理的黑盒性, prompt enginering是一门实证科学,目标是如何利用不同的提示策略来优化 LLM 性能,其研究过程便是假设,验证,再假设,再验证的不断迭代过程。 由于它能够很低成本的提升大模型的效果,被誉为“大模型的魔法杖”,它就和传统模型开发中的特征工程一样被赋予了一个非常高的位置。
下面介绍一些常见的高阶Prompt enginering的理论技术,它为我们后续人工利用大模型解决问题或者基于其构建系统架构如RAG,Agent提供了理论基础。
Chain of Thought(COT)
从刚才的例子看到,我们操纵大模型完成任务,只需要告诉它要完成的问题,并可根据情况提供例子就可以,但是对于一些复杂任务,可能需要多步才能完成的任务,比如一些逻辑推理问题,那么,借鉴人类解决这类问题的方法,让大模型不要急于一次性的完成整个任务,而是一步步的通过分解,推理来完成任务, 这就是Chain of Thought(思维链),简称CO T,它能够使大型语言模型解决算术推理(arithmetic Arithmetic)、常识推理(commonsense Reasoning)和符号推理( symbolic reasoning )等类型的复杂任务。
事实上,教大模型“思考”非常有效,通过这样的方法能够显著提升大模型的推理能力,而推理本身也是衡量模型是否具有智能涌现的重要标准。
https://browse.arxiv.org/pdf /2201.11903.pdf
根据笔者的验证,当下大模型不断进化,这类问题chatGPT、claud和文心一言均可以在不使用COT的情况下,甚至无需few-shot正确回答。
对于大模型来讲,研究者发现,触发COT能力,不一定非要提供推理步骤示例,zero-shot同样管用。最简单的做法是,增加prompt片段“Let’s think step by step” 就能够强制大模型生成推理步骤。
Large Language Models are Zero-Shot Reasoners(https://browse.arxiv.org/pdf/2205.11916.pdf)
类似的语句还有:
Let’s think about this logically.
Let’s solve this problem by splitting it into steps.
Let’s think like a detective step by step.
Before we dive into the answer.
在Zero-Shot-CoT领域,最近几天(10.3)刚刚有一个新的研究《 Large Language Models as Analogical Reasoners 》 提出,通过 类比 推理 提示 (Analogical Prompting)可以 让 大模型自己 生成 相似问题 做 为例 子 ,从而再 根据例子 步骤形成思维链 来解决新问题 。
相较于传统做法,这类做法不仅不用开发者自己想例子,而且提升了问题的泛化性,大模型可以根据问题不同生成不同的例子。更进一步,为了避免大模型过分依赖这些具体示例,缺乏变通,导致其在新问题时无法有好的表现。为了解决这个问题,我们让LLM自己生成一些泛化性的要点,论文称作“知识”来辅助生成示例,实际上这一过程类似于人类解决问题的,总结提炼要点,参考同类问题,再解决新问题的一般性方式。而大模型就像是在训练过程中已经学习了足够多的世界知识,通过这样的诱导,可以帮助大模型发挥自己的能力。
自生成示例
自生成示例+知识
该方法在效果上,相较于传统做法来讲,也有明显的提升,在研究中也发现,让大模型生成示例并不是越多越好,数量为3或者5是一个最佳的数量。
https://browse.arxiv.org/pdf/2310.01714.pdf
Self-consistency COT
相较于普通COT,由于大模型生成的随机性本质,并不能保证每一次生成都是正确的,如何提高其鲁棒性,提升其准确率,成了一个大问题。比如:文心一言在回答刚才题目时,第一次回答结果就是错误的。
但多生成了几次,文心一言就回答出了正确答案。基于这样的思路,研究者提出了自一致COT的概念, 利用"自一致性"(self-consistency)的解码策略,以取代在思维链提示中使用的贪婪解码策略,也就是说让大模型通过多种方式去生产答案,最后根据多次输出进行加权投票的方式选择一种最靠谱的答案。
https://browse.arxiv.org/pdf/2203.11171.pdf
其实,人类解答问题的时候也用到这样的方法,就是用多种方法解答问题,进而互相印证其结果的可靠性。与其他解码方法相比,自一致性避免了困扰贪婪解码的重复性和局部最优性,同时降低了单采样生成的随机性,显著的提升了效果。
显然,它也存在一个明显的缺陷就是太慢且耗费资源,因此,在具体应用时,需要结合实际需要灵活选择。
Least-to-Most
相较于Self-Consistency简单多次生成,然后选择最自洽的结果来讲,Least-to-Most更为精细。它在解决复杂问题时,先引导模型把问题拆分成子问题;然后再让大模型逐一回答子问题,并把子问题的回答作为下一个问题回答的上文,直到给出最终答案。可以看出,Least-to-Most是一种循序渐进式的引导大模型解决问题的方式。
下面是一个实际的例子:
CUSTOMER INQUIRY:
I just bought a T-shirt from your Arnold collection on March 1st.
I saw that it was on discount, so bought a shirt that was originally $30,
and got 40% off. I saw that you have a new discount for shirts at 50%.
I'm wondering if I can return the shirt and have enough store credit to
buy two of your shirts?
INSTRUCTIONS:
You are a customer service agent tasked with kindly responding to
customer inquiries. Returns are allowed within 30 days.
Today's date is March 29th. There is currently a 50% discount on all
shirts. Shirt prices range from $18-$100 at your store. Do not make up any
information about discount policies.
Determine if the customer is within the 30-day return window.
未使用Least-To-Most方式,text-danvnci-003回答错误。
采用该方法,首先诱导提出子问题:
然后让大模型依次回答这些问题:
可以看到,大模型在引导下,正确的回答了问题:
Yes, the customer can purchase two shirts at the current 50% discount
rate with their store credit, as $18 of store credit will cover the cost
of two shirts at $36.
与Least-To-Most类似,对于一个大模型没有在训练时直接见到的问题,通过诱导大模型以自我提问的问题,将问题分解为更小的后续问题,而这些问题可能在训练数据中见到过,这样就可以通过自问自答的方式,最终获得正确答案。
在此基础上,更进一步,对于没有见过的子问题还可以借助外部检索,帮助大模型最终完成问题解答。
简单讲,既然自己不知道写什么样的prompt有利于解决问题,那么让大模型帮你写提示,然后使用大模型提供的prompt,再去操纵大模型,从而获得效果改进,这就是元提示。
一个实际的为例:
完整例子见:https://chat.openai.com/share/77c59aeb-a2d6-4df8-abf6-42c8d19aba3d
通过知识生成来增强prompt,提升大模型的效果。其基本思路就是先基于问题让大模型给出问题相关的知识,再将知识整合到问题中,从而让大模型给予更细致有针对性的回答。它在一些特定领域的任务中有效果,比如问题本身比较笼统,这个时候就可以通过这种方法增强。
https://browse.arxiv.org/pdf/2110.08387.pdf
一个简单的示例,让大模型推荐一份健康、方便制作的早餐食谱:
1)创建一个提示模板,要求模型生成有关健康早餐选项的知识:
Prompt template:
Generate knowledge about healthy, easy-to-make breakfast recipes that are high in protein and low in sugar.
2)该模型可能会提供有关不同成分和配方的信息,例如:
Healthy breakfast options that are high in protein and low in sugar include Greek yogurt with berries, oatmeal with nuts and seeds, and avocado toast with eggs. These recipes are easy to make and require minimal cooking.
3)根据生成的知识,创建一个新的prompt,其中包含大模型提供的信息,并要求基于此提供食谱。
Based on the knowledge that Greek yogurt with berries, oatmeal with nuts and seeds, and avocado toast with eggs are healthy, high-protein, low-sugar breakfast options, provide a detailed recipe for making oatmeal with nuts and seeds."
4)如此,大模型将会提供一个相对更为细致,有针对性的回答。
迭代型提示,是指和大模型进行交互时,不要把它看作是独立的过程,而是将前一次的回答作为上下文提供给大模型,这样的方式可以有效的提高模型信息的挖掘能力,并消除一些无关的幻觉。上图所示,在上下文的帮助下,大模型顺利的回答出结果,而标准的prompt可能无法回答或者产生幻觉,回答错误。
TOT(Tree of thoughts)
TOT是在 "思维链 "方法的基础上的扩展,并能够探索连贯的子步骤(“思维”),作为解决问题的中间步骤。简单讲,COT是和大模型的一次交互,但复杂问题,并不能一次搞定,那么,可以诱导大模型将复杂问题拆分为多层的树结构,这样每一步选择,都可以以树的模式(广度优先搜索(BFS)和深度优先搜索(DFS))动态选择最合适的路径,它 允许 大模型通过考虑多种不同的推理路径和自我评估选择来决定下一步行动方案,并在必要时进行前瞻或回溯以做出全局选择,从而执行深思熟虑的决策。
https://arxiv.org/pdf/2305.08291.pdf
其基本过程是首先,系统会将一个问题分解,并生成一个潜在推理“思维”候选者的列表。然后,对这些思维进行评估,系统会衡量每个想法产生所需解决方案的可能性,最后方案进行排序。
基本流程参考这个视频:
对应的prompt参考:
Step1 :
Prompt: I have a problem related to [describe your problem area]. Could you brainstorm three distinct solutions? Please consider a variety of factors such as [Your perfect factors]
Step 2:
Prompt: For each of the three proposed solutions, evaluate their potential. Consider their pros and cons, initial effort needed, implementation difficulty, potential challenges, and the expected outcomes. Assign a probability of success and a confidence level to each option based on these factors
Step 3:
Prompt: For each solution, deepen the thought process. Generate potential scenarios, strategies for implementation, any necessary partnerships or resources, and how potential obstacles might be overcome. Also, consider any potential unexpected outcomes and how they might be handled.
Step 4:
Prompt: Based on the evaluations and scenarios, rank the solutions in order of promise. Provide a justification for each ranking and offer any final thoughts or considerations for each solution
如果将其过程实现,基本实现架构为:
一个执行的例子:
结果表明,ToT 能显著提高语言模型在需要非繁琐规划或搜索的新任务中解决问题的能力,如:24点游戏、数独等。
github地址:
https://github.com/princeton-nlp/tree-of-thought-llm
https://github.com/jieyilong/tree-of-thought-puzzle-solver
GOT( Graph-of-Thoughts )
由于 ToT 方法为思维过程强加了严格的树结构,所以会极大限制 prompt 的推理能力,而GOT则更进一步,将整个结构变成了DAG图,实际上,人类在进行思考时,不会像 CoT 那样仅遵循一条思维链,也不是像 ToT 那样尝试多种不同途径,而是会形成一个更加复杂的思维网。GoT的新颖之处在于它能够对这些想法进行转换,进一步完善推理过程。
https://arxiv.org/pdf/2308.09687v2.pdf
相较于TOT,主要的变化为:
- 聚合,即将几个想法融合成一个统一的想法;
- 精化,对单个思想进行连续迭代,以提高其精度;
- 生成,有利于从现有思想中产生新的思想。
这种转换强调推理路线的融合,相对于之前的CoT或ToT模型,提供了更复杂的问题支持。
此外,GoT引入了一个评估维度-思维容量(the volume of a thought),可用于评估 prompt 设计策略。研究者表示,使用这一指标的目标是更好地理解 prompt 设计方案之间的差异。
对于一个给定的思维 v,v 的容量是指 LLM 思维的数量,用户可以基于此使用有向边得到 v。 直观上说,这些就是有望对 v 做出贡献的所有 LLM 思维。
作者通过研究表明,通过整合聚合等思维变换技术,GoT 能让思维容量比其它方案显著更大。另一方面,GoT 是唯一能做到低延迟 log_k N 和高容量 N 的方案。GoT 之所以能做到这一点,是因为其利用了思维聚合,使其可从图分解中任何其它中间思维得到最终思维。
在具体技术官方实现上,由于GOT的更强泛化能力,因此,其本身也能支持COT或TOT方法。
from examples.sorting.sorting_032 import SortingPrompter, SortingParser, utils
from graph_of_thoughts import controller, operations
# Problem input
to_be_sorted = "[0, 2, 6, 3, 8, 7, 1, 1, 6, 7, 7, 7, 7, 9, 3, 0, 1, 7, 9, 1, 3, 5, 1, 3, 6, 4, 5, 4, 7, 3, 5, 7]"
# Create the Graph of Operations
gop = operations.GraphOfOperations()
gop.append_operation(operations.Generate())
gop.append_operation(operations.Score(scoring_function=utils.num_errors))
gop.append_operation(operations.GroundTruth(utils.test_sorting))
# Configure the Language Model (Assumes config.json is in the current directory with OpenAI API key)
lm = controller.ChatGPT("config.json", model_name="chatgpt")
# Create the Controller
ctrl = controller.Controller(
lm,
gop,
SortingPrompter(),
SortingParser(),
# The following dictionary is used to configure the initial thought state
{
"original": to_be_sorted,
"current": "",
"method": "cot"
}
)
# Run the Controller and generate the output graph
ctrl.run()
ctrl.output_graph("output_cot.json")
github实现:https://github.com/spcl/graph-of-thoughts
Algorithm-of-Thoughts(AoT)
前面了解到TOT和GOT的基本过程,一个很直观的感觉就是会和大模型产生多次的交互,从而导致高昂的算力成本,整体的交互逻辑也比较复杂。那么,怎么样尽可能减少TOT等对大模型查询交互,甚至把迭代的过程直接放在大模型内部完成。而AOT就是旨在解决这一问题而出现。它是由弗吉尼亚 理工大学和微软今年8月刚刚提出的,研究者探究了 LLM 能否实现类似的对想法的分层探索,通过参考之前的中间步骤来筛除不可行的选项 —— 所有这些都在 LLM 的生成周 期内完成。利用 LLM 的递归能力,研究者构建了一种人类 - 算法混合方法。其实现方式是通过使用算法示例(从最初的候选项到经过验证的解决方案)。 与早期的单一查询方法(COT)和最近的多次查询策略(TOT/GOT)相比,该技术表现出更好的性能。在不增加查询请求数量的情况下,通过利用LLM的递归能力,提高其思路探索能力。与其他方法相比,AoT方法具有更高的效率和性能,比TOT高出近10%。
https://browse.arxiv.org/pdf/2308.10379.pdf
官方提供了实现,下面是一个使用的示例:
!pip install aot-x
from aot.main import AoT
task = """
Use numbers and basic arithmetic operations (+ - * /) to obtain 24. When
considering the next steps, do not choose operations that will result in a
negative or fractional number. In order to help with the calculations, the
numbers in the parenthesis represent the numbers that are left after the
operations and they are in descending order.
Another thing we do is when there are only two numbers left in the parenthesis, we
check whether we can arrive at 24 only by using basic arithmetic operations
(+ - * /). Some examples regarding this idea:
(21 2) no
since 21 + 2 = 23, 21 - 2 = 19, 21 * 2 = 42, 21 / 2 = 10.5, none of which is equal
to 24.
(30 6) 30 - 6 = 24 yes
(8 3) 8 * 3 = 24 yes
(12 8) no
(48 2) 48 / 2 = 24 yes
Most importantly, do not give up, all the numbers that will be given has indeed a
solution.
14 8 8 2
OBJECTIVE
#########
5 10 5 2
"""
dfs = AoT(
num_thoughts=2,
max_steps=10,
value_threshold=1,
initial_prompt=task,
openai_api_key="ENETER IN YOUR API KEY"
)
result = dfs.solve()
print(result)
github地址:https://github.com/kyegomez/Algorithm-Of-Thoughts
从论文报告看,其查询大模型的次数有了明显的下降,效果仅比TOT略低,可能是因为模型的回溯能力未能得到充分的激活,而 相比之下,ToT具有利用外部内存进行回溯的优势。
Program-aided Language Model (PAL)
大模型通常具备一般的任务分解和推理能力,但是它在一些数学计算和逻辑执行上不擅长,一个经典的例子就是,早期大模型对于加减乘除这些小学生的问题都难以稳定准确的回答。而相反,普通的程序却善于逻辑执行和计算,于是就有了一个思路,就是让大模型根据问题生成解决该问题的程序,然后,将程序放在Python等程序解释器上运行,从而产生实际的结果。没错,这就是后来Open Code Interpreter的基本思想。
https://browse.arxiv.org/pdf/2211.10435.pdf
在此技术的支持下,在数理计算上,其性能有了显著提升。
不过从目前大模型的发展情况来看,普通的数学应用题,大模型在不需要外部支持的情况下也能算对,而PAL的使用场景变为复杂的数据分析和工具,API接口调用等场景。
Automatic Prompt Engineer(APE)
既然人写不好prompt也不知道什么样的prompt更好,那么就让模型来写,然后模型来评价。基于这个思路,提出了Automatic Prompt Engineer(APE),这是一个用于自动指令生成和选择的框架。指令生成问题被构建为自然语言合成问题,使用LLMs作为黑盒优化问题的解决方案来生成和搜索候选解。 其过程为, 首先 大模型生成后选的 指令,然后把这些指令提交给大模型打分,然后打分完成后,选择打分高的作为最后的指令。
从效果上看,APE相较于人类设计的prompt来看有比较高的提升,然而,它带来的是大量的算力消耗,其对应的就是成本,因此在使用这种方法时需要注意。
示例程序: https://colab.research.google.com/drive/1oL1CcvzRybAbmeqs--2csaIvSOpjH072?usp=sharing
Github 地址: https://github.com/keirp/automatic\_prompt\_engineer
ART(Automatic Reasoning and Tool-use)
使用 LLM 完成任务时,交替运用 CoT 提示和工具已经被证明是一种即强大又稳健的方法。在PAL中,大模型通过生成程序经过外部执行后,再交给大模型来执行,然而生成的程序的稳定性以及复杂问题的工具使用方法对于大模型来讲并不完全理解,而ART(Automatic Reasoning and Tool-use)可以认为是PAL的增强,这类方法通常需要针对特定任务手写示范供大模型参考,还需要精心编写交替使用生成模型和工具的脚本,进而提高准确性。其工作过程如下:
- 接到一个新任务的时候,从任务库中选择多步推理和使用工具的示范。
- 在测试中,调用外部工具时,先暂停生成,将工具输出整合后继续接着生成。
ART 引导模型总结示范,将新任务进行拆分并在恰当的地方使用工具。ART 采用的是零样本形式。ART 还可以手动扩展,只要简单地更新任务和工具库就可以修正推理步骤中的错误或是添加新的工具。这个过程如下:
https://browse.arxiv.org/pdf/2303.09014.pdf(opens in a new tab)
在 BigBench 和 MMLU 基准测试中,ART 在未见任务上的表现大大超过了少样本提示和自动 CoT;配合人类反馈后,其表现超过了手写的 CoT 提示。 下面这张表格展示了 ART 在 BigBench 和 MMLU 任务上的表现:
RAG(Retrieval Augmented Generation)
RAG,即Retrieval Augmented Generation,检索增强生成,现已成为最为流行的LLM框架模式之一,早在2020年5月就由meta和伦敦学院及纽约大学的研究者在论文《 Augmented Generation for Knowledge-Intensive NLP Tasks 》提出。其核心思路就是通过检索的方式,将问题相关的背景知识作为上下文一并传给大模型,这样能够有效的提供模型的准确性以及减轻幻觉。
其架构的工作流程比较简单清晰,如下图:
整体分为5步,第一步是用户向chatbot(即LLM应用)提出问题,第二步基于问题在数据库中检索相关问题,第三步,将检索结果top n的数据传给chatbot,chatbot基于用户问题以及检索到的相关信息进行合并形成最终的prompt,第四步,将prompt提交给大模型,第五步,大模型产生输出返回给chatbot,进而返回给用户。
采用RAG架构的LLM应用,除了能够破解prompt learning受限context window的问题,它还有以下好处:
1)它能够基于这种模式,尽量减少大模型幻觉带来的问题。
2)它减少了为了微调而准备问答对(带标记的样本数据),大大减少了复杂度。
3)prompt的构造过程,给了我们很大的操作空间,对于我们后续干预模型效果,完成特定业务需求提供了必要的手段。
ReAct, 由 Shunyu Yao 等人 2022年10月提出,用以解决语言模型语言理解和交互式决策制定等任务中推理(例如思维链提示)和行动(例如行动计划生成)能力结合的问题,现在已经是Agent流行的框架模式。在前面的模式里,虽然大模型具备了任务分解和推理以及使用外部工具的能力,但是它无法有机的将其整合成为一个闭环,类似于PDCA这样的管控模式。而ReAct 框架使用 LLM 以交错的方式生成推理轨迹和特定任务行动,使模型能够诱导、跟踪和更新行动计划,并处理异常情况。通过将模型的功能与外部资源(如知识库或环境)相结合,ReAct 使模型能够与外部工具(文档、搜索、数据库、代码执行等)交互并收集信息,从而做出更可靠、更真实的响应,它是一个多次迭代执行的过程。这种方法使模型能够利用其在自然语言处理和推理方面的优势,同时还能结合外部资源来提高特定任务的准确性和性能。在两个交互式决策基准(ALFWorld 和 WebShop)上,ReAct 的绝对成功率分别为 34% 和 10%,超过了模仿和强化学习方法,同时只需一到两个上下文示例的提示。
https://browse.arxiv.org/pdf/2210.03629.pdf
这一模式的具体实现和应用将会在后面的架构部分详细讨论。
这是当前AGent架构中另一个重要的模式,在前面提到的Re-Act的Agent架构里,其整个过程倾向于“走一步看一步”,虽然相较于原来的走一步增加了观察和调整,但是缺少对问题整体的规划,对于复杂问题来讲,这样的模式很容易越走越偏,从而难以解决问题。而Plan-And-Solve就旨在解决这一份问题,将问题分成两部分:
-
Plan(计划模块):该模块能够制定一个计划将整个任务分解成较小的子任务,然后根据计划执行这些子任务。在论文团队的实验中,他们简单地将Action Agent 中的“让模型逐步思考”替换为“让模型先理解问题并制定解决方案的计划。然后,让模型按步骤执行计划并解决问题”,通过这种方式,论文团队想要解决Missing-step Error 和 Semantic Misunderstanding Error 带来的中间推理步骤遗漏问题
-
Solve(解决模块): 该模块主要用来解决 Calculation Error 和 Misunderstanding Error 带来的计算结果偏误问题,解决方式是优化向大语言模型输入的Prompt,在Prompt中加入包括让大语言模型“提取相关变量及其对应的数字”和“计算中间结果”的等的说明。
这里plan专注做任务规划和拆解,而solve专注具体的实现,这和人类完成大的项目的模式基本相同。
https://browse.arxiv.org/pdf/2305.04091.pdf
更进一步,还可以在prompt上增加细节的instructions,被称作Plan-And-Solve Prompting accompanied by more detailed instructions,PS+,如图,这样可以进一步的提升执行的准确率。
当下,prompt enginering领域非常热门,每天都会有新的思路和方法以提高模型的性能。这里无法一一列举 ,但通过上面的介绍,已经大体理解,整个prompt enginering就是一个不断探索LLM能力,尝试验证的过程。
为什么Prompt如此重要
我们通过大篇幅介绍prompt概念及相关技术,其中核心原因就是它非常重要。但为什么呢?一个核心观点就是它改变了原有使用模型的方式(先根据具体任务finetune模型再进行使用),通过自然语言的方式就能够操纵大模型来完成各种各样的任务,这是对原因模型应用方式的颠覆。其相较于finetune也存在着以下优势:
1)更轻量,从模型的知识角度讲,一个模型的知识来自于它预训练和微调过程,但是由于这两个训练成本比较大,很难做到实时训练,这样就导致了模型知识的过时,比如ChatGPT只知道2021年9月以前的事实,而对于prompt learning来讲,它可以把知识实时传入给模型,这几乎零成本。另一方面,模型微调是需要大量的标记数据,而这样的标记问答对,本身就是很大的负担,相较于精心构造few-shot来讲,更为笨重。
2)更灵活,对于模型应对不同任务来讲,finetune的做法就是每个任务训练一个模型,这就导致了它是否不灵活,虽然从后期改进上有类似adpater机制,但总的来讲,和简单修改prompt来讲,完全不是一个量级。
3)更可控,对于大模型来讲,如何让它理解行业知识,其中做法就是把知识以问答对的方式finetune到模型中,然而这样的做法虽然可以改变模型的概率分布,提升zero-shot的效果,但是并不能直接约束模型是否使用这些知识,也很难很精细的操作。而另一种方式是,将知识以上下文的形式放置到prompt中,只让大模型基于prompt提供的背景发挥,某种意义上它更加可控,也发挥了各自的优势。
4)更经济,这一点很好理解,finetune的成本是远高于推理成本的,加上finetune在流程和技术层面的潜在要求,也更增加了使用的成本。
可以看出,prompt learning将会是未来大模型使用的首选方式,基于它也衍生了众多的大模型应用的架构,可以说prompt是大模型的灵魂,一切应用都是围绕它来衍生构建的。
prompt learning的一些问题
不过,虽然prompt有诸多的优势,但它本身也存在着诸多的缺陷,一方面是结构性的问题,另一方面是发展阶段的问题。
1)prompt受到context window的约束。
受限于其模型结构本身原因, 这一长度很难快速提高,因为它的增长带来的计算量(FLOPS)是呈O(n^2)增长的,具体推算逻辑可以查看:一文探秘LLM应用开发(12)-模型部署与推理(大模型相关参数计算及性能分析)。因此,它对算力的消耗是巨大的。目前GPT提供的context大小在8k左右,最大32K。
不过值得openAI的对手,新发布的claud 2支持100k的context window,可以直接上传一个万字长文供它分析。
不过,当下这一问题在领域内有所突破,由麻省理工学院、Meta AI以及卡内基梅隆大学研究人员联手,开发了让语言模型能够处理无限长度流媒体输入的框架StreamingLLM。该方法的工作原理是识别并保存模型固有的“注意力池”(Attention Sinks)锚定其推理的初始Token。结合最近Token的滚动缓存,StreamingLLM的推理速度提高了22倍,而不需要牺牲任何的准确性。
https://browse.arxiv.org/pdf/2309.17453.pdf
经研究团队实验证实,StreamingLLM能够让Llama 2、MPT、Falcon和Pythia可靠地处理高达400万token的文本。而且使用专为注意力下沉设计的token进行预训练时,更可以进一步提高模型的流媒体运算性能。重要的是,由于StreamingLLM让语言模型预训练窗口大小,与实际文本生增长度脱钩,在流媒体应用的语言模型部署方面提供了更多可能性。
2)prompt的技巧性、繁琐性、稳定性问题
经过刚才的介绍,我们了解到了不同的prompt在激发大模型潜在能力上存在着重大差异。而每一次都需要精心的去组织和验证,并且防止可能的不预期失败。这一类问题,预期会随着大模型技术发展会逐步解决,但当下来看,对于用户以及开发者都是一个很大的挑战,如何能够更好的解决这类问题呢?
目前面向用户侧,解决方案是社区提供的prompt模版及写作技巧,而面向开发者是由prompt开发工具及编排框架,如langchain,llamaindex等,通过对于前面提到的一些prompt enginering范式的封装,让普通开发者无需关注具体的prompt写法,而由这些工具内置,以langchain为例,它通过chain,agent等概念将常见的模式封装在这些对象中,普通用户学习langchain用法就能够比较好的使用到前面提到的一些prompt enginering技术。在社区中,针对于稳定性也提供了一些框架的支持,如
Guidance,typechat等。
3)Prompt的安全及权限隔离
在目前大模型技术水平下,大模型的使用安全成了一个阻碍大模型真实场景落地的重要问题。由于prompt是自然文本,构造非常容易,但其基于prompt实际大模型的运作原理又不是很清楚,这就使得,如何保证大模型不被利用和攻击成了一个难题。
当下,提示攻击成了一个非常令模型服务者头疼的问题。在笔者前面的文章中也提到过类似情况,如:继“奶奶漏洞”之后,ChatGPT又有了新“福利”。提示攻击通过精心设计的提示,欺骗大模型执行非预期的操作。提示攻击主要分为三种类型:提示注入、提示泄露和越狱。
- 提示注入:是将恶意或非预期内容添加到提示中,以劫持语言模型的输出。提示泄露和越狱实际上是这种攻击的子集;
- 提示泄露:是从LLM的响应中提取敏感或保密信息;
- 越狱:是绕过安全和审查功能。
如何防御提示攻击,有很多可能的做法,如一些关键词的屏蔽和替换,对提示词进行封装改写,如随机序列封装,三明治防御,xml封装防御等。 在前面 文章里也介绍了,业内也有防止提示攻击的中间层框架,如 Rebuff ,可以直接选择使用。
而关于模型权限,由于大模型无法直接处理权限层面问题,需要在外部增加权限粒度的管控,在RAG里就可以通过上下文的方式,将用户有权限的内容提供给大模型,而不需要大模型将其潜在的数据输出,减少可能的敏感数据泄漏。除此之外,在数据源层面做到硬隔离及后续处理上进行二次检查都能一定程度解决数据权限访问的问题。在笔者这篇文章中有相关介绍:引入元数据(metadata)提升RAG架构下LLM应用的效果和管控精度
小结
在本节中,大篇幅的介绍了prompt的概念、当下prompt enginering的相关技术、重要性及潜在问题。在后面的小节中,将从用户使用角度和开发角度来探讨如何更好的利用prompt enginering的相关理论写好用好大模型。
未完待续。。。
合集目录:
3)微调
4)模型部署与推理
一文探秘LLM应用开发(8)-模型部署与推理(DEMO验证)
一文探秘LLM应用开发(9)-模型部署与推理(模型适配优化之GPU面面观-1)
一文探秘LLM应用开发(10)-模型部署与推理(模型适配优化之GPU面面观-2)
一文探秘LLM应用开发(11)-模型部署与推理(模型大小与推理性能的关系)
一文探秘LLM应用开发(12)-模型部署与推理(大模型相关参数计算及性能分析)
一文探秘LLM应用开发(15)-模型部署与推理(框架工具-推理执行引擎(HF pipeline))
一文探秘LLM应用开发(16)-模型部署与推理(框架工具-TGI,vLLM,TensorRT-LLM,DS-MII)
一文探秘LLM应用开发(17)-模型部署与推理(框架工具-ggml、mlc-llm、ollama)
一文探秘LLM应用开发(18)-模型部署与推理(框架工具-Triton Server、RayLLM、OpenLLM)
一文探秘LLM应用开发(19)-模型部署与推理(FastChat、OpenChat、HuggingChat、GPT4ALL)
5)Prompt