赞
踩
原文:
zh.annas-archive.org/md5/2e3ab9ce96c35c507253e57a41b1a6f1
译者:飞龙
packt.link/EarlyAccessCommunity
人工智能(AI)取得了重大进展,影响着企业、社会和个人。大约过去的十年里,深度学习已经发展到可以处理和生成文本、图像、视频等非结构化数据的程度。这些基于深度学习的先进人工智能模型在各个行业都受到了欢迎,包括大型语言模型(LLMs)。目前,媒体和行业都对人工智能存在很高的热情。这是由多种因素推动的,包括技术进步、知名应用以及潜在的跨行业变革影响。在本章中,我们将讨论生成模型,特别是 LLMs,并将其应用于文本、图像、声音和视频等领域。我们将介绍一些使它们运转的技术背景,以及它们是如何训练的。我们将从一个介绍开始,澄清我们在技术最前沿的地方以及热潮是关于什么的。
在媒体上,人工智能相关突破及其潜在影响得到了大量报道。这些涵盖了从自然语言处理和计算机视觉的进步到像 GPT-3 这样的复杂语言模型的发展。媒体通常突出人工智能的能力以及其革命性改变医疗保健、金融、交通等行业的潜力。特别是,生成模型因其能够生成文本、图像和其他创意内容(通常与人类生成的内容难以区分)而受到了广泛关注。这些模型还提供了广泛的功能,包括语义搜索、内容操作和分类。这通过自动化实现了成本节约,并可以让人类以前所未有的水平利用他们的创造力。这张图表灵感来自于 LessWrong 上 Stephen McAleese 关于 GPT-4 预测的博文,显示了 LLM 在大规模多任务语言理解(MMLU)基准测试中的改进情况,该测试旨在量化基础数学、美国历史、计算机科学、法律等领域的知识和问题解决能力:
图 1.1:大型语言模型(LLM)在大规模多任务语言理解(MMLU)基准测试上的平均表现。请注意,虽然大多数基准结果来自 5-shot,但一些 GPT-2、PaLM 和 PaLM-2 的结果是指微调模型。
您可以在近年的基准中看到进展。特别值得强调的是 OpenAI 通过公共用户界面提供的模型的进展,特别是从 GPT-2 到 GPT-3 再到 GPT-3.5 到 GPT-4 版本之间的改进。这些模型最近才开始胜过平均人类评分员,但仍未达到人类专家的水平。这些人工智能模型的成就令人印象深刻;然而,值得注意的是这些模型的表现取决于领域;大多数模型在小学数学单词问题的 GSM8K 基准测试中仍表现不佳。
OpenAI 是一家美国人工智能研究实验室,旨在推动和发展友好的人工智能。它成立于 2015 年,得到了几位有影响力的人物和公司的支持,他们承诺向这项创业投资超过 10 亿美元。该组织最初承诺非营利性质,通过向公众开放其专利和研究成果,与其他机构和研究人员合作。2018 年,埃隆·马斯克因担心与特斯拉的角色存在潜在利益冲突而辞去了董事会成员职务。2019 年,OpenAI 转变为营利性组织,随后微软对 OpenAI 进行了重大投资,导致 OpenAI 系统与微软基于 Azure 的超级计算平台以及必应搜索引擎整合。该公司的最显著成就包括用于训练强化算法的 OpenAI Gym,以及最近推出的 GPT-n 模型和 DALL-E,另一个能从文本生成图像的深度学习模型。
生成预训练Transformers(GPT)模型,如最近推出的 OpenAI 的 ChatGPT,是 AI 在 LLM 领域的主要进展的典范。ChatGPT 通过在更大的规模上进行训练,并且比以前的模型更大,极大地改善了聊天机器人的能力。这些基于 AI 的聊天机器人可以生成类似人类的实时反馈以回应客户,并且可以应用于广泛的用例,从软件开发和测试到诗歌和商业通信。在行业内,对于 AI 的能力及其对业务运营的潜在影响,人们感到越来越兴奋。我们将在第十章,生成模型的未来中更详细地讨论这一点。随着 OpenAI 的 GPT 等 AI 模型的不断改进,它们可能成为需要多样化知识和技能的团队的不可或缺的资产。例如,GPT-4 可以被认为是一个可以无偿工作的“博学多才”的人(除了订阅或 API 费用),在数学、语言、统计、宏观经济学、生物学甚至通过法律考试方面提供帮助。随着这些 AI 模型变得更加熟练和易于访问,它们很可能在塑造未来工作和学习方面发挥重要作用。通过使知识更易于访问和适应,这些模型有可能促进公平竞争,并为各行各业的人们创造新的机会。这些模型在需要更高级别推理和理解的领域显示出潜力,尽管取得进展的程度取决于涉及的任务的复杂性。至于带有图像的生成模型,我们可以期待具有更好能力的模型协助创建视觉内容,并且可能在目标检测、分割、字幕生成等计算机视觉任务方面有所改进。让我们把术语稍微澄清一下,并更详细地解释生成模型、人工智能、深度学习和机器学习是什么意思。
在媒体中,当提到这些新模型时经常使用术语人工智能。值得更清晰地区分一下术语生成模型与人工智能、深度学习、机器学习和语言模型的区别:
人工智能(AI)是计算机科学的一个广泛领域,涉及创建智能代理的系统,这些系统可以推理、学习和自主行动。
机器学习(ML)是人工智能的一个子集,涉及开发能够从数据中学习的算法。ML 算法是在一组数据上训练的,然后它们可以使用该数据进行预测或决策。
深度学习(DL)是机器学习的一个子集,使用人工神经网络从数据中学习。神经网络受人类大脑启发,它们能够从数据中学习复杂的模式。
生成模型是一种可以生成新数据的机器学习模型。生成模型在一组数据上进行训练,然后它们可以利用该数据创建类似于训练数据的新数据。
语言模型是预测序列中的标记(通常是单词)的统计模型。其中一些能够执行更复杂的任务的模型由许多参数组成(数量达到数十亿甚至万亿),因此被称为大语言模型。
生成模型与其他类型的机器学习模型之间的主要区别在于生成模型不仅仅是做出预测或决策。它们实际上可以创建新数据。这使得生成模型非常强大,可以用于各种任务,比如生成图像、文本、音乐和视频。下表总结了人工智能(AI)、机器学习(ML)、深度学习(DL)、语言模型和生成模型之间的区别:
术语 | 定义 |
---|---|
人工智能 | 计算机科学的一个广泛领域,涉及智能体的创建。 |
机器学习 | 处理能够从数据中学习的算法开发的人工智能的一个子集。 |
深度学习 | 机器学习的一个子集,利用人工神经网络从数据中学习。 |
生成模型 | 一种能够生成新数据的机器学习模型。 |
语言模型 | 一种模型,如今主要是深度学习模型,用于在上下文中预测标记。 |
图 1.2:术语 - 人工智能、机器学习、深度学习和生成模型。生成模型是一种强大的人工智能类型,可以生成类似于训练数据的新数据样本。生成式人工智能模型已经取得了长足的进展,能够利用数据中的模式从头开始生成新示例。这些模型可以处理不同类型的数据,并应用于各种领域,包括文本生成、图像生成、音乐生成和视频生成。对于语言模型,重要的是要注意,其中一些模型,尤其是较新一代的模型,是生成的,可以产生语言(文本),而其他模型则不是。这些生成模型促进了生成合成数据来训练人工智能模型,当真实数据稀缺或受限时。这种数据生成方式可以降低标记成本并提高训练效率。微软研究采用了这种方法(“只需教科书”,2023 年 6 月),用 GPT-3.5 创建了合成教科书和练习作为他们的训练数据集。在接下来的章节中,我们将看看生成模型的不同领域,比如文本、图像、声音、视频。这些应用主要围绕内容生成、编辑和处理(识别)。让我们从文本开始!
文本生成,如 OpenAI 的 GPT-4,可以生成连贯和语法正确的诗歌,或者用不同语言编写代码并提取关键词和主题特征。这些模型在内容创作和自然语言处理(NLP)等领域具有实际应用,其最终目标是创建能够解释人类语言的算法。语言建模旨在基于先前的文本序列来预测下一个单词、字符,甚至句子。从这个意义上讲,语言建模可以作为一种编码语言规则和结构的方法,可以被机器理解。大型语言模型捕获了人类语言的语法、句法和语义结构。这些模型很重要,因为它们构成了许多更大的 NLP 任务的核心,例如内容创建、翻译、摘要、机器翻译和文本编辑任务,如拼写校正。从本质上讲,语言建模以及更广泛地说自然语言处理,严重依赖于表示学习的质量。一个训练良好的语言模型可以对其训练的文本信息进行编码,并基于这些学习生成新的文本,从而承担文本生成的任务。最近,大型语言模型已经在论文生成、代码开发、翻译和理解基因序列等任务中找到了应用。语言模型的更广泛应用涉及多个领域,例如:
问答:AI 聊天机器人和虚拟助手可以提供个性化和高效的帮助,缩短客户支持的响应时间,从而提升客户体验。这些系统可以用于解决诸如餐厅预订和票务预订等特定问题。
自动摘要:语言模型可以创建文章、研究论文和其他内容的简洁摘要,使用户能够迅速消化和理解信息。
情感分析:通过分析文本中的观点和情感,语言模型可以帮助企业更高效地理解客户的反馈和意见。
主题建模和语义搜索:这些模型可以识别、按主题分类,并将文档压缩成简洁向量,使得组织在内容管理和发现方面更加便利。
机器翻译:AI 驱动的语言模型可以将一种语言的文本翻译成另一种语言,支持企业的全球扩张努力。新型生成模型可以与商业产品(例如 Google 翻译)竞争。
尽管语言模型取得了显著的成就,但在处理复杂的数学或逻辑推理任务时,仍然存在限制。目前还不清楚不断增加语言模型规模是否会不可避免地导致新的推理能力。正如前面提到的,我们还必须考虑数据质量和规模的重要性,因为这些因素在改进不同任务和领域中的语言模型性能方面起着重要作用。生成模型的另一个应用领域是图像生成,让我们来看看这是怎么回事!
生成式人工智能广泛用于生成 3D 图像、头像、视频、图表、虚拟或增强现实中的插图、视频游戏图形设计、标识创建、图像编辑或增强。该图表展示了使用稳定扩散从文本提示中生成图像(来源:麻省理工学院和谷歌研究的 Yilun Xu 等人于 2023 年 6 月发表的“重启采样以改进生成过程”;https://arxiv.org/pdf/2306.14878.pdf):
图 1.3:从文本提示“一个由玻璃制成的透明鸭雕塑”生成的图像。
借助稳定的扩散模型,你可以在仅对模型的初始设置进行最小更改或使用数值求解器和抽样器的情况下,看到各种结果。尽管有时它们会产生惊人的结果,但这种不稳定性和不一致性对更广泛应用这些模型构成了重大挑战。像MidJourney、DALL-E 2和Stable Diffusion这样的服务,提供自文本输入或其他图像派生出的有创意和逼真的图像。像DreamFusion、Magic3D和Get3D这样的服务,让用户能够将文字描述转换为 3D 模型和场景,推动设计、游戏和虚拟体验领域的创新。主要应用有三大方面:
图像生成:模型可以生成绘画、照片和素描等图像。这可以用于各种用途,如创作艺术品、设计产品、生成逼真的视觉效果。
图像编辑:模型可以执行移除对象、更改颜色和添加效果等任务。这可以用于提高图像的质量,并使其更具视觉吸引力。
图像识别:大型基础模型可用于识别图像,包括场景分类,还有对象检测,例如检测人脸。
像生成对抗网络(GANs)和 DALL-E 这样的模型。GANs 生成逼真的图像,具有许多商业应用,而 DALL-E 则根据文本描述创建图像,这对于创意产业设计广告、产品和时尚非常有帮助。图像编辑涉及使用面部属性编辑或图像变形等技术修改图像的语义,通过优化和基于学习的方法生成具有通过 StyleGAN 预训练的 GAN 模型的潜在表示获得的风格的图像。扩散模型最近已被用于高级图像编辑任务,如通过文本引导无缝连接手动设计的遮罩区域或生成 3D 对象操作。这些技术使得图像生成灵活,但面临着有限的多样性问题,可以通过将其他文本输入纳入到过程中来缓解。图像编辑类别还包括图像恢复等任务,即从其降解版本中恢复清晰图像,这涉及图像超分辨率、修补、去噪、去雾和去模糊等任务。使用 CNN 和 transformer 架构的深度学习方法由于比传统方法具有优越的视觉质量而普遍存在。生成模型如 GANs 和扩散模型(DMs)用于恢复,但可能遭受复杂的训练过程和模式崩溃。多畸变数据集和带有注意模块或引导子网络的单网络方法提高了处理多种降解类型的效果。我们接下来将看到模型如何处理声音和音乐。
生成模型可以根据文本输入开发歌曲和音频片段,识别视频中的对象并创建相应的音频,并创建定制音乐。我们可以粗略地将应用程序再次分类为生成、编辑和识别:
音乐生成:生成模型可以用于生成音乐,比如歌曲、节拍和旋律。这可以用于各种目的,比如创作新音乐、谱写配乐和生成个性化播放列表。
声音编辑:生成模型可用于编辑声音,例如去除噪音、改变音调和添加效果。这可以用于提高声音质量,并使其更具声音吸引力。
声音识别:生成模型可以用于识别声音,例如识别乐器、分类流派和检测语音。这可以用于各种目的,比如音乐分析、搜索和推荐系统。
音乐生成算法始于 20 世纪 50 年代的算法作曲,近年来出现了诸如 Google 的 WaveNet 和 OpenAI 的 Jukebox 等创新。这些模型导致了 AI 作曲助手的出现,可以在各种风格中生成音乐,并实现了诸如语音合成之类的新应用。作为特例,语音转文本生成,也称为自动语音识别(ASR),是将口语转换为文本的过程。它们经过声音和文本的训练。ASR 系统的准确性越来越高,现在被广泛应用于各种应用中。但是,仍然存在一些需要解决的挑战,比如处理嘈杂环境和不同口音的能力。随着诸如语音拨号和像 Alexa 和 Siri 这样的计算机辅助个人助手的潜在应用越来越多,ASR 背后的技术从马尔可夫模型发展到依赖于 GPTs。接下来我们将看到视频。
DeepMind 的 Motion to Video 和 NVIDIA 的 Vid2Vid 等视频生成模型依赖于 GANs 进行高质量的视频合成。它们可以在不同领域之间转换视频,修改现有视频,并将静态图像制作成动画,展示了在视频编辑和媒体制作方面的巨大潜力。像 Make-a-Video 和 Imagen Video 这样的工具可以将自然语言提示转换为视频片段,简化视频制作和内容创作流程。这些应用的广泛类别包括:
视频生成:生成模型可以用来生成视频,比如短片、动画和商业广告。这可以用于创建新内容、推广产品和生成逼真的视觉效果。
视频编辑:我们可以编辑视频,比如删除对象、更改颜色和添加效果。这可以帮助提高视频的质量,并使其更具视觉吸引力。
视频识别:模型可以识别视频,比如识别物体、分类场景和检测人脸。这对于安全、搜索和推荐系统等应用非常有帮助。
一些模型可以在多个领域或模态中生成内容。这些称为多模态模型。
多模态生成模型可以生成文本、图像、声音和视频。这使它们能够创建更加逼真和沉浸式的体验。多模态模型仍处于早期开发阶段,但它们有可能彻底改变我们与计算机交互和体验世界的方式。例如,这些进步显著提高了图像字幕任务的性能,即通过自然语言描述图像内容的过程。多模态模型采用将图像和字幕融合为单一模型的生成架构进行共享学习空间。这个过程涉及到两步编码器-解码器架构:视觉编码和语言解码。我们可以区分出这些潜在的用例:
虚拟现实:这些模型可以用来创建更加真实和沉浸式的虚拟现实体验。这可以在游戏、教育和培训中起到帮助作用。
增强现实:它们可以创建增强现实体验,将数字内容叠加在现实世界上。这对导航、购物和娱乐非常有用。
在下一节中,我们将讨论大型语言模型的技术背景。
大型语言模型(LLMs)是深度训练的神经网络,擅长理解和生成人类语言。像 ChatGPT 这样的当前一代 LLMs 是深度神经网络架构,利用 Transformer 模型进行预训练,利用无监督学习在大量文本数据上进行预训练,从而使其能够学习语言模式和结构。最新一代 LLMs 的显著优势在于其作为对话界面(ChatBot)的能力,能够生成连贯且情景适当的回应,甚至在开放式对话中也是如此。通过根据前面的单词生成下一个单词,该模型产生流畅、连贯的文本,通常难以与人类产生的文本区分开来。然而,OpenAI 曾表示 ChatGPT 会有“有时写出听起来可信但是不正确或荒谬的答案”的现象。这被称为幻觉,这只是围绕 LLMs 的担忧之一。Transformer 是一个深度学习架构,于 2017 年首次由 Google 和多伦多大学的研究人员提出(在一篇名为“Attention is All You Need”的文章中),其包括自注意力和前馈神经网络,使其能够有效地捕捉句子中的单词关系。注意机制使模型能够专注于输入序列的不同部分。生成式预训练变换器(GPTs)是由 OpenAI 的研究人员于 2018 年与他们的第一款同名 GPT 模型 GPT-1 一起推出的,并发表在“通过生成式预训练来改进语言理解”的论文中。预训练过程涉及预测文本序列中的下一个单词,提高模型对语言的理解程度,这可以从输出的质量来衡量。在预训练完成后,模型可供特定语言处理任务(如情感分析、语言翻译或对话)进行微调。这种无监督和监督学习的组合使 GPT 模型能够在各种自然语言处理任务中表现更好,并减少了训练 LLMs 时面临的挑战。LLMs 的训练语料库规模已经急剧增加。2018 年由 OpenAI 推出的 GPT-1 是在包含 9.85 亿个单词的 BookCorpus 上进行的训练。同年发布的 BERT 是基于 BookCorpus 和 English Wikipedia 的联合语料库进行训练,共计 33 亿个单词。现在,LLMs 的训练语料库已经达到了数万亿的标记。这张图表说明了 LLMs 是如何越来越庞大的:
图 1.4:从 BERT 到 GPT-4 的大型语言模型 - 大小、训练预算和组织。
数据点的大小表示以 petaFLOP 天为单位的训练成本。对于一些模型,尤其是专有和闭源模型,这些信息是未知的 - 在这些情况下,我放了个叉。例如,对于 XLNet,论文没有提供有关 flops 计算的信息,但是,训练是在 512 个 TPU v3 芯片上进行的,历时 2.5 天。数据点的颜色显示了开发该模型的公司或组织 - 由于这些颜色在打印版或 Kindle 上可能看不到(除非你有一台彩色 Kindle),你可以在此网址找到这个图表的彩色版本:GPT 模型的开发取得了显著进展,OpenAI 的 GPT-n 系列在创建基础 AI 模型方面处于领先地位。LLM 的训练语料库规模已经大幅增长。2018 年,OpenAI 推出了 GPT-1,它是在包含 9.85 亿个单词的 BookCorpus 上进行训练的。BERT,也是在同一年发布的,是在 BookCorpus 和英文维基百科的结合语料库上进行训练的,总共有 33 亿个单词。现在,LLM 的训练语料库可达到数万亿个标记。
基础模型(有时称为基础模型)是一个大型模型,它在规模上经过了大量数据的训练,以便它可以适应各种下游任务。在 GPT 模型中,这种预训练是通过自监督学习完成的。
经过 3000 亿个标记的训练,GPT-3 拥有 1750 亿个参数,这是深度学习模型的一个前所未有的规模。GPT-4 是该系列中最新的,尽管由于竞争和安全方面的考虑,其规模和训练细节尚未公布,但不同的估计将其放在 200 到 5000 亿个参数之间。Sam Altman,OpenAI 的 CEO 表示,训练 GPT-4 的成本超过了 1 亿美元。ChatGPT,一个对话模型,由 OpenAI 在 2022 年 11 月发布。基于之前的 GPT 模型(特别是 GPT-3),并针对对话进行了优化,它结合了人类生成的角色扮演对话和人类标记者对所需模型行为的演示数据集。该模型展现了出色的能力,如广泛的知识保留和多轮对话中的精确上下文跟踪。另一个重要的进展出现在 2023 年 3 月的 GPT-4 上,它不仅限于文本输入,还包括多模态信号。由于训练期间进行了六个月的迭代对齐,GPT-4 在各种评估任务上表现出优异的性能,并且在避免恶意或挑衅性查询方面有着明显更好的响应。除 OpenAI 之外的其他知名基础 GPT 模型包括 Google 的 PaLM2。虽然 GPT-4 在性能上领先于大多数基准测试,但这些以及其他模型在某些任务上表现出可比性,并且为基于生成变换器的语言模型的进展做出了贡献。Meta 的 LLaMA 受到 1.4 万亿个标记的训练,而 Google 聊天机器人 Bard 背后的模型 PaLM2 由 3400 亿个参数组成,比以前的 LLMs 小,但在至少 100 种语言中似乎具有更大规模的训练数据。
有相当多的 公司和组织正在开发 LLMs,并且它们以不同的方式发布。OpenAI 已发布了 GPT-2,随后的模型已关闭源代码,但可以通过其网站或 API 使用。Meta 正在发布从 RoBERTa、BART 到 LLaMA 的模型,包括模型的参数(权重),尽管采用非商业许可证,以及设置和训练模型的源代码。Google AI 及其 DeepMind 部门已开发了许多大型语言模型,包括 BERT、GPT-2、LaMDA、Chinchilla、Gopher、PaLM 和 PaLM2。他们已经在开源许可下发布了一些模型的代码和权重,尽管最近他们在开发中更趋向于保密。微软已开发了许多大型语言模型,包括 Turing NLG 和 Megatron-Turing NLG,但他们已将 OpenAI 模型集成到 Microsoft 365 和 Bing 中。阿布扎比政府资助的研究机构科技创新研究所(TII)已经为研究和商业用途开源了 Falcon LLM。
GPT 模型也可以处理超出文本范围的模态输入和输出,正如 GPT-4 能够处理图像输入与文本一样。此外,它们还为文本到图像技术如扩散和并行解码奠定了基础,从而实现了与图像一起工作的系统的视觉基础模型(VFMs)的发展。总而言之,GPT 模型已经快速发展,使得可以创建多功能的基础 AI 模型,适用于广泛的下游任务和模态,最终推动了各种应用和行业的创新。在下一节中,我们将回顾深度学习和生成模型在最近几年取得的进展,这些进展导致了当前明显能力的爆炸性增长以及这些模型所吸引的关注。
2022 年生成 AI 成功进入公众视野的原因可以归因于几个相互关联的驱动因素。生成模型的发展和成功依赖于改进的算法,计算能力和硬件设计的显著进步,大型标记数据集的可用性,以及积极合作的研究社区帮助演化一套工具和技术。更复杂的数学和计算方法的发展对于生成模型的进步起着至关重要的作用。20 世纪 80 年代由 Geoffrey Hinton、David Rumelhart 和 Ronald Williams 引入的反向传播算法就是一个例子。它提供了一种有效地训练多层神经网络的方法。在 2000 年代,神经网络开始重新受到研究人员的关注,研究人员开发了更复杂的架构。然而,深度学习的出现,即具有多个层的神经网络的一种类型,标志着这些模型性能和能力的重大转折点。有趣的是,尽管深度学习的概念已经存在了一段时间,但生成模型的发展和扩展与硬件的显著进步有关,特别是图形处理单元(GPUs),这些硬件对推动该领域向前发展起到了重要作用。正如前面提到的,更便宜和更强大的硬件的可用性是发展更深层模型的关键因素之一。这是因为深度学习模型需要大量的计算资源来训练和运行。这涉及到处理能力、内存和磁盘空间的所有方面。此图显示了不同媒介(如磁盘、固态、闪存和内存)的计算机存储成本随时间变化的情况,以每千兆字节的价格表示(来源:Our World in Data;ourworldindata.org/moores-law
):
图 1.5:自 1950 年代以来每个千兆字节的计算机存储成本。
虽然过去,训练深度学习模型代价高昂,但随着硬件成本的降低,现在可以在更大的数据集上训练更大型的模型。模型的大小是决定其在逼近(以困惑度衡量)训练数据集方面表现的因素之一。
在 LLM 中参数数量的重要性:模型的参数数量越多,其捕捉单词和短语关系作为知识的能力就越强。作为这些高阶相关性的简单示例,LLM 可以学习当单词“猫”在词“追逐”之前出现时,如果其后跟着单词“狗”,那么猫更有可能追逐狗,即使中间还有其他单词。一般来说,模型的困惑度越低,其性能越好,例如在回答问题方面。特别地,似乎在由 20 亿到 70 亿个参数构成的模型中,新的功能会出现,例如生成不同的创意文本格式,如诗歌、代码、脚本、音乐作品、电子邮件、信件,并以信息丰富的方式回答问题,即使它们是开放性和挑战性的。
2009 年,Nvidia 催生了深度学习的“大爆炸”,推动了更大型的模型发展趋势。GPU 对于深度学习神经网络所需的矩阵/向量计算非常适用,因此将这些系统的速度和效率显著提高了数倍,并将运行时间从数周缩短到数天。特别是,Nvidia 的CUDA平台允许直接编程 GPU,使得研究人员和开发人员能够更轻松地尝试和部署复杂的生成模型。在 2010 年代,不同类型的生成模型开始受到关注。自编码器是一种神经网络,可以学习将输入层的数据压缩成一种表示,然后重新构建输入,这为更高级的模型(如 2013 年首次提出的变分自编码器 VAE)奠定了基础。与传统自编码器不同,VAE使用变分推理来学习数据的分布,也称为输入数据的潜在空间。与此同时,Ian Goodfellow 和其他人在 2014 年提出了生成对抗网络 GAN。GAN 的训练过程如下图所示(摘自“使用生成对抗网络生成文本的调查”,G de Rosa 和 J P. Papa,2022; arxiv.org/pdf/2212.11119.pdf
):
图 1.6:生成对抗网络(GAN)的训练。
GANs 由两个网络组成,在类似游戏的设置中相互对抗 - 生成器生成新数据,通常是图像,以及估计新数据为真实数据的概率的鉴别器。当它们相互竞争时,GANs 在任务上变得更加优秀,能够生成逼真的图像和其他类型的数据。在过去的十年中,在深度学习中使用的基本算法取得了重大进展,如更好的优化方法、更复杂的模型架构和改进的正则化技术。Transformer 模型,于 2017 年推出,建立在这一进展的基础上,并实现了像 GPT-3 这样的大规模模型的创建。Transformers 依赖于注意机制,并且使生成模型的性能进一步提升。这些模型,如 Google 的 BERT 和 OpenAI 的 GPT 系列,可以生成高度连贯和具有上下文相关性的文本。迁移学习技术的发展也是重要的一部分,它允许对一个任务上预训练的模型进行在另一个类似的任务上微调,这些技术使训练大规模生成模型更加高效和实用。此外,生成模型的崛起部分归功于专门设计用于处理这些人工神经网络的软件库和工具(TensorFlow、PyTorch、Keras),简化了构建、训练和部署的过程。为了进一步推动生成模型的发展,研究界定期举行像 ImageNet(用于图像分类)这样的挑战赛,并已开始为生成模型做同样的事情,比如 Generative Adversarial Networks (GAN) Competition。除了更便宜和更强大的硬件的可用性之外,大量标记数据集的可用性也是生成模型发展的关键因素。这是因为深度学习模型,尤其是生成模型,需要大量文本数据进行有效训练。互联网数据的爆炸性增长,尤其是在过去的十年中,创造了适合这种模型发展的环境。随着互联网的普及,收集大规模文本、图像和其他数据集变得更加容易。这使得可以在比过去更大的数据集上训练生成模型成为可能。总之,生成建模是一个令人着迷且正在快速发展的领域。它有潜力彻底改变我们与计算机的交互方式以及我们创建新内容的方式。我很期待看到这个领域的未来。让我们深入了解 - 这是如何工作的?
诸如 BERT 和 GPT 之类的模型,都是由Transformers深度神经网络架构所实现的,该架构已经成为自然语言处理的游戏规则改变者。设计为避免递归以允许并行计算,Transformers架构在不同的变体中继续推动自然语言处理和生成式人工智能领域可能性的边界。Transformers的定义特征之一是注意机制。传统的序列到序列模型经常受到处理长依赖性的问题的困扰-如果序列过长,则很难记住相关信息。Transformers模型引入了注意机制来解决这个问题。自注意机制,通常被称为Transformers模型的核心,为序列中的每个单词分配一个分数,决定应该给予该单词多少关注。Transformers由可以堆叠的模块组成,从而创建可以学习大规模数据集的非常大型模型。这在这里的图示中指示出。
图 1.7:Transformers架构(来源:Yuening Jia,维基共享资源)
对 Transformer 成功的架构特征:
编码器-解码器结构:Transformers模型遵循编码器-解码器结构。编码器接受输入序列并计算一系列表示(上下文嵌入),为每个词生成表示。这些表示不仅考虑词语的固有含义(它们的语义价值),还考虑它们在序列中的上下文。解码器然后使用此编码信息,逐个生成输出序列项,利用先前生成的项的上下文。
位置编码:由于 Transformer 不是顺序处理单词,而是同时处理所有单词,它缺乏对单词顺序的任何概念。为了弥补这一点,关于序列中单词位置的信息被注入到模型中,使用位置编码。这些编码被添加到表示每个单词的输入嵌入中,从而使模型考虑序列中的单词顺序。
层归一化:为了稳定网络的学习,Transformers使用一种称为层归一化的技术。这种技术通过特征维度(而不是批处理维度,如批处理归一化中)对模型的输入进行归一化,从而提高了整体学习的速度和稳定性。
多头注意力:Transformer 不是一次应用注意力,而是并行多次应用它,从而改进了模型聚焦于不同类型信息的能力,从而捕捉到更丰富的特征组合。
另一个可选的架构特性,不仅仅适用于 Transformers 的是 Skip Connections(也称为:Residual Connections)。这些被引入是为了减轻网络加深时出现的退化问题,使用了 Skip Connections。这允许梯度在层之间无缝流动,通过将输入直接传递给更深层次。Transformers 在自然语言处理领域推动了前沿,特别是在翻译和语言理解方面。神经机器翻译(NMT)是机器翻译的主流方法,它使用深度学习来捕捉句子中的长距离依赖关系。基于 Transformers 的 NMT 胜过了以往的方法,比如使用循环神经网络,特别是 长短期记忆(LSTM)网络。这可以归因于这种强大的架构,首先是注意力机制,它使得 Transformer 模型可以以灵活的方式处理单词顺序,不论它们之间有多远,这对每个特定情况都是最优的。此外,这些架构特性的结合使得它能够成功处理涉及理解和生成人类语言以及其他领域的任务。OpenAI 强大的用于语言生成的 GPT 模型也是 Transformer,同样如此的还有 DeepMind 的 AlphaFold 2,这是一个从基因序列预测蛋白质结构的模型。Transformers 能够比其他模型更好地保持在更长序列上的性能,例如循环神经网络。这为它们的成功做出了贡献,但是,Transformer 架构意味着它们只能捕捉到固定输入宽度内的依赖关系。早期的注意力机制随着数据点数量的增加呈二次方增长,使它们无法应用于具有大量输入的设置。已经提出了许多获取效率提升的方法,例如稀疏、低秩的自注意力机制和潜在的瓶颈,仅举几例。其他工作尝试扩展超出固定输入大小的序列,像是 Transformer-XL 这样的架构通过存储已编码句子的隐藏状态来重新引入递归,以便在后续编码下一句时利用它们。GPT 的特殊之处以及其名称的由来在于预训练。让我们看看这些 LLMs 是如何被训练的!
训练大型语言模型(LLM)的第一步是分词。这个过程涉及将单词转换为数字,以便模型能够处理它们,因为LLM是需要数值输入和输出的数学函数。为了执行这种分词,LLM使用独特的分词器。分词器将文本中的单词映射到对应的整数列表上。在训练LLM之前,分词器通常会适配整个训练数据集,然后冻结。一种常见的分词器类型是字节对编码。需要注意的是,分词器不会产生任意的整数。相反,它们输出在特定范围内的整数,从到,其中表示分词器的词汇量。现在,考虑到输出,当 LLM 接收到一段文本时,它主要会产生一个落在范围内的向量。然后将该输出向量通过 softmax 函数传递,得到另一个向量,称为概率向量。由于它的条目为非负且总和为,因此可以将该向量解释为LLM词汇表上的概率分布。另外,需要指出的是,LLM只能基于不超过其上下文窗口的一系列令牌生成令牌。该上下文窗口是指LLM可以使用的最长令牌序列的长度。如果呈现的序列长度超过了该窗口,LLM将需要截断该序列或采用算法修改来处理它。LLM的典型上下文窗口大小可以从约 1000 到 10000 个令牌不等。训练LLM涉及将输入数据进行特定的分词处理,将其馈送到模型中,并生成一个概率分布,该分布覆盖了模型的词汇表。该过程中的具体机制,如 softmax 函数和上下文窗口,有助于促进LLM对输入数据的理解和响应。负对数似然(NLL)和困惑度(PPL)是在训练和评估语言模型的过程中使用的重要指标。NLL是一种在机器学习算法中使用的损失函数,旨在最大化正确预测的概率。较低的NLL表明网络已成功地从训练集中学习了模式,因此它将能够准确地预测训练样本的标签。需要提到的是NLL是一个约束在正数区间内的值。另一方面,困惑度(PPL)是NLL的指数化,提供了一种更直观的方式来理解模型的性能。较小的PPL值表示经过良好训练的网络可以准确预测,而较高的值则表示学习性能不佳。直观地说,我们可以说低困惑度意味着模型对下一个单词的出现不太惊讶。因此,预训练的目标是最小化困惑度,这意味着模型的预测与实际结果更加一致。在比较不同的语言模型时,困惑度通常用作各种任务的基准指标。它提供了有关语言模型性能的信息,其中较低的困惑度表示模型对其预测更有信心。因此,与困惑度较高的其他模型相比,困惑度较低的模型将被认为具有更好的性能。
至少简要讨论架构的选择以及为什么这些模型如此庞大是值得的。在 2020 年的一篇来自 OpenAI 研究人员 Kaplan 等人的论文中,他们讨论了缩放定律和参数选择。有趣的是,他们比较了许多不同的架构选择,并且在其他方面表明,Transformers相对于LSTM作为语言模型在困惑度方面表现优越,这在很大程度上归功于对长上下文的改进使用 - 而这些循环网络在不到 100 个令牌后就停滞了,Transformers通过整个上下文改善。因此,Transformers不仅在训练和推断速度方面表现更好,而且在查看相关上下文时也表现更好。此外,他们发现了数据集大小、模型大小(参数数量)和用于训练的计算量之间的幂律关系,即为了以一定因子提高性能,其中一个因素必须按照因子的幂进行扩展,然而,为了实现最佳性能,这三个因素必须同时进行扩展,以避免产生瓶颈效应。DeepMind的研究人员(Hoffmann 等人,2022 年)分析了LLMs的训练计算量和数据集大小,并得出结论,根据缩放定律,LLMs在计算预算和数据集大小方面都被低估了。他们预测,如果大型模型比较小,并且训练时间更长,大型模型的性能将更好,并且事实上,他们通过将70 亿参数的 Chinchilla 模型与他们的 Gopher 模型进行比较,验证了他们的预测,后者由2800 亿参数组成。最近,该团队发现,以时代为单位的更长的训练或以 petaflops 为单位的更多计算似乎不再改善性能,较小的网络和更高质量的数据集可以提供非常具有竞争力的性能。
对大型语言模型进行调节是指将模型调整为特定任务。调节的不同方法包括微调、提示、指令调节和强化学习:
微调涉及通过监督学习在特定任务上对预训练语言模型进行修改。例如,为了使模型更适合与人类进行聊天,模型被训练使用自然语言指令(指令调节)的任务示例。
提示技术以文本提示形式呈现问题,并期望模型完成。
对于微调,通常,强化学习将监督微调与利用人类反馈的强化学习结合起来,根据人类偏好训练模型。LLM 可以在由 LLM 生成的示例的训练集上进行训练(从一小部分人类生成的示例开始引导)例如由微软研究院 (“Textbooks Are All You Need”, 2023 年 6 月) 提供的 phi-1 的训练集。通过提示技术,将呈现类似问题及其解决方案的文本示例。零-shot 提示不涉及已解决的示例,而少量提示包括少量类似(问题,解决方案)对的示例。这些调节方法不断发展,对各种应用变得更加有效和有用。第八章 提示工程 将进一步探讨提示工程和调节方法。
您可以通过他们的网站或 API 访问 OpenAI 的模型。如果您想在笔记本电脑上尝试其他大型语言模型,开源 LLM 是一个很好的开始地点。这里有很多资源!您可以通过 Hugginface 或其他提供商访问这些模型。您甚至可以下载它们,微调它们,或者 - 如果您感觉非常高级 - 完全训练一个模型。我们将在第九章 LLM 生产中的应用 中更详细地讨论如何使用这些模型。在接下来的部分中,我们将看看稳定扩散以及它是如何工作的。
图像生成模型是一种生成模型,可用于生成图像。图像生成模型是一个强大的工具,可以用来生成逼真和创意的图像。它们仍处于开发的早期阶段,但它们有可能彻底改变我们创建和消费图像的方式。最受欢迎的图像生成模型之一是稳定扩散,另一个是Midjourney。简单来说,这些是根据文本提示创建图像的深度学习模型。2022 年,Google Brain 宣布了两个文本到图像模型的创建,Imagen 和 Parti。
稳定扩散模型是由慕尼黑路德维希·马克西米连大学的计算机视觉组和 Runway 的研究人员开发的深度学习、文本到图像模型。它根据文本描述生成详细的图像,并利用潜在扩散模型架构。该模型的源代码甚至权重都已经公开发布,采用CreativeML OpenRAIL-M License许可证,该许可证“不对再利用、分发、商业化、适应性施加任何限制。”该模型可以在配备了适度 GPU(例如GeForce 40系列)的消费者硬件上运行。稳定扩散是一种使用 Gumbel 分布向图像添加噪声的扩散模型。Gumbel 分布是连续概率分布,通常在机器学习中使用,因为它易于采样,并且具有更稳定的属性。稳定性意味着模型不太可能陷入局部最小值,这可能会发生在其他类型的扩散模型中。该模型由变分自动编码器(VAE)、U-Net和文本编码器组成。VAE有两部分,一个编码器和一个解码器,将原始的高维图像压缩成低维的潜在空间,然后再将其重构回图像空间。潜在空间显著减少了计算复杂度,使得扩散过程更快速。VAE编码器将图像压缩成潜在空间,而U-Net执行从前向扩散到获得潜在表示的去噪。然后VAE解码器生成最终图像。该模型可以灵活地依赖于各种模态,包括文本,并利用交叉注意力机制来合并条件信息。U-Net是一种常见的具有对称编码器-解码器结构的卷积神经网络(CNN)。它通常用于图像分割任务,但在稳定扩散的背景下,它被用于预测图像中的噪声。U-Net 将噪声图像作为输入,并通过一系列卷积层来提取特征和学习表示。这些卷积层通常组织在收缩路径中,降低空间维度同时增加通道数量。一旦收缩路径到达 U-Net 的瓶颈,它就会通过对称扩展路径进行扩展。在扩展路径中,应用转置卷积(也称为上采样或反卷积)逐步上采样空间维度,同时减少通道数量。在扩散过程中,U-Net 的扩展路径获取噪声图像并从前向扩散中重建潜在表示。通过将重建的潜在表示与真实的潜在表示进行比较,U-Net 预测出原始图像中的噪声的估计。这种噪声的预测有助于在逆扩散过程中恢复原始图像。扩散模型通过与物理学中的扩散类似的过程运行。它通过向图像添加噪声进行前向扩散过程,直到图像变得不典型和嘈杂。这个过程类似于墨水滴落到水杯中逐渐扩散。这里的独特之处在于逆扩散过程,在这个过程中,模型试图从嘈杂的、无意义的图像中恢复原始图像。通过逐步从嘈杂图像中减去估计的噪声,最终恢复出类似原始图像的图像。去噪过程在这个图中展示(来源:维基媒体公共资源上的用户 Benlisquare):
图 1.8:在日本创建的欧洲风格城堡,使用了 Stable Diffusion V1-5 AI 扩散模型。仅展示了 40 个生成步骤中的几步。
在图中,您可以逐步看到图像生成的过程,使用 DDIM 采样方法进行 U-Net 去噪处理,该方法反复去除高斯噪声,然后将去噪后的输出解码为像素空间。 Stable Diffusion 是一个利用扩散过程生成图像的深度学习模型,经历了几个清晰的步骤生成从文本提示到图像的过程:
它首先在潜在空间中生成一个随机张量(随机图像),用作我们初始图像的噪声。
噪声预测器(U-Net)接收潜在的嘈杂图像和提供的文本提示,并预测噪声。
然后模型从潜在图像中减去潜在噪声。
步骤 2 和 3 将根据设定的采样步数重复执行,例如,如图所示的 40 次。
最后,VAE的解码器部分将潜在图像转换回像素空间,提供最终的输出图像。
在图像生成模型的训练过程中,使用损失函数来评估生成图像的质量。 其中一个常用的损失函数是均方误差(MSE)损失,它量化了生成图像与目标图像之间的差异。 模型被优化以最小化这种损失,鼓励它生成与期望输出密切相似的图像。模型是在名为LAION-5B的数据集上进行训练的,该数据集源自 Common Crawl 数据,包括数十亿个图像-文本对。 基于语言、分辨率、水印可能性和美学评分对训练数据集进行了分类。 Stable Diffusion 是在该数据集的子集上进行训练的。 模型的训练数据来源广泛,其中有相当一部分来自网站,如Pinterest,WordPress,Blogspot,Flickr,DeviantArt。总的来说,像 Stable Diffusion 和 Midjourney 这样的图像生成模型会将文本提示处理成生成的图像,利用正向和反向扩散过程的概念,并在较低维度的潜在空间中运行以提高效率。到目前为止,Stable Diffusion有两个主要的模型版本,版本 1和2。 让我们看看它们的区别。
稳定扩散 v1 和 v2 在文本处理、训练数据及其结果方面有所不同。在文本处理方面,稳定扩散 v2 使用 OpenClip 进行文本嵌入,而 v1 使用 Open AI 的 CLIP ViT-L/14 进行文本嵌入。OpenClip 比 CLIP 大五倍,这提高了图像质量,也使研究人员在研究和优化模型时更加透明。关于训练数据,稳定扩散 v1.4 是在三个不同的数据集上进行训练的,而 稳定扩散 v2 则是在一个子集上进行训练,该子集是根据一个阈值以上的审美评分和过滤了明确的色情材料(NSFW 过滤器)的 LAION-5B。LAION 5B 数据集是一个大规模数据集,包含 58.5 亿个 CLIP 过滤的图像文本对。数据集中超过 23 亿个样本包含英语,而 22 亿个样本 来自其他 100 多种语言。剩下的十亿个样本不允许某种语言分配,比如名字。数据集的获取管道非常复杂,需要大量处理。它包括对 PB 级 Common Crawl 数据集的分布式处理、图像的分布式下载以及对数据的少量 GPU 节点后处理,从而生成最终的数据集。过滤还删除了重复样本,并将数据集从 500 亿个候选样本修剪到了刚好低于 60 亿个 CLIP 过滤的图像文本对。在结果方面,稳定扩散 v2 更难用于控制风格和生成名人。这种差异可能是由于训练数据的差异造成的,因为 Open AI 的专有数据可能包含更多的艺术作品和名人照片,这些在稳定扩散 v2 的训练数据中没有包含。总而言之,稳定扩散 v2 使用了不同的文本嵌入模型,并在不同的数据子集上进行了训练,导致与 稳定扩散 v1 相比产生了不同的结果。虽然 稳定扩散 v2 可能更透明,更适合长期发展,但 稳定扩散 v1 可能在特定用例方面表现更好,例如控制风格或生成名人,这是由于其训练数据。现在我们将看一下文本到图像用例的模型条件。
条件过程允许这些模型受到输入文本提示或其他输入类型(如深度图或轮廓)的影响,以便在创建相关图像时获得更高的精度。在条件过程中,提示被标记化,每个标记转换为嵌入,一种特定长度的向量,有时是 768 个值。这些嵌入(考虑单词之间的语义关系)然后由文本Transformers处理并馈送到噪声预测器,引导它产生与文本提示相一致的图像。在从文本到图像的过程中,模型使用文本提示生成全新的图像。文本提示被编码为潜在空间,并且扩散过程逐渐添加噪声(由去噪强度控制)以使初始图像演变为输出图像。让我们总结本章!
大型语言模型(LLMs)等生成模型因其在改变多个行业和任务潜力而受到了广泛关注。特别是它们在文本生成和图像合成方面的应用引起了相当大的媒体炒作。领先公司如 OpenAI 正在推动 LLMs 的边界,其 Generative Pre-trained Transformers(GPT)系列因其令人印象深刻的语言生成能力而受到了广泛关注。在本章中,我们讨论了最新突破受到的媒体关注,深度学习和人工智能的最近历史,生成模型,LLMs 和预先训练的生成模型(GPTs)以及支撑它们的理论思想,特别是Transformers架构。我们还讨论了图像的扩散模型以及文本、图像、声音和视频的应用。下一章将探讨生成模型特别是 LLMs 的工具链框架,重点介绍该特定工具的基础知识、实施和使用以优化和增强 LLMs。我认为,在阅读技术书籍时检查是否消化了材料是一个好习惯。我为本章创建了一些问题。
如果你已经阅读并理解了本章,你应该能够回答这些问题:
什么是生成模型?
生成模型存在哪些应用?
什么是大型语言模型(LLM),它的作用是什么?
怎样才能从 LLMs 获得更高的性能?
使得这些模型成为可能的条件是什么?
哪些公司和组织是开发 LLMs 的主要参与者?
什么是Transformers,它由什么组成?
GPT 是什么意思?
稳定扩散是如何工作的?
稳定扩散是如何训练的?
如果你难以回答这些问题,请回到本章的相应部分,确保你已经理解了材料。
packt.link/EarlyAccessCommunity
在本章中,我们讨论了 LLMs 的限制,以及如何将 LLMs 与工具结合起来克服这些挑战,从而构建创新的基于语言的应用程序。有几个强大的框架为开发人员提供了强大的工具,用于快速工程、链式处理、数据检索等。无论您是开发人员、数据科学家,还是对自然语言处理(NLP)或生成式 AI 的技术进展感兴趣,都应该了解这些框架中最强大和流行的 LangChain。LangChain 解决了与使用 LLMs 工作相关的痛点,并提供了一个直观的框架来创建定制的 NLP 解决方案。在 LangChain 中,像 LLMs、网络搜索和数据库查询这样的组件可以链接在一起,这意味着根据数据或任务的需求,按照一定的顺序依次执行不同的任务。通过利用其特性,开发人员可以构建动态的、数据感知的应用程序,利用我们在第一章中讨论的最新技术突破。我们将包括一些用例来说明该框架如何帮助不同领域的企业和组织。LangChain 对代理和内存的支持使得可以构建比仅通过 API 调用语言模型更强大和灵活的各种应用程序。我们将讨论与框架相关的重要概念,如代理、链式处理、行动计划生成和内存。理解这些概念对于理解 LangChain 的工作原理非常重要。主要部分包括:
LLMs 的限制是什么?
什么是 LLM 应用程序?
什么是 LangChain?
LangChain 如何工作?
我们将在本章中首先讨论 LLMs 的限制。
大型语言模型(LLMs)因其生成类似人类文本和理解自然语言的能力而受到重视和普及,这使它们在围绕内容生成、文本分类和摘要的场景中非常有用。虽然 LLMs 提供了令人印象深刻的功能,但它们也存在一些限制,可能会影响其在某些情景中的有效性。了解这些限制在开发应用程序时至关重要。与大型语言模型相关的一些痛点包括:
过时知识:LLMs 无法提供实时或最新的数据,因为它们仅依赖于提供给它们的训练数据。
无法行动:LLMs 不能执行操作或与外部系统交互,限制了它们的功能。例如,它们无法发起网络搜索,实时查询数据库,或使用计算器进行数字乘法。
缺乏上下文和额外信息:LLMs可能难以理解和整合前面的提示或对话中的上下文。它们可能不记得先前提到的细节或未能提供给定提示之外的相关信息。
复杂性和学习曲线:使用大型语言模型开发应用程序通常需要对人工智能概念、复杂算法和 API 有深入的理解。对于可能没有这些领域专业知识的开发人员来说,这可能是一个挑战。
幻觉:LLMs在它们的权重中含有关于世界的许多常规知识。然而,它们可能对某些主题了解不足,产生不真实或不连贯的响应。例如,它们可能产生不存在的信息或提供不准确的细节。
偏见和歧视:根据它们受训数据的不同,LLMs 可能会展现出宗教、意识形态、政治等方面的偏见。
LLMs 没有关于当前事件的信息,因为它们与外部世界没有联系,它们不知道它们没有经过训练的事情,比如截止日期之后的事情。此外,它们在超出训练数据限制的上下文理解方面存在困难。例如,由于这些模型不能执行操作或直接与外部系统交互,它们不会知道天气情况,也无法访问你的文件。在这里,通过 OpenAI ChatGPT 聊天界面询问LangChain的 cutoff day 问题得到了正确的反馈:
图 1.1:ChatGPT - 缺乏最新信息。
在这种情况下,模型能够正确地捕捉到问题并给出正确的反馈。然而,如果我们在GPT-3 playground 中问同样的问题,我们会得到这样的回答:
图 1.2:使用 GPT 3.5 的 OpenAI playground - 幻觉。
在这种情况下,我们可以看到该模型组成术语,并以这个名字发明一个去中心化的平台。这是一种幻觉。需要注意这些问题。访问外部数据,如天气 API、用户喜好或来自网络的相关信息可以解决这个问题,这对于创建个性化和准确的语言驱动应用程序至关重要。LLMs擅长生成文本,但缺乏真正的理解和推理能力。然而,它们可能在逻辑推理方面遇到困难。例如,即使是高级LLMs在高中数学方面表现不佳,不能执行之前未见过的简单数学运算。我们可以通过简单的演示来说明这一点:
图 1.3:ChatGPT 数学求解。
所以,模型对第一个问题给出了正确的回答,但对第二个问题失败了。以防你想知道真正的结果是什么——如果我们使用计算器,我们得到这个结果:
图 1.4:使用计算器进行乘法(BC)。
LLM 没有存储计算结果或者没有在训练数据中经常遇到,以至于无法可靠地记住它并将其编码到其权重中。因此,它无法正确提出解决方案。在这种情况下,基于Transformers的 LLM 不是合适的工具。在部署应用程序之前,LLMs的输出可能需要监视和纠正以确保准确性和偏见和不当语言。Chatbot 领域有偏见的例子并不难找到,只需回想一下 Tay Chatbot,因为种族歧视言论和其他仇外言论而使微软陷入公关灾难。出于所有这些问题,LLMs需要与外部数据源、记忆和能力集成,以便根据提供的数据动态地与其环境交互并做出适当的响应。然而,连接大型语言模型与不同的数据源和计算可能会很棘手,并且需要开发和仔细测试特定的定制工具。因此,使用生成式 AI 构建数据响应型应用程序可能会很复杂,并且可能需要大量的编码和数据处理。最后,直接使用LLM模型可能会具有挑战性和耗时。这从提示工程开始,但更进一步。困难在于导航这些复杂的模型,提供有效的提示,并解析它们的输出。
为了解决上述挑战和限制,LLM可以与其他程序或服务的调用结合使用。主要思想是通过将工具连接在一起,通过使用工具来增强 LLM 的能力。将LLM与其他工具结合到使用专门工具的应用程序中,LLM驱动的应用程序有潜力改变我们的数字世界。通常,这是通过一个或多个提示调用LLMs的链来完成的,但也可以利用其他外部服务(例如 API 或数据源)来完成特定任务。
LLM 应用程序是一种使用大型语言模型(LLMs)如 ChatGPT 来辅助各种任务的应用程序。它通过向语言模型发送提示来生成响应,并且还可以与其他外部服务(如 API 或数据源)集成,以实现特定的目标。
为了说明一个LLM应用程序可能是什么样子,这里有一个非常简单的LLM应用程序,包括一个提示和一个LLM(来源:github.com/srush/MiniChain
):
图 1.5:一个简单的 LLM 应用,将提示与 LLM 结合起来。
LLM 应用对人类具有重要潜力,因为它们增强了我们的能力,简化了流程,并在各个领域提供了宝贵的帮助。以下是一些LLM应用重要的原因:
效率和生产力:LLM 应用自动化任务,实现了重复或复杂操作的更快更准确完成。它们可以以超出人类能力的速度和准确度处理数据处理、分析、模式识别和决策。这提高了数据分析、客户服务、内容生成等领域的效率和生产力。
任务简化:LLM 应用通过将复杂任务拆分为可管理的步骤或提供直观界面来简化复杂任务。这些工具可以自动化复杂的工作流程,使其对更广泛的用户群体可用,而无需专业专业知识。
增强决策能力:LLM 应用提供了先进的分析能力,支持基于数据的决策。它们可以快速分析大量信息,发现人类单独可能无法察觉到的趋势或模式,并为战略规划或问题解决提供有价值的见解。
个性化:AI 驱动的推荐系统根据个人偏好和行为模式个性化用户体验。这些应用程序考虑用户数据,以提供跨多个领域(如电子商务、娱乐和在线平台)的定制建议、推荐和个性化内容。
公司数据的使用,尤其是客户数据,与LLM一起的增长特别明显。然而,我们必须小心并考虑隐私和数据保护的影响。我们永远不应将个人身份可识别(PII)数据输入公共 API 端点。对于这些用例,部署模型到内部基础设施或私有云至关重要,精细调整甚至训练专门的模型提供了重要的改进。这就是我们将在第九章 LLM 应用在生产环境中 中讨论的内容。让我们比较一些可以帮助构建LLM应用的框架。
已开发出LLM 应用框架,提供了专门的工具,可以有效地利用LLM的力量来解决复杂的问题。一些库已经出现,满足了有效地将生成式 AI 模型与其他工具结合起来构建LLM应用的要求。有几个开源框架可用于构建动态的LLM应用。它们在开发尖端的 LLM 应用方面都提供了价值。这张图显示了它们随时间的流行程度(数据来源:github 星历史;star-history.com/
):
图 1.6:Python 中不同框架的流行度比较。我们可以看到每个项目在 github 上随时间的星星数量。
我们可以在图表中看到,Haystack 是比较的框架中最古老的,始于 2020 年初(根据 github 的提交记录)。从 github 上星星的数量来看,它也是最不受欢迎的。Langchain,LlamaIndex(之前称为 GPTIndex),和SuperAGI始于 2022 年末或 2023 年初,它们都在很短的时间内迅速走红,其中LangChain的增长最为惊人。在本书中,我们会看到为什么它的知名度现在爆炸式增长。LlamaIndex注重高级检索,而非LLM应用的更广泛方面。同样,Haystack 专注于创建具有专门设计的组件的大型搜索系统,用于可扩展的信息检索,利用检索器、阅读器和其他数据处理程序,通过预训练模型进行语义索引。LangChain擅长使用代理将LLMs链接在一起,用于委派模型的动作。其用例强调即时优化和上下文感知的信息检索/生成,但使用其 Python 式高度模块化的接口和其庞大的工具集,它是实施复杂业务逻辑的头号工具。SuperAGI具有类似于LangChain的功能。它甚至配备了一个 Marketplace,一个用于工具和代理的存储库。然而,它不如LangChain那样广泛和受支持。我没有包括AutoGPT(以及类似的工具如AutoLlama),这是一个递归应用,用于解决任务,因为它基于人类和 LLM 的反馈,其推理能力与LangChain相比非常有限。因此,它经常陷入逻辑循环,并且经常重复步骤。我也省略了一些集中在提示工程上的库,例如 Promptify。还有其他 LLM 应用程序框架,如 Rust、Javascript、Ruby 和 Java。例如,用 Rust 编写的 Dust 专注于 LLM 应用程序的设计和部署。让我们再看看LangChain。
LangChain 是一个用于开发由语言模型驱动的应用程序的框架,使用户能够更有效地使用 LLM 构建应用程序。它提供了一个标准接口,用于将语言模型连接到其他数据源,以及用于构建可以与其环境交互的代理程序。LangChain 被设计为模块化和可扩展的,使得构建适用于各种领域的复杂应用程序变得容易。LangChain 是开源的,用 Python 编写,虽然存在使用 JavaScript 或 - 更准确地说 - TypeScript(LangChain.js)实现的伴生项目,以及为 Ruby 提供代码执行器的初创项目 Langchain.rb。在本书中,我们关注的是框架的 Python 版本。
LangChain 是一个开源框架,允许 AI 开发者将像 ChatGPT 这样的 LLM 与其他计算和信息源结合起来。
2022 年 10 月由哈里森·查斯(Harrison Chase)在 github 上发起的开源项目,使用 MIT 许可证进行许可,这是一种常见的许可证,允许商业使用、修改、分发和私人使用,但限制了责任和保证。LangChain 还是相当新的,但已经拥有数百个集成和工具。在 discord 聊天服务器上有活跃的讨论,有博客,并且定期在旧金山和伦敦举行聚会。甚至有一个聊天机器人,ChatLangChain,可以回答关于使用 LangChain 和 FastAPI 构建的 LangChain 文档的问题,该文档可以通过文档网站在线获取!该项目已经吸引了数百万美元的风险投资,来自 Sequoia Capital 和 Benchmark 等公司,这些公司曾向 Apple、Cisco、Google、WeWork、Dropbox 等许多成功的公司提供过资金支持。LangChain 附带许多扩展和一个正在发展中的更大的生态系统。如前所述,它已经拥有大量的集成,每周都有许多新的集成。这个截图展示了一些集成(来源:integrations.langchain.com/trending
):
图 1.7:LangChain 集成。
例如,LangChainHub 是一个存储与LangChain相关的工件的仓库,如提示、链和代理,它们组合在一起形成复杂的 LLM 应用程序。受到 HuggingFace Hub 的启发,这是一个模型集合,它旨在成为分享和发现高质量LangChain原语和应用程序的中央资源库。当前,该中心仅包含一系列提示,但——希望——随着社区不断添加到此集合,您可能很快就能找到链和代理。此外,LlamaHub库通过提供更多的数据加载器和读取器来扩展 LangChain 和 LlamaIndex,例如Google Docs、SQL 数据库、PowerPoints、Notion、Slack和Obsidian。LangFlow是一个 UI,它允许通过将侧边栏组件拖放到画布上并将它们连接在一起来创建您的流水线的可执行流程图中连接LangChain组件。这是一个快速实验和原型流水线的方法。如下面的基本聊天流水线的屏幕截图所示:
图 1.8:具有基本聊天的 LangFlow UI。
在浏览器界面的侧边栏(此处未显示)中,您可以看到所有不同的LangChain组件,如零-shot 提示、数据加载器和语言模型包装器。这些流程可以直接导出并加载到LangChain中,或者可以通过 API 调用到本地服务器中调用。LangChain和LangFlow可以在本地部署,例如使用 Chainlit 库,或在包括 Google Cloud 在内的不同平台上。langchain-serve 库有助于将LangChain和LangFlow部署到Jina AI 云上作为 LLM 应用服务,只需一个命令。LangChain提供了一个直观的框架,使开发人员、数据科学家,甚至对 NLP 技术新手来说更容易使用大型语言模型创建应用程序。值得注意的是,LangChain既不是模型也不是提供商,而是一个促进与多种模型无缝交互的框架。使用LangChain,您不需要成为 AI 或复杂算法方面的专家——它简化了流程并减少了学习曲线。
请注意,尽管 LangChain 的主要关注点是 LLMs,这在本书中是我们将要讨论的内容,但也有用于图像生成的集成。
通过具有数据感知性和代理性,LangChain可以轻松集成各种数据源,包括Google Drive、Notion、Wikipedia、Apify Actors等。这种数据感知性使应用程序能够根据用户喜好或来自外部来源的实时信息生成个性化和情境相关的响应。让我们探讨一下LangChain为何重要,然后再看看它的用途。
LangChain 填补了我们在开始时概述的 LLM 的限制以及 LLM 应用程序的出现的许多需求。简而言之,它简化和优化了使用 LLM 开发应用程序的过程。它提供了一种构建比仅通过 API 调用语言模型构建的应用程序更强大和灵活的方式。特别是,LangChain 对代理和记忆的支持使开发人员能够构建以更复杂的方式与其环境交互的应用程序,并且可以随时间存储和重复使用信息。LangChain 可以用于改进各种领域的应用程序的性能和可靠性。在医疗保健领域,它可以用于构建可以回答患者问题并提供医疗建议的聊天机器人。在这种情况下,我们必须非常小心,关注信息的可靠性和保密性方面的监管和道德约束。在金融领域,该框架可用于构建可以分析金融数据并做出预测的工具。在这里,我们必须考虑这些模型的可解释性。在教育领域,LangChain 可用于构建可以帮助学生学习新概念的工具。这可能是最令人兴奋的领域之一,LLMs 可以将完整的教学大纲分解并以定制的交互式会话的形式传递,个性化地适应每个学习者。LangChain 的多功能性使其可以以几种动态方式使用,如构建能够回顾以前交互的虚拟个人助理;提取分析结构化数据集;创建提供与提供实时更新的 API 进行交互的问答应用程序;执行代码理解,从 GitHub 提取交互源代码,大大丰富了开发者体验和性能。使用 LangChain 有几个好处,包括:
灵活性增强:它提供了用于构建强大应用程序的各种工具和功能。此外,其模块化设计使其易于构建可以适应各种领域的复杂应用程序。
性能提升:行动计划生成的支持可以帮助改善应用程序的性能。
可靠性增强:LangChain 对内存的支持可以通过随时间存储和重复使用信息来改善应用程序的可靠性,并且通过访问外部信息,可以减少幻觉。
开源:开放的商业友好许可证以及庞大的开发者和用户社区意味着您可以根据自己的需要进行定制,并依赖广泛的支持。
总之:有很多理由使用 LangChain。然而,我应该提醒,由于 LangChain 还是相当新的,可能还存在一些尚未解决的错误或问题。文档已经相对全面而庞大,但在某些地方还在建设中。
LangChain 赋予了各种 NLP 用例的能力,例如虚拟助手、用于摘要或翻译的内容生成模型、问答系统等。它已经被用来解决各种真实世界的问题。例如,LangChain 被用来构建聊天机器人、问答系统和数据分析工具。它还被用于许多不同的领域,包括医疗保健、金融和教育。你可以使用 LangChain 构建各种各样的应用程序,包括:
聊天机器人:它可以用来构建可以以自然方式与用户交互的聊天机器人。
问答:LangChain 可以用于构建能够回答各种主题问题的问答系统。
数据分析:你可以将其用于自动化数据分析和可视化以提取见解。
代码生成:你可以设置软件对编程助手,帮助解决业务问题。
还有更多!
利用 LangChain,你可以构建利用最近在 自然语言处理(NLP)领域的突破性成果的动态应用程序。通过连接来自多个模块的组件(串联),你可以创建围绕大型语言模型量身定制的独特应用程序。从情感分析到聊天机器人,可能性是巨大的。LangChain 框架的主要价值主张包括以下几个部分:
组件:
模型 I/O:该组件提供了 LLM 包装器,作为连接到语言模型的标准化接口。
提示模板:这允许你管理和优化提示。
内存:索引被用于在链/代理的调用之间存储和重用信息。
代理:代理允许 LLM(Large Language Models)与其环境交互。他们决定要采取的行动并采取行动。
链:这些组件将组件组合在一起以解决任务。它们可以由对语言模型和其他实用程序的调用序列组成。
这里是这些部分的可视化表示:
图 1.9:LangChain 组件。
这些部分有很多需要探讨的地方。让我们稍微详细地讨论一下!虽然LangChain本身不提供模型,但它通过LLM包装器支持与各种不同的语言模型提供者的集成,使应用程序能够与聊天模型以及文本嵌入模型提供者进行交互。支持的提供者包括OpenAI、HuggingFace、Azure 和 Anthropic。提供标准化接口意味着能够轻松地更换模型,以节省费用和能源或获得更好的性能。LangChain的核心构建模块是提示类,它允许用户通过提供简洁的说明或示例与LLMs进行交互。提示工程有助于优化提示以获得最佳的模型性能。模板在输入和可用的提示集合方面提供了灵活性,在各种应用中经过了实战测试。当处理大型文档时,向量存储器发挥作用,其中文档需要被切块以便传递给LLM。文档的这些部分将存储为嵌入,这意味着它们是信息的向量表示。所有这些工具增强了LLMs的知识,并提高了它们在问答和摘要等应用中的性能。有许多用于向量存储的集成。这些包括阿里巴巴云 OpenSearch、AnalyticDB for PostgreSQL、Meta AI 的近似最近邻(ANN)搜索的 Annoy 库、Cassandra、Chroma、ElasticSearch、Facebook AI 相似度搜索(Faiss)、MongoDB Atlas 向量 搜索、作为Postgres的向量相似度搜索的PGVector、Pinecone、Scikit-Learn(SKLearnVectorStore
用于 k 最近邻搜索)等等。还有一些其他模块:
数据连接器和加载器:这些组件提供了连接到外部数据源的接口。
回调:回调用于记录和流式传输任何链的中间步骤。
数据连接器包括用于存储数据和与外部系统交互的实用程序模块,例如网络搜索或数据库,最重要的是数据检索。示例包括 Microsoft Doc(docx)、超文本标记语言(HTML)以及其他常见格式,如 PDF、文本文件、JSON 和 CSV。其他工具将向潜在客户发送电子邮件,向您的关注者发送有趣的双关语,或向您的同事发送 Slack 消息。让我们稍微详细地看一下,代理人可以为什么事情做得好以及它们如何做出决策。
代理人在LangChain中用于控制应用程序的执行流程,以与用户、环境和其他代理人进行交互。代理人可用于决定采取哪些行动,与外部数据源进行交互,并随时间存储和重用信息。代理人可以转移资金、预订航班或与您的客户交谈。
代理是可以在世界中执行动作和任务并与其环境交互的软件实体。在LangChain中,代理获取工具和链并为任务组合它们,并决定使用哪一个。
代理可以与外部世界建立连接。例如,可以利用搜索引擎或向量数据库找到最新和相关的信息。然后可以将此信息提供给模型。这被称为检索增强。通过整合外部信息源,LLMs可以从当前信息和扩展知识中汲取。这是代理如何克服LLMs固有的弱点并通过将工具与模型结合来增强它们的示例。在有关LLMs局限性的部分中,我们已经知道,对于计算而言,简单的计算器胜过了数十亿参数的模型。在这种情况下,代理可以决定将计算传递给计算器或 Python 解释器。我们可以在这里看到一个简单的应用程序,将 OpenAI 语言模型输出连接到 Python 函数:
图 1.10:在 LangFlow 中将 Python 函数可视化的简单 LLM 应用程序。
我们将在第三章的实践中看到这一点,开始使用 LangChain。LangChain中的代理可用于执行各种任务,例如:
搜索信息
调用 API
访问数据库
代码执行
每个代理都可以决定何时使用哪种工具。由于这对于理解LangChain如何工作至关重要,让我们稍微详细地看一下。
每个代理都配备了这些子组件:
工具,即功能组件,
工具包(这些是工具的集合),和
代理执行者
Agent Executor 是一种执行机制,允许在工具之间进行选择。它可以被视为代理和执行环境之间的中介。它接收代理的请求或命令,并将它们转换为可以由底层系统或软件执行的操作。它管理这些操作的执行,并向代理提供反馈或结果。正如我们将看到的,它有不同类型的执行或决策模式。ReAct 模式(由普林斯顿大学和 Google DeepMind 的研究人员于 2023 年 5 月发表的“ReACT:在语言模型中协同推理和行动 ”)意为推理和行动,代理主动将任务分配给适当的工具,为它定制输入,并解析它的输出以解决任务。在这篇论文中,文档存储被用作答案搜索的地方 - 这是作为 ReAct 文档存储模式 实现的。在 LangChain 中,默认情况下,代理遵循 零-shot ReAct 模式 (ZERO_SHOT_REACT_DESCRIPTION
),其中决策仅基于工具的描述。可以通过内存扩展这个机制,以考虑整个对话历史。通过 ReAct,而不是要求 LLM 自动完成文本,您可以提示它进行思考/行动/观察循环来进行回应。 LLM 的提示是逐步响应并将这些步骤与动作相关联。从这些步骤中得到的结果(例如搜索结果)将被传递回 LLM 以进行下一次审议,因为它朝着目标迭代。对于 ZeroShot 模式,提示非常重要,其由前缀、描述工具及其优点的字符串、格式说明和后缀组成:
PREFIX = """Answer the following questions as best you can. You have access to the following tools:"""
FORMAT_INSTRUCTIONS = """Use the following format:
Question: the input question you must answer
Thought: you should always think about what to do
Action: the action to take, should be one of [{tool_names}]
Action Input: the input to the action
Observation: the result of the action
... (this Thought/Action/Action Input/Observation can repeat N times)
Thought: I now know the final answer
Final Answer: the final answer to the original input question"""
SUFFIX = """Begin!
Question: {input}
Thought:{agent_scratchpad}"""
为了将其实践,例如,我们可以询问 LangChain agent executor 和 LangChain execution plan 之间的差异。以下是在 LangChain 中的日志 - 首先将问题发送到语言模型:
I'm not familiar with these terms, so I should search for information about them.
Action: Search
Action Input: "difference between langchain agent executor and langchain execution plan"
Observation: The Concept of Agents in LangChain Action Agents decide an action to take and execute that action one step at a time. They are more conventional and suitable for small tasks. On the other hand, Plan-and-Execute Agents first decide a plan of actions to take, and then execute those actions one at a time.
Thought:Based on the observation, a langchain agent executor is an agent that decides and executes actions one step at a time, while a langchain execution plan is an agent that first decides a plan of actions and then executes them one at a time.
Final Answer: A langchain agent executor executes actions one step at a time, while a langchain execution plan first decides a plan of actions and then executes them.
还有一些已实施的机制。在 2022 年 10 月,华盛顿大学、MosaicAI、Meta AI Research 和 Allen Institute(在论文“测量和缩小语言模型中组合性差距”中)发现,LLMs 在需要组合推理的问题上常常无法给出正确和完整的答案,需要将多个信息组合在一起才能回答问题。self-ask with search 模式将一个问题分解成组件,并调用搜索引擎方法来检索必要的信息以回答问题。LangChain 的用户 nkov 在其 GitHub 上讨论了此强大机制的示例。问题是,穆罕默德·阿里和艾伦·图灵谁活得更久?对话发展如下:
Question: Who lived longer, Muhammad Ali or Alan Turing?
Are follow up questions needed here: Yes.
Follow up: How old was Muhammad Ali when he died?
Intermediate answer: Muhammad Ali was 74 years old when he died.
Follow up: How old was Alan Turing when he died?
Intermediate answer: Alan Turing was 41 years old when he died.
So the final answer is: Muhammad Ali
在每一步中,LLM决定是否需要跟进搜索,并将该信息反馈给LLM。最近,OpenAI 模型(gpt-3.5-turbo-0613,gpt-4-0613)已被微调以检测何时应执行函数调用以及应将哪个输入馈入这些函数。为了使之生效,函数也可以在这些语言模型的 API 调用中描述。这也在LangChain中实现。有一些策略尚未作为LangChain的执行机制实现,包括:
递归批判和改进输出(《语言模型能够解决计算机任务》; Kim 等人,2023 年 6 月)使用LLM作为规划者构建代理,前者在执行动作之前使用LLM生成思路,而后者促使LLM思考学到的经验以改进后续的事件。
思考树(ToT)算法(普林斯顿大学和谷歌 DeepMind 研究人员于 2023 年 5 月发表的 “Tree of Thoughts: Deliberate Problem Solving with Large Language Models”)通过遍历搜索树推进模型推理。基本策略可以是深度优先或广度优先树遍历,但也可以测试和使用许多其他策略,如最佳优先,蒙特卡罗和 A*。这些策略被发现可以显着提高问题解决的成功率。
这些决策可以提前计划或在每个步骤中进行。创建代理可以采取的一系列动作序列来实现目标的过程称为动作计划生成。在动作计划生成中有两种不同类型的代理,可以基于任务所需的动态性来选择:
动作代理在每次迭代中根据所有前一个动作的输出决定下一个动作。
计划和执行代理在开始时决定所有操作步骤的完整计划。然后它们执行所有这些操作步骤,而不更新序列。该实现在LangChain中是受BabyAGI启发而来的。
通常,动作代理更灵活,而计划和执行代理更擅长维护长期目标。如果我们希望尽可能灵活,我们可以为我们的代理指定一个零-shot ReAct机制,在每个回合做出决策。现在让我们来看看链吧!
LangChain的核心思想是LLM和其他组件的组合可共同工作。例如,用户和开发人员可以将多个LLM调用和其他组件组合在序列中,以创建复杂的应用程序,例如聊天重复社交互动,数据提取和数据分析。
在最通用的术语中,链被认为是一系列对组件的调用,其中可以包括其他链。
例如,提示链是一种可以用来改善 LangChain 应用程序性能的技术。 提示链涉及将多个提示链接在一起以自动完成更复杂的响应。简而言之,链和代理都是组件的包装器。 二者都可以通过使它们与外部系统交互并收集最新信息来扩展 LLMs 的功能。 通过将应用程序模块化为链和代理等构建块,可以更容易地调试和维护它们。 链的最常见示例可能是PromptTemplate
,它将格式化的响应传递给语言模型。 链的更有趣的例子包括用于与数学查询相关的LLMMath
和用于查询数据库的SQLDatabaseChain
。 这些被称为实用链,因为它们将语言模型与特定工具结合在一起。 一些链可以做出自主决定。 与代理类似,路由器链可以根据其描述决定使用哪个工具。 RouterChain
可以动态选择要使用的检索系统,例如提示或索引。 LangChain 实现链以确保输出内容不会有毒或违反 OpenAI 的调节规则(OpenAIModerationChain
),或符合道德、法律或自定义原则(ConstitutionalChain
)。 LLMCheckerChain 可以通过验证提供的语句和问题背后的假设来防止错觉,并减少错误响应。 在 2023 年 5 月的《SELF-REFINE: Iterative Refinement with Self-Feedback》一文中,卡耐基梅隆大学、艾伦研究所、华盛顿大学、NVIDIA、加州大学圣地亚哥分校和谷歌研究的研究人员发现,该策略可以将任务性能平均提高约 20%。 让我们来看看记忆策略!
LLMs 和工具在某种意义上是无状态的,它们不会保留任何关于先前响应和对话的信息。 记忆是 LangChain 中的一个关键概念,可以通过存储先前调用语言模型、用户、代理操作环境的状态以及代理的目标的结果来提高 LangChain 应用程序的性能。 这可以帮助减少语言模型需要调用的次数,并确保即使环境发生变化,代理也能继续运行。
记忆 是一种用于随时间存储和重复使用信息的数据结构。
记忆有助于为应用程序提供上下文,并可以使 LLM 输出更连贯和相关。例如,我们可以存储所有对话(ConversationBufferMemory
)或使用缓冲区保留对话中的最后一条消息,使用 ConversationBufferWindowMemory
。记录的消息将在每次调用中包含在模型的历史参数中。但是我们应该注意,这将增加令牌使用量(因此会增加 API 费用)和响应的延迟。这也可能会影响模型的令牌限制。还有一种对话摘要记忆策略,其中 LLM 用于总结对话历史 - 这可能会导致额外的 API 调用费用。关于这些记忆选项有一些令人兴奋的细节。例如,一个有趣的特性是,与 LLM 的对话可以被编码为知识图(ConversationKGMemory
),这可以集成回提示或用于预测回应而不必去 LLM。
知识图是使用图结构数据模型表示数据的表示形式,通常用三元组的形式,主语、谓语和宾语,例如主语=Sam,谓语=loves,宾语=apples。这个图存储有关实体(如人、地点或事件)及其之间的连接的信息。
总之,在LangChain中,记忆可以用来存储各种信息,包括:
先前对语言模型的调用结果
代理正在操作的环境状态
代理正在尝试实现的目标。
现在,我们将看一下我们可以使用的不同工具。
工具是LangChain中可以与模型结合以扩展其能力的组件。LangChain提供类似文档加载器、索引和向量存储的工具,这些工具可以促进LLMs的数据检索和存储。有许多可用的工具,以下只是一些工具的示例:
机器翻译器:语言模型可以使用机器翻译器更好地理解和处理多种语言的文本。这个工具使非翻译专用的语言模型能够理解和回答不同语言的问题。
计算器:语言模型可以利用简单的计算器工具来解决数学问题。计算器支持基本的算术运算,使模型能够准确地解决针对数学问题解决而设计的数据集中的数学查询。
地图:通过与必应地图 API 或类似服务连接,语言模型可以检索位置信息,辅助路线规划,提供驾驶距离计算,并提供附近景点的详细信息。
天气:天气 API 为语言模型提供全球各地城市的实时天气信息。模型可以回答关于当前天气状况或特定地点在不同时间范围内的天气预报的查询。
股票:连接股票市场 API(如 Alpha Vantage)使语言模型能够查询特定股票市场信息,如开盘价、收盘价、最高价、最低价等。
幻灯片:配备幻灯片制作工具的语言模型可以利用诸如 python-pptx 库提供的高级语义或根据给定主题从互联网检索图像来创建幻灯片。这些工具有助于完成各个专业领域中所需的幻灯片制作任务。
表格处理:使用 pandas DataFrame 构建的 API 使语言模型能够在表格上执行数据分析和可视化任务。通过连接这些工具,模型可以为用户提供更简洁自然的处理表格数据的体验。
知识图谱:语言模型可以使用模拟人类查询过程的 API 查询知识图谱,例如查找候选实体或关系,发送 SPARQL 查询,以及检索结果。这些工具有助于基于知识图谱中存储的事实知识回答问题。
搜索引擎:通过利用类似必应搜索的搜索引擎 API,语言模型可以与搜索引擎交互,提取信息并回答实时查询。这些工具增强了模型从网络上收集信息并提供准确响应的能力。
维基百科:配备维基百科搜索工具的语言模型可以在维基百科页面上搜索特定实体,查找页面内的关键词,或对具有相似名称的实体进行消歧义。这些工具能够使用从维基百科检索的内容进行问答任务。
在线购物:将语言模型与在线购物工具连接,使其能够执行诸如搜索商品、加载产品详细信息、选择商品特性、浏览购物页面,并根据特定用户指示做出购买决策的操作。
其他工具包括 AI 绘画,允许语言模型使用 AI 图像生成模型生成图像;3D 模型构建,使用复杂的 3D 渲染引擎使语言模型创建三维(3D)模型;化学性质,通过像 PubChem 这样的 API 协助解决关于化学性质的科学研究;数据库工具,通过自然语言访问数据库数据以执行 SQL 查询和检索结果。这些各种各样的工具为语言模型提供了额外的功能和能力,使其能够执行超越文本处理的任务。通过通过 API 连接这些工具,语言模型可以增强其在诸如翻译、数学问题解决、基于位置的查询、天气预测、股市分析、幻灯片制作、表格处理和分析、图像生成、文本转语音转换等诸多专业任务领域的能力。所有这些工具都可以为我们提供先进的人工智能功能,而且几乎没有限制。我们可以轻松构建定制工具来扩展 LLMs 的能力,正如我们将在下一章节 3 中看到的那样。使用不同的工具扩展了语言模型的应用范围,并使其能够更有效地处理各种各样的现实任务。让我们总结一下!
如今,在智能应用的发展以及创造个性化和有效用户体验方面,准确理解和处理语言至关重要。因此,大型语言模型(LLMs)非常适合赋予应用这种能力。然而,正如我们在本章中讨论的,独立的LLMs有其局限性。如果我们为LLMs提供工具,我们就能克服其中一些限制,并极大增强它们的性能,创造LLM应用程序。这就是 LangChain 的作用所在,它是一个旨在为人工智能开发人员建立代理应用的框架-这些代理由计算实体组成,例如 LLMs 和其他可以自主执行某些任务的工具。我们已经讨论了它的重要概念,首先是代理和链条的概念。总之,LangChain 是一个有价值的开源框架,可简化使用提供者和平台(如 OpenAI 和 Hugging Face 等)的大型语言模型(LLMs)开发应用程序。这个框架在释放生成式人工智能的力量方面提供了巨大价值。在接下来的章节中,我们将通过构建LLM应用程序来进一步完善LangChain的核心原则。通过利用LangChain的能力,开发人员可以充分发挥LLMs的潜力。在第三章,LangChain 入门中,我们将使用LangChain实现我们的第一个应用程序!让我们看看你是否记得本章的一些关键要点!
请查看一下,看看你是否能找到这些问题的答案。如果你对任何问题不确定,我建议你回到本章的相应部分查看一下:
LLMs 的局限性是什么?
LLM 应用有哪些?
LangChain 是什么,为什么应该使用它?
LangChain 的关键特点是什么?
什么是 LangChain 中的代理?
什么是行动计划生成?
什么是链?
LangChain 应用程序为什么需要记忆?
有哪些可用工具?
LangChain 是如何工作的?
packt.link/EarlyAccessCommunity
在本章中,我们将首先设置LangChain和本书所需的库,提供对通用依赖管理工具的说明,例如Docker,Conda,Pip和Poetry。然后,我们将逐个介绍、设置和使用我们可以使用的模型集成,例如OpenAI的Chatgpt,Huggingface 上的模型和 Jina AI,等等。我们将获取 API 密钥令牌,然后进行一个简短的实际示例。这将为我们提供更多关于有效使用LangChain的上下文,并介绍使用它的技巧和窍门。作为最后部分,我们将开发一个LangChain应用程序,这是一个实际示例,它说明了LangChain如何在客户服务的实际业务用例中应用。主要章节包括:
如何设置LangChain?
模型集成
客户服务助手
我们将从在您的计算机上设置LangChain开始本章。
在这本书中,我们谈论的是 LangChain。我们可以通过在终端中简单地输入pip install langchain
来安装 LangChain,但是在这本书中,我们也将在几种不同的用例中使用各种其他工具和集成。为了确保所有的示例和代码片段都能按预期工作,并且不只是在我的机器上能够工作,而是对于任何安装这个的人都能够工作,我提供了设置环境的不同方法。设置 Python 环境有各种不同的方法。在这里,我们描述了四种安装相关依赖的流行方法:Docker,Conda,Pip 和 Poetry。如果您在安装过程中遇到问题,请查阅各自的文档或在本书的 Github 仓库上提出问题。在发布本书时,已经测试了不同的安装方法,然而,事情是会变的,我们将更新 Github 上的 readme,包括可能出现问题的解决方法。请在本书的仓库github.com/benman1/generative_ai_with_langchain
中找到Dockerfile
用于 docker,requirements.txt
用于 pip,pyproject.toml
用于 poetry,以及langchain_ai.yml
文件用于Conda。让我们从 Python 开始设置我们的环境。
在设置 Python 环境和安装相关依赖之前,您通常应该安装 Python 本身。我假设购买本书的大多数人都已经安装了 Python,但是以防万一,让我们来看看。您可以从 python.org 下载适合您操作系统的最新版本,或者使用您平台的包管理器。让我们来看看 MacOS 上,使用 Homebrew 可以这样做:
brew install python
对于 Ubuntu,我们可以使用 apt-get:
sudo apt-get updatesudo apt-get install python3.10
提示:如果您是编程或 Python 新手,请在继续使用 LangChain 和本书中的应用程序之前,建议您先阅读一些初学者级别的教程。
用于交互式尝试数据处理和模型的重要工具是 Jupyter 笔记本和 lab。让我们现在来看一下这个。
Jupyter Notebook 和 JupyterLab 是用于创建、共享和协作计算文档的开源基于 Web 的交互式环境。它们使用户能够在单个文档中编写代码、显示可视化效果并包含解释性文本。两者之间的主要区别在于它们的界面和功能。
Jupyter Notebook 的目标是支持 Julia、Python 和 R 等各种编程语言 - 实际上,项目名称是对这三种语言的参考。Jupyter Notebook 提供了一个简单的用户界面,允许用户以线性布局创建、编辑和运行笔记本。它还支持用于额外功能和定制的扩展。
另一方面,JupyterLab 是 Jupyter Notebook 的增强版本。JupyterLab 于 2018 年推出,提供了一个更强大、更灵活的环境,用于处理笔记本和其他文件类型。它提供了一个模块化、可扩展和可定制的界面,用户可以在其中并排排列多个窗口(例如笔记本、文本编辑器、终端),从而促进更高效的工作流程。
您可以像这样从终端在您的计算机上启动一个笔记本服务器:
jupyter notebook
您应该看到您的浏览器打开一个新选项卡,并显示 Jupyter 笔记本,类似于这样:
图 3.1:带有 LangChain 代理的 Jupyter Notebook。
或者,我们也可以使用 JupyterLab,这是下一代笔记本服务器,它在可用性方面带来了显著的改进。您可以像这样从终端启动 JupyterLab 笔记本服务器:
jupyter lab
我们应该看到类似于这样的东西:
图 3.2:带有 LangChain 代理的 Jupyter Lab。
这两个之一,Jupyter notebook
或 JupyterLab
,都将为您提供一个集成开发环境(IDE),用于处理本书中将介绍的一些代码。在安装 Python 和笔记本或 lab 之后,让我们快速探索依赖管理工具(Docker、Conda、Pip 和 Poetry)之间的差异,并使用它们完全设置我们的环境,用于 LangChain 项目!
在我们探索各种设置 Python 环境以与 LangChain 中的生成模型一起工作的方法之前,了解主要依赖管理工具之间的差异是至关重要的:Docker、Conda、Pip 和 Poetry。这四个工具在软件开发和部署领域被广泛使用。
Docker是一个开源平台,通过容器化提供操作系统级别的虚拟化。它自动化了轻量级、便携式容器内应用程序的部署,在任何安装了 Docker 的系统上都可以一致地运行。
Conda是一个跨平台的包管理器,擅长于从多个通道安装和管理软件包,不局限于 Python。它主要面向数据科学和机器学习项目,并且可以强大地处理复杂依赖树,适用于具有大量依赖项的复杂项目。
Pip 是 Python 中最常用的包管理器,可以轻松安装和管理第三方库。但是,在处理复杂依赖关系时,Pip 存在一定的限制,增加了依赖冲突在包安装过程中出现的风险。
Poetry是一个结合了 Pip 和 Conda 两种最佳特点的新型包管理器。Poetry 具有现代化和直观的界面、强大的依赖关系解决系统以及虚拟环境创建的支持,同时提供了额外的功能,如依赖隔离、锁定文件和版本控制。
Poetry 和 Conda 都简化了虚拟环境管理,而使用 Pip 通常需要利用类似于 virtualenv 的单独工具。在这里推荐使用 Conda 进行安装。我们还提供了一个 pip 的 requirements 文件和使用 poetry 的说明,但在一些情况下可能需要进行一些调整。我们将依次介绍使用这些不同工具的安装过程。对于所有说明,请确保您已经下载了本书的存储库(使用 Github 用户界面)或在计算机上克隆了存储库,并且已切换到项目的根目录。下面是如何在 Github 上找到下载选项:
图 3.3:Github 用户界面(UI)中的下载选项。
如果您是 git 的新手,可以按“Download ZIP”下载并使用您最喜欢的工具解压缩存档。或者,使用 git 克隆该存储库并进入项目目录,可以输入以下命令:
git clone https://github.com/benman1/generative_ai_with_langchain.git
cd generative_ai_with_langchain
现在我们在计算机上拥有了该存储库,让我们从 Docker 开始!
Docker 是一个平台,使开发人员能够自动化应用程序的部署、打包和管理。Docker 使用容器化技术,帮助标准化和隔离环境。使用容器的好处是可以保护你的本地环境免受容器内运行的任何可能不安全的代码的影响。缺点是镜像可能需要时间来构建,并且可能需要大约 10 GB 的存储容量。与其他环境管理工具类似,Docker 很有用,因为你可以为项目创建可重复的环境。你可以使用 Docker 创建包含你项目所需的所有库和工具的环境,并与其他人共享该环境。要开始使用 Docker,请按照以下步骤操作:
在你的机器上安装 Docker。你可以在网页浏览器中访问 Docker 网站,并按照这里的安装说明进行安装:docs.docker.com/get-docker/
在终端中运行以下命令来构建 Docker 镜像(请注意:你需要在项目根目录下才能正常工作)。
docker build -t langchain_ai
这将从 Docker Hub 拉取 continuumio/miniconda3 镜像,并构建镜像。
docker run -it langchain_ai
这将在容器内启动我们的笔记本。我们应该能够从浏览器导航到Jupyter Notebook
。我们可以在这个地址找到它:http://localhost:8080/
接下来让我们看一下 conda。
Conda
允许用户为不同的项目管理多个环境。它与 Python、R 和其他语言一起工作,并通过维护与 Python 库关联的库列表来帮助安装系统库。开始使用 conda 的最佳方法是按照此链接的说明安装 anaconda 或 miniconda:docs.continuum.io/anaconda/install/
尽管从 anaconda 开始,conda
环境占用的磁盘空间比 Docker 少,但完整环境仍然需要大约 2.5 GB。miniconda 设置可能会节省一些磁盘空间。还有一个图形界面工具 conda
,Anaconda Navigator,可以安装在 macOS 和 Windows 上,可以从终端安装任何依赖项以及 conda
工具。让我们继续使用 conda
工具并安装本书的依赖项。要创建一个新环境,请执行以下命令:
conda env create --file langchain_ai.yml
Conda
让我们可以创建具有许多不同库的环境,还可以使用不同版本的 Python。我们在本书中始终使用 Python 3.10。通过运行以下命令激活环境:
conda activate langchain_ai
就是这样,我们完成了。我们可以看到这应该是简单和直接的。你现在可以在环境中启动一个 jupyter notebook
或 jupyter lab
,例如:
jupyter notebook
让我们来看一下 pip,作为conda
的一个替代方案。
Pip
是 Python 的默认包管理器。它允许你轻松安装和管理第三方库。我们可以安装单个库,也可以维护完整的 Python 库列表。如果它尚未包含在你的 Python 发行版中,请按照pip.pypa.io/
上的说明安装 pip。要使用 pip 安装库,可以使用以下命令。例如,要安装 NumPy 库,可以使用以下命令:
pip install numpy
你也可以使用pip
安装库的特定版本。例如,要安装 NumPy 库的 1.0 版本,你可以使用以下命令:
pip install numpy==1.0
为了设置一个完整的环境,我们可以从一个要求列表开始——按照惯例,该列表在一个名为requirements.txt
的文件中。我已经在项目的根目录中包含了这个文件,列出了所有必要的库。你可以使用以下命令安装所有这些库:
pip install -r requirements.txt
请注意,正如前面提到的,Pip 并不处理环境问题。Virtualenv 是一个可以帮助维护环境的工具,比如不同版本的库。我们来快速看一下这个:
# create a new environment myenv:
virtualenv myenv
# activate the myenv environment:
source myenv/bin/activate
# install dependencies or run python, for example:
python
# leave the environment again:
deactivate
Please note that in Windows, the activation command is slightly different – you'd run a shell script:
# activate the myenv environment:
myenv\Scripts\activate.bat
接下来我们来看 Poetry。
Poetry 是 Python 的一个依赖管理工具,可以简化库的安装和版本控制。安装和使用都很简单,我们来看一下。下面是快速的 Poetry 概述:
按照python-poetry.org/
上的说明安装 poetry。
在终端中运行poetry install
(来自项目根目录,如前所述)
该命令将自动创建一个新的环境(如果你尚未创建),并安装所有依赖项。这完成了 Poetry 的设置。现在我们来看模型提供者。
在正式开始生成式人工智能之前,我们需要设置访问诸如大型语言模型(LLMs)或文本到图像模型等模型的权限,以便将它们集成到我们的应用程序中。正如第一章,生成模型是什么中所讨论的那样,有各种各样的LLMs由科技巨头提供,比如OpenAI的GPT-4,Google的BERT和PaLM-2,Meta AI的LLaMA等等。借助LangChain的帮助,我们可以与所有这些模型进行交互,例如通过应用程序编程接口(APIs),或者我们可以调用已在计算机上下载的开源模型。其中一些集成支持文本生成和嵌入。在本章中,我们将专注于文本生成,并在第五章,构建像 ChatGPT 这样的聊天机器人中讨论嵌入,向量数据库和神经搜索。模型托管有许多提供商。目前,OpenAI,Hugging Face,Cohere,Anthropic,Azure,Google Cloud Platform Vertex AI(PaLM-2)和Jina AI是LangChain支持的众多提供商之一,但这个列表一直在不断增加。您可以在integrations.langchain.com/llms
上找到所有支持的LLMs的集成。至于图像模型,主要的开发者包括OpenAI(DALL-E),Midjourney,Inc.(Midjourney),和Stability AI(Stable Diffusion)。LangChain目前没有针对非文本模型的开箱即用处理,但其文档描述了如何使用 Replicate 与 Stable Diffusion 模型进行交互。对于这些提供商的每一个,要调用其应用程序编程接口(API),您首先需要创建一个帐户并获取一个 API 密钥。这对于所有人都是免费的。其中一些甚至无需提供信用卡信息。为了在环境中设置 API 密钥,在 Python 中我们可以这样做:
import os
os.environ["OPENAI_API_KEY"] = "<your token>"
这里 OPENAI_API_KEY
是适用于 OpenAI 的环境密钥。将密钥设置在您的环境中的优点是我们不会将它们包含在我们的代码中。您也可以像这样从终端公开这些变量:
export OPENAI_API_KEY=<your token>
让我们依次了解一些著名的模型提供商。我们将为每个模型提供一个示例用法。我们从一个用于测试的 Fake LLM 开始,这样我们就可以展示基本的概念!
用于测试的 Fake LM。LangChain 文档中有一个示例,用于与 LLMs 的工具使用。您可以直接在 Python 中或笔记本中执行此示例。
from langchain.llms.fake import FakeListLLM
from langchain.agents import load_tools
from langchain.agents import initialize_agent
from langchain.agents import AgentType
tools = load_tools(["python_repl"])
responses = ["Action: Python_REPL\nAction Input: print(2 + 2)", "Final Answer: 4"]
llm = FakeListLLM(responses=responses)
agent = initialize_agent(
tools, llm, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, verbose=True
)
agent.run("whats 2 + 2")
我们连接了一个工具,一个 Python Read-Eval-Print Loop(REPL),根据LLM的输出调用它。Fake List LLM 将给出两个响应,responses
,它们不会根据输入而改变。我们设置了一个代理,它基于我们在第二章介绍的 ReAct 策略做出决策,介绍了 LangChain (ZERO_SHOT_REACT_DESCRIPTION
)。我们用一个文本运行代理,问题是“2 + 2 等于多少”。我们可以观察到假 LLM 输出导致对 Python 解释器的调用,它返回 4. 请注意,操作必须与工具的name
属性匹配,即PythonREPLTool
,它的开头是这样的:
class PythonREPLTool(BaseTool):
"""A tool for running python code in a REPL."""
name = "Python_REPL"
description = (
"A Python shell. Use this to execute python commands. "
"Input should be a valid python command. "
"If you want to see the output of a value, you should print it out "
"with `print(...)`."
)
工具的名称和描述被传递给LLM,然后根据提供的信息做出决定。Python 解释器的输出被传递给 Fake LLM,它忽略观察并返回 4. 很明显,如果我们将第二个响应改为“最终答案:5
”,那么代理的输出就不会对应问题。在接下来的章节中,我们将通过使用真正的LLM而不是假的来使其更有意义。目前,任何人首先想到的提供者之一是 OpenAI。
正如 第一章,生成模型是什么? 中所解释的,OpenAI 是一家美国人工智能研究实验室,是当前生成式人工智能模型领域的市场领导者,特别是 LLM。他们提供一系列具有不同功率水平的模型,适用于不同的任务。我们将在本章中看到如何通过 LangChain 和 OpenAI Python 客户端库与 OpenAI 模型交互。OpenAI 还为文本嵌入模型提供了 Embedding 类。我们将主要用 OpenAI 来进行我们的应用程序。有几个模型可供选择 - 每个模型都有其自己的优点、令牌使用计数和用例。主要的 LLM 模型是 GPT-3.5 和 GPT-4,具有不同的令牌长度。您可以在openai.com/pricing
看到不同模型的定价我们首先需要获得一个 OpenAI API 密钥。为了创建一个 API 密钥,请按照以下步骤操作:
您需要在platform.openai.com/
创建一个登录账号。
设置您的计费信息。
您可以在个人 -> 查看 API 秘钥下看到API 秘钥。
点击创建新的秘钥并给它一个名称。
下面是在 OpenAI 平台上应该是什么样子:
图 3.4: OpenAI API 平台 - 创建新的秘钥。
按下“创建秘钥”后,您应该看到消息“API 秘钥已生成”。您需要将秘钥复制到剪贴板上并保存。我们可以将该秘钥设置为环境变量(OPENAI_API_KEY
),或者每次构造 OpenAI 调用类时都将其作为参数传递。我们可以使用 OpenAI
语言模型类来设置一个LLM以进行交互。让我们创建一个使用这个模型进行计算的代理 - 我省略了前面示例中的导入部分:
from langchain.llms import OpenAI
llm = OpenAI(temperature=0., model="text-davinci-003")
agent = initialize_agent(
tools, llm, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, verbose=True
)
agent.run("whats 4 + 4")
我们应该看到这个输出:
> Entering new chain...
I need to add two numbers
Action: Python_REPL
Action Input: print(4 + 4)
Observation: 8
Thought: I now know the final answer
Final Answer: 4 + 4 = 8
> Finished chain.
'4 + 4 = 8'
这看起来相当有前途,我认为。让我们继续下一个提供商和更多示例!
Hugging Face 是 NLP 领域中非常突出的参与者,在开源和托管解决方案中具有相当大的影响力。该公司是一家美国公司,开发用于构建机器学习应用程序的工具。其员工开发和维护 Transformers Python 库,该库用于自然语言处理任务,包括最先进和流行的模型实现,如 BERT 和 GPT-2,并兼容 PyTorch、TensorFlow 和 JAX。Hugging Face 还提供了 Hugging Face Hub,这是一个托管 Git 的代码库、机器学习模型、数据集和 Web 应用程序的平台,提供超过 120k 个模型、20k 个数据集和 50k 个演示应用程序(Spaces)用于机器学习。这是一个在线平台,人们可以在其中合作和共同构建 ML。这些工具允许用户加载和使用 Hugging Face 的模型、嵌入和数据集。例如,HuggingFaceHub
集成提供了访问不同模型的功能,例如文本生成和文本分类。HuggingFaceEmbeddings
集成允许用户使用句子转换模型。他们在其生态系统中还提供了各种其他库,包括用于数据集处理的 Datasets,用于模型评估的 Evaluate,用于模拟的 Simulate 和用于机器学习演示的 Gradio。除了他们的产品之外,Hugging Face 还参与了诸如 BigScience 研究研讨会之类的倡议,他们在其中发布了一个名为 BLOOM 的开放大型语言模型,具有 1760 亿个参数。他们获得了大量资金,包括 4 亿美元的 B 轮融资和最近由 Coatue 和 Sequoia 领投的 C 轮融资,估值为 20 亿美元。Hugging Face 还与 Graphcore 和 Amazon Web Services 等公司建立了合作关系,优化了他们的产品,并使其能够面向更广泛的客户群体。为了将 Hugging Face 用作您的模型提供商,您可以在 huggingface.co/settings/profile
创建帐户和 API 秘钥。您可以在环境中将令牌设置为 HUGGINGFACEHUB_API_TOKEN
。让我们看一个例子,我们使用了由谷歌开发的开源模型,即 Flan-T5-XXL 模型:
from langchain.llms import HuggingFaceHub
llm = HuggingFaceHub(
model_kwargs={"temperature": 0.5, "max_length": 64},
repo_id="google/flan-t5-xxl"
)
prompt = "In which country is Tokyo?"
completion = llm(prompt)
print(completion)
我们得到了响应“japan
”。LLM 接受文本输入,这里是一个问题,并返回完成。该模型具有许多知识,并可以回答知识问题。我们还可以获得简单的建议:
由 Microsoft 运营的云计算平台 Azure 与 OpenAI 集成,提供强大的语言模型,如 GPT-3、Codex 和 Embeddings。它通过全球数据中心提供访问、管理和开发应用程序和服务,用于编写辅助、摘要、代码生成和语义搜索等用例。它提供的功能包括软件即服务(SaaS)、平台即服务(PaaS)和基础设施即服务(IaaS)。通过 Github 或 Microsoft 凭据进行身份验证,我们可以在azure.microsoft.com/
下创建 Azure 帐户。然后,您可以在Cognitive Services -> Azure OpenAI下创建新的 API 密钥。需要进行一些步骤,个人而言,我觉得这个过程很烦人和沮丧,所以我放弃了。设置完成后,模型应通过 LangChain 中的AzureOpenAI()
LLM 类访问。
通过 Google Cloud Platform(GCP)和 Vertex 的机器学习平台,有许多模型和功能可用。 Google Cloud 提供访问 LLM,如 LaMDA、T5 和 PaLM。Google 还通过基于 LLM 的模型更新了 Google Cloud 自然语言(NL)API,以进行内容分类。这个更新的版本提供了一个广泛的预先训练的分类术语表,以帮助广告定向和基于内容的过滤。NL API 的改进版 v2 分类模型配备有超过 1000 个标签,并支持 11 种语言,具有更高的准确性。对于使用 GCP 的模型,您需要安装 gcloud 命令行界面(CLI)。您可以在这里找到指令:cloud.google.com/sdk/docs/install
然后,您可以使用终端中的此命令进行身份验证并打印密钥令牌:
gcloud auth application-default login
您还需要为您的项目启用 Vertex。如果尚未启用,则应收到一条有用的错误消息,指向正确的网站,在该网站上,您必须单击“启用”。让我们运行一个模型!
from langchain.llms import VertexAI
from langchain import PromptTemplate, LLMChain
template = """Question: {question}
Answer: Let's think step by step."""
prompt = PromptTemplate(template=template, input_variables=["question"])
llm = VertexAI()
llm_chain = LLMChain(prompt=prompt, llm=llm, verbose=True)
question = "What NFL team won the Super Bowl in the year Justin Beiber was born?"
llm_chain.run(question)
我们应该看到以下的响应:
[1m> Entering new chain...[0m
Prompt after formatting:
[[Question: What NFL team won the Super Bowl in the year Justin Beiber was born?
Answer: Let's think step by step.[0m
[1m> Finished chain.[0m
Justin Beiber was born on March 1, 1994\. The Super Bowl in 1994 was won by the San Francisco 49ers.
我已将 verbose 设置为 True,以便查看模型的推理过程。即使名称拼写错误,它也能给出正确的响应,这相当令人印象深刻。一步一步的提示指令是得出正确答案的关键。Vertex 提供了各种模型,例如:
模型 | 描述 | 属性 |
---|---|---|
text-bison | 被细化以遵循自然语言指令 | 最大输入令牌:8,192 最大输出令牌:1,024 训练数据:截至 2023 年 2 月 |
chat-bison | 经过精细调整以用于多轮对话 | 最大输入标记数:4,096 最大输出标记数:1,024 训练数据: 至 2023 年 2 月 最大轮数:2,500 |
code-bison | 经过精细调整,基于自然语言描述生成代码 | 最大输入标记数:4,096 最大输出标记数:2,048 |
codechat-bison | 经过精细调整,用于帮助解决与代码相关的问题的聊天机器人对话 | 最大输入标记数:4,096 最大输出标记数:2,048 |
code-gecko | 经过精细调整以建议代码完成 | 最大输入标记数:2,048 最大输出标记数:64 |
表 3.1:Vertex Generative AI 提供的模型。你可以在cloud.google.com/vertex-ai/docs/generative-ai
查看文档。我们还可以生成代码。让我们看看Code-Bison模型是否能够解决 FizzBuzz,这是入门和中级软件开发人员职位的常见面试问题:
question = """
Given an integer n, return a string array answer (1-indexed) where:
answer[i] == "FizzBuzz" if i is divisible by 3 and 5.
answer[i] == "Fizz" if i is divisible by 3.
answer[i] == "Buzz" if i is divisible by 5.
answer[i] == i (as a string) if none of the above conditions are true.
"""
llm = VertexAI(model_name="code-bison")
llm_chain = LLMChain(prompt=prompt, llm=llm)
print(llm_chain.run(question))
我们得到的响应是:
```python(注:不需要翻译,这是内联代码) answer = [] for i in range(1, n + 1): 如果 i % 3 == 0 and i % 5 == 0: answer.append("FizzBuzz")(注:不需要翻译,这是内联代码) 否则如果 i % 3 == 0: answer.append("Fizz")(注:不需要翻译,这是内联代码) 否则如果 i % 5 == 0: answer.append("Buzz")(注:不需要翻译,这是内联代码) 否则: answer.append(str(i)) return answer ```py
你会雇佣 Code-Bison 加入你的团队吗?
Anthropic 是一家总部位于美国的人工智能初创公司和公共利益公司。它由 OpenAI 的前成员,包括兄弟姐妹 Daniela Amodei 和 Dario Amodei 于 2021 年创立。该公司专注于开发通用人工智能系统和语言模型,并关注负责任的人工智能使用。截至 2023 年 7 月,Anthropic 已经获得了 15 亿美元的资金。他们还参与了类似于 OpenAI’s ChatGPT 的 AI 聊天机器人 Claude 的项目,并对机器学习系统的可解释性进行了研究,特别是变形器架构。不幸的是,Claude 目前(尚)不对普通大众开放。你需要申请访问权限来使用 Claude,并设置ANTHROPIC_API_KEY
环境变量。
Jina AI 由 Han Xiao 和 Xuanbin He 于 2020 年 2 月创立,是一家位于柏林的德国人工智能公司,专门提供基于云原生的神经搜索解决方案,包括文本、图像、音频和视频模型。他们的开源神经搜索生态系统使企业和开发者能够轻松构建可扩展和高可用的神经搜索解决方案,实现高效的信息检索。最近,Jina AI推出了Finetuner,这是一款工具,可以根据特定的用例和需求对任何深度神经网络进行精细调整。该公司通过三轮融资共筹集了 3750 万美元,最近一轮融资是在 2021 年 11 月进行的 A 轮融资。Jina AI的知名投资者包括GGV Capital和Canaan Partners。您可以在cloud.jina.ai/
上设置登录。在平台上,我们可以为不同的用例设置 API,例如图像描述、文本嵌入、图像嵌入、视觉问答、视觉推理、图像放大或中文文本嵌入。在这里,我们正在设置一个视觉问答 API,使用推荐的模型:
图 3.5:Jina AI 中的视觉问答 API。
我们在 Python 和 cURL 中获得了客户端调用的示例,以及一个演示,在演示中我们可以提问。这很酷,不幸的是,这些 API 目前还不透过LangChain可用。我们可以通过将LLM
类子类化为自定义LLM接口来实现这样的调用。让我们再设置另一个聊天机器人,这次由 Jina AI 提供支持。我们可以生成 API 令牌,并将其设置为JINA_AUTH_TOKEN
,网址是chat.jina.ai/api
。我们在这里将从英语翻译成法语:
from langchain.chat_models import JinaChat
from langchain.schema import HumanMessage
chat = JinaChat(temperature=0.)
messages = [
HumanMessage(
content="Translate this sentence from English to French: I love generative AI!"
)
]
chat(messages)
We should be seeing
AIMessage(content="J'adore l'IA générative !", additional_kwargs={}, example=False).
我们可以设置不同的温度,低温会使响应更可预测。在这种情况下,几乎没有什么区别。我们从系统消息开始对话,澄清聊天机器人的目的。让我们问一些食物推荐:
chat = JinaChat(temperature=0.)
chat(
[
SystemMessage(
content="You help a user find a nutritious and tasty food to eat in one word."
),
HumanMessage(
content="I like pasta with cheese, but I need to eat more vegetables, what should I eat?"
)
]
)
我在 Jupyter 中看到这个响应:
AIMessage(content='A tasty and nutritious option could be a vegetable pasta dish. Depending on your taste, you can choose a sauce that complements the vegetables. Try adding broccoli, spinach, bell peppers, and zucchini to your pasta with some grated parmesan cheese on top. This way, you get to enjoy your pasta with cheese while incorporating some veggies into your meal.', additional_kwargs={}, example=False)
它忽略了单字指令,但我实际上很喜欢这些想法。我想我可以试试这个给我的儿子。使用其他聊天机器人时,我得到了 Ratatouille 的建议。了解 LangChain 中 LLM 和 Chat Models 之间的区别很重要。LLM 是文本完成模型,它将字符串提示作为输入,并输出字符串完成。Chat Models 类似于 LLM,但专门设计用于对话。它们将带有发言者标签的聊天消息列表作为输入,并返回聊天消息作为输出。LLM 和 Chat Models 都实现了 Base Language Model 接口,其中包括predict()
和predict_messages()
等方法。这种共享接口允许在应用程序中以及在 Chat 和 LLM 模型之间实现可互换性。
成立于 2019 年,Replicate Inc.是一家总部位于旧金山的初创公司,为 AI 开发人员提供简化流程,他们可以通过利用云技术以最少的代码输入实现和发布 AI 模型。该平台可与私人模型和公共模型一起工作,并实现模型推理和微调。该公司最新的资金来自一轮 A 轮融资,总投资额为 1250 万美元,由安德森·霍洛维茨(Andreessen Horowitz)领投,并参与的还有 Y Combinator、Sequoia 和各种独立投资者。本·菲舍曼(Ben Firshman)是 Docker 开源产品负责人,安德烈亚斯·杨松(Andreas Jansson)是 Spotify 的前机器学习工程师,他们共同创立了 Replicate Inc.,共同期望消除 AI 大规模接受的技术障碍。因此,他们创建了 Cog,这是一个开源工具,可以将机器学习模型打包成标准的生产就绪容器,可以在任何当前操作系统上运行,并自动生成 API。这些容器还可以通过复制平台部署在 GPU 集群上。结果,开发人员可以集中精力进行其他重要任务,从而提高其生产力。您可以使用 Github 凭据在replicate.com/
上进行身份验证,然后点击左上角的用户图标,您将找到 API 令牌 - 只需复制 API 密钥并在您的环境中提供为REPLICATE_API_TOKEN
。为了运行更大的作业,您需要设置您的信用卡(在账单下)。您可以在replicate.com/explore
上找到很多可用的模型。这是一个创建图像的简单示例:
from langchain.llms import Replicate
text2image = Replicate(
model="stability-ai/stable-diffusion:db21e45d3f7023abc2a46ee38a23973f6dce16bb082a930b0c49861f96d1e5bf",
input={"image_dimensions": "512x512"},
)
image_url = text2image("a book cover for a book about creating generative ai applications in Python")
我得到了这张图片:
图 3.7:一本关于使用 Python 进行生成性 AI 的书籍封面 - 稳定扩散。
我认为这是一张不错的图片 - 那是一个创作艺术的 AI 芯片吗?让我们快速看看如何在 Huggingface transformers 或 Llama.cpp 中在本地运行模型!
我们还可以从 LangChain 运行本地模型。让我们先说明一点注意事项:LLM 很大,这意味着它会占用大量空间。如果您有一台老旧的计算机,可以尝试托管服务,例如谷歌 colab。这些将让您在具有大量内存和不同硬件(包括张量处理单元(TPU)或 GPU)的计算机上运行。由于这两种用例运行时间可能会很长或导致 Jupyter 笔记本崩溃,我没有在笔记本中包含此代码或在安装说明中包含相关依赖项。我认为在这里讨论这点仍然值得。在 Hugging Face 的 transformers 库中首先看看如何在本地运行模型,然后再看看这个。
我将快速展示设置和运行流水线的一般步骤:
from transformers import pipeline
import torch
generate_text = pipeline(
model="aisquared/dlite-v1-355m",
torch_dtype=torch.bfloat16,
trust_remote_code=True,
device_map="auto",
framework="pt"
)
generate_text("In this chapter, we'll discuss first steps with generative AI in Python.")
这个模型非常小(3.55 亿个参数),但相对性能不错,并且针对对话进行了调整。请注意,我们在本地模型中不需要 API 令牌!这将下载模型所需的一切,例如分词器和模型权重。然后,我们可以运行文本补全,以便为本章提供一些内容。为了将此流水线插入到 LangChain 代理或链中,我们可以像以前一样使用它:
from langchain import PromptTemplate, LLMChain
template = """Question: {question}
Answer: Let's think step by step."""
prompt = PromptTemplate(template=template, input_variables=["question"])
llm_chain = LLMChain(prompt=prompt, llm=generate_text)
question = "What is electroencephalography?"
print(llm_chain.run(question))
在这个例子中,我们还看到了使用PromptTemplate
的例子,它提供了特定的任务说明。我们接下来来看看 Llama.cpp。
Llama.cpp 是一个基于 Llama 架构的模型执行程序,Llama 是 Meta AI 发布的第一个大型开源模型之一,它衍生出了许多其他模型的开发。请注意,您需要安装一个 md5 校验工具。这在几个 Linux 发行版中默认包含,如 Ubuntu。在 MacOs 上,您可以像这样使用 brew 安装它:
brew install md5sha1sum
我们需要从 Github 下载 llama.cpp 仓库。您可以在线选择 Github 上的下载选项之一进行此操作,或者您可以像这样从终端使用 git 命令:
git clone https://github.com/ggerganov/llama.cpp.git
然后,我们需要安装 Python 要求,我们可以使用 pip 包安装器来完成 - 为了方便起见,让我们也切换到 llama.cpp 项目的根目录:
cd llama.cpp
pip install -r requirements.txt
在安装要求之前,您可能希望创建一个 Python 环境 - 但这取决于您。现在我们需要编译 llama.cpp:
make -C . -j4 # runs make in subdir with 4 processes
我们可以使用 4 个进程并行构建。为了获取 Llama 模型权重,您需要注册并等待来自 Meta 的注册电子邮件。有一些工具,如 pyllama 项目中的 llama 模型下载器,但请注意,它们可能不符合 Meta 的许可条款。您可以从 Hugging Face 下载模型 - 这些模型应该与 llama.cpp 兼容,例如 Vicuna 或 Alpaca。假设您已经将 7B Llama 模型的模型权重下载到 models/7B 目录中。您可以下载更大尺寸的模型,如 13B、30B、65B,但在这里需要注意一点:这些模型在内存和磁盘空间方面都相当大。我们必须将模型转换为 llama.cpp 格式,称为ggml,使用转换脚本。然后,我们可以选择对模型进行量化,以在进行推理时节省内存。量化是指减少用于存储权重的位数。
python3 convert.py models/7B/
./quantize ./models/ggml-model-f16.bin ./models/7B/ggml-model-q4_0.bin q4_0
这个最后的文件比前面的文件小得多,并且在内存中占用的空间也少得多,这意味着你可以在较小的机器上运行它。一旦我们选择了要运行的模型,我们就可以将其集成到代理或链中,例如:
llm = LlamaCpp(
model_path="./ggml-model-q4_0.bin",
verbose=True
)
这结束了对模型提供者的介绍。让我们构建一个应用程序!
在本节中,我们将为客服代理构建一个文本分类应用程序。给定一个文档,比如一封电子邮件,我们希望将其分类到与意图相关的不同类别中,并提取情绪,并提供摘要。客服代理负责回答客户查询,解决问题和处理投诉。他们的工作对于维护客户满意度和忠诚度至关重要,这直接影响公司的声誉和财务成功。生成式人工智能可以在几个方面帮助客服代理:
情感分类:这有助于识别客户情绪,并允许代理进行个性化回应。
摘要:这使代理人能够理解冗长的客户消息的要点,并节省时间。
意图分类:类似于摘要,这有助于预测客户目的,并可以更快地解决问题。
答案建议:这为代理人提供了针对常见查询的建议回复,确保提供准确而一致的消息。
这些结合方法可以帮助客服代理以更准确、及时地回应,最终提高客户满意度。在这里,我们将集中讨论前三点。我们将记录查找,这些可用于第五章中的答案建议,构建类似 ChatGPT 的 Chatbot。LangChain是一个非常灵活的库,拥有许多整合,使我们能够解决各种文本问题。我们可以选择许多不同的整合来执行这些任务。我们可以要求任何 LLM 为我们提供开放领域(任何类别)分类或在多个类别之间选择。特别是由于它们庞大的训练量,LLM 是非常强大的模型,尤其是在给定少量提示时进行情感分析,而不需要任何额外的训练。这是由 Zengzhi Wang 等人在 2023 年 4 月的研究“ChatGPT 是一个好的情感分析器吗?初步研究”中进行的分析。LLM 进行情感分析的提示可能是这样的:
Given this text, what is the sentiment conveyed? Is it positive, neutral, or negative?
Text: {sentence}
Sentiment:
LLM 在摘要方面也非常有效,比以前的模型好得多。不利的一面是这些模型调用比传统的机器学习模型更慢,而且成本更高。如果我们想尝试传统或较小的模型。Cohere 和其他提供商将文本分类和情感分析作为其能力的一部分。例如,NLP Cloud 的模型列表包括 spacy 和许多其他模型:docs.nlpcloud.com/#models-list
许多 Hugging Face 模型都支持这些任务,包括:
文档问题回答
摘要
文本分类
文本-问题-回答
翻译
我们可以在本地执行这些模型,通过在 transformer 中运行pipeline
,在 Hugging Face Hub 服务器上远程执行(HuggingFaceHub
),或者通过load_huggingface_tool()
加载器作为工具。Hugging Face 包含了成千上万个模型,其中许多都针对特定领域进行了精细调整。例如,ProsusAI/finbert
是一个在 Financial PhraseBank 数据集上训练的 BERT 模型,可以分析金融文本的情感。我们也可以使用任何本地模型。对于文本分类,模型往往要小得多,因此这对资源的消耗就不那么大了。最后,文本分类也可以使用嵌入,我们将在第五章,构建类似 ChatGPT 的聊天机器人中讨论。我已经决定尽可能多地使用我在 Hugging Face 上找到的小型模型进行此练习。我们可以通过 huggingface API 列出 Hugging Face Hub 上文本分类的 5 个下载量最高的模型:
def list_most_popular(task: str):
for rank, model in enumerate(
list_models(filter=task, sort="downloads", direction=-1)
):
if rank == 5:
break
print(f"{model.id}, {model.downloads}\n")
list_most_popular("text-classification")
让我们看看列表:
模型 | 下载量 |
---|---|
nlptown/bert-base-multilingual-uncased-sentiment | 5805259 |
SamLowe/roberta-base-go_emotions | 5292490 |
cardiffnlp/twitter-roberta-base-irony | 4427067 |
salesken/query_wellformedness_score | 4380505 |
marieke93/MiniLM-evidence-types | 4370524 |
表 3.2:Hugging Face Hub 上最受欢迎的文本分类模型。我们可以看到这些模型涉及的分类范围比较小,例如情感、情绪、讽刺或者格式良好。让我们使用情感模型。
I've asked GPT-3.5 to put together a long rambling customer email complaining about a coffee machine. You can find the email on GitHub. Let's see what our sentiment model has to say:
from transformers import pipeline
sentiment_model = pipeline(
task="sentiment-analysis",
model="nlptown/bert-base-multilingual-uncased-sentiment"
)
print(sentiment_model(customer_email))
我得到了这个结果:
[{'label': '2 stars', 'score': 0.28999224305152893}]
心情不好。我们继续!让我们看看总结的 5 个最受欢迎的模型:
模型 | 下载量 |
---|---|
t5-base | 2710309 |
t5-small | 1566141 |
facebook/bart-large-cnn | 1150085 |
sshleifer/distilbart-cnn-12-6 | 709344 |
philschmid/bart-large-cnn-samsum | 477902 |
表 3.3:Hugging Face Hub 上最受欢迎的摘要模型。
所有这些模型与大型模型相比占用的空间都比较小。让我们在服务器上远程执行摘要模型:
from langchain import HuggingFaceHub
summarizer = HuggingFaceHub(
repo_id="facebook/bart-large-cnn",
model_kwargs={"temperature":0, "max_length":180}
)
def summarize(llm, text) -> str:
return llm(f"Summarize this: {text}!")
summarize(summarizer, customer_email)
请注意,您需要设置您的HUGGINGFACEHUB_API_TOKEN
才能使此功能正常运行。我看到了这样的摘要:一位顾客的咖啡机不幸损坏,引发了一种深深的不信任和绝望的感觉。 “这令人心碎的疏忽行为粉碎了我对每天完美享用咖啡的梦想,让我情绪低落,难以安慰,” 顾客写道。 "我希望在我写信给你的时候,您能够理解我的情绪纷乱,尽管我内心充满了交织的情感。"他补充道。这个摘要勉强过得去,但并不是非常令人信服。摘要中仍然存在很多冗长的内容。我们可以尝试其他模型,或者直接使用带有总结提示的 LLM。让我们继续吧。知道顾客写了什么样的问题可能会非常有用。让我们问一下VertexAI:
from langchain.llms import VertexAI from langchain import PromptTemplate, LLMChain template = """Given this text, decide what is the issue the customer is concerned about. Valid categories are these: * product issues * delivery problems * missing or late orders * wrong product * cancellation request * refund or exchange * bad support experience * no clear reason to be upset Text: {email} Category: """ prompt = PromptTemplate(template=template, input_variables=["email"]) llm = VertexAI() llm_chain = LLMChain(prompt=prompt, llm=llm, verbose=True) print(llm_chain.run(customer_email))
我们得到了“产品问题”的反馈,这在我这里使用的长电子邮件示例中是正确的。我希望看到我们可以多快地将几个模型和工具组合在一起在 LangChain 中得到实际有用的东西是令人兴奋的。我们可以很容易地在界面上展示给客服代理人看。让我们总结一下。
在本章中,我们介绍了四种安装 LangChain 和本书所需其他库作为环境的不同方法。然后,我们介绍了几个文本和图像模型的提供者。对于每一个,我们解释了如何获取 API 令牌,并演示了如何调用模型。最后,我们为客服的一个使用案例开发了一个文本分类的 LLM 应用程序。通过在 LangChain 中连接各种功能,我们可以帮助减少客服的响应时间,并确保答案准确且简洁。在第三和第四章中,我们将更深入地探讨诸如通过增强检索来进行问题回答的用例,使用像网页搜索和依赖于文档搜索的聊天机器人等工具。让我们看看你是否记得本章的一些关键收获!
请查看,看看你是否能够回答这些问题。如果你对任何问题不确定,我建议你回到本章的相应部分查看一下:
如何安装 LangChain?
列出除 OpenAI 外至少 4 个 LLM 的云服务提供商!
什么是 Jina AI 和 Hugging Face?
如何使用 LangChain 生成图像?
如何在本地机器上而不是通过服务来运行模型?
如何在 LangChain 中执行文本分类?
如何通过生成式人工智能帮助客服代理人工作?
packt.link/EarlyAccessCommunity
在当今快节奏的商业和研究环境中,跟上不断增长的信息量可以是一项艰巨的任务。对于计算机科学和人工智能等领域的工程师和研究人员来说,了解最新发展是至关重要的。然而,阅读和理解大量论文可能是耗时和需大量精力的。这就是自动化发挥作用的地方。在本章中,我们将描述一种自动化总结研究论文和回答问题的方法,使研究人员更容易理解和保持知情。通过利用语言模型和一系列问题,我们将开发的总结可以简洁和简化地概括论文的核心论点、含义和机制。这不仅可以节省研究主题的时间和精力,还可以确保我们能有效地驾驭科学进步的加速步伐。我们还会尝试一下 OpenAI 模型的功能,并将其应用于信息提取。我们将看到它们如何(或者尚未)用于解析简历(CVs)。这个函数语法是特定于 OpenAI 的 API,并有许多应用,然而,LangChain 提供了一个平台,允许创建任何大型语言模型(LLMs)的工具,增强它们的功能。这些工具使 LLMs 能够与 API 交互,访问实时信息,并执行各种任务,如检索搜索、数据库查询、撰写电子邮件,甚至打电话。我们将使用检索增强生成(RAG)实现问答应用程序。这是一种通过向上下文注入相关数据来更新大型语言模型(LLMs)如 GPT 的技术。最后,我们将讨论代理决策的不同策略。我们将实现两种策略,即计划和执行(或计划和解决)和一次性代理,并将它们集成到一种视觉界面中,作为浏览器中的视觉应用程序(使用 Streamlit)以回答问题。主要章节包括:
什么是幻觉?
如何总结长篇文件?
从文件中提取信息
使用工具回答问题
推理策略
我们将从讨论 LLM 可靠性问题开始这一章节。
生成语言模型的快速发展,如 GPT-3、Llama 和 Claude 2,引起了人们对其局限性和潜在风险的关注。一个主要关注点是幻觉,即模型生成的输出是荒谬的、不连贯的或不忠实于提供的输入。幻觉在现实世界的应用中会带来性能和安全风险,比如医疗或机器翻译。幻觉的另一个方面是,LLM 生成包含敏感个人信息的文本,比如电子邮件地址、电话号码和实际地址。这引起了重大的隐私问题,因为它表明语言模型可以从其训练语料库中记忆和恢复这些私人数据,尽管它们不存在于源输入中。
幻觉在 LLM 的背景下指的是生成的文本与预期内容不忠实或荒谬的现象。这个术语类比于心理幻觉,后者涉及感知不存在的东西。在 NLG 中,幻觉文本可能在所提供的上下文中看起来流畅和自然,但缺乏具体性或可验证性。忠实性,即生成的内容保持与源的一致性和真实性,被认为是幻觉的反义词。
内在幻觉发生在生成的输出与源内容相矛盾时,而外在幻觉涉及生成无法通过源材料验证或支持的信息。外在幻觉有时可能包括事实上正确的外部信息,但它们的不可验证性引起了来自事实安全角度的担忧。
努力解决幻觉问题正在进行中,但需要在不同任务之间有一个全面的理解,以开发有效的缓解方法。LLM 中的幻觉可能由各种因素引起:
编码器的不完美表示学习。
错误解码,包括注意到源输入的错误部分和解码策略的选择。
曝光偏差,即训练和推理时间之间的差异。
参数化知识偏差,其中预训练模型优先考虑自己的知识而不是输入,导致生成过多的信息。
幻觉缓解方法可以分为两组:数据相关方法和建模与推理方法(见“自然语言生成中幻觉的调查”,季子威等,2022 年):
数据相关方法:
构建一个忠实的数据集:从零开始构建具有清洁和忠实目标的数据集,或者在确保语义一致性的同时重写真实句子。
自动清理数据:识别和过滤现有语料库中的不相关或矛盾信息,以减少语义噪声。
信息增强:使用外部信息(如检索到的知识或合成数据)来增强输入,以提高语义理解并解决源目标差异。
建模和推理方法:
架构:修改编码器架构以增强语义解释,注意机制以优先处理源信息,解码器结构以减少幻觉并强制实施隐式或显式约束。
训练:结合规划、强化学习(RL)、多任务学习和可控生成技术,通过改善对齐、优化奖励函数和平衡忠实度与多样性来减轻幻觉。
后处理:通过生成-再精化策略来纠正输出中的幻觉,或使用后处理校正方法专门优化结果的忠实度。
幻觉的结果是,自动事实核查可以应用的地方,是错误信息的传播危险或政治目的的滥用。 错误信息,包括误导信息、欺骗性新闻和谣言,对社会构成了重大威胁,尤其是在内容的创建和传播变得更加容易的社交媒体环境中。社会所面临的威胁包括对科学、公共卫生叙事、社会极化和民主进程的不信任。新闻业和档案学已经广泛研究了这个问题,事实核查倡议也在回应中不断增长。致力于事实核查的组织为独立事实核查人员和记者提供培训和资源,从而扩大专家事实核查工作的规模。解决错误信息问题对于维护信息的完整性并通过打击其对社会的有害影响至关重要。在文献中,这种问题被称为文本蕴含,即模型预测文本对之间的方向性真实关系(即如果,通常,一个阅读 t 的人会推断 h 最有可能是真实的)。在本章中,我们将重点关注通过信息增强和后处理进行自动事实核查。事实可以从 LLMs 或使用外部工具中检索。在前一种情况下,预训练语言模型可以取代知识库和检索模块的位置,利用其广泛的知识来回答开放领域问题,并使用提示来检索特定事实。我们可以在这个图表中看到这个总体观念(来源:https://github.com/Cartus/Automated-Fact-Checking-Resources by Zhijiang Guo):
图 4.1:三个阶段的自动事实核查流程。
我们可以区分三个阶段:
主张检测 - 确定需要验证的主张
检索 - 检索证据以查找支持或反驳主张的来源
主张验证 - 根据证据评估主张的真实性
从 2018 年开始,从 24 层 BERT-Large 开始,语言模型已经在诸如维基百科之类的大型知识库上进行预训练,因此能够回答来自维基百科或因为其训练集越来越包括其他来源 - 互联网、教科书、arxiv 和 Github 的知识问题。使用简单的掩蔽提示即可查询事实。例如,为了回答问题“微软的总部在哪里?”,该问题将被重写为“微软的总部在[MASK]”,然后输入到语言模型中获取答案。在这种方法中,最终激活函数引起的东西有趣的是,如果一个没有接收源文本(无条件 LLM)的 LLM 产生比接收源文本(有条件 LLM)的 LLM 更小的生成目标损失,这表明所生成的令牌具有幻觉性(Fillippova,2020)。幻象令牌占目标令牌总数的比率可以作为所生成输出中幻象程度的度量标准。在 LangChain 中,我们有一个链可用于事实检查和提示链,其中模型积极质疑陈述中涉及的假设。在这种自我检查的链中,LLMCheckerChain
,模型被提示按顺序进行多次操作,首先将假设明确表达出来,看起来像这样:
Here’s a statement: {statement}\nMake a bullet point list of the assumptions you made when producing the above statement.\n
请注意,这是一个字符串模板,其中花括号中的元素将被变量替换。接下来,这些假设将被反馈给模型,以便通过这样的提示逐个检查它们:
Here is a bullet point list of assertions:
{assertions}
For each assertion, determine whether it is true or false. If it is false, explain why.\n\n
最后,模型被要求做出最终判断:
In light of the above facts, how would you answer the question '{question}'
LLMCheckerChain
可以自己完成所有这些操作,正如这个例子所示:
from langchain.chains import LLMCheckerChain
from langchain.llms import OpenAI
llm = OpenAI(temperature=0.7)
text = "What type of mammal lays the biggest eggs?"
checker_chain = LLMCheckerChain.from_llm(llm, verbose=True)
checker_chain.run(text)
模型可以返回不同的结果给该问题,其中的一些是错误的,而一些会被正确地标识为假的。当我尝试这个东西时,我得到了像蓝鲸、北美海狸或已灭绝的巨型恐鸟之类的结果。我认为这是正确的答案:
Monotremes, a type of mammal found in Australia and parts of New Guinea, lay the largest eggs in the mammalian world. The eggs of the American echidna (spiny anteater) can grow as large as 10 cm in length, and dunnarts (mouse-sized marsupials found in Australia) can have eggs that exceed 5 cm in length.
• Monotremes can be found in Australia and New Guinea
• The largest eggs in the mammalian world are laid by monotremes
• The American echidna lays eggs that can grow to 10 cm in length
• Dunnarts lay eggs that can exceed 5 cm in length
• Monotremes can be found in Australia and New Guinea – True
• The largest eggs in the mammalian world are laid by monotremes – True
• The American echidna lays eggs that can grow to 10 cm in length – False, the American echidna lays eggs that are usually between 1 to 4 cm in length.
• Dunnarts lay eggs that can exceed 5 cm in length – False, dunnarts lay eggs that are typically between 2 to 3 cm in length.
The largest eggs in the mammalian world are laid by monotremes, which can be found in Australia and New Guinea. Monotreme eggs can grow to 10 cm in length.
> Finished chain.
因此,虽然这不能保证正确的答案,但它可以阻止一些错误的结果。至于扩展检索(或 RAG),我们在本章的问题回答部分中已经看到了这种方法。事实检查方法涉及将声明分解为更小的可检查查询,这些查询可以被构造为问题回答任务。专为搜索领域数据集而设计的工具可以帮助事实检查员有效地查找证据。现成的搜索引擎如 Google 和 Bing 也可以检索涵盖主题和证据的相关内容,以准确捕捉声明的真实性。在下一节中,我们将应用这种方法来返回基于网络搜索和其他工具的结果。在下一节中,我们将实现一个链来总结文档。我们可以问任何问题以从这些文档中得到答案。
在本节中,我们将讨论自动化长文本和研究论文摘要的过程。在当今快节奏的商业和研究环境中,跟上不断增长的信息量可能是一项令人望而生畏的任务。对于计算机科学和人工智能等领域的工程师和研究人员,保持最新发展的状态至关重要。然而,阅读和理解大量的论文可能是耗时费力的。这就是自动化发挥作用的地方。作为工程师,我们的愿望是构建和创新,通过创建管道和进程来自动化避免重复的任务。这种方法经常被误解为懒惰,其实它允许工程师集中精力解决更复杂的挑战,并更有效地利用他们的技能。在这里,我们将搭建一个自动化工具,可以快速概括长文本的内容,以更易消化的格式呈现。此工具旨在帮助研究人员跟上每天发表的论文数量,特别是在人工智能等快速发展的领域。通过自动化摘要过程,研究人员可以节省时间和精力,同时也确保他们了解其领域的最新发展。该工具将基于 LangChain,并利用大型语言模型(LLMs)以更简明和简化的方式概述论文的核心主张、含义和机制。它还可以回答有关论文的特定问题,使其成为文献综述和加速科学研究的有价值资源。作者计划进一步开发该工具,以便自动处理多个文档并针对特定研究领域进行定制。总体而言,这种方法旨在通过提供更高效、更易于访问的方式来让研究人员受益于最新研究。LangChain 支持使用 LLMs 处理文档的 Map Reduce 方法,以实现文档的高效处理和分析。当阅读大型文本并将其拆分为适合 LLM 令牌上下文长度的文档(块)时,可以将链逐个应用于每个文档,然后将输出组合成一个文档。核心主张是 Map Reduce 过程涉及两个步骤:
映射步骤——将 LLM 链分别应用于每个文档,将输出视为新文档,然后
减少步骤——所有新文档都将传递到一个独立的组合文档链中,以获取单个输出。
图中所示:
图 4.2:LangChain 中的映射减少链(来源:LangChain 文档)。
这种方法的影响是它允许对文档进行并行处理,并且能够使用 LLM 进行推理、生成或分析单个文档以及组合它们的输出。该过程的机制涉及压缩或折叠映射文档,以确保它们适合于组合文档链,这也可能涉及到利用 LLM。如果需要,压缩步骤可以递归执行。下面是加载 PDF 文档并对其进行摘要的简单示例:
from langchain.chains.summarize import load_summarize_chain
from langchain import OpenAI
from langchain.document_loaders import PyPDFLoader
pdf_loader = PyPDFLoader(pdf_file_path)
docs = pdf_loader.load_and_split()
llm = OpenAI()
chain = load_summarize_chain(llm, chain_type="map_reduce")
chain.run(docs)
变量pdf_file_path
是一个包含 PDF 文件路径的字符串。映射和减少步骤的默认提示是这样的:
Write a concise summary of the following:
{text}
CONCISE SUMMARY:
我们可以为每一步指定任何提示。在为本章开发的文本摘要应用中,我们可以看到如何传递其他提示。在 LangChainHub 上,我们可以看到 qa-with sources 提示,它采用了这样一个 reduce/combine 提示:
Given the following extracted parts of a long document and a question, create a final answer with references (\"SOURCES\"). \nIf you don't know the answer, just say that you don't know. Don't try to make up an answer.\nALWAYS return a \"SOURCES\" part in your answer.\n\nQUESTION: {question}\n=========\nContent: {text}
在这个提示中,我们会提出一个具体的问题,但同样我们也可以给 LLM 一个更抽象的指令,提取假设和含义。文本将会是从映射步骤中得到的摘要。这样的指令会有助于避免幻觉。其他指令的示例可能是将文档翻译成不同的语言或以某种风格重新表述。一旦我们开始做很多调用,特别是在映射步骤中,我们会看到成本增加。我们在做很多调用,并且总共使用了很多标记。是时候给这个问题一些关注了!
在使用模型时,特别是在长循环中,比如使用映射操作时,跟踪标记使用情况并了解你花费了多少钱是很重要的。对于任何严肃的生成式人工智能使用,我们需要了解不同语言模型的能力、定价选项和用例。OpenAI 提供了不同的模型,包括 GPT-4、ChatGPT 和 InstructGPT,以满足各种自然语言处理需求。GPT-4 是一个强大的语言模型,适用于解决自然语言处理中的复杂问题。它提供了基于使用的标记大小和数量的灵活定价选项。ChatGPT 模型,如 GPT-3.5-Turbo,专注于对话应用,如聊天机器人和虚拟助手。它们在生成准确和流畅的响应方面表现出色。ChatGPT 模型的定价基于使用的标记数量。InstructGPT 模型专为单轮指令遵循而设计,并针对快速和准确的响应生成进行了优化。InstructGPT 家族中的不同模型,如 Ada 和 Davinci,提供不同水平的速度和功率。Ada 是最快的模型,适用于速度至关重要的应用,而 Davinci 是最强大的模型,能够处理复杂的指令。InstructGPT 模型的定价取决于模型的能力,从像 Ada 这样的低成本选项到像 Davinci 这样的更昂贵的选项。OpenAI 的 DALL·E、Whisper 和 API 服务用于图像生成、语音转录、翻译和访问语言模型。DALL·E 是一种 AI 驱动的图像生成模型,可以无缝集成到应用程序中,用于生成和编辑新颖的图像和艺术品。OpenAI 提供了三个分辨率层次,允许用户选择他们所需的细节级别。更高的分辨率提供更复杂和更详细的图像,而较低的分辨率提供更抽象的表示。每张图像的价格根据分辨率而变化。Whisper 是一个能够将语音转录为文本并将多种语言翻译成英语的 AI 工具。它有助于捕捉对话,促进交流,并提高跨语言理解。使用 Whisper 的成本基于每分钟的费率。OpenAI 的 API 提供了对强大语言模型的访问,如 GPT-3,使开发人员能够创建高级应用程序。当注册 API 时,用户会获得一个初始的标记使用限制,表示在特定时间范围内与语言模型进行交互的标记数量。随着用户的记录和使用增加,OpenAI 可能会增加标记使用限制,为模型提供更多访问权限。如果用户需要更多标记来支持其应用程序,他们也可以请求配额增加。我们可以通过连接到 OpenAI 回调来跟踪 OpenAI 模型中的标记使用:
with get_openai_callback() as cb:
response = llm_chain.predict(text=”Complete this text!”)
print(f"Total Tokens: {cb.total_tokens}")
print(f"Prompt Tokens: {cb.prompt_tokens}")
print(f"Completion Tokens: {cb.completion_tokens}")
print(f"Total Cost (USD): ${cb.total_cost}")
在这个例子中,带有 llm_chain
的那一行可以是任何 OpenAI 模型的用法。 我们应该看到成本和令牌的输出。还有其他两种获得令牌使用情况的方法。 除了 OpenAI 回调外,llm
类的 generate()
方法返回 LLMResult
类型的响应而不是字符串。 这包括令牌使用情况和完成原因,例如 (来自 LangChain 文档):
input_list = [
{"product": "socks"},
{"product": "computer"},
{"product": "shoes"}
]
llm_chain.generate(input_list)
结果看起来像这样:
LLMResult(generations=[[Generation(text='\n\nSocktastic!', generation_info={'finish_reason': 'stop', 'logprobs': None})], [Generation(text='\n\nTechCore Solutions.', generation_info={'finish_reason': 'stop', 'logprobs': None})], [Generation(text='\n\nFootwear Factory.', generation_info={'finish_reason': 'stop', 'logprobs': None})]], llm_output={'token_usage': {'prompt_tokens': 36, 'total_tokens': 55, 'completion_tokens': 19}, 'model_name': 'text-davinci-003'})
最后,OpenAI API 中的聊天完成响应格式包括一个使用对象,其中包含令牌信息,例如可能看起来像这样的 (节选):
{
"model": "gpt-3.5-turbo-0613",
"object": "chat.completion",
"usage": {
"completion_tokens": 17,
"prompt_tokens": 57,
"total_tokens": 74
}
}
接下来,我们将看一下如何使用 OpenAI 函数和 LangChain 从文档中提取特定的信息。
2023 年 6 月,OpenAI 宣布更新 OpenAI API,包括对函数调用的新功能,这将提供增强的功能。 开发人员现在可以向 gpt-4-0613 和 gpt-3.5-turbo-0613 模型描述功能,并让模型智能生成包含调用这些功能的参数的 JSON 对象。此功能旨在增强 GPT 模型与外部工具和 API 之间的连接,提供了一种可靠的方式来从模型中检索结构化数据。函数调用使开发人员能够创建使用外部工具或 OpenAI 插件回答问题的聊天机器人。 它还允许将自然语言查询转换为 API 调用或数据库查询,并从文本中提取结构化数据。 更新的机制涉及使用新的 API 参数,即 /v1/chat/completions
终点的 functions
。 通过名称、描述、参数和要调用的功能本身对来定义函数。开发人员可以使用 JSON Schema 向模型描述功能,并指定要调用的所需功能。在 LangChain 中,我们可以使用 OpenAI 中的这些函数调用进行信息提取或调用插件。 在信息提取中,我们可以使用 OpenAI 聊天模型中的提取链来指定实体及其属性从文本和文档中提取实体及其属性。 例如,这有助于识别文本中提到的人。 通过使用 OpenAI 函数参数并指定模式,可以确保模型输出所需的实体和属性及其适当的类型。这种方法的意义在于它允许通过定义具有所需属性和类型的模式精确提取实体。 它还能够指定哪些属性是必需的,哪些是可选的。模式的默认格式是字典,但我们还可以在 Pydantic 中定义属性及其类型,以控制和灵活提取过程。这是一个期望的用于 Curricum Vitae(简历)中信息的模式示例:
from typing import Optional from pydantic import BaseModel class Experience(BaseModel): start_date: Optional[str] end_date: Optional[str] description: Optional[str] class Study(Experience): degree: Optional[str] university: Optional[str] country: Optional[str] grade: Optional[str] class WorkExperience(Experience): company: str job_title: str class Resume(BaseModel): first_name: str last_name: str linkedin_url: Optional[str] email_address: Optional[str] nationality: Optional[str] skill: Optional[str] study: Optional[Study] work_experience: Optional[WorkExperience] hobby: Optional[str]
我们可以利用它来从简历中提取信息。这是来自github.com/xitanggg/open-resume
的示例简历。
图 4.3: 示例简历摘录
我们将尝试从这份简历中解析信息。利用 LangChain 中的create_extraction_chain_pydantic()
函数,我们可以将我们的模式作为输入,并且输出将是一个符合该模式的实例化对象。简而言之,我们可以尝试以下代码片段:
from langchain.chains import create_extraction_chain_pydantic
from langchain.chat_models import ChatOpenAI
from langchain.document_loaders import PyPDFLoader
pdf_loader = PyPDFLoader(pdf_file_path)
docs = pdf_loader.load_and_split()
# please note that function calling is not enabled for all models!
llm = ChatOpenAI(model_name="gpt-3.5-turbo-0613")
chain = create_extraction_chain_pydantic(pydantic_schema=Resume, llm=llm)
return chain.run(docs)
我们应该会得到这样的输出:
[Resume(first_name='John', last_name='Doe', linkedin_url='linkedin.com/in/john-doe', email_address='hello@openresume.com', nationality=None, skill='React', study=None, work_experience=WorkExperience(start_date='May 2023', end_date='Present', description='Lead a cross-functional team of 5 engineers in developing a search bar, which enables thousands of daily active users to search content across the entire platform. Create stunning home page product demo animations that drives up sign up rate by 20%. Write clean code that is modular and easy to maintain while ensuring 100% test coverage.', company='ABC Company', job_title='Software Engineer'), hobby=None)]
它离完美还差得远 - 只有一个工作经验被解析出来。但考虑到我们迄今为止所付出的少量工作,这是个不错的开始。请在 Github 上查看完整示例。我们可以添加更多功能,例如猜测个性或领导能力。OpenAI 以特定语法将这些函数调用注入系统消息中,他们的模型已经针对此进行了优化。这意味着函数计入上下文限制,并相应地计入输入标记。LangChain 本身具有将函数调用注入为提示的功能。这意味着我们可以在 LLM 应用程序中使用除 OpenAI 之外的模型提供者进行函数调用。我们现在将着眼于这一点,并将其构建成一个交互式 Web 应用程序与 Streamlit。
LLMs 是在一般语料库数据上进行训练的,可能对需要特定领域知识的任务效果不佳。单独使用 LLMs 不能与环境交互,并访问外部数据源,然而,LangChain 提供了一个平台,用于创建访问实时信息并执行诸如天气预报、预订、建议菜谱和管理任务等任务的工具。代理和链中的工具允许开发由 LLMs 驱动的数据感知和代理性应用程序,并且为解决问题的各种方法提供了广泛的应用范围,扩展了它们的用例并使它们更加多样和强大。工具的一个重要方面是它们可以在特定领域内或处理特定的输入。例如,LLM 缺乏固有的数学能力。然而,像计算器这样的数学工具可以接受数学表达式或方程作为输入并计算结果。LLM 和这样的数学工具结合起来进行计算并提供准确答案。通常,这种检索方法和 LLMs 的组合被称为检索增强生成(RAG),并通过从外部源中检索相关数据并将其注入到背景中来解决 LLMs 的局限性。这些检索的数据作为增强提示给 LLMs 的附加信息。通过通过 RAG 用特定用例的信息根植 LLMs,改善了响应的质量和准确性。通过检索相关数据,RAG 有助于减少 LLMs 的错觉响应。例如,将 LLM 用于医疗应用程序,可以在推断期间从外部来源检索相关医学信息,如医学文献或数据库。然后,这些检索的数据可以被合并到上下文中,以增强生成的响应,并确保它们与特定领域的知识一致和准确。在这种情况下,实施 RAG 的好处是双重的。首先,即使模型的训练数据截止日期过去,它也允许将最新信息纳入响应中。这确保用户甚至对于最新事件或不断发展的主题都可以收到准确和相关的信息。其次,RAG 通过利用来自新闻文章或与特定主题相关的网站等来源的具体上下文,增强了 ChatGPT 提供更详细和上下文的答案的能力。通过检索特定上下文的信息,响应将更加准确。
RAG(检索增强生成)通过从数据源中检索信息,以补充提供给语言模型的提示,为模型提供所需的背景信息以生成准确的响应。RAG 涉及几个步骤:
提示: 用户向聊天机器人提供提示,描述他们对输出的期望。
研究:执行上下文搜索,并从各种数据源中检索相关信息。这可能涉及查询数据库,基于关键字搜索索引文档,或调用 API 从外部源检索数据。
更新资源:检索到的上下文被注入到原始提示中,通过提供访问事实数据,增强提示,提高准确性。
叙述:基于这个增强输入,LLM 生成包含事实正确信息的响应,并将其发送回聊天机器人以传递给用户。
因此,通过结合外部数据源并将相关上下文注入提示中,RAG 增强了 LLM 生成准确、最新并与特定领域或主题对齐的响应的能力。图示了通过工具和推理增强 LLM 的过程(来源:https://github.com/billxbf/ReWOO,由 Binfeng Xu 等人于 2023 年 5 月编写的论文 “Decoupling Reasoning from Observations for Efficient Augmented Language Models Resources” 的实现):
图 4.4:工具增强的语言模型范例,利用语言模型的可预见推理能力来提高系统参数和提示效率
让我们看看这个实例!LangChain 中有很多可用的工具,而且 - 如果这还不够 - 自己开发工具也不难。让我们设置一个带有几个工具的代理:
from langchain.agents import (
AgentExecutor, AgentType, initialize_agent, load_tools
)
from langchain.chat_models import ChatOpenAI
def load_agent() -> AgentExecutor:
llm = ChatOpenAI(temperature=0, streaming=True)
# DuckDuckGoSearchRun, wolfram alpha, arxiv search, wikipedia
# TODO: try wolfram-alpha!
tools = load_tools(
tool_names=["ddg-search", "wolfram-alpha", "arxiv", "wikipedia"],
llm=llm
)
return initialize_agent(
tools=tools, llm=llm, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, verbose=True
)
了解一个重要的细节是 AgentExecutor
是一个链,因此 - 如果我们想的话 - 我们可以将其集成到更大的链中。我们可以使用不同的语法初始化这个链,就像这样:
return MRKLChain.from_chains(llm, chains, verbose=True)
在这种语法中,我们将工具传递为链配置。MRKL 代表模块化推理、知识和语言。零射击代理是 MRKL 框架中最通用的行动代理。请注意 ChatOpenAI
构造函数中的参数 streaming
设置为 True
。这样做可以提供更好的使用体验,因为它意味着文本响应将随着其到来而更新,而不是一次性完成所有文本。目前只有 OpenAI、ChatOpenAI 和 ChatAnthropic 实现支持流式处理。所有提到的工具都有其特定的用途,这是描述的一部分,传递给语言模型。这些工具是插入到代理中的:
DuckDuckGo - 一个注重隐私的搜索引擎;它的一个额外优势是不需要开发者注册。
Wolfram Alpha - 一个结合了自然语言理解和数学能力的集成,用于像“2x+5 = -3x + 7?”这样的问题。
Arxiv - 搜索学术预印出版物;这对于研究导向的问题很有用。
Wikipedia - 有关任何有重要名声的实体的问题
请注意,要使用 Wolfram Alpha,您必须设置一个帐户,并设置 WOLFRAM_ALPHA_APPID
环境变量,其中包含您在 developer.wolframalpha.com/
创建的开发者令牌。除了 DuckDuckGo 之外,LangChain 还集成了很多其他搜索工具,可以利用 Google 或 Bing 搜索引擎,或者使用元搜索引擎。还有一个用于天气信息的 Open-Meteo 集成,但是这些信息也可以通过搜索获得。让我们将我们的 agent 设计为一个 streamlit 应用。
Streamlit是一个面向机器学习和数据科学团队的开源应用程序框架。它允许用户使用 Python 在几分钟内创建美观的网络应用程序。
让我们使用我们刚刚定义的load_agent()
函数编写代码:
import streamlit as st
from langchain.callbacks import StreamlitCallbackHandler
chain = load_agent()
st_callback = StreamlitCallbackHandler(st.container())
if prompt := st.chat_input():
st.chat_message("user").write(prompt)
with st.chat_message("assistant"):
st_callback = StreamlitCallbackHandler(st.container())
response = chain.run(prompt, callbacks=[st_callback])
st.write(response)
请注意,我们在调用链中使用回调处理程序,这意味着我们将在返回结果时立即看到响应。我们可以在终端上像这样本地启动应用:
PYTHONPATH=. streamlit run question_answering/app.py
Streamlit 应用程序的部署可以在本地或服务器上进行。或者,您可以在 Streamlit Community Cloud 上或 Hugging Face Spaces 上部署此应用程序。
对于Streamlit Community Cloud,请执行以下操作:
1. 创建一个 Github 存储库
2. 前往 Streamlit Community Cloud,点击“New app”,然后选择新的存储库
3. 点击“部署!”
至于Hugging Face Spaces,它的工作原理如下:
1. 创建一个 Github 仓库
2. 在 https://huggingface.co/ 上创建一个 Hugging Face 账户
3. 前往“Spaces”,然后点击“Create new Space”。在表单中,填写一个名称,将空间类型设置为“Streamlit”,并选择新的存储库。
这是应用程序的截图:
Figure 4.5: 在 Streamlit 中的问答应用程序。
搜索结果相当不错,尽管具体取决于所使用的工具,可能仍然会出现错误结果。对于关于拥有最大蛋的哺乳动物的问题,使用 DuckDuckGo 搜索会返回一篇讨论鸟类和哺乳动物蛋的文章,并有时得出鸵鸟是拥有最大蛋的哺乳动物的结论,尽管鸭嘴兽有时也会出现。以下是正确推理的日志输出(缩写版):
> Entering new AgentExecutor chain...
I'm not sure, but I think I can find the answer by searching online.
Action: duckduckgo_search
Action Input: "mammal that lays the biggest eggs"
Observation: Posnov / Getty Images. The western long-beaked echidna ...
Final Answer: The platypus is the mammal that lays the biggest eggs.
> Finished chain.
你可以看到,拥有一个强大的自动化和问题解决框架,你可以将需要数百小时才能完成的工作压缩到几分钟之内。你可以尝试不同的研究问题,以了解工具的使用方式。书籍仓库中的实际实现允许您尝试不同的工具,并提供了自验证选项。检索增强生成(RAG)与 LLMs 可以通过将来自外部来源的相关数据注入上下文中,显著提高响应的准确性和质量。通过用特定用例的知识基础来奠定 LLMs 的基础,我们可以减少幻觉,并使它们在真实世界情景中更有用。RAG 比重新训练模型更具成本效益和效率。您可以在 BlockAGI 项目中看到使用 LangChain 的增强信息检索的非常高级的示例,该项目受到 BabyAGI 和 AutoGPT 的启发,网址为github.com/blockpipe/BlockAGI
。在接下来的几节中,我们将通过它们的决策制定策略来比较主要类型的代理。
当前一代的生成模型,如 LLMs,擅长发现现实世界数据的模式,例如视觉和音频信息,以及非结构化文本,但是它们在涉及结构化知识表示和推理的任务所需的符号操作方面存在困难。推理问题对 LLMs 构成挑战,并且有不同的推理策略可以补充神经网络作为生成模型固有的模式完成能力。通过专注于在提取的信息上实现符号操作,这些混合系统可以增强语言模型的能力。模块化推理,知识和语言(MRKL)是一个结合语言模型和工具来执行推理任务的框架。在 LangChain 中,这包括三个部分:
工具,
一个LLMChain
,以及
代理本身。
工具是代理可以使用的可用资源,如搜索引擎或数据库。LLMChain 负责生成文本提示并解析输出以确定下一步操作。代理类使用 LLMChain 的输出来决定采取哪些行动。我们在第二章,LangChain 简介中讨论了工具使用策略。我们可以在此图表中看到观察模式的推理:
图 4.6:推理观察(来源:https://arxiv.org/abs/2305.18323;许滨峰等人,2023 年 5 月)。
依赖观察的推理包括基于当前知识状态或通过观察获取的证据做出判断、预测或选择。在每次迭代中,代理向语言模型(LLM)提供上下文和示例。用户的任务首先与上下文和示例结合,然后交给 LLM 启动推理。LLM 生成一个思考和一个动作,然后等待来自工具的观察。观察结果添加到提示中以启动下一次对 LLM 的调用。在 LangChain 中,这是一个行动代理(也称为零-shot 代理, ZERO_SHOT_REACT_DESCRIPTION
),这是创建代理时的默认设置。正如提到的,计划也可以在任何操作之前制定。在 LangChain 中称为计划和执行代理的策略在这里示例化:
图 4.7: 从观察中分离推理(来源:https://arxiv.org/abs/2305.18323;许彬锋等人,2023 年 5 月)。
规划器(一个 LLM)可以针对规划和工具使用进行微调,产生一个计划列表(P)并调用一个工作者(在 LangChain 中:代理)通过使用工具来收集证据(E)。P 和 E 与任务结合,然后传递给求解器(一个 LLM)得出最终答案。我们可以编写一个伪算法如下:
规划所有步骤(规划器)
对于步骤中的每一步:
规划器和求解器可以是不同的语言模型。这样就可以使用更小、更专业的规划器和求解器模型,并针对每次调用使用更少的标记。我们可以在我们的研究应用程序中实现计划和求解,让我们做吧!首先,让我们向load_agent()
函数添加一个strategy
变量。它可以取两个值,即“plan-and-solve”或“one-shot-react”。对于“one-shot-react”,逻辑保持不变。对于“plan-and-solve”,我们将定义一个规划器和一个执行器,我们将使用它们来创建一个PlanAndExecute
代理执行器:
from typing import Literal from langchain.experimental import load_chat_planner, load_agent_executor, PlanAndExecute ReasoningStrategies = Literal["one-shot-react", "plan-and-solve"] def load_agent( tool_names: list[str], strategy: ReasoningStrategies = "one-shot-react" ) -> Chain: llm = ChatOpenAI(temperature=0, streaming=True) tools = load_tools( tool_names=tool_names, llm=llm ) if strategy == "plan-and-solve": planner = load_chat_planner(llm) executor = load_agent_executor(llm, tools, verbose=True) return PlanAndExecute(planner=planner, executor=executor, verbose=True) return initialize_agent( tools=tools, llm=llm, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, verbose=True )
为了简洁起见,我省略了我们之前已有的导入操作。让我们定义一个通过 Streamlit 中的单选按钮设置的新变量。我们将把这个变量传递给load_agent()
函数:
strategy = st.radio(
"Reasoning strategy",
("plan-and-solve", "one-shot-react", ))
你可能注意到load_agent()
接受一个字符串列表tool_names
。这也可以在用户界面(UI)中选择:
tool_names = st.multiselect(
'Which tools do you want to use?',
[
"google-search", "ddg-search", "wolfram-alpha", "arxiv",
"wikipedia", "python_repl", "pal-math", "llm-math"
],
["ddg-search", "wolfram-alpha", "wikipedia"])
最后,在应用程序中,代理如下加载:
agent_chain = load_agent(tool_names=tool_names, strategy=strategy)
我们可以在这里看到 UI:
图 4.8: 在我们的研究应用程序中实现计划和执行。
请查看应用程序,并查看关于“在大型语言模型的背景下什么是计划和求解代理”的不同步骤。简单地说,第一步,计划如下:
定义大型语言模型:大型语言模型是经过大量文本数据训练的人工智能模型,可以根据其接收到的输入生成类似人类的文本。
在大型语言模型的背景下理解计划的概念:在大型语言模型的背景下,计划是指模型生成的解决问题或回答问题的结构化大纲或一组步骤。
在大型语言模型的背景下理解求解代理的概念:求解代理是大型语言模型的组成部分,负责生成解决问题或回答问题的计划。
认识到计划和求解代理在大型语言模型中的重要性:计划和求解代理有助于组织模型的思维过程,并为解决问题或回答问题的任务提供了结构化方法。
给出以上所采取的步骤后,请回答用户的原始问题:在大型语言模型的背景下,计划是由求解代理生成的结构化大纲或一组步骤,用于解决问题或回答问题。求解代理是大型语言模型的组成部分,负责生成这些计划。
因此,第一步是执行 LLMs 的查找:
Action:
{
"action": "Wikipedia",
"action_input": "large language models"
}
我们没有讨论这个问题的另一个方面,即在这些步骤中使用的提示策略。例如,不同的提示策略提供了解决 LLM 复杂推理问题挑战的方法。一种方法是few-shot chain-of-thought(CoT)提示,其中 LLM 通过逐步推理演示进行引导。例如,在算术推理中,可以向 LLM 展示解方程的示例演示,以帮助其理解过程。另一种策略是zero-shot-CoT提示,它消除了手动演示的需要。而是,将类似“让我们逐步思考”这样的通用提示附加到提供给 LLM 的问题陈述中。这使模型能够在没有先前明确示例的情况下生成推理步骤。在算术推理中,问题陈述可以附加这个提示并输入 LLM。Plan-and-Solve (PS)提示,涉及将复杂任务分解为较小的子任务,并根据计划逐步执行它们。例如,在解方程或涉及多个步骤的单词问题的数学推理问题中,PS 提示使 LLM 能够为接近每个子步骤制定计划,如提取相关变量和计算中间结果。为了进一步提高推理步骤和指导的质量,引入了**PS+**提示。它包括更详细的说明,如强调提取相关变量并考虑计算和常识。PS+提示确保 LLM 更好地理解问题并能够生成准确的推理步骤。例如,在算术推理中,PS+提示可以指导 LLM 识别关键变量,正确执行计算,并在推理过程中应用常识知识。这结束了我们对推理策略的讨论。所有策略都存在问题,可能表现为计算错误、缺少步骤错误和语义误解。然而,它们有助于提高生成的推理步骤的质量,增加问题解决任务的准确性,并增强 LLM 处理各种类型推理问题的能力。
在本章中,我们谈到了幻觉问题,自动事实核查以及如何使 LLMs 更加可靠。工具和提示策略特别受到强调。我们首先查看并实施了提示策略,以分解和总结文档。这对于消化大型研究文章或分析非常有帮助。一旦我们开始大量调用 LLMs,这就意味着我们会产生很多成本。因此,我专门为令牌使用分配了一节。工具为 LLMs 在各个领域提供了创造性的解决方案,并开辟了新的可能性。例如,可以开发一个工具,使 LLM 能够执行高级检索搜索,查询数据库以获取特定信息,自动编写电子邮件,甚至处理电话。OpenAI API 实现了我们可以使用的功能,其中包括在文档中进行信息提取等。我们已经实现了一个非常简单的 CV 解析器版本,作为此功能的示例。但是,工具和函数调用并不是 OpenAI 的特有功能。通过 Streamlit,我们可以实现调用工具的不同代理。我们已经实现了一个应用程序,可以通过依赖外部工具(如搜索引擎或维基百科)来回答研究问题。然后,我们查看了代理使用的不同策略来做出决策。主要区别在于决策点。我们将一个计划和解决代理实施到了 Streamlit 应用程序中。我希望这能表明,在几行代码中,我们可以实现在几种情况下非常令人印象深刻的应用程序。然而,重要的是要明确,本章中开发的应用程序具有局限性。它们可以帮助您显著提高效率,但是您 - 作为人类 - 必须运用判断力并改进写作,以确保其连贯和合理。让我们看看您是否记得本章的一些关键要点!
请看一下,看看你能否从记忆中得出这些问题的答案。如果对任何一个不确定,请返回本章的相应部分:
什么是幻觉?
自动事实核查是如何工作的?
在 LangChain 中,我们可以采取什么措施来确保输出有效?
LangChain 中的 map-reduce 是什么?
我们如何统计我们使用的令牌数量(以及为什么应该这样做)?
RAG 代表什么,使用它有什么优势?
LangChain 中有哪些工具可用?
请定义计划和解决代理
请定义一次性代理
我们如何在 Streamlit 中实现文本输入字段和单选按钮?
packt.link/EarlyAccessCommunity
在本章中,我们将讨论聊天机器人,它们是什么,它们能做什么,以及如何实现它们。我们将从讨论聊天机器人的演变和当前技术的最新进展开始本章。理解和增强当前聊天机器人和大型语言模型(LLMs)的能力对它们在包括医学和法律在内的不同领域的安全和有效使用具有实际意义。积极的沟通,对于与客户需求接触很重要,需要在技术上,实现机制来维护上下文和记忆。本章的重点是检索机制,包括矢量存储以提高响应的准确性和聊天机器人对可用信息和当前对话的忠实度。我们将介绍现代聊天机器人的基础知识,如检索增强语言模型(RALMs),我们在 LangChain 中实现它们所需的技术背景。我们将详细讨论加载文档和信息的方法,包括矢量存储和嵌入。我们将进一步讨论关于记忆的更具体的方法,这些方法涉及维护正在进行的对话的知识和状态。最后,我们从声誉和法律的角度讨论另一个重要主题:审查。让我们确保我们的回答不是滥用的,不宽容的,或者违背组织的精神。LangChain 允许您通过一个审查链来通过任何文本,以检查它是否包含有害内容。在整个章节中,我们将使用 Streamlit 中的界面来实现一个聊天机器人,您可以在 github.com/benman1/generative_ai_with_langchain
的 Github 仓库中的 chat_with_retrieval
目录中找到。主要部分包括:
什么是聊天机器人?
检索和矢量
实现一个聊天机器人
不要说傻话!
我们将通过介绍聊天机器人和技术的最新发展开始本章。
聊天机器人是一种可以与用户聊天、提供信息和支持、预订事物以及执行各种其他任务的人工智能程序。它用于重现与用户的强大互动,并可用于不同的行业和不同的目的。聊天机器人有益的原因在于它们可以自动化任务、提供即时响应,并为用户提供个性化体验。它们可以用于客户支持、潜在客户生成、销售、信息检索等。聊天机器人可以节省时间、提高效率、增强客户体验,并简化业务流程。聊天机器人通过利用自然语言处理(NLP)和机器学习算法工作。它们分析用户输入,理解其意图,并生成适当的回应。它们可以设计为与基于文本的消息平台或基于语音的应用程序配合使用。客户服务中聊天机器人的一些用例包括提供全天候支持、处理常见问题、协助产品推荐、处理订单和付款以及解决简单的客户问题。聊天机器人的更多用例包括:
预约安排:聊天机器人可以帮助用户安排预约、预订预约并管理其日历。
信息检索:聊天机器人可以为用户提供特定信息,如天气更新、新闻文章或股票价格。
虚拟助手:聊天机器人可以充当个人助手,帮助用户完成任务,如设置提醒、发送消息或打电话。
语言学习:聊天机器人可以通过提供互动对话和语言练习来协助语言学习。
心理健康支持:聊天机器人可以提供情感支持,提供资源,并进行心理健康对话。
教育:在教育环境中,正在探索虚拟助手作为虚拟导师的潜力,帮助学生学习和评估他们的知识,回答问题,并提供个性化的学习体验。
人力资源和招聘:聊天机器人可以协助招聘流程,通过筛选候选人、安排面试并提供有关职位空缺的信息。
娱乐:聊天机器人可以让用户参与互动游戏、测验和故事体验。
法律:聊天机器人可用于提供基本法律信息,回答常见法律问题,协助法律研究,并帮助用户导航法律程序。它们还可以协助文件准备,如起草合同或创建法律表格。
医学:聊天机器人可以协助检查症状,提供基本医疗建议,并提供心理健康支持。它们可以通过提供相关信息和建议,改善临床决策,帮助医疗专业人员。
这些只是一些例子,聊天机器人的用途正在不断扩展到各个行业和领域。任何领域的聊天技术都有潜力使信息更易获取,并为寻求帮助的个人提供初步支持。
图灵测试,以英国计算机科学家、密码分析师和数学家艾伦·图灵命名,是人工智能(AI)中一种用于确定计算机是否具有像人类一样思考能力的调查方法。尽管关于图灵测试的相关性以及以此为基础的竞赛的有效性存在着很多争论,但这一测试仍然是讨论和研究人工智能的哲学起点。随着我们对人工智能的不断进步,以及对人类大脑功能的更深入理解和映射,图灵测试仍然是定义智能的基础,并且是关于我们对技术期望达到什么程度才能被认为是“思考机器”的辩论的基线。图灵提出,如果计算机可以在特定条件下模仿人类的反应,那么可以说计算机具有人工智能。最初的图灵测试需要三个终端,每个终端在物理上与其他两个终端分开。一个终端由计算机操作,另外两个由人类操作。在测试过程中,一个人类扮演提问者的角色,而另一个人类和计算机扮演回答者的角色。提问者在特定主题领域内使用指定的格式和上下文对回答者进行审问。经过预设的时间或问题数量后,提问者被要求决定哪个回答者是人类,哪个是计算机。自从测试形式形成以来,许多人工智能已经能够通过测试;其中最早的一个是 Joseph Weizenbaum 的 ELIZA。1966 年,他发表了一篇关于他的聊天机器人 ELIZA 的文章,“ELIZA - 一个用于研究人机自然语言交流的计算机程序。”ELIZA 是最早创建的聊天机器人之一,模拟了心理医生的角色。作为一种展示技术局限性的幽默,这个聊天机器人采用了简单的规则和模糊的开放式问题,以在对话中给人一种共情理解的印象,被认为是人工智能的一个具有讽刺意味的里程碑。然而,ELIZA 知识有限,只能在特定话题领域内进行对话。它也无法长时间保持对话或从对话中学习。图灵测试多年来一直备受批评,特别是因为历史上,问询的性质必须受限,以使计算机表现出类似于人类的智能。很多年来,只有当提问者制定查询时,计算机才会获得较高的分数,因此问题只能有“是”或“否”回答,或者与一小范围的知识领域相关。当问题是开放式的,并需要对话回答时,计算机程序能够成功欺骗提问者的可能性就小了。此外,像 ELIZA 这样的程序可以通过操纵它并不完全理解的符号来通过图灵测试。哲学家约翰·西尔尔(John Searle)认为这并不决定与人类相媲美的智能。对许多研究人员来说,计算机是否能通过图灵测试的问题已经变得无关紧要。与其专注于如何说服某人他们正在与一个人而不是一个计算机程序对话,真正的关注应该集中在如何使人机交互更直观和高效。���如,通过使用会话接口。1972 年,另一个重要的聊天机器人 PARRY 被开发出来,它扮演了一名患有精神分裂症的病人。它具有固定的个性,其回答是基于一系列假设,并且情绪反应是由用户表述的变化触发的。在 1979 年的一次实验中,PARRY 被五名精神科医生测试,他们必须确定他们所交流的患者是一个计算机程序还是真正的精神分裂病患者。结果各有不同,有些精神科医生给出了正确的诊断,而有些给出了
以下是一些聊天机器人的示例:
ELIZA:ELIZA 是最早的聊天机器人之一,于上世纪 60 年代开发,使用模式匹配来模拟与用户的对话。
Siri:Siri 是由苹果开发的流行的基于语音的聊天机器人。它集成在苹果设备中,可以执行任务,回答问题并提供信息。
Alexa:Alexa 是亚马逊开发的智能个人助理。它可以响应语音命令,播放音乐,提供天气更新,并控制智能家居设备。
Google Assistant:Google Assistant 是由谷歌开发的聊天机器人。它可以回答问题,提供建议,并根据用户命令执行任务。
Mitsuku:Mitsuku 是一款多次赢得 Loebner 奖图灵测试的聊天机器人。它以参与自然和类似人类的对话而闻名。
这些只是一些示例,各行业和应用中还有许多其他聊天机器人可用。
使用图灵测试及其衍生物的一个关注点是它侧重于模仿和欺骗,而更有意义的测试应该强调开发者需要专注于创建有用和有趣的功能,而不仅仅是执行花招。使用基准测试和学术/专业考试提供了对 AI 系统性能的更具体评估。目前该领域研究人员的目标是为测试人工智能(AI)系统的能力提供更好的基准,特别是对于大型语言模型(LLM)如 GPT-4。他们旨在了解 LLM 的限制并确定可能失败的领域。先进的 AI 系统,包括 GPT-4,在与语言处理相关的任务上表现出色,但在简单的视觉逻辑难题上很难。LLM 可以根据统计相关性生成合理的下一个词,但可能缺乏推理或对抽象概念的理解。研究人员对 LLM 的能力有不同的看法,有些人将其成就归因于有限的推理能力。测试 LLM 并了解其能力具有实际意义。它可以帮助在医学和法律等现实领域安全有效地应用 LLM。通过确定 LLM 的优势和劣势,研究人员可以确定如何最好地利用它们。ChatGPT 的训练使其更擅长处理幻觉,与其前身相比,这意味着它生成荒谬或无关紧要的回应的可能性较小。然而,重要的是要注意,ChatGPT 仍然可以自信地提供不准确的信息,因此用户应谨慎并验证提供的信息。上下文和记忆在确保聊天机器人的对话提供准确信息和对之前互动的准确反映的响应方面起着重要作用,从而使其能够更忠实地与用户互动。我们现在将更详细地讨论这一点。
上下文和记忆是聊天机器人设计的重要方面。它们使聊天机器人能够保持对话的上下文,回应多个查询,并存储和访问长期记忆。它们是调节聊天机器人响应准确性和忠实度的重要因素。在聊天机器人中,记忆和上下文的重要性可与人与人之间对话中记忆和理解的重要性相比。没有回顾过去的交流或理解或了解更广泛背景的对话可能会杂乱无章,并导致误解,从而导致不令人满意的对话体验。上下文理解极大地影响着聊天机器人响应的准确性。它指的是聊天机器人理解整个对话以及一些相关背景的能力,而不仅仅是用户最后一条消息。了解上下文的聊天机器人能够保持对话的整体视角,使对话流程更加自然和人性化。记忆保持直接影响着聊天机器人性能的忠实度,这涉及识别和记住以前对话中的事实以供将来使用的一致性。此功能增强了用户的个性化体验。例如,如果用户说:“给我显示最便宜的航班”,然后跟着说:“那个地区的酒店怎么样?”如果没有上下文的前一条消息,聊天机器人将不知道用户指的是哪个地区。在反向场景中,一个具有上下文意识的聊天机器人会理解用户在谈论与飞行目的地相同地区的住宿。记忆缺乏导致对话中的一致性不足(忠实度不足)。例如,如果用户在一次对话中已经通过姓名确定了自己的身份,而机器人在下一次对话中忘记了这些信息,就会导致不自然和不个性化的互动。记忆和上下文对于使聊天机器人的互动更加有效、准确、亲切和令人满意至关重要。如果没有这些元素,机器人可能会显得不足、僵化并且无法与人类对话伙伴建立联系。因此,这些特征对于计算机和人类之间复杂而令人满意的互动至关重要。LLM 聊天机器人的一个新方面是它们不仅可以对意图做出响应,还可以更智能地与用户进行对话。这被称为主动对话。
在语言模型或聊天机器人的背景下,主动指的是系统在未明确受到用户提示的情况下启动行动或提供信息的能力。它涉及根据先前的互动或上下文线索预测用户的需求或偏好。另一方面,有意意味着聊天机器人被设计为理解并满足用户的意图或请求,并根据这些意图和期望的结果采取具体的行动或提供相关的回应。主动式聊天机器人很有用,因为它可以与客户建立联系并改善他们的体验,从而创建更好的客户旅程。这可以通过节省时间和精力来增强用户体验,还可以通过在问题出现之前快速有效地解决客户查询来提高客户满意度。主动沟通对于企业的成功至关重要,因为它提高了客户的生命周期价值(CLV)并降低了运营成本。通过主动预测客户的需求并主动提供信息,企业可以控制沟通并以有利的方式构建对话。这建立了信任、客户忠诚度,并增强了组织的声誉。此外,主动沟通通过在客户提问之前解决客户查询并减少来电支持电话,有助于提高组织的生产率。技术上,这种能力可以通过上下文、记忆和推理机制实现。这是本章的重点。在下一节中,我们将讨论现代聊天机器人的基础知识,如检索增强语言模型(RALM)以及实现它们所需的技术背景。
在第四章中,我们讨论了检索增强生成(RAG),其旨在通过利用外部知识和确保生成的文本准确和上下文适当来增强生成过程。在本章中,我们将进一步讨论如何结合检索和生成技术来提高生成文本的质量和相关性。特别是,我们将讨论检索增强语言模型(RALM),这是 RAG 的特定实现或应用,它指的是在生成过程中条件于一个基准语料库(即一系列书面文本)中的相关文档的语言模型。在检索中,利用语义过滤和向量存储来预过滤大型文档库中的相关信息,并将该信息纳入生成过程。这个检索包括文档的向量存储。
检索增强语言模型(RALMs)是具有检索组件以增强性能的语言模型。传统语言模型根据输入提示生成文本,但是 RALMs 通过从大量文档中检索相关信息,并将该信息用于生成更准确和上下文相关的响应而进一步发展。
RALMs 的好处包括:
提高性能:通过整合主动检索,LM 可以从外部来源访问相关信息,从而增强其生成准确和信息丰富响应的能力。
避免输入长度限制:检索增强 LM 丢弃先前检索的文档,并仅使用当前步骤检索的文档来调节下一生成。这有助于防止达到 LM 的输入长度限制,使它们能够处理更长和更复杂的查询或任务。
更详细地说,检索增强 LM 的工作机制涉及以下步骤:
检索:RALMs 从大型语料库中搜索相关文档或段落。LM 根据向量相似性搜索查询和当前上下文来从外部源检索相关信息。
调节:检索的信息用于调节 LLM 的下一生成。这意味着 LM 将检索的信息整合到其语言模型中,以生成更准确和上下文适当的响应。
迭代过程:检索和调节步骤是迭代执行的,每一步建立在前一步之上。这种迭代过程允许 LLM 通过整合来自外部源的相关信息逐渐提高其理解和生成能力。
检索的信息可以以不同方式使用。它可以作为语言模型的额外上下文,帮助其生成更准确和上下文相关的响应。它还可以用于提供事实信息或在生成的文本中回答特定问题。有两种主要的检索增强生成策略:
单次检索增强生成:这一策略涉及使用用户输入作为检索的查询,并一次生成完整的答案。检索的文档与用户输入拼接在一起,用作语言模型生成的输入。
主动检索增强生成:这一策略涉及在生成过程中积极决定何时以及检索什么内容。在生成的每个步骤中,根据用户输入和先前生成的输出,制定检索查询。检索的文档随后用作语言模型的输入进行生成。这种策略允许检索和生成交错进行,使模型能够根据需要动态检索信息。
在增强生成框架中,有两种前瞻性方法称为 FLARE(前瞻性增强检索生成):
使用检索指令的 FLARE(检索指令 FLARE):该方法在生成回答时需要时提示语言模型生成检索查询。它使用鼓励检索的指令,例如“[搜索(查询)]”,以表示需要额外的信息。
FLARE Direct(直接 FLARE):该方法直接使用语言模型生成的内容作为搜索查询。它迭代地生成下一句以了解未来的主题,并且在存在不确定的令牌时,它会检索相关文档以重新生成下一句。
不同于传统方法只检索一次,然后用于生成,FLARE 采取迭代过程。它包括使用即将出现的句子预测作为查询来检索相关文档。如果初始生成的置信度较低,这允许系统重新生成句子。RALM 在诸如问答、对话系统和信息检索等任务中显示出很好的结果。它们可以通过利用外部知识源来提供更准确和有信息的回答。此外,通过在特定领域的文档集上对其进行培训,RALM 可以进行微调,从而增强其在专业应用中的效用。总体而言,通过融合检索,RALM 可以利用文档语料库中丰富的知识,使其在各种自然语言处理任务中更加强大和有用。RALM 利用主动检索来提升性能并克服处理复杂查询或任务的限制。LangChain 实现了构建检索系统的不同构建块的工具链。这包括数据加载器、文档转换器、嵌入模型、向量存储和检索器。它们之间的关系在此图表中显示(来源:LangChain 文档):
图 5.1:向量存储和数据加载器。
在 LangChain 中,我们首先通过数据加载器加载文档。 然后我们可以转换它们,将这些文档传递给一个向量存储作为嵌入。 然后我们可以查询向量存储或与向量存储相关联的检索器。 LangChain 中的检索器可以将加载和向量存储封装为一个步骤。 在本章中,我们将大多数跳过转换,但是你将在数据加载器、嵌入、存储机制和检索器的示例中找到解释。 由于我们正在讨论向量存储,我们需要讨论向量搜索,这是一种根据它们与查询向量的相似度搜索和检索向量(或嵌入)的技术。 它通常用于诸如推荐系统、图像和文本搜索以及异常检测等应用中。 我们将更深入地了解 RALM 背后的基础知识,现在我们将从嵌入开始。 一旦你理解了嵌入,你就能够构建从搜索引擎到聊天机器人的一切。
嵌入是以机器可处理和理解的方式对内容进行数字表示。 这个过程的本质是将对象(比如图像或文本)转换为一个向量,尽可能地封装其语义内容,同时丢弃不相关的细节。 嵌入将一段内容,比如一个单词、句子或图像,映射到一个多维向量空间中。 两个嵌入之间的距离表示对应概念(原始内容)之间的语义相似度。
嵌入是机器学习模型生成的数据对象的表示形式。它们可以将单词或句子表示为数字向量(浮点数列表)。 至于 OpenAI 语言嵌入模型,嵌入是一个包含 1536 个浮点数的向量,表示文本。 这些数字来自于一个捕捉语义内容的复杂语言模型。
举个例子 - 比如我们有单词猫和狗 - 这些可以在一个与词汇表中的所有其他单词一起的空间中以数字方式表示。 如果空间是三维的,那么这些可以是如下形式的向量:对于猫是[0.5, 0.2, -0.1],对于狗是[0.8, -0.3, 0.6]。 这些向量编码了这些概念与其他单词的关系的信息。 粗略地说,我们期望猫和狗的概念与动物的概念更接近(更相似),而不是计算机或嵌入概念。
可以使用不同的方法创建嵌入。对于文本,一个简单的方法是词袋方法,其中每个单词由其在文本中出现的次数表示。这种方法在 scikit-learn 库中被实现为CountVectorizer
,在word2vec出现之前很受欢迎。Word2vec 大致上通过预测句子中的单词来学习嵌入,忽略了线性模型中单词顺序。嵌入的总体思想在这张图中有所展示(来源:“解释类比:向理解词嵌入迈进” by 卡尔·艾伦和蒂莫西·霍斯佩代尔, 2019; https://arxiv.org/abs/1901.09813)。
图 5.2:Word2Vec 词嵌入在 3D 空间中。我们可以用这些向量进行简单的向量运算,例如减去男人向量加上女人向量得到更接近女王的向量。
对于图像,嵌入可以来自特征提取阶段,例如边缘检测、纹理分析和颜色组成。这些特征可以在不同的窗口大小上提取,使表示既具有尺度不变性又具有平移不变性(尺度空间表示)。如今,通常情况下,卷积神经网络(CNNs)是在大型数据集(如 ImageNet)上进行预训练,以学习图像属性的良好表示。由于卷积层在输入图像上应用一系列滤波器(或卷积核)来生成特征图,概念上类似于尺度空间。当经过预训练的 CNN 在新图像上运行时,它可以输出一个嵌入向量。如今,对于大多数领域,包括文本和图像,嵌入通常来自基于变换器的模型,这些模型考虑了句子和段落中单词的上下文和顺序。根据模型架构,尤其是参数数量,这些模型可以捕捉非常复杂的关系。所有这些模型都是在大型数据集上进行训练,以建立概念及其关系。这些嵌入可以用于各种任务。通过将数据对象表示为数值向量,我们可以对它们进行数学运算,并衡量它们的相似性,或将它们用作其他机器学习模型的输入。通过计算嵌入之间的距离,我们可以执行搜索和相似性评分等任务,或对对象进行分类,例如按主题或类别。例如,我们可以通过检查产品评论的嵌入是否更接近积极或消极的概念来执行简单的情感分类器。
嵌入之间的距离度量
在向量相似性计算中使用了不同的距离度量方法,例如:
余弦距离是一种相似度度量,它计算向量空间中两个向量之间的夹角的余弦。它的取值范围是从 -1 到 1,其中 1 表示相同的向量,0 表示正交的向量,-1 表示完全相反的向量。
欧氏距离:它衡量向量空间中两个向量之间的直线距离。它的取值范围是从 0 到无穷大,其中 0 表示相同的向量,较大的值表示越不相似的向量。
点积:它测量两个向量的大小乘积和它们之间的夹角的余弦。它的取值范围是从 -∞ 到 ∞,其中正值表示指向相同方向的向量,0 表示正交向量,负值表示指向相反方向的向量。
在 LangChain 中,您可以通过使用 OpenAIEmbeddings
类的 embed_query()
方法来获取嵌入。以下是一个代码示例:
from langchain.embeddings.openai import OpenAIEmbeddings
embeddings = OpenAIEmbeddings()
text = "This is a sample query."
query_result = embeddings.embed_query(text)
print(query_result)
print(len(query_result))
此代码将单个字符串输入传递给 embed_query
方法,并检索相应的文本嵌入。结果存储在 query_result
变量中。可以使用 len()
函数获取嵌入的长度(维度数)。我假设您已经像第三章“LangChain 入门”中建议的那样将 API 密钥设置为环境变量。您也可以使用 embed_documents()
方法获取多个文档输入的嵌入。以下是一个示例:
from langchain.embeddings.openai import OpenAIEmbeddings
words = ["cat", "dog", "computer", "animal"]
embeddings = OpenAIEmbeddings()
doc_vectors = embeddings.embed_documents(words)
在这种情况下,embed_documents()
方法用于检索多个文本输入的嵌入。结果存储在 doc_vectors
变量中。我们本来可以检索长文档的嵌入 - 相反,我们只检索了单个单词的向量。我们还可以在这些嵌入之间进行算术运算,例如计算它们之间的距离:
from scipy.spatial.distance import pdist, squareform
import pandas as pd
X = np.array(doc_vectors)
dists = squareform(pdist(X))
这给了我们单词之间的欧氏距离作为一个方阵。让我们来画出它们:
import pandas as pd
df = pd.DataFrame(
data=dists,
index=words,
columns=words
)
df.style.background_gradient(cmap='coolwarm')
距离图应该是这样的:
图 5.3:单词 cat、dog、computer、animal 的嵌入之间的欧氏距离。
我们可以确认:猫和狗确实比起计算机更接近动物。这里可能会有很多问题,例如,狗是否比猫更像动物,或者为什么狗和猫与计算机的距离仅比与动物的距离稍远一点。尽管在某些应用中这些问题可能很重要,但让我们记住这只是一个简单的例子。在这些例子中,我们使用了 OpenAI 的嵌入——在接下来的例子中,我们将使用由 Huggingface 提供的模型的嵌入。LangChain 中有一些集成和工具可以帮助这个过程,其中一些我们将在本章后面遇到。此外,LangChain 提供了一个名为 FakeEmbeddings
的类,可以用于在不实际调用嵌入提供者的情况下测试您的管道。在本章的上下文中,我们将使用它们来检索相关信息(语义搜索)。但是,我们仍然需要讨论如何将这些嵌入集成到应用程序和更广泛的系统中,这就是向量存储发挥作用的地方。
正如前面提到的,在向量搜索中,每个数据点都表示为高维空间中的一个向量。这些向量捕捉数据点的特征或特性。目标是找到与给定查询向量最相似的向量。在向量搜索中,数据集中的每个数据对象都被分配一个向量嵌入。这些嵌入是可以在高维空间中用作坐标的数字数组。可以使用余弦相似度或欧氏距离等距离度量计算向量之间的距离。要执行向量搜索,将查询向量(表示搜索查询)与集合中的每个向量进行比较。计算查询向量与集合中每个向量之间的距离,并将距离较小的对象视为与查询更相似。为了高效执行向量搜索,使用向量数据库等向量存储机制。
向量搜索是指在向量数据库等存储的其他向量中,基于它们与给定查询向量的相似度而搜索相似向量的过程。向量搜索通常用于各种应用,例如推荐系统、图像和文本搜索以及基于相似性的检索。向量搜索的目标是使用诸如点积或余弦相似度等相似性度量,高效准确地检索与查询向量最相似的向量。
向量存储指的是用于存储向量嵌入的机制,这也与它们的检索方式有关。向量存储可以是专门设计的独立解决方案,可高效地存储和检索向量嵌入。另一方面,向量数据库专为管理向量嵌入而构建,并提供多个优势,以便于使用诸如 FAISS 等独立向量索引。下面我们将更深入地探讨其中的一些概念。在这方面有三个层次:
索引
向量库
向量数据库
这些组件共同用于创建、操作、存储和高效检索向量嵌入。索引组织向量以优化检索,将它们结构化,以便快速检索向量。对于此,有不同的算法,如 k-d 树或 Annoy。向量库提供了用于向量操作(如点乘和向量索引)的函数。最后,向量数据库(如 Milvus 或 Pinecone)专为存储、管理和检索大量向量而设计。它们使用索引机制来方便地在这些向量上进行高效的相似度搜索。现在让我们依次看看这些。在 LangChain 中有第四个层次即检索器,我们将在最后介绍它们。
在向量嵌入的上下文中,索引是一种组织数据以优化检索和/或存储的方法。这与传统数据库系统中的概念类似,其中索引允许更快地访问数据记录。对于向量嵌入,索引旨在结构化向量,即将相似的向量存储在一起,以便进行快速的接近性或相似性搜索 – 粗略地说。在此上下文中应用的典型算法是 K 维树(k-d 树),但许多其他方法,如 Ball Trees,Annoy 和 FAISS 也经常实现,特别是对于传统方法难以解决的高维向量。
K 最近邻(KNN)是一种用于分类和回归任务的简单直观的算法。在 KNN 中,算法通过查看训练数据集中 k 个最近邻居来确定数据点的类或值。
这就是 KNN 的工作原理:
选择 k 的值:确定在进行预测时将考虑的最近邻居(k)的数量。
计算距离:计算要分类的数据点与训练数据集中的所有其他数据点之间的距离。最常用的距离度量标准是欧几里得距离,但还可以使用其他距离度量标准,如曼哈顿距离。
查找 k 个最近邻居:选择与要分类的数据点距离最短的 k 个数据点。
确定多数类别:对于分类任务,计算在 k 个最近邻居中每个类别中的数据点的数量。具有最高计数的类别成为数据点的预测类别。对于回归任务,取 k 个最近邻居的平均值。
进行预测:一旦确定了多数类或平均值,就将其分配为数据点的预测类别或值。
注意:KNN 是一种惰性学习算法,这意味着它在训练阶段不会显式构建模型。相反,它会在预测时存储整个训练数据集并进行计算。
至于 KNN 的替代方案,还有几种其他常用于相似性搜索索引的算法。其中一些包括:
产品量化(PQ):PQ 是一种将向量空间划分为较小子空间并分别量化每个子空间的技术。这降低了向量的维度,从而实现了高效的存储和搜索。PQ 以其快速的搜索速度而闻名,但可能会牺牲一些准确性。
局部敏感哈希(LSH):这是一种基于哈希的方法,将相似的数据点映射到相同的哈希桶中。它适用于高维数据,但可能具有更高的误报和漏报的概率。
分层可导航小世界(HNSW):HNSW 是一种基于图的索引算法,它构建了一个分层图结构来组织向量。它使用随机化和贪婪搜索的组合来构建一个可导航网络,从而实现高效的最近邻搜索。HNSW 以其高搜索准确性和可扩展性而闻名。
PQ 的示例包括 KD 树和球树。在 KD 树中,建立了一个二叉树结构,根据特征值对数据点进行分区。它适用于低维数据,但随着维度的增加,效果会变差。球树:一种将数据点划分为嵌套超球体的树结构。它适用于高维数据,但对于低维数据可能比 KD 树慢。除了 HNSW 和 KNN 外,还有其他基于图的方法,如图神经网络(GNN)和图卷积网络(GCN),它们利用图结构进行相似性搜索。Annoy(Approximate Nearest Neighbors Oh Yeah)算法使用随机投影树来索引向量。它构建了一个二叉树结构,其中每个节点表示一个随机超平面。Annoy 使用简单,提供快速的近似最近邻搜索。这些索引算法在搜索速度、准确性和内存使用方面有不同的权衡。算法的选择取决于应用程序的具体要求和向量数据的特性。
矢量库,如 Facebook(Meta)Faiss 或 Spotify Annoy,提供了处理矢量数据的功能。在矢量搜索的背景下,矢量库专门设计用来存储和执行矢量嵌入的相似性搜索。这些库使用近似最近邻(ANN)算法来高效地搜索矢量并找到最相似的。它们通常提供 ANN 算法的不同实现,如聚类或基于树的方法,并允许用户为各种应用程序执行矢量相似性搜索。下面是一些开源矢量存储库的快速概述,显示它们随时间的流行程度(来源:star-history.com):
图 5.4:几种最受欢迎的开源矢量库的 Star 历史。
你可以看到 faiss 在 Github 上被很多用户收藏。Annoy 排名第二。其他库还没有达到相同的流行度。我们快速浏览一下这些:
FAISS(Facebook AI 相似性搜索)是 Meta(以前是 Facebook)开发的库,提供了高效的相似性搜索和密集向量的聚类功能。它提供了各种索引算法,包括 PQ、LSH 和 HNSW。FAISS 被广泛应用于大规模矢量搜索任务,并支持 CPU 和 GPU 加速。
Annoy 是由 Spotify 维护和开发的一种高维空间近似最近邻搜索的 C++库,实现了 Annoy 算法。它被设计为高效和可扩展的,适用于大规模矢量数据。它可以与一组随机投影树一起工作。
hnswlib 是一个使用 Hierarchical Navigable Small World(HNSW)算法进行近似最近邻搜索的 C++库。它为高维度矢量数据提供了快速和内存高效的索引和搜索功能。
nmslib(非度量空间库)是一个开源库,提供非度量空间中高效的相似性搜索功能。它支持各种索引算法,如 HNSW、SW-graph 和 SPTAG。
Microsoft 的 SPTAG 实现了分布式近似最近邻搜索(ANN)。它配备了 kd-tree 和相对邻域图(SPTAG-KDT)以及平衡的 k-means 树和相对邻域图(SPTAG-BKT)。
nmslib 和 hnswlib 都由 Amazon 的高级研究科学家 Leo Boytsov 和 Yury Malkov 维护。还有许多其他库。你可以在github.com/erikbern/ann-benchmarks
上看到一个概述。
向量数据库是一种专门设计来处理向量嵌入从而更易于搜索和查询数据对象的数据库类型。它提供了额外的功能,如数据管理、元数据存储和过滤、以及可伸缩性。虽然向量存储专注于存储和检索向量嵌入,但向量数据库提供了更全面的解决方案,用于管理和查询矢量数据。向量数据库对于涉及大量数据并需要灵活和高效的跨各种类型的矢量化数据的搜索能力的应用非常实用,例如文本、图像、音频、视频等。
向量数据库可用于存储和提供机器学习模型及其相应的嵌入。主要应用是相似性搜索(又称:语义搜索),可以高效地搜索大量文本、图像或视频,根据向量表示来识别与查询匹配的对象。这在文档搜索、逆向图像搜索和推荐系统等应用中特别有用。
向量数据库的其他用例随着技术的发展而不断扩展,但向量数据库的一些常见用例包括:
异常检测:向量数据库可通过比较数据点的向量嵌入来检测大型数据集中的异常。这在欺诈检测、网络安全或监控系统中具有重要价值,因为识别异常模式或行为至关重要。
个性化:向量数据库可用于创建基于用户喜好或行为的相似向量的个性化推荐系统。
自然语言处理(NLP):向量数据库广泛用于 NLP 任务,如情感分析、文本分类和语义搜索。通过将文本表示为向量嵌入,比较和分析文本数据变得更加容易。
这些数据库之所以受欢迎,是因为它们经过优化,可以在高维向量空间中表示和检索数据。传统数据库无法高效处理大维度向量,比如用于表示图像或文本嵌入的向量。向量数据库的特点包括:
高效检索相似向量:向量数据库擅长在高维空间中寻找接近的嵌入或相似点。这使它们非常适合逆向图像搜索或基于相似性的推荐任务。
专门用于特定任务:向量数据库旨在执行特定任务,比如查找接近的嵌入。它们不是通用数据库,而是专门设计以高效地处理大量向量数据。
高维空间支持:向量数据库可以处理具有数千个维度的向量,从而实现对数据复杂表示。这对于自然语言处理或图像识别等任务至关重要。
实现高级搜索功能:通过向量数据库,可以构建强大的搜索引擎,可以搜索相似的向量或嵌入。这为内容推荐系统或语义搜索等应用程序打开了可能性。
总的来说,向量数据库提供了一种专业高效的解决方案,用于处理大维度向量数据,实现诸如相似性搜索和高级搜索功能。目前,开源软件和数据库市场蓬勃发展,原因有几点。首先,人工智能(AI)和数据管理对企业至关重要,导致对高级数据库解决方案的需求量很高。在数据库市场上,出现了新型数据库并创建了新的市场类别的历史。这些市场创造者通常主导着行业,吸引了风险投资人(VCs)的大量投资。例如,MongoDB、Cockroach、Neo4J 和 Influx 都是成功引入创新数据库技术并获得大量市场份额的公司的例子。流行的 Postgres 具有用于高效向量搜索的扩展:pg_embedding。使用 Hierarchical Navigable Small Worlds(HNSW),它提供了比 IVFFlat 索引更快更高效的 pgvector 扩展的替代方案。风险投资人正在积极寻找下一个开创性的数据库类型,而 Chroma 和 Marqo 等向量数据库有可能成为下一个大事件。这创造了一个竞争激烈的格局,公司可以筹集大量资金来开发和扩展其产品。一些向量数据库的示例列在以下表中:
数据库提供商 | 描述 | 商业模式 | 首次发布 | 许可证 | 索引 | 组织 |
---|---|---|---|---|---|---|
Chroma | 商业开源嵌入存储 | (部分开放) SaaS 模型 | 2022 年 | Apache-2.0 | HNSW | Chroma Inc |
Qdrant | 带有扩展过滤支持的托管/自托管向量搜索引擎和数据库 | (部分开放) SaaS 模型 | 2021 年 | Apache 2.0 | HNSW | Qdrant Solutions GmbH |
Milvus | 专为可扩展相似性搜索构建的向量数据库 | (部分开放) SaaS | 2019 年 | BSD | IVF,HNSW,PQ 等 | Zilliz |
Weaviate | 存储对象和向量的云原生向量数据库 | 开放 SaaS | 2018 年作为传统图数据库启动,2019 年首次发布 | BSD | 支持 CRUD 的自定义 HNSW 算法 | SeMI Technologies |
Pinecone | 使用来自 AI 模型的嵌入进行快速可扩展的应用程序 | SaaS | 2019 年首次发布 | 专有 | 建立在 Faiss 之上 | Pinecone Systems Inc |
Vespa | 商业开源向量数据库,支持向量搜索、词法搜索和搜索 | 开放 SaaS | 最初是一个网络搜索引擎(alltheweb),在 2003 年被 Yahoo!收购,并在 2017 年作为 Vespa 进行开源 | Apache 2.0 | HNSW,BM25 | 雅虎! |
Marqo | 云原生商业开源搜索和分析引擎 | 开放 SaaS | 2022 | Apache 2.0 | HNSW | S2Search Australia Pty Ltd |
图 5.5:向量数据库。
我自作主张地为每个搜索引擎突出了以下几个方面:
价值主张。是什么独特特点使整个向量搜索引擎脱颖而出?
商业模式。此引擎的一般类型:向量数据库,大数据平台。托管/自托管。
索引。这个搜索引擎采用了怎样的相似性/向量搜索算法,并提供了哪些独特的能力?
许可证:开源还是封闭源?
我省略了其他方面,比如体系结构,例如对分片或内存处理的支持。有许多向量数据库提供商。我省略了许多方案,如 FaissDB 或 Hasty.ai,并专注于一些集成在 LangChain 中的方案。对于开源数据库,Github 星标历史记录可以很好地反映它们的受欢迎程度和吸引力。这是随时间变化的情况(来源:star-history.com):
图 5.6:Github 上开源向量数据库的星标历史记录。
您可以看到 milvus 非常受欢迎,但其他库如 qdrant、weviate 和 chroma 也在迎头赶上。在 LangChain 中,可以使用 vectorstores
模块来实现向量存储。该模块提供了用于存储和查询向量的各种类和方法。LangChain 中向量存储的一个示例是 Chroma 向量存储。让我们看两个示例!
这个向量存储器被优化用于使用 Chroma 作为后端的向量存储和查询。 Chroma 接管了基于角度相似性对向量进行编码和比较。要在 LangChain 中使用 Chroma,您需要按照以下步骤进行操作:
from langchain.vectorstores import Chroma
from langchain.embeddings import OpenAIEmbeddings
vectorstore = Chroma.from_documents(documents=docs, embedding=OpenAIEmbeddings())
文档(或在第四章中看到的拆分)将被嵌入并存储在 Chroma 向量数据库中。我们将在本章的另一部分讨论文档加载程序。我们可以使用其他嵌入集成,或者像这样提供嵌入:
vector_store = Chroma()
# Add vectors to the vector store:
vector_store.add_vectors(vectors)
在这里,vectors
是您想要存储的数值向量(嵌入)的列表。我们可以查询向量存储器以检索相似的向量:
similar_vectors = vector_store.query(query_vector, k)
在这里,query_vector
是您想要找到相似向量的向量,k
是您要检索的相似向量的数量。
这是将松鼠与 LangChain 集成的步骤:
开始安装松鼠 Python 客户端库。您可以在终端中运行以下命令来执行此操作:pip install pinecone
。
在您的 Python 应用程序中导入松鼠:import pinecone
。
连接到 Pinecone:要连接到 Pinecone 服务,需要提供您的 API 密钥。可以通过在 Pinecone 网站上注册来获得 API 密钥。一旦获得 API 密钥,请将其传递给 pinecone 封装器或将其设置为环境变量:
pinecone.init()
Docsearch = Pinecone.from_texts([“dog”, “cat”], embeddings)
例如,嵌入式信息可能是 OpenAI 嵌入式信息。
docs = docsearch.similarity_search(“terrier”, include_metadata=True)
然后,我们可以再次查询或将这些文档用于问题回答链,就像我们在第四章的问题回答中看到的一样。在 LangChain 中,我们可以通过集成文档加载器从许多源和各种格式中加载文档。可以使用 LangChain 集成中心浏览并选择适合您数据源的合适加载器。选择加载器后,可以使用指定的加载器加载文档。让我们简要地看一下 LangChain 中的文件加载器!
文件加载器用于从数据源加载数据作为 Document 对象,这些对象由文本和关联元数据组成。可以使用不同类型的集成,例如用于加载简单 .txt
文件(TextLoader
)的文件加载器,用于加载网页文本内容(WebBaseLoader
),从 Arxiv 中加载文章(ArxivLoader
),或者加载 YouTube 视频转录(YoutubeLoader
)等。对于网页,Diffbot
集成提供了内容的干净提取。对于图像,可能还有其他的集成,例如提供图像标题(ImageCaptionLoader
)。文件加载器具有 load()
方法,该方法从配置的源中加载数据并将其返回为文档。它们还可能具有 lazy_load()
方法,以便在需要它们时将数据加载到内存中。以下是从文本文件加载数据的文档加载器示例:
from langchain.document_loaders import TextLoader
loader = TextLoader(file_path="path/to/file.txt")
documents = loader.load()
documents
变量将包含加载的文档,可以访问这些文档以进行进一步处理。每个文档由page_content
(文档的文本内容)和metadata
(关联元数据,如来源 URL 或标题)组成。同样,我们可以从维基百科中加载文档:
from langchain.document_loaders import WikipediaLoader
loader = WikipediaLoader("LangChain")
documents = loader.load()
需要注意的是,文件加载器的具体实现可能因使用的编程语言或框架而异。在 LangChain 中,代理或链中的向量检索通过检索器完成,它们可以访问向量存储。现在让我们看看这是如何工作的。
LangChain 中的检索器是一种组件,用于搜索和检索给定索引中的信息。在 LangChain 的上下文中,主要的检索器类型是向量存储器检索器。这种类型的检索器利用后端向量存储器(如 Chroma)来索引和搜索嵌入式信息。检索器在文档的问题回答中扮演着至关重要的角色,因为它们负责根据给定的查询检索相关信息。以下是一些检索器的示例:
BM25 Retriever:这个检索器使用 BM25 算法根据其与给定查询的相关性对文档进行排名。它是一种考虑到词项频率和文档长度的流行信息检索算法。
TF-IDF Retriever:这个检索器使用 TF-IDF(词频-逆文档频率)算法根据文档集合中词项的重要性对文档进行排名。它给在集合中罕见但在特定文档中频繁出现的词项分配更高的权重。
Dense Retriever:这个检索器使用密集嵌入来检索文档。它将文档和查询编码成密集向量,并使用余弦相似度或其他距离度量计算它们之间的相似度。
kNN retriever:这个检索器利用著名的 k-最近邻算法根据它们与给定查询的相似度检索相关文档。
这些只是 LangChain 中可用的检索器的几个例子。每个检索器都有自己的优势和劣势,并且选择检索器取决于特定的用例和需求。例如,要使用 kNN 检索器,您需要创建检索器的新实例并为其提供文本列表。以下是使用来自 OpenAI 的嵌入创建 kNN 检索器的示例:
from langchain.retrievers import KNNRetriever
from langchain.embeddings import OpenAIEmbeddings
words = ["cat", "dog", "computer", "animal"]
retriever = KNNRetriever.from_texts(words, OpenAIEmbeddings())
创建了检索器后,您可以通过调用 get_relevant_documents()
方法并传递查询字符串来使用它来检索相关文档。检索器将返回与查询最相关的文档列表。以下是如何使用 kNN 检索器的示例:
result = retriever.get_relevant_documents("dog")
print(result)
这将输出与查询相关的文档列表。每个文档包含页面内容和元数据:
[Document(page_content='dog', metadata={}),
Document(page_content='animal', metadata={}),
Document(page_content='cat', metadata={}),
Document(page_content='computer', metadata={})]
LangChain 中还有一些更专门的检索器,如来自 Arxiv、Pubmed 或 Wikipedia 的检索器。例如,Arxiv 检索器的目的是从 Arxiv.org 存档中检索科学文章。它是一个工具,允许用户在物理学、数学、计算机科学等各个领域搜索和下载学术文章。Arxiv 检索器的功能包括指定要下载的文档的最大数量,根据查询检索相关文档以及访问检索文档的元数据信息。Wikipedia 检索器允许用户从 Wikipedia 网站检索 Wikipedia 页面或文档。Wikipedia 检索器的目的是为用户提供访问大量信息的便捷途径,并使用户能够从中提取特定信息或知识。PubMed 检索器是 LangChain 中的一个组件,有助于将生物医学文献检索纳入他们的语言模型应用程序中。PubMed 包含来自各种来源的数百万篇生物医学文献的引用。在 LangChain 中,PubMedRetriever
类用于与 PubMed 数据库进行交互,并根据给定的查询检索相关文档。该类的get_relevant_documents()
方法接受一个查询作为输入,并从 PubMed 返回相关文档的列表。以下是如何在 LangChain 中使用 PubMed 检索器的示例:
from langchain.retrievers import PubMedRetriever
retriever = PubMedRetriever()
documents = retriever.get_relevant_documents("COVID")
for document in documents:
print(document.metadata["title"])
在这个例子中,get_relevant_documents()
方法被查询“COVID”调用。该方法然后从 PubMed 中检索与查询相关的文档,并将它们作为列表返回。我得到了以下标题作为打印输出:
The COVID-19 pandemic highlights the need for a psychological support in systemic sclerosis patients.
Host genetic polymorphisms involved in long-term symptoms of COVID-19.
Association Between COVID-19 Vaccination and Mortality after Major Operations.
可以通过创建一个继承自BaseRetriever
抽象类的类来在 LangChain 中实现自定义检索器。该类应该实现get_relevant_documents()
方法,该方法接受查询字符串作为输入并返回相关文档的列表。以下是检索器的一个示例实现方式:
from langchain.retriever import BaseRetriever
from langchain.schema import Document
class MyRetriever(BaseRetriever):
def get_relevant_documents(self, query: str) -> List[Document]:
# Implement your retrieval logic here
# Retrieve and process documents based on the query
# Return a list of relevant documents
relevant_documents = []
# Your retrieval logic goes here…
return relevant_documents
你可以根据需要自定义此方法以执行任何检索操作,例如查询数据库或搜索索引文档。一旦你实现了检索器类,就可以创建一个实例并调用get_relevant_documents()
方法来根据查询检索相关文档。让我们实现一个带检索功能的聊天机器人!
我们现在将实现一个聊天机器人。我们将从第四章问答章节中的类似模板开始。与前一章类似,我们假设您已按照第三章开始使用 LangChain中的说明安装了必要的库和 API 密钥。要在 LangChain 中实现一个简单的聊天机器人,您可以按照以下步骤进行:
载入文档
创建一个向量存储
设置一个带有来自向量存储的检索的聊天机器人
我们将通过几种格式进行泛化,并通过 Streamlit 在 Web 浏览器中通过界面提供此功能。您将能够放入您的文档并开始提问。在生产中,对于企业部署以进行客户参与,您可以想象这些文档已经被加载,并且您的向量存储可以是静态的。让我们从文档阅读器开始。如前所述,我们希望能够阅读不同的格式:
from typing import Any from langchain.document_loaders import ( PyPDFLoader, TextLoader, UnstructuredWordDocumentLoader, UnstructuredEPubLoader ) class EpubReader(UnstructuredEPubLoader): def __init__(self, file_path: str | list[str], ** kwargs: Any): super().__init__(file_path, **kwargs, mode="elements", strategy="fast") class DocumentLoaderException(Exception): pass class DocumentLoader(object): """Loads in a document with a supported extension.""" supported_extentions = { ".pdf": PyPDFLoader, ".txt": TextLoader, ".epub": EpubReader, ".docx": UnstructuredWordDocumentLoader, ".doc": UnstructuredWordDocumentLoader }
这使我们能够读取 PDF、文本、EPUB 和带有不同扩展名的 Word 文档的接口。我们现在将实现加载器逻辑。
import logging
import pathlib
from langchain.schema import Document
def load_document(temp_filepath: str) -> list[Document]:
"""Load a file and return it as a list of documents."""
ext = pathlib.Path(temp_filepath).suffix
loader = DocumentLoader.supported_extentions.get(ext)
if not loader:
raise DocumentLoaderException(
f"Invalid extension type {ext}, cannot load this type of file"
)
loader = loader(temp_filepath)
docs = loader.load()
logging.info(docs)
return docs
目前这不能处理很多错误,但如果需要,可以进行扩展。现在我们可以通过界面使这个加载器可用,并将其连接到向量存储。
from langchain.embeddings import HuggingFaceEmbeddings
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.vectorstores import DocArrayInMemorySearch
from langchain.schema import Document, BaseRetriever
def configure_retriever(docs: list[Document]) -> BaseRetriever:
"""Retriever to use."""
# Split each document documents:
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1500, chunk_overlap=200)
splits = text_splitter.split_documents(docs)
# Create embeddings and store in vectordb:
embeddings = HuggingFaceEmbeddings(model_name="all-MiniLM-L6-v2")
# Single call to the huggingface model with all texts:
vectordb = DocArrayInMemorySearch.from_documents(splits, embeddings)
# Define retriever:
return vectordb.as_retriever(search_type="mmr", search_kwargs={"k": 2, "fetch_k": 4})
DocArray 是一个 Python 包,提供了用于表示和操作多模态数据的高级 API。它提供了各种功能,如高级索引、全面的序列化协议、统一的 Python 接口等。此外,它为自然语言处理、计算机视觉和音频处理等任务提供了高效且直观的多模态数据处理。我们可以使用不同的距离度量初始化内存中的 DocArray 向量存储,例如余弦和欧氏距离 - 余弦是默认值。对于检索器,我们有两个主要选项:
相似度搜索:我们可以根据相似性检索文档,或者
最大边际相关性(MMR):我们可以在检索过程中应用基于多样性的文档重新排序,以获得覆盖到目前为止检索到的文档的不同结果。
在相似性搜索中,我们可以设置相似性得分阈值。我们选择了 MMR,这应该会给我们更好的生成结果。我们将参数k
设置为 2,这意味着我们可以从检索中获取 2 个文档。检索可以通过上下文压缩进行改进,这是一种可以压缩检索到的文档并过滤掉无关信息的技术。上下文压缩使用给定查询的上下文来提取和返回仅相关信息,而不是原封不动地返回完整的文档。这有助于减少处理成本并改善检索系统中响应的质量。基本压缩器负责根据给定查询的上下文压缩各个文档的内容。 它使用语言模型(例如 GPT-3)来执行压缩。压缩器可以过滤掉不相关的信息并仅返回文档的相关部分。基本检索器是存储文档的系统,它根据查询检索文档。 它可以是任何检索系统,例如搜索引擎或数据库。 当在上下文压缩检索器中进行查询时,它首先将查询传递给基本检索器以检索相关文档。 然后,它使用基本压缩器根据查询的上下文压缩这些文档的内容。 最后,包含仅相关信息的压缩文档将作为响应返回。我们有几种上下文压缩选项:
LLMChainExtractor
– 这个会从返回的文档中提取仅相关的内容。
LLMChainFilter
– 这个稍微简单一些;它只过滤相关的文档(而不是来自文档的内容)。
EmbeddingsFilter
- 这个可以基于嵌入数据对文档和查询进行相似性过滤。
前两个压缩器需要调用 LLM,这意味着它可能会很慢,而且代价昂贵。因此,EmbeddingsFilter
可能是一种更有效的选择。我们可以在最后加上一个简单的开关语句来整合压缩(替换返回语句):
if not use_compression:
return retriever
embeddings_filter = EmbeddingsFilter(
embeddings=embeddings, similarity_threshold=0.76
)
return ContextualCompressionRetriever(
base_compressor=embeddings_filter,
base_retriever=retriever
)
对于我们选择的压缩器 EmbeddingsFilter
,我们需要包含两个额外的导入:
from langchain.retrievers.document_compressors import EmbeddingsFilter
from langchain.retrievers import ContextualCompressionRetriever
我们可以通过 configure_qa_chain()
方法将 use_compression
参数传递到 configure_retriever()
方法中(此处未显示)。既然我们有了创建检索器的机制,我们可以设置聊天链:
from langchain.chains import ConversationalRetrievalChain from langchain.chains.base import Chain from langchain.chat_models import ChatOpenAI from langchain.memory import ConversationBufferMemory def configure_chain(retriever: BaseRetriever) -> Chain: """Configure chain with a retriever.""" # Setup memory for contextual conversation memory = ConversationBufferMemory(memory_key="chat_history", return_messages=True) # Setup LLM and QA chain; set temperature low to keep hallucinations in check llm = ChatOpenAI( model_name="gpt-3.5-turbo", temperature=0, streaming=True ) # Passing in a max_tokens_limit amount automatically # truncates the tokens when prompting your llm! return ConversationalRetrievalChain.from_llm( llm, retriever=retriever, memory=memory, verbose=True, max_tokens_limit=4000 )
最终的检索逻辑的最后一步是获取文档并将其传递给检索器设置:
import os
import tempfile
def configure_qa_chain(uploaded_files):
"""Read documents, configure retriever, and the chain."""
docs = []
temp_dir = tempfile.TemporaryDirectory()
for file in uploaded_files:
temp_filepath = os.path.join(temp_dir.name, file.name)
with open(temp_filepath, "wb") as f:
f.write(file.getvalue())
docs.extend(load_document(temp_filepath))
retriever = configure_retriever(docs=docs)
return configure_chain(retriever=retriever)
既然我们有了聊天机器人的逻辑,我们需要设置接口。如前所述,我们将再次使用 streamlit:
import streamlit as st
from langchain.callbacks import StreamlitCallbackHandler
st.set_page_config(page_title="LangChain: Chat with Documents", page_icon="声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/正经夜光杯/article/detail/880159
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。