news 2026/4/3 4:52:49

使用 LangChain 和 Chainlit 将外部 API 集成到聊天机器人应用程序中

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
使用 LangChain 和 Chainlit 将外部 API 集成到聊天机器人应用程序中

原文:towardsdatascience.com/integrating-an-external-api-with-a-chatbot-application-using-langchain-and-chainlit-b687bb1efe58

在本教程中,我们将了解如何将外部 API 集成到自定义聊天机器人应用程序中。在我之前关于构建自定义聊天机器人应用程序的文章中,我们介绍了使用LangChain和OpenAI创建具有特定功能的聊天机器人的基础知识,以及如何使用Chainlit构建聊天机器人的 Web 应用程序。

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/939e7713bebcf18135d76be98934a7e6.png

API 集成聊天机器人的工作流程 - 图片由作者提供

如果你是这个系列的初学者,我建议查看我之前发布的文章,以获取详细的分步指南:

使用 Chainlit 和 LangChain 构建聊天机器人应用程序

如何使用 LangChain 和 OpenAI 构建自己的聊天机器人

本教程将侧重于增强我们的聊天机器人Scoopsie,一个冰淇淋助手,通过将其连接到外部 API。您可以将 API 视为在程序内部和程序之间提取和共享数据的一种可访问方式。用户可以向 API 发出请求以获取或发送数据,API 会返回一些信息。我们将连接Scoopsie到 API 以获取虚构冰淇淋店的信息,并使用这些响应提供信息。对于大多数聊天机器人应用程序,将自定义聊天机器人链接到外部 API 可能非常有用,在某些情况下甚至可能是必要的。

这里是对我们上次停止的地方的快速回顾:目前我们的chatbot.py使用 LLMChain 查询 OpenAI 的 GPT-3.5 模型来回答用户关于冰淇淋相关的问题:

importchainlitasclfromlangchain_openaiimportOpenAIfromlangchain.chainsimportLLMChainfrompromptsimportice_cream_assistant_prompt_templatefromlangchain.memory.bufferimportConversationBufferMemoryfromdotenvimportload_dotenv load_dotenv()@cl.on_chat_startdefquery_llm():llm=OpenAI(model='gpt-3.5-turbo-instruct',temperature=0)conversation_memory=ConversationBufferMemory(memory_key="chat_history",max_len=50,return_messages=True,)llm_chain=LLMChain(llm=llm,prompt=ice_cream_assistant_prompt_template,memory=conversation_memory)cl.user_session.set("llm_chain",llm_chain)@cl.on_messageasyncdefquery_llm(message:cl.Message):llm_chain=cl.user_session.get("llm_chain")response=awaitllm_chain.acall(message.content,callbacks=[cl.AsyncLangchainCallbackHandler()])awaitcl.Message(response["text"]).send()

环境设置

如果您还没有为项目设置conda环境,您可以继续创建一个。请记住,Chainlit 需要python>=3.8

conda create--name chatbot_langchain python=3.10

使用以下命令激活您的环境:

conda activate chatbot_langchain

要安装所有依赖项,请运行:

pip install-r requirements.txt

创建一个虚构的商店 API

我们将首先创建一个 API 以连接到 Scoopsie。此 API 代表一个虚构的冰淇淋店,允许用户检索商店的菜单,以及其他信息,如自定义项、用户评论和特别优惠。我们将利用 Flask,一个用于 Web 开发的 Python 框架,将上述信息编码在不同的 API 端点中。这些包括:

  1. /menu:一个**GET**端点,用于检索口味和配料菜单。

  2. /customizations:一个**GET**端点,用于检索自定义项

  3. /special-offers:一个**GET**端点,用于检索特别优惠。

  4. /user-reviews:一个**GET**端点,用于检索用户评价。

为了让Scoopsie专注于提供信息而不是处理交易或处理订单,我们将当前范围限制在这些信息端点上。然而,您可以扩展此 API 以包括其他端点,例如允许用户提交订单的 POST 端点或其他 GET 端点。

第 1 步

