InfoQ 推荐 ( ) • 2024-04-18 08:23

在2023年初,ChatGPT"的浪潮风靡全球。对于这项技术能做什么、不能做什么,人们既恐惧又兴奋。就我个人而言,我对它感到非常惊奇,而且几乎每天都会使用ChatGPT来帮助我实现自己的想法,它的速度之快超出我的想象。

 

过去的几个月,我一直在学习OpenAI"的beta版API,以便于将ChatGPT风格的助手(也叫聊天机器人)集成到我们自己的应用程序中。坦白讲,在任何应用程序中添加自然语言接口"都非常容易,这让我大受震撼(我的样例是web应用程序,但是你完全可以将其集成到原生应用中)。

 

本文将介绍我所学到的知识,希望这能够说明将其集成到自己的应用程序中是多么容易。我预期你是一名开发人员,这样能够从本文中获得最大的收益,但是如果你仅仅掌握了一些开发技能,你会惊讶地发现,这其实也没有太大的难度。

 

在本文的最后,我们将介绍一些关于如何利用聊天机器人和自然语言接口提升业务能力的想法。

实时样例和示例代码

本文提供了实时样例和可运行的示例代码。你可以尝试实时演示,看一下它的运行效果,而无需在本地运行代码。不过,要运行代码也不难,下一步我们就介绍如何基于代码自己来运行它。

 

在阅读下面的章节时,你可能需要在VS Code"(或其他编辑器)中打开示例代码,这样你就可以跟随我们的进度,在上下文环境中查看完整的代码。

 

在本文中,我们讨论了两个使用场景的样例:

 

使用聊天和语音控制地图:

实时样例"示例代码"

从自定义数据源提问:

实时样例"示例代码"

前置条件

要实践并运行示例代码,你需要有一个OpenAI账户,请在此"进行注册。

构建基本的聊天机器人

我们从最基本的聊天机器人开始。这需要在应用程序中添加一个消息用户界面,以便于用户与聊天机器人对话。这本身并没有太大的用处(因为直接使用ChatGPT也是很便利的),但这一步是实现更复杂聊天机器人的必要步骤。

 

你可以在这里"找到聊天机器人的完整代码。

 

为了亲身实践并自行运行代码,请使用如下命令将仓库克隆到你的电脑上:

git clonehttps://github.com/ashleydavis/chatbot-example.git

 

在图1中你可以看到聊天机器人的结构。我们有一个前端,它加载后会创建一个聊天线程。然后,我们创建一个消息循环(message loop),允许用户向聊天机器人输入消息,聊天机器人则以自己的消息作为响应。

 

需要注意的是,我们必须在前端和OpenAI REST API之间放置自己的后端服务器。如果前端能够直接与OpenAI对话,那就更简单了,但令人遗憾的是,这样是不行的,因为我们必须向它发送OpenAI API秘钥。如果我们直接从前端代码中发送的话,就无法确保其私密性了。

 

我们的API秘钥必须保持私密,所以不能在前端代码中使用。将后端置于前端和OpenAI之间,能够让我们隐藏API秘钥。不过,别以为这样会使得结构变得特别复杂,我们的后端非常简单,主要就是将前端的HTTP请求转发给OpenAI REST API。

图1 OpenAI聊天机器人的基本操作

 

注册OpenAI之后,你需要进入API秘钥页面,创建API秘钥(或者使用现有的秘钥),如图2所示。在运行聊天机器人后端之前,我们需要将其设置为环境变量。

图2 获取OpenAI API秘钥

对于前端,我使用了Tailwind Components"的开源UI框架,如图3所示。非常感谢Porter-smith将其提供给大家使用。这个聊天机器人的UI是使用HTML和Tailwind构建的。

图3 获取聊天机器人的UI

 

回到OpenAI的仪表盘,创建并配置一个assistant,如图4所示。请注意这里的assistant id,在运行聊天机器人的后端时,这是我们需要以环境变量的形式设置的另一个配置细节。

 

请同时注意图4中的Test按钮。你可以尝试点击它,这样就能在不离开OpenAI仪表盘的情况下试用聊天机器人。这一点非常重要,因为你可能会花费很多的时间编写前端和后端代码,却发现聊天机器人并没有达到你的要求。你应该在这里对聊天机器人进行尽可能多的测试,确保它适合你的业务和用户,然后再花费时间将其集成到应用程序中。

图4 创建OpenAI assistant

在获得API秘钥并配置好OpenAI assistant之后,你就可以为聊天机器人编写代码了。为了节省时间,你可以直接运行我已经准备好的代码"。关于如何运行后端和前端的说明,请参阅readme文件。请确保你已经将OpenAI API密钥和assistant ID设置为后端的环境变量。

 

示例项目的前端使用了JavaScript和React,后端使用了JavaScript和Express。选择哪种语言和框架并不重要,无论你如何构建,它看起来大致都是相同的,需要做的事情基本也都一样。

 

