在这个故事中, 我们将探索如何使用plain将旧的REST接口转换为Chatbot ChatGPT函数调用. 有很多是以数据为中心的 REST API它们中的许多被用于网站的上下文中,以列出或对所有类型的数据集进行搜索. 这里的主要思想是基于现有REST接口创建基于聊天的体验. 因此,我们将在现有的REST接口上添加一个由ChatGPT提供支持的会话层,该接口在事件数据库上执行搜索.
我们还将探索如何从头创建聊天机器人UI Python 建立服务器. 因此,我们不会使用任何预构建的开源库来构建UI. 服务器将用Python编写,基于web的用户界面将使用打印稿和反应编写.
事件聊天-一个REST转换项目
为了理解如何将REST接口转换为聊天机器人, 我们已经构建了一个小型事件聊天应用程序. 此应用程序接收有关即将发生的事件的用户问题,并使用有关事件的详细信息列表(包括图像和链接)回答这些问题.
事件聊天截图
此应用程序支持流媒体,并使用存储在数据库中的外部链接和图像进行回复.
应用程序体系结构
下图是我们构建的应用程序的粗略架构:
高级组件
我们在这个应用程序中有以下组件:
类编写的用户界面 反应 框架的使用 打印稿. 用户界面使用web套接字与聊天服务器通信. 输入只是十大网博靠谱平台一些事件的问题.
一个用Python编写的聊天服务器,包含一个http服务器,它也使用web套接字s与客户端通信. 聊天服务器编排与ChatGPT和老式REST接口的交互,以回答用户的问题.
ChatGPT分析用户问题并将其路由到正确的函数,然后从REST接口接收结果以生成最终输出.
REST接口,用于搜索事件,并用一些额外的数据丰富检索到的事件
为REST接口提供数据的PostgresSQL数据库. 实际上我们用a来搜索 Lucene索引,但其中的数据来自PostgresSQL数据库.
应用程序工作流程
这是处理单个聊天请求的工作流:
单事件请求工作流
请注意,我们在图中省略了错误边界.
工作流有4个参与者(池):
只提出问题并接收对问题的响应的用户.
在所有其他参与者之间协调大部分操作的聊天服务器.
ChatGPT接收初始问题, 计算函数调用并接收函数调用的结果,将其格式化为自然语言.
REST接口——只有两个:一个是简单的搜索接口,第二个是用网页和图像的url来丰富初始响应.
聊天服务器工作流程的细节
主要操作发生在聊天服务器层. 以下是十大网博靠谱平台这个池的工作流程的细节(仅限快乐路径):
最初,它从客户端接收问题,通常应该是十大网博靠谱平台事件的问题.
问题与函数调用请求一起发送到ChatGPT 3.5 (gpt-3.5 -涡轮- 16 k - 0613)
如果没有错误发生, ChatGPT接收函数名和从用户问题中提取的参数.
在此阶段调用ChatGPT指定的函数, 这只是一个事件搜索REST接口).
结果以JSON格式从REST接口返回.
对REST接口的第二次调用恰好丰富了当前数据. 这个调用的目的是用URL和图像来丰富初始搜索结果.
然后第二次调用ChatGPT,并引用先前调用的函数和丰富的数据
ChatGPT使用自然语言处理JSON数据后进行回复. 结果实际上被流式传输到客户端. 一旦ChatGPT生成令牌,它就会通过web套接字s流传输到客户端.
函数调用是如何工作的?
函数调用 已于2023年6月推出,以帮助开发人员接收带有本地可调用函数描述的结构化JSON. 事实证明,函数调用非常适合集成 ChatGPT 使用REST接口,因为它有助于提高ChatGPT的输出可靠性.
当您使用ChatGPT模型(如e.g. gpt-3.5-turbo-16k-0613或gpt-4-0613您最初发送消息, 函数和提示符的说明. 在理想的场景中,ChatGPT使用要调用的函数进行响应.
在第二步中,使用提取的参数调用ChatGPT指定的函数,并以某种文本格式获得结果(如i.e. JSON).
在最后一步中,将被调用函数的输出发送给ChatGPT, 与初始提示一起. ChatGPT使用自然语言生成最终答案.
总共有3个步骤:
查询ChatGPT以获取函数调用及其参数. 以基于JSON的格式发送用户提示和功能规范.
使用ChatGPT提取的参数调用实际的Python函数, 哪些是从用户提示符中提取的.
使用函数输出和初始用户提示查询ChatGPT,以获得最终的基于自然语言的输出.
例子
在我们的例子中,我们有一个签名如下的函数:
def event_search (
搜索:str,
locality:可选[str] = "",
country:可选[str] = "",
tags: List[str] = []
repeat: bool = True;
) -> str:
...
当用户询问例如:
你能在英国找到十大网博靠谱平台冥想的活动吗?
ChatGPT将在第一次调用(步骤1)中提取对应的两个函数参数:
搜索:“冥想”
国家:“联合王国”
然后使用这两个参数调用函数(步骤2),然后调用返回基于JSON的响应的REST接口. 然后,这个JSON响应将与原始问题一起发送回ChatGPT(步骤3)。.
在步骤3中 聊天完成API 将用3条消息调用:
系统消息(ChatGPT请求的后台信息)
原始用户提示
使用提取的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原型包含两个应用程序. 第一个应用程序是用Python编写的后端应用程序,可以在这个存储库中找到:
http://github.com/onepointconsulting/event_management_agent
第二个应用程序是用Javascript编写的前端应用程序 反应:
http://github.com/onepointconsulting/chatbot-ui
后端代码
后端代码由一个基于web套接字的服务器组成 python-套接字io (实现了一个传输协议,该协议支持客户端之间基于事件的实时双向通信)和 aiohttp 异步HTTP客户端/服务器 asyncio 和Python).
主要的web套接字服务器实现可以在这个文件中找到:
处理用户问题的函数如下:
这是在聊天服务器上触发整个工作流的功能. 它接收来自客户端的问题, 触发事件搜索并将数据流发送到客户端. 它还确保在发生错误时正确关闭流.
这个方法调用另外两个方法:
process_search—此方法处理传入的问题,直到通过REST API执行搜索.
Aprocess_stream——这个方法接收搜索结果并返回一个可迭代对象,允许流式传输到客户端.
这些方法可以在这个文件中找到: http://github.com/onepointconsulting/event_management_agent/blob/main/event_management_agent/service/event_search_service.py
你可以在这里找到process_search方法: 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
前端代码
聊天界面的主要组成部分是:
http://github.com/onepointconsulting/chatbot-ui/blob/main/src/components/MainChat.tsx
除了渲染UI,它还使用webhook useWeb套接字, 其中包含处理基于web套接字的事件处理程序的代码 套接字.io-client 图书馆. useWeb套接字hook的实现可以在这个文件中找到: http://github.com/onepointconsulting/chatbot-ui/blob/main/src/hooks/useWebsocket.ts
观察
这个项目只是一个小的原型和学习经验,可以在很多方面进行改进-特别是用户界面需要一个更好和更专业的设计,缺乏像e.g. 聊天记录.
外卖
如果您有允许您搜索数据的REST接口, 然后,您应该能够使用它们构建聊天界面. ChatGPT的函数调用是在这些搜索界面之上堆叠聊天层的好方法. 你不需要一个非常强大的模型,你可以使用像gpt-3这样的旧模型.5-turbo-16k-0613,仍然提供良好的用户体验.
编写自己的聊天用户界面也是一种有趣的体验,它允许您创建更自定义的实现——与使用像e.g Chainlit or Streamlit. 等项目 Chainlit 为您提供了大量的功能,并帮助您快速启动和运行, 但在某个阶段限制你的设计选择,以防你做了很多UI定制. 不过,编写自己的聊天用户界面需要对打印稿或Javascript和一些UI框架有所精通, 像反应Js, VueJs或苗条.
如果你想有聊天流媒体, 那么你绝对应该使用web套接字协议,它也允许你以一种相当方便的方式保持聊天内存, 由于其内置的web套接字会话.
我的最后一个结论是,当您想要与LLM模型交互时,并不总是需要使用LangChain. LangChain 作为许多LLM api之上的一层非常方便,但代价是一个很大的依赖树. 如果你真的知道,你只会使用一个特定的LLM的一个非常具体的功能, 那你就别用了 LangChain.
吉尔·费尔南德斯,Onepoint咨询公司