让我们创建一个名为data_store.py的 Python 脚本,用于存储静态数据,如菜单、特别优惠、客户评价和定制选项。以下是它的结构:

# Example menu, special offers, customer reviews, and customizationsmenu={"flavors":[{"flavorName":"Strawberry","count":50},{"flavorName":"Chocolate","count":75}],"toppings":[{"toppingName":"Hot Fudge","count":50},{"toppingName":"Sprinkles","count":2000},{"toppingName":"Whipped Cream","count":50}]}special_offers={"offers":[{"offerName":"Two for Tuesday","details":"Buy one get one free on all ice cream flavors every Tuesday."},{"offerName":"Winter Wonderland Discount","details":"25% off on all orders above $20 during the winter season."}]}customer_reviews={"reviews":[{"userName":"andrew_1","rating":5,"comment":"Loved the chocolate flavor!"},{"userName":"john","rating":4,"comment":"Great place, but always crowded."},{"userName":"allison","rating":5,"comment":"Love the ice-creams and Scoopsie is super helpful!"}]}customizations={"options":[{"customizationName":"Sugar-Free","details":"Available for most flavors."},{"customizationName":"Extra Toppings","details":"Choose as many toppings as you want for an extra $5!"}]}

您可以根据自己的具体需求调整上述脚本。这些示例显示了每个类别的可能属性。在实际应用中,将此数据存储在数据库中以进行动态检索更为合适。

第 2 步

让我们在名为ice_cream_store_app.py的文件中设置我们的 Flask 应用程序,我们将从data_store.py导入数据。我们可以从导入所需的库和初始化 Flask 应用程序开始:

fromflaskimportFlask,jsonifyfromdata_storeimportmenu,special_offers,customer_reviews,customizations app=Flask(__name__)

第 3 步

现在,让我们配置 API 端点函数。在 Flask 中,这些函数直接响应 Web 请求,无需显式参数,这得益于 Flask 的路由机制。这些函数的设计目的是:

  • 自动处理请求,无需直接传递参数,除了基于类的视图的隐式self,这里我们没有使用。

  • 返回一个包含两个元素的tuple

  • 通过jsonify()转换成 JSON 格式的dict

  • 一个 HTTP 状态码,通常是200,表示成功。

下面是端点函数:

@app.route('/menu',methods=['GET'])defget_menu():""" Retrieves the menu data. Returns: A tuple containing the menu data as JSON and the HTTP status code. """returnjsonify(menu),200@app.route('/special-offers',methods=['GET'])defget_special_offers():""" Retrieves the special offers data. Returns: A tuple containing the special offers data as JSON and the HTTP status code. """returnjsonify(special_offers),200@app.route('/customer-reviews',methods=['GET'])defget_customer_reviews():""" Retrieves customer reviews data. Returns: A tuple containing the customer reviews data as JSON and the HTTP status code. """returnjsonify(customer_reviews),200@app.route('/customizations',methods=['GET'])defget_customizations():""" Retrieves the customizations data. Returns: A tuple containing the customizations data as JSON and the HTTP status code. """returnjsonify(customizations),200

对于上述每个函数,使用jsonify()将 Python 字典转换为 JSON 格式,然后返回带有200状态码的成功查询。

第 4 步

最后,让我们将以下代码添加到我们的ice_cream_store_app.py脚本中:

if__name__=='__main__':app.run(debug=True)

可以通过在终端运行以下命令来启动 API:

python ice_cream_store_app.py

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/592c831982158b7a3eebd33aec804ccb.png

启动冰淇淋店 API 的 Flask 服务器 – 作者图片

一旦应用程序运行,Scoopsie 的自定义 API 将通过**http://127.0.0.1:5000/可访问。要检查各种端点,您可以使用 Postman 或使用网页浏览器查看特定端点:http://127.0.0.1:5000/{endpoint_name}**。

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/dd7f328051b1fb71dcdd415b79949f06.png

冰淇淋店 API 端点 – 作者图片

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/049ddec3c19af258088f90f8ef851ae2.png

冰淇淋店 API 端点在实际应用中 – 作者

LangChain 的 APIChain 解释

