memo-llm应用开发极简入门
这篇书评可能有关键情节透露
大模型应用开发极简入门:基于GPT-4和ChatGPT
奥利维耶·卡埃朗 [法]玛丽-艾丽斯·布莱特49个笔记
1.1 LLM概述
- 这场革命的核心支柱是注意力机制,这是一个简单而又强大的机制。模型不再将文本序列中的所有词视为同等重要,而是在任务的每个步骤中关注最相关的词。交叉注意力和自注意力是基于注意力机制的两个架构模块,它们经常出现在LLM中。Transformer架构广泛使用了交叉注意力模块和自注意力模块。 交叉注意力有助于模型确定输入文本的不同部分与输出文本中下一个词的相关性。它就像一盏聚光灯,照亮输入文本中的词或短语,并突出显示预测下一个词所需的相关信息,同时忽略不重要的细节。
- 自注意力机制是指模型能够关注其输入文本的不同部分。具体到NLP领域,自注意力机制使模型能够评估句子中的每个词相比于其他词的重要性。这使得模型能够更好地理解各词之间的关系,并根据输入文本中的多个词构建新概念。
- Transformer架构由来自谷歌公司的Ashish Vaswani等人在2017年的论文“Attention Is All You Need”中提出,最初用于序列到序列的任务,如机器翻译任务。标准的Transformer架构有两个主要组件:编码器和解码器,两者都十分依赖注意力机制。编码器的任务是处理输入文本,识别有价值的特征,并生成有意义的文本表示,称为嵌入(embedding)。解码器使用这个嵌入来生成一个输出,比如翻译结果或摘要文本。这个输出有效地解释了编码信息。
- 生成式预训练Transformer(Generative Pre-trained Transformer,GPT)是一类基于Transformer架构的模型,专门利用原始架构中的解码器部分。在GPT中,不存在编码器,因此无须通过交叉注意力机制来整合编码器产生的嵌入。也就是说,GPT仅依赖解码器内部的自注意力机制来生成上下文感知的表示和预测结果。
- 理解标记与词长的一条经验法则是,对于英语文本,100个标记大约等于75个单词。
1.2 GPT模型简史:从GPT-1到GPT-4
- 2018年年中,就在Transformer架构诞生一年后,OpenAI发表了一篇题为“Improving Language Understanding by Generative Pre-Training”的论文,作者是Alec Radford等人。这篇论文介绍了GPT,也被称为GPT-1。 在GPT-1出现之前,构建高性能NLP神经网络的常用方法是利用监督学习。这种学习技术使用大量的手动标记数据。以情感分析任务为例,目标是对给定的文本进行分类,判断其情感是积极的还是消极的。一种常见的策略是收集数千个手动标记的文本示例来构建有效的分类模型。
- GPT-1的作者提出了一种新的学习过程,其中引入了无监督的预训练步骤。这个预训练步骤不需要标记数据。相反,他们训练模型来预测下一个标记。由于采用了可以并行化的Transformer架构,预训练步骤是在大量数据上进行的。对于预训练,GPT-1模型使用了BookCorpus数据集。该数据集包含约11000本未出版图书的文本。BookCorpus最初由Yukun Zhu等人在2015年的论文“Aligning Books and Movies: Towards Story-like Visual Explanations by Watching Movies and Reading Books”中给出,并通过多伦多大学的网页提供。然而,原始数据集的正式版本如今已不能公开访问。
- GPT-1是小模型,它无法在不经过微调的情况下执行复杂任务。因此,人们将微调作为第二个监督学习步骤,让模型在一小部分手动标记的数据上进行微调,从而适应特定的目标任务。比如,在情感分析等分类任务中,可能需要在一小部分手动标记的文本示例上重新训练模型,以使其达到不错的准确度。
- 2019年初,OpenAI提出了GPT-2。这是GPT-1的一个扩展版本,其参数量和训练数据集的规模大约是GPT-1的10倍。这个新版本的参数量为15亿,训练文本为40 GB。2019年11月,OpenAI发布了完整版的GPT-2模型。
- 2020年6月,OpenAI发布了GPT-3。GPT-2和GPT-3之间的主要区别在于模型的大小和用于训练的数据量。GPT-3比GPT-2大得多,它有1750亿个参数,这使其能够捕捉更复杂的模式。此外,GPT-3是在更广泛的数据集上进行训练的。这包括Common Crawl(它就像互联网档案馆,其中包含来自数十亿个网页的文本)和维基百科。这个训练数据集包括来自网站、书籍和文章的内容,使得GPT-3能够更深入地理解语言和上下文。
- GPT-3取消了微调步骤,而这在之前的GPT模型中是必需的。
- 2021年,OpenAI发布了GPT-3模型的新版本,并取名为InstructGPT。与原始的GPT-3基础模型不同,InstructGPT模型通过强化学习和人类反馈进行优化。这意味着InstructGPT模型利用反馈来学习和不断改进。这使得模型能够从人类指令中学习,同时使其真实性更大、伤害性更小。
- 在题为“Training Language Models to Follow Instructions with Human Feedback”的论文中,OpenAI的欧阳龙等人解释了InstructGPT是如何构建的。 从GPT-3模型到InstructGPT模型的训练过程主要有两个阶段:监督微调(supervised fine-tuning,SFT)和通过人类反馈进行强化学习(reinforcement learning from human feedback,RLHF)。每个阶段都会针对前一阶段的结果进行微调。也就是说,SFT阶段接收GPT-3模型并返回一个新模型。RLHF阶段接收该模型并返回InstructGPT版本。
2.3 在OpenAI Playground中使用GPT模型
- OpenAI Playground是一个基于Web的平台。你可以使用它直接测试OpenAI提供的语言模型,而无须编写代码。在OpenAI Playground上,你可以编写提示词,选择模型,并轻松查看模型生成的输出。要测试OpenAI提供的各种LLM在特定任务上的表现,OpenAI Playground是绝佳的途径。
2.9 小结(含速查清单)
- 以下是向GPT-3.5 Turbo发送输入消息时可参考的速查清单。 01.安装openai依赖项。 pip install openai 02.将API密钥设置为环境变量。 export OPENAI_API_KEY=sk-(...) 03.在Python中,导入openai。 import openai 04.调用openai.ChatCompletion端点。 response = openai.ChatCompletion.create( model="gpt-3.5-turbo", messages=[{"role": "user", "content": "Your Input Here"}],) 05.获取答案。 print(response['choices'][0]['message']['content'])
3.4 示例项目
- 有两种方法可用于将ChatGPT的功能与你自己的数据集集成。 微调 针对特定的数据集重新训练现有模型。 少样本学习 向提示词中添加示例。
4.1 提示工程
- 很多任务可以通过提示词来完成,包括摘要、文本分类、情感分析和问题回答。在所有这些任务中,我们通常需要在提示词中定义三大要素:角色、上下文和任务
- 为了找到可改进之处,你可以请GPT-4提些意见。在下面的示例中,我们修改提示词,不再要求模型回答问题,而是指示它以增强补全效果为目标来向我们提出关于上下文的问题。 使用以下提示词: prompt = """Context: I do 2 hours of sport a day. I am vegetarian and I don'tlike green vegetables. I am very careful to eat healthily.Task: Give me a suggestion for a main course for today's lunch? Donot perform the requested task! Instead, can you ask me questionsabout the context so that when I answer, you can perform therequested task more efficiently?"""chat_completion(prompt) GPT-4向我们提出以下问题: Sure, I have a few questions to help me suggest a suitable maincourse for you:1. What type of sport do you do, and do you have any specific nutritional requirements related to it?2. Are there any other vegetables or ingredients that you particularly enjoy or dislike?3. Do you prefer a hot or cold meal for lunch?4. Are you open to trying new recipes or do you prefer sticking to familiar dishes?
- 任务定义了你对GPT-4模型的用法,并且应该明确且具体。你应该提供足够的任务信息,并在提示词中使用合适的短语来引导模型给出你所期望的结果。 在前面的例子中,任务是让模型为午餐推荐一道主菜。我们可以为该任务添加细节,以说明我们想要的内容。在本例中,我们要求模型添加一张表格,列出每种食材所需的克数: prompt = """Context: I do 2 hours of sport a day. I am vegetarian, and I don'tlike green vegetables. I am conscientious about eating healthily.Task: Give me a suggestion for a main course for today's lunch. Withthis suggestion, I also want a table with two columns where each rowcontains an ingredient from the main course. The first column of thetable is the name of the ingredient. The second column of the tableis the number of grams of that ingredient needed for one person. Donot give the recipe for preparing the main course."""chat_completion(prompt)
- Python转自然语言 用自然语言解释一段Python代码。 提示词示例如下。 # Python 3def hello(x):print('hello '+str(x))# Explanation of what the code does 计算时间复杂度 计算一个函数的时间复杂度。 提示词示例如下。 # Python 3def hello(x, n): for i in range(n): print('hello '+str(x))# The time complexity of this function is 修复Python bug 修复含有bug的Python代码。 提示词示例如下。 ### Buggy Pythondef hello(x, n): for i in rang(n): print('hello '+str(x))### Fixed Python
- 在撰写提示词时,影响模型的最后一种方式是赋予其一个角色。当然,角色和上下文可以独立使用,但同时使用可以加强对模型输出的控制。在以下示例中,我们赋予模型运动营养专家的角色: prompt = """Role: You are a nutritionist designing healthy diets for high-performance athletes. You take into account the nutrition needed for a good recovery.Context: I do 2 hours of sport a day. I am vegetarian, and I don't like green vegetables. I am conscientious about eating healthily.Task: Based on your expertise defined in your role, give me a suggestion for a main course for today's lunch. With this suggestion, I also want a table with two columns where each row in the table contains an ingredient from the main course. The first column of the table is the name of the ingredient. The second column of the table is the number of grams of that ingredient needed for one person. Do not give the recipe for preparing the main course."""chat_completion(prompt)
- 在提示词的末尾添加“让我们逐步思考”这样的话,已被证明可以使模型解决更复杂的推理问题。这种技术称为零样本思维链策略(zero-shot-CoT strategy),由Takeshi Kojima等人在2022年发表的论文“Large Language Models are Zero-Shot Reasoners”中提出。 思维链是指使用提示词鼓励模型逐步模仿推理的技术。零样本这个术语意味着模型不依赖于特定任务的示例来执行这种推理,它已经准备好根据其一般的训练结果来处理新任务。与我们稍后就会讨论的少样本学习等技术不同,零样本学习试图在不需要特定任务示例的情况下进行泛化。
- 在提示词末尾添加逐步思考的字样(比如示例中的“Let's think step by step”)
- 少样本学习(few-shot learning)是由Tom B. Brown等人在论文“Language Models Are Few-Shot Learners”中提出的,它指的是LLM仅通过提示词中的几个示例就能进行概括并给出有价值的结果。在使用少样本学习技巧时,你可以给模型提供几个示例
- 指导LLM的另一种方法是单样本学习(one-shot learning)。顾名思义,在单样本学习中,我们只提供一个示例来帮助模型执行任务。尽管这种方法提供的指导比少样本学习要少,但对于简单的任务或LLM已经具备丰富背景知识的主题,它可能很有效。单样本学习的优点是更简单、生成速度更快、计算成本更低(因而API使用成本更低)。然而,对于复杂的任务或需要更深入理解所需结果的情况,少样本学习的效果可能更好。
- 本节将介绍更多技巧,不妨在为GPT模型编写提示词时酌情使用。 01.指示模型提出更多问题 在提示词的末尾,询问模型是否理解问题并指示模型提出更多问题。如果你正在构建基于聊天机器人的解决方案,那么这样做非常有效。举例来说,你可以在提示词的末尾添加如下文本: 你清楚地理解我的请求了吗?如果没有,请问我关于上下文的问题。这样一来,当我回答时,你就能够更高效地执行我所请求的任务。 02.格式化输出 有时,你可能希望在一个较长的过程中使用LLM的输出。在这种情况下,输出格式很重要。如果你想要一个JSON输出,那么模型往往会在JSON代码块之前和之后写入输出。如果你在提示词中说输出必须被json.loads接受,那么模型给出的结果可能更好。这种技巧适用于许多场景。 比如,使用此脚本: prompt = """Give a JSON output with 5 names of animals. The output must beaccepted by json.loads."""chat_completion(prompt, model='gpt-4')
- 03.重复指示 经验表明,重复指示会取得良好的效果,尤其是当提示词很长时。基本思路是,在提示词中多次添加相同的指令,但每次采用不同的表述方式。
- 04.使用负面提示 在文本生成场景中,负面提示是指通过指定不希望在输出中看到的内容来引导模型。负面提示作为约束或指南,用于滤除某些类型的回答。对于复杂任务,这种技巧特别有用:当以不同的表述方式多次重复指令时,模型往往能够更准确地遵循指令。
- 我们在第3章的项目3中使用了负面提示: Extract the keywords from the following question: {user_question}.Do not answer anything else, only the keywords. 没有这个提示词的话,模型往往不会遵循指示。
- 05.添加长度限制 限制长度通常是不错的做法。如果你只希望模型回答1个词或者10个句子,那么不妨将要求添加到提示词中。这就是我们在第3章的项目1中所做的:我们指示模型用100个单词生成一篇内容翔实的新闻稿。在项目4中,我们所用的提示词也含有长度限制:“如果你能回答问题,回答ANSWER;如果你需要更多信息,回答MORE;如果你无法回答,回答OTHER。只回答一个词。”如果没有最后一句话,模型往往会生成句子,而不会遵循指示。
4.2 微调
- 假设你想为公司创建一个电子邮件自动回复生成器。由于你的公司所在的行业使用专有词汇,因此你希望生成器给出的电子邮件回复保持一定的写作风格。要做到这一点,有两种策略:要么使用之前介绍的提示工程技巧来强制模型输出你想要的文本,要么对现有模型进行微调。
- 对比微调和少样本学习微调是指针对特定任务在一组数据上重新训练现有模型,以提高模型的性能并使其回答更准确。在微调过程中,模型的内部参数得到更新。少样本学习则是通过提示词向模型提供有限数量的好例子,以指导模型根据这些例子给出目标结果。在少样本学习过程中,模型的内部参数不会被修改。无论是微调还是少样本学习,都可以用来增强GPT模型。微调可以帮助我们得到高度专业化的模型,更准确地为特定任务提供与上下文相关的结果。这使得微调非常适合有大量数据可用的场景。这种定制化确保模型生成的内容更符合目标领域的特定语言模式、词汇和语气[插图]。少样本学习是一种更灵活的方法,其数据使用率也更高,因为它不需要重新训练模型。当只有有限的示例可用或需要快速适应不同任务时,这种技巧非常有益。少样本学习让开发人员能够快速设计原型并尝试各种任务,这使其成为许多用例的实用选择。这两种方法的另一个关键选择标准是成本,毕竟使用和训练微调模型更贵。
5.1 LangChain框架
- LangChain框架的关键模块。
- Models(模型) 该模块是由LangChain提供的标准接口,你可以通过它与各种LLM进行交互。LangChain支持集成OpenAI、Hugging Face、Cohere、GPT4All等提供商提供的不同类型的模型。 Prompts(提示词) 提示词已成为LLM编程的新标准。该模块包含许多用于管理提示词的工具。 Indexes(索引) 该模块让你能够将LLM与你的数据结合使用。 Chains(链) 通过该模块,LangChain提供了Chain接口。你可以使用该接口创建一个调用序列,将多个模型或提示词组合在一起。 Agents(智能体) 该模块引入了Agent接口。所谓智能体,就是一个可以处理用户输入、做出决策并选择适当工具来完成任务的组件。它以迭代方式工作,采取一系列行动,直到解决问题。 Memory(记忆) 该模块让你能够在链调用或智能体调用之间维持状态。默认情况下,链和智能体是无状态的。这意味着它们独立地处理每个传入的请求,就像LLM一样。 LangChain是用于不同LLM的通用接口,你可以查阅其文档以了解更多信息。
- 智能体及工具是LangChain框架提供的关键功能:它们可以使应用程序变得非常强大,让LLM能够执行各种操作并与各种功能集成,从而解决复杂的问题。 这里所指的“工具”是围绕函数的特定抽象,使语言模型更容易与之交互。智能体可以使用工具与世界进行交互。具体来说,工具的接口有一个文本输入和一个文本输出。LangChain中有许多预定义的工具,包括谷歌搜索、维基百科搜索、Python REPL、计算器、世界天气预报API等。要获取完整的工具列表,请查看LangChain文档中的工具页面。除了使用预定义的工具,你还可以构建自定义工具并将其加载到智能体中,这使得智能体非常灵活和强大。
- 本节介绍一种适用于应用程序的智能体,它需要一系列中间步骤。该智能体安排执行这些步骤,并可以高效地使用各种工具响应用户的查询。从某种意义上说,因为“逐步思考”,所以智能体有更多的时间来规划行动,从而完成更复杂的任务。 智能体安排的步骤如下所述。 01.智能体收到来自用户的输入。 02.智能体决定要使用的工具(如果有的话)和要输入的文本。 03.使用该输入文本调用相应的工具,并从工具中接收输出文本。 04.将输出文本输入到智能体的上下文中。 05.重复执行步骤2~步骤4,直到智能体决定不再需要使用工具。此时,它将直接回应用户。
- 如以下代码所示,LangChain智能体可以使用两个工具:维基百科搜索和计算器。在通过load_tools函数创建工具之后,我们使用initialize_agent函数创建智能体。智能体的推理功能需要用到一个LLM,本例使用的是gpt-3.5-turbo。参数ZERO_SHOT_REACT_DESCRIPTION定义了智能体如何在每一步中选择工具。通过将verbose的值设置为True,我们可以查看智能体的推理过程,并理解它是如何做出最终决策的。 from langchain.chat_models import ChatOpenAIfrom langchain.agents import load_tools, initialize_agent, AgentTypellm = ChatOpenAI(model_name="gpt-3.5-turbo", temperature=0)tools = load_tools(["wikipedia", "llm-math"], llm=llm)agent = initialize_agent( tools, llm, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, verbose=True)question = """What is the square root of the population of the capitalof the Country where the Olympic Games were held in 2016?"""agent.run(question)
- 嵌入 将语言模型与你自己的文本数据相结合,这样做有助于将应用程序所用的模型知识个性化。原理与第3章讨论的相同:首先检索信息,即获取用户的查询并返回最相关的文档;然后将这些文档发送到模型的输入上下文中,以便它响应查询。本节展示使用LangChain和嵌入技术实现这一点是多么简单。 document_loaders是LangChain中的一个重要模块。通过这个模块,你可以快速地将文本数据从不同的来源加载到应用程序中。比如,应用程序可以加载CSV文件、电子邮件、PowerPoint文档、Evernote笔记、Facebook聊天记录、HTML页面、PDF文件和许多其他格式。要查看完整的加载器列表,请查阅LangChain文档。
- 如果PDF文件位于当前工作目录下,则以下代码将加载文件内容并按页进行划分。 from langchain.document_loaders import PyPDFLoaderloader = PyPDFLoader("ExplorersGuide.pdf")pages = loader.load_and_split()
- 进行信息检索时,需要嵌入每个加载的页面。正如我们在第2章中讨论的那样,在信息检索中,嵌入是用于将非数值概念(如单词、标记和句子)转换为数值向量的一种技术。这些嵌入使得模型能够高效地处理这些概念之间的关系。借助OpenAI的嵌入端点,开发人员可以获取输入文本的数值向量表示。此外,LangChain提供了一个包装器来调用这些嵌入,如下所示。 from langchain.embeddings import OpenAIEmbeddingsembeddings = OpenAIEmbeddings()
- 索引保存页面嵌入并使搜索变得容易。LangChain以向量数据库为中心。有许多向量数据库可供选择,详见LangChain文档。以下代码片段使用Faiss向量数据库,这是一个主要由Facebook AI团队开发的相似性搜索库。 from langchain.vectorstores import FAISSdb = FAISS.from_documents(pages, embeddings)
- 现在很容易搜索相似内容: q = "What is Link's traditional outfit color?"db.similarity_search(q)[0] 我们得到以下内容: Document(page_content='While Link’s traditional green tunic is certainly an iconic look, his wardrobe has expanded [...] Dress for Success', metadata={'source': 'ExplorersGuide.pdf', 'page': 35}) 这个问题的答案是,Link的服装颜色是绿色。我们可以看到,答案就在选定的内容中。
- 你可能希望将嵌入整合到聊天机器人中,以便在回答问题时使用它检索到的信息。再次强调,使用LangChain,只需几行代码即可轻松实现。我们使用RetrievalQA,它接受LLM和向量数据库作为输入。然后,我们像往常一样向所获得的对象提问: from langchain.chains import RetrievalQAfrom langchain import OpenAIllm = OpenAI()chain = RetrievalQA.from_llm(llm=llm, retriever=db.as_retriever())q = "What is Link's traditional outfit color?"chain(q, return_only_outputs=True) 这一次,我们得到以下答案: {'result': " Link's traditional outfit color is green."}
- 你可能会问:为什么在将信息添加到LLM的上下文中之前需要进行信息检索?事实上,目前已有的语言模型无法处理包含数百页的大型文件。因此,如果输入文件过大,那么我们会对其进行预过滤。这是信息检索过程的任务。在不久的将来,随着输入上下文的不断增加,可能就不再需要使用信息检索技术了。
5.2 GPT-4插件
- 模型就成了智能的API调用者。当用户询问关于插件的问题时,模型可以调用你的插件API。是否调用插件是基于OpenAPI规范和关于应该使用API的情况的自然语言描述所做出的决策。一旦模型决定调用你的插件,它就会将API的结果合并到上下文中,以向用户提供响应。因此,插件的API响应必须返回原始数据而不是自然语言响应。这使得GPT-4可以根据返回的数据生成自己的自然语言响应。
5.3 小结
- LangChain框架和GPT-4插件有助于大幅提升LLM的潜力。 凭借其强大的工具和模块套件,LangChain已成为LLM领域的核心框架。 它在集成不同模型、管理提示词、组合数据、为链排序、处理智能体和管理记忆等方面的多功能性为开发人员和AI爱好者开辟了新的道路。
- 请记住,LangChain的真正潜力在于创造性地利用各种功能来解决复杂问题,并将通用语言模型转化为功能强大且具体的应用程序。 GPT-4插件是语言模型和实时可用的上下文信息之间的桥梁。如本章所述,开发插件需要结构良好的API和描述性文件。因此,开发人员必须在这些文件中提供详细和自然的描述。这将有助于GPT-4充分利用API。
术语表
- chain of thought(CoT,思维链) 一种提示工程技术,核心思想是通过向大语言模型展示少量的示例,在示例中将具体问题拆分成多个推理步骤,并要求模型遵循多步,比如“让我们逐步思考”。这会改善模型在执行复杂的推理任务(算术推理、常识推理和符号推理)时的表现。
来自微信读书