skip navigation
skip mega-menu

使用ChatGPT函数将REST接口转换为Chatbots

In this story, 我们将探索如何使用plain将旧的REST接口转换为Chatbot ChatGPT Function calling. There are lots of data centric REST API它们中的许多被用于网站的上下文中,以列出或对所有类型的数据集进行搜索. 这里的主要思想是基于现有REST接口创建基于聊天的体验. 因此,我们将在现有的REST接口上添加一个由ChatGPT提供支持的会话层,该接口在事件数据库上执行搜索.

我们还将探索如何从头创建聊天机器人UI Python based server. 因此,我们不会使用任何预构建的开源库来构建UI. 服务器将用Python编写,基于web的用户界面将使用Typescript和React编写.

Event Chat — A REST Conversion Project

为了理解如何将REST接口转换为聊天机器人, we have built a small event chat application. 此应用程序接收有关即将发生的事件的用户问题,并使用有关事件的详细信息列表(包括图像和链接)回答这些问题.

Event Chat screenshot

此应用程序支持流媒体,并使用存储在数据库中的外部链接和图像进行回复.

Application Architecture

下图是我们构建的应用程序的粗略架构:

High Level components

We have the following components in this application:

  • User interface written using the React framework using Typescript. 用户界面使用web套接字与聊天服务器通信. The input is just a question about some events.

  • 一个用Python编写的聊天服务器,包含一个http服务器,它也使用websockets与客户端通信. 聊天服务器编排与ChatGPT和老式REST接口的交互,以回答用户的问题.

  • ChatGPT分析用户问题并将其路由到正确的函数,然后从REST接口接收结果以生成最终输出.

  • REST接口,用于搜索事件,并用一些额外的数据丰富检索到的事件

  • 为REST接口提供数据的PostgresSQL数据库. Actually we search using a Lucene index, but the data in it comes from a PostgresSQL database.

Application Workflow

这是处理单个聊天请求的工作流:

Single event request workflowSingle event request workflow

请注意,我们在图中省略了错误边界.

The workflow has 4 participants (pools):

  • 只提出问题并接收对问题的响应的用户.

  • 在所有其他参与者之间协调大部分操作的聊天服务器.

  • ChatGPT which receives the initial questions, 计算函数调用并接收函数调用的结果,将其格式化为自然语言.

  • REST接口——只有两个:一个是简单的搜索接口,第二个是用网页和图像的url来丰富初始响应.

Chat Server Workflow in Detail

The main actions happen in the chat server layer. 以下是全球最大的博彩平台这个池的工作流程的细节(仅限快乐路径):

  • 最初,它从客户端接收问题,通常应该是全球最大的博彩平台事件的问题.

  • 问题与函数调用请求一起发送到ChatGPT 3.5 (gpt-3.5-turbo-16k-0613)

  • If no error occurs, ChatGPT接收函数名和从用户问题中提取的参数.

  • The function specified by ChatGPT is called (at this stage, this is only an event search REST interface).

  • 结果以JSON格式从REST接口返回.

  • 对REST接口的第二次调用恰好丰富了当前数据. 这个调用的目的是用URL和图像来丰富初始搜索结果.

  • 然后第二次调用ChatGPT,并引用先前调用的函数和丰富的数据

  • ChatGPT使用自然语言处理JSON数据后进行回复. The results are actually streamed to the client. 一旦ChatGPT生成令牌,它就会通过websockets流传输到客户端.

How does Function Calling work?

Function calling 已于2023年6月推出,以帮助开发人员接收带有本地可调用函数描述的结构化JSON. 事实证明,函数调用非常适合集成 ChatGPT 使用REST接口,因为它有助于提高ChatGPT的输出可靠性.

When you use function calling with ChatGPT models like e.g. gpt-3.5-turbo-16k-0613或gpt-4-0613您最初发送消息, the specification of a function and a prompt. 在理想的场景中,ChatGPT使用要调用的函数进行响应.

在第二步中,使用提取的参数调用ChatGPT指定的函数,并以某种文本格式获得结果(如i.e. JSON).

在最后一步中,将被调用函数的输出发送给ChatGPT, together with the initial prompt. ChatGPT使用自然语言生成最终答案.

So there are 3 steps:

  1. Query ChatGPT to get the function call and its parameters. 以基于JSON的格式发送用户提示和功能规范.

  2. 使用ChatGPT提取的参数调用实际的Python函数, which are extracted from the user prompt.

  3. 使用函数输出和初始用户提示查询ChatGPT,以获得最终的基于自然语言的输出.

Example

In our case we have a function with this signature:

def event_search(

   search: str,

   locality: Optional[str] = "",

   country: Optional[str] = "",

   tags: List[str] = [],

   repeat: bool = True,

) -> str:

...

When the user asks for example:

你能在英国找到全球最大的博彩平台冥想的活动吗?

ChatGPT将在第一次调用(步骤1)中提取对应的两个函数参数:

  • search: “meditation”

  • country: “United Kingdom”