图 5展示了我们如何在页面加载时创建新的聊天线程。前端向后端发出HTTP POST请求。后端使用来自npm的OpenAI代码库创建聊天线程。这个库简化了OpenAI REST API的使用。

图5 创建聊天线程

 

当聊天机器人的用户输入信息并点击Send按钮时,我们将通过HTTP POST向后端提交请求,如图6所示。然后,我们在后端调用OpenAI库中的函数来创建消息并运行线程。运行线程会让人工智能“思考”我们发送给它的信息,并最终做出响应(目前响应速度还比较慢,希望OpenAI今后能在这方面有所改进)。

 

图6 向聊天线程添加信息

 

然后,前端必须接收来自AI的响应,并将其展示给用户。在这里,我们通过轮询来接收响应。如图7所示,我们会定期向后端发出HTTP POST请求。后端会调用OpenAI函数来检索消息和当前运行的状态。这样,我们就可以在前端展示消息了(将其设置为React的状态),如果运行已完成的话,我们就可以终止轮询了。

图7 检索聊天信息

这就是一个基本的聊天机器人。我们总结一下最重要的组成部分:

在页面加载时创建聊天线程;当用户输入信息时,将其提交给OpenAI;当AI生成响应时,将其显示给用户。

为聊天机器人添加自定义的知识

这样一个基本的聊天机器人本身并没有太大的用处。除了ChatGPT用户界面所能提供的内容之外,它并不能为我们带来更大的价值。但是,既然有了这个基本的聊天机器人,我们就可以通过各种方式对它进行扩展和定制。

 

第一种方法是为聊天机器人添加自定义的知识。这一点很容易实现,我们甚至不需要为聊天机器人添加任何代码。在OpenAI Playground"中,导航至你的assistant,启用Retrieval,然后点击Add按钮以上传PDF和CSV文件,如图8所示。OpenAI会扫描你的文件,并将其中包含的知识赋予聊天机器人。

图8 在OpenAI中向assistant上传文件

 

此时,我们可以直接在OpenAI Playground中测试assistant。同样,我建议在为聊天机器人编写代码之前进行测试。这可以让你在投入大量的时间之前预先进行测试,看看助手是否满足你的需求。你可以试着问一些与上传的PDF文件相关的问题。在我的样例中,我上传了一份PDF格式的简历,这样我可以问一些这样的问题,比如“Ashley具有哪些技能?”。聊天机器人会以简历中描述的技能摘要作为答复。请在实时演示"中亲自体验一下。

 

严格来讲,这就是让聊天机器人自定义知识所需的全部过程,你可以定义你自己、你的公司、你的产品或其他任何的知识,只要它能够使用PDF或CSV文件记录即可。

自定义聊天机器人的行为

聊天机器人的下一步扩展就是让它能够在应用程序中执行特定的任务,这是无法在OpenAI Playground中测试的。

 

例如,假设你正在创建一个电子邮件的客户端,比如希望对外暴露“发送电子邮件”和“检查新邮件”的功能,这样用户就可以通过与聊天机器人的对话来调用这些操作。在我的这个版本的OpenAI Wunderlust样例中,你可以与地图进行互动,提出像“告诉我巴黎在哪里”和“标出一个与埃菲尔铁塔拍照的好位置”这样的问题。你可以在Wunderlist的实时样例"中实验一下,效果非常棒!

 

Wunderlust示例的代码请参见此处"。

 

如果你想继续实践并亲自运行代码,请克隆代码仓库到你的电脑上:

git clonehttps://github.com/ashleydavis/wunderlust-example.git

 

请按照readme文件中的说明运行wunderlust-example的前端和后端。

 

我们通过允许聊天机器人调用代码中的函数来扩展它的功能。在样例中,我创建了一个基于地图的应用程序(灵感来源于OpenAIs Wunderlust样例),可以通过函数来更新地图(使其处于中心位置并缩放比例)以及在地图上添加标记。你可以在图9中看到这些函数的JavaScript实现。

图9 创建函数以暴露应用程序的功能

 

聊天机器人只有知道这些函数,才能调用它们。所以,我们需要为每个函数配置元数据,以便于告诉OpenAI这些函数的作用。元数据包括函数的名称、函数功能的描述以及输入和输出的描述。你可以在图10中看到添加到OpenAI assistant中updateMap函数的JSON描述。

图10 以JSON格式描述我们的函数

 

通过这种方式描述应用程序的特性,OpenAI就能够根据用户的自然语言命令调用这些特性了。但我们依然需要编写一些代码,以便于允许AI调用这些函数。你可以在图11中的聊天机器人消息循环中看到,我们如何响应聊天机器人的“required_action”状态,从而知道聊天机器人想要调用一个或多个函数的。

图11 在聊天循环中集成函数调用

 

然后,我们必须枚举聊天机器人想要调用的函数列表,调用这些函数,收集它们的输出,然后通过HTTP POST将函数输出提交到OpenAI后台。在图12中,你可以看到这是如何实现的。