LangChain 中的链通过将它们作为一系列简单、连接的操作执行来简化复杂任务。这些链通常包含元素,如 LLM、PromptTemplates、输出解析器或外部第三方 API,我们将在本教程中关注这些内容。我在本系列的第一个文章中更详细地介绍了 LangChain 的链功能,你可以通过这里访问。

以前,我们使用 LangChain 的 LLMChain 直接与 LLM 进行交互。现在,为了扩展Scoopsie的功能以与外部 API 交互,我们将使用 APIChain。APIChain 是一个 LangChain 模块,用于将用户输入格式化为 API 请求。这将使我们的聊天机器人能够向外部 API 发送请求并接收响应,从而扩展其功能。

APIChain 可以配置为处理不同的 HTTP 方法(GET、POST、PUT、DELETE 等),设置请求头,并管理请求体。它还支持 JSON 负载,这在 RESTful API 通信中很常见。

设置 LangChain 的 API Chain

第 1 步

首先在我们的chatbot.py文件中导入 LangChain 的 APIChain 模块以及其他所需的模块。这个脚本将托管我们所有的应用程序逻辑。你可以在.env脚本中设置必要的环境变量,例如OPENAI_API_KEY,该变量可以通过dotenvPython 库访问。

importchainlitasclfromlangchain_openaiimportOpenAIfromlangchain.chainsimportLLMChain,APIChainfromlangchain.memory.bufferimportConversationBufferMemoryfromdotenvimportload_dotenv load_dotenv()

第 2 步

对于 APIChain 类,我们需要以字符串格式的外部 API 文档来访问端点详情。这个文档应该概述 API 的端点、方法、参数和预期的响应。这有助于 LLM 构建 API 请求并解析响应。将此信息定义为字典并将其转换为字符串以供以后使用是有帮助的。

让我们创建一个新的 Python 脚本api_docs.py并添加我们虚构商店的 API 文档:

importjson scoopsie_api_docs={"base_url":"<http://127.0.0.1:5000/>","endpoints":{"/menu":{"method":"GET","description":"Retrieve the menu of flavors and customizations.","parameters":None,"response":{"description":"A JSONobjectcontaining available flavorsandtoppings alongwiththeir counts.","content_type":"application/json"}},"/special-offers":{"method":"GET","description":"Retrieve current special offers and discounts.","parameters":None,"response":{"description":"A JSONobjectlisting the current special offersanddiscounts.","content_type":"application/json"}},"/customer-reviews":{"method":"GET","description":"Retrieve customer reviews for the ice cream store.","parameters":None,"response":{"description":"A JSONobjectcontaining customer reviews,ratings,andcomments.","content_type":"application/json"}},"/customizations":{"method":"GET","description":"Retrieve available ice cream customizations.","parameters":None,"response":{"description":"A JSONobjectlisting available customizations like toppingsandsugar-free options.","content_type":"application/json"}}}}# Convert the dictionary to a JSON stringscoopsie_api_docs=json.dumps(scoopsie_api_docs,indent=2)

我已经将我们自定义 API 的文档格式化为一个名为scoopsie_api_docs的 Python 字典。这个字典包括 API 的基本 URL,并在endpoints键下详细说明我们的四个端点。每个端点列出其 HTTP 方法(对我们来说都是GET),一个简洁的描述,接受的参数(这些端点没有参数),以及预期的响应格式——一个包含相关数据的 JSON 对象。然后使用json.dumps将该字典转换为 JSON 字符串,并缩进 2 个空格以提高可读性。

让我们在chatbot.py脚本中导入这个 API 文档:

fromapi_docsimportscoopsie_api_docs

第 3 步

APIChain 需要两个提示:一个用于选择正确的 API 端点,另一个基于该端点创建对用户查询的简洁回复。这些提示有默认值,然而,我们将创建自己的提示以确保个性化的交互。我们可以在prompts.py文件中添加以下新提示:

api_url_template=""" Given the following API Documentation for Scoopsie's official ice cream store API: {api_docs} Your task is to construct the most efficient API URL to answer the user's question, ensuring the call is optimized to include only necessary information. Question: {question} API URL: """api_url_prompt=PromptTemplate(input_variables=['api_docs','question'],template=api_url_template)api_response_template="""" With the API Documentation for Scoopsie's official API: {api_docs} and the specific user question: {question} in mind, and given this API URL: {api_url} for querying, here is the response from Scoopsie's API: {api_response}. Please provide a summary that directly addresses the user's question, omitting technical details like response format, and focusing on delivering the answer with clarity and conciseness, as if Scoopsie itself is providing this information. Summary: """api_response_prompt=PromptTemplate(input_variables=['api_docs','question','api_url','api_response'],template=api_response_template)

在这里,api_url_prompt生成使用提供的 API 文档(api_docs)查询的确切 API URL。在通过api_url_prompt识别正确的端点后,APIChain 使用api_response_prompt总结 API 的响应以回答用户的查询。让我们在我们的chatbot.py脚本中导入这些提示:

frompromptsimportapi_response_prompt,api_url_prompt

第 4 步

让我们设置 APIChain 以连接到我们之前创建的虚构冰淇淋商店的 API。LangChain 模块的 APIChain 提供了from_llm_and_api_docs()方法,允许我们仅从 LLM 和之前定义的 API 文档中加载链。我们将继续使用 OpenAI 的gpt-3.5-turbo-instruct模型作为我们的 LLM。

# Initialize your LLMllm=OpenAI(model='gpt-3.5-turbo-instruct',temperature=0)api_chain=APIChain.from_llm_and_api_docs(llm=llm,api_docs=scoopsie_api_docs,api_url_prompt=api_url_prompt,api_response_prompt=api_response_prompt,verbose=True,limit_to_domains=["<http://127.0.0.1:5000/>"])

上述代码中的limit_to_domains参数限制了 APIChain 可以访问的域。根据官方 LangChain 文档,默认值是一个空元组。这意味着默认情况下不允许任何域。按照设计,这将在实例化时引发错误。如果您想默认允许所有域,可以传递None。然而,出于安全考虑,这不被推荐,因为它会允许恶意用户向任意 URL 发起请求,包括可以从服务器访问的内部 API。为了允许我们的商店 API,我们可以指定其 URL;这将确保我们的链在受控环境中运行。

第 5 步

在之前的教程中,我们设置了一个 LLMChain 来处理与冰淇淋相关的通用查询。我们仍然希望保留这个功能,因为 Scoopsie 是一个有用的对话伙伴,同时通过 APIChain 整合访问我们虚构商店的菜单和定制选项。为了结合这些功能,我们将使用llm_chain处理通用查询,并使用api_chain访问商店的 API。这需要调整我们的 Chainlit 设置,以支持用户会话开始时的多个链。以下是我们可以如何调整@cl.on_chat_start装饰器的方法:

@cl.on_chat_startdefsetup_multiple_chains():llm=OpenAI(model='gpt-3.5-turbo-instruct',temperature=0)conversation_memory=ConversationBufferMemory(memory_key="chat_history",max_len=200,return_messages=True,)llm_chain=LLMChain(llm=llm,prompt=ice_cream_assistant_prompt,memory=conversation_memory)cl.user_session.set("llm_chain",llm_chain)api_chain=APIChain.from_llm_and_api_docs(llm=llm,api_docs=scoopsie_api_docs,api_url_prompt=api_url_prompt,api_response_prompt=api_response_prompt,verbose=True,limit_to_domains=["<http://127.0.0.1:5000/>"])cl.user_session.set("api_chain",api_chain)

当启动新的用户会话时,此设置实例化llm_chainapi_chain,确保Scoopsie能够处理广泛的查询。每个链都存储在用户会话中,以便于检索。有关设置llm_chain的信息,您可以查看我的上一篇文章。

第 6 步

让我们现在定义围绕@cl.on_message装饰器的包装函数:

@cl.on_messageasyncdefhandle_message(message:cl.Message):user_message=message.content.lower()llm_chain=cl.user_session.get("llm_chain")api_chain=cl.user_session.get("api_chain")ifany(keywordinuser_messageforkeywordin["menu","customization","offer","review"]):# If any of the keywords are in the user_message, use api_chainresponse=awaitapi_chain.acall(user_message,callbacks=[cl.AsyncLangchainCallbackHandler()])else:# Default to llm_chain for handling general queriesresponse=awaitllm_chain.acall(user_message,callbacks=[cl.AsyncLangchainCallbackHandler()])response_key="output"if"output"inresponseelse"text"awaitcl.Message(response.get(response_key,"")).send()

在这个设置中,我们检索了llm_chainapi_chain对象。如果用户消息包含反映我们虚构商店 API 端点的关键词,应用程序将触发 APIChain。如果没有,我们假设它是一个一般的冰淇淋相关查询,并触发 LLMChain。这是一个简单的用例,但对于更复杂的用例,您可能需要编写更复杂的逻辑来确保触发正确的链。有关 Chainlit 装饰器和如何有效利用它们的更多详细信息,请参阅我之前的文章previous article,我在那里对这些主题进行了深入探讨。

第 7 步

现在我们应用程序的代码已经准备好了,我们可以启动我们的聊天机器人。在您的项目目录中打开一个终端,并运行以下命令:

chainlit run chatbot.py-w--port8000

您可以通过在 Web 浏览器中导航到**localhost:8000**来访问聊天机器人。

演示

Scoopsie的应用程序界面现在已准备就绪!以下是一个展示聊天机器人实际操作的演示:

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/620a5a11b20e74233c8d15826dc2fceb.png

Scoopsie 聊天机器人演示:互动冰淇淋助手在实际操作中 – 作者

总结

我们已经成功为一家虚构的冰淇淋店构建了一个 API,并将其与我们的聊天机器人集成。如上所示,您可以使用 Chainlit 访问聊天机器人的 Web 应用,在那里可以访问一般查询和虚构商店的 API 端点。

您可以在本GitHub仓库中找到这个教程的代码。本教程的GitHub 检查点将包含到此为止开发的所有代码。

您可以跟随,我会分享关于 AI 领域的工作演示、解释和有趣的项目。在LinkedIn和X上打招呼!👋

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/3/23 14:41:18

利用DDS技术生成多频混合波形的发生器方案

用DDS技术打造多频混合波形发生器&#xff1a;从原理到实战的完整指南你有没有遇到过这样的场景&#xff1f;测试一个音频放大器时&#xff0c;想同时注入多个频率来评估其非线性失真&#xff1b;或者在做EMC抗扰度试验时&#xff0c;需要模拟多种干扰信号共存的复杂电磁环境。…

作者头像 李华
网站建设 2026/3/27 21:17:36

双层锚点图哈希(Two-Layer Anchor Graph Hashing)训练函数实现详解

双层锚点图哈希(Two-Layer Anchor Graph Hashing)是锚点图哈希家族中的进阶版本,它在单层 AGH 的基础上引入了精细的双阈值学习机制。前 r/2 位哈希码采用传统的零阈值二值化,而后 r/2 位则为每一比特单独计算正、负样本的最优阈值,从而显著降低量化误差,提升哈希码的平衡…

作者头像 李华
网站建设 2026/3/30 11:00:23

GCC是什么?

GCC是什么&#xff1f; GCC&#xff08;GNU Compiler Collection&#xff09;是一个非常庞大且功能丰富的编译器系统。本文涵盖其内部架构、编译流程、高级功能以及在实际开发中的应用深度。GCC 的详细解析 1. 历史与演变 1987年&#xff1a;Richard Stallman 为 GNU 项目编写了…

作者头像 李华
网站建设 2026/3/27 6:25:06

推荐工具-ToDoList-待办清单

概述 挺适合电脑使用的一款待办清单列表软件&#xff1a;ToDoList。&#xff08;不止是待办&#xff09; 下载 本来想要给链接&#xff0c;但是发现之前收藏的失效了就不发了。 自己搜索&#xff1a;todolist绿色版 、或者正常版的都行。 图&#xff1a;

作者头像 李华