然后使用这两个参数调用函数(步骤2),然后调用返回基于JSON的响应的REST接口. 然后,这个JSON响应将与原始问题一起发送回ChatGPT(步骤3)。.

In step 3 the chat completion API will be called with 3 messages:

  • 系统消息(ChatGPT请求的后台信息)

  • The original user prompt

  • The function call with the extracted JSON

注意,最后一条消息的角色是“function”,并在变量“content”中包含JSON内容。. 为最后一次调用ChatGPT补全API提取参数的函数的完整代码可以在函数extract_event_search_parameters中找到 http://github.com/onepointconsulting/event_management_agent/blob/main/event_management_agent/service/event_search_service.py

Event Chat Implementation

The Event Chat prototype contains two applications. 第一个应用程序是用Python编写的后端应用程序,可以在这个存储库中找到:

http://github.com/onepointconsulting/event_management_agent 

第二个应用程序是用Javascript编写的前端应用程序 React:

http://github.com/onepointconsulting/chatbot-ui 

Back-End Code

后端代码由一个基于websocket的服务器组成 python-socketio (实现了一个传输协议,该协议支持客户端之间基于事件的实时双向通信)和 aiohttp (an asynchronous HTTP Client/Server for asyncio and Python).

主要的web套接字服务器实现可以在这个文件中找到:

http://github.com/onepointconsulting/event_management_agent/blob/main/event_management_agent/server/websocket_server.py 

处理用户问题的函数如下:

http://github.com/onepointconsulting/event_management_agent/blob/main/event_management_agent/server/websocket_server.py#L37 

这是在聊天服务器上触发整个工作流的功能. It receives the question from the client, 触发事件搜索并将数据流发送到客户端. 它还确保在发生错误时正确关闭流.

This method calls two other methods:

  • process_search—此方法处理传入的问题,直到通过REST API执行搜索.

  • Aprocess_stream——这个方法接收搜索结果并返回一个可迭代对象,允许流式传输到客户端.

These methods are to be found in this file: http://github.com/onepointconsulting/event_management_agent/blob/main/event_management_agent/service/event_search_service.py 

You can find the process_search method here: http://github.com/onepointconsulting/event_management_agent/blob/main/event_management_agent/service/event_search_service.py#L115 

这个方法首先包含对event_search_openai的调用,这个main函数执行对OpenAI函数调用的所有调用: http://github.com/onepointconsulting/event_management_agent/blob/main/event_management_agent/service/event_search_service.py#L53 

process_search方法还包含对execute_chat_function的调用,execute_chat_function接受OpenAI函数产生的completion_message,并使用Python的evalmethod找到函数,最后执行event_search函数: http://github.com/onepointconsulting/event_management_agent/blob/main/event_management_agent/service/event_search_service.py#L89 

这个方法处理process_search中第二次调用event_search_openai的结果. 它大部分时间通过OpenAI API生成的令牌流循环: http://github.com/onepointconsulting/event_management_agent/blob/main/event_management_agent/service/event_search_service.py#L176 

Front-End Code

The main component with the chat interface is:

http://github.com/onepointconsulting/chatbot-ui/blob/main/src/components/MainChat.tsx 

Apart from rendering the UI it uses a webhook useWebsocket, 其中包含处理基于websocket的事件处理程序的代码 socket.io-client library. useWebsockethook的实现可以在这个文件中找到: http://github.com/onepointconsulting/chatbot-ui/blob/main/src/hooks/useWebsocket.ts 

Observations

这个项目只是一个小的原型和学习经验,可以在很多方面进行改进-特别是用户界面需要一个更好和更专业的设计,缺乏像e.g. chat history.

Takeaways

如果您有允许您搜索数据的REST接口, then you should be able to build chat interfaces with them. ChatGPT的函数调用是在这些搜索界面之上堆叠聊天层的好方法. 你不需要一个非常强大的模型,你可以使用像gpt-3这样的旧模型.5-turbo-16k-0613 and still provide a good user experience.

编写自己的聊天用户界面也是一种有趣的体验,它允许您创建更自定义的实现——与使用像e.g Chainlit or Streamlit. Projects like Chainlit 为您提供了大量的功能,并帮助您快速启动和运行, 但在某个阶段限制你的设计选择,以防你做了很多UI定制. 不过,编写自己的聊天用户界面需要对Typescript或Javascript和一些UI框架有所精通, like ReactJs, VueJs or Svelte.

If you want to have chat streaming, 那么你绝对应该使用web套接字协议,它也允许你以一种相当方便的方式保持聊天内存, due to its in-built web socket session.

我的最后一个结论是,当您想要与LLM模型交互时,并不总是需要使用LangChain. LangChain 作为许多LLM api之上的一层非常方便,但代价是一个很大的依赖树. 如果你真的知道,你只会使用一个特定的LLM的一个非常具体的功能, then you should perhaps consider not using LangChain.


Gil Fernandes, Onepoint Consulting

Subscribe to our newsletter

Sign up here