图12 调用请求的函数并将结果提交给OpenAI

 

让聊天机器人在我们的应用程序中调用函数需要一些额外的工作。但现在我们有了一个可扩展的设置,可以继续为聊天机器人添加更多的功能,让越来越多的应用特性可以通过自然语言接口来使用。

启用语音控制

为了给用户带来更好的体验,我们现在要继续扩展聊天机器人,让用户可以用语音与聊天机器人交互。你可能已经注意到Wunderlust示例"中的麦克风按钮,如果你还没有注意到的话,现在可以尝试一下。点击按钮并与聊天机器人对话。试着说“请为我展示世界上最高的山峰”,聊天机器人会将地图中心放在珠穆朗玛峰上。

 

凭借现代web浏览器的音频捕获功能再加上OpenAI的语音转录服务",要实现这个过程非常简单。

 

首先,我们必须征得用户同意,才能在浏览器中捕获音频。你可以在图13中看到如何实现这一点。

 

图13 请求允许在浏览器中记录音频

 

获取音频流后,我们可以据此创建一个MediaRecorder对象。如图14所示,我们可以通过处理ondataavailable事件来收集音频流传入的音频块(chunk)。

图14 使用媒体记录器捕获音频

 

当用户停止录音时,就会触发onstop事件。此时,我们会汇总音频块,并通过HTTP POST将其提交给后端。然后,后端使用OpenAI将音频转录为文本。文本将作为用户的下一条消息添加到聊天线程中。你可以在图15中看到其运行原理。

图15 提交音频进行转录并添加到聊天线程中

 

现在,我们有了一个聊天机器人,并且为它灌输了自定义的知识,它可以代表我们调用操作,我们可以通过说话而不是打字向它发出指令。当然,OpenAI完成了所有繁重的工作。在完成构建应用程序的初期艰苦工作后,添加一个聊天机器人并不难。

自然语言接口是未来的趋势

我们看到,在应用程序中添加自然语言接口是非常容易的,而且我们可以将其用于许多业务场景中:

将聊天机器人作为我们组织的代表,允许公众询问有关我们、我们公司、我们产品或活动的问题,我们只需向聊天机器人提供已有的文档即可。设想一下,在一个活动管理应用程序中,用户会问“我要几点出门才能准时到达John Smith上午10点主持的会议?”。无论是打字还是说话,我们都能让客户用他们的母语与应用程序进行交互。我们可以让客户自由选择与软件交互的方式。公开应用程序的所有特性意味着,用户不再需要在互联网上搜索如何完成他们想做的事情。他们只需描述自己想要什么,聊天机器人可能需要在消息线程中往返几轮以明确用户的意图,但在聊天机器人的帮助下,他们可以在不离开应用程序的情况下找到想要的功能。让聊天机器人访问所有功能,能够让它以意想不到的组合智能地使用这些功能,从而弄清用户究竟想要什么。我对一些客户使用软件的非常规方式已经感到非常惊讶了,添加聊天机器人后,客户的创造力肯定会更上一层楼。查询我们的应用程序以获取非常具体的信息,再次假设在活动管理应用中,用户可能会问,“和John一起演讲的另一位发言人是谁?”。通过CSV格式的数据文件向聊天机器人暴露应用程序中的所有数据之后,用户就可以进行查询数据分析,比如“给我生成一张图表,我想比较会议所有环节的持续时间”。如果你已经尝试将CSV数据文件上传到ChatGPT,并要求它制作图表和分析数据的话,那么你应该已经知道这有多么强大了,而且现在还只是初期阶段!它无疑将改变我们与数据交互的方式。

 

鉴于在应用程序中添加聊天机器人的便利性和它的实用性,我们所有最重要的应用程序中都将出现新一波的聊天机器人。我认为,在未来,语音控制将变得普遍、快速和准确,并且能够帮助我们在与软件交互时实现新的创造力。

 

你可以想象,当语音控制变得无处不在时,语音界面将内置于我们的操作系统中。实际上,根本不用想象,移动设备中已经内置了语音界面。但未来的一个关键区别是,应用程序将暴露自己的功能,让我们可以口头执行命令和进行查询,不仅如此,我们还能在不同的应用程序之间拼接任务和协调活动。像“我如何才能准时赴约?”这样的查询将会涉及到日历、时钟和地图之间的交互。

 

整个愿景唯一的问题在于,这些聊天机器人需要连接互联网才能运行。这一点需要改变。我衷心希望它们能离线运行。我们的大型语言模型很大,可能无法在本地设备上运行,但这一点在未来也并非一成不变。随着模型的优化和规模的缩小,以及设备功能的不断增强,我们最终应该能够在本地而不是云端运行AI模型。当我写下这些文字时,我正在为周末的停机做准备。我期待着能够断开连接和戒掉对网络的依赖,但这并不意味着我不会想念我的智能好友ChatGPT。

原文链接:

Adding a Natural Language Interface to Your Application"