ChatGPT-对话式人工智能与聊天机器人-全-
ChatGPT 对话式人工智能与聊天机器人(全)
原文:
zh.annas-archive.org/md5/8b787882ae881368e104eb61c483426f译者:飞龙
前言
你好!
自 2022 年发布以来,ChatGPT 席卷全球,迎来了大型语言模型(LLM)的时代,并彻底改变了对话 AI 领域。
这本书,《ChatGPT for Chatbots and Conversational AI: Leveraging advanced language models to revolutionize conversational experiences》,是你理解和掌握对话 AI 最新进展的全面指南,特别关注 OpenAI 的 ChatGPT。
ChatGPT 的出现标志着聊天机器人和虚拟助手能力的重大飞跃。与传统的基于规则的系统不同,LLM 根据提供的上下文生成类似人类的文本。这允许更流畅、自然和上下文适当的交互,从而在各种应用中改变用户体验,从客户服务到个人助理。
在这本书中,我们将探讨 ChatGPT 和 LLM 如何重塑对话 AI 的格局。
内容结构旨在提供理论见解和实际应用。我们首先从基础知识开始,涵盖聊天机器人和 LLM 的演变及其在对话设计中的应用,以及 ChatGPT 和 OpenAI 模型的坚实基础介绍。然后,我们转向更高级的主题,包括提示工程的最先进技术、LangChain 的深入研究、检索增强生成(RAG)系统的使用,以及创建你自己的复杂聊天机器人应用。
目前仍有成千上万的基于传统自然语言理解(NLU)的系统在生产中运行,我知道关于何时、如何或是否应该过渡到基于大型语言模型(LLM)的系统,仍然存在许多疑问。我将通过强调你可能会遇到的挑战和克服这些挑战的策略来尝试解答这些问题。
将你的 LLM 应用投入生产不仅仅是技术实现。它需要强大的评估策略,以确保模型在现实世界场景中按预期表现。本书强调了持续监控、严格测试和迭代改进的重要性,以保持高质量交互和用户满意度。
在整本书中,我们强调现实世界的应用和案例,确保你学到的概念可以直接应用于你的项目。到这本书的结尾,你不仅将了解如何在各种场景中实施 ChatGPT,而且还将为该领域的未来趋势做好准备。
这本书通过提供对 ChatGPT 全景的全面概述脱颖而出,将最新研究与实用见解相结合。我们深入探讨基础概念、高级技术、创新工具和行业最佳实践,为任何希望使用 ChatGPT 开发复杂对话应用的人提供清晰的路线图。
有很多内容要涵盖,而且这是一个快速变化的领域。加入我,一起发掘 ChatGPT 在对话式 AI 应用中的全部潜力。
快乐阅读!
本书面向的对象
本书旨在为那些渴望利用 ChatGPT 和其他高级语言模型在他们的对话式 AI 项目中发挥作用的个人设计。主要受众包括以下几类:
-
对话式 AI 专业人士:从对话设计师到客户体验经理和对话式 AI 负责人,任何参与与聊天机器人、语音助手、智能 IVR 系统和多模型客户支持工作的人都将发现利用 ChatGPT 创造更吸引人和自然互动的实际见解。
-
开发人员和对话式 AI 工程师:那些有技术背景,希望从传统的 NLU 系统过渡到 LLM 驱动应用的人将受益于关于集成、部署和克服常见挑战的详细指导。
-
产品负责人:负责 AI 驱动产品开发的领导者将获得对最新技术、工具和最佳实践的全面理解,这些是带来创新对话解决方案到市场所必需的。
-
AI 爱好者和研究人员:对 AI 进步充满热情的个人将欣赏对 ChatGPT、提示工程、LangChain 和其他正在塑造对话式 AI 未来创新技术的深入探讨。
无论你是想改进现有的聊天机器人应用、启动新的 AI 项目,还是保持行业趋势的领先地位,本书都提供了帮助你成功的知识和工具。
本书涵盖的内容
第一章,Chatbot、对话式 AI 和 ChatGPT的介绍,介绍了聊天机器人和对话式 AI 的基础知识。它探讨了它们的演变、各种类型,以及它们在电子商务、客户服务和医疗保健等行业中的影响。本章深入探讨了 OpenAI 的 ChatGPT,详细介绍了其开发、功能和局限性,并考察了它在更广泛的对话式 AI 领域中的位置。
第二章,使用 ChatGPT 进行对话设计,深入探讨了对话设计师的角色以及 ChatGPT 等 LLM 对对话设计的影响。它涵盖了实际应用,包括模拟对话和创建角色,并强调了在开发引人入胜的对话式 AI 系统中测试和迭代的重要性。到结束时,你将了解如何有效地在对话设计中使用 ChatGPT。
第三章, ChatGPT 精通 – 解锁其全部潜力,探讨了与 ChatGPT 交互的技术方面,包括网络聊天界面、OpenAI 游乐场、API 使用和官方库。您将了解免费版和 Plus 版之间的区别、自定义指令以及如何使用游乐场。到那时,您将具备选择最适合您需求交互方法的能力。
第四章, 使用 ChatGPT 进行提示工程,专注于掌握提示工程。您将了解成功提示的核心组件、音调和复杂性的策略,以及提高可读性的技术。本章使您能够创建最大化 ChatGPT 能力的提示,确保精确和相关的交互。
第五章, LangChain 入门,介绍了 LangChain,这是一个用于构建复杂 LLM 应用的开源框架。您将了解核心组件、LangChain 表达式语言(LCEL)以及您可以创建的各种链类型。到那时,您将拥有构建 LangChain 应用和解决下一章中更高级功能的坚实基础。
第六章, 使用 LangChain、代理和工具进行高级调试、监控和检索,深入探讨了高级 LangChain 主题,重点关注调试技术、利用代理和工具以及理解 LLM 驱动的对话体验中的内存。您将探索 LangSmith 平台、开箱即用的工具以及为代理创建自定义工具。本章建立在先前概念的基础上,使您能够开发更复杂的 LangChain 应用。
第七章, 将向量存储作为检索增强生成(RAG)的知识库,介绍了 RAG,这是 LLM 的一个流行用例。您将了解创建 RAG 系统的基本步骤以及如何使用 LangChain 实现这些流程。通过一个真实世界的例子,您将获得掌握 RAG 概念和技术的基础知识。
第八章, 创建您的 LangChain 聊天机器人示例,将前几章的关键概念整合到一个实际项目中。您将构建一个由 ChatGPT 驱动的聊天机器人,能够回答有关您数据的问题并处理复杂任务。我们将探讨项目的范围、为 RAG 准备数据、创建代理工具、在 LangChain 中使用它们,以及最后使用 Streamlit 框架创建您自己的聊天机器人 UI。到那时,您将拥有一个功能齐全的聊天机器人,并深入理解如何使用 ChatGPT 构建复杂的对话代理。
第九章,使用大型语言模型(LLMs)的对话式人工智能的未来,深入探讨了将 ChatGPT 应用推向生产,检查行业中学到的经验教训,并探索成功策略。它探讨了 ChatGPT 的替代方案,特别是较小的语言模型,并讨论了 LLMs 的未来趋势。到那时,你将能够导航不断发展的对话式人工智能领域,并为你的组织规划未来。
要充分利用本书
熟悉聊天机器人和对话式人工智能的基本概念将是有益的,尽管这不是必需的。建议具备一定的编码知识,尤其是 Python,以便有效地跟随示例和练习。需要运行 Python 3.10 的 Python 工作环境。我们建议使用 Anaconda 来设置此环境,并安装 Jupyter Notebook,因为所有章节示例都使用 Jupyter Notebook。
| 本书涵盖的软件/硬件 | 操作系统要求 |
|---|---|
| Python 3.10 | 跨平台 |
| LangChain | 跨平台 |
需要一个免费的 OpenAI 账户,以便你可以获取用于访问 ChatGPT 和其他相关服务的 OpenAI API 密钥:openai.com/
需要 LangSmith 账户,以便你可以创建用于监控和测试你的 LangChain 应用的 API 密钥:smith.langchain.com
通过满足这些先决条件,你将准备好深入探索本书中涵盖的实际应用。
如果你使用的是本书的数字版,我们建议你亲自输入代码或从书的 GitHub 仓库(下一节中有一个链接)获取代码。这样做将帮助你避免与代码的复制和粘贴相关的任何潜在错误 。
下载示例代码文件
你可以从 GitHub 下载本书的示例代码文件:github.com/PacktPublishing/ChatGPT-for-Conversational-AI-and-Chatbots。如果代码有更新,它将在 GitHub 仓库中更新。
我们还有其他来自我们丰富的图书和视频目录的代码包,可在github.com/PacktPublishing/找到。查看它们吧!
使用的约定
本书使用了多种文本约定。
文本中的代码:表示文本中的代码单词、数据库表名、文件夹名、文件名、文件扩展名、路径名、虚拟 URL、用户输入和 Twitter 昵称。以下是一个示例:“确保你已经通过运行 pip install -U langsmith 安装了 LangSmith。”
代码块设置如下:
def format_evaluator_inputs(run: Run, example: Example):
return {
"input": example.inputs["question"],
"prediction": next(iter(run.outputs.values())),
"reference": example.outputs["answer"],
}
任何命令行输入或输出都按以下方式编写:
splitter = RecursiveCharacterTextSplitter(chunk_size=250,
chunk_overlap=20)
粗体:表示新术语、重要单词或您在屏幕上看到的单词。例如,菜单或对话框中的单词以粗体显示。以下是一个示例:“点击 SUCCESS 或 FAILURE 按钮将显示数据集中每个输入和输出的测试详细信息。”
小贴士或重要注意事项
看起来是这样的。
联系我们
我们始终欢迎读者的反馈。
一般反馈:如果您对此书的任何方面有疑问,请通过电子邮件发送至 customercare@packtpub.com,并在邮件主题中提及书名。
勘误表:尽管我们已经尽一切努力确保内容的准确性,但错误仍然可能发生。如果您在此书中发现错误,我们将不胜感激,如果您能向我们报告,请访问www.packtpub.com/support/errata并填写表格。
盗版:如果您在互联网上以任何形式遇到我们作品的非法副本,如果您能提供地址或网站名称,我们将不胜感激。请通过 copyright@packt.com 与我们联系,并提供材料的链接。
如果您有兴趣成为作者:如果您在某个领域有专业知识,并且您有兴趣撰写或为书籍做出贡献,请访问authors.packtpub.com。
分享您的想法
一旦您阅读了《ChatGPT for Conversational AI and Chatbots》,我们非常乐意听到您的想法!请点击此处直接转到此书的亚马逊评论页面并分享您的反馈。
您的评论对我们和科技社区非常重要,并将帮助我们确保我们提供高质量的内容。
下载此书的免费 PDF 副本
感谢您购买此书!
您喜欢在路上阅读,但无法携带您的印刷书籍到处走吗?
您的电子书购买是否与您选择的设备不兼容?
不要担心,现在,随着每本 Packt 书籍,您都可以免费获得该书的 DRM 免费 PDF 版本。
在任何地方、任何设备上阅读。直接从您喜欢的技术书籍中搜索、复制和粘贴代码到您的应用程序中。
优惠远不止于此,您还可以获得独家折扣、时事通讯和每日免费内容的每日电子邮件。
按照以下简单步骤获取优惠:
- 扫描下面的二维码或访问以下链接

packt.link/free-ebook/978-1-80512-953-0
-
提交您的购买证明
-
就这样!我们将直接将您的免费 PDF 和其他优惠发送到您的电子邮件地址。
第一部分:对话式 AI 的基础
在这部分,你将全面了解对话式人工智能的基础。我们首先探讨聊天机器人的基础知识、它们的演变以及在各个行业中的影响。你还将了解 OpenAI 的 ChatGPT 的革命性功能、其应用和局限性。此外,我们还将深入探讨如何在对话设计中使用 ChatGPT,以增强用户交互并创造更自然的对话体验。
本部分包含以下章节:
-
第一章, 对聊天机器人、对话式人工智能和 ChatGPT 的 简介
-
第二章, 使用对话设计与 ChatGPT
第一章:聊天机器人、对话式人工智能和 ChatGPT 简介
欢迎来到聊天机器人、对话式人工智能(conversational AI)和 ChatGPT 的激动人心世界!
在本章的介绍部分,我们将向您介绍聊天机器人和对话式人工智能。
我们的旅程将从探索聊天机器人的基础知识及其不同类型开始,追溯这些数字对话者的演变过程,并评估它们在多个行业(如电子商务、客户服务、医疗保健)中的影响。
接下来,我们将探讨对话式人工智能领域随着时间的推移而发生的变革,以及大型语言模型(LLM)技术的近期快速崛起,特别是 OpenAI 的 ChatGPT、生成式预训练变换器 3(GPT-3)和 GPT-4 模型的崛起。
在阅读本章的过程中,您将全面了解 OpenAI 的 ChatGPT。我们将揭开这一技术奇迹的神秘面纱,探讨其发展、功能和局限性。您将亲眼看到 ChatGPT 如何融入更广泛的对话式人工智能领域,以及它如何通过其多样化的应用彻底改变了各个行业。
为什么本章有价值?我们的目标是审视对话式人工智能的更广泛图景,并深入理解 ChatGPT,为本书后面将要学习的实用技能打下基础。到本章结束时,您将对聊天机器人和对话式人工智能有一个丰富的理解,特别是 ChatGPT 的现实应用和潜力,以及与早期对话式人工智能技术相比,ChatGPT 提供的机遇。这种洞察力将使您能够看到 ChatGPT 的对话式人工智能应用如何为您的组织带来实际利益,提升用户体验和业务流程,并为您的行业带来新的优势。让我们共同踏上这段启发性的旅程吧!
本章将涵盖以下主要内容:
-
什么是聊天机器人和对话式人工智能?
-
聊天机器人和对话式人工智能的演变
-
理解对话式人工智能应用
-
OpenAI 的 ChatGPT 是什么?
-
ChatGPT 的功能和应用
-
ChatGPT 的局限性
什么是聊天机器人和对话式人工智能?
当我们想到对话式人工智能时,我们指的是一个不断发展的 AI 领域,它使计算机系统能够以交互式的方式使用自然语言(NL)与人类进行交流。
在过去的十年中,由对话式人工智能驱动的基于语音和文本的助手已经融入我们的日常生活,在各种平台上提升了用户体验,并应对了广泛的使用案例。它们彻底改变了企业与客户互动的方式,已成为现代数字战略的关键组成部分。
本节旨在提供一个关于对话式人工智能领域的全面概述。它将深入探讨聊天机器人和对话式人工智能的历史,突出塑造从基本的基于规则的系统到复杂的 AI 驱动聊天机器人进步的关键里程碑。我们将研究技术进步,如自然语言理解(NLU)以及从基于规则的聊天机器人到 AI 聊天机器人的转变,强调它们的能力和局限性。总的来说,本节旨在为读者提供一个关于对话式人工智能在革命性地改变人类与计算机之间互动的重要性和潜力的清晰理解。
对话式人工智能的简要历史
第一个聊天机器人是在 20 世纪中叶创建的,第一个记录的例子 ELIZA 是在 1966 年从神圣的麻省理工学院(MIT)的殿堂中诞生的,这得益于约瑟夫·魏岑鲍姆的开创性工作。ELIZA 被设计成模仿心理治疗师的语言模式,能够与人类用户进行直接的互动。这一开创性的创造为后来更复杂的对话式人工智能系统的发展奠定了基础。
最初,这些基本的聊天机器人只能执行一组有限的预编程响应或决策树。然而,它们已经经历了显著的演变,扩展了它们对各种输入做出响应的能力。
革命性技术如机器学习(ML)、自然语言处理(NLP)和 NLU 的出现,促进了从基本的聊天机器人到复杂的对话式人工智能系统的转变。这些先进系统不仅能够以更自然、更本能的方式理解和回应人类的语言,而且还能进行更动态的对话。这些现代系统的一个关键特征是它们能够使用 ML 随着时间的推移进行学习和适应,从而不断提高它们的效率和用户接受度,因此也提高了它们的需求。
对话式人工智能的发展和演变被一系列重要的里程碑所标记,这些里程碑突出了它从基本的聊天机器人到能够模拟类似人类对话的高级人工智能系统的稳步进步。
这些里程碑中的每一个都代表了对话式人工智能发展中的一个重大进步,为今天我们所看到的复杂基于意图的系统铺平了道路。然而,说直到 2022 年 11 月对话式人工智能才真正起飞并不夸张。
为了强调 ChatGPT 的非凡增长,考虑这样一个事实:它在 2022 年 11 月发布后的短短 5 天内就积累了超过一百万用户。这种增长轨迹甚至超过了 Netflix、Facebook、Instagram 和 Zoom 等科技巨头。
聊天机器人和自动化助手概述
当我们谈论聊天机器人或数字助手时,我们究竟指的是什么?聊天机器人这个术语一直存在争议,有些人认为它在技术还处于萌芽阶段时,承担了过去的失望的主要责任。为了本书的目的,无论我们称它们为聊天机器人、数字助手还是其他任何术语,我们本质上都是在讨论一种与人类通过文本或语音进行交流的计算机程序。这种交互式通信可以在各种媒介上进行,例如网站、移动应用、消息平台、协作工具、智能音箱、数字人类头像或交互式语音响应(IVR)系统。
为了进一步区分,我们可以将这些实体分为两种主要类型的对话代理,它们具有不同的能力:

图 1.1 – 基于规则和人工智能驱动的聊天机器人的比较
基于规则的聊天机器人/数字助手
简单的基于规则的聊天机器人基于一组预定义的规则或常见问题解答(FAQs)。它们被设计用来回答常见问题、提供信息或引导用户完成特定任务。然而,它们处理交互的能力仅限于预编程的知识,并且它们可能会在偏离预定义脚本的要求时遇到困难:

图 1.2 – 与基于规则的聊天机器人的交互
简而言之,这些聊天机器人无法理解它们被编程去理解的任何语言之外的任何语言。这类聊天机器人不利用任何机器学习(ML)技术,在用例和功能上有限且脆弱。如果用户提出的要求超出了它们的对话能力或决策树的范围,那么它们往往会崩溃,导致用户体验不佳。
由对话式人工智能驱动的聊天机器人/数字助手
对话式人工智能是指使计算机或机器能够与用户进行自然和类似人类的对话的技术。它结合了自然语言处理(NLP)、自然语言理解(NLU)、机器学习(ML)和对话管理等多个领域,以对话的方式理解和响应用户输入。如今,对话式人工智能是涵盖聊天机器人和语音助手以及创建它们的系统和技术的领域的通用术语。
随着技术的进步,对话式人工智能已经发展到更加复杂,能够理解复杂的查询,提供有意义的、上下文相关的响应,并采用更加稳健、更加动态和适应性强的方法。
对话式人工智能聊天机器人的核心功能包括以下内容:
-
对上下文的理解:NLU 最显著的特征之一是其理解对话上下文的能力。这意味着它不仅独立处理单词,还考虑这些单词被使用的上下文。这允许 AI 正确地解释用户输入背后的含义,即使它是模糊的或复杂的。
-
语义理解:NLU 系统具有高度的语义理解能力。它们可以通过使用实体识别来理解用户话语背后的含义,包括同义词、俚语、地方方言和行业特定术语。
-
处理歧义:在人类交流中,歧义是常见的。我们经常使用模糊或不清晰的表述,这些表述可以有不同的解释。一个 NLU 系统可以通过使用上下文线索来推断意图的含义来处理这种歧义。例如,考虑这个句子,“我看到了她的鸭子。”这个句子可以有多个解释:它可能意味着说话者看到了一个女性躲避某物,或者它可能意味着说话者看到了属于女性的鸭子。如果之前的对话是关于避免飞行物体,系统就会推断第一个含义。如果对话是关于宠物或动物,它就会推断第二个含义。
-
意图识别:NLU 系统可以识别用户话语背后的意图。这意味着它们不仅处理用户所说的话,还理解用户想要实现的目标。这对于提供有帮助和相关的响应至关重要。
-
实体识别:实体识别是 NLP 中的一个关键技术。它是识别和分类文本输入中的命名实体(如人名、组织、地点、产品类型、日期和其他变量)的任务。
-
槽填充:槽填充是根据实体类型从输入中提取信息的功能。它高度依赖于实体识别,它涉及到从输入中识别和提取特定的信息片段,并将它们放入预先定义的槽位中供以后使用。例如,在一个酒店预订对话系统中,槽位可能包括房间类型、预订时间和人数。
-
情感分析:许多 NLU 系统可以分析用户话语背后的情感。这使得它们能够识别用户是高兴、沮丧、愤怒还是悲伤,并以对用户情绪状态敏感的方式做出响应。
-
对话管理:NLU 系统可以管理复杂的对话。它们可以跟踪对话的历史并使用这些信息来指导它们的响应。它们可以处理中断、后续问题和对话主题的变化,提供更类似人类的交互。
-
多语言能力:高级 NLU 系统可以理解和用多种语言进行交流。这使得企业能够为全球受众提供客户服务和支持。
-
与外部系统的集成:NLU 系统通常可以与其他系统集成,例如客户关系管理(CRM)系统、数据库或其他 API。这使得 AI 在与用户交互时能够检索和利用实时数据,提供更个性化和相关的响应。
以下图表展示了与现代对话式 AI 聊天机器人交互的步骤:

图 1.3 – 与 AI 聊天机器人的交互
在过去的 5 年里,对话式 AI 平台经历了巨大的增长,大小技术供应商都在努力构建最佳的低代码、无代码、专业代码解决方案。多年来在对话式 AI 领域工作过的每个人都对什么是最优秀或他们最喜欢的平台来构建对话体验有自己的看法。
所有这些系统的关键组成部分是它们都是基于意图的。AI 技术根据一组训练好的意图处理用户意图,并根据其对对话上下文的理解提供答案。
对话式 AI 平台
现代对话式 AI 系统采用几个功能来管理对话。这些功能通常包括以下内容:
-
能够通过文本或语音理解用户的 NL 输入
-
能够生成相关、连贯且引人入胜的 NL 输出
-
能够理解对话中的多个意图、实体和上下文
-
能够从用户反馈和数据中学习,以随着时间的推移提高它们的准确性和理解能力
-
能够在多个平台和渠道上提供一致和个性化的体验

图 1.4 – 现代对话式 AI 系统的元素
市场上有许多优秀的对话式 AI 系统,供应商从最大的技术提供商到专注于对话式 AI 解决方案的技术初创公司都有。
实际上,并不是这些系统之一创建的最终对话体验决定了成功的实施,而是系统中实际的功能以及这些功能的可用性,这些功能使得用户能够创建对话体验。
为了欣赏今天先进的对话式 AI,让我们回顾一下聊天机器人从其不起眼的起点的发展历程。
聊天机器人和对话式 AI 的演变
当聊天机器人最初进入场景时,它们被誉为技术领域的突破性进化,有望彻底改变企业与其客户沟通的方式。
然而,早期的版本并没有像许多人所期望的那样令人印象深刻。结合聊天机器人平台的发展以及任何人都能轻松创建聊天机器人的便利性,这导致了糟糕的用户体验和整体表现不佳,从而损害了它们的声誉。
早期聊天机器人的一个主要缺陷是它们在理解和回应人类语言方面缺乏复杂性和细微差别。这些基本的版本通常是基于规则的,严重依赖预先编写的脚本。这意味着它们只能处理非常具体的输入,并且很容易因为任何偏离脚本的内容而受到影响。因此,用户常常发现自己陷入令人沮丧的循环对话中,聊天机器人无法理解他们的查询,并持续提供无关或无意义的回应。
语音助手的旅程也充满了起伏。虽然它们在最初很受欢迎,尤其是在亚马逊的 Alexa、苹果的 Siri 和谷歌助手推出后,但随着时间的推移,它们的人气有所下降。这些语音助手的准确性和理解能力导致了一些用户的不满。此外,关于隐私和数据安全的担忧在下降中发挥了重要作用。设备“始终在监听”的想法让许多用户感到不舒服,不愿意使用这些助手。
早期聊天机器人和语音助手的炒作与它们局限性的现实形成了鲜明对比,导致这些技术出现了一种“AI 寒冬”。媒体迅速抓住这些失败,引发了一波负面报道。宣称聊天机器人和语音助手“死亡”的标题变得司空见惯,导致人们对这些技术的潜力普遍持怀疑态度。
更高级的 AI 技术,如自然语言处理(NLP)和机器学习(ML)的出现,使得更先进和强大的聊天机器人和语音助手得以开发。这些新一代的产品在理解和回应人类语言方面表现得更加出色,并且能够随着时间的推移学习和适应。正如基于意图的对话式 AI 超越了基于规则的代理一样,大型语言模型(LLMs)也寻求实现同样的目标。
大型语言模型(LLMs)已经开发了好几年。然而,直到最近几年,随着 OpenAI 推出的 GPT-3 技术的出现,这项技术才开始获得一些曝光并进入主流。但在 2022 年 11 月,这一切都发生了变化,ChatGPT 的爆炸式增长引发了技术竞赛,数百个组织都在努力创造最先进的 LLMs。随着 ChatGPT 和现在的 GPT-4 的领先,它们可以说是最具挑战性的。事实上,不仅仅是 LLM 技术正在进步,构成生态系统的其他相关技术也在不断发展。
对话式 AI 专业人士可以看到,随着 AI 驱动通信的巨大飞跃,其中存在机会。为聊天训练的 GPT 模型可以使聊天机器人和自动化助手之间的对话看起来极其像人类。在下一节中,我们将更详细地探讨这些应用。
理解对话式 AI 应用
在查看 ChatGPT 之前,考虑对话式人工智能应用的使用案例,并首先在传统对话式人工智能系统和技术的可能性背景下考虑它们是很重要的。
对话式人工智能已成为众多行业中的强大工具,从客户服务到医疗保健、银行、保险、零售和人力资源。通过自动化常规任务和增强用户交互,对话式人工智能应用已经改变了许多领域的格局。让我们看看一些现有的对话式人工智能的例子。
客户服务
对话式人工智能在客户支持用例中取得了巨大成功,以多种方式简化流程并改善用户体验。通过采用 AI 驱动的聊天机器人和虚拟助手,企业可以无缝且高效地处理大量客户互动。
在这个用例中,对话式人工智能提供了几个能力和改进。首先,代表可以同时与多个客户互动,即时解决查询。这消除了常见的客户不满来源——长时间的等待。
第二,AI 支持的全天候可用性极大地提升了客户体验。对话式人工智能可以随时处理客户咨询,包括节假日,确保持续的支持。
第三,AI 与 CRM 系统和其他数据库的集成提供了个性化的体验。对话式人工智能可以使用客户数据来了解他们的偏好和购买历史,提供定制化的解决方案或产品推荐,从而提高客户满意度并可能推动销售。
最后,对话式人工智能可以帮助企业节省资源。AI 可以处理常规、重复性的任务,让人类代表有更多时间处理更复杂和敏感的问题。这不仅提高了效率,还降低了运营成本。
loveholidays,一家位于英国的在线旅行社,实施了一个名为 Sandy 的聊天机器人。Sandy 被设计用来实时响应客户查询,减少等待时间并提升客户体验。这个机器人全天候处理大量互动,比人工代表更高效地解决简单问题。这是一个典型的例子,说明了对话式人工智能如何正在革命性地改变客户服务,从回答常规问题到主动的客户参与。
语言翻译
语言翻译系统,如 Google Translate 和 DeepL,使用对话式人工智能来促进实时翻译口头或书面交流。考虑一个场景,一个说法语的用户需要与一个说中文的同事沟通。使用 Google Translate,他们可以无缝沟通,每个人都在自己的母语中,从而打破语言障碍,实现顺畅的沟通。
教育
基于 AI 的教育平台,如卡内基学习,利用 AI 提供个性化的学习体验。这些平台根据学生的个人需求进行调整,提供定制化的指导和反馈。通过研究学生的习惯,这些算法个性化他们的学习体验,提供更有效、个性化的学习方法。
医疗保健
在医疗保健领域,对话式 AI 用于患者分诊和初步诊断。例如,Babylon Health 开发了一个聊天机器人,可以进行初步症状检查,根据检查结果推荐进一步医疗关注或家庭护理。此机器人还可以安排预约和续方,显著提高患者护理和满意度。
其他用例示例包括为心理健康应用创建的;例如,Woebot 是一个 AI 驱动的个人心理健康伴侣,旨在帮助用户维持他们的情绪健康。利用具有 NLP 能力的对话式 AI,它逐渐了解用户的心理状态,提供基于认知行为疗法(CBT)、人际心理治疗(IPT)和辩证行为疗法(DBT)的定制、经临床验证的策略。这种复杂 AI 和经证实治疗策略的独特组合创造了一个独特的心理健康聊天机器人,它使用智能对话能力和流畅的聊天用户界面(UI)。
银行和保险
银行和保险行业使用对话式 AI 进行常规查询、账户管理、账单支付、索赔处理和政策管理。一些机构,如摩根大通,使用对话式 AI 提供个性化的财务建议和推荐,创造更具吸引力的客户体验。
零售
在零售业,聊天机器人通过推荐产品、跟踪订单和回答常规查询来提升客户服务。例如,一个 AI 驱动的聊天机器人可以根据客户的浏览历史推荐产品,创造个性化的购物体验。它们还帮助定制营销活动,有助于增加销售额和客户保留率。
人力资源
在人力资源领域,AI 驱动的聊天机器人使招聘任务更加高效。例如,Mya 可以回答常见问题、筛选候选人、安排面试和管理简历。Mya 在最初的 10,000 次对话中与 92%的候选人进行了有效互动,显著减轻了招聘人员的负担。
总之,对话式 AI 的应用范围广泛且持续发展。无论是提高客户服务的效率、个性化教育、简化医疗保健、革命化银行、保险和零售,还是提升人力资源流程,对话式 AI 注定将在各个行业中继续发挥其变革性作用。
尽管旅程充满坎坷,但聊天机器人和语音助手的传奇故事远未结束。随着这些技术的持续发展,它们有潜力真正改变我们与机器以及彼此沟通的方式。与任何技术创新一样,关键是从过去的错误中学习并继续前进。
对话式人工智能作为培训工具——数字人的出现
随着对话式人工智能能力的不断发展,我们正在见证“数字人”的崛起,这些数字人是高度逼真的、由人工智能驱动的虚拟生物,以类似人类的方式与用户互动。这些数字人,结合对话式人工智能的力量,为许多组织在健康、教育、培训和客户服务领域开辟了新的前沿;例如,德国电信、沃达丰、契尔氏和瑞士信贷。
UneeQ 和 Soul Machines 等公司处于开发能够表达情感、根据情境调整反应并从每次互动中学习的数字人的前沿。这类创新界面可以直接集成到现代对话式人工智能系统中,处理语音转文本(STT)和文本转语音(TTS)功能,并支持语音合成标记语言(SSML)以及它们自己的动作编程语言,以展示人类情感和手势。
在教育和培训领域,由对话式人工智能驱动的数字人可以用来创建满足每位学习者需求的沉浸式学习体验。例如,一个数字人可以充当导师,提供各种学科的个性化一对一辅导,或在企业环境中充当培训助理,引导员工通过复杂的过程或系统。
数字人供应商是 LLM 和生成式人工智能(GenAI)的早期采用者。可能性真正令人着迷,并为 AI 领域的进一步探索和发展开辟了广泛的机会。许多公司已经意识到,结合高级数字人和由 LLM 驱动的对话式服务能够实现独特的品牌体验。
创建数字人形态的代理有助于创造更个人化、富有同理心的互动,并使应用范围更广泛。以下是一些显著的例子:
-
心理健康应用:南加州大学创意技术研究所开发的数字人 Ellie 被用于对人们进行访谈,以筛查抑郁症和创伤后应激障碍的迹象。
-
医学教育:可以使用数字病人来训练医学生进行病人互动和诊断。
-
数字训练师,为每位学习者量身定制沉浸式学习体验。想象一下你自己的私人导师或在企业环境中的一名培训助理,他们引导员工通过复杂的过程或系统。
在过去,即使是基于意图的最先进对话式人工智能系统也难以提供支持这些类型代理所需的对话体验的广度,尤其是在涉及多个回合和复杂上下文的对话中。LLM 技术能够提供更真实的对话。
结论
我们全面审视了对话式人工智能领域,探讨了其应用并承认了其局限性。现在,让我们将焦点转向 ChatGPT 的增强能力。这个强大的工具有可能在对话式人工智能领域带来根本性的转变,为更复杂的虚拟助手、聊天机器人和各种其他通信系统和设备铺平道路。
OpenAI 的 ChatGPT 是什么?
ChatGPT 是 OpenAI 的特定聊天 LLM,它使用机器学习来生成对您的文本输入类似人类的响应。
在 2022 年 11 月推出仅一个多月后,ChatGPT 的用户数量就超过了 1 亿。到 2023 年 2 月,其总网站访问量飙升至 10 亿次。这种爆炸性的增长使 ChatGPT 成为历史上增长最快的消费级软件应用。
ChatGPT 可以以期望的风格或编程语言解释科学和技术概念,基本上可以头脑风暴任何你可以想到的问题……当然,当然可以举行复杂的对话!
理解 ChatGPT 背后的大型语言技术
ChatGPT 建立在一种称为 LLM 的人工智能类型之上。在 LLM 的领域内,有两种主要类型:基本 LLM 和指令优化 LLM。在检查 OpenAI 的 ChatGPT 时,理解这两种类型之间的区别非常重要。
探索基本的 LLM
基本 LLM 被编程为预测一串单词中的下一个单词,使用从各种在线来源获得的大量文本数据集。它们的主要功能是预测给定序列的单词之后最可能出现的单词。
到目前为止,实际上预测的不是单词,而是标记;关于这一点,稍后在本节中会进一步讨论。
为了说明预测的上下文,让我们看看一些例子,从叙事生成开始。如果我们向一个基本的 LLM 输入短语“Hey diddle diddle,the cat and the fiddle”,它可能会继续说“the cow jumped over the moon”。它使用从其庞大的语料库中学到的模式,根据其文本训练数据预测一个有趣且与上下文相关的下一个标记。
这里有一个例子,说明一个特定查询没有得到完美回答:如果你问“1988 年美国总统是谁?”基本 LLM,而不是提供直接答案(罗纳德·里根),可能会返回一个这样的声明:“美国总统在总统选举中每 4 年选举一次。”这个回答虽然与美国总统的主题相关,但并没有直接回答原始问题,这是基本 LLM 概率预测方法的一个潜在缺点。
理解指令优化的 LLM 和基于人类反馈的强化学习
与基础 LLM 相比,指令优化的 LLM 是专门开发来更准确地遵循指令的。因此,它们是当前 LLM 研究和应用的主要兴趣领域。
让我们看看这个过程,它可以分解为三个步骤:
-
预训练语言模型(LM)
-
收集数据和训练奖励模型
-
使用强化学习(RL)微调 LM
要开始这个过程,指令优化的 LLM 最初是在与基本 LLM 相同的大型文本数据集上训练的。OpenAI 为其第一个流行的基于人类反馈的强化学习(RLHF)模型 InstructGPT 使用了 GPT-3 的一个较小版本。该模型通过特定的指令遵循数据进行更多的微调,从而产生更精确的响应。
因此,当被问及“谁在 2020 年赢得了普利策小说奖?”时,一个指令优化的 LLM 可能会直接回答:“2020 年的普利策小说奖授予了科尔斯顿·怀特黑德的《镍男孩》。”
为了提高 LLM 输出的质量,一个常见的做法是针对某些标准对许多不同 LLM 输出的质量进行人工评分;例如,如果输出是有帮助的、真实的和无害的。
这种指令学习通过一种称为 RLHF 的方法进一步精炼,这种方法本质上优化了 LM 使其更有用。RLHF 是一种关键的方法,它微调 LLM,尤其是指令优化的模型。RLHF 方法基于强化学习的原则,强化学习是机器学习的一个子领域,其中代理通过与环境的交互获得决策技能,并作为反馈获得奖励或惩罚。然而,在对话中定义明确的奖励或惩罚以区分好或坏的回答是复杂的,并且在大规模上可能不切实际。为了改进这些模型的响应,我们得到了人们的帮助。AI 训练师与模型进行对话。当模型给出不同的回答时,训练师决定哪些是最好的。他们将答案从最好到最差进行排名。这种排名给模型一种评分:好的答案得到高分。然后,模型使用这些评分来学习给出更好的答案,这个过程类似于通过分析你获得的分数来磨练你在游戏中的技能。
以下图表概述了 RLHF 的过程:

图 1.5 – RLHF 的过程
这个过程通常是迭代的,包括多轮交互、反馈收集和微调,以提高模型的响应。重要的是,RLHF 比传统的监督学习(SL)提供了更细致和上下文相关的反馈,导致与人类价值观的更好对齐,并减少了有害或不适当的响应。
RLHF 的挑战
尽管 RLHF 有其好处,但它也伴随着挑战,可能会产生有害或不准确的事实性文本。
收集人类偏好数据的过程,RLHF(强化学习与人类反馈)的一个基本组成部分,可能因为需要包含人类工作者而变得成本高昂。RLHF 的有效性取决于其人类标注的质量,这包括人类生成的文本和模型输出之间的人类偏好标签。这种数据收集通常需要雇佣额外的工作人员,这使得它对于学术实验室来说既昂贵又具有挑战性。此外,人类标注者可能存在分歧,这可能会给训练数据带来潜在的变异性。
RLHF 是创建有效、安全和用户友好的指令优化 LLMs 的重要工具,但它需要谨慎实施和持续改进。
对于进一步提高 RLHF 性能的研究仍有相当大的空间。在开源或众包人类协助训练这些模型方面也存在潜力。在撰写本文时,一个成功的开源 RLHF 示例是 LAION 创建的 Open Assistant 模型,贡献者可以协助排名、标注和制作回应:open-assistant.io/。
标记在 LLMs 中的作用
OpenAI 的 GPT-3 等 LLMs 在技术上并不预测单词;相反,它们预测标记。要理解这个概念,重要的是要认识到标记是什么以及标记化是如何工作的。
标记化是 NLP(自然语言处理)中的一种常见过程,涉及将文本分解成更小的单元,称为标记。根据标记化策略,这些标记可以代表整个单词、单词的一部分,甚至标点符号。
在英语中,标记通常等同于单词,但这并不总是如此。一些标记化方法,如 GPT-3 等模型使用的 WordPiece、字节对编码(BPE)或单语 LM,将单词分解成更小的子单词单元。例如,“conversational ai”这个单词可能被分成五个标记:[“con”, “versa”, “**ational”,” a”,”i”]。
当我们说 LLMs 预测标记时,这意味着模型的任务是根据先前标记序列预测最可能的下一个标记。这种标记级预测使模型能够处理广泛的词汇,包括罕见单词、人名甚至新词。它还有助于模型更有效地处理除英语以外的语言,因为许多语言具有复杂的形态学,这些形态学在简单的单词级别上无法得到充分表示。
这对于 LLMs(大型语言模型)生成连贯且上下文适当的文本的能力至关重要。通过预测序列中的下一个标记,模型可以构建句子并完成思想,给人一种理解和生成自然语言(NL)的假象。然而,理解这些模型并不真正理解它们生成的文本是至关重要的;它们是基于在训练期间学习到的模式进行序列生成的概率模型。
令牌成本是确定 OpenAI 的语言模型(包括 ChatGPT)成本的基础,这些模型具有不同的能力和价格选项,我们将在后续章节中介绍。
理解 OpenAI 的语言模型
OpenAI 凭借其开创性的语言模型 GPT,已成为对话人工智能领域的先驱。
OpenAI 的语言模型演变
OpenAI 的 GPT-3 作为 ChatGPT 的基础架构,自 2020 年发布以来已经经历了多次改进。
GPT-3
2020 年 6 月发布的 GPT-3,凭借其不同的基础模型:Ada、Babbage、Curie 和 Davinci,为语言生成能力设定了新的标准。每个变体都有其独特的特点。
GPT-3.5
GPT-3.5 作为文本补全任务的优化版本被引入,其中一个模型专门用于代码补全任务。这一系列中的最新版本 gpt-3.5-turbo 于 2023 年 3 月推出。gpt-3.5-turbo 是最先进的 GPT-3.5 模型,专门针对聊天应用进行了优化。最重要的是,它的成本仅为 text-davinci-003 模型的十分之一。该模型可以处理高达 4,096 个令牌,其知识更新至 2021 年 9 月。还创建了 gpt-3.5-turbo-16k 模型。这个模型与标准 gpt-3.5-turbo 模型具有相同的性能,但提供了四倍的上下文,允许进行更长和更复杂的对话。
GPT-4
2023 年 3 月 14 日推出的 GPT-4 被誉为 OpenAI 语言模型中最先进的。它拥有更高的事实准确性、多模态图像处理能力和创意输出。它提供两种模型变体:gpt-4-8k 和 gpt-4-32k,它们由其上下文窗口大小区分。
GPT-3、GPT-3.5 和 GPT-4 之间的关键差异
在提供各种能力、上下文容量和输入类型的可用模型之间有一些关键差异:
-
能力:GPT-4 在可靠性、创造力、协作和细微指令处理方面显著优于其前辈。OpenAI 在不同基准上进行的测试比较证明了 GPT-4 在各个领域的优越性。
-
上下文长度:GPT 版本之间最显著的差异之一是上下文长度。虽然 GPT-3 模型可以处理最多 2,049 个令牌,但 GPT-3.5 将此提升至 4,096 个令牌。GPT-4 实现了巨大的飞跃,其两个模型分别可以处理 8,192 和 32,768 个令牌。
-
输入类型:GPT-4 不仅能够处理文本输入,还具有处理图像的能力。这种独特的能力可以彻底改变其在各个领域的应用。
-
成本影响:更高的能力伴随着更高的价格。GPT-4 的先进功能使得每 1K 令牌的提示和完成成本更高。由于输入和输出令牌的不同成本,使用成本不仅更高,而且也更不可预测。
虽然 GPT-4 无疑在对话人工智能领域设定了新的基准,但重要的是要记住,它并没有使 GPT-3 和 GPT-3.5 过时。每个模型都提供了独特的功能和潜在的应用。
结论
总之,ChatGPT 模型基于强化学习(RLHF)和 OpenAI 的 GPT 系列模型,这些模型本身是在大量数据上训练的。
为了创建 ChatGPT,最新的 GPT-3.5 指令模型通过对话示例进行了微调,而不是整个互联网,以集中提高模型的专业对话能力。然后使用强化学习(RL)使模型能够练习其对话技能并改进其响应。
在接下来的章节中,我们将更详细地探讨其能力、用例以及对对话人工智能领域格局的变革性影响。
ChatGPT 的能力和应用
大型语言模型(LLMs)提供了大量的实用用途,ChatGPT 通过其先进的自然语言处理(NLP)能力脱颖而出。在本节中,我们将探讨这项技术带来的各种应用,以及 ChatGPT 在最具潜力的行业领域中的突出表现。虽然许多这些用例对于对话人工智能应用来说并不一定新颖,但 ChatGPT 确实有可能承担更高级的任务。
ChatGPT 的能力
在接下来的章节中,我们将探讨 ChatGPT 的各种应用,从 NLU 和自然语言生成(NLG)用于聊天机器人和虚拟助手开始。然后,我们将继续探讨其在机器翻译、摘要、情感分析和内容创作方面的能力。其他主题包括其在垃圾邮件过滤、语言教学和软件开发中的应用。最后,我们将讨论通过 ChatGPT 插件提供的扩展功能。
NLU 和 NLG 用于聊天机器人和虚拟助手
对话能力是本书的核心焦点,我们将更详细地探讨这些内容。
ChatGPT 的革命性能力,尤其是其能够在不同主题和风格中维持复杂的多轮对话的能力,标志着对话人工智能领域的重大里程碑。ChatGPT 可以用来完成大多数对话人工智能系统和体验经常难以实现的事情。对于一直使用基于意图的系统并了解挑战的资深从业者来说,ChatGPT 的出现确实具有变革性。
必须指出,看到对话人工智能现在在各种媒体平台上获得的关注,包括电视、广播和报纸,也是非常令人兴奋的。
除了支持对话之外,一个不那么明显用例是 ChatGPT 还可以用作创建和管理基于意图系统的对话人工智能应用的工具。我们将在第二章中更详细地探讨这些应用。
机器翻译之间的语言
ChatGPT 支持 95 种语言。模型如 ChatGPT 中的语言翻译技术,在教育、旅行等行业中架起了语言障碍。通过学习过去的交互,这些系统提供准确的实时翻译,增强了跨文化交流。
文章、报告或其他文本文档的总结
ChatGPT 模型擅长将复杂主题压缩成简洁、易于理解的摘要。它们可以快速处理大量文本,为用户提供精确、易于消化的信息,并消除手动研究的需求。
市场研究或社交媒体监控的情感分析
通过理解和生成类似人类的响应,工具如 ChatGPT 为企业提供了对客户情绪的更深入洞察。它们可以集成到分析并标记可能存在欺诈活动的系统中,尤其是在银行等领域的应用。
为营销、社交媒体或创意写作生成内容
内容创作者可以利用 ChatGPT 高效地生成引人入胜的内容。从博客文章和营销材料到社交媒体帖子,该模型可以生成独特、用户定制的内容。它甚至可以提供主题建议、校对和编辑服务。
邮件过滤、主题分类或文档组织
在任何行业中,ChatGPT 都可以用于分类客户咨询、检测可疑交易和分析内容。
定制化语言学习和辅导工具
模型如 ChatGPT 提供的语言支持,理解超过 40 种语言,扩展到个性化语言学习工具。它们可以处理多语言查询并提供帮助,从而增强了语言学习的可访问性和用户体验。
代码生成和软件开发辅助
ChatGPT 可以理解和生成多种语言的代码,包括以下:
-
Python
-
JavaScript
-
C++
-
C#
-
Java
-
Ruby
-
PHP
-
Go
-
Swift
-
TypeScript
-
SQL
-
Shell
ChatGPT 简化了调试和代码重构任务,为复杂的编码问题提供高效解决方案。它可以快速定位潜在问题,自动化手动任务,并提供高度准确的结果,使其成为软件开发人员的宝贵工具。
ChatGPT 插件通过创建自己的代码解释器插件来扩展这些功能,旨在处理一些特定任务:
-
解决数学问题
-
执行数据分析与可视化
-
在不同格式之间转换文件
与图像一起工作
ChatGPT 无法生成图像。然而,当与 GPT-4 结合使用时,它可以分析信息图表和图像,并根据输入回答问题。例如,您可以输入食品成分的图片,它将提供食谱,或者它可以描述信息图表。
通过使用新插件功能与其他技术结合使用,还可以通过传递图像描述到这些服务中来创建图形。
ChatGPT 插件
ChatGPT 插件于 3 月份发布,是 OpenAI 的一项创新发展,旨在扩大 GPT-4 和 ChatGPT 的现实世界应用、影响和安全。
ChatGPT 插件作为专门的扩展,旨在增强语言模型的功能。它们使 ChatGPT 能够访问实时信息,执行计算任务,并与第三方服务交互。
开发者可以为 ChatGPT 设计插件,并且模型通过全面的文档提供了如何利用每个插件的具体说明。从概念上讲,插件作为语言模型(LM)的感觉输入,使它们能够获取太新、太个人化或太特定于上下文的信息,这些信息原本不可能成为原始训练数据的一部分。它们还允许模型在用户的明确请求下执行安全、有限的操作。
插件提供了丰富的优势。它们解决了与 LLMs 相关的内在挑战,例如幻觉(我们将在本章后面讨论)、跟上最新发展以及访问需要权限的专有信息源。通过促进对外部数据的明确访问,LLMs 可以使用基于证据的参考来丰富其响应,增强模型的效用,并使用户能够交叉验证输出的准确性。
插件不仅解决了当前的局限性,还为几乎任何用例铺平了道路。OpenAI 与来自不同行业的公司之间的合作正在改变我们与技术互动的方式,从浏览产品目录和预订航班到直接从组织订购产品。
随着 ChatGPT 插件生态系统的持续发展,我们可以期待看到更多利用 ChatGPT 力量的创新应用和解决方案。
OpenAI 发布了自己的插件,包括网页浏览器和代码解释器,以及来自受信任提供商的几个第三方插件。
ChatGPT 有多聪明?
AI,尤其是像 ChatGPT 这样的语言模型,在传统的人类意义上并不一定“聪明”。所以,基本上,它没有意识或自我意识。相反,它在理解和生成类似人类的文本方面表现出高水平的能力,从而显得聪明。
最近的研究试图通过进行智商测试和现实世界应用来量化 ChatGPT、GPT-3 和 GPT-4 等 AI 模型的智能程度。
OpenAI 对 GPT-3.5 和 GPT-4 进行了多项专业和学术基准测试,以及为机器学习模型设计的基准测试。
结果在此处有详细记录:openai.com/research/gpt-4。
结果表明,这些 GPT 模型在各个领域的表现水平与平均水平相当,在某些情况下甚至超过了平均水平。例如,ChatGPT 在语言智力测试和雷文测试(衡量抽象推理和解决问题的能力)中取得了分数,使其位于 99.9 百分位。
ChatGPT 令人印象深刻的成就不止于此。它成功通过了西班牙医学考试和美国医学执照考试(USMLE),在雷文渐进矩阵能力测试中优于大学生,甚至通过了沃顿商学院的 MBA 学位考试。此外,GPT-3.5,GPT-3 的一个后续版本,成功通过了美国律师资格考试和美国注册会计师(CPA)考试。
ChatGPT 也已经在现实世界中得到了应用。它在哥伦比亚协助法官做出裁决,在美国撰写了几个法案,甚至登上了《时代》杂志的封面。这些 AI 模型的成就为这项技术的潜力提供了令人瞩目的证明。
ChatGPT 及其变体的成就展示了这些 AI 模型的强大能力。然而,尽管这些分数和成功凸显了它们在理解和生成文本方面的熟练程度,但我们必须记住,它们并不等同于人类的智能或意识。AI 的“智能”在于其编程以及根据该编程处理和生成文本的能力。ChatGPT 的“智能”,正如其高智商分数和现实世界应用所证明的,是对话式人工智能领域取得的令人印象深刻的进步的证明。
ChatGPT 的应用
从传统对话式人工智能方法的运用,特别是更基于意图的方法,过渡到 ChatGPT 的一些实际应用,让我们来看看 ChatGPT 在现实世界中的应用。
商业和金融
近年来,商业和金融领域对 AI 的采用显著增加。从自动化财务报告生成到识别潜在的金融风险,ChatGPT 已被证明是简化运营和促进数据驱动决策的有价值工具:
-
客户服务聊天机器人:ChatGPT 的一个关键应用,对话式人工智能可以在任何需要智能和大规模处理客户支持的职位中得到利用。ChatGPT 提供了一个前线交互平台,创建能够处理客户咨询、处理交易甚至提供个性化产品推荐的代理。
-
市场分析和预测:ChatGPT 的能力扩展到市场分析和预测领域,它可以分析大量财务数据以识别模式和趋势,并对市场状况提供见解。它可以生成分析摘要,提供对金融格局的全面理解。
-
投资管理:ChatGPT 的数据分析能力也使其成为投资管理的宝贵工具。它可以通过提供个性化的投资建议,考虑个人风险特征和财务目标,帮助企业和投资者做出明智的决策。
-
欺诈检测:在金融安全领域,ChatGPT 可以用来检测欺诈活动。通过分析交易数据并识别欺诈活动的指示性模式,ChatGPT 可以提供强大的欺诈检测机制。
-
风险管理:ChatGPT 在风险管理中也发挥着重要作用。通过分析财务数据并识别潜在风险,它可以帮助企业和金融机构制定减轻这些风险的策略。
-
财务报告:通过分析数据和提供对财务表现的见解,ChatGPT 可以用于自动化生成财务报告。
总结来说,ChatGPT 在商业和金融领域的应用广泛且具有变革性。从通过聊天机器人增强客户服务到识别风险和欺诈,这个 AI 模型提供了众多功能,颠覆了传统的业务运营,并为由智能、数据驱动策略主导的未来铺平了道路。
医疗和医学应用
可能是充满最多伦理和监管挑战的领域。在医疗保健领域,ChatGPT 强大的对话体验可以应用于医疗和医学应用。从帮助诊断和治疗计划到推动患者参与,这个领域有许多用例:
-
患者分诊聊天机器人:ChatGPT 可以成为开发用于患者分诊的聊天机器人的重要工具。这类系统有助于医疗保健提供者评估患者状况的紧迫性,并找到最合适的行动方案。
-
医学诊断和治疗建议:ChatGPT 的一个令人信服的应用在于协助医学诊断和治疗建议,以帮助提高治疗计划的准确性和有效性。通过分析患者数据、症状和医疗史,ChatGPT 可以为医疗专业人员提供有价值的见解和建议,用于诊断和治疗。
-
医学教育:ChatGPT 提供准确和全面信息的能力使其成为医学教育的宝贵工具。它可以作为医疗保健提供者和患者的信息资源,提供关于各种医疗状况和治疗选项的信息。
将 ChatGPT 应用于培训师或面试官的角色也是该技术可以大放异彩的领域:
-
心理健康咨询: ChatGPT 可以作为设计用于提供心理健康咨询的聊天机器人的基础。通过分析患者数据并提供个性化建议,这些聊天机器人可以帮助患者管理他们的心理健康状况。尽管不能替代专业咨询,但这些人工智能平台可以提供初步的支持和指导。
我们已经看到,会话式人工智能技术在多个聊天机器人产品中成功应用,例如 Woebot (
woebothealth.com) 和 Wysa (www.wysa.com)。 -
患者参与和依从性: ChatGPT 还可以用来加强患者参与和治疗方案的依从性。它可以生成个性化的提醒和建议,帮助患者遵守他们的处方方案。这种由人工智能驱动的患者参与方式对于慢性病管理尤其有益,因为药物依从性至关重要。
ChatGPT 在医疗和医学领域的应用是多方面的,并且具有深远的影响。通过在诊断、患者参与和研究方面提供可靠和基于数据的解决方案,ChatGPT 正在为人工智能辅助医疗的新时代铺平道路。
法律和法律服务
人工智能正在越来越多地渗透到各个领域,法律领域也不例外。ChatGPT 的应用范围从总结法律文件、协助起草法律简报到提供法律研究和促进法律专业人士之间高效沟通的见解:
-
合同审查: ChatGPT 在审查合同时可以发挥关键作用,能够发现需要进一步审查或修改的法律问题,如不一致或含糊不清的条款。
-
法律咨询聊天机器人: 再次,这是另一个特定于会话式人工智能的应用场景。ChatGPT 可以作为法律咨询聊天机器人的基础,能够帮助客户处理法律咨询。由 ChatGPT 驱动的代理可以分析法律数据,并提供个性化的建议,帮助客户了解他们的选择。
-
文档起草: ChatGPT 可以通过分析相关法律数据,提出有见地的内容和建议,从而简化复杂法律文件(如合同和简报)的起草过程。
-
尽职调查和电子发现: ChatGPT 可以成为进行尽职调查和电子发现的有力工具,能够评估法律文件、执行背景调查、识别可能的法律挑战,以及通过审查文本数据、识别主导趋势和模式,帮助在法律纠纷中确定相关的文件和数据。
总之,ChatGPT 对法律和法律服务的影响是深远的。它提供了变革性的解决方案,增强了法律专业人士的能力,使他们能够更高效、更有效地履行职责。从促进法律研究和合同审查,到简化法律文件的起草和加快电子发现,ChatGPT 确实正在改变法律服务领域,塑造一个 AI 和法律实践内在交织的未来。
教育和培训
教育和培训是关于 ChatGPT 以及一般 LLMs 的热门话题。随着 LLMs 变得越来越智能,它们在教育领域的应用也变得更加广泛,从提供实时反馈、生成吸引人的教育内容、协助教育工作者和创建适应性学习环境:
-
个性化学习:ChatGPT 在个性化学习体验中可以发挥关键作用。通过使用关于学习者偏好的数据、优势、劣势或能力水平,ChatGPT 可以生成学习材料和活动的建议,遵循任何特定领域的个性化计划。
-
教师支持:同样,ChatGPT 可以通过根据特定年龄、课程或水平提出针对性的课程计划建议,以及提供不同的课堂管理和教学方法,显著地协助教育工作者。
-
考试准备:ChatGPT 可以成为考试准备的重要工具。它可以提供学习材料的建议,以及创建练习考试和试卷。
这些能力还可以通过与新的媒介,如数字人相结合,实现丰富的学习体验。
总之,AI 与教育的交汇点开辟了无数的可能性。在教育领域使用 AI 语言模型如 ChatGPT 对教学和学习实践产生了深远的影响。从个性化学习、教师支持到语言学习、考试准备和在线辅导,ChatGPT 的应用正在帮助重塑教育格局,使其更加个性化、吸引人、有效。随着我们继续前进,我们可以期待在教育中看到更多创新的 AI 应用,引领一个由技术赋能的新学习时代。
这里列出的许多应用与本章早期部分“理解对话式 AI 应用”中涵盖的使用案例类似。过去,许多对话式 AI 解决方案已经针对它们开发,并取得了不同程度的成功,这并不令人惊讶。
ChatGPT 的局限性
与其他 LLMs 一样,ChatGPT 并非完美无缺,它存在一些重要的风险、局限性和安全考虑,如果你打算在生产对话式 AI 用例中使用 ChatGPT,这些是需要注意的。
局限性
毫无疑问,ChatGPT 拥有一些令人难以置信的能力,但让我们来看看事情可能出错的地方。
准确性和深度
可能最著名的限制,也是人们投入最多努力去克服的,就是 ChatGPT 的“信息截止日期”。早期的 GPT-4 模型是在公开可用的互联网数据上训练的,截止日期可以追溯到 2021 年。最新的 GPT 模型已经显示出改进。根据 OpenAI 的说法,最新的 GPT-4 Turbo (gpt-4-turbo)的知识截止日期是 2023 年 12 月。然而,在此之后,它并没有更新最新的信息或事件。这种限制意味着,使用 ChatGPT 实现的对话式 AI 应用无法原生支持 2023 年 12 月之后发生的数据或事件,至少直到发布新的模型。
ChatGPT 回答关于私人数据或更近期的信息的能力,当然是许多对话式 AI 应用的核心要求之一,我们将在稍后更详细地探讨这一点。
幻觉与准确性
在 LLM 的背景下,“幻觉”指的是模型生成的不连贯、不相关或不准确的文本。ChatGPT 等 AI 系统中的幻觉问题是一个复杂的问题。这可能会发生,因为 ChatGPT 在数据中学习了某些模式,这些模式并不适用于任务的特定上下文。在其他情况下,LLM 可能会生成与输入或任务完全不相关的文本,这可以描述为“幻觉”文本。对于 ChatGPT 来说,幻觉是其中最令人担忧的问题之一。
这不仅仅是 AI 编造事情的问题;这是 AI 生成可能有害或误导性信息的问题。在 AI 的输出被用于做出重要决策或向人们通报关键问题时,这个问题尤其严重。
主要担忧之一是 ChatGPT 生成的输出的准确性。OpenAI 承认,输出有时可能是不准确的、不真实的或误导性的。这对那些希望依赖由 ChatGPT 驱动的生产应用的公司来说是一个复杂的问题。
准确性不仅仅是 ChatGPT 对话式 AI 应用中的一个考虑因素。任何生成的内容都需要经过审查,并确保其真实性,这可能会出现问题。2023 年 6 月,两名美国律师因提交来自 ChatGPT 的虚假法庭引证而被罚款。律师的事务所在虚假引证和引证是由 ChatGPT 创建并作为航空伤害索赔的一部分提交的事实曝光后受到了惩罚。
虽然 ChatGPT 擅长生成看似连贯和逻辑的文本,但其回答可能并不总是正确或足够详细。输出通常需要人工审查和强大的验证机制。解决幻觉问题并始终保持 ChatGPT 无法辨别事实准确性的认识,对于确保 ChatGPT 应用的可靠性和安全性至关重要。
上下文限制
ChatGPT 通过使用每次对话新回合之前的对话信息来管理对话上下文。这样,它知道之前说了什么,并可以利用这些信息作为其决定接下来说什么的过程的一部分。
尽管上下文理解能力有所提高,但 GPT-3.5 和 GPT-4 都有上下文限制,GPT-4 的限制明显更大。这种限制可能导致 ChatGPT 只考虑其最新的输出,而忽略了互动中较早的上下文。OpenAI 最近也发布了一个新的针对聊天的特定模型:gpt-3.5-turbo-16k,其上下文容量是早期模型的四倍。上下文限制是一个可以通过摘要策略和书中后面提到的方法进行改进的领域。
风险和安全
ChatGPT 的快速采用和广泛使用引发了重大的安全和知识产权(IP)担忧,担心这项技术可能被犯罪企业滥用。
财产权
另一个复杂问题是公司的知识产权,尤其是在声称对 ChatGPT 生成的内容或部分由 AI 生成的内容拥有权利时。
根据 OpenAI 的使用条款,用户拥有输入内容,而 OpenAI 将所有其权利、所有权和利益转让给输出内容。然而,OpenAI 无法转让其最初不拥有的内容的权利。这导致了关于 AI 生成知识产权及其所有权的未解决疑问。
安全性
这并不是与 AI 和 ChatGPT 功能本身相关的安全问题,但考虑到 OpenAI 的用户数量,这是一个非常现实的问题。2023 年,OpenAI 确认了一起由代码开源库中的漏洞引起的数据泄露事件,这测试了 ChatGPT 自身的安全性。这次泄露允许用户看到其他活跃用户的聊天历史,引发了关于用户数据安全性的担忧。漏洞很快被修补,但它突显了使用 AI 技术可能带来的潜在风险。
在另一起事件中,更深入的调查发现,同样的漏洞可能在 ChatGPT 下线之前暴露了几个小时的用户支付信息。这一事件进一步引发了关于敏感用户数据安全性的担忧。
ChatGPT 插件的日益流行也可能通过无意中启用有害或未预期的行为来放大安全风险,尽管 OpenAI 做出了最大努力。
教育方面的担忧
如前所述,ChatGPT 可以通过教育测试并执行现实世界的应用。这导致了教育专家和学术界对伦理问题、作弊和学校中的滥用表示担忧。
许多学术机构已经在其网络上禁止了这项技术,这是一个徒劳的措施,但也表明人们确实担心学生可能会利用 ChatGPT 来撰写论文、作弊并规避学习过程。这引发了关于学术机构诚信以及学习和教育本质的问题。随着 LLM 能力的增长,这些问题只会随着其他 LLM 技术在识别 AI 生成内容方面的增长而增加。
隐私担忧
使用 ChatGPT 等 AI 语言模型也引发了隐私担忧。这些模型存储了大量的数据,并使用这些信息来生成回应。
已用于训练模型的内容是一个主要问题,但另一个更紧迫的问题是 ChatGPT 对话数据会发生什么。
如果将敏感数据,如组织的知识产权或敏感客户信息输入到聊天机器人中,它就会进入聊天机器人库,并超出用户的控制。
针对这些担忧,一些企业和国家已经加强了对人工智能使用的限制。例如,摩根大通和苹果公司因安全担忧而限制了员工使用 ChatGPT。
意大利因通用数据保护条例(GDPR)合规问题而暂时在全国范围内封锁了该应用程序。
值得注意的是,ChatGPT 允许用户停止记录聊天历史,但如果用户将内部数据(如病历)作为其提示工程的一部分,这是一个重要的考虑因素。
恶意使用
ChatGPT 的许多优势,如逼真的对话能力和文本生成,很可能会被用于犯罪目的,从工业规模的增强钓鱼到有针对性的虚假信息传播。
犯罪分子也将能够使用不太传统的媒介,如消息平台,来进行针对性攻击。
在过去,钓鱼邮件通常具有语法差和句子结构不寻常的特点,这使得它们很容易被识别。犯罪分子将利用 ChatGPT 来开发令人信服的钓鱼邮件。这些邮件现在可以模仿母语人士并传递定制信息。ChatGPT 无缝翻译语言的能力预计将大大增强外国犯罪分子进行全球攻击的能力。
偏见
与许多其他 LLM 一样,ChatGPT 是在互联网上的人类生成内容上训练的。因此,ChatGPT 容易受到各种偏见的影响,包括性别、种族、文化、语言、意识形态和商业偏见,以及其他一些偏见。
偏见问题范围广泛;以下是一些例子:
-
生成内容未能融入对多样化个人经验和语言细微差别的全面视角
-
制定基于性别或种族分配角色或工作的回应,从而加强现有的刻板印象
-
创建描述对某些社会哲学或政治意识形态有微妙偏见的文本
-
产生与训练数据中存在的占主导地位叙事相匹配的内容,导致产生耸人听闻或寻求关注的标题和声明
即使有安全措施,这些模型有时也会说出性别歧视/种族歧视/恐同的话。在使用面向消费者的 LLM 应用时请小心,当使用 ChatGPT 进行研究时也需要格外小心。
摘要
总之,在本章中,我们看到了从基于规则的到基于 AI 驱动的意图系统的对话 AI 如何稳步发展。通过观察 ChatGPT 的应用,我们看到随着现代对话 AI 系统能力的增长,对话体验的使用案例的广度和深度也在增加。有成千上万的这些系统,在多个行业中执行复杂任务。
从我们最初对 ChatGPT 的关注来看,我们看到它是一个强大的工具,具有通过承担更多复杂任务和使用案例来颠覆对话 AI 领域的潜力,这些任务和使用案例直到最近都难以用现代对话 AI 平台实现。它在许多行业中提供了广泛的应用,包括客户服务、医疗保健、金融、法律、教育等。
然而,本章也强调了了解其局限性和风险的重要性,包括准确性和深度限制、幻觉、上下文限制、安全问题、隐私问题以及偏见。这些挑战在开发和使用 ChatGPT 应用时需要仔细考虑和缓解策略。随着我们继续前进,解决这些限制并确保 ChatGPT 被负责任、道德地使用,并采取适当的保护措施至关重要。
在我们开始探讨使用 ChatGPT 创建对话应用之前,让我们看看这项技术如何在传统的对话设计中得到应用。
在下一章中,我们将更深入地探讨 ChatGPT 的对话设计应用。我们将探讨如何使用 ChatGPT 设计有效且吸引人的对话,涵盖对话流程、用户提示、系统响应、上下文管理等多个方面。加入我们,一起揭示创建强大且富有意义的对话 AI 体验所需的实用技能。
进一步阅读
要了解更多与本章节相关的话题,您可以访问以下链接:
-
企业对话 AI
www.gartner.com/reviews/market/enterprise-conversational-ai-platforms -
弥合差距:关于自然语言生成中(人类)反馈整合的调查
第二章:使用 ChatGPT 进行对话设计
在本章中,我们将深入探讨 ChatGPT 与对话设计的交汇点。我们将探讨对话设计师的角色,并探讨大型语言模型(LLMs)如 ChatGPT 如何影响对话设计。我们还将检查 ChatGPT 在对话设计中的实际应用,包括其在模拟对话和创建角色中的应用。最后,我们将讨论测试和迭代设计在创建有效和引人入胜的对话人工智能系统中的重要性。到本章结束时,您将全面了解如何利用 ChatGPT 进行对话设计。
一些提示结果被列出,而其他结果则因空间限制而被省略。我们鼓励您亲自尝试这些提示。
在本章中,我们将涵盖以下主要主题:
-
理解对话设计
-
与 ChatGPT 在对话设计中的实际应用合作
-
模拟对话
-
使用 ChatGPT 创建角色
-
使用 ChatGPT 进行对话设计的测试和迭代
技术要求
在本章中,我们将使用 ChatGPT。我们建议您在 OpenAI 上注册。
理解对话设计
对话设计是一个复杂且重要的角色,对于创建一个有用、自然并且因此成功的聊天机器人或语音助手至关重要。对话设计领域还有其他角色,尤其是 AI 训练师及其变体。为了本书的目的,在讨论对话设计时,我们将考虑这些其他角色,因为许多任务的执行在这些角色之间有很大的重叠。
对话设计利用用户体验设计、语言学、认知心理学和人工智能的原则,通过语音或文字媒介创造人类与机器之间引人入胜的互动体验。在核心上,对话设计师理解沟通、对话人工智能的技术格局、向用户部署的媒介,以及如何满足用户需求。
对话设计的目的是创建一个流畅、直观、自然的用户界面,使用户感觉像是在进行类似人类的对话,同时利用现有技术来模拟这种对话。
探索对话设计师的角色
对话设计师执行几个重要的任务。这些任务很重要,这样我们才能看到 LLMs 和 ChatGPT 如何被用来简化并改进这个过程。让我们看看创建对话设计所涉及的过程。这些设计将在项目所选的对话人工智能平台上实施。
理解用户需求
对话设计的第一步是理解用户的需求和行为,以及对话发生的背景。
对话设计师的角色是理解组织的运营、流程、挑战和目标。一个好的设计师可以将业务需求转化为客户旅程、用例和自然流程。设计师需要了解目标用户的角色,包括他们的年龄、人口统计、需求、期望和语言。他们还需要了解组织或应用中的当前交互。对现有查询和现有非结构化或结构化数据的彻底理解在这里尤为重要,对对话体验将部署到的渠道的深入了解也同样重要。
设计角色
代理的角色不仅决定了其语气,还指导了其对话方式。这需要仔细考虑以匹配用户需求。
还需要考虑现有的品牌和内容指南。
例如,部署在企业软件平台上处理客户支持查询的聊天机器人,其语气和角色将与设计在新生入学周期间帮助学生在 WhatsApp 上查询的代理不同。
设计对话
对话流程是用户与对话代理之间交互的序列。
对话设计师需要优先考虑现有用例,以了解代理需要执行的任务以及如何构建对话来实现这一目标。
意图澄清、话语创建和实体澄清
意图代表了用户的意图。例如,意图可能是查询订单状态或预订航班。每个意图都与一组话语相关联,这些话语是用户可能用来表达该意图的短语。例如,对于检查航班状态的意图,话语可能是“我的航班什么时候起飞?”或“我的航班 准时吗?”。
实体是聊天机器人需要用来实现意图的具体信息片段。例如,对于预订航班的意图,实体可能是出发城市、目的地城市和旅行日期。理解每种类型的实体及其不同条目是对话设计师的工作。常见的实体通常很简单,因为它们由对话 AI 模型支持。然而,如果需要自定义实体,每个都需要单独获取。例如,一个狗训练聊天机器人可能需要理解所有不同的狗品种。
对话设计
在对话的用户旅程被规划出来后,对话设计师的任务是创建交互的细节。这包括设计用户与对话代理之间的对话流程。它包括定义聊天机器人将用于引导对话的提示、用户响应和代理的回复。对话应该设计得自然且引人入胜,并引导用户实现他们的目标。
设计师会仔细编写对话和响应的不同路径。这些路径基于可能的用户输入,其中需要收集信息以使用户能够传达他们的需求,并使代理收集回答查询所需的值。设计师从通常所说的“快乐路径”开始,这是实现目标的最简单对话路径,然后扩展以处理对话周围的边缘情况。
设计需要支持其他情境边缘情况,例如未处理的意图、不匹配的意图、输入时以及用户尝试引导对话的任何其他方式。这里有很多需要记录的内容。随着对话的许多转折,这些设计可能会变得复杂,因为对话通常不是线性的,用户可能会改变话题或提出意外的问题。这是对话设计师在设计中包含这一点的任务。
对话设计通过以下几种不同的方法在项目利益相关者之间共享:
-
流程图
-
电子表格
-
模拟伪代码
-
对话管理软件,如 Voiceflow
根据项目的大小、团队和预算,以及个人偏好,没有一种适合所有对话设计工具的方法。只要它们易于迭代和协作,这些设计通常会在签署前被多个不同的团队触及。然而,一些更受欢迎的对话管理工具提供了比设计和协作更多的功能,并包括一些利用 LLMs 的非常有用的功能。这将在下一节中介绍。
写作
最后一步是编写聊天机器人的实际回复文本。这需要使用有说服力和引人入胜的语言引导用户通过对话。文案应反映聊天机器人的个性,并与品牌的语气和风格保持一致。对于拥有数百甚至数千个回复的大型代理,挑战通常在于确保一致性,尤其是在有多个对话设计师同时或随着时间的推移在一个项目上工作时。随着对话人工智能项目的成熟,这种情况发生的可能性更大。由于每个参与者都会为项目带来自己的风格,因此语气可能会偏离代理的原始个性和品牌指南。
在我们介绍了对话设计师的角色以及构成对话设计过程的特定任务,并在实施对话式人工智能解决方案之前,现在是时候看看 ChatGPT 在这些特定工作流程中可以如何被利用了。
在对话设计中使用 ChatGPT 的实际应用
从我们对需要执行对话设计任务的了解来看,很容易看出在某些领域,我们可以利用 ChatGPT 来帮助完成这些任务。一些最受欢迎的对话设计工具也提供了作为其功能一部分执行这些任务的能力。
小贴士
记住,ChatGPT 是一个对话设计工具,而不是对话设计最佳实践的替代品。
使用 ChatGPT 进行意图聚类
意图是大多数传统对话式人工智能代理的核心概念。意图的存在是为了定义用户的意图,每个意图都需要有一组话语来触发这个意图。许多对话式人工智能实现都是从大量的实时聊天数据、语音转录或其他非结构化文本数据开始的,这些数据将形成聊天机器人或语音界面需要支持的任务或意图的基础。
意图聚类有什么用?
一个对话式人工智能项目可能还处于起步阶段。它也可能是一个在重压下使用或主题内容经常变化的成熟项目。通常,对话设计师或 AI 训练师的工作是利用这些数据通过聚类非结构化训练数据或话语来理解和优先排序意图。
例如,如果你正打算从实时聊天过渡到聊天机器人自动化,你可能有一个大量的历史聊天语料库。你将需要查看这些数据并决定哪些常见问题或意图被问得最多。同样,处理特定流动主题内容(如假日)的聊天机器人或语音助手可能需要定期更新以回答由外部因素引起的新问题。这些新问题可以通过聚类来突出显示。
什么是意图聚类?
意图聚类本质上意味着查看大量数据并寻找语义相似句子的分组。因此,对于我们的用例,我们将查看我们的非结构化聊天数据,并根据语义相似的意义进行分组,以便我们可以开始浮现意图。
在过去,通过聚类进行意图浮现的过程涉及使用嵌入的复杂过程,或者使用如 HumanFirst 之类的专有解决方案。这个过程将遵循以下步骤:
-
数据收集:组装你想要分析的文本数据语料库。这可能包括从科学文章的集合到用户生成内容的数据库。
-
嵌入生成:使用 TensorFlow 等机器学习库、Word2Vec 等服务或双向编码器表示的 Transformer(BERT)生成文本数据的相似性嵌入。这些嵌入是高维向量表示,捕获文本的语义内容。因此,如果一个文本与另一个文本具有相似的意义,那么嵌入将更接近。
-
聚类算法:将无监督机器学习算法(如 K-means)应用于生成的嵌入。这些算法根据点之间的密度和距离将高维嵌入空间分离成簇。
-
聚类分析:一旦完成,应该有一组包含语义相似文本的话语簇。分析这些簇可以揭示意图或问题,然后可以用来训练基于意图的机器学习模型。
在这个背景下,聚类是一种无监督技术,它使用语义嵌入将相似文本分组在一起,帮助发现大量非结构化文本数据集中的潜在意图。
学习如何使用 ChatGPT 创建意图簇
当你遵循简单的提示工程规则时,使用 ChatGPT 实现这一点很简单:指令、上下文、输入数据和输出指示符。我们将在第四章中更详细地介绍更多提示工程示例。
对于我们的意图,提示可能看起来像以下这样。重要的是要注意,设计提示是一个迭代过程,有时需要实验才能得到你想要的结果。
对于我们的第一个示例,我们正在创建一个用于我们大学网站的聊天机器人,该机器人将回答有关大学的问题。我们有一组从实时聊天实现中收集的非结构化话语。
对于这个示例,我们在提示中使用指令、输入数据和输出指示符。指令和输入数据处理告诉 ChatGPT 我们想要什么以及使用哪些话语。输出指示符还显示了我们想要的输出格式。在这种情况下,JSON 将最有用,因为我们正在考虑将意图或话语作为自动化过程的一部分使用。该模型还将处理其他输出格式,如 CSV。它看起来像这样:
Look at the following utterances from livechat transcripts and cluster them into intents
Utterances: "can you tell me where is the college located", "where's the college", "where is college located", "how can I reach college","whats is the college address", "whats the Syllabus for IT", "what is the Information Technology syllabus"," "Whats my next lecture"
Output: Return as JSON in the following format-{"intent": {name},"utterance":{utterances}}
结果应该看起来像以下这样:
[
{
"intent": "Get_College_Location",
"utterances": ["can you tell me where is the college located", "where's the college", "where is college located", "how can I reach college"]
},{
"intent": "Get_College_Address",
"utterances": ["whats is the college address"]
}
]
除了通过 ChatGPT 界面手动创建意图外,还可以通过直接使用 ChatGPT API 进一步自动化此过程。
将示例扩展以创建意图
考虑到我们的聊天机器人用例,我们可能希望通过创建更多意图来构建我们的意图集。例如,如果你的实时聊天数据有限,并且你想扩展到其他意图,你可以使用 ChatGPT 执行一个任务,通过使用一些现有的意图来创建更多意图和话语。
让我们通过使用我们之前示例的输出,提示意图聚类来创建我们的提示,您可以在提示中看到{``input_data}占位符:
Look at the following intents and utterances for a chatbot which will answer questions about a college, these JSON objects consist of an array of intent objects, each of which includes a name and a list of corresponding utterances.
Create another 5 examples of intents and ensure that each intent has 10 utterances:
Intents:
{input_data}
Output: Return as JSON in the following format-{"intent": {name},"utterance":{utterances}}
如果我们运行这个提示,我们可以看到这很有效。这是输出:
[
{
"intent": "Get_College_Events",
"utterances": ["Whats happening on Tuesday","What are the upcoming events?", "Can you tell me about any college events?", "What's happening on campus?", "What events are scheduled this month?", "Is there a college event this week?", "Are there any sports events coming up?", "When is the next cultural fest?", "Are there any seminars or workshops?", "What's the college event calendar?", "Are there any academic events happening soon?"]
},
{
"intent": "Inquire_About_College_Facilities",
"utterances": ["What facilities are available in the college?", "Does the college have a library?", "Can you tell me about the sports facilities?", "What are the lab facilities in the college?", "Are there any on-campus cafeterias?", "Does the college have a gym?", "Are there any hostel facilities?", "Does the college have a swimming pool?", "Tell me about the medical facilities", "Are there any recreational facilities in the college?"]
},
...
]
理解语句和实体生成
在现代对话式人工智能系统中,意图和实体是至关重要的组成部分,它们使系统能够理解和处理人类语言,从而实现更自然、更有效的对话。创建这些元素是对话设计师最常见的任务之一。这些元素随后可以用于训练我们用于对话式人工智能平台的机器学习模型。
创建语句
在前面的如何使用 ChatGPT 创建意图聚类部分,我们探讨了如何从非结构化训练数据中聚类语句以提取意图。ChatGPT 也可以用来创建语句。
如果我们没有足够多的语句来满足特定的意图,我们可以提示 ChatGPT 为特定意图创建一组语句,如下所示:
Consider a "Get_College_Events" intent for a chatbot which will answer questions about college events.
Create another 10 examples of utterances for each intent:
Output: Return as JSON in the following format-{"intent": {name},"utterance":{utterances}}
结果令人惊讶地好:
[
{
"intent": "Get_College_Events",
"utterances": ["What's happening in college this week?", "Tell me about the upcoming college events.", "Are there any events in college next month?", "Is there a sports meet this year?", "What are the details of the cultural fest?", "When is the next science fair?", "Is there any guest lecture scheduled soon?", "When is the annual college fest?", "Are there any workshops I can attend?", "Can you give me a list of events for this semester?"]
}
]
我们还可以更具体地说明语句的类型。例如,如果我们想要更广泛的语句范围,我们可以提示 ChatGPT 提供更长的尾部示例。让我们以“获取大学位置”的意图用例为例,向现有语句中添加长尾语句:
Look at the following intent for a chatbot that will answer questions about a college, these JSON objects consist of an array of intent objects, each of which includes a name and a list of corresponding utterances.
Create another 5 examples of long tail utterances for each intent and add to the array of utterances
Utterances:
[
{
"intent": "Get_College_Location",
"utterances": ["can you tell me where is the college located", "where's the college", "where is college located", "how can I reach college"]
}
]
Output: Return as JSON in the following format-{"intent": {name},"utterance":{utterances}}
这使得我们的 NLU 训练数据集的语句范围更广:
[
{
"intent": "Get_College_Location",
"utterances": ["can you tell me where is the college located", "where's the college", "where is college located", "how can I reach college", "I am new to this city, can you guide me to the college?", "Can you provide the exact location of the college?", "I am not familiar with the area, could you help me find the college?", "I would like to visit the college, can you tell me its location?", "I need directions to the college, can you help?", "Could you give me the location details of the college?"]
}
]
每个创建的语句都符合我们的标准,具有更对话式和复杂的(长尾)格式。
小贴士
记住,人工训练数据,即使是 LLM 创建的,也不能替代真实使用数据。这一点在创建语音语句时尤其正确,因为 ChatGPT 是在文本数据上训练的。
创建实体
ChatGPT 非常擅长的一项生成任务是创建实体。
实体是与意图相关的具体信息片段。它们是提供用户请求详细信息的变量。
例如,考虑我们的Get_College_Events意图。为了正确回答问题,我们需要了解一些事情:事件的日期和类型。虽然系统日期通常由对话式人工智能平台支持,但为了训练 NLU,通常需要创建自定义实体。对于这个特定用例,事件类型就是我们需要填充的自定义实体。我们可以请 ChatGPT 帮助我们。记住,提示要尽可能具体。在这种情况下,我们要求输出格式正确,以便导入到我们的对话式人工智能平台:
Consider a "Event_Type" entity which needs to be extracted from utterances for the Get_College_Events for a chatbot which will answer questions about college events.
Create 5 examples of entity_val and 5 synonyms for each entity type:
Output: Return as JSON in the following format-{"entity_val":
{entity_val},"synonyms ": [synonyms] }
结果是一套全面的实体类型及其对应同义词:
[
{
"entity_val": "seminar",
"synonyms": ["workshop", "conference", "symposium", "meeting", "forum"]
},
{
"entity_val": "sports meet",
"synonyms": ["athletic meet", "sports event", "sports day", "athletic event", "games"]
},…
]
通过正确地查找和处理实体,ChatGPT 可以快速创建精确且有用的响应。
在没有客户对话数据的情况下,ChatGPT 的语句可以作为启动聊天机器人进行进一步迭代的好方法。
使用 ChatGPT 帮助编写您的对话
编写引人入胜的聊天和语音对话是对话设计师角色的重要部分。那么,ChatGPT 如何帮助,您甚至应该考虑使用它吗?
理解编写对话的挑战
作为对话设计师,我们工作中最吸引人但最具挑战性的方面之一是制作聊天机器人或语音助手的回应。毕竟,这是您展示自己的机会。好的对话是平淡的对话体验和真正吸引用户的对话体验之间的区别。
创建示例对话,确保对话流中各部分之间的平稳过渡,并为高度具体的环境制定精确的回应,这些都需要时间和仔细的考虑。这一切都是在应对满足截止日期的压力、保持利益相关者知情并采取反馈行动的同时完成的。以下是一些需要考虑的事项:
-
保持与您的 AI 助手角色相呼应的声音和语调
-
遵守公司内容指南
-
使用与您可能需要提供给用户的内含内容相一致的语言
-
能够熟练且一致地处理错误情况
-
在说得太多和过于冗长之间找到平衡
-
确保精心制作的回应在各种模态中都是有效的,而不仅仅是理论上
-
解决可能影响我们使用语言的内隐偏见,并可能对最终用户产生影响
-
仔细遵循法律和合规指南,以确保我们使用的语言是正确的,不会让您陷入法律麻烦
从本质上讲,编辑对话性对话是一系列复杂的任务,需要创造力和精确性的微妙平衡。
使用 ChatGPT 编辑您的对话
ChatGPT 可以执行多项任务来增强您的对话。让我们深入探讨一些例子,例如重新编写以提高可读性、检查内容指南或为更好的对话体验创建副本的不同版本。
重新编写以提高可读性
如果您有不适合您用例的副本,但仍然需要传达包含的信息,您可以要求 ChatGPT 为您重新编写。以下是一个执行此操作的提示示例。这是一个临床试验患者信息表的副本:
I'm writing a chatbot response for my "what is the purpose of this drug trial" intent. Revise this dialogue to make it more understandable for clinical trial patients and ensure it's under 100 words:
Chronic kidney disease (CKD), affecting 1 in 10 UK adults, is a progressive loss of kidney function that can lead to complete kidney failure, requiring dialysis or transplantation. High blood pressure treatment, especially with drugs like Angiotensin Converting Enzyme inhibitors (ACEi) or Angiotensin Receptor Blockers (ARBs), can slow CKD progression. However, recent research suggests that stopping these drugs in advanced CKD (stage 4 or 5) can stabilize kidney function and delay dialysis, indicating these drugs might contribute to kidney function decline. To confirm this, the ACEi trial will recruit 500 CKD stage 4 or 5 patients on ACEi/ARBs treatment, randomly allocating half to continue and half to stop their treatment. The trial will also examine other effects of stopping these drugs, such as heart effects and participant quality of life.
从结果来看,您可以看到 ChatGPT 在总结内容方面做得非常出色:
The STOP-ACEi trial is for CKD patients, a kidney condition affecting 1 in 10 UK adults. We're studying if stopping certain blood pressure drugs (ACEi/ARBs) can help stabilize kidney function and delay the need for dialysis. We'll have two groups: one continues the medication, the other stops. We aim to understand the best approach for CKD treatment
用您自己的示例文本尝试这个方法。不断迭代您的提示,直到您对结果满意为止。
另一个良好的对话创建示例是为特定目的重新编写内容。例如,如果我们想从描述性副本中创建一组简洁的说明,我们可能会使用以下方法:
I'm writing copy for my dog training chatbot intent "how do i teach my dog to sit". Rewrite these instructions into a set of steps in the style of Barbara Woodhouse. Each step can only be 150 characters. Also write an introductory sentence:
Training a puppy to sit is one of the most basic commands and is useful in various situations. Start by holding a treat close to your puppy's nose and then move your hand up, allowing their head to follow the treat and causing their bottom to lower. Once they're in sitting position, say "sit", give them the treat and share affection. Remember, repetition is key. Practice this command a few times each day and be sure to reward your puppy for sitting even without command, to reinforce this behavior.
提供具有上下文、输入和输出指令的简洁说明,可以得到良好的结果,并且是我们可以工作的内容。用您自己的例子尝试这个方法。
认为我们可以自动化响应创建是很诱人的。然而,这样做并不明智。ChatGPT 创建的内容只是一个起点。确保 ChatGPT 提供正确的信息,同时不改变意义,并遵守你的对话设计要求是至关重要的。
使用 ChatGPT 创建用户画像
用户画像在以用户为中心的设计中是关键组成部分,因为它们使组织能够了解他们的目标受众,并构建满足他们需求的解决方案。本节将深入探讨如何使用 ChatGPT 生成复杂和智能的用户画像。
真实世界案例
认识 LuxeLocks,这是我们虚构的公司,专门销售奢华护发产品。LuxeLocks 热衷于为其客户提供高端、高质量的产品,将他们的头发变成荣耀的象征。为了将客户服务提升到下一个层次,并随时回答查询,LuxeLocks 决定实施聊天机器人。
这个聊天机器人将被设计成以各种方式协助客户,从帮助他们根据头发类型和问题选择完美的产品,到回答关于产品使用和成分的常见问题,甚至协助订单跟踪和退货。
通过提出问题和呈现场景,你可以深入了解用户偏好、行为和痛点。
画像创建基于硬事实和特定用户数据。使用 ChatGPT 不是真实研究的捷径,但它可以帮助。
使用 ChatGPT 进行用户研究
在本书中概述通过调查、访谈和市场研究收集关于目标受众信息的过程超出了范围。这也无法替代。以下是一些外部资源,以了解更多关于此过程的信息:
-
我推荐的每本 UX 书籍及其原因
然而,使用 ChatGPT 帮助你提出一些进行研究的想法是可行的。你可以通过以下提示来完成:
Create an outline for market research, including surveys, interviews, and additional market research methods for a luxury haircare brand:
至少,输出可以形成一个基础,开始你的研究。这可能看起来是这样的:
A. Customer Interviews:
Purpose: Gain deeper insights into the customer experience.
Sample Questions:
Describe your haircare routine.
What led you to try our brand?
Are there any challenges you have faced with our products?
B. Expert Interviews:
Purpose: Gather insights from industry experts, such as hairstylists or dermatologists.
Sample Questions:
What trends are you currently noticing in the luxury haircare market?
How do you think our brand is perceived in the market?
IV. Additional Market Research:
A. Competitor Analysis:
Purpose: Understand the competitive landscape.
Identify key competitors in the luxury haircare market.
Analyze their product range, pricing strategy, marketing efforts, and customer reviews. Identify their strengths and weaknesses.
B. Focus Groups:
Purpose: Gather qualitative data on potential new products or marketing strategies.
Assemble a diverse group of individuals who are part of the target market. Present them
with new product concepts, packaging designs, or marketing materials.
Facilitate a discussion to gather their feedback and impressions.
C. Market Trend Analysis:
Purpose: Identify current trends in the luxury haircare market.
Review industry reports and publications for data on emerging trends.
Analyze social media and influencer content to identify popular products and ingredients.
…..
一旦你有了详细信息,你还可以使用 ChatGPT 来分析数据,并揭示一些关于用户群体的细节:
Based on the following data {data}, please describe the main demographic characteristics and preferences of our target audience.
Preferences:
Characteristics:
LuxeLocks 用户的偏好和特征可以帮助我们构建用户画像,并为我们的聊天机器人画像提供指导。
创建我们的用户和聊天机器人画像
您可以使用从早期提示中创建的人口统计特征来帮助您创建用户和聊天机器人角色。
创建我们的用户角色
让我们提示 ChatGPT 创建一个角色,并使用我们之前提示中的偏好和特征结果。在以下提示中,将*characteristics*和*preferences*替换为这些值:
Create a user persona description for a luxury haircare brand. Users tend to have these Characteristics: *characteristics*
Preferences: *preferences*
The persona is to be the user of our luxury haircare brand over multiple channels. The brand sells high end haircare products which are targeted at specific hair types:
Use the following template:
Name: {first_name}
Age: {age}
Relationship status: {relationship_status}
Occupation: {occupation}
Location: {location}
Interests: {interests}
Bio: {bio}
{first_name}'s motivations:
1\. {motivation 1}
2\. {motivation 2}
3\. {motivation 3}
{first_name}'s goals:
1\. {goal 1}
2\. {goal 2}
3\. {goal 3}
{first_name}'s frustrations:
1\. {frustration 1}
2\. {frustration 2}
3\. {frustration 3}
{first_name}'s Key concern/barrier to purchase:
1\. {barrier 1}
2\. {barrier 2}
3\. {barrier 3}
A quote from {first_name}'s: {quote}
我们可以在后续问题中用这个角色描述来询问 ChatGPT。
创建我们的聊天机器人角色
您还可以使用 ChatGPT 来创建您的聊天机器人或虚拟助手的角色。与任何提示一样,您可以调整包含的信息量,但我发现更详细的提示会产生更好的结果。尝试使用类似以下的内容:
Create our luxury haircare chatbot persona:
Name and Title:
What is the chatbot's name?
Does the chatbot have a title or role (e.g., Customer Care Assistant, Haircare Expert)?
Background and Purpose:
Why was this chatbot created?
What is its primary role in interacting with customers?
我们现在可以使用用户和聊天机器人的角色来指导 ChatGPT 在创建对话和交互相关的进一步任务中。
模拟对话
ChatGPT 可以用来与具有特定角色的潜在用户创建样本对话,这可以帮助创建您的对话流程。我再次强调,这不应取代对话流程设计过程,而是一种有效查看特定用例的方法。
样例对话是什么?
样例对话包括用户和代理之间特定多轮对话的例子。
对于参与对话体验设计和开发的人来说,这些对话片段是必不可少的工具。它们使我们能够探索对话可能遵循的潜在路径,并评估哪些分支需要考虑并整合到最终的对话设计中。
User: What's the luggage limit for my flight to Paris?
Chatbot: May I know the airline you are flying with?
User: It's AirExcellence.
Chatbot: For AirExcellence, you're allowed one carry-on up to 10 kg and one checked bag up to 23 kg. Carry-on size: 55 cm x 40 cm x 23 cm.
User: Thanks!
Chatbot: You're welcome! Have a great flight.
现在我们将来看如何创建我们自己的聊天机器人对话。
创建示例对话
在以下提示中,我们提供有关语气、语言、澄清和对话元素的信息。我们希望在这种情况下提供这些信息,以确保我们已经解决了问题:
Generate a conversation between a user and a customer support chatbot. The user is trying to troubleshoot a problem with their internet connection. The chatbot should follow these content guidelines:
1\. Maintain a polite and professional tone throughout the conversation.
2\. Use simple, clear language that is easy for the user to understand.
3\. Ask clarifying questions to accurately diagnose the problem.
4\. Provide step-by-step instructions to resolve the issue.
5\. Confirm that the user's problem has been resolved before ending the conversation.
6\. If the chatbot cannot resolve the issue, it should suggest the user to contact a human support representative.
User: "Hello, I'm having trouble with my internet connection. It's really slow."
这产生了一个好的对话示例。尝试不同的变体是值得的,这样您可以建立起对对话可能走向的理解。
在这个阶段,我们正在设计我们的流程,但稍后我们也会看到,我们可以将这种技术作为我们测试过程的一部分。
创建带有角色的示例对话
我们可以通过将更多关于用户和代理角色的信息传递到提示中,来构建基于样本对话片段的创建,这些片段到目前为止主要集中在特定的用例上:
We are going to create some sample dialogues between our luxury haircare chatbot and a user:
User persona:
Name: Sophia
Age: 42
Relationship status: Single
Occupation: Corporate Wellness Coach
Location: London, UK
Interests: Pilates, Culinary Arts, Wine Tasting, Sustainable Fashion, Volunteering
...
这里的技巧是向 ChatGPT 提供您的用户和聊天机器人角色的详细信息。一旦您向 ChatGPT 提供了这些信息,您就可以给出后续提示,要求进一步提供对话或用例的示例。
当查看示例用例时,这种技术同样适用。在下一个提示中,我们将在此基础上继续,并要求另一个对话示例:
Using the persona descriptions of Sophia and Lila, create a conversation between them in which Sophia is asking about the best shampoo for her hair type.. Lila asks whether Sophie would like to do her quiz so she can learn about her hair.
ChatGPT 的回应在这里很令人印象深刻,因为它更进一步,创建了一些测验问题,尽管最好的选择是包括您的测验细节。
使用详细提示来创建对话示例的技术也可以用于测试和进一步的迭代,我们将在下一节中介绍。
使用 ChatGPT 进行对话设计和迭代测试
对话设计是一个迭代的过程。自动化智能体总是在变化和改进。在本节中,我们将探讨使用 ChatGPT 测试和改进我们的智能体。
使用 ChatGPT 进行测试
在前面的章节中,我们看到了 ChatGPT 可以通过创建对话来帮助我们设计,从而在简化设计过程中成为一个有价值的工具。在部署之前测试我们的智能体时,我们可以采取类似的方法。
我们通常根据我们认为他们会被问到的问题来创建智能体。如果我们是从零开始启动一个对话人工智能项目,几乎没有训练数据,这种情况就更加可能。如果是这种情况,在将智能体发布到野外之前测试您的智能体就更加重要。
即使对话人工智能项目有内部测试人员,或者您在 alpha 或 beta 发布之前可以向朋友或家人展示您的智能体,但在将其交给人类用户之前尽可能彻底地进行测试仍然很有价值。这就是 ChatGPT 可以发挥作用的地方。
测试的对话模拟
这个过程与设计过程类似。我们可以创建模拟,其中 ChatGPT 扮演用户角色。然后,您可以构建一系列测试用户交互脚本,以便在无需真实用户参与的情况下与聊天机器人进行交互。
我们将在我们的奢华护发聊天机器人示例的上下文中考虑这一点。就像 ChatGPT 被用来创建实体和话语一样,我们也可以用它来生成反映现实对话的额外训练数据。
小贴士
如果您继续使用之前的 ChatGPT 会话,我们已经在提示中设置了角色。如果您开始一个新的会话,请记住将这些添加到您的提示中,以设置上下文。
因此,我们将简单地要求 ChatGPT 创建以问题形式呈现的训练数据结果,这些问题涵盖了与护发、产品推荐、可持续性和个性化流程相关的各种主题,反映了 Sophia 的角色和兴趣:
Create 10 questions which Sophia could ask Lila
我们还可以提示更多长尾示例,以便我们可以用我们的智能体进行测试:
Create 10 long tail questions which Sophia could ask Lila
一旦我们有一组训练问题,您就可以手动测试我们的智能体,或者如果您的聊天机器人提供 API,您可以创建自动化。
创建更具体的测试脚本
对于更复杂的对话交互,ChatGPT 也可以用来创建相同的流程示例,以便您可以使用它们来测试您的智能体。
考虑一个用户对其订单状态感兴趣的具体询问。这可以用作提示 ChatGPT 创建具有不同对话转折的其他示例:
Consider the following enquiry from Sophie about her order:
####
Sophia: Hi, placed an order for the Curl Harmony Shampoo yesterday. Can you tell me when it will be shipped?
Lila: Welcome back, Sophia! I'm glad to assist you. Your order for the Curl Harmony Shampoo is scheduled to be shipped tomorrow. You'll receive an email confirmation with the tracking details once it's on its way. Is there anything else I can help you with?
Sophia:
#####
Create 3 examples of this conversation when Sophie asks follow up questions
然后,您可以通过这些脚本示例运行您的聊天机器人,以查看其表现。
测试失败和边缘情况
对于同一用例的其他对话结果也可以考虑并使用 ChatGPT 进行处理。例如,你可以使用 ChatGPT 来覆盖设计中需要考虑的边缘情况。
一些例子可能涉及用户偏离了快乐路径,或者以下例子,其中存在 Lila 提供答案所依赖的服务问题:
Give 1 example where Lila has technical issues so she can't access any order details.
你也可以提示 ChatGPT 在这里提供自己的建议:
Provide 3 examples of what else could go wrong with the conversation
这些结果可以用来检查你在设计和实施过程中是否遗漏了任何内容。
使用 ChatGPT 迭代你的聊天机器人
一旦你的代理有真实用户进行测试,你就可以使用转录和交互日志来查看如何通过向 ChatGPT 提供示例来改进你的对话设计。
Look at the following chat transcript:
{transcript}
Provide an example of how to improve this conversation
这尤其有用,如果你想要查看失败的对话、以不满意结果结束的对话或以不满意的用户结束的对话。它让你能够查看你可以改进对话流程的方式。
摘要
在本章中,我们重点介绍了如何将 ChatGPT 应用于对话设计。我们探讨了对话设计师的多重角色,并更详细地审视了构成对话设计过程的许多任务。我们了解到,其中一些任务可以在 ChatGPT 的帮助下完成。
我们深入探讨了涉及的实际任务,例如理解用户需求、设计角色、创建对话流程和编写对话。
我们还了解到,理解 ChatGPT 并非是优秀对话设计实践的替代品,而是一个功能极其强大的工具。
我们将 ChatGPT 作为对话设计助手的使用核心是有效实施提示工程。我们开始研究提示工程所涉及的原则。在第四章中,我们将更详细地探讨提示工程,以深入了解这一新兴领域。在下一章中,我们将探讨使用 ChatGPT 的不同方式。
进一步阅读
以下链接是帮助你在本章中使用的资源:
第二部分:使用 ChatGPT、提示工程和探索 LangChain
本部分侧重于 ChatGPT 的实际应用、提示工程的复杂性以及深入探讨 LangChain。你将探索与 ChatGPT 交互的不同方式,无论是通过网页界面、API 还是官方库。你还将深入了解提示工程,学习如何制作有效的提示。最后,本节介绍了 LangChain,指导你了解其基本和高级用法,包括调试技术、内存管理和利用代理增强功能。
本部分包含以下章节:
-
第三章, ChatGPT 精通 – 解锁其全部潜力
-
第四章, 使用 ChatGPT 进行提示工程
-
第五章, LangChain 入门
-
第六章, 使用 LangChain 进行高级调试、监控和检索
第三章:ChatGPT 精通 – 解锁其全部潜力
在本章中,我们将深入探讨使用 ChatGPT 的技术方面,以便你能充分利用这项技术,并使用几种不同的技术有效地与 OpenAI 模型互动。我们将详细介绍与 ChatGPT 互动的四种不同方式——即通过网页聊天界面、OpenAI 游乐场、直接使用应用程序编程接口(API)或使用官方 OpenAI 库之一,所有这些我们都会更详细地探讨。
你将牢固理解 ChatGPT 界面以及免费版和 Plus 版之间的差异,以及自定义指令的力量。接下来,你将了解如何使用 AI 游乐场。最后,我们将介绍如何直接与 API 互动,并探讨 OpenAI 的 Python 和 Node.js 库。
到本章结束时,你将牢固掌握与 ChatGPT 交互的不同方式,并能够就使用哪些技术做出明智的决定。
在本章中,我们将涵盖以下主要主题:
-
掌握 ChatGPT 界面
-
探索 OpenAI 游乐场
-
学习使用 ChatGPT API
技术要求
在本章中,我们将广泛使用 ChatGPT,因此你需要注册一个免费账户。如果你还没有创建账户,请访问openai.com/,点击页面右上角的开始使用,或访问chat.openai.com。
对于入门示例,根据你的编程语言,你需要一个已安装 Python 的环境。
掌握 ChatGPT 界面
使用 ChatGPT 界面是大多数用户开始使用 ChatGPT 的方式,也是与这项技术互动的最简单方法。在撰写本文时,你可以在 iOS 和 Android 上使用 ChatGPT,也可以通过网页使用。
ChatGPT 的免费版和 Plus 版
在撰写本文时,ChatGPT 有免费版和 Plus 版。免费版允许你在一些限制下使用 ChatGPT,而 Plus 版包括一些更强大的功能和访问最新的 GPT-4 模型。
让我们来看看两个版本之间的差异以及它们在设备上的可用性。
-
免费版 – 基本 ChatGPT 功能:
-
模型: GPT-3.5
-
功能: 不支持插件
-
成本: 免费
-
支持: 无客户支持
-
响应时间: 相比 Plus 版本,响应时间更低
-
-
ChatGPT Plus – 带有 高级访问权限 的扩展功能:
-
模型: GPT-3.5 和 GPT-4
-
功能: 访问包括浏览、插件和高级 数据分析在内的测试版功能
-
成本: 每月 24.00 美元
-
支持: 客户支持
-
响应时间: 相比免费版,响应时间更快,尽管 GPT-4 目前每 3 小时有 50 条消息的上限
-
你应该选择免费版还是 Plus 版?
你是否选择 Plus 版本取决于你的预算以及你是否需要额外的功能。Plus 版本确实提供了更快的响应时间和访问最新 GPT-4 模型的能力,这使得它物有所值。如果你想要完成更复杂的任务,那么 GPT-4 会提供更好的输出,并能处理更复杂的任务。
此外,由于 Plus 版本提供了测试版功能,你可以使用插件,这极大地扩展了 ChatGPT 的功能。
ChatGPT 界面
在本节中,我们将详细说明您在使用主 ChatGPT 界面时将看到的特性,并使用图像作为参考。尽管大部分内容都是自我解释的,但某些区域需要进一步说明。以下截图显示了当前的 ChatGPT 界面:

图 3.1 – ChatGPT 界面
一旦您登录到您的 OpenAI 账户,您就可以开始使用 ChatGPT (chat.openai.com/)界面。让我们熟悉这个 AI 工具的界面。
侧边栏
在屏幕的左侧是侧边栏,其中包含以下功能,用于管理对话和您的账户:
-
新聊天:这允许您开始新的对话。如果您想要在没有先前讨论的上下文中开始新的对话,请使用此按钮。请记住,ChatGPT 模型会保留对过去对话的记忆,以提供上下文相关的回复。因此,如果您想要改变对话的主题,开始一个新的对话是明智的。
-
聊天历史:左侧侧边栏存储了您所有的过去对话,允许您在必要时重新访问它们。您也可以在设置 | 数据控制中关闭此功能。
-
账户选项:点击侧边栏底部的电子邮件地址或姓名,会弹出一个窗口,提供以下选项的访问权限:
-
我的计划
-
自定义指令
-
设置 和测试版
-
如果你没有 ChatGPT Plus,你也可以升级。
聊天视图
聊天屏幕是您与 ChatGPT 互动的地方。它设计成模仿一个消息平台,提供了一个用户友好的环境,您可以在此输入您的查询并从 AI 那里获得响应:
-
从下拉菜单中选择一个模型:对于 Plus 用户,你可以选择你想要与之交互的 GPT 模型:GPT 3.5、GPT 4或插件。
-
提示示例:还有四个按钮可供选择,以及尝试的提示示例
-
文本输入区域:在这里,您可以输入您的问题和回复
-
回复:当 ChatGPT 对您的查询做出回应时,您可以通过选择点赞和踩按钮,并将回复复制到剪贴板来提供反馈。
-
底部栏:这会告诉您您正在使用 ChatGPT 的哪个发布版本,并包括指向发布说明的链接。这对于检查最新功能以及它们是否在您的地区可用非常有用。
自定义指令
直到最近,ChatGPT 的一个问题是需要在每个会话中重复上下文和指令。你不得不将你的提示存储在某个地方,并记住你之前使用过哪些。
自定义指令功能解决了这个问题,因为它允许用户通过提供特定的指令来个性化他们与 AI 的互动,AI 将记住所有未来的对话中。
自定义指令是 ChatGPT 的指南,帮助它理解你的偏好和需求,而无需你在提示中包含所有这些内容。你可以提供指令,涵盖你希望 ChatGPT 了解的有关你的信息,以便它能提供更好的回复。
让我们看看这个主题的一个具体例子:为对话 AI 专业人士的指令。
对话设计师指令示例
我是一名对话设计师,正在为虚拟助手创建引人入胜且自然的对话。我经常需要帮助构思对话流程、生成自然回复以及理解对话设计的最佳实践。
使用此指令,ChatGPT 将以以下几种方式提供协助:
-
设计流程:每当设计师请求帮助创建对话流程时,ChatGPT 可以提供符合行业标准的结构和详细对话序列。
-
自然回复:ChatGPT 可以帮助生成自然且引人入胜的回复,这些回复可以用在虚拟助手的脚本中,节省设计师的时间和精力,并在他们想要提供不同变体时提供多样性。
-
最佳实践:设计师可以询问对话设计的最佳实践,ChatGPT 将基于最新的行业标准和趋势提供见解。
-
反馈和审查:设计师可以要求 ChatGPT 审查他们创建的对话,并获得建设性反馈以提升他们的工作。
-
资源推荐:ChatGPT 可以建议书籍、课程和其他资源,帮助设计师进一步拓展他们在对话设计方面的知识和技能。
通过设置自定义指令,对话设计师可以拥有一个了解他们专业需求的个性化助手,并高效地协助他们工作。它本质上成为一个理解对话设计细微差别并提供定制化协助的工具,无需在后续会话中输入这些信息。
如何设置自定义指令
设置自定义指令是一个简单的过程,并且对免费用户和 ChatGPT Plus 用户都可用,他们可以在网页上或通过 Android 和 iPhone 应用程序使用它。
简单地点击肉丸菜单(…)并选择自定义指令选项。您将看到两个文本框:一个用于添加有关自己的详细信息(例如年龄、位置、爱好、行业和职业类型),另一个用于指定 ChatGPT 应遵循的指令(例如回复的语气和长度)。
提示
需要注意的是,在使用 API 时不支持自定义指令。相反,这可以通过将自定义指令放入系统提示消息中来实现。
GPT
GPT 是为特定任务或目的构建的 ChatGPT 的定制版本。您可以通过给出指令、添加额外知识和创建动作来创建自己的 GPT,而无需编码。动作允许您从 ChatGPT 外部获取信息,使您能够调用外部 API 并将返回的数据用于 GPT 的知识库。创建 GPT 界面将引导您完成此过程,使其易于构建自己的 GPT。
将 GPT 视为 ChatGPT 的专业版本,根据您的需求定制。例如,您可以创建一个 GPT 来帮助您学习棋盘游戏规则,教您的孩子数学,或设计贴纸。您甚至可以将这些 GPT 与 GPT 市场中的其他人分享,如果它们受到欢迎,您可能还能赚钱。
ChatGPT 社区正在积极构建和分享用于各种目的的 GPT。 “GPT 商店”使得查找和使用这些创作变得容易。GPT 代表了一种新的定制 ChatGPT 和解锁其在特定应用中潜力的方式。
到目前为止,您已经很好地理解了如何使用 ChatGPT 界面。在下一节中,我们将探讨我们使用 ChatGPT 和其他 GPT 模型的三种方法中的第二种:OpenAI 游乐场。
探索 OpenAI 游乐场
OpenAI 游乐场提供了一个免费使用的基于网页的沙盒环境,使用户能够轻松测试和实验 ChatGPT 和 GPT 系列语言模型。该平台还提供了使用这些模型可以执行的有用指南和示例任务。用户可以与各种模型进行交互,并保存他们的游乐场会话,以便他们可以返回或与其他用户分享。
入门
在此阶段,我假设您已经创建了一个免费的 OpenAI 账户。一旦登录,您可以通过点击页面顶部的 游乐场 链接来访问 OpenAI 游乐场。
以下截图显示了 OpenAI 游乐场的登录页面:

图 3.2 – OpenAI 游乐场
主要文本区域是您可以与模型交互的地方。尝试使用本书早期部分中的一个提示输入一个问题。您还可以加载预设。OpenAI 内置了数十个预制的提示。点击 您的预设 | 浏览示例 并从列表中选择一个。查看这些示例是值得的,这样您就可以了解您可以执行的任务类型以及实现它们所需的条件。
用户界面功能
OpenAI 游乐场易于理解,但让我们快速看一下核心功能,所有这些功能都提供了几个有用的功能。
保存您的预设
你可以通过点击保存按钮来保存游乐场的状态。此时,你可以切换是否希望预设对任何拥有链接的人开放。这些预设也将显示在预设下拉菜单中,以便以后使用。
模式
模式设置允许你决定系统如何响应你的提示。最好将其设置为聊天,因为其他两个选项现在已弃用。
AI 模型
你可以通过使用模型下拉菜单来选择你希望与之交互的模型。列表包含所有最新的 GPT-3 和 GPT-4 模型,以及一些旧版本。
参数
在这里,你可以配置以下新参数,以获得不同结果的提示。当我们在提示工程部分进行详细说明时,我会详细介绍这些内容。
-
温度:这可以在 0 到 1 之间设置,决定了 AI 的创造力水平。默认设置为0.7,这通常对我的创意任务提供了更好的性能。
-
最大长度:这决定了输入提示和结果输出的范围,以“标记”而不是单词或字符来衡量。一个标记大约相当于四个英语字符。
-
停止序列:这指示 AI 在指定点停止生成。通常,在对话式 AI 用例设置中,模型在生成一行回复后停止是有用的。
-
Top P:此参数通过根据标记与现有提示的相关性进行排名,为生成内容的随机性和创造力提供另一种引导输出的方式。
内容过滤器偏好
点击菜单上的三个点可以显示选择游乐场会话内容过滤器偏好的选项。开启此功能,如果发现涉及性主题、仇恨言论、暴力或自残的内容,将会显示警告。
历史
点击历史按钮可以加载你过去 30 天的使用记录。选择你的任何一次会话,你可以查看会话,并选择恢复此版本,这将覆盖你当前会话。
查看代码
对于我来说,游乐场的一个关键特性是能够看到驱动操作和生成输出的底层代码。点击菜单顶部的查看代码选项,可以检查你在与所选模型交互时执行的代码。
在顶部选择库下拉菜单时,你可以从以下选项中选择,以查看如何与 OpenAI 模型交互的示例:
-
API使用 curl 和 JSON 有效载荷
-
SDKs使用 Python 和 Node.js
在下一节中,我们将更详细地介绍这些使用 ChatGPT 技术的方案。
API 和游乐场的定价
OpenAI 的定价基于按需付费模式。在初始注册时,用户将获得一个包含有效期为前 3 个月的增值试用积分;在此期间之后,积分将过期。
信用消费因每个模型而异,这些成本已在 OpenAI 网站上记录。计费指标基于使用的令牌数量,每 1K 个令牌相当于大约 750 个单词,产生费用。
小贴士
当您使用沙盒环境时,您仍然调用的是与直接调用 OpenAI 端点时相同的 API 端点。因此,沙盒环境和 API 调用成本相同。
如何跟踪和控制令牌使用
您可以通过以下仪表板查看您的 LLM 使用跟踪:

图 3.3 – OpenAI 使用仪表板
点击页面右上角的用户名以显示主菜单,然后转到管理账户 | 使用情况。
您可以查看在当前和过去的计费周期中使用了多少令牌,以及每个请求的令牌细分。您还可以查看其他统计数据,例如您还剩下多少信用可以消费。
为了让您放心,设置使用限制也是一个好主意,这样您可以管理您的支出。您可以通过访问组织计费 | 使用限制来实现这一点。在这里,您可以设置硬限制和软限制。
如果您有多个团队成员使用该 API,这一点尤为重要。建议您定期检查使用跟踪仪表板。
学习使用 ChatGPT API
对于我们在第二章中讨论的许多用途,使用 ChatGPT 网页界面或交互式沙盒环境是有意义的。
然而,OpenAI 提供了一个广泛的 API,允许您使用他们的模型执行多个任务,包括使用代码与 ChatGPT 及其其他模型进行交互。所以,如果您想创建复杂的 ChatGPT 应用程序,并且我希望您是这样的,那么使用 API 是您的最佳选择。
在本节中,我们将更深入地探讨您可以使用来与 ChatGPT API 交互的不同技术。这些技术将在剩余的章节中得到应用。
开始使用
您可以通过任何语言的常规 HTTP 请求轻松与 API 交互,通过官方的 Python 或 Node.js 库,或社区维护的库。查看 Playground 并点击代码选项以查看每个库或curl请求的示例代码是有用的。或者,您可以查看 API 文档,其中包含各种示例。认证、模型名称、消息和超参数是在与 API 和库进行交互时必须理解的因素。
认证
在使用任何可用方式与 OpenAI API 交互之前,你需要使用 API 密钥进行身份验证,该密钥可以在控制台中创建。登录到 OpenAI 仪表板后,点击右上角的用户名。从下拉菜单中选择查看 API 密钥。然后,点击创建新的秘密密钥并为其命名。确保你记下你的 API 密钥,因为你将无法再次看到它。
可用模型
在可用模型下,你可以指定要使用哪个模型。在这种情况下,是 GPT-3.5 Turbo,这是 ChatGPT 界面的动力模型,除非你选择了 GPT4。在撰写本文时,以下模型可用于聊天完成:
-
gpt-4 -
gpt-4-0613 -
gpt-4-32k -
gpt-4-32k-0613 -
gpt-3.5-turbo -
gpt-3.5-turbo-0613 -
gpt-3.5-turbo-16k -
gpt-3.5-turbo-16k-0613
游戏场提供了你可以使用的其他 GPT 模型的名称,尽管你可以参考模型页面以获取更多详细信息:platform.openai.com/docs/models。
消息
消息数组是由角色和内容形成的一系列消息对象。角色可以是以下类型之一:
-
系统消息: 系统消息描述了在整个对话期间 AI 助手的行为了例,“*你是一位像电影《好家伙》中的角色一样的 Python 专家程序员。”
-
用户消息: 用户消息本质上是你将发送给 API 的提示。在本教程中,我们将涵盖用户消息的示例。
-
助手消息: 助手消息是会话中的先前响应。
发送的第一条消息应该是系统消息。随后的消息应在用户和助手之间交替,并包含内容。
小贴士
消息数组是你在 API 集成中持久化对话中过去消息的地方。API 不会神奇地记住对话的上下文。这个机制是 ChatGPT 在底层使用的。
超参数
通过微调这些值,你可以显著影响模型输出:
-
temperature: 这是模型输出的随机程度 -
max_tokens: 生成标记的最大数量 -
top_p: 这控制着生成文本的多样性 -
frequency_penalty: 这影响基于训练数据中它们的频率出现的标记的可能性 -
presence_penalty: 这影响表示“存在”的某些实体或概念在生成文本中的可能性
通过微调这些参数,你可以影响模型输出,使其更加确定、有创意或具有上下文意识。
直接调用 API
API 端点提供其他功能,例如嵌入和微调模型,以及生成任务。然而,对于本书,我们只关注与与我们的模型聊天相关的功能,即聊天/完成端点。
要直接与 ChatGPT API 交互,您可以发出一个 POST 请求到 api.openai.com/v1/completions。
包含一个带有 API 密钥和其他您想要发送到 API 的参数的认证头:
curl --location 'https://api.openai.com/v1/chat/completions' \--header 'Content-Type: application/json' \--header 'Accept: application/json' \--header 'Authorization: Bearer OPEN_AI_KEY' \
--data '{
"model": "gpt-3.5-turbo",
"messages": [{
"role": "user",
"content": "Provide 3 names for dog training chatbot"}],
"temperature": 1,
"top_p": 1,
"n": 1,
"stream": false,
"max_tokens": 250,
"presence_penalty": 0,
"frequency_penalty": 0
}'
API 的响应包括生成的文本以及其他元数据,如下所示:
{
"id": "chatcmpl-84DaAYWLg69y4XUD86YbXgD4iuI5j",
"object": "chat.completion",
"created": 1696016214,
"model": "gpt-3.5-turbo-0613",
"choices": [{
"index": 0,
"message": {
"role": "assistant",
"content": "1\. \"Pawsitive PupBot\"\n2\. \"Canine Companion Coach\"\n3\. \"Smart Bark Assistant\""},
"finish_reason": "stop"}],
"usage": {
"prompt_tokens": 17,
"completion_tokens": 25,
"total_tokens": 42
}
}
返回的有效负载包括聊天的完成细节,包括响应本身和使用数据。
这种直接的方法提供了对与 OpenAI 模型交互的细粒度控制,这对于理解 API 端点的请求和响应是理想的。
直接使用类似 curl 的工具调用 OpenAI API 是直接的,但可能会有些烦人。使用 Postman 这样的 API 工作流程工具来简化调用端点是个好主意。有一个非官方的 Postman 收藏夹,您可以将其分支并使用它来简化流程。
现在我们已经介绍了直接调用 API,在下一节中,我们将探讨如何开始使用 Python 和 Node.js 库。
使用 OpenAI Python 库进行设置
设置环境以使用 OpenAI Python 库是一个简单的过程。以下是开始步骤:
-
首先,使用以下命令安装库:
$ pip install openai -
创建一个 Python 文件,并向其中添加以下代码。导入 OS 和 OpenAI Python 包。然后,从环境变量中加载您的密钥,以便您可以使用它与包一起使用:
import os import openai openai.api_key = os.getenv("OPENAI_API_KEY") -
要调用 ChatGPT API,您需要调用
openai.ChatCompletion.create()。这是您必须调用来与聊天完成端点交互的方法。以下是如何调用此方法的示例。为了使您的代码更具可重用性,将其包装在辅助函数中。它将接受您想要发送的消息和其他传递给create()函数的参数,并返回 API 的响应:import os import openai openai.api_key = os.getenv("OPENAI_API_KEY") print(openai.api_key) def chat_with_gpt( model, user_message, top_p=1,frequency_penalty=0,presence_penalty=0, temperature=0 ): try: response = openai.ChatCompletion.create( model=model, messages=[ { "role": "system", "content": "You are a helpful conversational AI expert." }, {"role": "user", "content": user_message}, ], top_p=top_p, frequency_penalty=frequency_penalty, presence_penalty=presence_penalty, temperature=temperature) return response except Exception as e: return str(e)
以下辅助函数允许您轻松自定义与 ChatGPT API 的交互。您可以按如下方式调用该函数并打印响应:
response = chat_with_gpt(
"gpt-3.5-turbo",
"Suggest a good name for a customer support chatbot working for a holiday company",
top_p=0.9,
frequency_penalty=-0.5,
presence_penalty=0.6,
temperature=0.5)
print(response)
这使我们能够发送我们想要的任何超参数并更改模型。
运行程序
让我们看看如何运行程序:
-
YOUR_API_KEY使用您的实际 API 密钥):export OPENAI_API_KEY='YOUR_API_KEY' -
执行 Python 脚本:将代码保存到文件中,例如 chatgpt_interaction.py,然后从您的终端运行脚本:
python chatgpt_interaction.py
这种设置允许您发送任何消息并调整参数以微调 GPT 模型的行为,并比较不同模型之间的响应。
使用 OpenAI Node.js 库进行设置
OpenAI 提供了一个 TypeScript 编写的 Node.js 库,这使得它成为 TypeScript 项目的绝佳选择,因为库包括 TypeScript 定义。让我们开始使用这个库:
-
首先,使用以下命令安装库:
.env file to store your environment variables (make sure you add this file to .gitignore to avoid committing it to your version control). You can use a package such as dotenv to load these environment variables in your application:import * as dotenv from 'dotenv';
dotenv.config();
const mySecret = process.env['OPENAI_API_KEY']
Reference your OpenAI API key stored in an environment variable. -
创建一个辅助函数以获得更大的灵活性也是合理的:
import OpenAI from 'openai'; const openai = new OpenAI({ apiKey: mySecret, // defaults to process.env[" OPENAI_API_KEY"] }); async function chatWithGPT( model, userMessage, topP = 1, frequencyPenalty = 0, presencePenalty = 0, temperature = 0 ) { try { const prompt = userMessage; const maxTokens = 100; const chatResponse = \ await openai.chat.completions.create({ model: model, messages: [{ role: "user", content: prompt }], temperature: temperature, top_p: topP, frequency_penalty: frequencyPenalty, presence_penalty: presencePenalty, max_tokens: maxTokens }); return chatResponse; } catch (error) { return error.toString(); } } -
辅助函数允许你轻松自定义与 ChatGPT API 的交互。你可以这样调用它:
async function main() { try { const response = await chatWithGPT("gpt-3.5-turbo", "Hello world", 0.9, -0.5, 0.6); console.log("ChatGPT Response:", response.data); } catch (error) { console.error("Error:", error); } }
模型、消息和超参数与 Python 库中使用的相同。
处理错误
如果库无法与 API 建立连接或收到非成功状态码,例如 4xx 或 5xx 响应,它将抛出一个从APIError类派生的异常。
在这种情况下,处理从服务返回的错误很容易,你可以根据需要选择处理这些错误。在我们的辅助函数中,我们正在寻找APIError:
if (error instanceof OpenAI.APIError) {
// Do something with the APIError
console.log(error.status); // 400
console.log(error.name); // BadRequestError
throw error;
} else {
throw error;
}
返回的错误代码如下:
-
400:BadRequestError -
401:AuthenticationError -
403:PermissionDeniedError -
404:NotFoundError -
422:UnprocessableEntityError -
429:RateLimitError -
>=500:InternalServerError -
N/A:APIConnectionError
通过理解这些错误代码及其处理方法,你可以使用 OpenAI Python 库创建更健壮且具有错误恢复能力的应用程序。
请求和响应结构
该库包含所有请求参数和响应字段的 TypeScript 定义。它们可以按如下方式导入和使用:
const parameters: OpenAI.Chat.ChatCompletionCreateParams = {
model: model,
messages: [{
role: "user",
content: prompt
}],
temperature: temperature,
top_p: topP,
frequency_penalty: frequencyPenalty,
presence_penalty: presencePenalty,
max_tokens: maxTokens
};
const chatResponse: OpenAI.Chat.ChatCompletion = \
await openai.chat.completions.create(parameters);
通过在OpenAI库中使用请求参数和响应字段的 TypeScript 定义,你可以确保你的代码是类型安全的,并与 API 预期的结构保持一致。这种方法简化了请求构建和响应解释的过程,并在与 OpenAI API 交互时确保更高效和更健壮的开发体验。
重试和超时
API 抛出的以下错误会自动重试两次,默认情况下带有短指数退避:
-
408、409和429 -
>=500
你可以使用maxRetries选项配置或禁用所有 API 调用,如下所示:
const openai = new OpenAI({
maxRetries: 0, // default is 2
});
或者,你可以为每个调用设置以下参数:
await openai.chat.completions.create({
messages: [{
role: 'user',
content: 'How can I...?'
}], model: 'gpt-3.5-turbo' }, {
maxRetries: 5
});
类似地,API 超时可以通过timeout选项进行配置。默认超时时间为 10 分钟。你可以为所有请求设置默认值:
const openai = new OpenAI({
timeout: 20 * 1000, // 20 seconds (default is 10 minutes)
});
你也可以为每个请求设置超时:
await openai.chat.completions.create({
messages: [{
role: 'user',
content: 'How can I......?' }],
model: 'gpt-3.5-turbo' },
{timeout: 5 * 1000,}
);
使用哪种语言是个人喜好。也有几个开源库可用。
其他 ChatGPT 库
如果你想要使用其他语言与 OpenAI API 交互,有很多选择。开源社区已经为各种编程语言开发了与 OpenAI 服务交互的库。这些库涵盖了多种编程语言,并为使用 OpenAI API 提供了绑定和便捷的方法。
如果你正在使用微软的 Azure,提供了特定的库来与 Azure 上的 OpenAI 服务交互,例如 Java 和.NET 的 Azure OpenAI 客户端库,这些库是 OpenAI REST API 的适配版本。
这些库共同形成了一个丰富的生态系统,开发者可以利用它直接或通过云平台(如 Azure)与 OpenAI 服务和模型交互。
摘要
在本章中,我们重点关注了与 ChatGPT 交互的各种方法,每种方法都有其独特的优势,满足不同用户的需求和技术水平。最初,我们探讨了 ChatGPT 界面,区分了免费版和 Plus 版,并突出了后者增强的功能,包括更快的响应时间和访问 GPT-4 模型,这对于更复杂的任务至关重要。我们还介绍了自定义指令这一新颖功能,它通过在会话间保留指定指令,显著优化了用户交互。
接下来,我们转向 OpenAI Playground,探讨了这个沙盒如何成为实验 OpenAI 模型的绝佳平台。它拥有用户友好的界面,允许用户亲手探索模型,保存和分享会话,并查看底层代码,充当点对点操作和更代码驱动方法之间的桥梁。
在最后一节中,我们介绍了您与 OpenAI API 交互的不同方式。
API 是开发者使用 ChatGPT 的主要手段。您通过直接通过 HTTP 使用 API 或使用 OpenAI 的 Python 和 Node.js 库来了解如何这样做。我们解释了进行 API 调用、处理错误以及配置重试和超时的过程,为开发者提供了一本全面的指南。
到目前为止,您可能想知道何时应该使用 API 而不是网页界面或 Playground。对于日常交互以及我们迄今为止查看的许多对话设计任务,使用广受欢迎的聊天界面是有意义的,它能很好地处理您的对话上下文、自定义指令和插件交互。
如果您想开始查看其他模型并了解与 API 交互背后的代码,那么 OpenAI Playground 是一个不错的选择。
然而,如果您想在您的对话式 AI 应用程序、内部服务或数据管道中包含 ChatGPT,或者您只是想对您与模型交互有更多的控制,那么 API 是更合适的选择。通过 OpenAI 的库或您团队选择的语言的社区驱动库利用 API 是一条可行的道路。无论您的选择如何,在这个阶段,您应该对所有这些方法都感到舒适。
到目前为止,您在第二章中广泛使用了提示词,学习如何使用 ChatGPT 进行对话设计任务。在下一章中,我们将更深入地探讨提示工程这一新兴领域。
进一步阅读
以下链接是一份精选资源列表,可以帮助您使用 ChatGPT:
第四章:使用 ChatGPT 进行提示工程
在本章中,我们将把重点转向 ChatGPT 的提示工程艺术和科学,这是任何希望充分发挥对话式 AI 潜力的人的关键技能集。我们将剖析提示的结构、语气和复杂性,探讨它们如何影响模型的响应。
你将学习如何制作出适合专业对话的提示,我们还将分享一些技巧,以在不使模型感到不知所措的情况下引入复杂性。我们还将深入研究段落和项目符号的战略使用,以增强可读性和理解力。
此外,我们还将讨论如何在提供充分上下文的同时,保持提示的简洁性。对于那些想要扮演特定角色的人来说,我们将提供通过提示模仿对话式 AI 工程师专业知识的见解。
到本章结束时,你将准备好制作出能够引发准确和上下文相关的响应,同时提升 ChatGPT 能力到新高度的提示。
在本章中,我们将涵盖以下关键领域:
-
通过提示工程的概念
-
理解成功提示的核心组件
-
使用提示工程策略
-
了解提示工程技巧
本章旨在成为你掌握提示工程的终极指南,使你能够更有效、更细致地与 ChatGPT 互动。
技术要求
在本章中,我们将广泛使用 ChatGPT,因此你需要注册一个免费账户。如果你还没有创建账户,请访问openai.com/,然后在页面右上角点击开始使用,或者访问chat.openai.com。
为了执行本章中演示的示例,我建议除非另有说明,否则请通过网页或移动应用使用 ChatGPT。
最后一个示例技术需要安装 Python 3.9 和 Jupyter Notebook,请使用以下链接:jupyter.org/try-jupyter/notebooks/?path=notebooks/Intro.ipynb。
通过提示工程的概念
随着大型语言模型(LLMs)及其能力的兴起,提示工程已成为一门新学科,似乎每个人都正在谈论它。我们可以利用提示工程来帮助我们使用 LLMs 处理各种任务,从常见的问答到与其他系统的更复杂集成。对于任何使用 LLMs 的人来说,掌握这项技能是非常重要的。
那么,提示工程到底是什么呢?简单来说,提示工程是创建最优化输入以从与 LLMs 的交互中获得最大收益。因此,你的提示结构越好,输出的结果就会越好。
如果你发送模糊的提示,那么现实是你会得到模糊或不正确的结果。确实,提供一个简单的在线提示通常会得到一些有趣的结果。然而,它们不太可能是你希望得到的结果,尤其是如果你在寻找完成更复杂任务的话。
这里是一个简单提示语的例子。尝试用 ChatGPT 来试试:
Tips on conversation design
好的,这确实返回了一些有用的信息。然而,如果我们想要返回更精确的结果,我们可以做得更好:
"Suggest methods to enhance a conversation design to better capture and retain user engagement, with a particular focus on utilizing empathetic language and providing meaningful responses."
在这个改进的提示语中,我们提供了更多的清晰度和具体性,以确保 AI 的帮助能够指向我们感兴趣的对话设计领域。
构建一个成功的提示语不仅仅是提出正确的问题,还涉及到向 LLM 提供足够的信息以创建正确的答案,并确保一切都在 LLM 理解的理想格式中。提示工程完全在于根据你试图完成的任务了解使用哪些技术。
在下一节中,让我们首先看看提示语的不同组成部分,并考虑其他具体细节,例如最佳格式。
理解成功提示语的核心组件
没有一种万能的提示语可以保证成功。每个你想要执行的任务都是不同的,因此所需的提示语也是不同的。然而,由于模型训练的方式和用于训练它们的数据,有一些规则需要遵循以获得最佳结果。在第二章中,我们探讨了 ChatGPT 在对话设计任务中的应用。这包括提供详细的提示,包括成功提示的一些关键组成部分。是的,你已经进行了一些广泛的提示工程,并使用了以下列表中概述的一些核心提示组件:
-
指令:指定要采取的行动,通常通过输入动词(如设计或编写)来启动
-
上下文:提供额外的信息以指导模型,例如环境或目的
-
范围:缩小任务的重点,指定要涵盖的查询或主题类型
-
角色:定义 AI 应操作的能力,例如专家或客户服务代表
-
受众:表明预期输出接收者的知识水平和兴趣
-
输入数据:指定任务中要使用的数据,通常由分隔符分隔
-
输出数据:详细说明预期输出格式和结构,指导 AI 的响应
下一个图示说明了有助于构建成功提示语的核心组件:

图 4.1 – 成功提示语的核心组件
让我们更详细地看看成功提示语的关键组成部分。
指令
为你的提示给出明确的指令。一个好的做法是以动词开始提示,例如设计、草拟、创建、生成、撰写或制作。这样,ChatGPT 应该能确切地知道你希望它如何回应,并且没有误解的空间。同时,告诉 ChatGPT 你期望在回复中看到什么,例如对话流程、网站文案、博客文章、聊天记录或描述。
让我们看看一个例子提示,要求 ChatGPT 给我们一个聊天机器人对话示例:
"Design a conversation flow for a customer service chatbot that handles product returns and exchanges, focusing on a friendly and efficient user experience"
在这个提示中,我们给出了一个精确的指令:设计一个对话流程。因此,指令越清晰、越精确,留给 ChatGPT 猜测你试图完成的事情就越少。
上下文
为了改进提示,我们可以在第一条指令之外提供更多信息。让我们通过提供一些上下文来继续这个例子,以指导模型理解我们对话设计请求的需求和目的:
"Design a conversation flow for a customer service chatbot"
我们在我们的提示中添加了for a customer service chatbot。这应该有助于 ChatGPT 定制聊天机器人的对话和动作。因此,通过额外的上下文,我们可以引导模型理解对话流程将使用的环境。
范围
就像任何项目概要或工作说明书一样,向 ChatGPT 提供更多关于任务范围的信息是有意义的。在我们的案例中,我们的对话设计是为客户服务聊天机器人,这可能涉及任何类型的请求,从常见问题解答到投诉或退货。因此,让我们提供一个范围,以便我们可以专注于我们正在为哪些类型的查询进行设计:
"Design a conversation flow for a customer service chatbot that handles product returns and exchanges"
希望通过向 ChatGPT 提供处理产品退货和换货,我们可以确保模型专注于生成与产品退货和换货相关的对话流程,避免离题的偏离。
角色
成功提示最重要的组成部分之一是角色组件。为 ChatGPT 提供一个角色,以指定 AI 在生成响应时应采取的能力。例如,你可以要求它扮演专家或具有特定的观点或能力:
Act as a first line customer service representative and provide assistance on how to troubleshoot technical problems with the SAAS. Please ensure a professional tone and intermediate level of complexity in your response.
将此角色作为你提示的一部分将引导 ChatGPT 驱动的客户支持聊天机器人的语言和行为。在提供角色时,重要的是要具体、清晰且相关。记住,我们在第二章的创建我们的用户和聊天机器人角色部分探讨了提供更复杂的角色细节。
根据你的任务,提示中未定义的角色可能导致响应泛化或模糊,缺乏所需的关注或专业性。
受众
在你的提示中指定受众细节可以显著定制输出。例如,考虑以下提示:
"Explain the principles of machine learning to a technical audience."
这可能结果是一个深入的解释,使用技术术语并讨论算法、数据训练、验证和背后的数学原理。
如果你想为更广泛的受众创建内容,你可以尝试以下类似的方法:
Explain the principles of machine learning to a general audience.
预期的输出将是一个使用通俗易懂的语言进行简化的解释,避免使用技术术语。
通过在提示中包含受众的具体信息,你可以使 ChatGPT 的响应与目标接收者的知识水平和兴趣相匹配。
输入数据
输入数据通常是你的提示的重点。这可以是文本或其他格式的数据。
在提示的开头放置指令。如果你在提示中包含了 ChatGPT 用作提示部分的具体数据,使用某种分隔符是一种好的做法。我发现使用###或"""来分隔指令和输入数据效果很好:
Summarize the conversation delimited with triple hashes
Conversation: ###{conversation}###
这里是一个示例,这个提示提供了我们的输入对话数据作为纯文本:
Summarize the conversation below as a bullet point list of the most important points. The conversation is delimited with triple hashes
Conversation: ###
User: Hi, I'd like to return a product I purchased last week.
Chatbot: Of course, I can aid with that. May I have your order number, please?
User: Sure, it's 12345.
Chatbot: Thank you. I found your order. May I ask the reason for the return?
User: The product has a defect and doesn't work properly.
Chatbot: I apologize for the inconvenience. I can process the return for you. Would you like a refund or an exchange?
User: I'd prefer an exchange.
Chatbot: Great! I've started the exchange process. You'll receive an email with further instructions shortly.
User: Thank you!
###
ChatGPT 擅长分析各种输入类型,如JavaScript 对象表示法(JSON)、超文本标记语言(HTML)、可扩展标记语言(XML)、图像、标记和纯文本等。例如,如果你的对话数据存储为 JSON,你可以简单地将其传递到你的提示中:
Summarize the conversation below as a bullet point list of the most important points. The conversation is delimited with triple hashes
Conversation: ###
{
"conversation": [
{
"speaker": "User",
"message": "Hi, I'd like to return a product I purchased last week."
},{
"speaker": "Chatbot",
"message": "Of course, I can assist with that. May I have your order number, please?"
},{
"speaker": "User",
"message": "Sure, it's 12345."
}]
}
###
确保输入数据的格式和结构的一致性对于获得可靠的响应至关重要。
一旦你提供了正确的输入,告诉 ChatGPT 它应该提供什么作为输出是很重要的。让我们看看下一个例子。
输出数据
指定预期的输出数据和详细程度,可以引导 AI 生成符合你要求的结果。我们可以提供详细的说明,说明我们想要的输出是文本、格式化数据还是代码。
为了获得最佳结果,明确定义所需输出的结构和格式是明智的。这可能包括指定使用数组、对象或其他数据结构来组织信息。也可能涉及定义属性或键的命名约定,确保输出标准化和可预测,从而简化数据提取和进一步处理,如果你计划在软件或管道中使用你的响应。你已经在许多例子中广泛应用了这种做法,当我们要求 ChatGPT 返回 JSON 数据时,在第二章。
简单文本
让我们看看更多的例子。在这个简单的例子中,我们要求以项目符号列表的形式输出文本:
Summarize the conversation delimited with ### as a bullet point list of the most important points which should be no more than 150 characters each.
Conversation: ###{conversation}###
输出特定格式或代码
另一个技巧是指定编号的表格,例如,使用以下方式:
Please can you create a numbered table of the components of a successful chatbot for a technical audience.
你可以用后续问题来引用编号的项目:
can you provide more detail on number 3
我们也可以要求 ChatGPT 返回更复杂的特定格式,例如 HTML 中的表格数据:
Create a table summarizing the chatbot's performance across four metrics (User Engagement, Response Accuracy, Processing Time, and User Satisfaction) over a span of three months. Output the table as HTML. The metrics are as follows:
- User Engagement: Jan: 1200 interactions, Feb: 1300 interactions, Mar: 1400 interactions
- Response Accuracy: Jan: 85%, Feb: 87%, Mar: 90%
- Processing Time: Jan: 1.2 seconds, Feb: 1.1 seconds, Mar: 1.0 second
- User Satisfaction: Jan: 80%, Feb: 82%, Mar: 85%
Include a column for the average across the three months for each metric.
你还可以更进一步,要求特定的格式以及基于我们选择的格式,最佳输出是什么。在下一个例子中,我们将要求 ChatGPT 提供 Vega-Lite(视觉分析的高级语法):
The following is data delimited in ### summarizing a chatbot's performance across four metrics (User Engagement, Response Accuracy, Processing Time, and User Satisfaction) over a span of three months.
Please can you create this for vega lite representation for this data?
Include a column for the average across the three months for each metric.
###
- User Engagement: Jan: 1200 interactions, Feb: 1300 interactions, Mar: 1400 interactions
- Response Accuracy: Jan: 85%, Feb: 87%, Mar: 90%
- Processing Time: Jan: 1.2 seconds, Feb: 1.1 seconds, Mar: 1.0 second
- User Satisfaction: Jan: 80%, Feb: 82%, Mar: 85%
###
另一个指定输出的好例子是指导 ChatGPT 查看非结构化数据并将其转换为我们可以用于进一步管道或软件应用的输出。在以下示例中,我们将请求 JSON 并指定我们想要创建的属性,以及添加一个用于填充情感的属性:
Please look at these live chat transcripts and create JSON for this conversation as a list of message objects, add one extra property which will include sentiment for each message:
[2023-10-09 08:00:00] User: What's the weather like today?
[2023-10-09 08:00:05] Virtual Assistant: Today's forecast is cloudy with a high of 68°F and a low of 52°F. There's a 60% chance of rain in the afternoon.
[2023-10-09 08:01:00] User: Do you have any suggestions for indoor activities?
[2023-10-09 08:01:05] Virtual Assistant: Certainly! You might consider reading a good book or visiting a local museum. Both activities are excellent ways to spend a rainy day indoors.
LLM 的输出可能不一致,列表等结果可能脆弱,因此如果你想在软件或管道中使用输出,通常建议返回 JSON。
正如你所看到的,输出可以是几乎任何东西,因此仔细指定我们希望 ChatGPT 提供的确切内容是有意义的。
结论
一个提示并不需要所有这些元素,其格式根据你想要完成的特定任务而变化。还值得注意的是,相同的提示组件可以与任何大型语言模型(LLM)一起使用。
尽管这些组件并不全面,但它们应该能够帮助你持续获得更好的结果。
因此,现在你已经知道了提示的关键部分,让我们通过考虑你的提示策略来更详细地探讨提示工程。
与提示工程策略一起工作
提示工程是一个迭代的过程。你很可能不会在第一次、第二次或第三次尝试中就成功完成你的任务。这就是为什么我倾向于避免互联网上提供的 100 个最佳提示指南。在提示工程中没有一成不变的规则,但有一些策略可以遵循,同时使用一些或所有我们有效的提示组件。让我们更详细地探讨一些这些策略。
定义明确的目标
在你开始使用提示之前,最好考虑你试图完成的任务。明确的设计和目标将意味着整体迭代次数更少。因此,考虑你的任务,看看你是否能清楚地对自己解释它,或者用几句话描述它,包括一些适当的关键词,以确保你已经深思熟虑,并且有足够的细节提供给 ChatGPT。如果没有提供足够的细节,LLM 往往会偏离主题,因为它们有太多的可能性走向错误的方向。
采用迭代提示开发
提示开发是一个迭代的过程。你最初用来向 LLM 解释任务的提示可能不会是你在生产中使用的提示。关键是你要从简单开始,然后,根据每次输出的结果,在需要改进或缺乏的地方对提示进行迭代。在下一个示例中,我们将展示对特定任务的提示进行迭代。
迭代开发示例
在这个例子中,你被要求为即将部署在大学网站上的新聊天机器人设计一个对话流程,以回答有关招生、项目和校园设施的问题。对话流程应该是直观的、信息丰富的,并且能够吸引潜在学生找到他们所需的信息。
你有一些关于大学录取的数据,这些数据可以作为你的提示的一部分提供:
Data:
Admissions:
Application Period: 6 September to 15 January
Requirements:
A-Level qualifications or equivalent (specific grade requirements may vary by program)
Personal Statement (4000 characters max)
Academic References (1 required, 2 recommended)
Transcripts from previous institutions
我们的第一尝试相当简单:
Create a chatbot conversation flow for university inquiries
Data: {data}
这相当模糊,缺乏上下文和指导,让 ChatGPT 没有生成有意义对话流程所必需的信息。ChatGPT 的输出相当令人印象深刻,包括一个示例对话,但它相当基础。
让我们尝试通过更多细节来改进我们的提示:
You are tasked with designing a conversational flow for a chatbot deployed on a university's website. The chatbot should be able to answer queries regarding admissions, programs, and campus facilities based on the provided data. Draft a conversational script for the following user inquiry: "Tell me about the admission process and deadlines."
Data: {data}
这是一个更好的提示;我们提供了更广泛的范围和更清晰的指示,以及一个场景,并要求为特定的用户查询编写脚本。然而,它并没有提供关于聊天机器人角色的任何指导或对聊天机器人语气的强调。
Envision yourself as a chatbot developer crafting a conversational flow for a university chatbot called Unipal. Utilizing the given data, ensure the chatbot provides informative, clear, and engaging responses regarding admissions. Here's a scenario: A prospective student inquires, "I am interested in the Engineering program. Can you guide me through the admission requirements and process?" Create a conversational script that demonstrates how the chatbot would guide the user through this inquiry, providing all necessary details in a friendly and supportive manner.
Data: {data}
这个提示为 ChatGPT 创建了一个角色,将其置于一个现实场景中,并提供了一个特定的用户查询来响应。它强调了友好、支持和吸引人的语气的重要性,并为 ChatGPT 提供了构建有意义、信息丰富的响应所需的环境和数据,以满足我们的对话流程任务。
如你所见,提示工程是一个迭代的过程。我们开始得很简单,通过一系列提示改进,根据每个提示的结果逐步构建了我们的提示细节。
从简单开始
还要注意的是,根据你想要完成的任务,使用几个简单的提示可能比一个长而复杂的提示效果更好。如果你使用的是 ChatGPT 的网页或移动聊天界面,你可以从一个简单的明确提示开始,并通过后续的跟进提示来构建。记住,ChatGPT 应用在幕后管理上下文和对话历史,如果你使用的是 API,你必须自己实现这一点。
小贴士
如果你试图在一个提示中完成太多事情,LLMs 可能会变得困惑,可能不会提供最佳结果。如果你试图一次做四到五件事情以上,可能该将这些任务分解成一系列后续提示了。
如果你试图完成一个非常复杂的任务,可能更容易不是试图创建一个完美的提示,而是将任务分解成多个提示。从一个清晰简洁的提示开始,然后通过进一步的问题或澄清来跟进。
让我们考虑一个更复杂的任务:为医疗提供者设计一个多功能对话式 AI 系统,该系统能够处理预约安排、开具续方,并提供关于医疗状况的一般信息。与其让 ChatGPT 一次性提供所有信息,你不妨从一个清晰简洁的提示开始,为系统的构建奠定基础:
Design a conversational interface for a healthcare provider that can greet users and ask for their primary concern.
一旦你有了基本结构,你可以通过后续问题深入了解每个功能,例如询问预约安排的更多细节:
Elaborate on how the conversational AI should handle appointment scheduling including checking doctor availability and confirming appointment details with the user.
你在这里所做的是从简单开始,这样 ChatGPT 就能理解整体任务,然后将复杂任务分解成更小、更易于管理的子任务。这种方法对于更大、更复杂的任务,如编码和文本用例,效果很好。
使用后续提示测试多个示例
有时候你会有多个数据示例来评估你的提示。测试提示在一系列输入上是有意义的,这样你可以看到你的提示是否在多个示例中正确执行。如果你使用 ChatGPT 处理大量数据,这一点尤为重要。你可以使用 ChatGPT 来帮助完成这项工作。以下是一个例子。假设你有一个基于一组酒店数据的 LLM 自动化系统,用于创建酒店描述。这个提示可能看起来像这样:
Act as a travel agent and provide a comprehensive hotel description of 200 words maximum for the following hotel data: {
"hotel_name": "Mountain Lodge",
"location": "Swiss Alps",
"rating": 4.5,
"no_of_rooms": 80,
"facilities": [
"Ski-in/Ski-out",
"Fireplace",
"Restaurant"
],
"price_range": "£200-600",
"description": "A lodge nestled among the snow-capped Swiss Alps."
}
Output the description as a description property on the same JSON
可能是你并不完全确定设施数据将适用于每家酒店,你不想有任何虚构的设施细节或提及没有设施的情况,因此你可以检查描述中是否提到了设施,在另一个提示中进行检查:
Look at the following hotel_description and return are_facilities_mentioned = true if facilities are mentioned or are_facilities_mentioned = false if not.
You don't need to explain your reasoning
hotel description: "situated in the..."
你可以在这里看到测试你的提示在一系列输入上的价值,并使用后续提示对 ChatGPT 的输出进行清理。
当你需要时使用温度
我们在第三章中介绍了如何更改温度。温度允许你改变模型响应的随机性。温度越高,响应就越多样化、越随机。通常,当你构建希望得到可预测响应的应用程序时,使用零温度是一个好习惯。因此,如果你试图构建一个可靠且可预测的系统,我建议使用零。对于你希望有更多创造性的应用,提高温度是个好主意。
处理 ChatGPT 中的内存限制
在尝试维持长时间或复杂对话或理解更广泛背景时,ChatGPT(或任何 LLM)的内存限制可能成为瓶颈。所有 GPT 模型都有一个令牌限制,包括输入和输出令牌。一旦达到令牌限制,你就必须截断、省略或以其他方式管理对话历史,为新输入和输出腾出空间。
管理内存问题的策略
在解决对话式 AI 的内存限制时,可以采用几种策略来优化交互流程。以下是一些有效的技术:
-
选择性截断:只保留对话的必要部分。例如,删除问候语或不太相关的交流,以在后续消息中节省空间。
-
总结:定期总结到目前为止讨论的内容,并在后续提示中使用这些内容。
-
分页:将对话或上下文内容分解成页面或部分,并独立处理每个部分。你可以使用如
www.chatsplitter.com/这样的提示分割器将较长的输入文档分成更小的、可管理的段。如果你处理的是较大的文档,这很有用。这个工具允许你轻松上传多个文件,并将它们自动分割成多个块,你可以将它们加载到 ChatGPT 中。 -
提示最小化:在最小化提示长度方面有一些空间,但正如你在这章中学到的,在整个章节中创建最佳提示,限制它们并没有太多意义。结果可能微不足道。话虽如此,根据你的用例,可能值得删除你在提示中添加的输入数据。
重置机制
当达到内存限制时,重置模型非常重要。未能这样做可能会导致输入或输出不可预测地截断,造成上下文丢失或答案错误。重置应该是一个受控的操作,在丢弃可丢弃部分的同时保持对话的精髓。最有效的方法是总结对话并将其用于下一个提示。
小心复制早期迭代中的错误转向。如果回答偏离了轨道,确保你在重置模型时不要包括那部分内容。
以下是一些重置对话的不同方法:
-
硬重置:完全清除对话并从新的初始化上下文开始
-
软重置:保留先前对话的关键点或总结作为初始化上下文
-
上下文缓存:将关键信息存储在外部数据库或上下文管理器中,并在需要时重新引入
使用具有更大内存的 GPT-4 模型
这是一个简单的修复,并在缓解内存问题方面取得了重大进展。最新的 GPT-4 模型具有更大的内存。GPT-35-Turbo 的令牌限制为 4,096 个令牌,而 GPT-4 和 GPT-4-32k 的令牌限制分别为 8,192 和 32,768,因此通常明智的做法是使用这些。只需记住 API 成本。
结论
正如你所学的,拥有一个坚实的提示工程策略非常重要,这样你才能克服提示工程的挑战。遵循迭代策略,并确保你提供具体、清晰的提示,包含丰富的背景信息和上下文,并避免歧义。在下一节中,我们将探讨一些具体的提示工程技巧。
了解提示工程技巧
让我们利用所学的 ChatGPT 提示技巧和特定于对话式人工智能的应用场景来使用它们。
在本节中,我们将深入研究高级提示工程技术,旨在利用 ChatGPT 在对话式 AI 中的特定用例的潜力。我们将探讨诸如针对响应的少样本学习、数据解释的摘要以及为旅行聊天机器人迭代改进提示的方法。每种技术都是为了提高 AI 的理解和输出,确保最终交互尽可能有效和与任务相关。无论是塑造客户支持聊天机器人还是集成 LLMs 进行数据摘要,本节应有助于你学习使用最有用的提示技术。
针对客户支持聊天机器人的少样本学习
一种常见的提示 ChatGPT 的方法,同时为输出提供上下文和更严格的边界,是使用少样本学习方法。在少样本学习中,一组训练示例作为你的提示的一部分提供。这种方法的优点是提供了额外的上下文,每个响应都为 ChatGPT 提供了你期望的输出示例,因此你可以对响应有相当程度的信心。
为了观察这一过程,让我们考虑让 ChatGPT 扮演一家智能手机公司的客户支持聊天机器人的角色。
单次提示可能如下所示:
Act as a dog training chatbot designed to answer questions about dog training.
- Only answer questions related to dog training
- If you're unsure of an answer, you can say "I don't know" or "I'm not sure" and recommend a source on the internet
ChatGPT 的输出效果良好,但对我们用例来说有点过于详细。你可以提供更多的输出指南,或者,通过少样本学习方法,你可以指导 ChatGPT 以更结构化和一致的方式回答:
Act as a dog training chatbot called Fido designed to answer questions about dog training.
- Only answer questions related to dog training
- If you're unsure of an answer, you can say "I don't know" or "I'm not sure" and recommend a source on the internet
Example conversations:
Example 1:
User: How do I stop my dog from barking at strangers?
Assistant: To curb your dog's barking at strangers, work on socialization and desensitization techniques. Reward calm behavior and consider using a 'quiet' command.
Example 2:
User: What's the best way to potty train my puppy?
Assistant: Consistency is key for potty training. Take your puppy outside frequently, especially after meals or playtime, and reward them for doing their business outside.
Example 3:
User: My dog pulls on the leash. What should I do?
Assistant: To correct leash-pulling, use a short leash and stop walking when your dog pulls. Only resume walking when the leash is slack. This teaches them that pulling gets them nowhere.
对于同样的例子,如果你在与 ChatGPT 的完成 API 交互,你的示例将是你发送给 API 的消息数组的一部分:
{"role": "system", "content": "You are a dog training chatbot called Fido designed to answer questions about dog training. Only answer questions related to dog training - If you're unsure of an answer, you can say "I don't know" or "I'm not sure"},
{"role": "user", "content": " How do I stop my dog from barking at strangers "},
{"role": "assistant", "content": " To curb your dog's barking at strangers, work on socialization and desensitization techniques. Reward calm behavior and consider using a 'quiet' command."},
{"role": "user", "content": " What's the best way to potty train my puppy?"},
{"role": "assistant", "content": " Consistency is key for potty training. Take your puppy outside frequently, especially after meals or playtime, and reward them for doing their business outside "}
通过向 ChatGPT 提供示例,你正在为模型提供特定领域的知识,同时设置任务的交互角色、响应格式和任务理解。你也许还在帮助保持响应的一致性。
对于这个用例,少样本学习使 ChatGPT 能够充当专业助手,将其从通用聊天机器人转变为能够提供特定领域指导的机器人,在这个例子中是针对狗的训练。在下一节中,我们将探讨如何使用 ChatGPT 执行另一个具有一些额外复杂性的常见用例。
为对话式代理总结数据的提示
LLMs 的一个显著用途是利用它们进行摘要任务。我们的提示摘要示例与标准文本摘要任务不同。相反,我们将创建一个提示来回答有关 JSON 格式数据的疑问。
这种技术在你的聊天机器人或自动化助手旨在回答询问者关于特定数据的问题时非常有价值。
在这个例子中,假设您有一个在线旅行社的客户支持聊天机器人。您的聊天机器人正在处理客户关于其航班行李详情的询问。聊天机器人与机构的后台网络服务有直接集成。它还拥有当前用户的详细信息,因此查找客户的预订数据非常直接。复杂性在于解释和表示数据以回答用户的问题。
在我们的示例中,系统返回的航班数据看起来如下:
"flights": [{
"status": "CONFIRMED",
"supplierName": "Easyjet Flight",
"segments": [{
"direction": "OUTBOUND",
"legs": [{
"flightNumber": "EZY8703",
"airline": {
"bagsConfiguration": {
"cabinBagWeight": "NO_LIMIT",
"holdWeight": "20kg",
"baggageIncluded": false, "cabinBagDimensions": "36x45x20 cm", "cabinBagAllowance": 1}
},"carrier": {"carrierCode": "EZY","name":"easyJet"}
}
]},{
"legs": [{
"airline": {
"bagsConfiguration": {
"holdWeight": "20kg",
"cabinBagDimensions": "36x45x20cm",
"cabinBagAllowance": 1,
lugageIncluded": false,
"cabinBagWeight": "NO_LIMIT"
}
},"carrier": {"name": "easyJet","carrierCode": "EZY"},
"flightNumber": "EZY8706"
}
],
direction": "INBOUND"}
]
}]
在基于意图的对话式人工智能系统中,我们会根据数据构建对用户的响应,通过解析这些数据并手动或使用模板系统构建它。这可能会变得脆弱且难以维护。相反,我们可以使用 ChatGPT 来处理使用航班数据的总结来回答问题。
让我们看看一个实现这一目标的提示:
You are a customer support chatbot for an online travel agency. look at the following flights information represented in JSON format delimited with ###, use this to create a summary of inbound and outbound flight baggage details
Summarize outbound then inbound and include all flights even if they have no baggage
If a flight has no baggage state "My records show no confirmed hold luggage for this part of your trip.
Include the following statement as the last part of the summary:
"Hold luggage is not per person, but for the entire booking."
flights: ###{flights}###
在收到 ChatGPT 的连贯输出后,我们可以迭代地改进我们的提示以适应我们的特定用例。例如,我们可以通过改变输出以生成针对 IVR 系统定制的摘要:
create a summary of inbound and outbound flight baggage details for an IVR system
如您所见,当输入是结构化数据或非结构化文本时,使用 ChatGPT 进行总结的技术效果良好。如果您正在使用基于意图的系统,但希望谨慎地引入 LLM 技术,并且仅在意图级别或针对某些意图进行,这也是一种很好的技术。
ChatGPT 仍然可以做更多。让我们考虑在下一个示例中构建我们的示例,以创建一个完整的聊天机器人。
提示创建由 ChatGPT 驱动的自己的聊天机器人
我们可以通过使用 ChatGPT 创建自己的工作旅行助手聊天机器人来构建我们之前旅行助手代理的示例。
这个代码示例展示了使用 Python、ChatGPT 和 IPython 小部件在 Jupyter Notebook 环境中创建的一个简单的交互式聊天机器人。聊天机器人包含一些以 JSON 格式存储的节假日信息,这些信息包含在你的提示中。
导入必要的库
首先,我们需要导入所有必要的库:
import os
import json
import openai
import ipywidgets as widgets
from IPython.display import display, clear_output, Markdown
openai.api_key = os.getenv("OPENAI_API_KEY")
导入了必要的库和模块以支持聊天机器人的功能。例如,使用 openai 与 GPT-3.5-Turbo 模型交互,使用 ipywidgets 和 IPython.display 在 Jupyter Notebook 中创建交互式用户界面。我们还传递了包含我们的 OpenAI 密钥的环境变量。
加载聊天机器人的预订数据
接下来,我们需要从 JSON 文件中加载聊天机器人的预订数据:
with open('booking.json', 'r') as f:
booking = json.load(f)
代码读取 booking.json 文件以获取一个虚构客户的预订详情,这样当您询问它关于您的假期时,聊天机器人将有一些信息。这模拟了与后台系统的集成。
定义用于调用完成端点的辅助函数
以下代码概述了调用带有我们的消息和其他参数的 completions 端点的辅助函数:
def chat_with_gpt(messages, model="gpt-3.5-turbo",
top_p=1, frequency_penalty=0,
presence_penalty=0,temperature=0
):
try:
response = openai.ChatCompletion.create(
model=model,
messages=messages,
top_p=top_p,
frequency_penalty=frequency_penalty,
presence_penalty=presence_penalty,
temperature=temperature
)
return response.choices[0].message["content"]
except Exception as e:
return str(e)
此函数将对话历史(messages)发送到 GPT-3.5-Turbo 模型,并返回模型的响应。
创建 UI 元素
以下元素是构成我们聊天界面的简单 UI 组件:
inp = widgets.Text(value="Hi",
placeholder='Enter text here…')
chat_button = widgets.Button(description="Chat!")
output = widgets.Output()
panels = []
UI 组件使用 ipywidgets 创建。这包括一个文本输入字段(inp)、一个按钮(chat_button)和一个输出区域(output),用于显示对话,以及初始化以保存将要显示的对话面板的面板列表。
初始化上下文
接下来,我们将使用系统提示和预订信息为与系统的对话创建上下文:
system_content = f"You are Shelley an automated travel assistant to answer questions about a customers holiday, \
start by greeting them by their first name and asking them how you can help with their holiday \
mention where they are going \
This customers holiday details are here: \
{booking}"
context = [{'role':'system', 'content':system_content}]
上下文数组以系统消息初始化,该消息指示助手提示细节和客户数据输入。这很重要,因为它为对话设置了场景。
定义 collect_messages 函数和 UI 元素
我们还将创建一个函数来格式化消息并创建我们的 UI 元素:
def collect_messages(change):
# ...
context.append({'role':'user', 'content': f"{prompt}"})
# ...
context.append({'role':'assistant', 'content': f"{response}"})
# ...
当用户点击 Chat! 按钮时,将触发此函数。
它读取用户的输入,清除输入字段,将用户的消息更新到上下文数组中,并通过调用 chat_with_gpt 获取助手的响应。
上下文数组再次更新,以包含助手的响应,从而形成对话历史。
用户和助手的消息将被格式化并添加到面板列表中,该列表用于保存对话。
collect_messages 函数也绑定到 chat_button 的点击事件:
chat_button.on_click(collect_messages)
dashboard = widgets.VBox([inp, chat_button, output])
display(dashboard)
创建一个垂直框(VBox)小部件来包含文本输入、按钮和输出区域,形成聊天机器人仪表板。
使用 display 函数在 Jupyter Notebook 中渲染仪表板。
聊天机器人上下文
上下文数组在管理对话历史和确保 ChatGPT 提供连贯且与上下文相关的响应中起着关键作用。它随着用户和助手之间的每次交流而更新,为根据进行中的对话和初始系统指令生成有意义的响应提供必要的上下文。本质上,这就是当你与 ChatGPT UI 交互时幕后发生的事情。
运行代码后,你应该能够看到一个简单的聊天机器人界面:

图 4.2 – 聊天机器人界面
你现在可以通过说“你好”开始对话。你应该会被 ChatGPT 欢迎并能够就你的假期提出后续问题。
尝试更改 JSON 中的信息,并自己提出其他问题。
你也可以尝试更改提示和数据输入,创建不同类型的聊天机器人和用例。
摘要
在本章中,我们探讨了提示工程这一新兴领域。您对成功提示的核心组件有了理解。我们介绍了在提示中明确定义角色、受众、输入和输出数据的重要性,以便调整模型的响应以适应特定任务或用户群体。
在强调提示工程的迭代性质方面,我们看到了拥有一个稳固的提示工程策略的重要性。我们希望已经涵盖了在提示工程期间需要寻找或考虑的一些具体细节。
我们还探讨了提示工程的一些技术和如何在针对对话人工智能领域的实际案例中使用这些技术。
通过在多个数据示例上的迭代开发和测试,我们鼓励您优化提示以从 ChatGPT 中获得更好、更一致的结果,从而增强模型在各种应用中的实用性。
因此,您现在应该对继续探索更复杂的 ChatGPT 用例感到舒适。在我们下一章中,我们将深入探讨 LangChain,这是一个开源框架,有助于将 ChatGPT 与其他外部组件集成,从而创建更高级的应用。
进一步阅读
以下链接是该章的资源:
第五章:LangChain 入门
在本章中,我们将探讨 LangChain 以及这个框架如何使用户能够构建复杂的 LLM 应用。您将了解 LangChain 及其解决的问题,以及 LangChain 的核心组件、LangChain 表达式语言和您可以创建的不同类型的链的介绍。
在其核心,LangChain 是一个开源的开发框架,旨在构建 LLM 应用。到本章结束时,您将具备构建 LangChain 应用和使用下一章中介绍的高级功能和能力的技能。
在本章中,我们将涵盖以下关键领域:
-
LangChain 简介
-
LangChain 的核心组件
-
理解 LangChain 表达式语言
-
创建不同的 LangChain 链
本章旨在为您介绍核心概念,为您掌握 LangChain 打下坚实的基础,使您能够继续学习更复杂的 LangChain 应用。
技术要求
在本章中,我们将广泛使用 ChatGPT,因此您需要注册一个免费账户。如果您还没有创建账户,请访问 https://openai.com/,然后在页面右上角点击开始使用,或者访问 https://chat.openai.com。
为了执行示例,除非另有说明,否则建议您通过网页或移动应用使用 ChatGPT。
最后一个示例技术需要安装 Python 3.9 和 Jupyter Notebook(https://jupyter.org/try-jupyter/lab/index.html)。
LangChain 简介
随着我们进一步深入 LLM 应用开发的领域,您会开始注意到这类应用很快就会变得复杂,并需要越来越复杂的提示。一个提示可以包括基本的系统指令、用户输入、主题元数据、用户个性化、之前的交互数据以及其他来自其他系统的信息。因此,一个典型的应用可能需要多次提示 LLM,并解析其输出,从而需要大量的辅助代码。这就是 Harrison Chase 创建的 LangChain 发挥作用的地方,为您的 LLM 应用添加结构,并简化开发过程。
LangChain 的出现是由于在开发蓝图中使用常见抽象的同时,需要构建复杂的 LLM 应用。它是一个拥有强大社区和许多活跃贡献者的开源框架。
LangChain 的诞生是由简化开发流程的愿望驱动的,使开发者与 LLM 合作时不再感到那么困难。实际上,这正是我开始使用 Langchain 的主要原因——作为一种简单的方式来部署一个潜在客户的原型,展示一个能够就客户自己的数据进行聊天的聊天机器人。
LangChain 是一个针对构建由语言模型驱动的应用程序的框架。它通过接口与语言模型和应用特定数据,强调上下文感知和推理。它提供模块化组件和现成的链,以简化使用和定制,便于以结构化的方式组装组件以执行高级任务。该框架还封装了各种模块,如模型 I/O、检索、链、代理、内存和回调,以满足 LLM 应用程序中交互和数据处理的各个方面。
LangChain 库
LangChain 框架支持两种不同的脚本语言:Python 和 JavaScript(TypeScript)。LangChain 的精髓在于其对组合和模块化的强调,包含众多单个组件。这些组件可以合并使用,也可以独立使用,展示了框架的灵活特性。
两个库都易于使用。虽然 Python LangChain 库更加成熟且功能丰富,但 TypeScript 库较新,但正在开发中,以紧密模仿 Python 版本的特性。两者都旨在易于使用,重点在于简化 LLM 在各种应用程序中的集成和使用。
由于拥有如此强大的社区,两个库中都有大量的贡献者,从文档加载器到代理蓝图,再到内存提供者,以及来自大小技术提供商的集成。
但为了最好地利用 LangChain,从其基础知识开始是很好的。在下一节中,我们将探讨 LangChain 的核心组件。
LangChain 的核心组件
LangChain 提供了各种模块,可用于创建语言模型应用程序。这些模块可以单独用于简单应用,也可以组合起来创建更复杂的应用。灵活性是这里的关键!
任何 LangChain 链最常见的基本组件如下:
-
LLM 模型:LangChain 的核心推理引擎是你的语言模型。LangChain 使得使用多种不同类型的 LLM 变得容易。
-
提示模板:这些为 LLM 提供指令,控制其输出。理解如何构建提示和不同的提示策略至关重要,因此我们很高兴在上一章中已经涵盖了这一点。
-
输出解析器:这些将 LLM 的原始响应转换为更可用的格式,简化了下游处理。
让我们更详细地看看这些核心组件。
在 LangChain 中与 LLMs 一起工作
LangChain 中有两种不同的 LLM 模型,称为 LLMs 和 ChatModels。这些模型用于与不同的 LLM 模型进行接口。LangChain 支持许多不同类型的 LLMs,因此是尝试不同类型 LLMs 和比较结果的强大推动者。
-
LLMs:这是一个以字符串作为输入并返回字符串的语言模型
-
ChatModel: 这是一个以消息列表为输入并返回消息的语言模型
LLMs
LangChain 中的 LLM 指的是它们与之交互的纯文本完成模型——例如,GPT-4。这些模型接受简单的字符串输入并输出字符串。
Chat 模型
相比之下,Chat 模型是针对对话进行调优的。LLM API 使用与纯文本完成模型不同的接口。它们不是接受单个字符串,而是接受一个带有特定角色标签的聊天消息列表:系统、助手和用户。您已经在第三章的学习使用 ChatGPT API部分中了解了与聊天消息列表一起工作的概念。ChatGPT 的完成端点期望这种输入。
由于我们专注于使用 ChatGPT 和通过 LangChain 创建对话体验,所以本章的其余部分我们将更多地关注 Chat 模型。如果您对执行生成任务感兴趣,那么使用 LLM 模型可能更适合。
在 LangChain 中,聊天模型支持一个 ChatMessages 列表,它有两个属性:
-
content: 消息的内容 -
role:ChatMessage来源实体的角色
支持的角色如下:
-
AIMessage -
HumanMessage -
SystemMessage -
FunctionMessage
您也可以在ChatMessage类中手动创建角色。
ChatModel 提供了一个predict_messages()方法,通过消息列表与模式进行交互。这看起来可能如下所示:
from langchain.schema import HumanMessage
text = " Im looking to book a direct flight from New York to London departing on December 10th and returning on January 5th. Can you provide me with the available options, including airlines, flight times, and prices?"
messages = [HumanMessage(content=text)]
chat_model.predict_messages(messages)
这应该输出以下类似的内容:
AIMessage(content='Certainly! Here are some available options for direct flights....')
现在我们来看如何使用 LLM 的提示模板。
提示模板
正如我们所见,提示词可以很快变得详细和长。我们也经常希望重用我们的提示词。这就是 LangChain 提示模板能大量帮助的地方。它们作为结构化的蓝图,用于为我们要执行的所有不同任务创建提示词。
提示模板可以组合,LangChain 还提供了常见任务的提示,如问答和摘要。
从本质上讲,我们不必直接用指令操作提示字符串,只需传递特定提示的变量,让 LangChain 处理其余部分。我们还可以使用 LangChain 提示来处理我们的 Chat Model 提示,让我们看一下。
LangChain 中的PromptTemplate类充当字符串提示的模具,可以用用户定义的参数填充。
让我们来看一个例子。您正在尝试构建一个应用程序,该应用程序可以分析您的聊天记录,以便您能够了解不同部门之间对话的情感。
我们导入PromptTemplate,然后使用from_template函数创建模板和相应的变量占位符:
from langchain.prompts import PromptTemplate
prompt_template = PromptTemplate.from_template(
"Look at the following conversation {conversation} from the following service area {service_area} on {event_date_time} and returna sentiment"
)
conversation = """Customer: My new bike is missing a wheel!\
Chatbot: I'm sorry to hear that. Could I have your order number, please? ….
"""
conversation_analysis = prompt_template.format(
conversation=conversation,
service_area="complaints",
event_date_time="2023-10-19 14:30:00"
)
如果您在模板上调用format方法并输出conversation_analysis,您应该得到以下类似的内容:
"Look at the following conversation Customer: My new bike is missing a wheel!Chatbot: I'm sorry to hear that. Could I have your order number, please?... from the following service area complaints on 2023-10-19 14:30:00 and return a sentiment"
注意,您已经完成了一个由模板和传递的变量组成的完整提示。
聊天提示模板
ChatPromptTemplate与聊天模型一起工作,允许创建对话提示,封装一系列具有指定角色(如'system'、'human'和'AI')的聊天消息。
让我们来看一个例子。我们正在创建一个健康诊所聊天机器人,以协助处理一般健康相关咨询。我们导入ChatPromptTemplate,然后通过调用from_messages函数创建模板:
from langchain.prompts import ChatPromptTemplate
chat_template = ChatPromptTemplate.from_messages(
[
("system", "You are a health advisory bot for HealthHub Clinic. You can answer questions from the patient called {name}"),
("ai", "Hi, {name} please ask me your question."),
("human", "{user_input}"),
]
)
然后,您可以使用此模板如下;这将创建我们的消息列表,并用我们分配的变量填充:
messages = chat_template.format_messages(name="Lucy",
user_input="What are the symptoms of the flu?")
这些消息现在已正确格式化为以下形式:
[SystemMessage(content='You are a health advisory bot for HealthHub Clinic. You can answer questions from the patient called Lucy'),
AIMessage(content='Hi, Lucy please ask me your question.'),
HumanMessage(content='What are the symptoms of the flu?')]
您现在可以使用这些内容在调用您的聊天模型时传递格式化的提示列表:
chat_model= ChatOpenAI()
Chat_model(messages)
此外,还有一些现成的提示,例如使用少量示例的提示模板。少量示例模板的主要组成部分是示例,这是一个要传递到提示中的示例列表,以及示例提示本身。提示模板为您提供了许多提示类型的选择;然而,有时您可能想创建自己的提示模板。LangChain 也通过自定义提示模板使这一过程变得简单。让我们在下一节中看看这些内容。
自定义模板
LangChain 中的自定义提示模板通过允许用户为超出标准模板范围的任务创建定制提示,提供了灵活性。当任务需要特定的提示格式或特定细节来引导语言模型朝预期方向时,这些自定义模板变得非常有用。让我们来看一个例子:
Consider a scenario where you want to generate responses for a learning productivity assistant in a chat interface. This assistant might need to consider the specific task the user is asking about, the time available, and any particular user preferences or constraints.
Here's an example of what the custom prompt template for this productivity assistant could look like:
from langchain.prompts import StringPromptTemplate
from pydantic import BaseModel, validator
class ProductivityAdvicePromptTemplate(
StringPromptTemplate, BaseModel
):
@validator("input_variables")
def validate_input_variables(cls, v):
required_vars = {"task", "time_available",
"user_preferences"}
if not required_vars.issubset(v):
raise ValueError(
f"Input variables must include: {required_vars}")
return v
def format(self, **kwargs) -> str:
prompt = f"""
As a virtual productivity assistant, provide advice on:
Task: {kwargs['task']}
Time Available: {kwargs['time_available']}
User Preferences: {kwargs['user_preferences']}
Advice:
"""
return prompt
此模板的示例用法可能如下所示,通过在定义提示时传递输入变量,并使用您所需的变量调用format函数:
productivity_advisor = ProductivityAdvicePromptTemplate(
input_variables=[
"task", "time_available", "user_preferences"])
# Generate a prompt for the virtual assistant
prompt = productivity_advisor.format(
task="write a research paper",
time_available="2 hours",
user_preferences="focus on quality over quantity")
您现在拥有了一个可以重复使用和分享的生产力建议提示模板。
使用输出解析器
现在我们已经了解了 LLM 和我们的提示,LangChain 应用的核心组件的最后一个是输出解析器。
通常,一旦我们从我们的 LLM 中提取出响应,我们会对某种格式有特定的要求。我们的示例用例基于我们在第二章中执行的一些任务,在名为创建话语的部分。我们可以使用我们的 LLM 来创建意图和话语。在这些例子中,尽管看起来是以 JSON 格式响应,但实际上是一个字符串。更有用的情况是将 LLM 的输出字符串解析为 Python 字典。
首先,我们导入所有必需的库,然后通过提供名称和描述来创建我们的ResponseSchema。我们可以根据需要创建多个此类方案,以匹配我们的输出变量,然后通过调用StructuredOutputParser.from_response_schemas函数来创建输出解析器。
我们可以通过在输出解析器上调用get_format_instructions()来创建我们的指令,以便包含在我们的提示模板中。然后,这些指令将用于我们的提示模板。请记住将我们的意图格式指令传递到我们的提示中。让我们在下面的代码示例中看看我们如何做:
intent_schema = ResponseSchema(name="intents",
description="Format the output as JSON object consisting of a key: intents, the intents key will be a list of objects with the following keys: intent, utterance, category")
response_schemas = [intent_schema]
intent_output_parser = StructuredOutputParser.from_response_schemas(
response_schemas)
intent_format_instructions = \
intent_output_parser.get_format_instructions()
print(intent_format_instructions)
intent_template = """
Create intents and utterances for a chatbot which will answer questions about a college, \
Create 10 examples of intents for the following categories: facilities and course_information \
ensure that each intent has 10 utterances, create 5 long tail and 5 more common utterances \
{intent_format_instructions}
"""
prompt_template = ChatPromptTemplate.from_template(intent_template)
messages = prompt_template.format_messages(
intent_format_instructions=intent_format_instructions)
#messages = prompt_template.format_messages(intent_examples=intents)
chat = ChatOpenAI(temperature=0.0, model="gpt-4")
response = chat(messages)
output_dict = intent_output_parser.parse(response.content)
output_dict.get('intents')
一旦我们从 LLM 那里得到响应,我们只需将我们的响应传递到我们的解析函数中,以格式化我们的结果 - output_dict = intent_output_parser.parse(response.content) - 现在,它将是一个我们可以像通常一样交互的字典。
在这里使用输出解析器有很多好处,因为它可以管理在提示中使用的大量特定指令,并且可以根据需要解析生成的响应,而无需手动格式化每个响应。输出解析器是 LangChain 应用的核心组件之一。
在下一节中,我们将探讨链的概念以及用于操作它们的语言。
理解 LangChain 表达式语言
我们已经涵盖了核心 LangChain 组件。现在,我们将关注一个关键概念,该概念可用于创建和执行这些组件:LangChain 表达式语言(LCEL)。让我们深入了解 LCEL 是什么,并理解它在 LangChain 框架中的重要性。
什么是 LCEL?
链的概念是它们是 LangChain 的关键构建块。链是一系列功能块的集合,在其最简单的形式中,一个链将包括一个提示、对 LLM 的调用以及结果的处理。我们在上一节中看到了这些功能块。在最复杂的情况下,链可以由数百个步骤组成。
LCEL 提供了一个声明性语法和编排框架,它是为了使用户能够以标准化的方式定义和调用功能链,使其尽可能容易运行以及创建自定义链而创建的。
LCEL 的关键组件
LCEL 提供了许多开箱即用的功能,并基于管道化和模块化,以及一些特定功能和每个组件的可运行协议,每个对象都提供了一个通用接口,因此您可以以相同的方式与每个对象交互。
以下列出了 LCEL 的关键特性:
-
流支持:LCEL 通过减少第一个输出产生前的延迟来提高流效率。它从 LLM 流式传输令牌到输出解析器,以便在实时中进行快速、逐步的解析。
-
异步和同步支持:使用 LCEL 构建的链可以使用同步(例如,在 Jupyter 笔记本中进行原型设计)和异步(例如,在 LangServe 服务器上)API 进行调用。
-
优化并行执行:LCEL 通过按顺序执行并行步骤,如同时从多个来源检索文档以最小化延迟,有效地处理任务。
-
重试和回退:为了确保您的应用程序是可靠的,您可以在 LCEL 链的任何部分配置重试和回退。
-
输入和输出模式:为了帮助进行输入和输出验证、文档编写和错误处理,LCEL 链包括 Pydantic 和 JSON Schema,这些都可以用于验证。
-
可观察性:LCEL 默认记录链中每个步骤的输入和输出以及步骤序列的详细信息,然后可以使用 LangSmith 服务器查看,我们将在后面的章节中介绍。
-
集成:对于复杂的链,访问每个步骤的结果对于反馈或调试通常至关重要。LCEL 为 LangSmith 提供了易于集成的功能,用于监控和调试。
Runnable 协议
LCEL 的 Runnable 协议对于自定义链的创建非常重要。LCEL 采用“Runnable”协议来简化自定义链的开发。
LCEL 中的 Runnable 协议旨在使构建和使用自定义处理链更加容易。简单来说,它就像一套规则或指南,有助于组织这些链的创建和运行。此协议包括用于流式传输数据和批量处理等任务的特定方法,以及它们的高级版本,用于更复杂的操作。本协议的主要目的如下:
-
标准化:它创建了一种统一的方式来定义和使用系统的不同部分。这意味着无论您处理的是哪个组件(例如模型或工具),您都使用相同的一组规则来与之交互。
-
灵活性:通过采用标准方法,混合和匹配不同组件变得更加容易。您可以将不同的部分插入到链中,它们将协同工作得很好。
-
清晰性:它提供了关于每个组件输入和输出的清晰指南。这有助于理解和检查系统的每个部分是如何工作的。
-
效率:它简化了构建和修改链的过程,节省时间,并减少了出错的可能性。
因此,本质上,Runnable 协议就像是一种通用语言或蓝图,它有助于在 LCEL 中有效地构建、修改和理解自定义链。
LCEL 语法
在 LCEL 中,我们使用 管道操作符(|)而不是 Chain 来创建我们的链。
Chain = x | y
当 LangChain 遇到两个对象之间的管道操作符时,它会尝试将 x 传递给 y。
LCEL 的一个简单示例
为了帮助您看到使用 LCEL 和传统方法之间的差异,让我们比较创建简单链的两种方法。
这两个示例实现了相同的结果:设置一个包含语言模型和默认提示的链。让我们探索每个示例:
-
按照以下方式使用
LLMChain类。在这种方法中,您明确创建LLMChain类的一个实例:llm = ChatOpenAI(() second_prompt = ChatPromptTemplate.from_template("tell me a joke")) chain = LLMChain(llm=llm, prompt=default_prompt)这涉及到将语言模型(
llm)和默认提示(default_prompt)作为参数传递。 -
通过使用管道操作符(
|)将每个步骤连接起来,使用 LCEL 创建链:chain = llm | default_prompt此方法使用管道操作符(
|)将语言模型(llm)和默认提示(default_prompt)链接在一起。管道操作符有效地将一个组件(LLM)的输出“管道”到下一个组件(默认提示处理器)。
LCEL 的关键差异和优势
这里有一些关键差异和优势需要指出:
-
LLMChain实例化可能更易于阅读和理解。虽然管道操作符简洁,但可能需要一些时间来适应。 -
LLMChain类,您可以通过子类化或修改类来扩展功能。使用管道操作符,您通过向管道添加更多组件来扩展。 -
底层机制:虽然两者都实现了类似的结果,但底层机制可能略有不同。
-
高级功能:LCEL 在 Python 和 Typescript 中提供了优化并行执行和通过重试和回退处理错误的支持等好处。LCEL 还提供了在最终链完成之前输出链的各个部分结果的能力,这对于调试和向最终客户端发送更新非常有用——例如,如果您想在长时间执行期间发送聊天界面更新。
小贴士
初始时,LLMChain 接口是标准方法。然而,更现代的方法是 LCEL。LLMChain 仍然有效,但对于新的应用程序开发,建议使用 LCEL 来组合链。
在本章的后续示例和本书的其余部分,我们将尽可能使用 LCEL。在下一节中,我们将深入探讨创建不同类型的 LangChain 链。
创建不同的 LangChain 链
在本节中,我们将探讨如何在 LangChain 中创建一些可以创建的各种链。我们的目标是指导您从基本链到更高级链。
我们将从示例开始,介绍简单链的基本概念。这将为我们理解 LangChain 中链的工作原理打下基础。接下来,我们将学习如何创建顺序链、并行链,最后是路由链。
到本节结束时,您将清楚地了解如何创建和利用不同的 LangChain 链,并具备将这些技能应用于您未来 LangChain 项目的技能。让我们深入探讨。
基本链示例
在这个基本示例中,我们将展示使用提示和 LLM 组件的最简单链,这构成了许多更复杂实现的基石。在这个例子中,我们正在使用我们的模型将文本翻译成任何语言:
prompt = ChatPromptTemplate.from_template("""
Translate this text: {text} to {language}
""")
language = "Spanish"
text = "what is the capital of england"
runnable = prompt | ChatOpenAI() | StrOutputParser()
runnable.invoke({"text":text,"language":language})
通过查看代码,你可以看到这是一个简单的链。我们从一个模板字符串创建一个ChatPromptTemplate实例。模板字符串定义了将呈现给语言模型的提示。提示要求模型将文本翻译成指定的语言:
prompt = ChatPromptTemplate.from_template("""
Translate this text: {text} to {language}
""")
提示模板是一个包含以下占位符的字符串:
-
{text}:这个占位符将被要翻译的文本替换 -
{language}:这个占位符将被目标语言替换
然后,我们可以创建 runnable,这是我们实现 runnable 接口并设计成可以串联在一起的组件链,这是 LCEL 的核心概念。这一行代码使用 | 运算符创建了 runnable 链:
runnable = prompt | ChatOpenAI() | StrOutputParser()
runnable 是由三个组件组成的链:
-
prompt:这个组件将聊天提示模板应用于输入数据 -
ChatOpenAI:这是一个将提示文本发送到ChatOpenAI聊天模型的模型 -
StrOutputParser:这个模型将ChatOpenAI聊天模型的输出解析为字符串,便于轻松集成到各种应用程序中。
很可能你会在实例化 LLMChain 类的链中遇到这种情况。这相当于我们在这个例子中的可运行代码:
llm_chain =LLMChain(llm=llm,
prompt=PromptTemplate.from_template(prompt_template))
LLMChain 现在是一个过时类,因此最好使用 LCEL。
在下一节中,我们将探讨创建一个简单的顺序链,用于更复杂的特定于对话人工智能的用例。
创建一个用于调查对话数据的顺序链
让我们先看看一个简单的顺序链。顺序链依次运行一系列链,当你有预期的输入和输出以执行下游处理时,它工作得很好。
对于这个例子,假设我们有一个名为 GreenRide 的电动汽车订阅公司,它使用实时聊天在其网站上处理客户查询。它有兴趣创建一个聊天机器人来自动化其部分客户对话。它有很多未分类的聊天记录。它希望将这些聊天记录分类到 常见问题(FAQs)和交易性查询中,以便了解哪些查询是复杂的,哪些是简单的。它对使用基于意图的 自然语言理解(NLU)平台来处理交易性查询以及使用大型语言模型(LLM)来处理 FAQs 感兴趣。对于交易性查询,它希望根据意图对对话进行聚类,以便它可以更详细地查看每个用例,并查看哪些团队需要参与。
你被分配去查看这些转录数据并执行这些任务。因此,让我们来分解一下:
-
将每个对话分类,并将其分为两个列表:FAQs 和交易性对话。
-
看一下交易性对话列表,并根据意图对这些对话进行聚类。
为了实现这一点,我们将使用 LangChain 通过一系列操作处理聊天记录。这些过程在以下图中突出显示:

图 5.1 – 调查对话数据的顺序链过程
你需要两个链来完成分类和聚类。第一个链,使用一个 LLM 和一个提示,将接受会话记录列表并返回两个对话列表。第二个链也将由一个 LLM 和一个提示组成,并将接受交易对话列表并按意图类型进行聚类。
在这个例子中,我们将使用 LCEL 并将一个链的结果传递给另一个链以进行进一步处理:
-
首先,从
langchain导入必要的模块,并使用温度0初始化我们的ChatOpenAI模型,因为这不是一个创意任务:import json from langchain.output_parsers import ( ResponseSchema, StructuredOutputParser) from langchain.prompts import ( SystemMessagePromptTemplate, HumanMessagePromptTemplate, ChatPromptTemplate) from langchain.chat_models import ChatOpenAI chat_model = ChatOpenAI( temperature=0, model="gpt-3.5-turbo-1106") -
会话记录从 JSON 文件中加载,这将是处理的数据源:
with open('transcripts.json', 'r') as file: transcripts = json.load(file) -
设置我们的输出模式以将两个对话分类到
transactional_transcripts和faq:response_schemas = [ ResponseSchema(name="transactional_transcripts", description="Format the output as JSON list of conversations with the same JSON format as the input,add a category key to each conversation", type="list"), ResponseSchema(name="faq", description="Format the output as JSON list of conversations with the same JSON format as the input, add a category key to each conversation ", type="list"), ]你会注意到,尽管你为你的两个分类会话记录列表有一个响应模式,但你将只使用一个,即
transactional_transcripts,来完成这个处理任务。 -
设置你的提示模板以分类会话记录,包括动态内容的占位符:
transcript_template = "Look at the following chat transcripts {transcripts} and categorize them into FAQ and transactional in the following format {format_instructions}" -
配置一个输出解析器来结构化语言模型的输出,并设置一个
ChatPromptTemplate用于分类任务:output_parser = StructuredOutputParser.from_response_schemas( response_schemas) format_instructions = output_parser.get_format_instructions() prompt = ChatPromptTemplate( messages=[transactional_categorization_prompt_template], input_variables=["transcripts"], partial_variables={"format_instructions": format_instructions}, ) -
创建你的交易分类处理链,结合提示、ChatGPT 模型和输出解析器来分类会话记录。这是使用 LangChain 的链机制组成的,其中每个组件都通过管道运算符(
|)连接:chain_one = prompt | chat_model | output_parser这是第一个完成的链,所以现在你可以继续创建下一个链。
-
对于第二个意图聚类阶段,你将创建新的响应模式和一个意图聚类提示模板:
intent_response_schemas = [ ResponseSchema(name="transactional_intents", description="Format the output as JSON list of conversations, add an intent key to each conversation", type="list"), ] intent_transcript_template = "Look at the following chat transcripts {transactional_transcripts} Cluster these conversations by intent {intent_format_instructions}" -
首先设置第二个处理链进行意图聚类,通过创建一个新的提示和意图输出解析器。我们可以使用与第一个链相同的聊天模型,尽管根据你的任务,这些可能不同。LangChain 的美丽之处在于所有组件都是可互换的。
intent_clustering_prompt_template = \ HumanMessagePromptTemplate.from_template( intent_transcript_template) intent_output_parser = \ StructuredOutputParser.from_response_schemas( intent_response_schemas) intent_format_instructions = \ intent_output_parser.get_format_instructions() prompt_two = ChatPromptTemplate( messages=[intent_clustering_prompt_template], input_variables=["transactional_transcripts"], partial_variables={ "intent_format_instructions": intent_format_instructions}, ) -
代码的最后部分帮助你使用你创建的元素创建第二个链。
chain_one的会话记录输出被传递进去:chain2 = ( {"transactional_transcripts": chain_one} | prompt_two | chat_model | intent_output_parser ) chain_two_result = chain2.invoke({"transcripts": transcripts})输出应该是一个字典,由会话记录列表和意图及类别属性组成。你可以如下访问第一个:
print(chain_two_result.get('transactional_intents')[0])
这里还有其他你可以尝试的改进。如果你将要处理大量的会话记录,循环处理数据块可能是个好主意,这样你就不太可能遇到标记问题。
你还可以通过添加另一个链元素进行进一步处理,例如,为意图创建话语或为特定部门分类意图。
使用 LangChain,我们还可以并行运行链。在下一节中,让我们看看一个例子。
利用 LangChain 中的并行链进行高效的多源信息收集
可能会有这样的情况,你想要将链作为序列的一部分并行运行。例如,想象一个场景,我们想要同时查询多个信息源。这种能力在用户提出需要从不同类型的内容中获取数据的问题时特别有用,例如新闻文章、科学论文和一般网络信息。以下图概述了并行链中涉及的过程:

图 5.2 – 在序列中使用并行链
以下代码示例说明了如何实现这种方法:
-
创建我们的模型,然后创建三个我们将要在链中使用单独的提示(
news_chain、academic_chain和web_info_chain),每个提示都使用一个模板来查询特定类型的内容(新闻、学术论文和一般网络信息)关于一个给定主题:model = ChatOpenAI(model="gpt-4-1106-preview") news_prompt = ChatPromptTemplate.from_template( "summarize recent news articles about {topic}") academic_prompt = ChatPromptTemplate.from_template( "summarize recent scientific papers about {topic}") web_info_prompt = ChatPromptTemplate.from_template( "provide a general overview of {topic} from web sources") -
使用
RunnableParallel类创建我们的可运行并行链,因为它用于并行运行这些链:parallel = RunnableParallel( news = news_prompt | model, academic = academic_prompt | model, web_info = web_info_prompt | model ) -
使用主题(例如,“人工智能”)调用并行链,每个链将根据其配置检索相关信息:
results = parallel.invoke({"topic": "artificial intelligence"})这将实现你预期的效果。所有链都并行运行,并以
results['web_info'])的形式返回它们的结果。创建所有三个结果的总结可能更有用,以回答用户的问题。为了实现这一点,你需要运行并行链,然后将其作为序列链的一部分使用。
-
创建总结提示:
summarise_prompt = ChatPromptTemplate.from_template(""" summarize the following information from these different sources: News source: {news} Academic: {academic} Web: {web_info} Summary: """) -
创建我们的
RunnableSequence并使用invoke()调用我们的链:summarise_chain = parallel | summarise_prompt | model summarise_output = summarise_chain.invoke( {"topic": "artificial intelligence"})
总结来说,RunnableParallel会输出一个包含每个并行链结果的字典。
我们可以使用我们给并行链提供的键来访问这些结果(例如,新闻、学术和网页信息)。
我们将整个输出字典传递给RunnableSequence。
然后,我们的summarise_prompt提示可以通过键访问这些结果来填充其模板。因此,这允许将并行过程的输出平滑地传递到序列链中。
让我们继续一个稍微复杂一点的例子,其中我们智能地路由我们的请求到不同的链。
路由链以有效回答问题
在创建一个由 LLM(大型语言模型)驱动的应用程序时,你可能需要根据需要提供的问题或信息类型调用不同的链。RunnableBranch允许你这样做。
对于这种类型实现的示例,让我们回到我们的汽车订阅公司:GreenRide。我们有一个需要处理的各种查询类型的想法,这些类型可以分为三类:维护、汽车信息和账户。然而,我们需要使用不同的链来回答这些问题。让我们看看这是如何实现的:
-
首先,我们从
langchain库导入必要的类,然后初始化我们的模型:from langchain.chat_models import ChatOpenAI... llm = ChatOpenAI(temperature=0, model="gpt-4-1106-preview") -
接下来,我们需要为每个部门创建提示。我们为不同类型的查询(维护、车辆信息和账户)创建模板。每个模板都旨在引导语言模型在特定上下文中回答:
maintenance_template = "You are an expert in car maintenance {input}" maintenance_prompt = PromptTemplate.from_template( maintenance_template) car_info_template = "You are knowledgeable about various car models {input}" car_info_prompt = PromptTemplate.from_template( car_info_template) accounts_template = "You are well-versed in account management {input}" accounts_prompt = PromptTemplate.from_template( accounts_template) -
我们还需要一个通用的模板:
general_prompt = PromptTemplate.from_template( "You are a helpful assistant. Answer the question... {input}" )这是一个适用于不符合特定部门查询的回退模板。
-
接下来,我们使用
RunnableBranch创建分支逻辑:prompt_branch = RunnableBranch( (lambda x: x["topic"] == "maintenance", maintenance_prompt), general_prompt, )这一部分定义了基于主题决定使用哪个模板的逻辑。它检查输入的主题并将其与相应的模板匹配。
-
然后,我们需要创建主题分类器和分类器链:
class TopicClassifier(BaseModel): topic: Literal["maintenance", "car_info", "accounts", "general"]TopicClassifier类定义了一个 Pydantic 数据模型,它表示主题分类过程的输出。它有一个字段,topic,它是一个枚举值,表示用户问题的分类主题。 -
接下来,我们使用
convert_pydantic_to_openai_function函数将TopicClassifierPydantic 模型转换为可以与ChatOpenAIAPI 一起使用的 OpenAI 函数:classifier_function = \ convert_pydantic_to_openai_function(TopicClassifier) parser = PydanticAttrOutputFunctionsParser( pydantic_schema=TopicClassifier, attr_name="topic" ) -
然后,我们使用
bind方法将转换后的TopicClassifier函数添加到ChatOpenAI对象中。这有效地使主题分类函数在ChatOpenAI上下文中作为一个可调用的函数可用。PydanticAttrOutputFunctionsParser类用于解析主题分类函数的输出,它是一个 JSON 对象。pydantic_schema参数指定用于解析 JSON 对象的 Pydantic 模型,在这种情况下是TopicClassifier模型。attr_name参数指定从 Pydantic 模型中提取分类主题的属性,即主题属性。
OpenAI 函数
我们在这里使用 OpenAI 函数调用以确保我们接收正确的 JSON 格式和模式。值得注意的是,使用 OpenAI 模型的最新版本(gpt-4-1106-preview 或 gpt-3.5-turbo-1106),可以将 response_format 设置为 { "type": "json_object" } 以启用 JSON 模式。当启用 JSON 模式时,模型将仅生成可以解析为有效 JSON 对象的字符串。然而,这并不保证正确的模式。
-
然后,我们将这些整合到我们的链中:
classifier_chain = llm | parser当使用用户问题调用
classifier_chain时,问题首先被传递到ChatOpenAI函数进行主题分类。然后,主题分类函数的输出被 Pydantic 属性输出函数解析器解析,并返回提取的分类主题,使我们能够定义要调用的模板。 -
最后,我们创建我们的主链管道,将所有这些整合在一起:
final_chain = ( RunnablePassthrough.assign(topic=itemgetter("input") | classifier_chain) | prompt_branch | ChatOpenAI() | StrOutputParser() )最终链首先对输入进行分类,然后选择适当的模板,使用语言模型处理输入,并解析输出。最后,调用我们的链变得很容易:
final_chain.invoke( {"input": "How do I update my payment method for my car subscription?"})
现在,你应该有一个可以工作的示例,它设置了一个能够智能地将客户支持查询路由到特定部门(如维护、车辆信息和账户)的聊天机器人。
目前,我们正在考虑不同的提示。我们可以扩展 RunnableBranch 以将输入路由到不同的提示,甚至完全不同的链。这允许根据输入的主题或其他标准进行更复杂和专业的处理。
假设除了处理维护、车辆信息和账户查询外,你还想将一些查询路由到不同的链进行特殊处理。例如,你可能有一个处理信用控制查询(如支付)的链,这需要访问支付服务和用户历史记录,因此链更加复杂。这只是创建链并在 RunnableBranch 配置中的分支逻辑中添加的一个简单案例:
credit_control_template = PromptTemplate.from_template(
"You are a credit control assistant. Provide immediate and useful credit control advice for GreenRide customers and allow them to pay their bills .\n\n{input}"
)
credit_control_chain = llm | access_stripe_details credit_control_template
prompt_branch = RunnableBranch(
(lambda x: x["topic"] == "credit_control", credit_control_chain),
general_prompt,
)
这是一个相当简单的链和理论示例,它使用文档加载组件来查找用户支付账户详情。这介绍了 LangChain 中可用的许多不同模块之一,我们将在下一章中探讨。
摘要
在本章中,我们首次了解了 LangChain,你应该对其是什么、解决的问题以及它在简化复杂 LLM 应用程序开发中的作用有良好的理解。
我们已经探讨了 LangChain 的核心组件,例如 LLM 模型、提示模板和输出解析器。你应该对 LCEL 有良好的理解,包括其关键特性和在 LangChain 框架中创建和执行链的作用。最后,本章还涵盖了 LangChain 链的多种示例,从基本到复杂,以展示所讨论概念的实际应用。
在本章中,我们只是对 Langchain 进行了初步探讨,但希望我们已经为你建立了一个坚实的基础,以便构建 LangChain 应用程序,并使你能够继续学习 LangChain 库的更复杂概念和应用。在下一章中,我们将探讨其他概念,如内存以及代理、模块和其他工具,特别是 LangSmith。
进一步阅读
以下链接是经过精选的资源列表,可以帮助你了解本章讨论的主题:
第六章:使用 LangChain 进行高级调试、监控和检索
在本章中,我们将探讨一些更高级的 LangChain 主题及其应用。你将了解一些重要过程,例如调试 LangChain 和使用新的 LangSmith 平台。你将了解代理和工具的力量,并了解它们如何被用来赋予你的代理超级能力。你将查看现成的工具,并为代理创建一个自定义工具。然后,你将了解在创建由大型语言模型(LLM)驱动的对话体验的背景下内存,并了解如何使用 LangChain 实现这一点。
本章旨在在前一章的基础上,通过探讨更高级的概念,使你能够创建更复杂的 LangChain 应用程序。
在本章中,我们将涵盖以下主题:
-
调试和监控 LangChain
-
利用 LangChain 代理
-
探索 LangChain 内存
技术要求
在本章中,我们将广泛使用 ChatGPT,因此你需要注册一个免费账户。如果你还没有创建账户,请访问openai.com/,点击页面右上角的开始使用,或访问chat.openai.com。
这些示例需要 Python 3.9 和 Jupyter Notebook,你都可以从jupyter.org/install下载。Jupyter Notebook 也包含在 Anaconda 中。你可以在这本书的 GitHub 仓库中找到本章的代码:github.com/PacktPublishing/ChatGPT-for-Conversational-AI-and-Chatbots/chapter6。
调试和监控 LangChain
到目前为止,你可能已经意识到,即使是在简单的链中,LangChain 内部仍然有很多事情在进行。通常,当你从不同的来源构建你的提示时,你需要查看你的语言模型的输入和输出,以便理解和迭代它们。
因此,了解你应用程序内部发生的事情非常重要,这样你才能构建、监控和调试你的应用程序。LangChain 提供了几种不同的方式来实现这一点。
让我们探索这些选项,以更清楚地了解它们如何增强你应用程序的功能。我们将从最简单的选项开始,逐步过渡到最全面的选项:LangSmith。
理解跟踪技术
LangChain 提供了一些简单的方法来输出链的不同步骤。
如果你正在使用 Jupyter Notebook 或简单地运行 Python 脚本来使用本书中提供的示例,你有几种方法可以提供跟踪输出:
-
将
verbose设置为True创建一个全局设置,并将以最高级别输出链的步骤,这样我们就可以看到正在发生的不同 LLM 调用。你可以这样设置:from langchain.globals import set_verbose set_verbose(True) -
将
debug设置为True创建一个全局设置,输出所有具有回调支持的组件(链、代理、模型、工具和检索器)生成的输入和输出,并给出最全面的信息:from langchain.globals import set_debug set_debug() -
详细日志:您可能还希望在特定链上激活详细日志,因为如果您正在处理多个链,全局输出可能会太多。如果您使用链对象,则可以按以下方式实现:
conversation_with_summary = ConversationChain( llm=llm, verbose=True, ) -
将
verbose设置为True后,您需要使用回调。在以下代码示例中,我们在调用chain上的invoke时传递了包含ConsoleCallbackHandler的配置:from langchain.callbacks.tracers import ConsoleCallbackHandler from langchain.schema.runnable import RunnableLambda def fun_1(x: int) -> int: return x + 1 def fun_2(x: int) -> int: return x * 2 runnable = RunnableLambda(fun_1) | RunnableLambda(fun_2) runnable.invoke(1, config={'callbacks': [ConsoleCallbackHandler()]})上述代码创建了一个可运行对象的链,然后调用它。我们使用
|运算符来连接两个可运行对象。这意味着fun_1的输出将被作为fun_2的输入。在这里,runnable.invoke(1, config={'callbacks': [ConsoleCallbackHandler()]})从输入 1 开始调用链。配置指定使用ConsoleCallbackHandler。输出将显示链运行过程中的每个步骤。部分输出如下所示:
[chain/start] [1:chain:RunnableSequence] Entering Chain run with input: { "input": 1 } [chain/start] [1:chain:RunnableSequence > 2:chain:fun_1] Entering Chain run with input: { "input": 1 }
如果您仍在使用笔记本或 Python 脚本进行开发,这些技术是很好的。然而,如果您想持久化日志,则需要更细粒度的信息和直观的界面,或者您想将应用程序投入生产,那么可能是时候考虑使用 LangSmith 了。我们将在下一节中介绍这一点。
介绍 LangSmith
LangSmith 目前是一个处于测试阶段的早期产品。除了是早期发布之外,它还是处理 LangChain 的新工具,您可能会经常使用它。它简化了调试、测试、监控和评估您的 LangChain 项目。本节将简要介绍 LangSmith,因此鼓励您查看文档,因为它正在不断更新。
设置 LangSmith
开始使用 LangSmith 涉及几个简单的步骤:
-
首先,您需要创建一个 LangSmith 账户并生成一个 API 密钥。
-
访问 LangChain 网站smith.langchain.com。按照网站上的说明注册并创建一个新账户。
-
账户创建后,使用新凭据登录 LangSmith 控制台。
-
登录后,导航到 LangSmith 控制台中的设置页面。在这里,找到创建 API 密钥并生成一个的选项。
-
-
接下来,您需要配置您的开发环境,以便它们可以与 LangSmith 集成。这只是一个设置以下变量的简单问题:
os.environ['LANGCHAIN_TRACING_V2'] = "true" os.environ['LANGCHAIN_ENDPOINT'] = "https://api.smith.langchain.com" os.environ['LANGCHAIN_API_KEY'] = "Your Langchain API key"
一旦您设置了这些,每次运行都意味着相应的跟踪将被记录到您的默认项目中。运行代表应用程序中的单个工作单元。
通过设置以下命令可以轻松地针对特定项目:
os.environ[' LANGCHAIN_PROJECT'] = "Your project name"
然后,您可以查看每个运行情况,并深入了解每个步骤的具体情况,以确切了解每个步骤中发生了什么。
利用 LangChain 代理
LLM 非常强大,但它们也有一些基本缺陷。我们已经广泛讨论了它们的局限性;记住,它们的知识只到 2021 年底 ChatGPT 训练数据截止时为止。令人惊讶的是,这种先进的技术在其他计算任务上也不太擅长,例如基本的数学、逻辑,甚至查找它们不知道的其他信息的能力。
为了弥补这些缺点,我们需要另一种技术或方法来帮助我们的 LLM 在需要帮助的地方。这些解决方案被称为 代理,在本节中,我们将探讨它们是什么,如何工作,以及如何使用 LangChain 来使用它们。
什么是代理?
代理为 LLM 提供工具,以便它们能够执行自己无法有效执行的任务。有几种不同类型的代理,旨在与不同的模型(如 OpenAI LLM)一起工作,并提供对不同的任务和用例的支持,例如 XML 或 JSON 处理。
每种类型都有特定的用例,因此查看每个代理的 LangChain 信息是值得的,这样你可以决定哪个最适合你的用例。
要创建一个代理,我们需要考虑三个不同的组件:
-
LLM
-
执行任务的工具
-
控制任务的代理
LLM 将处理理解和生成响应,专用工具将执行特定任务,而代理将协调这些任务。
什么是 LangChain 工具?
LangChain 工具允许代理通过与其他系统交互来执行其定义的任务。一个工具由一个工具模式组成,其中包含有关工具期望的输入信息,以及一个用于执行任务的函数。LangChain 提供了许多内置工具,并允许你创建自定义工具,你可能会在某个时候想要这样做。除了单个工具之外,LangChain 还提供了工具包的概念,你可以使用这些工具包来执行特定任务。
让我们看看构成工具的要素:
-
一个名称和描述来记录其预期用途
-
一个 JSON 模式来定义输入参数
-
一个运行函数,它将带有输入被调用
-
一个
return_direct标志,指示输出是否应发送给用户
重要的是尽可能包含这些信息,并保持工具简单,以便 LLM 能够轻松使用。名称、描述和模式都将用于向 LLM 的提示中,以便它知道要采取什么行动。这些需要清晰简洁。
OpenAI 工具调用的介绍
在我们深入研究下一个示例之前,了解 OpenAI 函数/工具非常重要,这样我们才能理解它们为什么存在以及如何使用它们。只是为了混淆,这些曾经被称为 函数,但现在它们被称为 工具,这更有意义。
在函数调用发布之前,你会向 ChatGPT 提出一个像“伦敦的最新新闻是什么?”这样的问题,而且你不会得到一个有用的回答。正如我们所知,它不擅长返回最新信息,因为它没有连接到互联网,无法拉取或抓取数据。
我们可以编写一些代码去调用新闻服务,但我们需要传递位置和其他任何参数,然后回到我们的对话中。这并不容易做到,尤其是如果我们想使用对话中的参数来调用我们的服务。
函数调用是由 ChatGPT Turbo 和 GPT4 模型创建并支持的,以克服这些问题,并通过轻松调用外部 API 和提取结构化数据来提供轻松回答问题的简单方法。这些模型被训练来查看函数,并智能地决定何时调用它们。实现函数的基本过程如下:
-
使用用户查询和预定义的函数来触发模型。模型可能会调用函数,生成一个包含可能假设参数的 JSON 对象。
-
在你的代码中解码 JSON 并使用任何给定的参数执行函数。
-
将函数的响应输入回模型,以便它可以对用户进行总结。
让我们看看一个简单的例子。
查看一个简单的 OpenAI 工具示例
我们通过聊天完成调用中的 tools 参数将我们的函数定义传递给聊天完成,该参数接受一个表示为标准 JSON 格式的工具数组。以下是一个定义,ChatGPT 希望考虑并调用以获取特定主题的最新新闻文章:
tools = [{
"type": "function",
"function": {
"name": "get_news_articles",
"description": "Retrieve news articles based on a specific topic and date range",
"parameters": {
"type": "object",
"properties": {
"topic": {
"type": "string",
"description": "The topic or subject of interest for the news articles"
},
"required": ["topic"]
}
}
}
]
我们提供工具的名称,这将强制模型调用我们的函数,并尽可能提供详细的描述。记住,这个描述将在提示的上下文中使用,所以越准确、越详细越好。当涉及到工具时,尽量描述你的函数将要做什么,因为这是模型被训练的方式。然后,我们添加将要发送给函数的参数描述。在我们的例子中,我们传递一个 topic 字符串。
现在,当我们尝试通过询问我们的 ChatGPT 模型关于伦敦的最新新闻来进行聊天完成时,模型将知道使用我们在工具定义中定义的特定参数来调用我们的函数。如果我们定义了更多的参数在我们的工具中,ChatGPT 会询问澄清问题,直到它获得所需的所有信息。
工具如下传递到我们的完成调用中:
response = client.chat.completions.create(
model="gpt-3.5-turbo-0125",
messages=messages,
tools=tools,
tool_choice="auto",
)
注意,我们已经将 tool_choice 设置为 auto,这告诉 ChatGPT 决定是否使用工具。
这应该输出类似以下内容,显示没有指定内容的 ChatCompletionMessage。然而,在我们的工具调用中应该有 ChatCompletionMessageToolCall,用于我们的函数。我们还有 topic 参数和我们的函数名称:
ChatCompletionMessage(content=None, role='assistant',
function_call=None,
tool_calls=[
ChatCompletionMessageToolCall(
id='call_ewHp8R8GUAHY6Dy4UXdEej3B',
function=Function(
arguments='{"topic":"London"}',
name='get_news_articles'),
type='function')])
在这里,我们可以看到 ChatGPT 决定调用我们的函数;如果它决定不这样做,我们可以进行一些测试。如果我们把问题改为“解释量子物理”,那么我们应该得到包含回答问题的内容的 ChatCompletionMessage:
ChatCompletionMessage(content="Chess is a classic strategy board game played ....
如我们所见,ChatGPT 决定使用哪些工具来满足这个问题,并将这些工具列在我们的 tool_calls 列表中。如果我们循环遍历这个列表,并且 ChatGPT 从我们的问题中提取了这些参数,我们可以调用每个函数。之后,我们可以将结果添加到我们的消息列表中,并让 ChatGPT 为用户总结结果。
不要忘记,你还可以在我们的聊天完成调用中设置 tool_choice={"type": "function", "function": {"name": " another_response_function"}},以强制 ChatGPT 使用特定的函数,而不是让它自己决定。
函数/工具的另一个强大应用是让 ChatGPT 创建确定性、完美形成的数据变得容易。在第二章中,我们是在提示用户话语或数据集为 JSON。现在,我们可以通过创建一个函数定义来为我们完成这项工作,从而使用工具来创建完美的输出。我建议你查看第二章中的一些训练数据创建任务,并创建一个工具来实现相同的结果。
OpenAI 函数目前正在进行许多工作,但这至少应该能让你对使用它们的益处和涉及步骤有足够的了解。现在,让我们来看看 LangChain 工具,看看 LangChain 如何简化 OpenAI 函数的使用。
插件式 LangChain 工具,立即集成
LangChain 提供了许多现成的工具,这使得为你的代理提供工具变得容易。你可以在文档中找到这些工具的列表,网址为 python.langchain.com/docs/integrations/tools/,这些工具由供应商和社区成员创建和维护。它们涵盖了从搜索引擎到与文件系统交互以及与像 Google Drive 这样的大型云服务供应商交互的广泛功能。
一个现成的工具示例
让我们来看看我最喜欢的工具之一:Tavily 搜索 API。Tavily 搜索是一个针对 LLM 优化的搜索引擎,以提供最佳搜索结果。因此,它是一个很好的 LLM 工具示例,你可能会用到。在查看如何创建这个工具的同时,了解其细节也很有用,这样我们就可以了解构成有效工具的组件。首先,我们需要安装所需的库:
pip install -U langchain-community tavily-python
接下来,导入库并创建我们需要的 API 密钥:
os.environ['OPENAI_API_KEY'] = OPENAI_KEY
os.environ["LANGCHAIN_API_KEY"] = "TAVILY_API_KEY "
现在,我们可以通过创建 TavilySearchAPIWrapper 类的实例来创建工具,该类作为 Tavily 搜索 API 的包装器。我们可以将此实例传递给我们的 TavilySearchResults 类:
tavily_search = TavilySearchAPIWrapper()
tavily_tool = TavilySearchResults(api_wrapper=tavily_search)
你可以通过 print(tavily_tool.name), print(tavily_tool.description), print(tavily_tool.args) 打印出工具的不同属性,最重要的是通过调用 invoke() 来执行搜索:
tavily_tool.invoke({"query": "how many named storms have there been this year in the UK"})
当你运行这个程序时,你应该得到一个包含搜索最新信息的响应。你应该看到以下类似的输出:

图 6.1 – Tavily 搜索输出
在下一节中,我们将探讨如何使用代理和工具。
使用代理和我们的工具
到目前为止,我们已经创建了一个工具,但还没有使用它。为了做到这一点,我们需要创建一个代理。在我们的示例中,我们使用的是 OpenAI Functions 代理。我们在上一节中介绍了 OpenAI 函数;在本节中,我们将看到使用 LangChain 实现这一点是多么简单。代理可以通过 create_openai_functions_agent() 函数创建,该函数接受三个参数:
-
llm:支持 OpenAI 函数调用 API 的语言模型 -
tools:代理可以使用的工具列表 -
prompt:代理将使用的提示
我们传递这三个参数来创建我们的代理:
open_ai_agent = create_openai_functions_agent(llm, tools,prompt)
现在我们有了这个代理,我们需要创建一个 AgentExecuter 类来运行它:
open_ai_agent_executor = AgentExecutor(agent=agent, tools=tools)
然后,我们应该能够调用 invoke() 函数并返回包含最新信息的一些结果:
result = open_ai_agent_executor.invoke({"input": "how many named storms have there been in 2024 in the UK"})
如果你打印出结果,你应该得到一个包含最新信息的答案,显示我们的代理和工具正在正确工作。请记住查看 Langsmith 中的日志,以便你可以了解那里发生了什么。
你可以通过使用 LangChain 生态系统提供的工具包来进一步使用 LangChain 的即插即用工具。这些工具包提供了专为特定任务设计的工具集合。
现在我们已经查看了一个预构建的工具箱并介绍了代理,你可以看到 LangChain 代理是多么强大。我们鼓励你查看 python.langchain.com/docs/integrations/tools/ 上的其他工具和代理类型。
你可能需要一种不同类型的工具来满足特定的需求。好消息是创建自定义工具也很容易。让我们深入探讨一个具体的例子,以便你了解涉及的步骤。
创建自定义天气工具
对于我们的示例,我们将创建一个自定义工具,使用 Open-Meteo(免费天气 API Meto)获取位置的当前天气。
我们的工具将接受两个参数,latitude 和 longitude,这样我们就可以查找特定位置的天气。这两个参数都是必需的。
首先要考虑的是,我们需要一个支持多个输入的代理类型。所以,我们选择 StructuredChatAgent。让我们直接进入代码:
-
首先,导入必要的模块。该脚本导入了各种 Python 模块,包括用于制作 HTTP 请求、处理数据和特定 LangChain 组件(用于工具和代理创建)的模块:
import os from langchain.tools import BaseTool from typing import Union from langchain.agents import (AgentExecutor, create_structured_chat_agent) from langchain import hub from langchain_openai import ChatOpenAI -
设置 OpenAI 和 LangChain API 所需的环境变量,你的 LangSmith 密钥用于日志记录,以及其他配置细节。
-
LangChain 工具只是我们从代理中调用的函数。要创建一个工具,我们必须遵循相同的基本模式。这涉及到从
BaseTool继承,实现run()方法,并在创建代理时传递我们工具的实例。自定义工具类GetWeatherByLocationTool扩展了BaseTool类,为其提供了基于纬度和经度获取天气信息的具体功能。我们还必须提供一个名称和描述,以便我们的 LLM 了解如何以及何时使用该工具:class GetWeatherByLocationTool(BaseTool): name = "Weather service" description = " A weather tool optimized for comprehensive up to date weather information. Useful for when you need to answer questions about the weather. Use this tool to answer questions about the weather for a specific location. To use the tool, you must provide at the following parameters" "['latitude', 'longitude']. " def _run(self, latitude: Union[int, float], longitude: Union[int, float]) -> str: ... return result_string else: return "Failed to retrieve weather data."这个工具的
_run()方法执行实际的逻辑,使用 Open-Meteo API 获取天气信息,并将结果作为字符串返回。 -
现在我们已经创建了我们的工具,我们可以初始化语言模型和自定义工具,然后使用
create_structured_chat_agent()函数创建代理,该函数将语言模型与工具结合起来以处理特定查询:llm = ChatOpenAI(model="gpt-3.5-turbo-1106") tools = [GetWeatherByLocationTool()] prompt = hub.pull("hwchase17/structured-chat-agent") agent = create_structured_chat_agent(llm, tools, prompt) -
创建一个
AgentExecutor类,它负责使用提供的工具执行代理。然后,使用特定的查询调用代理,如下所示:executor = AgentExecutor(agent=agent, tools=tools,,handle_parsing_errors=True) output = executor.invoke({"input": "What's the weather like in waddesdon"}) print(output)希望当你运行这个程序时,你会得到以下类似的结果:
{'input': 'whats the weather like in waddesdon', 'output': 'The current weather in Waddesdon is 5.6°C with no rain.'}
好玩的是,我们传递了一个位置,LLM 知道该位置使用的纬度和经度坐标,并在调用自定义工具时使用这些坐标。
通过这个例子,你看到了 LangChain 代理在创建自定义工具以及依赖一些强大的内置工具时的强大之处。可能性是无限的!
在下一节中,我们将探讨为你的 ChatGPT 驱动的代理提供更高级要求,即为其提供内存。我们将学习如何使用 LangChain 实现这一点。
探索 LangChain 内存
随着我们与 LLM 一起工作,一个关键挑战出现了,因为它们无法天生地回忆起过去的交互。因此,本质上,它们是无状态的。无状态的操作不会将信息从一次请求持久化到下一次请求,如果你想要创建一个聊天机器人,这就会成为一个问题。解决这个问题的方法是将整个对话添加到上下文中。ChatGPT 客户端本身会在对话进行过程中将整个对话传递到每个提示中。
我们希望我们的 ChatGPT 应用能够提供有状态的交互,其中信息在请求和会话之间被记住。为了实现这一点,我们需要使用记忆机制。然后,不同的记忆表示将包含在 LLM 提示中。本节致力于探讨 LLM 上下文中的记忆概念。我们将深入研究不同类型的记忆以及在使用 LLM 时面临的挑战,然后再深入探讨如何使用 LangChain 为 ChatGPT 驱动的应用提供记忆功能。
小贴士
ChatGPT UI 在底层使用记忆,通过在每次提供提示时传递消息历史来引入状态。这也允许你选择并重新启动之前的对话。
探索不同类型的记忆应用
如果你考虑进行一次对话——无论是只是就某个主题聊天,还是更私人的对话,或者是为了实现交易结果而进行的对话——很快就会变得明显,可能会有不同类型的记忆在发挥作用。对记忆的明显需求是存储在活跃对话中说过的内容。然而,可能还需要其他类型的记忆,比如历史对话的记忆、与特定用户相关的特定信息的记忆,或者与用户或应用相关的特定主题知识的记忆。让我们在有效对话的背景下看看不同的记忆类型。
活跃对话中的记忆
在活跃对话中,以下形式的记忆会发挥作用:
-
对话缓冲记忆:这种记忆类型存档了正在进行中的对话的整个文本,包括所有输入和响应。它保留了对话的全部上下文,以便可以将每个提示传递给 LLM。
-
对话缓冲窗口记忆:这是缓冲记忆的更复杂版本,它仅维护最近指定数量的交互,丢弃较旧的交互或将它们作为摘要合并。它作为短期记忆,随着对话在多个回合中进展,优化标记的使用。
历史记忆
历史记忆可以分为两种类型:
-
过去对话:这包括长期记忆,可能是之前与特定用户的对话和会话。这个用户可能会通过身份验证被你的代理所知。历史对话可能只是之前交互的列表,或者可能是更复杂的实现,其中在使用之前会查询交互。
-
过去对话摘要:这种方法基于历史记忆,并压缩之前的交互,在将其整合到模型的历史中之前。它旨在减少标记的使用并简化内存管理,同时保留对话的精华元素。
个性化记忆
个性化记忆可能包括更广泛的信息,例如用户偏好和历史数据,这些数据可以是结构化格式(如知识图谱)或非结构化格式(如文档集合)。这种类型的记忆还可能提供记忆库机制,以微调记忆,为 LLM 提供最佳支持。
理解记忆挑战
对于所有这些不同类型的记忆,我们必须考虑的关键资源是我们使用的 LLM 的上下文窗口大小。这将决定工作对话的大小,包括提示和结果,因此您选择的每种类型的记忆都需要在上下文窗口的整体大小中进行考虑。作为 ChatGPT 开发者,您需要将这个上下文窗口大小视为有限资源,因此决定哪些信息应该包含在这个窗口内可能成为创建复杂 LLM 应用的一个挑战性方面。
对于您 ChatGPT 应用的发展来说,好消息是 OpenAI 已经为他们的模型发布了越来越大的上下文窗口。例如,最新的 GPT-4 模型支持超过 32k 个标记,这大约是 24k 个单词。
坏消息是,拥有更大、越来越大的上下文并不能保证性能的改善。以下是一些可能影响响应准确性或产生其他影响的其他因素:
-
位置:信息的相对位置可能会影响结果,因此将最重要的信息有策略地放置在上下文窗口的开始或结束处可能会提高模型的输出。
-
清晰度:更大的上下文可能意味着准确性下降。明智的做法不是认为上下文越大,您就能添加的内容就越多。尽可能多地加载信息可能会导致响应不够准确或不相关。
-
知识优先级:许多 LLM 实现将涉及特定领域的知识。作为 LLM 开发者,您可能需要决定当上下文记忆资源有限时,这种知识是否应该优先于对话记忆。
-
成本:尽管 OpenAI 试图通过每次发布的 GPT 模型来降低成本,但这些更大的上下文使您能够使用更多的标记,如果不小心,成本可能会飙升。
提示
在使用记忆时,不仅要考虑选择适当的信息,还要以增强模型性能的方式对信息进行结构化。
介绍记忆使用技术
您可以使用几种不同复杂度和实施难度的记忆管理技术,其中一些旨在简化活跃对话记忆,而另一些则有助于历史和知识。让我们看看我们可以使用的不同记忆使用技术:
- 滚动活跃对话记忆:滚动窗口技术维护一个动态窗口,包含最近的交互或消息,确保模型始终关注最新的上下文。以下图展示了这种类型记忆实现的流程:

图 6.2 – 滚动对话记忆过程
当新消息到达时,旧数据将从窗口中移除,从而有效地限制模型对过去消息的暴露。这种方法既简单又高效。然而,这是一个基本的方法,它存在丢弃有价值消息历史记录的风险,而在这种情况下,我们无法知道刚刚移除了什么,以及这将对对话产生怎样的影响。
- 活跃对话记忆的增量摘要:这种方法将对话的关键要点作为摘要提取出来,并将其与最新的消息一起输入上下文,而不是整个对话。这种方法降低了数据丢失的风险,并允许进行简洁的摘要,同时仍然保持对话的主题。以下图展示了增量记忆实现的过程:

图 6.3 – 增量摘要技术
然而,如果你在多个对话调用中总结内容,这可能会导致对话细微差别的持续稀释。此外,创建这些摘要还需要进一步的 LLM 调用,从而增加计算成本。
- 使用记忆库增强上下文:有一种新兴的技术称为记忆库,这是一种为 LLM 量身定制的记忆机制。这种类型的实现将回忆多轮对话、个人信息和总结事件,从其记忆存储机制中。以下图概述了使用记忆库所涉及的过程:

图 6.4 – 记忆库技术
应用程序将通过使用受 Ebbinghaus 遗忘曲线理论启发的记忆更新器来管理存储和遗忘的内容,同时使用其 LLM 调用决定当前对话中要使用的内容,从而不断进化其上下文。将这些内容整合在一起,希望可以提供更加个性化的体验。实现一个具有记忆库的应用程序将是一项复杂的任务。
在“理解记忆挑战”部分,我们概述了可能存在一些与较大上下文相关的问题。可能的情况是,具有 4k 令牌限制的模型根本不足以支持所有需要放入上下文的内容,因此查看具有更大上下文的 GPT 模型可能是一个好主意。
克服记忆约束的最简单方法之一是将更复杂的任务分解成更小的提示。这种技术有助于简化复杂的提示,并且通常能获得更好的结果。
希望你现在能够从创建对话体验的角度理解记忆,了解一些可用的技术,并能够欣赏到添加记忆所面临的挑战和复杂性。在下一节中,我们将看到 LangChain 如何被用来向 LLM 应用添加记忆功能。
理解在 LangChain 中使用记忆的示例
在其最简单的形式中,一个对话系统必须能够直接访问一系列过去的交互,以便它们可以在聊天界面中显示对话历史,或者在我们的情况下传递给 LLM。在这个示例中,我们将探讨使用 LangChain 记忆来为现场音乐助手创建一个简单的对话界面。主要目的是展示我们如何在简单的对话应用中使用记忆。
LangChain 提供了多种不同的集成方式来支持记忆功能,从内存到持久数据库。在下面的示例中,我们将使用ConversationBufferMemory类,这是 langChain 中最基本的记忆形式。
基本上,我们的记忆系统应该促进两个主要功能:读取和写入记忆。
在接收用户初始输入并在启动其核心逻辑之前,链从其记忆系统中读取,以便以前交互可以用于提示。
在核心逻辑执行完毕但在发送响应之前,链将输出和输入写入记忆。这一动作确保了这些信息可以在未来的交互中供参考。本质上,这与传统对话人工智能平台管理对话的方式相似。
这些过程在以下示例中得到了说明:
-
首先,我们必须从
langchain库中导入必要的类,然后初始化我们的模型:llm = ChatOpenAI(temperature=0.0, openai_api_key=os.getenv("OPENAI_API_KEY"), model="gpt-4-1106-preview") -
接下来,必须初始化一个
ConversationBufferMemory对象来管理对话历史。return_messages=True参数确保在查询时记忆返回一个消息列表。默认情况下,这些是单个字符串:memory = ConversationBufferMemory(return_messages=True) -
现在,我们必须设置一个
ChatPromptTemplate模板来结构化对话。它包括一个系统消息,定义了机器人的角色(一个音乐粉丝活动聊天机器人),一个用于历史消息的占位符,以及接收人类输入的结构。prompt = ChatPromptTemplate.from_messages([...]) -
到目前为止,我们可以使用 LCEL 创建链。链由一系列操作组成。链结合了记忆加载、提示处理和语言模型响应生成:
chain_with_memory = ( RunnablePassthrough.assign( conversation_history=RunnableLambda( memory.load_memory_variables) | itemgetter("conversation_history") ) | prompt | llm )
小贴士
使用RunnablePassthrough允许你在链的步骤中按顺序继续添加数据字典。在这个示例中,我们将其加载到历史键中,用于提示。
在这里,使用RunnablePassthrough.assign(...)创建了一个额外的键,之后将对话历史分配给这个键。然后,RunnableLambda(memory.load_memory_variables) | itemgetter("history")检索对话历史。
链接随后应用提示模板,并将处理后的输入发送到 LLM 以生成响应。
我们可以通过输入hi并等待响应来启动第一次交互。然后我们可以将输入和输出保存在内存中,以便在未来的交互中提供上下文:
inputs = {"input": "hi"}
response = chain_with_memory.invoke(inputs)
memory.save_context(inputs, {"output": response.content})
后续交互继续。对于每个新的用户输入都会重复这个过程,从而保持对话的上下文:
inputs = {"input": "My name is Adrian and I like the high flying birds"}
response = chain_with_memory.invoke(inputs)
memory.save_context(inputs, {"output": response.content})
inputs = {"input": "I'm looking for gigs in London this summer"}
response = chain_with_memory.invoke(inputs)
memory.save_context(inputs, {"output": response.content})
记得检索对话历史,以便我们可以加载存储的对话变量以供审查或进一步处理:
memory.load_memory_variables({})
这个例子很简单,因为ConversationBufferMemory是一个内存存储,它存储了所有的交互。LangChain 提供了几种不同的记忆集成。在下一节中,我们将探讨这些集成如何提供更好的记忆支持。
探索更多高级的记忆类型
让我们看看 LangChain 中可用的更多高级记忆类型。
内存存储
由于我们正在学习使用 ChatGPT 创建对话体验以支持更多复杂性,我们可能需要支持多轮对话。随着对话的延长,你可以想象缓冲区大小可能会成为一个问题。考虑使用ConversationBufferWindowMemory可能是个明智的选择,它允许你通过在创建时传递k值来存储特定数量的交互:
memory_with_5_interactions = ConversationBufferWindowMemory( k=5)
这样,你将保持一个包含5个最新交互的滑动窗口,以防止缓冲区过大。
将你的对话交互固定在记忆中的特定数量可能会限制你的能力,因此你可以考虑使用ConversationSummaryMemory来帮助总结对话。这种类型的记忆可以按照以下方式实例化:
memory = ConversationSummaryMemory(llm=llm, return_messages=True)
memory.save_context({"input": "hi I'm adrian"},
{"output": "whats up"})
memory.load_memory_variables({})
在这里,ConversationSummaryMemory收集和更新正在进行的对话的概述。这个存储在内存中的摘要可以随后在提示或链中使用,以提供对话到目前为止的快速回顾。
你可以通过结合对话缓冲区和对话摘要的两种概念,使用ConversationSummaryBufferMemory来进一步扩展这一功能。
这种类型的记忆根据你在实例化记忆时设置的标记长度存储最新的交互。而不是仅仅在交互超出标记限制时删除它们,记忆将它们存储为摘要,并在后续交互中使用它们。这种记忆可以在ConversationChain中如下使用:
conversation_with_summary = ConversationChain(
llm=llm,
# Notice the max_token_limit is very low so you can see the output of the summary
memory=ConversationSummaryBufferMemory(
llm=llm, max_token_limit=150),
verbose=True,
)
response = conversation_with_summary.predict(input = "My name is Adrian and I like 1990s music, can you remember my 3 favourite bands, Nirvana, Offspring and Underworld")
response = conversation_with_summary.predict(input = "What's my second favourite band")
注意,我们设置了verbose=True和max_token_limit=150,这样我们可以在内存中看到摘要和消息历史。如果我们输出内存,
memory.load_memory_variables({}),我们应该得到以下类似的结果:
{'history': [SystemMessage(content='Adrian, who likes 1990s ...'),
HumanMessage(content="What's my second favourite band"),
AIMessage(content="Your second favorite band is Offspring, Adrian...")]}
注意,摘要被加载到系统内存中,并且有一个包含HumanMessage和AIMessage对象交互的列表存储在内存中。
使用持久化记忆
我们之前查看的 LangChain 内存实现类型非常适合处理实时对话。然而,这种内存不会在会话之间持久化。我们在“介绍内存使用技术”部分提到了这种类型的方法,即你可以将历史对话作为你上下文的一部分使用。那么,让我们看看如何使用 LangChain 来实现这一点。
在这个例子中,我们将使用向量存储和嵌入。现在不必担心这些概念的具体细节——我们将在下一章中深入探讨,当我们探索检索增强生成(RAG)时。在这里,我们使用嵌入和向量存储来跟踪过去的对话轮次,以便我们可以搜索它们。
当向 LLM 发送提示以提供对话历史作为上下文时,我们可以引用早期交互中的相关信息。让我们开始吧:
-
首先,我们必须安装所需的包,最值得注意的是 ChromaDB,这是我们用于存储嵌入的数据库:
pip install -U chromadb langchain-openai tiktoken我们还必须添加我们的导入,并创建我们的环境变量以存储 API 密钥和 LangChain 配置:
from langchain_openai import OpenAI, (ChatOpenAI, OpenAIEmbeddings) ... # Environment variables for API keys and LangChain configurations os.environ['OPENAI_API_KEY'] = 'your-openai-api-key' ... os.environ['LANGCHAIN_API_KEY'] = 'your-langchain-api-key' -
接下来,我们必须初始化
ChatOpenAI和OpenAIEmbeddings,这样我们就可以生成响应和嵌入:llm = ChatOpenAI(temperature=0.0, model="gpt-4-1106-preview") embeddings = OpenAIEmbeddings() -
现在,我们可以设置 ChromaDB 和我们的向量存储。ChromaDB 是一个用于管理嵌入的开源数据库,允许我们存储和搜索我们的嵌入。向量存储使得基于这些嵌入高效检索过去的对话轮次成为可能。注意,我们已经创建了
PersistentClient,Chroma 数据库已经被存储在当前 Jupyter Notebook 文件夹下的embeddings文件夹中:chroma_client = chromadb.PersistentClient(path="./embeddings") history_vectorstore = Chroma( persist_directory="embeddings/", collection_name="conversation_history", client=chroma_client, embedding_function=embeddings) -
现在,我们必须创建内存和检索对象。内存对象存储对话轮次,检索器通过向量存储的默认相似度搜索帮助我们获取相关的过去轮次:
retriever = history_vectorstore.as_retriever( search_kwargs=dict(k=2)) memory = VectorStoreRetrieverMemory( retriever=retriever, memory_key="conversation_history", input_key="input") -
接下来,我们必须将一些示例对话保存到内存中,这样我们就可以检查它们是否包含在对话的上下文中:
memory.save_context({"input": "Hi, my name is Adrian, how are you?"}, {"output": "nice to meet you Adrian"}) memory.save_context({"input": "My favourite sport is running"}, {"output": "that's a good thing to be doing"}) -
现在,我们必须定义我们的对话模板,其中包括过去的对话作为上下文和当前输入:
_DEFAULT_TEMPLATE = """下面是一个人类和 AI 体育助手之间的友好对话。AI 很有帮助,并从其上下文中提供具体细节以支持聊天。如果 AI 不知道问题的答案,它会诚实地表示不知道:
Relevant pieces of previous conversation: {conversation_history} (Don't use these pieces of information if not relevant) Current conversation: Human: {input} AI:""" PROMPT = PromptTemplate( input_variables=["conversation_history", "input"], template=_DEFAULT_TEMPLATE ) -
最后,我们必须创建
ConversationChain,它结合了所有这些组件并发送聊天输入:conversation_with_history = ConversationChain( llm=llm, prompt=PROMPT, memory=memory, verbose=True) response = conversation_with_history.invoke({ "input":"what gear do i need to buy to get started in my sport"}) print(response)在这里,
verbose被设置为True,这样我们就可以看到 LLM 的输出。我们会看到对话历史被包含在提示中。如果我们重新启动我们的 Jupyter Notebook 内核并再次运行代码,对话应该会被持久化。
小贴士
如果你想要查看存储在你的 Chroma 向量存储中的文档及其嵌入,你可以通过运行 print(vector_store._collection.get(include=['embeddings'])) 来输出整个集合。
你也可以通过运行 similar_documents = vector_store.similarity_search(query="your question", k=1) 来尝试你自己的相似度搜索。
摘要
在本章中,我们深入探讨了 LangChain,研究了一些更高级的主题。我们首先探讨了调试技术,并介绍了 LangSmith,这是 LangChain 应用高级日志记录和监控的必备工具。我们还研究了 LangChain 代理,了解了如何使用它们为我们的大型语言模型项目提供不同的功能,以及它们如何与 OpenAI 函数调用相结合。我们专注于 LangChain 提供的现成工具,并通过查看实际示例来创建自定义工具,帮助我们的 ChatGPT 应用回答有关实时新闻和天气的问题。最后,我们讨论了为我们的代理提供内存的概念,同时探讨了不同类型的内存、挑战以及 LangChain 中提供内存的技术。
在下一章中,我们将探讨 RAG。你将了解它是什么,涉及的概念和过程,以及如何在 LangChain 中实现检索。
进一步阅读
以下链接是一份精心挑选的资源列表,可以帮助你理解本章内容:
-
LangChain:
www.langchain.comLangSmith:
smith.langchain.comChromaDB:
docs.trychroma.com -
迷失在中间:语言模型如何使用长上下文,作者 F. Liu:
arxiv.org/abs/2307.03172 -
MemoryBank: 通过长期 内存 增强大型语言模型:
ar5iv.labs.arxiv.org/html/2305.10250 -
艾宾浩斯遗忘 曲线:
www.mindtools.com/a9wjrjw/ebbinghauss-forgetting-curve虚拟上下文管理 实现:
memgpt.ai/ -
LangChain 代理:
python.langchain.com/docs/modules/agents/LangChain 工具:
python.langchain.com/docs/integrations/tools/
第三部分:构建和增强 ChatGPT 应用
在本部分,我们将探索检索增强生成(RAG)系统,展示如何使用向量存储作为知识库。然后,我们将结合到目前为止所涵盖的所有概念,构建和增强 ChatGPT 应用。你将进行自己的实际项目,创建一个能够处理复杂任务并提供个性化交互的聊天机器人。最后,我们将探讨对话式 AI 和大型语言模型(LLMs)的未来,讨论将 ChatGPT 应用推向生产的挑战,并考察该领域的替代技术和新兴趋势。
本部分包含以下章节:
-
第七章, 向量存储作为检索增强生成的知识库
-
第八章, 创建您自己的 LangChain 聊天机器人示例
-
第九章, 使用大型语言模型(LLMs)的对话式 AI 的未来
第七章:向量存储作为检索增强生成的知识库
检索增强生成(RAG)无疑是自 ChatGPT 爆发以来最常见的一种 LLM 应用场景。在本章中,我们将探讨创建 RAG 系统所涉及的关键步骤和概念。一旦您理解了每个步骤所涉及的内容,我们将探讨如何使用 LangChain 来执行这些过程和技术。进一步来说,我们将通过一个真实世界的例子来构建我们自己的 RAG 系统。
本章旨在介绍 RAG 的核心概念,以便您有一个坚实的基础来掌握它。
在本章中,我们将涵盖以下主题:
-
我们为什么需要 RAG?
-
理解创建 RAG 系统所需的步骤
-
使用 LangChain 工作通过一个 RAG 示例
技术要求
在本章中,我们将广泛使用 ChatGPT,因此您需要注册一个免费账户。如果您还没有创建账户,请访问 openai.com/ 并点击页面右上角的开始使用,或者访问 chat.openai.com。
这些示例需要安装 Python 3.9 和 Jupyter Notebook,这两个都可以在 jupyter.org/try-jupyter/notebooks/?path=notebooks/Intro.ipynb 找到。
我们将使用 ChromaDB 作为我们的开源向量数据库,因此建议您先了解一下它,并熟悉 Chroma (www.trychroma.com)。然而,对于向量存储提供商,还有很多其他不同的选择。
您可以在本书的 GitHub 仓库中找到本章的代码:github.com/PacktPublishing/ChatGPT-for-Conversational-AI-and-Chatbots/chapter7。
我们为什么需要 RAG?
LLM 受限于其训练数据中的世界知识,因此 ChatGPT 不了解最近的事件或您自己的数据,这严重限制了其提供相关答案的能力。由于幻觉,LLM 没有任何知识来支持一个问题,因此它编造了事情。
因此,当我们谈论一个 LLM 的知识时,有两种类型:
-
来自 LLM 在训练期间使用的知识的知识。
-
来自在对话上下文中通过提示传递给 LLM 的信息的知识。我们可以称之为上下文特定知识。
因此,LLM 应用的一个突出用例,也是我最常被问到的一个,就是如何让 LLM 解释和讨论其训练数据集之外的数据。这包括访问实时信息或其他外部数据源,例如公司文档存储库或数据库中包含的专有信息。实际上,我们需要提高 LLM 的上下文特定知识,而 RAG 正是我们实现这一目标的手段。
任何可能需要基础语言模型具备所需知识广度和深度的要求,意味着我们需要从某处获取上下文信息,以便将其传递给我们的 LLM。我们还要注意 ChatGPT 的上下文窗口限制以及更大上下文窗口的成本。如果你有大量数据,那么向 ChatGPT 发送大量数据块将会增加你的令牌使用量和成本。因此,我们的上下文特定知识越小、越相关,就越好。
尽管在本章中我们将专注于为我们的 ChatGPT 应用提供其他特定主题的上下文特定知识,但请记住,上下文特定知识可以指与对话相关的任何内容。当我们在上一章中查看持久化记忆时,你已经了解了 RAG 系统的机制。让我们更详细地看看 RAG 的不同元素。
理解创建 RAG 系统所需的步骤
要实现 RAG,需要执行一系列步骤。首先,我们需要定义数据检索的来源。这可能包括在线数据库、特定网站,甚至根据系统需求定制的数据存储库。然后,我们需要优化并存储这些信息以供检索。一旦完成这些,我们就可以使用检索系统根据查询上下文检索相关信息。然后,在提示过程中将这些信息传递给语言模型。以下图概述了不同的步骤:

图 7.1 – 创建 RAG 系统的步骤
我明白这里有很多事情在进行中,所以让我们更详细地看看每个步骤。
定义你的 RAG 数据源
在我们的第一步中,我们必须识别和选择我们的知识数据检索来源。这可能包括在线数据库、特定网站,或根据系统需求定制的定制数据存储库。我们的来源可能以不同类型的文件格式存在,如原始 HTML、PDF、PowerPoint、Word 文档,或整个网站——这完全取决于你的用例。
为了获得最佳结果,你需要在开始分块过程和其他下游任务之前预处理你的数据,以确保最佳质量。
在创建嵌入之前,你可以做很多事情来提升你的内容。这个过程可能会产生一些成本,但这是值得投资的。一旦完成,你就可以在多个下游任务中使用处理过的内容。
理想情况下,你不需要关心你的内容来自哪里,无论是文件类型;你希望能够处理它们,无论来源格式如何,这样你就可以以相同的方式处理它们。为此,你需要将它们分解成常见的元素,如标题和可读的叙事文本。最常见的形式是 JSON,因为它是一个常见且易于理解的格式。这样,你可以序列化内容并提取和存储元数据,如页码、文档名称和关键词。
每种文档类型都不同,并使用不同的元素来区分不同类型的信息。例如,HTML 有标签,或者我们可以使用 NLP 来理解文本;较短的句子可能是标题。对于 PDF 和图像,我们可以使用更高级的技术,如文档布局检测或视觉转换器。
内容处理可能涉及复杂任务,因此考虑使用像 Unstructured 这样的库或服务是值得的。它们提供了一些非常强大的核心开源工具和优秀的文档,以及执行更复杂任务(如内容提取)的 API。它们还计划推出企业级服务。查看他们的文档并遵循他们的快速入门指南以获取更多信息。
预处理我们的内容并生成嵌入
一旦我们确定了将要使用的数据集,我们需要通过将其分割成可管理的块并从这些块中创建嵌入来清理和准备我们的数据。
为有效与 LLM 交互进行分块
你的数据集可能包含许多文档和字符,因此索引你的数据的第一个步骤是通过文本分割将其缩小到合理的尺寸。我们这样做有几个原因:
-
通过提高嵌入的准确性来增强后续处理的成果相关性。
-
以支持较小的上下文窗口,这是嵌入模型通常支持的。
-
这样我们就可以通过缩小更大的文本来源到更小、更专注的片段来提供更准确和具体的信息。
-
为了减少我们将要传递给 LLM 的上下文知识量。这保持了相关性,影响了响应的质量,并降低了成本。它还允许我们使用更大的文档。
当你分块你的文本数据时,文本的大块被分割成更小的块,如部分、句子、短语、分隔符,甚至单词。通过有效的分块策略,我们的目标是把大内容分解成有意义的片段,我们可以用它们来准确回答用户的查询。以下图展示了分块策略的不同元素:

图 7.2 – 分块策略
然而,分块并不是万能的解决方案。设计一个有效的策略需要仔细考虑你要分块的 内容以及你的应用程序的使用场景。让我们更仔细地看看这些元素:
-
块大小:将其视为你 LLM 的“一口大小”。较小的块(句子、短语)提供了更细粒度的控制,但可能导致信息丢失和上下文碎片化。相反,较大的块(段落、章节)保持了上下文,但可能会超出 LLM 的容量。找到最佳平衡点取决于以下因素:
-
LLM 能力:不同的嵌入模型有不同的处理能力。请参考文档以获取推荐的上下文大小。别忘了,当块被检索时,我们仍然需要将这些添加到我们的上下文中,因此我们还需要考虑 LLM 上下文限制。请注意,如果你使用的是带有 32k 内容窗口的 GPT-4,这问题就不那么严重了。
-
任务复杂度:你打算使用什么类型的内容?是较长的文档,例如文章,还是较短的文档,例如聊天记录?简单的任务,如情感分析,可能可以处理更大的块,而细微的任务,如摘要,则从较小的块中受益。
-
所需细节级别:你需要一个广泛的概述还是深入的研究?你希望支持哪些类型的问题?相应地调整块的大小。
-
-
分块方法:你如何切割文本很重要。流行的方法有不同的优缺点,所以我鼓励你尝试不同的方法,看看你能达到什么样的结果。LangChain 支持所有这些方法的不同库。以下是一些流行的方法:
-
固定大小分块:简单且高效,但可能会破坏句子并丢失上下文。我们在本书的例子中最常用固定大小分块。
-
基于句子的分块:内容感知分块允许你将文本分割成单独的句子。
-
递归分块:这个分块过程通过使用不同的标准迭代地将文本分割成更小的部分,直到达到相似但并非完全相同的块大小,从而允许结构灵活性。
-
记住,最佳的分块策略是针对你的 LLM、任务和期望结果独特的。尝试不同的方法,监控性能,并优化你的策略以充分发挥 LLM 交互的潜力。
关键要点是 LangChain 提供了一些强大的开箱即用的分块工具。现在我们有了分块数据,我们就可以创建我们的嵌入。
理解嵌入 - 将文本转换为有意义的向量
在机器学习和自然语言处理的情况下,向量和嵌入这两个术语密切相关,但它们指的是不同的概念。首先,让我们看看什么是向量:
-
什么是向量?:向量是数据在由维度定义的空间中的数学表示。它本质上是一个浮点数数组。类似于将物品打包进手提箱,我们将数据的各种属性,如高度、重量、颜色或词频,存储在这个列表中。这使得我们可以将复杂的信息输入仅理解数字的机器学习算法。这使计算更高效,允许算法有效地处理大量现实世界的数据。
-
不同类型的向量:有不同类型,例如特征向量和嵌入(我们感兴趣用于 RAG 的向量类型)。
-
它们代表不同的事物:向量可以表示各种数据类型,从简单的数值特征(如图像像素值)到复杂的概念,如词义或文档主题。
-
带有意义的编码:向量值不是随机的;它们包含意义!例如,在词嵌入中,向量空间中单词之间的距离反映了它们的语义相似度。
-
从输入到输出:向量可以表示输入算法的数据和其输出预测。例如,一个向量(稍后会更详细地介绍)可能输入一些文本作为向量,并输出一个表示最接近问题的答案的向量。
词嵌入解释 – 从文本到有意义的数字
我们可以创建各种单词或句子嵌入。然而,在 RAG 的上下文中,我们感兴趣的是分块句子,并希望理解它们之间的关系。为此,我们可以使用句子嵌入。
句子嵌入将整个句子转换成固定大小的密集向量,捕捉整体语义意义。与表示单个单词的词嵌入不同,句子嵌入考虑了句子中单词的上下文和关系。我们可以通过测量向量之间的距离来展示它们的相关性。
让我们想象我们正在为句子“我喜欢吃蛋糕”和“我对烘焙感兴趣”创建嵌入,每个句子使用一个五维向量。请注意,现实世界的嵌入比这要大得多:
-
句子:“我喜欢吃蛋糕:”
[0.45, -0.2, 0.33,0.1, -0.4]
-
句子:“我对烘焙感兴趣:”
[0.4, -0.15, 0.35,0.05, -0.3]
在这个假设的例子中,每个向量在五维空间中代表整个句子的意义。维度是抽象的,不能直接解释,但它们以这种方式组织,使得具有相似意义的句子在这个多维空间中更接近。
想象每个句子都是一个有五个无形墙壁(维度)的巨大房间中的点。具有相似意义的句子在这个房间里会靠得更近,尽管你无法直接看到那些意义。
将“我喜欢吃蛋糕”和“我对烘焙感兴趣”想象成房间里的两个人。当然,他们正在做不同的事情(吃与烘焙),但他们都对食物有着共同的热爱,就像在房间里的同一个“食物区域”里一样。这反映在他们点之间的接近程度,尽管房间本身是看不见的。
在现实世界的应用中,这个“房间”会有更多墙壁(维度)来捕捉意义的更细微细节。维度的数量可以从 50 到 1,024,其中 300 是一个常见的选项。
创建嵌入最简单的方法是使用预训练模型。我们将在下一节中查看一些这些模型以及我们如何创建嵌入。
OpenAI 的文本嵌入模型
OpenAI 的文本嵌入模型一直是最受欢迎的,其中 text-embedding-ada-002 是最广泛使用的。然而,这些模型已经被更优秀的嵌入模型所取代。text-embedding-3-small 和 text-embedding-3-large 是最新且性能最出色的嵌入模型。
OpenAI 的最新进展,文本嵌入 v3,代表了人工智能能力的重大飞跃。这个模型,其“小型”和“大型”的变体,展示了性能的显著提升,尤其是在多语言嵌入和英语语言处理方面。它引入了一种更有效的方法来处理数据维度性,同时不牺牲准确性,这得益于创新的套娃表示学习。通过以层状结构化数据,就像俄罗斯套娃一样,这优化了嵌入过程,提高了语言模型的效率和准确性。
除了 OpenAI 之外,还有许多其他嵌入模型,例如 Google 的 BERT 和 T5,Facebook 的 RoBERTa,以及多语言的 XLM-R。LangChain 通常会简化使用不同模型的过程。对于本章,我们将专注于使用 OpenAI 嵌入模型。在下一节中,我们将看到这是如何实现的。
使用 OpenAI 模型创建嵌入
使用 OpenAI 嵌入模型有几种不同的方式。一种选择是直接调用 embeddings API 端点:
curl https://api.openai.com/v1/embeddings \
-H "C OpenAI content-Type: application/json" \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-d '{
"input": ["I like eating cake"," I'm interested in baking"],
"model": "text-embedding-3-small"
}'
或者,LangChain 提供了一个简单的 OpenAIEmbeddings 包装类,用于使用 OpenAI API 创建嵌入。以下是一个简单的示例:
import ...
os.environ['OPENAI_API_KEY'] = 'KEY'
embeddingsService = OpenAIEmbeddings()
embeddings = embeddingsService.embed_documents(["I like eating cake",
" I'm interested in baking"])
通常,没有必要直接使用嵌入创建服务。许多矢量存储提供了同时嵌入和存储文档的简化方法。我们将通过检查 ChromaDB 中的过程来展示这一点。现在我们已经涵盖了矢量和嵌入,我们可以继续进行 RAG 流程的下一步:使用矢量存储存储和搜索我们的嵌入。
使用矢量存储存储和搜索我们的嵌入
现在我们有了我们高维数据向量嵌入,我们需要能够有效地存储和搜索它们。我们的向量数据库将在存储和搜索我们的数据中扮演重要的角色。以下图表说明了这个过程:

图 7.3 – 索引我们的数据
我们向量数据库是一种特定类型的数据库,它已被优化以与多维向量一起工作。让我们看看使用这种存储类型的优势。
向量数据库的主要优势
向量数据库专门设计用于管理向量嵌入,因此它们提供了以下优势:
-
直观的数据管理:向量数据库提供了我们期望的数据库的所有创建、读取、更新、删除(CRUD)操作。向量数据库还提供了简单的方法来执行元数据存储和过滤,以便我们可以使用额外的元数据过滤器进行更细粒度的查询。
-
相似度搜索:使用向量数据库的主要优势是它允许我们根据向量中表示的意义的相似性来搜索我们的嵌入。因此,虽然传统数据库是基于精确匹配或标准进行查询的,但我们可以使用向量数据库根据语义或上下文意义找到最相似或相关的数据。
-
可扩展性:在大多数用例中,我们可能会处理大量向量。随着数据量的增长,向量数据库可以通过在多台机器之间分配数据来实现水平扩展,确保即使在大数据集上也能保持高效性能。
向量数据库是如何工作的?
虽然传统数据库以行和列的形式存储数据,以适应字符串和数字等标量数据类型,但向量数据库的设计是为了管理向量。这种基本差异也扩展到它们的优化和查询机制。
在传统的数据库设置中,查询通常基于指定的标准在行之间寻找精确匹配。然而,向量数据库却采用相似度指标来识别与查询密切相似的向量,这与精确匹配的方法不同。
向量数据库的核心是近似最近邻搜索(ANN),它利用一系列算法来优化和加速搜索过程。这些算法包括哈希、量化以及基于图的搜索等方法,被编排成一个流水线,以返回快速、准确的结果。
由于向量数据库产生近似结果,一个关键考虑因素是在准确性和查询速度之间的平衡。更高的准确性水平通常会导致搜索速度变慢。然而,一个经过良好优化的向量数据库可以在不显著降低准确性的情况下实现非常快的搜索,为许多应用提供了最佳平衡。向量数据库采用多种不同的技术或相似度度量来比较数据库内的向量,以便它们可以识别最相关的结果。
相似度度量是用于量化向量空间中两个向量之间相似度的数学技术。这使得数据库能够评估存储的向量与查询向量的相似度。有几种相似度度量,以下是一些突出的例子:
-
余弦相似度:这个度量计算两个向量之间角度的余弦值,值范围从-1 到 1。在这里,1 的值表示向量完全相同,0 表示正交(独立)向量,-1 表示完全相反的向量。
-
欧几里得距离:这衡量两个向量之间的直接线距离,范围从 0 到无穷大。0 的值表示向量完全相同,随着值的增加,表示向量之间的相似性逐渐降低。
-
点积:这表示两个向量的模长乘积以及它们之间角度的余弦值。正值表示向量指向同一方向,0 表示正交向量,负值表示相反方向。
现在您已经了解了向量数据库的基本工作原理,下一步是选择适合您项目的正确数据库。
决定使用哪个向量数据库
许多向量数据库和供应商提供开源、托管、可扩展的解决方案,满足每个价格点和需求。
就像选择任何持久层一样,为 RAG 系统和 LangChain 应用选择正确的向量数据库需要仔细考虑几个关键因素,这些因素针对这些高级 AI 框架进行了定制。
对于 RAG 系统,向量数据库必须在快速和精确的检索能力上出类拔萃,并且必须易于使用。向量数据库通常提供特定编程语言的 SDK,这些 SDK 封装了 API,这将使您在应用程序中与数据库交互变得更加容易。
在 LangChain 的背景下,大多数主要的向量提供商已经在 LangChain 库中创建了集成,并成为langchain-community包的一部分。只需查看集成页面,就可以了解哪些供应商创建了现成的集成和详尽的文档。
预算考虑也起着至关重要的作用;开源向量数据库可能为愿意投资设置和维护的团队提供成本节约和可定制性。然而,对于需要无缝可扩展性和最小操作开销的项目,基于云的托管向量数据库可能更为合适,尽管可能成本更高。项目的范围和规模在这里很重要;可能你有选择提供商的奢侈,也可能你被要求查看你选择的云提供商提供的科技。
杰出的向量数据库提供商
当涉及到向量数据库时,既有开源选项,也有托管选项可用。让我们看看一些例子:
-
ChromaDB 是一个可靠的开源向量数据库。我们已经在本书中使用过它,并且我们将将其作为本书剩余部分的首选向量数据库。Chroma 是一个开源嵌入数据库,允许你轻松管理文本文档,将文本转换为嵌入,并进行相似性搜索。是的,有一个 ChromaDB LangChain 包装器和检索类用于查询。其他值得提及的杰出开源向量存储包括 Qdrant 和 Weaviate。
-
Pinecone 是一个专为解决与向量相关独特挑战而构建的托管向量数据库平台,它提供了进入生产所需的一切。
-
由 Meta 提供的 Facebook AI Similarity Search(FAISS)是一个开源库,用于快速搜索相似性和聚类密集向量。它并不完全是一个向量数据库;它是一个向量索引,也称为向量库。它包含了能够搜索不同大小和复杂度向量集的算法。FAISS 在 LangChain 中得到了良好的支持。
这些只是可用的向量数据库选项中的一部分。我强烈建议进行彻底的研究,以确定最适合你项目的选择。此外,考虑探索 LangChain 集成中特色展示的向量提供商,以更全面地了解可用的内容。
到目前为止,我们理解了我们的 RAG 中的步骤顺序。我们已经学习了如何定义我们的数据源,将我们的数据预处理为块,以及如何使用专业模型创建我们的嵌入,以及我们如何利用向量数据库进行存储和搜索。在下一节中,我们将查看一个端到端示例,使用 LangChain 框架将所有这些技术结合起来。
使用 LangChain 通过 RAG 示例进行工作
LangChain 提供了执行我们所概述的所有步骤的功能。因此,让我们在更详细地查看如何使用 LangChain 实现这些步骤的同时,看看一个 RAG 示例。
对于我们的用例,我们将探讨使用非结构化网站数据作为我们 RAG 系统的基石。这是一个常见的 RAG 应用示例,因为大多数组织都有网站和希望使用的非结构化数据。想象一下,如果你的组织要求你创建一个由 LLM 驱动的聊天机器人,能够回答关于组织网站内容的问题。
在我们的场景中,我们将探索利用非结构化网站数据作为我们 RAG 系统的基石。鉴于大多数组织都拥有他们希望使用的充满数据的网站,利用网站上的非结构化数据是 RAG 应用中的一种常见方法。想象一下,如果你的组织要求你开发一个能够回答与公司网站内容相关的查询的聊天机器人。
对于我们的示例,我们将创建一个能够提供关于纽约经济最新信息的聊天机器人。对于我们的数据源,我们将使用维基百科。你可以根据自己的主题领域来跟随这个示例,甚至可以使用你自己的网站页面。
第一步是使用文档加载器加载我们的数据集。那么,让我们开始吧。
集成数据 - 选择你的文档加载器
LangChain 文档加载器旨在轻松地从不同来源获取文档,作为数据检索过程的初始步骤。LangChain 提供了超过 100 种不同的文档加载器,可以满足各种数据源的需求,例如私有云存储、公共网站,甚至是特定的文档格式,如HTML、CSV、PDF、JSON和代码文件。
你需要的文档加载器将取决于你的用例和需求。有了这些选项,你可以将来自几乎任何来源的数据集成到你的 ChatGPT 应用中,无论是来自网站的非结构化公共或私有数据,还是来自 Google Drive 等云存储。你也可以从许多不同的数据库类型或数据存储提供商加载更多结构化的信息。
除了它们的通用性之外,LangChain 中的文档加载器还设计得易于使用。它们提供了直观的接口,允许开发者快速设置并开始以最小的配置获取文档。这种简单性加速了开发过程,尤其是在你创建概念验证以尝试不同的数据源时。希望这能给你更多时间专注于应用程序更复杂的功能。
让我们看看文档加载器的一个简单示例。记住,我们想要回答关于纽约的问题,因此我们的数据集需要满足这些要求。维基百科是一个提供最新信息的绝佳来源,所以这在这个例子中就足够了。让我们看看如何使用WebBaseLoader,一个HTML文档加载器,从维基百科中提取一些信息作为数据集的基础:
from langchain_community.document_loaders import WebBaseLoader
loader = WebBaseLoader(
["https://en.wikipedia.org/wiki/New_York_City#Economy"])
docs = loader.load()
print(len(docs))
print(docs)
打印出docs变量应该会产生类似于以下内容的结果,其中page_content是我们将要使用的数据文本:
[Document(page_content='\n\n\n\nNew York City – Wikipedia
...
metadata={'source': 'https://en.wikipedia.org/wiki/New_York_City#Economy', 'title': 'New York City - Wikipedia', 'language': 'en'})]
考虑到我们所拥有的非结构化 HTML 数据,也许使用documentTransformer来清理我们的 HTML 成纯文本,例如AsyncHtmlLoader,也是值得考虑的。
许多其他 LangChain 文档加载器选项是为特定用例专门构建的,因此始终值得检查 Python 或 TypeScript 中可用的选项。
在我们的例子中,我们将使用WikipediaLoader,这是我们在此章节中之前使用过的。请注意,为了这个例子的目的,我将load_max_docs保持得较低:
docs = WikipediaLoader(query="New York economy",
load_max_docs=5).load()
使用此方法的优点是,我们现在有了来自多个维基百科页面的数据。WikipediaLoader的结果应该看起来相当不错,列出的文档结构与WebBaseLoader的结果相似。
现在我们有了我们的数据集,下一步是对其进行索引。
通过文本分割创建可管理的块
正如我们在关于有效 LLM 交互的块分割部分所讨论的,文本分割的过程可能相当复杂,需要关于块大小和适当方法的仔细决策。幸运的是,LangChain 提供了易于使用的接口和集成,用于几个模块,可以将我们的文档数据集“块化”或分割,以便进行进一步处理。
LangChain 的文本分割算法旨在灵活高效,确保在优化检索的同时,保持原文的完整性和上下文。这涉及到考虑诸如文本的性质和格式、文档内的逻辑划分以及当前检索任务的具体要求等因素。
在 LangChain 中实现文本分割可以通过使用现成的分割器之一来完成,这些分割器根据数据集本身提供不同的分割方式。
小贴士
一个理解不同的块分割策略并评估文本块分割结果的绝佳工具是chunkviz.up.railway.app。这是一个查看基于 LangChain 实用程序和不同参数(如块大小和重叠)如何分割文本的绝佳方式。
对于这个用例,我们将使用RecursiveCharacterTextSplitter来分割我们的文本。RecursiveCharacterTextSplitter实用程序旨在高效地将文本分割成可管理的部分。它寻找预定义的分隔符字符,如换行符、空格和空字符串。结果应该是分割成段落、句子和单词的块化文本,其中文本段保留了相关文本段的意义。该实用程序动态地将文本分割成块,以字符计数为目标大小。一旦块达到这个预定的尺寸,它就被标记为输出段。为了确保这些段之间的连续性和上下文保持一致,相邻的块具有可配置的重叠程度。
它的参数可以完全自定义,提供灵活性以适应各种文本类型和应用需求。
这是一个将大量文本分解成更小、语义上有意义的单元的好方法。
下面是我们的示例代码,它使用了RecursiveCharacterTextSplitter。这适用于通用文本:
from langchain.text_splitter import RecursiveCharacterTextSplitter
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=500, chunk_overlap=100)
split_documents = text_splitter.split_documents(docs)
print(len(split_documents))
我们可以创建我们的RecursiveCharacterTextSplitter类,并设置我们希望控制的属性,包括chunk_size,这确保了处理的可管理大小,以及chunk_overlap,它允许块之间有字符重叠,保持上下文连续性。如果您更改块大小,您将能够创建一个包含更多条目的文档列表。您可以通过运行以下命令查看其中一个分割的文档:
print(documents[5])
使用RecursiveCharacterTextSplitter,我们已经将我们的大型文本内容分解成更小的、有意义的单元。这为我们的数据处理和分析做好了准备。现在,我们已经探讨了文本分割,让我们深入了解如何使用我们的块来创建嵌入:
创建和存储文本嵌入
现在我们有了可管理的数据块,是时候从这些块中创建嵌入并将它们存储在我们的向量数据库中。在这个例子中,我们将使用 ChromaDB 作为我们的向量存储。
在这里,我们将从langchain_openai和langchain.vectorstores库中创建我们的嵌入,这些库允许我们调用 OpenAI 嵌入服务并将它们存储在 ChromaDB 中。按照以下步骤操作:
-
首先,我们必须使用我们的特定模型
text-embedding-3-small初始化OpenAIEmbeddings类的实例:from langchain_openai import OpenAIEmbeddings from langchain.vectorstores.chroma import Chroma embeddings_model = OpenAIEmbeddings( model=" text-embedding-3-small") -
docs_vectorstore = Chroma(...)这一行创建了一个 Chroma 类的实例,用于存储文档向量。以下参数被提供给 Chroma:-
collection_name="chapter7db_documents_store":这指定了 Chroma 中存储文档向量的集合名称。将其视为在数据库中命名一个表,其中将保存您的数据。 -
embedding_function=embeddings_model:在这里,之前创建的embeddings_model被用作嵌入函数。这告诉 Chroma 在存储文档之前使用OpenAIEmbeddings实例来生成文档的嵌入。本质上,每当文档被添加到 Chroma 时,它将通过这个嵌入模型转换成向量。 -
persist_directory="chapter7db":此参数指定 Chroma 将持久存储其数据的目录。这允许向量存储在程序运行之间保持其状态。在我们的情况下,它将是我们运行 Jupyter Notebook 的文件夹:documents_vectorstore = Chroma( collection_name="docs_store", embedding_function=embeddings_model, persist_directory="chapter7db", )
-
-
然后,我们可以通过调用
add_documents()将我们之前分割的文档传递进去。之后,我们可以通过在 Chroma 实例上调用persist()来持久化所有内容:chroma_document_store.add_documents(split_documents) chroma_document_store.persist() -
现在,我们可以进行搜索以查看是否有任何结果返回。我们将通过在 Chroma 实例上执行相似性搜索,并使用我们的文本查询调用
similarity_search来实现这一点。尝试一个与纽约经济相关的问题:similar_documents = chroma_document_store.similarity_search( query="what was the gross state product in 2022") print(similar_documents)
你应该能够打印出查询的搜索结果。现在,让我们看看如何将我们的 RAG 系统与 LangChain 结合在一起。
使用 LangChain 整合一切
现在我们已经让 Chroma 文档存储返回结果,让我们学习如何使用 LangChain 将所有我们的 RAG 元素整合在一起,以便我们可以创建一个能够根据我们文档中的信息回答问题的系统:
-
我们将首先从
langchain_openai和langchain_core库中导入必要的类,以及我们需要登录 LangSmith 的变量。然后,我们需要创建ChatOpenAI类的实例,以便我们可以利用 GPT-4 生成我们的答案:from langchain_openai import ChatOpenAI from langchain_core.prompts import ChatPromptTemplate from langchain_core.runnables import ( RunnableParallel, RunnablePassthrough) os.environ['LANGCHAIN_API_KEY'] = '' os.environ['LANGCHAIN_PROJECT'] = "book-chapter-7" os.environ['LANGCHAIN_TRACING_V2'] = "true" os.environ['LANGCHAIN_ENDPOINT'] = "https://api.smith.langchain.com" from langchain_core.output_parsers import StrOutputParser llm = ChatOpenAI(model="gpt-4", temperature=0.0)将温度设置为
0.0使模型的响应确定性,这对于一致的问答性能通常是期望的。 -
现在我们已经设置了 Chroma 文档存储,我们可以初始化一个检索器来根据我们的查询检索相关文档:
retriever = chroma_document_store.as_retriever( search_kwargs={"k": 5})检索器被配置为返回与查询匹配的前
5个文档。 -
接下来,我们需要创建一个提示模板,告诉语言模型如何利用检索到的文档来回答问题:
template = """ You are an assistant specializing in question-answering tasks based on provided document excerpts. Your task is to analyze the given excerpts and formulate a final answer, citing the excerpts as "SOURCES" for reference. If the answer is not available in the excerpts, clearly state "I don't know." Ensure every response includes a "SOURCES" section, even if no direct answer can be provided. QUESTION: {question} ========================== EXCERPTS: {chroma_documents} ========================== FINAL ANSWER(with SOURCES if available): """ prompt = ChatPromptTemplate.from_template(template)此模板帮助模型从我们的数据中提供有来源的答案,或者指导我们在信息不可用时进行指示:

图 7.4 – 传递给 LLM 的提示
-
接下来,实现一个函数来格式化检索到的文档,以便它们可以包含在提示中:
def format_chroma_docs(chroma_docs) -> str: return "\n".join( f"Content: {doc.page_content}\nSource: {doc.metadata['source']}" for doc in chroma_docs )我们将使用此函数在提示中包含文档内容和来源时,将它们组织成可读的格式。
-
现在,我们必须使用 LCEL 来创建我们的问答管道。这种设置允许我们直接对检索到的文档进行格式化,并简化了提示生成和答案生成阶段的流程:
rag_chain_from_docs = ( {"chroma_documents": retriever | format_docs, "question": RunnablePassthrough()} | prompt | llm | StrOutputParser() )下面是这个管道的每个部分所做的工作:
-
使用
RunnablePassthrough和文档检索进行处理:{"chroma_documents": retriever | format_docs, "question": RunnablePassthrough()}:此字典设置两个并行流。对于chroma_documents,文档通过retriever检索,然后立即使用format_docs进行格式化。对于question,使用RunnablePassthrough()简单地将问题传递过去,不做任何修改。这种方法有效地为下一步准备格式化的文档和问题。 -
提示应用:
| prompt:处理过的信息(问题和格式化的文档)随后被导入提示。此步骤利用ChatPromptTemplate根据预定义的模板将问题与格式化的文档结合,为 LLM 生成答案做好准备。 -
语言模型生成:
llm: 在这里,将上一阶段的综合输入输入到之前初始化的语言模型(GPT-4)中。模型根据提示生成响应,有效地通过从检索到的文档中提取的信息来回答问题。 -
输出解析:
| StrOutputParser(): 最后,语言模型输出的内容通过StrOutputParser()解析成字符串格式。这一步骤确保最终答案是易于阅读且格式正确的。
-
-
最后,我们可以用一个问题和打印答案来调用管道:
question = "what stock exchanges are located in the big apple" rag_chain_from_docs.invoke(question)此搜索应返回类似以下内容,包括答案和来源:
The stock exchanges located in New York City, often referred to as the "Big Apple", are the New York Stock Exchange and Nasdaq. These are the world\'s two largest stock exchanges by market capitalization of their listed companies. \n\nSOURCES: \n- https://en.wikipedia.org/wiki/New_York_City\n- https://en.wikipedia.org/wiki/Economy_of_New_York_City'
通过遵循这些步骤,您已经构建了一个能够用维基百科的最新信息回答关于纽约经济问题的 RAG 系统。尝试一些其他问题,看看 FAQ 的表现如何。
记住,查看 LangSmith 中的调试输出是有用的,这样您就可以看到 LangChain 的每个步骤中发生了什么。在下面的屏幕截图中,我们深入到了 LangSmith 提示模板输出,以便我们可以看到我们检索并传递给 LLM 提示的文档:

图 7.5 – 使用 LangSmith 查看内部运作情况
首先,我们根据我们的主题标准从维基百科加载了我们的文档,将数据分块,并创建了存储在我们向量存储中的嵌入。然后,我们定义了一个检索器来查询我们的存储库,将文档搜索结果传递给 LLM 提示,并将其交给我们的 LLM 以获取对问题的准确响应,同时列出来源并防止幻觉。这是通过在 LCEL 中定义的 LangChain 实现的。
摘要
在本章中,我们探讨了 RAG 系统是什么以及为什么我们需要它们。然后,我们详细介绍了创建 RAG 系统必须遵循的步骤。到这一点,您应该知道如何使用分块选择和预处理数据,以及向量和嵌入是什么以及如何使用专用模型创建它们,以便您可以将它们存储在用于存储向量的特定类型的数据库中。最后,我们创建了一个 RAG 系统,通过每个步骤使用真实世界的例子,并在 LangChain 中将它们全部整合在一起。
在下一章中,我们将更详细地探讨一个由 ChatGPT 驱动的更复杂的真实世界 LangChain 应用。我们将利用前几章的核心概念以及本章中我们关于如何实现 RAG 所学到的东西。我们的目标是创建一个更复杂的聊天机器人,它支持记忆、RAG 以及由 LangChain 工具驱动的更多特定功能。
进一步阅读
以下是一个精心挑选的资源列表,旨在帮助您理解本章提供的内容:
-
LangSmith:
smith.langchain.com/ -
嵌入模型:
python.langchain.com/docs/integrations/text_embedding和platform.openai.com/docs/guides/embeddings/embedding-models -
ChromaDB:
docs.trychroma.com/
第八章:创建您自己的 LangChain 聊天机器人示例
在本章中,我们将结合前几章的关键概念,将其应用于一个实际项目。到目前为止,我们已经涵盖了大量的内容,从对话人工智能基础和提示工程到利用 LangChain 创建 RAG 系统。现在,我们准备通过构建一个由 ChatGPT 驱动的聊天机器人来应用这些知识。
这个项目将展示如何在实际、真实世界的对话人工智能场景中应用 ChatGPT 技术。我们的目标是创建一个自动助手,它不仅能回答关于我们自己的数据的问题,还能处理更复杂的任务并提供个性化服务。
到本章结束时,你不仅将拥有一个功能齐全的 ChatGPT 聊天机器人,而且还将对如何构建更复杂的对话代理有一个扎实的理解。你还将获得洞察力,以更好地评估将 LLM 驱动的代理集成到你的业务运营中的可行性,并确定是否是过渡到现有 NLU 系统的正确时机。
在本章中,我们将涵盖以下关键领域:
-
确定我们的 ChatGPT 项目范围
-
准备我们的聊天机器人数据
-
创建我们的复杂交互代理
-
将所有内容整合在一起——使用 Streamlit 构建您自己的 LangChain 聊天机器人
让我们开始构建我们的聊天机器人,但首先,我们需要考虑我们的对话代理的使用案例和范围。
技术要求
在本章中,我们将广泛使用 ChatGPT,因此你需要注册一个免费账户。如果你还没有创建账户,请访问openai.com/,然后在页面右上角点击开始使用,或者访问 https://chat.openai.com。
这些示例需要 Python 3.9 和一个安装了 Jupyter 笔记本的环境:jupyter.org/try-jupyter/notebooks/?path=notebooks/Intro.ipynb。
我们将使用 Chroma DB 作为我们的开源向量数据库,因此建议查看并熟悉 Chroma (www.trychroma.com),尽管还有许多其他不同的向量存储提供商选项。
确定我们的 ChatGPT 项目范围
每个人都喜欢假期,帮助旅行者通过智能对话自动化是我非常热衷的领域,因此对于我们的用例,我们将创建我们自己的 ChatGPT 驱动的旅行助手。
在这一点上,我们必须对范围保持现实;一个在线旅行代理可能能够执行数千种不同任务,复杂程度各异,但让我们选择一些既有趣又能够结合我们在本书中迄今为止所涵盖的技术的方法。
假日助手用例
你为在线旅行社工作,并被指派创建一个由大型语言模型(LLM)驱动的假日助手,旨在彻底改变旅行者选择住宿的方式。在线旅行社在住宿搜索方面往往受限,因此你的挑战是提供更个性化的细致搜索。利用包含描述、评论和其他可能的信息来源(如天气和位置)的酒店数据集,你的目标是构建一个由 ChatGPT 驱动的聊天机器人,能够引导用户找到理想的酒店选择。让我们称我们的代理为艾莉探险者,并深入挖掘她的角色。
艾莉探险者的角色轮廓
首先,让我们考虑艾莉的个性和她将向用户提供的能力。
艾莉的个性
艾莉热情、友好,知识渊博。她以积极的态度和真诚的帮助意愿对待每一次互动。她的回答深思熟虑且个性化,反映了她对每个用户独特偏好和需求的了解。艾莉不仅仅是一个聊天机器人;她是一个兴奋地帮助用户规划旅行的旅行伴侣,会像朋友一样提供建议。
艾莉的互动以其温暖和热情为特点。她以对话的语气进行沟通,让复杂的旅行规划感觉像与知识渊博的朋友聊天。她的回答迅速、信息丰富,始终考虑用户的需求和偏好。
艾莉的能力
让我们概述一下艾莉在处理用户查询时将具备的能力:
-
学习用户偏好:艾莉警觉且观察力敏锐,能够迅速捕捉到关于用户旅行偏好、家庭动态和最喜欢的假日活动的微妙暗示。她会在互动中记住这些细节,不断改进对每个用户喜好的理解。
-
个性化推荐:利用她对酒店数据集的全面知识,艾莉超越了简单的关键词搜索。她理解自由文本问题,并深入数据库提供与每个用户愿望完美匹配的推荐,无论他们是在寻找家庭友好的度假村、浪漫的度假胜地,还是充满冒险的旅舍。
-
目的地信息:艾莉拥有无数目的地的宝贵信息。她可以告诉你何时是访问某个地方的最佳时间,分享当地景点的见解,提供安全建议,甚至教你一些文化小贴士,帮助你更好地融入当地。她的建议总是最新的,确保旅行者拥有最佳的旅行体验。
-
天气状况:艾莉密切关注全球的天气状况。她可以提供任何目的地的当前和预报条件,并就天气可能如何影响旅行计划提供建议。无论是建议最适合海滩游玩的最佳日子,还是警告因恶劣天气可能导致的旅行中断,艾莉的指导是无价的。
现在我们已经了解了 Ellie 的能力,让我们看看她的对话能力和我们想要支持的交互类型。
Ellie 的对话范围
让我们概述 Ellie 将能够进行的对话。她希望能够执行以下类型的交互:
-
个性化推荐:根据酒店的数据库,基于用户偏好和以往互动,聊天机器人可以提供个性化的酒店推荐,以满足每个用户的特定需求。我们希望提供比仅针对设施等参数的关键词搜索更多的服务。我们希望支持基于酒店描述和假日制造者评论的免费文本问题,使我们能够向用户提供更细致的建议。
-
目的地信息:关于目的地的查询,包括最佳访问时间、当地景点、安全建议和文化提示。
-
天气状况:关于特定目的地的当前和预报天气状况,或天气可能如何影响旅行计划的问题。
希望我们的概念验证(POC)一旦运行正常,我们就能做出明智的决定,是否要制作一个具有更全面功能、包含更大酒店数据集的代理。
技术特性
为了创建 Ellie 这个探险家和达到我们概述的对话范围,我们将实现以下功能:
-
一个 RAG 系统来存储关于我们酒店描述的信息,我们可以用它来提供我们的建议
-
LangChain 代理提供与外部数据源交互的工具,以获取最新信息
-
使用 LangSmith 进行性能监控,以便我们可以看到我们的助手的表现
-
一个工作的基于 Web 的聊天机器人界面,我们可以看到我们的对话并与代理交互,同时跟踪正在进行的对话
为聊天机器人准备我们的数据
为了使我们的数据准备就绪,我们首先需要获取并处理它,使其处于最干净的状态,以便使用。
选择我们的数据源
对于这个项目,我们需要向我们的 LLM 代理提供多种不同类型的特定上下文知识,以便我们可以服务预期的问答类型:
-
酒店信息:这将从我们的在线旅行社酒店数据集中获得,因此我们需要一些酒店数据来代表我们想要向用户推荐的酒店。我们将使用的数据集是
www.kaggle.com/datasets/raj713335/tbo-hotels-dataset数据集的一个小子集,以提供酒店推荐。这个数据集包含来自不同国家和地区的超过 1,000,000 家酒店的信息,例如它们的费用、评论、设施、位置和星级评定。数据是从各种来源收集的,例如酒店网站、在线旅行社和评论平台。我们将使用这个数据集的一个更小的版本,以降低我们的模型交互成本。 -
位置天气:用户可能会询问特定位置的天气,因此我们将使用免费的天气 API Open-Meteo。
-
详细位置信息:为了提供最新的位置信息,我们将使用维基百科,这样我们就可以通过位置进行搜索。
准备酒店数据
我们将要使用的酒店数据集hotel-info-chapter8-001.csv是一个包含约 900 条来自世界各地酒店的CSV文件,以提供一些多样性。这些数据包含以下列:
countryCode、countryName、cityCode、cityName、HotelCode、HotelName、HotelRating、Address、Attractions、Description、HotelFacilities、Map、PhoneNumber、PinCode、HotelWebsiteUrl和Reviews
这些内容都比较容易理解;我们最感兴趣的列是Description和Reviews列,因为我们打算使用这些数据作为我们 RAG 系统的基石,以帮助艾莉提供酒店推荐。所以,为了总结,我们需要做什么来使这些数据对 RAG 可用?我们需要*清洗数据、分块创建嵌入,并将数据作为嵌入存储,以便我们以后可以检索它?。
清洗和标准化数据
在创建嵌入之前,我们需要确保我们的Description和Reviews列中的数据是干净和标准化的。这涉及到移除任何 HTML。如果你查看descriptions字段,你会注意到其中包含带有 HTML 标签的文本,所以我们应该做的第一件事就是清理这些内容。为此,我们可以使用 Python 的bs4包中的BeautifulSoup库。在下面的代码中,我们将使用remove_html_tags函数移除Descriptions和Attractions中的任何 HTML:
def remove_html_tags(text):
if pd.isna(text):
return "" # Return an empty string for NaN values
elif isinstance(text, str):
return BeautifulSoup(text, "html.parser").get_text()
else:
# Convert non-string, non-NaN values to string
return str(text)
df['Description'] = df['Description'].apply(remove_html_tags)
df['Attractions'] = df['Attractions'].apply(remove_html_tags)
我们清洗过程的其它改进可能包括标准化缩写(例如,将Rest.改为Restaurant)和纠正拼写错误。标准化数据有助于减少嵌入的方差,从而提高推荐的准确性。
创建我们的数据块
让我们看看如何从Description和Reviews列创建我们的块。你可以用多种不同的方式来做这件事;我们使用 LangChain 文档加载器,但在一个可能拥有大量数据集的生产环境中,你可能会发现使用我们在上一节中用来清理数据的pandas库更高效。在我们的方法中,我们从 CSV 文件中读取数据,从每一行创建一个字典,以便我们可以访问列值,查看每个文档,然后从Description和Reviews列创建块:
-
CSVLoader类用于此目的。指定文件路径、包含酒店名称的列以及任何其他元数据列。我们使用HotelName作为源列:loader = CSVLoader( file_path="hotel-info-chapter8-001_cleaned.csv", source_column="HotelName", metadata_columns=["countyCode", "countyName", "cityCode", "cityName", "HotelCode", "HotelName", "HotelRating", "Address", "Attractions", "HotelFacilities", "Map", "PhoneNumber", "PinCode", "HotelWebsiteUrl"] ) docs = loader.load() -
使用
RecursiveCharacterTextSplitter进行此操作,设置块大小和重叠以确保文本分析的连续性。描述实际上并不大,但为了我们的示例,目标是将它们分解成足够小的块,以提供有关每个酒店的某些粒度信息:splitter = RecursiveCharacterTextSplitter( metadata and page_content, ready for downstream processing:chunked_docs = []
for doc in docs
content_dict = {}
pairs = doc.page_content.split('\n')
for pair in pairs
if ': ' in pair:
key, value = pair.split(': ', 1)
content_dict[key.strip()] = value.strip()
for column in content_columns:
if column in content_dict and content_dict[column]:
chunks = splitter.split_text(content_dict[column])
chunked_docs.extend(
[
Document(page_content=doc_part,
metadata=doc.metadata)
for doc_part in chunked_doc_parts
]
)
我们希望遍历每个 CSV 记录,并选择Description和Review,然后分别分块处理,这样每个包含原始 CSV 元数据的块就添加到我们的chunked_docs列表中,以便创建嵌入。
创建我们的嵌入
一旦我们得到了分块文本,我们希望创建我们的嵌入。对于我们的向量数据库,我们将使用 Chroma DB 和 OpenAI 模型来创建嵌入。我们将数据库存储在本地,并使用最新的 OpenAI 嵌入模型text-embedding-3-small来创建嵌入。为了降低我的 OpenAI 嵌入成本,我只会从前 100 个块中创建嵌入;至于你想要为你的项目创建多少,那就取决于你了:
embeddings_model = OpenAIEmbeddings(
model="text-embedding-3-small")
chroma_document_store = Chroma(
collection_name="chapter8db_hotel_store",
embedding_function=embeddings_model,
persist_directory="chapter8db",
)
chroma_document_store.add_documents(chunked_docs[:100])
我们可以通过查看具有count()的记录数或进行相似度搜索来测试我们是否在存储中有了记录:
print("There are",
chroma_document_store._collection.count(),
"in the collection")
similar_documents = chroma_document_store.similarity_search(
query="I'm interested in going trail running",k=1)
similar_documents
现在我们已经将酒店嵌入及其元数据存储好了,我们可以开始创建我们的代理将用来与这些数据和其他来源交互的工具。
创建我们的代理以进行复杂交互
我们代理将要由提供满足我们需求功能性的工具驱动。主要概念是代理将能够接收我们的问题,并使用一个 LLM 调用进行推理,将这个任务分解成更小的任务,同时决定使用哪些工具来满足我们的请求并给出问题的答案。代理使用的推理过程在以下图中展示:

图 8.1 – 代理的推理过程
首先,创建一个专门的文件夹,将包含我们代理的所有代码。这将帮助我们组织项目文件,并使代码库更容易导航。我将把这个文件夹命名为 streamlit,因为我们将在那里创建我们的 Streamlit 应用。
将我们创建的用于存储向量的 Chroma 数据库复制到这个文件夹中:path to your project\streamlit\chapter8db\。
接下来,创建一个名为 tools 的文件夹,这样我们就可以开始创建代理的工具。
创建代理工具
在我们创建 LangChain 代理之前,我们需要创建 LangChain 工具以满足我们的需求。我们将尝试使用代理工具实现所有我们的功能,包括 RAG 功能:
-
酒店信息
-
天气信息
-
位置信息
每个工具都将具备执行其自身任务的能力。让我们逐一处理;目前,创建一个名为 tools 的文件夹,我们将在这里保存用于最终项目的工具。
定制酒店推荐
第一个工具可以说是对我们应用最重要的,因为这个工具将与我们向量存储交互,构成我们 RAG 系统的检索部分。我们将创建一个自定义工具来完成这项任务。当我们开始思考代理如何执行这些搜索时,有几个挑战需要克服。
我们目前将嵌入存储在我们的向量存储中,因此我们需要创建一个检索器,它将接受查询以在这些嵌入中搜索,例如“你能推荐一些有 美食 的酒店吗?”
记住我们已经将我们的文本嵌入与其元数据一起存储。更有用的事情是,如果我们能够像使用关系数据库一样过滤我们的嵌入元数据。例如,hotel countryName 和 HotelRating 都在我们的元数据中有所表示。所以,如果我们想寻找特定国家特定评分的酒店相似文档,我们的问题可能类似于“你能推荐一家在英国有 美食 的四星级酒店吗?”
幸运的是,Chroma DB 提供了在元数据上过滤查询的能力,因此我们知道我们可以通过我们的向量存储实现这一点。
接下来要考虑的是如何在我们的 LangChain 工具中实现这一点。第一个挑战是我们希望从问题中提取参数,以便我们可以将这些参数用于下游,特别是在我们的 chroma 查询中。
一种方法是与 LLM 交互,从用户交互中提取相关的搜索参数,然后将这些参数输入到您的检索器中,以对 Chroma DB 执行搜索。然而,在深入之前,查看 LangChain 生态系统已经提供的功能总是最好的实践。事实上,我们已经有一些可以利用的东西,那就是SelfQueryRetriever,这是一个专门构建来执行此任务的检索器。让我们将其分解为详细的步骤,解释每个组件的作用以及它们是如何集成的。
-
hotel_search.py。 -
OpenAI Embeddings。这个模型负责将文本转换为向量表示,这些表示用于语义搜索,并且这是我们创建嵌入时使用的相同模型:from langchain_openai import OpenAIEmbeddings embeddings_model = OpenAIEmbeddings( model="text-embedding-3-small") -
使用
embeddings_model来执行语义搜索。存储在 Chroma 中的文档可以根据其与查询字符串的语义相关性检索:from langchain.vectorstores.chroma import Chroma chroma_document_store = Chroma( collection_name="chapter8db_hotel_store", embedding_function=embeddings_model, persist_directory="chapter8db", ) -
HotelRating、cityName和CountryName。您可以随意添加任何其他您想要搜索的参数:from langchain.chains.query_constructor.base import AttributeInfo metadata_field_info = [ AttributeInfo(name="HotelRating", description="Hotel rating", type="string"), AttributeInfo(name="cityName", description="Name of the city", type="string"), AttributeInfo(name="countryName", description="Name of the country", type="string"), ] -
SelfQueryRetriever使用语言模型、文档存储和我们在上一步中定义的元数据信息初始化。它被配置为在其索引内容内执行基于相似度的搜索,找到与用户查询在语义上相关的文档:from langchain_openai import OpenAI from langchain.retrievers.self_query.base import SelfQueryRetriever # Initialize the language model with a specific temperature llm = OpenAI(temperature=0.0) retriever = SelfQueryRetriever.from_llm( llm=llm, document_store=chroma_document_store, document_content_description="Reviews and Descriptions of hotels", metadata_field_info=metadata_field_info, verbose=True, search_type='similarity', search_kwargs={'k': 10} )我们还限制了返回的文档数量为 10,并设置
verbose=True,以便我们可以查看输出。让我们继续创建我们的提示。 -
PromptTemplate被定义出来,以确保从文档中检索到的信息在回答用户查询时对 LLM 呈现得清晰:from langchain_core.prompts import PromptTemplate template = """you can use the info below to answer questions. Helpful Answer: HotelName: {HotelName} CountryName: {countryName} CityName: {cityName} Address: {Address} HotelRating: {HotelRating} HotelWebsite: {HotelWebsiteUrl}\n\n{page_content}""" prompt = PromptTemplate( input_variables=["HotelName", "HotelRating", "countryName","cityName","Address", "HotelWebsiteUrl"], template=template, )现在我们已经创建了我们的提示,我们可以将所有这些整合在一起来创建我们的工具:
-
使用
create_retriever_tool,传入工具的标题、传递给检索器的描述以及我们创建的文档提示:retriever_description = """ "Searches and provides hotel suggestions by searching by question, return the Hotel name, Hotel Rating, Hotel City, Description, Website and a short summary from the metadata. If there are no hotels matching, state that it can't find any hotels with this criteria """ hotel_search = create_retriever_tool( retriever, "search_hotel_suggestions", retriever_description, document_prompt=prompt )
create_retriever_tool返回我们的工具类型为Tool。最后一步是将hotel_search集成到我们的 LangChain 对话代理中,我们将在创建代理时通过将其传递给AgentExecutor来实现。为了回顾,这个代理将处理关于酒店推荐的用户查询,利用SelfQueryRetriever的语义搜索能力,该检索器现在理解在酒店问题中查找和处理的元数据,为用户提供有用的酒店推荐。
天气信息
我们可以创建一个自定义工具来提供我们的天气信息。创建自定义工具最简单的方法是使用@tool注解一个函数。
因此,对于我们的天气工具,构建起来很简单。我们创建了一个名为 search_weather 的函数,装饰器使用该函数作为工具名称,描述是从文档字符串中提取的。对于天气数据,我们将使用 OpenWeatherMap,为了使调用此 API 的过程既简单又方便,我们将使用 Langchain 实用工具,OpenWeatherMapAPIWrapper。再次强调,如果您想为您的 ChatGPT 应用消费某个服务,在构建任何定制工具之前,总是先在 LangChain 生态系统中四处看看。创建一个名为 search_weather.py 的文件,并添加以下内容:
from langchain.tools import BaseTool, StructuredTool, tool
from langchain_community.utilities import OpenWeatherMapAPIWrapper
os.environ["OPENWEATHERMAP_API_KEY"] = st.secrets.OPENAI_API_KEY
@tool
def search_weather(query: str) -> str:
"""A weather tool optimized for comprehensive up to date weather information.
Useful for when you need to answer questions about the weather, use this tool to answer questions about the weather for a specific location.
Look in context for the location to provide weather for"""
weather = OpenWeatherMapAPIWrapper()
weather_data = weather.run(query)
return weather_data
前往 openweathermap.org/api/ 并注册一个账户以获取您的 API 密钥。这需要作为一个环境变量可用。我们将在创建聊天应用时查看如何设置环境变量。
位置信息
我们希望创建一个工具,用最新的数据回答有关酒店位置的问题,这样我们就可以将这些结果添加到我们的上下文中。有几种选择。我们可以使用 Tavily 搜索引擎,这是为 LLMs 定制的搜索引擎,LangChain 中也有一个现成的工具,TavilySearchResults。
然而,一个寻找信息的好地方是维基百科,所以让我们将其作为我们工具的信息来源。
我们将使用一个现成的 LangChain 工具与维基百科进行交互,WikipediaQueryRun。您需要通过运行 pip install --upgrade --quiet Wikipedia 来安装 Wikipedia Python 包。
创建这个工具很简单——创建一个名为 wikipedia.py 的文件,并添加以下内容以创建 Wikipedia API 包装器:
from langchain.tools import WikipediaQueryRun
from langchain_community.utilities import WikipediaAPIWrapper
api_wrapper = WikipediaAPIWrapper(top_k_results=5,
doc_content_chars_max=500)
包装器提供了一些微调维基百科搜索结果的有用方法,因此我们已将返回的结果数量限制为 5,并将每个返回文档的内容限制为 500 个字符。
接下来,通过传递我们的包装器并给出工具描述来创建工具:
wikipedia_search = WikipediaQueryRun(
api_wrapper=api_wrapper,
description="look up tourist information for locations")
现在,我们将在我们的代理中使用这个工具。在下一节中,我们将探讨如何使用我们创建的工具来创建我们的 LangChain 代理。在下一节中,我们将通过创建一个能够利用我们创建的工具的代理来将这些所有元素结合起来。
整合所有元素——使用 Streamlit 构建您自己的 LangChain 聊天机器人
让我们开始构建我们的基于 Web 的聊天机器人,以便我们可以使用 LangChain 与 ChatGPT 交互。为了实现这一点,我们将使用 Streamlit Python 库来构建界面。Streamlit 丰富的现成组件和实用工具,以及出色的文档,使我们能够迅速开发一个功能性的基于 Web 的聊天机器人。它简单而强大的功能支持快速原型设计和迭代改进,非常适合我们的聊天机器人项目。Streamlit 简化了交互元素的集成,并提供了许多现成的功能,这将缩短我们的开发时间,并使我们能够专注于 LangChain 项目。
确保您已使用 pip install streamlit 或其他许多其他方式安装了 Streamlit。我使用 Anaconda,所以我使用这个发行版。您可以通过运行 streamlit hello 来测试您是否已正确安装 Streamlit。
在我们的项目文件夹中,创建一个名为 app 的文件夹,我们将在此文件夹中存储我们的应用程序代码。将您之前创建的工具复制到 app/tools 下的工具文件夹中。接下来,让我们看看如何管理我们的 API 密钥。
创建密钥和配置管理
Streamlit 的第一个魔法技巧将是使用现成的密钥管理器。Streamlit 提供了基于文件的密钥管理功能,使我们能够轻松存储和安全管理我们的 API 密钥并管理项目。创建一个名为 .streamlit 的文件夹和一个名为 secrets.toml 的文件,然后添加本项目所需的 API 密钥:
-
OPENAI_API_KEY="YOUR KEY" -
LANGCHAIN_API_KEY="YOUR KEY" -
OPENWEATHERMAP_API_KEY="YOUR KEY"
在开发过程中,Streamlit 会自动将 secrets.toml 中的密钥加载到您的项目目录中,并提供选项,如果您想通过 Streamlit Cloud 界面部署或使您的应用程序公开可用。接下来,让我们继续创建我们的代理代码。
创建我们的代理服务
让我们在一个专门的 LangChain 服务文件中组织我们的 LangChain 服务代码。
-
创建 LangChain 服务:首先创建一个用于 LangChain 服务的 Python 文件,并将其存储在应用文件夹中。这个文件可以命名为 langchain_service.py。这个文件将包含设置和运行您的代理所需的所有必要代码。
-
ChatOpenAI模型,AgentExecutor用于管理提示和对话记忆,以及我们在早期步骤中创建的工具(weather_search、wikipedia_search和hotel_search),这些工具旨在为特定的聊天机器人功能设计。 -
setup_agent创建一个AgentExecutor实例,配备特定的工具和设置以用于聊天机器人:def setup_agent(msgs: list, openai_api_key: str, langchain_api_key: str, openweathermap_api_key: str ) -> AgentExecutor: os.environ["OPENAI_API_KEY"] = openai_api_key os.environ['LANGCHAIN_TRACING_V2'] = "true" os.environ['LANGCHAIN_ENDPOINT'] = "https://api.smith.langchain.com" os.environ['LANGCHAIN_PROJECT'] = "ellie_chatbot"前面的参数包括来自 Streamlit 应用和 OpenAI、LangChain 以及
OpenWeatherMap服务的 API 密钥的消息列表,用于会话历史。然后我们设置环境变量,以便 LangChain 可以访问它们。我还设置了环境变量,以便我们可以在 LangSmith 中跟踪一切,以及一个项目名称,这样我们就可以轻松跟踪我们与 Ellie 的所有交互。 -
创建
ChatOpenAI时指定了特定的温度和模型参数。我们还创建了我们的工具列表:llm = ChatOpenAI(temperature=0.0, model=' gpt-4-1106-preview',verbose=True) tools = [hotel_search,weather_search,wikipedia] hub_prompt = hub.pull("hwchase17/openai-tools-agent")预定义的工具(
hotel_search、weather_search和wikipedia)将添加我们的专用功能,代理将根据提出的问题决定使用哪些功能。hub_prompt是通过hub.pull获取的,它从 LangChain hub 中获取一个预定义的提示模板。如果您想有更多的控制权,可以手动创建,但对我们这个例子来说,这已经足够完美。 -
ConversationBufferWindowMemory,它将为我们的聊天机器人提供对话记忆,并允许它提供上下文感知的回复。注意,我们通过设置k=20来保留最后 20 个交互的记忆,并且我们还从我们的 Streamlit 代理中传递一个消息列表 (msgs) 到chat_memory,这使得我们可以将代理记忆与 Streamlit 会话状态联系起来。 -
create_openai_tools_agent函数。这个 LangChain 函数创建了一个能够使用 OpenAI 的tools功能的代理:agent = create_openai_tools_agent(llm, tools, hub_prompt)使用语言模型 (
llm)、工具列表和hub_prompt调用create_openai_tools_agent来创建一个配置好的代理。 -
AgentExecutor,它使用创建的代理、工具、内存配置和详细设置进行实例化。这个执行器管理聊天机器人的执行流程,处理输入,并根据集成的工具和对话记忆生成响应。setup_agent()函数返回AgentExecutor实例,现在它已准备好在 Streamlit 聊天机器人应用程序中使用。我们将在下一节中查看如何创建这个应用程序以及如何使用我们的 LangChain 服务:
构建我们的 Streamlit 聊天应用
现在我们所有的组件都已准备就绪,是时候构建我们的聊天机器人了。首先创建一个名为 main.py 的文件;这个文件将作为主要的 Streamlit 脚本。在这个脚本中,我们将开发 Ellie 的聊天机器人界面。让我们一步步来创建这段代码:
-
使用
streamlit (as st)为我们的聊天机器人元素。我们还导入setup_agent()。这个函数来自我们创建的langchain_service.py,它使用必要的配置和 API 密钥初始化聊天机器人的代理。 -
init_streamlit()函数;这个函数使用st.set_page_config设置 Streamlit 页面配置,指定页面标题和图标。我们还使用st.title("✈️ Ellie the explorer ")给我们的页面一个标题。 -
StreamlitChatMessageHistory是一个类,允许您在 Streamlit 应用中存储和使用聊天消息历史,msgs = StreamlitChatMessageHistory()。它与 LangChain 无缝工作,允许您将聊天消息历史集成到您的 LangChain 链中。它通过在指定的键(默认为
langchain_messages)中存储消息来实现。然后,我们将此内存的引用传递给我们的代理。 -
prepare_agent和setup_agent使用存储在st.secrets中的聊天消息历史和 API 密钥,返回一个配置好的AgentExecutor。 -
AgentExecutor和prepare_agent()用于创建我们的agent_executoragent_executor: AgentExecutor = prepare_agent(msgs),将聊天消息历史和从st.secrets获取的 API 密钥传递给从我们的 LangChain 服务代码langchain_service.py导入的setup_agent()函数,该函数返回为聊天机器人配置的AgentExecutor实例。 -
显示欢迎消息:在对话开始时向用户添加欢迎词,指导他们如何与聊天机器人交互:
if len(msgs.messages) == 0: msgs.add_ai_message(welcome)如果是初始加载(即,历史中没有消息),则定义并添加消息到聊天历史。
-
用户交互和响应处理:接下来,我们想要处理用户输入。如果用户输入一个新的提示,我们将生成并绘制一个新的响应:
if prompt := st.chat_input(): st.chat_message("human").write(prompt) try: response = agent_executor.invoke({"input": prompt}) if 'output' in response: st.chat_message("ai").write(response['output']) else: st.error("Received an unexpected response format from the agent.") except Exception as e: st.error(f"An error occurred: {str(e)}. Please try again later.")可以添加一个可选组件,以便您可以轻松查看存储在
st.session_state.langchain_messages中的内容。这是一个展开小部件(st.expander),用于以 JSON 格式显示消息历史。应用程序通过
st.chat_input()监听用户输入。当接收到输入时,它使用st.chat_message()将其显示为human消息。然后将输入传递给
agent_executor.invoke()以处理响应,如果成功,则将响应作为ai消息显示给用户。我们还处理响应格式错误以及从我们的代理调用返回的错误;如果有错误,则使用
st.error()显示此消息。如果脚本是主程序(即,不是作为模块导入),则调用
init_streamlit()以启动应用程序:if __name__ == "__main__": init_streamlit()
就这些了!现在,一切应该都已经就绪,可以创建一个功能性的聊天机器人。在下一节中,让我们来试一试。
运行和测试我们的聊天机器人应用程序 Ellie
要运行这个 Streamlit 应用程序,请确保您已经在 Python 环境中安装了 Streamlit 以及所有必要的包。然后,导航到包含main.py文件的目录,并在您的终端中运行以下命令:
streamlit run app/main.py
此命令启动 Streamlit 网络服务器,并在您的默认网络浏览器中打开应用程序,允许您与聊天机器人交互。如果存在问题,请检查您的 API 密钥和任何其他必需的配置是否已正确设置在st.secrets中,并且已适当地传递给setup_agent()函数,以便应用程序按预期运行。您还应该能够在开始与聊天机器人交互后看到您的日志出现在 LangChain 中,这使您能够深入了解每次运行。
让我们尝试我们的第一个酒店推荐搜索。我们得到了一个有用的结果,如以下输出截图所示:

图 8.2 – 向我们的代理请求酒店推荐
代理查看问题并选择使用哪个工具来满足请求。这个问题是针对酒店的,因此代理调用我们的hotel_search工具来回答我们的问题。记得查看 LangSmith 中的调试输出以查看项目的单个运行。这将允许你看到对 LLMs 的单独调用,从而深入了解你的代理如何与不同的 LLMs 交互以决定使用哪个工具,并返回我们的响应,以及针对单个工具的其他特定任务 – 例如,提取用于过滤我们的向量搜索的参数。以下 LangSmith 截图显示了这一点:

图 8.3 – 查看 LangSmith 中我们的代理对 LLMs 的调用
随意尝试你自己的问题,任何与你的数据相关的问题。
我们还应该能够提出后续问题,以便代理练习其他工具。在以下截图中,我们还询问了天气,你可以看到 Ellie 使用我们的天气搜索工具提供数据。

图 8.4 – 我们提出一个特定于天气的问题来测试我们的天气工具
通过询问关于该地区的具体信息来尝试使用wikipedia_search工具。
因此,我们现在有一个基于 ChatGPT 的运行良好的代理,这可以作为一个更高级代理的良好基础。让我们看看你可以实施的其他改进。
改进 Ellie 的方法
你可以实施许多不同的增强来改进 Ellie 的旅行助手功能:
-
改进聊天界面 – 例如,实现流式回答
-
通过增强我们的 LangChain 代理,提供更复杂的交互,以便我们可以执行更复杂的交易任务
-
学习用户偏好 – 他们的兴趣、家庭状况以及他们喜欢在假期做什么
-
通过向量存储增强聊天机器人内存,以便在会话之间持久化对话,以便可以使用
-
查看分块策略以改进向量嵌入,以实现更好的搜索
到目前为止,你所创建的只是一个起点,是创建更复杂的 ChatGPT 代理的良好基础。这些增强中的任何一个都值得实施以改进 Ellie 的能力。
摘要
在本章中,我们探讨了创建一个由 ChatGPT 驱动的对话代理的真实世界示例,使用了我们在前几章中介绍的一些技术和方法。我们的示例经过精心设计,涵盖了聊天机器人的用例、功能和特性,使我们能够有效地应用我们对 LangChain、RAG 系统和相关工具的知识。您还介绍了 Streamlit 库来创建丰富的聊天界面,并看到了如何将其与 LangChain 结合使用。希望我们已经实现了我们的代码库,使我们的代理可扩展,并且可以用于更复杂的项目。我们已经实现了我们的目标,即创建一个具有我们自己的数据知识并能够使用外部信息和来源的 ChatGPT 对话代理。
我们已经创建了我们的原型并验证了我们的概念。这是一个开始,但在创建更广泛的应用程序并上线之前,还有很多事情需要考虑。在我们的最后一章中,我们将考虑使用到目前为止所学的内容进入生产,以及我们需要创建哪些其他核心功能来实现这一目标。我们还将考虑 ChatGPT 的其他替代方案以及小型语言模型的兴起和重要性。最后,我们将得出一些结论,并探讨在当前技术状态下我们将如何继续前进。
进一步阅读
以下链接是本章中使用的资源精选列表:
-
Streamlit:
-
LangSmith:
-
嵌入模型:
python.langchain.com/docs/integrations/text_embedding和platform.openai.com/docs/guides/embeddings/embedding-models -
Chroma DB:
第九章:基于大型语言模型(LLMs)的对话式 AI 的未来
在本章中,我们将深入探讨与将我们的 ChatGPT 应用投入生产相关的话题。我们在本书的其它部分已经涉及了一些这些领域,但现在让我们更详细地考虑这些方面,同时也要看看行业中学到的经验教训。基于到目前为止我们从创建 ChatGPT 应用中学到的知识,我们可以做出明智的决定,并创建与我们的对话式 AI 项目相关的成功策略。
我们还将探讨在撰写本文时 ChatGPT 的其它替代技术,特别关注小型语言模型(SLM)的潜力。最后,我们将展望 LLMs 的未来可能,以及你的组织可能的发展方向,为你准备对话式 AI 演变中的下一个阶段。
在本章中,我们将涵盖以下主题:
-
投入生产
-
评估生产系统
-
学习如何使用 LangSmith 评估你的项目
-
LangSmith 的高级监控功能
-
ChatGPT 和 LangChain 的替代方案
-
小型语言 模型(SLM)的增长
-
接下来的方向
技术要求
在本章中,我们将广泛使用 ChatGPT,因此你需要注册一个免费账户。如果你还没有创建账户,请访问openai.com/,并在页面右上角点击开始使用。
这些示例需要安装 Python 3.10 和 Jupyter Notebook jupyter.org/try-jupyter/notebooks/?path=notebooks/Intro.ipynb。这些示例需要安装 Python 3.10 和 Jupyter Notebook,你可以通过访问jupyter.org/try-jupyter/lab/index.html来完成。
你可以在以下链接找到本章的代码:github.com/PacktPublishing/ChatGPT-for-Conversational-AI-and-Chatbots/chapter9。
投入生产
随着你在本书中的进展,你在如何创建由 ChatGPT 驱动的对话代理方面的知识得到了很大的提升。希望你也了解了一些由 LLMs 驱动的系统的局限性、挑战和陷阱,最重要的是,使它们准备好投入生产。这些挑战不容小觑,过去一年多来,尽管 LLMs 得到了广泛的应用,但完全由 LLMs 驱动的对话式 AI 代理的例子却很少,而且其中一些在某些情况下表现不佳。让我们在下一节中看看一个例子。
理解投入生产的危险
最近的一个例子是,LLM 在生产中如何迅速让你陷入困境,就是一个知名配送公司部署的聊天机器人出现的问题。我不会在这里点名这家公司;还有其他表现不佳的聊天机器人的例子。另一个例子是花一美元买了一辆雪佛兰塔霍——我建议你谷歌一下这个例子!
对于交付聊天机器人,一位不满意的客户决定通过提出一系列尴尬的问题来给他们的对话增添一些幽默感,结果聊天机器人开始咒骂,并背诵了一首诗,指责配送公司无用。这对客户支持聊天机器人来说并不是一次最好的对话,但却是任何没有适当防护措施的 LLM 驱动的对话代理可能出错的一个很好的例子。
那么,这里发生了什么?我无法对这家公司在聊天机器人项目中使用的技术栈或 LLM 技术发表评论。然而,如果一个代理开始用脏话回应,看起来他们没有采用任何输出验证器或内容审查检查。这允许公众成员直接提示 LLM。这看起来不太可能是模型训练的问题,而更可能是缺少防护措施来阻止恶意(好吧,有点夸张)的提示。这允许用户参与 LLM 的非品牌话题或超出范围的请求。因此,对 LLM 问题的内容过滤将阻止这种情况,同时结合对输出进行审查,以确保在发送给客户之前内容适当。
这里实际上有两个问题:输入和输出,你希望这些问题能够通过更稳固的提示策略来处理。例如,如果代理是一个由 ChatGPT 驱动的 LangChain 代理,那么我们会考虑创建一个强大的系统提示,并在我们进入主管道之前使用 LLM 调用检查初始问题。这需要有一个广泛评估过程的支持,不仅包括标准问题,还包括系统如何处理试图操纵和/或破坏系统的用户,以便他们在社交媒体上发布关于它。
记住——权力越大,责任越大,在创建 LLM 项目时,与传统自然语言理解(NLU)系统相比,这是一场不同的比赛。我们实际上已经从创建一个系统并关注正确、错误和缺失的答案,转变为一个所有这些都可以发生,而且几乎任何其他事情都可以发生的系统,除非你做出了足够的努力来阻止它。
到现在为止,我相信你已经意识到最受欢迎的 LLM 应用之一是 RAG 系统,我们已经在之前的章节中对此进行了广泛的讨论。然而,这些系统也并非没有挑战;让我们更详细地探讨一些这些问题。
RAG 系统的挑战
正如我们所学的,RAG 系统是 LLM 对话式 AI 中流行的实现之一,可能出现在你目前正在尝试使用 LLM 技术或正在开发的绿色项目中重新创建的系统。你也了解到,你可以从这些系统中获得相当不错的性能,而不需要付出巨大的努力。然而,尽管 RAG 系统是 LLM 驱动对话式 AI 的典范,但它确实提出了挑战,随着你向生产阶段迈进,这些挑战变得更加重要,我们将在下一节中探讨这些挑战。因此,让我们考虑我们正在考虑将一个带有 RAG 系统的项目投入生产——例如,第八章中的项目:我们旅行助手的概念验证(POC)。到目前为止,关键利益相关者对 Ellie Explorer 印象深刻,并希望将其作为基于网络的聊天机器人发布,同时扩大其范围,提供更多针对性的个性化酒店建议,并回答常见问题以及更多交易性用例。为了回顾,我们使用了 RAG 系统,以便从我们的 LLM 准备好的酒店信息数据存储库中注入上下文参考数据,以提供简洁、可信的酒店推荐。
尽管它们采用了创新的方法,但简单的 RAG 系统存在一些挑战,可能会阻碍其有效性和可靠性。
从 POC 过渡到生产是一个巨大的步骤,在将 Ellie 投入市场之前,我们需要考虑 RAG 系统的挑战。
传统 RAG 的不足
让我们详细看看 RAG 系统的不足之处以及这些不足如何在我们的系统中体现:
-
缺失内容:当尝试处理一个无法从现有底层文档数据中找到答案的问题时,可能会出现失败,可能是因为信息根本不存在,或者存在一些分块或嵌入过程的问题。这可能很难调试,并且需要正确处理。理想情况下,RAG 系统将简单地回复一条消息,例如“抱歉,我没有这个信息。”然而,在问题与内容相关但缺乏具体答案的情况下,系统可能会被误导提供回应。或者,一个更难发现的失败可能是从我们之前的例子中得出的:如果 RAG 系统搜索没有返回结果——例如,对于不在我们提供的酒店数据库中的国家的酒店推荐。LLM 正在从它自己对酒店的知识中回应,而不是从 RAG 结果中,因此建议的公司酒店列表之外的酒店。这种行为可以通过提示来纠正,但你可以看到这里的问题:很难发现。现实情况下,我们需要定期检查我们的酒店结果建议,以确保这种情况不会发生。
-
检索和精确度不足的问题:对于 RAG 系统来说,检索相关信息是一个关键挑战。底层检索模型可能会获取相关数据,这可能导致生成误导性或不相关的文本。这种情况通常是由于在质量不足的数据上训练或数据未能准确代表目标领域而发生的。提高数据质量和确保其与目标领域的一致性是解决这一挑战的关键步骤。然而,这也可能表明我们需要更复杂的检索算法,这些算法可以准确理解查询的上下文和细微差别。
也可能存在结果排名问题,其中文档包含问题的答案,但排名不够高,无法呈现给用户。也可能会出现结果排名问题,其中文档包含问题的答案,但它排名不够高,无法呈现给用户。在 Ellie 的情况下,如果我们返回n个酒店结果,从理论上讲,所有文档都会被排名,但这可能意味着一些文档可能无法达到标准,无法发送到上下文中。
基本上,如果我们输入的提示包含错误或不恰当的上下文参考,那么结果响应可能不会提供良好的结果也就不足为奇了。基本上,如果我们输入的提示包含错误或不恰当的上下文参考,那么结果响应可能不会提供良好的结果。
-
过时信息:如果知识源没有定期更新或模型缺乏识别和整合时间信息的机制,RAG 生成的内容可能会基于过时的事实。保持知识库的时效性和设计检索系统以考虑信息的时效性是很重要的。
-
增加的 RAG 成本:有人担心,随着许多具有 RAG 组件的 ChatGPT 系统,将出现越来越多的不必要的令牌成本开销,这主要是由于未优化的检索和额外的文本结果被传递到上下文中造成的。
-
AgentExecutor将解决a,但b和c是你需要构建到你的系统中的内容。 -
常见的 LLM 问题:幻觉、毒性、不相关性
幻觉和不相关性可能源于系统设计中的缺陷或知识库中的不准确,以及来自底层 RAG 数据或通过 ChatGPT 调用生成的响应中的毒性和偏见。所有这些都是需要在生产系统中注意的问题。
因此,现在我们已经讨论了你将要面对的挑战和解决方案,在下一节中,让我们考虑如何评估你的 LLM 应用程序。
评估生产系统
开发一个包含 RAG 组件的 ChatGPT 原型应用相对直接,但为生产做准备并有效维护它则需要持续的评估,这具有挑战性。使用 LLM 辅助评估是一个明显的途径;然而,请注意,由于 LLM 表现出位置偏差、答案风格偏好以及每次运行结果的不确定性,这导致需要更结构化的方法。还值得记住的是,代理的使用场景和性质将影响你的评估方法。例如,与更会话式的代理相比,简单的 RAG 问答需要不同的评估方法。
重要的是要理解,就像任何机器学习(ML)项目一样,你应该使用验证数据集和评估指标来评估 RAG 管道的性能。这涉及到对组件进行个别和集体评估:知识检索、响应生成以及它们的集成。你可以考虑多种不同的评估指标,例如上下文相关性、扎根性和答案相关性。
目前,确定合适的评估指标和收集良好的验证数据是一个快速发展的主题。为了解决 LLM 辅助评估的缺点,有各种方法和指标用于评估 RAG 系统,包括检索增强生成评估(RAGAs)或 RAG 三联指标,以及一系列工具选项和库。这些方法中的每一个都值得在这里详细讨论,并且值得阅读其中的一些,以了解不同的方法和它们如何实现。这些主要是通过关注知识检索的精确性和响应生成的质量,以结构化和全面的方式评估 RAG 应用有效性的方法。让我们在下一节中考虑使用 LangSmith 对 LangChain 应用进行评估的过程。
评估系统的组成部分
LangSmith 提供了一个强大的评估框架,旨在通过以下图中概述的精心设计的组件来监控和改进 LLM 应用:

图 9.1 – 评估过程
LangSmith 提供用于构建数据集、编辑和版本控制它们的 UI 和 SDK:一个用于定义自己的评估器或创建和使用自定义评估器的 SDK,以及一个用于执行检查和跟踪分析的 UI。
让我们更详细地探讨一个有效评估系统的组成部分:
-
数据集 和示例:
LangSmith 中任何评估系统的基本单元是数据集,它由多个示例组成。数据集中的每个示例代表一个包含输入和预期输出的测试用例:
-
输入:这些是 LLM 将处理的数据点。
-
输出:这些是 LLM 在给定输入时应产生的预期结果。
数据集通常来自各种来源,包括手动创建、用户反馈或良好的对话示例,或从 LLMs 生成的输出。如果你正在考虑从现有系统迁移到 ChatGPT 驱动的代理,那么你的历史对话数据对于评估将是至关重要的。
-
-
数据集类型:LangSmith 支持不同类型的数据集:
-
KV:键值对,可以容纳多个输入和输出。
-
LLM:直接输入和输出字符串,通常用于简单的提示-响应模型。
-
聊天:结构类似于聊天对话,适用于在对话上训练的模型。
在 LangSmith 中创建数据集很容易,你可以创建和编辑数据集以及示例行,还可以从 CSV 导入。
-
-
任务:被评估的实际操作或模型。它处理数据集中的示例输入并生成输出,然后由评估器进行评估。
-
评估器:评估器是评估任务生成的输出的函数或机制。它们将这些输出与预期结果进行比较或应用特定标准以确定输出的质量。评估器返回分数,并为每个示例提供反馈。存在多种不同类型的评估器:
-
启发式评估器:这些是执行检查的简单函数,例如验证输出格式(例如,JSON 验证)或与预期输出进行字符串匹配。
-
LLM-as-judge:使用另一个 LLM 来根据内容标准(如冒犯性或相关性)评估输出质量的先进评估器。
-
人工:手动审查输出,通常用于最终验证或在需要细微判断的情况下使用。
-
-
EvaluationResult包含以下内容:-
关键:正在评估的度量名称(例如,准确度、完整性)。
-
分数:衡量输出与预期结果匹配程度或满足评估标准的定量度量。
-
注释:可选的见解或关于分数背后的推理。
-
现在你已经了解了评估系统组件,在下一节中,我们将通过一个示例来探讨如何将其应用于实践。
学习如何使用 LangSmith 评估你的项目
记住,不同类型的 AI 代理将需要不同的评估方法。没有一种适合所有情况的方案,你需要根据你的用例来决定采用的方法和途径。如果你想要支持特定领域的知识,例如来自 RAG 系统的公司特定信息,那么一个问答代理将更容易评估;而需要支持交易性对话的代理将需要一个更复杂的评估实现,因为你需要确保你的对话代理能够始终如一地完成任务。
在基于意图的系统下,你可以精确控制对话的每一步,而在 LLM 驱动的对话代理下,你通过提示来控制代理的动作和能力,这在我的看法中是一种更微妙且易变的方法。
Langsmith 使得这种深入的特定评估成为可能,让我们通过一个简单的代码示例来运行,这样你可以看到与 LangChain 一起工作的基本原理:LangSmith 使得这种深入的特定评估成为可能。让我们通过一个简单的代码示例来运行,这样你可以看到与 LangChain 一起工作的基本原理。
我们的示例由一个 RAG 系统组成,该系统从简单的知识库中回答关于超级马拉松跑步的问题:
-
source.text文档源.text 包含一些关于跑步的信息。请随意使用你自己的主题——我只是喜欢跑步!我们遵循前面章节中概述的标准工作流程,创建一个简单的基于简单文本语料库的 LangChain RAG 以进行评估——文档分块、嵌入创建以及使用 OpenAI 嵌入和内存中的 Chroma DB 作为向量存储的检索器创建:loader = TextLoader('source.txt') documents = loader.load() text_splitter = RecursiveCharacterTextSplitter( chunk_size=500, chunk_overlap=20, length_function=len, is_separator_regex=False,) split_documents = text_splitter.split_documents(documents) embeddings = OpenAIEmbeddings(model="text-embedding-3-small") chroma_document_store = Chroma.from_documents( split_documents, embeddings) retriever = chroma_document_store.as_retriever( search_kwargs={"k": 4}) -
创建一个
ChatOpenAI类,并从模板字符串创建一个ChatPromptTemplate实例,其中包含问题和上下文的占位符,这些占位符将在 RAG 管道执行期间被填充。接下来,使用 LangChain 表达式语言(LCEL)将所有内容整合在一起,创建我们的链,你可以调用它来检查一切是否正常工作:model = ChatOpenAI(model="gpt-3.5-turbo-0125") template = """You are a helpful documentation Q&A assistant, trained to answer questions about ultra marathon running. Use the following pieces of retrieved context to answer the question. If you don't know the answer, just say that you don't know. Use two sentences maximum and keep the answer concise. Question: {question} Context: {context} Answer: """ prompt = ChatPromptTemplate.from_template(template) # Setup RAG pipeline rag_chain = ( {"context": retriever, "question": RunnablePassthrough()} | prompt | model | StrOutputParser() ) chain.invoke("do i need to do any long runs in my training") -
pip install -U langsmith. 然后,设置你的环境以使用 LangSmith,然后创建你的 LangSmith 客户端:from langsmith import Client, evaluate from langsmith.schemas import Run, Example # Initialize the LangSmith client client = Client() -
使用
client.create_dataset()创建数据集,然后使用create_examples()添加我们的示例。我们也可以直接使用 LangSmith UI 添加这些示例:dataset_name = "Ultra Marathon QA Dataset" description = "Dataset for evaluating QA correctness of an ultra marathon chatbot." dataset = client.create_dataset(dataset_name, description=description) client.create_examples( inputs=[ {"question": "How do...", "context": "..."}, {"question": "will i...", "context": "..."} ], outputs=[ {"answer": "Training..."}, {"answer": "Consider buying..."} ], dataset_id=dataset.id, )向数据集添加示例的另一个简单选项是从 LangChain 中的现有运行中获取。只需转到 运行详情 页面,然后点击 添加到 数据集 按钮即可。
-
定义一个 评估方法:
创建一个函数来调用我们正在评估的东西,在我们的例子中是 RAG 链,但这可以是你的管道中的任何可运行元素:
def predict(inputs: dict): return rag_chain.invoke({"question": inputs["question"]}) -
定义一个用于评估器的输入格式化器:
定义一个函数来格式化评估器的输入。此步骤确保评估器函数以一致格式接收必要的数据:
def format_evaluator_inputs(run: Run, example: Example): return { "input": example.inputs["question"], "prediction": next(iter(run.outputs.values())), "reference": example.outputs["answer"], } -
LangChainStringEvaluator评估器。这涉及到配置它以根据预定义的标准和归一化因素评估聊天机器人的响应的正确性。此评估器将处理字符串比较,从而允许精确测量答案的准确性:from langsmith.evaluation import LangChainStringEvaluator correctness_evaluator = LangChainStringEvaluator( "labeled_score_string", config={"criteria": "correctness", "normalize_by": 10}, prepare_data=format_evaluator_inputs)让我们看看创建评估器的详细信息:
-
标签:
"labeled_score_string"指定评估结果中输出的评分标签。"labeled_score_string"指定评估结果中输出的评分标签。 -
"criteria":"correctness",它定义了评估应测量的内容——在这里,是响应的准确性。 -
"normalize_by":10,将分数调整到 0 到 10 的比例,使其更容易解释结果。
-
-
准备数据:
format_evaluator_inputs是一个函数,它以评估器可以有效地处理的方式格式化输入、预测和参考。format_evaluator_inputs是一个函数,它以评估器可以有效地处理的方式格式化输入、预测和参考。 -
使用
evaluate()而不是正在被弃用的run_on_dataset(),后者将返回评估结果:results = evaluate( predict, data=dataset_name, experiment_prefix="Chat Single Turn", evaluators=[correctness_evaluator], metadata={"model": "gpt-3.5-turbo"}, )让我们看看
evaluate()调用的不同元素:-
predict) 是聊天机器人用来从输入生成答案的。 -
LangChainStringEvaluator评估器,在之前的步骤中设置。您也可以创建自己的自定义评估器并将其包含在这里;您可以使用多个评估器。 -
元数据:包含有关所使用的模型版本的详细信息,便于进一步分析和追溯。
-
请记住,LangSmith 还会在您从 UI 选择创建实验时创建评估代码。这也提供了不同预构建评估链的示例,允许您评估以下内容:
-
正确性
-
简洁性
-
相关性
-
一致性
-
有害性
-
恶意
-
有用性
-
有争议性
-
偏见
-
犯罪性
-
不敏感
在编写本文时,代码示例使用 run_on_dataset(),但将其迁移到 evaluate() 应该相当简单。当您运行 evaluate() 时,这应在 LangSmith 中创建一个实验,您应该看到如下输出:
在以下位置查看实验:‘Chat Single Turn-46c45783’的评估结果:
https://smith.langchain.com/...
此链接应带您进入 LangSmith 中的实验链接,您可以在其中查看每个实验的详细信息,如下面的截图所示:

图 9.2 – 在 LangSmith 的实验视图中显示的评估输出
点击成功或失败按钮将显示数据集中每个输入和输出的测试详情。从这一视角,你还可以深入到每个运行中,查看发生了什么,以及通过其他信息,如每个运行的令牌成本。评估的令牌成本可能会根据你的数据集大小迅速上升。
让我们尝试测试我们用来阻止 LLM 使用其他数据并反馈给用户(如果它无法回答)的提示。在 LangSmith 中尝试向你的数据集添加另一个问答对,但这次,让我们添加一个它不应该能够回答的问题。在我的例子中,这是关于训练师的一些具体信息,我知道我的知识库中没有提到:
Input: {"question": "Do I have to use carbon inserts in my trainers"}
输出:{"answer": "提供的文档不包含关于在超长跑训练师中使用碳插件的任何信息。"}
当我重新运行评估时,我们可以看到测试通过,我们的智能体正在按照预期响应。你可以在下面的屏幕截图中看到输出:

图 9.3 – LangSmith 中显示幻觉测试的评估输出
尝试查看其他类型的现成评估器,看看你是否可以针对其他标准进行评估。
对于评估不同基于 LLM 的系统,没有一种适合所有情况的解决方案。不同类型的对话式 AI 智能体将需要不同类型的评估方法和不同的数据集。在 LangSmith 网站上查找不同类型智能体测试的示例。
任何评估系统的目标都是为了提供一个强大的框架来评估你的智能体。LangSmith 使运行评估和提供对单个和集成组件性能的详细洞察变得容易。使用 LangSmith,你可以更好地为 ChatGPT 应用的生产环境需求做好准备,确保它提供高质量、可靠的响应。
记住——成功开发 AI 的关键是持续测试和改进。评估不是一个一次性任务,而是开发周期中的常规部分。在下一节中,我们将考虑应用监控。
使用 LangSmith 进行生产中的应用监控
监控任何基于 LLM 的应用都是一项挑战,直到 LangSmith 的发布,很难全面了解 LangChain 应用底层的运作情况。对应用进行详细监控对于保持运行顺畅至关重要,LangSmith 提供了众多功能来实现这一点。
LangSmith 的高级监控功能
LangSmith 的监控系统通过允许开发者配置和管理跟踪,使得对生产应用的有效监督成为可能。这个系统中的关键特性是针对优化生产过程中数据收集和使用的特性。
跟踪和数据管理
LangSmith 的跟踪和管理能力通过采样提供选择性数据点记录,通过元数据改进数据组织,并通过反馈集成提供关键见解:
-
采样:在生产中至关重要,此功能允许仅记录数据点的子集,以有效地管理数量和相关性。
-
元数据:将元数据附加到运行中增强了过滤和分组数据的能力,便于进行更有针对性的分析
-
反馈:整合用户反馈有助于突出显示重要数据点,将注意力集中在最需要的地方
监控工具
LangSmith 提供了一套全面的监控工具,旨在帮助监控您的应用。以下是关键功能:
-
过滤功能:用户可以使用高级过滤选项深入到特定的运行中,这些选项包括按名称、元数据、反馈和全文搜索进行过滤。
-
监控图表:在项目仪表板上的监控选项卡提供了各种指标的视觉表示,例如跟踪延迟、每秒令牌数和成本。这些图表支持时间序列分析,并可以深入到具体数据点以进行详细的跟踪表,有助于调试。
-
元数据分组:这允许在同一图表中并排比较不同的应用程序版本,这对于 A/B 测试变化特别有用。
高级监控功能
LangSmith 提供其他高级功能,帮助您理解复杂的对话并自动化一些任务。
-
线程:对于跟踪是同一对话一部分的应用,LangSmith 通过元数据键提供线程化,方便地分组相关跟踪。
-
自动化:为了减少人工监督,LangSmith 的自动化可以配置为处理重复性任务。设置过滤器后,开发者可以自动化将数据发送到数据集、注释队列或进行在线评估等操作。
在 LangChain 空间中,一直缺少一个功能齐全的监控工具,LangSmith 填补了这一空白。
它作为确保您 LLM 应用稳健性能的必备工具而脱颖而出。通过提供详细的指标和实时数据可视化,LangSmith 应允许您在对话式 AI 解决方案中保持高性能、可靠性和用户满意度的高标准。
ChatGPT 和 LangChain 的替代方案
自 ChatGPT 的早期以来,不仅 LLM 技术在不断进步,而且服务提供的选择和可用性也在增加。在本节中,我们将探讨出现的各种服务提供,探索 ChatGPT 和 LangChain 之外的可行替代方案。
ChatGPT 和 OpenAI LLMs 的替代方案
去年年初,你可能会争辩说 OpenAI 的生成预训练转换器(GPT)LLM 处于一场单马竞赛中,并且很可能是你构建 LLM 驱动项目的首选。如今,许多公司都在竞相发布最佳模型,导致可供选择的 LLM 数量不断增加,无论是开源的还是封闭的,都可以创建一个对话式 AI 系统。LLM 军备竞赛仍在继续;让我们看看一些例子,值得注意的是,这并不是一个详尽的列表:
-
Meta: Meta 提供的 Llama 模型系列是流行的 LLM。最新的模型,Llama 3 模型,具有 8B 和 70B 参数,在与其他 LLM 的测试中表现出令人印象深刻的表现,并且以多种方式提供。
-
Anthropic: Anthropic 以其专注于构建可靠和可解释的 AI 模型而闻名。他们的主要模型 Claude 旨在增强安全性和可控性,旨在减少有害或误导性的输出。Anthropic 强调道德 AI 开发,利用从人类反馈中进行强化学习(RLHF)等技术来微调模型响应,确保它们与人类价值观和安全期望紧密一致。
-
AI21: AI21 提供访问 Jurassic-2 和 Jamba transformer 模型。Jurassic-1 是 AI21 Labs 的旗舰模型系列。Jurassic-1 有多种尺寸,从小型模型适合成本效益的应用到可以生成更复杂和细微文本的非常大的模型。这些模型旨在执行广泛的任务,从回答问题和总结文本到生成内容和代码。
-
Google: Google 从不错过提醒我们他们发明了 transformer 架构,并创建了强大的模型,如 PaLM 2 和最近推出的 Gemini 系列。Gemini 系列,尤其是最新的 Gemini 1.5,以 1 百万 token 的巨大上下文窗口和据说更好的性能推动了边界。1.5 系列也提供 3 种尺寸:Ultra、Pro 和 Nano。Google 还将 Bard 更名为 Gemini。到目前为止,我所看到的 Gemini 性能与 GPT-4 模型相当。
-
Cohere: Cohere 专注于自然语言理解和生成。Cohere: Cohere 专注于 NLU 和自然语言生成(NLG)。他们的模型设计用于各种应用,如内容生成、摘要和语义搜索。Cohere 的模型以其用户友好的 API 和强大的安全特性而闻名,适用于数据隐私和应用程序完整性至关重要的企业环境。
-
MistralAI: MistralAI 将自己定位为专注于企业级 LLM,并拥有保护隐私的基础设施。他们提供开源模型:Mistral 7B、Mixtral 8x7B 和 Mixtral 8x22B,这些模型可定制。它们可以在 Mistral 平台上下载或按需使用。公司还提供大型和小型优化的商业模型。
-
Cerebras:Cerebras 发布了一系列 7 个 GPT 模型,参数量从 11 亿到 130 亿不等。他们声称这是训练速度最快、成本最低的模型之一。Cerebras 还提供云基础设施用于模型训练和 Cerebras AI Model Studio,这是一个专门用于训练和微调 LLMs 的平台。
测试这些模型的一种很好的方法是使用 Hugging Face Chat,在这里你可以从流行的 LLMs 中选择来回答你的问题。你会发现,除非被提示做其他事情,否则所有 LLMs 的回答都有一种细微的风格差异。这个观察是从我与 VUX World 的杰出人物凯恩·西蒙斯(Kane Simms)的对话中得出的。
有证据表明,LLMs 之间的差距正在缩小。最近的表现比较表明,不同 LLMs 之间的差距正在缩小。例如,Claude 3、GPT-4 和 Gemini Ultra 在多项选择题和推理等任务中取得了相似的成绩。有趣的是,一些较小的模型,如 Mixtral 和 Llama2,在某些领域(例如推理)的表现优于较大的模型,这表明并非总是最大的模型就是最好的。
我们在这本书中大量使用了 LangChain。让我们在下一节中看看 LangChain 的替代方案。
LangChain 的替代方案
我非常喜欢 LangChain,现在 LangSmith 已经完全支持它在生产中监控和运行你的应用程序,这是一个稳固的平台。然而,LangChain 并不是适合每个人,在做出决定之前有许多定义因素在起作用。还有很多其他选择。你可以用代码构建自己的应用程序并直接与 LLM API 交互,同时仍然使用 LangSmith 进行监控。你也可以使用像 企业生成式 AI 大型语言模型(GALE)这样的东西:Kore.ai 的新生产力套件,这是一个无代码解决方案,用于使用最新的 LLM 模型。
或者,还有像 LlamaIndex 这样的选项。LlamaIndex 是一个针对在 LLMs 上构建的应用程序进行优化的全面数据框架。
它支持大量数据格式,例如 APIs、PDFs、文档和 SQL 数据库,允许你摄取、组织和结构化你的数据。该平台提供高级检索界面和创建提示链的能力,以创建 LLM 应用程序和评估能力,允许你创建高级 RAG 系统。
LlamaIndex,凭借其支持的 Python 和 TypeScript SDKs 以及一个充满活力的社区提供的丰富资源,例如连接器、工具和数据集,展示了在 LLM 领域出现的创新解决方案。这种 LLM 专用服务的增长标志着人工智能领域的一个重大趋势,我们将在下一节中进一步探讨。
观察不断增长的 LLM 领域
自从去年 ChatGPT 发布以来,LLM 领域的世界发生了巨大变化,了解这一点对于您可能为 ChatGPT 或 LLM 项目做出的任何技术决策都至关重要。
访问 LLM 的方式越来越多,这可以主要分为以下图表中展示的四种方法:

图 9.4 – 与 LLM 交互的不同方式
让我们来看看访问和利用 LLM 的四种不同方式的优缺点:
-
llama.cpp库。尽管免费使用,但托管和运营这些模型的相关成本可能相当高,需要专业知识。随着使用量的增加,这些费用和持续维护的需求往往会增加。 -
LLM 编排:提供专业云基础设施以托管和训练模型,同时提供一种简单的方式来编排和公开这些模型以供使用,以及针对特定领域专业知识和使用案例进行微调的手段。大多数云服务提供商(CSP),如 Google Cloud、Amazon Web Services(AWS)和 Microsoft Azure,提供基础设施即服务(IaaS)以托管您的模型。这可能很昂贵,但提供了在不承担基础设施成本的情况下利用开源 LLM 的能力。还有一些有前景的平台,允许您创建由 LLM 驱动的端到端对话助手,例如 Quiq。
-
通过 API 使用 LLM:这是组织将 LLM 功能集成到其应用程序中最常用的方法。API 为使用 LLM 开发应用程序提供了一条直接的路径。然而,使用这些 API 也带来了一些挑战,例如成本影响、对数据隐私的担忧、推理延迟问题、速率限制、灾难性遗忘的风险以及模型漂移。
-
LLM 用户界面:无需过多介绍,ChatGPT、HuggingChat、Cohere Coral 和 Gemini 等界面直接为用户提供对话体验,并已成为许多人日常生活的一部分。这些界面旨在提供与 LLM 互动的最高效和用户友好的方式。它们通常还使包括其他来源的上下文信息以及通过管理历史对话和利用外部工具进行聊天个性化变得容易。
这些与 LLM 交互的方法各自提供了不同的优势,并带来了独特的挑战,因此选择取决于您的用例、定制需求、技术专长、资源可用性和预算限制。最后,在下一节中,我们将简要考虑一种越来越受欢迎的新型模型:SLM(小型语言模型)。
小型语言模型(SLM)的增长
当考虑围绕 LLM 技术的复杂性以及最新和最伟大 LLMs 巨大收益放缓时,引入 SLM 是有意义的,SLM 的受欢迎程度一直在增长。SLMs 正在挑战“越大越好”和“大小不是一切”(请原谅这个双关语)的观念。模型大小可能不是性能的唯一决定因素,而诸如架构、训练数据和微调技术等因素也起着重要作用。
LLMs 是否达到了极限?
当性能趋于平稳时,这引发了一个问题:LLMs 是否达到了极限?当 ChatGPT 首次发布时,我们都对它的广泛知识感到震惊,但随后的迭代并没有那么革命性。当涉及到训练数据时,随着使用新 GPT 版本的新鲜训练数据的采用,已经取得了一些改进,但事实上,除非模型定期训练,否则 LLM 数据将始终存在局限性,这似乎不太可能。
尽管 LLMs 具有令人印象深刻的性能,但它们也伴随着显著的缺点,我在本书中已经进行了概述。这里简要回顾一下。它们需要大量数据和参数进行训练,导致高计算能力和能源消耗。这导致了高昂的成本,使得小型组织和个人的核心 LLM 开发难以触及。此外,LLMs 由于涉及的工具和技术复杂,以及从训练到部署的漫长周期,给开发者带来了陡峭的学习曲线,这可能会减缓实验和创新工作。
其他挑战包括训练数据中的偏差以及幻觉问题、缓慢的推理性能、高令牌成本,以及如果您打算消费和从敏感数据中推断,严重的安全影响。将 LLMs 比作砸坚果的锤子,突显了庞大的互联网知识对于许多对话式 AI 用例可能并非必要。这引发了以下问题:对于有效的对话式 AI 项目,哪些品质真正重要,SLM 能否满足这些要求,甚至比 LLMs 提供优势?
SLMs 的登场
从本质上讲,SLM(小型语言模型)是大型 AI 模型的紧凑版本,旨在理解、解释和生成人类语言。SLMs 为 LLMs(大型语言模型)提供了一个简化的替代方案。由于参数较少和设计简单,它们需要的数据、训练时间和计算能力更少——通常只需几分钟或几个小时。这使得 SLMs 更高效,并且更容易在现场或小型设备上实施,以及针对特定用例进行微调的小型数据集。
SLMs 与 LLMs——关键区别
为了更清晰地了解 SLMs,直接将它们与 LLMs 进行比较是有帮助的:
-
规模和范围:SLMs 被设计成紧凑和高效,使其适合特定领域和任务。它们在较小的数据集上训练,允许更快的训练和推理时间以及针对性的知识。另一方面,LLMs 更大、更全面,在广泛和多样化的数据源上训练。LLMs 捕捉广泛的语言模式,在生成关于几乎所有主题的高度连贯和上下文相关的文本方面表现出色。
-
训练时间和计算资源:由于规模较大,LLMs 需要更多的计算资源和更长的训练时间。SLMs 由于其较小的规模和更简单的架构,在资源有限或需要快速部署的场景和预算中更为实用。
-
领域专业知识:虽然这两种模型都可以针对特定领域进行微调,但由于 SLMs 规模较小且推理时间更快,因此在需要特定领域专业知识的情况下,SLMs 通常更有效率。SLMs 还可以在更小的数据集上训练。一个训练良好的特定领域 SLM 在与在上下文级别提供领域知识的 LLM 相比时,可能表现足够好。
-
多功能性和成本:这完全取决于使用场景,但 LLMs 由于其更广泛的知识库,在内容生成、翻译和理解复杂查询方面表现出色。然而,经过适当微调的 SLMs 可以在计算成本的一小部分内实现与特定对话任务相当的性能。SLM 不一定需要理解每个主题。SLMs 可以被训练在与特定领域特定知识的基础上与客户互动,提供定制解决方案并改善用户体验。这可以通过使用专业训练数据微调 SLMs 来实现,并且可能更加直接。此外,微调 SLMs 需要很少的资源。具体的硬件要求以及相关的成本取决于模型大小、复杂性和数据集需求,但这些可能要少得多。
SLMs 的优势
SLMs 的一个关键好处是它们适合特定应用。它们专注的范围和减少的数据需求使它们非常适合微调特定领域或任务。这种定制化使公司能够创建满足其特定需求的 SLMs,例如情感分析、命名实体识别(NER)或特定领域的问答。
SLMs 还提供了增强的隐私和安全。它们较小的代码库和简单的架构使它们更容易审计,不太可能包含漏洞。这对于医疗保健和金融等行业处理敏感数据来说特别有吸引力。SLMs 降低的计算需求还使本地处理成为可能,从而进一步提高了数据安全性。
SLMs 在其特定领域内不太容易出现幻觉。它们在目标数据集上的训练有助于它们学习相关模式、词汇和信息,减少了产生无关或不一致输出的可能性。由于参数较少,SLMs 也不太可能捕捉和放大训练数据中的噪声或错误。
SLMs 的缺点
SLMs 尽管具有许多优点,但在某些情况下观察到其性能下降。一个关键限制是它们对上下文的理解减少,与大型模型相比,整体知识库不够全面。这使得 SLMs 在需要深入理解或广泛上下文意识复杂任务时效果较差。此外,由于 SLMs 尺寸较小且训练数据集聚焦,它们在生成连贯流畅的文本方面可能存在困难。例如,参数较少的模型通常在保持较长文本的连贯性或在更复杂的交互中表现出局限性。这可能会限制它们在需要高质量响应且在技术或复杂领域进行对话的应用中的效用。
SLMs 的一些示例
Phi-3 是微软最新推出的轻量级 Mini 3B 和 14B 中端最先进的开放模型家族,在基准测试中获得了非常令人印象深刻的性能结果。谷歌的 Gemma 是一系列专为效率和用户友好性设计的 SLMs。与其他 SLMs 一样,Gemma 模型可以在日常设备上运行,无需专用硬件。Cerule 是一款强大的图像和语言模型,将 Gemma 2B 与谷歌的Sigmoid 损失函数用于语言-图像预训练(SigLIP)相结合,利用高效的数据选择技术。这使得 Cerule 非常适合边缘计算用例。另一个例子是 Llama 2 7B 和现在的 Llama 3 8B,它们不需要大量的硬件要求,还有 Stable Beluga 和 Hugging Face 的 Zephyr。许多这些模型都可在 Hugging Face 和 LLM API 提供商等平台上找到,以及像 Google Vertex AI 这样的云服务。这些模型都是针对对话用例进行训练的。尝试这些模型的一个好方法是使用 Ollama,这是一个轻量级框架,用于在本地机器上运行模型。
SLMs 的变革潜力
SLMs 有潜力使人工智能访问民主化并推动创新。它们更快的开发周期和更高的效率使得成本效益高、目标明确的解决方案成为可能。在边缘部署 SLMs 为金融、娱乐、汽车、教育、电子商务和医疗保健等领域的实时、个性化、安全应用打开了可能性。
使用 SLM 的边缘计算通过本地处理数据来提高响应时间、数据隐私和用户体验,这是一个吸引人的解决方案,并且能够纠正企业希望在更敏感领域应用 LLM 时的许多缺点。这种去中心化的 AI 方法有潜力改变企业和消费者与 LLM 技术互动的方式。
通过将 SLM 暴露于专门的训练数据并对它们的能力进行微调,它们可以在训练 LLM 成本的一小部分内产生针对对话用例的准确和相关的输出。它们通常能够提供与 LLM 相似的对话能力并取得很好的结果。如果你正在寻找使用 LLM 技术但担心其缺点,考虑一个 SLM 模型可能是一个明智的选择。
然而,也存在局限性:虽然 SLM 提供了显著的好处,尤其是在效率和成本方面,但它们的适用范围有时会根据预期的用例而受到限制。
尽管存在任何缺点,它们都提出了一个有力的论点。随着特定模型平台即服务(PaaS)和模型训练平台的日益可用,探索和测试 SLM 能力的便利性越来越高,因此投入时间和精力去研究是非常值得的。
接下来该往哪里走
在这本书的整个过程中,我们专注于利用 ChatGPT 和 LLM 作为工具和技术来创造引人入胜的对话体验。自从我们开始这段旅程以来,LLM 的领域经历了巨大的变革,这得益于 LLM 技术的持续进步。尽管 ChatGPT 在发布时是一项突破性的创新,但现在它只是更大、更灵活的 LLM 生态系统中的一个组成部分。
我在对话式人工智能领域工作了多年,早在 ChatGPT 之前,就有幸参与并投入生产了许多基于 NLU 的应用。这让我对对话式人工智能的挑战有了深刻的理解,包括 LLM 需要做什么来克服这些挑战,以及它们是否能够做到。目前有数千个由 NLU 驱动的对话式人工智能应用正在运行,其中许多你可以认为可以被 ChatGPT 应用所取代。或者至少它们的一些元素可以被取代,这通常取决于现有平台的底层技术和供应商构建利用 LLM 技术以及传统基于意图的系统能力的速度和效率。
就像所有人一样,我最初对 ChatGPT 的发布和技术的无限可能性感到震惊。然而,我一直试图对技术的采用、其局限性和风险保持现实态度。当然,这都取决于具体的应用场景。如果你想深入讨论自己的数据,那么 RAG 系统在对话式人工智能领域是一个巨大的进步,但在交易性角色中,适度的克制是明智的。
我个人认为,向前发展的最大转变在于为更复杂的应用场景构建交易性 LLM 驱动应用的可行性。使用 LangChain 等框架创建这些应用已经成为一个更加现实的目标,但仍然不是一件简单的事情。随着专门用于测试和监控 LLM 行为的支持工具(如 LangSmith)的出现,部署交易性机器人的风险得到了缓解。这为考虑用 LLM 的灵活性和适应性来取代传统的基于意图的系统打开了大门。
LLM 的未来在于多模型方法。我们可以在 LLM 管道内利用适合特定任务的模型。想象一下,一个特定的 LLM 在 LangChain 应用中充当代理执行者,利用其他专业模型的优势来完成特定任务。此外,LLM 推理能力的进步也提供了令人兴奋的潜力。
然而,在规划 LLM 应用时,模型选择仍然是一个复杂的决策。使用案例、底层数据、领域类型、成本、安全考虑和可维护性等因素在规划生产时都起着至关重要的作用。这些因素突出了探索 ChatGPT 之外替代方案的重要性。SLMs 为特定场景提供了一个有趣的选项,尤其是在拥有大量对话日志和历史使用数据的长期对话式人工智能系统中,这些数据可以用于微调。
LangChain 生态系统仍然是构建 LLM 驱动应用的强大平台。随着针对几乎所有需求的集成和工具,我们只是触及了其潜力的表面。你可以利用不断增长的向量存储和服务,以及像 Tavily Search 这样的专业工具,来增强我们 LLM 应用的能力。有许多 LangChain 模板的例子,我建议这些是查看更复杂对话用例的好地方。
同样重要的是要承认将大型语言模型(LLMs)投入生产所涉及的风险。它们具有随机性,即输出中的固有随机性,可能导致不可靠的结果。这需要仔细规划和稳健的测试方法,尤其是在关键应用中。
OpenAI 不断通过其 GPT 模型突破边界。我们已经见证了从 GPT-3.5 到 GPT-4 及其针对聊天应用优化的 Turbo 版本的演变。最新的 GPT-4o,于 2024 年 5 月发布,通过将它们特定模态的模型整合到一个新的模型中,集成了多模态能力。结果是,它能够以类似人类的响应速度处理文本、音频、图像和视频输入,实现完全的多模态对话交互。以前,GPT 在语音交互中平均存在 3-6 秒的延迟问题。
当 OpenAI 不断通过令人叹为观止的能力增强其模型,包括多模态、多语言、扩展的上下文窗口、提高的准确性和改进的 LLM 推理时,他们还明智地保持了 API GPT-4o 的成本在较低水平,并将其包含在 ChatGPT 的免费版本中,使这项技术能够惠及更广泛的受众。OpenAI 不断通过令人叹为观止的能力增强其模型——多模态、多语言、扩展的上下文窗口、提高的准确性和改进的 LLM 推理——同时他们也明智地保持了 API GPT-4o 的成本在较低水平,并将其包含在 ChatGPT 的免费版本中,使这项技术能够惠及更广泛的受众。
我们最初所了解的景象已经发生了巨大的变化,反映了 LLM 技术的快速演变。LLM 生态系统持续繁荣,为开发者提供了越来越多的模型和简化工具,以构建和利用其能力。随着技术的持续发展,构建变革性对话体验的可能性也将随之增加。拥抱实验,探索不断扩大的 LLM 生态系统,并保持在这次激动人心的革命的前沿。
摘要
在本章中,我们探讨了将 ChatGPT 驱动的系统从原型验证过渡到完全运营的生产环境所涉及的关键考虑因素和挑战,突出了部署 LLM 驱动的应用程序,尤其是 RAG 系统所涉及的显著责任和风险。到目前为止,你应该已经理解了采取稳健的安全措施以防止不适当回应并确保可靠性的重要性。我们回顾了一个由于内容监管不力和系统控制不足而导致聊天机器人故障的事件,强调了适当安全措施的需求。
本章的大部分内容都致力于讨论 RAG 系统在生产过程中面临的具体挑战。我们还探讨了评估 LLM 应用的全面策略,强调了对广泛标准的持续验证的必要性,以确保系统的有效性和可靠性。我希望能通过介绍一个评估示例,让您对 LangSmith 这样的工具的重要性有一个坚实的理解,并为您构建稳健的评估打下良好的知识基础。评估和监控工具为管理、测试和改进 LLM 应用提供了一种结构化的方法,它们需要在您的 ChatGPT 项目中扮演重要的角色。
为了提供一个平衡的视角,在本章中,我们了解了一些替代的 LLM 服务提供者和模型,包括 LangChain 和 ChatGPT 的替代品,并反思了对话式 AI 技术快速发展的格局。这一领域已经取得了相当大的进展,您可能会对根据具体用例和运营需求选择正确模型的重要性有所把握。我们还探讨了 SLMs 作为传统大型 LLM 的更易于管理和专业化的替代品的潜力。
最后,我们探讨了下一步该怎么做,这取决于您和您的组织在 LLM 旅程中的位置,无论是继续实施 LLM 功能,将您的对话式 AI 项目过渡到生产,还是开始绿色场 LLM 应用。
我们在这里涵盖了大量的内容,但希望这能帮助您克服挑战,提出关键问题,以便您能够成功利用 LLM 技术向前发展。
进一步阅读
以下链接是本章节中精选的资源列表,旨在帮助您:
-
LangChain:
chat.langchain.com -
LangChain 模板:
templates.langchain.com -
LangSmith:
docs.smith.langchain.com -
LlamaIndex:
www.llamaindex.ai -
HuggingChat:
huggingface.co/chat/ -
ChromaDB:
docs.trychroma.com/ -
LLMs:
www.together.ai -
Ollama:
ollama.com -
Quiq:
quiq.com

浙公网安备 33010602011771号