你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn。
Azure Cosmos DB 中的 AI 代理
AI 代理旨在执行特定任务、回答问题并为用户自动执行流程。 这些代理的复杂性差异很大。 它们的范围从简单的聊天机器人到助手,再到可以自主运行复杂工作流的数字或机器人系统形式的高级 AI 助手。
本文提供了 AI 代理的概念性概述和详细的实施示例。
什么是 AI 代理?
与独立的大型语言模型 (LLM) 或基于规则的软件/硬件系统不同,AI 代理具有这些共同特征:
- 规划:AI 代理可以规划和排序操作以实现特定目标。 集成 LLM 彻底改变了它们的规划能力。
- 工具使用:高级 AI 代理可以使用各种工具(例如代码执行、搜索和计算功能)来有效地执行任务。 AI 代理通常通过函数调用来使用工具。
- 感知:AI 代理可以从其环境中感知和处理信息,使其更具交互性和上下文感知性。 此信息包括视觉、听觉和其他感官数据。
- 记忆:AI 代理具有记住过去交互(工具使用和感知)和行为(工具使用和规划)的能力。 它们可以存储这些体验,甚至进行自我反思,以指导未来的行动。 这种记忆组件可确保代理性能保持连续性并随着时间的推移不断改进。
注意
AI 代理上下文中术语“memory”的使用不同于计算机内存的概念(如易失性、非易失性和持久性内存)。
助手
助手是一种 AI 代理。 它们与用户一起工作,而不是独立运行。 与完全自动化的代理不同,助手提供建议和推荐,以帮助用户完成任务。
例如,当用户正在写电子邮件时,助手可能会建议短语、句子或段落。 用户还可以要求助手在其他电子邮件或文件中查找相关信息来支持该建议(请参阅检索增强生成)。 用户可以接受、拒绝或编辑建议的段落。
自主代理
自主代理可以更独立地运行。 设置自主代理来协助撰写电子邮件时,可以让它们执行以下任务:
- 查阅与主题相关的现有电子邮件、聊天、文件和其他内部和公共信息。
- 对收集到的信息进行定性或定量分析,并得出与电子邮件相关的结论。
- 根据结论撰写完整的电子邮件并纳入支持证据。
- 将相关文件附加到电子邮件。
- 检查电子邮件以确保所有纳入的信息均与事实相符,且断言有效。
- 为“收件人”、“抄送”和/或“密送”选择适当的收件人并查找他们的电子邮件地址。
- 安排适当的时间发送电子邮件。
- 如果未按预期收到回复,则进行跟进。
可以将代理配置为在经过或未经过人工批准的情况下执行上述每个任务。
多代理系统
一个实现高性能自主代理的热门策略是使用多代理系统。 在多代理系统中,多个自主代理(无论是数字形式还是机器人形式)相互作用或协同工作,以实现个人或集体目标。 系统中的代理可以独立运行,并拥有自己的知识或信息。 每个代理还可能具有感知其环境、做出决策以及根据其目标执行操作的能力。
多代理系统具有以下关键特征:
- 自主:每个代理独立运行。 它会做出自己的决定,而不直接受人工干预或由其他代理控制。
- 交互性:代理会相互通信和协作,以共享信息、协商和协调其行动。 这种交互可以通过各种协议和通信渠道进行。
- 以目标为导向:多代理系统中的代理旨在实现特定目标,这些目标可以与单个目标或代理之间共享的目标保持一致。
- 分布式:多代理系统以分布式方式运行,没有单一控制点。 这种分布增强了系统的稳健性、可扩展性和资源效率。
与助手或单个 LLM 推理实例相比,多代理系统具有以下优势:
- 动态推理:与思路链或思路树提示相比,多代理系统允许通过各种推理路径进行动态导航。
- 周全的功能:多代理系统可以通过进行彻底的决策过程并在多个代理之间分配任务来处理复杂或大规模的问题。
- 增强的记忆:具有内存的多代理系统可以克服 LLM 的上下文窗口,以便更好地进行了解和信息保留。
AI 代理的实现
推理和规划
复杂的推理和规划是高级自主代理的标志。 热门的自主代理框架结合了以下一种或多种推理和规划方法(包含 arXiv 存档页的链接):
-
通过让模型在回答初始问题之前明确地问自己(并回答)后续问题来改进思路链。
-
使用 LLM 以交错方式生成推理轨迹和特定于任务的操作。 推理跟踪有助于模型引导、跟踪和更新行动计划,以及处理异常。 行动使模型与外部源(如知识库或环境)连接,以收集其他信息。
-
制定计划,将整个任务划分为较小的子任务,然后根据计划执行子任务。 此方法可以减少零样本思维链提示中经常出现的计算错误、缺失步骤错误和语义误解错误。
-
使用口头反思任务反馈信号的反射代理。 这些代理会在情节记忆缓冲区中维护自己的反思文本,以在后续试验中引入更好的决策。
框架
各种框架和工具可以促进 AI 代理的开发和部署。
对于不需要复杂规划和记忆的工具使用和感知,一些常用的 LLM 编排器框架包括 LangChain、LlamaIndex、Prompt Flow 和 Semantic Kernel。
对于高级和自主的规划和执行工作流,AutoGen 推动了始于 2022 年底的多代理浪潮。 OpenAI 的 Assistants API 让用户可以在 GPT 生态系统中本机创建代理。 LangChain Agents 和 LlamaIndex Agents 也在同一时间面世。
提示
本文后面的实现示例演示了如何使用一个常用框架和一个统一的代理记忆系统构建简单的多代理系统。
AI 代理记忆系统
2022 年至 2024 年试验 AI 增强应用程序的普遍做法是使用独立数据库管理系统来处理各种数据工作流或类型。 例如,可以使用内存数据库进行缓存、使用关系数据库处理操作数据(包括跟踪/活动日志和 LLM 对话历史记录)、使用纯矢量数据库进行嵌入管理。
但是,这种使用复杂独立数据库网络的做法可能会损害 AI 代理的性能。 将所有这些不同的数据库集成到一个具有凝聚力、可互操作且具有弹性的 AI 代理记忆系统中本身就是一项挑战。
此外,对于 AI 代理系统所需的速度和可扩展性来说,许多常用的数据库服务并不是最佳方案。 这些数据库各自的弱点在多代理系统中更加严重。
内存中数据库
内存数据库在速度方面非常出色,但可能难以满足 AI 代理所需的大规模数据持久性。
关系数据库
关系数据库并不适用于代理处理的数据的多种模态和流动模式。 关系数据库需要手动操作,甚至停机来管理配置、分区和分片。
纯矢量数据库
纯矢量数据库对事务操作、实时更新和分布式工作负载往往不太有效。 目前常用的纯矢量数据库通常具有以下特点:
- 不保证读取和写入。
- 有限的引入吞吐量。
- 低可用性(低于 99.9%,或年化停机时间 9 小时或更长)。
- 一个一致性级别(最终)。
- 资源密集型内存矢量索引。
- 有限的多租户选项。
- 有限的安全性。
可靠的 AI 代理记忆系统的特征
正如高效的数据库管理系统对软件应用程序的性能至关重要一样,为 LLM 驱动的代理提供相关且有用的信息以指导其推理也至关重要。 强大的记忆系统能够组织和存储代理在推理时可以检索的各种类型的信息。
目前,基于 LLM 的应用程序通常使用检索增强生成,即使用基本语义搜索或矢量搜索来检索段落或文档。 矢量搜索可用于查找常规信息。 但矢量搜索可能不会捕获与特定任务或领域相关的具体上下文、结构或关系。
例如,如果任务是编写代码,矢量搜索可能无法检索语法树、文件系统布局、代码摘要或 API 签名,而这些对于生成连贯且正确的代码很重要。 同样,如果任务是处理表格数据,矢量搜索可能无法检索模式、外键、存储过程或用于查询或分析数据的报告。
将独立的内存数据库、关系数据库和矢量数据库(如之前所述)集成在一起不是应对各种数据类型的最佳解决方案。 此方法可能适用于原型代理系统。 但是,它增加了复杂性和性能瓶颈,从而阻碍了高级自主代理的性能。
一个强大的记忆系统应该具有以下特点。
多模式
AI 代理记忆系统应该提供用于存储元数据、关系、实体、摘要或其他类型的信息的集合,用于各种任务和领域。 这些集合可以基于数据的结构和格式,例如文档、表或代码。 或者,它们可以基于数据的内容和含义,例如概念、关联或过程步骤。
记忆系统不仅对 AI 代理至关重要。 它们对于开发、维护和使用这些代理的人也很重要。
例如,人类可能需要近乎实时地监督代理的规划和执行工作流程。 在监督的同时,人类可能会插入指导或对代理的对话或独白进行在线编辑。 人类可能还需要审核代理的推理和行为,以验证最终输出的有效性。
人/代理交互可能使用自然语言或编程语言,而代理则通过嵌入来“思考”、“学习”和“记忆”。 这种差异对记忆系统在不同数据模态之间的一致性提出了另一个要求。
操作性
记忆系统应该提供用于存储与用户和环境交互相关的信息的记忆库。 此类信息可能包括聊天记录、用户偏好、感官数据、做出的决策、学到的事实或其他高频率和大量更新的操作数据。
这些记忆库可以帮助代理记住短期和长期信息,避免重复或自相矛盾,并保持任务连贯性。 即使代理连续执行大量不相关的任务,这些要求也必须成立。 在高级用例下,代理还可能对在不同点发散或汇聚的众多分支进行测试。
可共享,也可分离
在宏观层面上,记忆系统应通过提供所有代理均可访问的共享内存,使多个 AI 代理能够协作解决一个问题或处理问题的不同方面。 共享记忆可以促进代理之间的信息交换和行动协调。
同时,记忆系统必须允许代理保留自己的角色和特征,例如其独特的提示和记忆集合。
构建强大的 AI 代理记忆系统
前述特征要求人工智能代理记忆系统具有高度可扩展性和快速性。 痛苦地将内存数据库、关系数据库和矢量数据库(如之前所述)编织在一起可能适合处于早期的由 AI 支持的应用程序。 但是,此方法增加了复杂性和性能瓶颈,从而阻碍了高级自主代理的性能。
Azure Cosmos DB 可以代替所有独立数据库,作为 AI 代理记忆系统的统一解决方案。 它的稳健性使 OpenAI 的 ChatGPT 服务能够以较高的可靠性和较低的维护成本动态扩展。 它由原子记录序列引擎提供支持,是世界上第一个提供无服务器模式的全球分布式 NoSQL、关系和矢量数据库服务。 基于 Azure Cosmos DB 构建的 AI 代理提供了速度、规模和简单性。
速度
Azure Cosmos DB 提供单位数的毫秒级延迟。 此功能使它适合需要快速数据访问和管理的进程。 这些进程包括缓存(传统缓存和语义缓存)、事务和操作工作负载。
低延迟对于需要执行复杂推理、做出实时决策和提供即时响应的 AI 代理至关重要。 此外,该服务对 DiskANN 算法的使用可提供准确且快速的矢量搜索,同时消耗最少的内存。
缩放
Azure Cosmos DB 专为全局分发和水平可伸缩性而设计。 它为多区域 I/O 和多租户提供支持。
该服务有助于确保内存系统可以无缝扩展,并跟上快速增长的代理和相关数据。 它的服务级别协议 (SLA) 中的可用性保证相当于每年不到 5 分钟的停机时间。 相比之下,纯矢量数据库服务具有 9 小时或更多的停机时间。 此可用性为任务关键型工作负载提供了坚实的基础。 同时,Azure Cosmos DB 中的各种服务模型(如预留容量或无服务器)有助于降低财务成本。
简易性
Azure Cosmos DB 通过将多种数据库功能集成到一个统一的平台中来简化数据管理和架构。
其集成的矢量数据库功能可以存储、索引和查询嵌入以及自然语言或编程语言中的相应数据。 此功能可实现更好的数据一致性、缩放性和性能。
其灵活性可以支持代理工作流中涉及的元数据、关系、实体、摘要、聊天记录、用户偏好、感官数据、决策、学到的事实或其他操作数据的各种形式和流畅架构。 数据库会自动为所有数据编制索引,而无需进行架构或索引管理,从而帮助 AI 代理快速高效地执行复杂查询。
Azure Cosmos DB 是完全托管的,这消除了数据库管理任务(例如缩放、修补和备份)的开销。 没有了这项开销后,开发人员可以专注于构建和优化 AI 代理,而不必担心底层数据基础设施。
高级功能
Azure Cosmos DB 集成了变更源等高级功能,允许实时跟踪和响应数据变化。 此功能对于需要及时响应新信息的 AI 代理非常有用。
此外,内置对多主数据库写入的支持可实现高可用性和弹性,帮助确保 AI 代理即使在区域故障后也能持续运行。
五种可用的一致性级别(从强到最终)还可以根据场景要求满足各种分布式工作负载。
提示
可以从两个 Azure Cosmos DB API 中进行选择,以生成 AI 代理记忆系统:
- Azure Cosmos DB for NoSQL 提供 99.999% 的可用性保证,并提供三种矢量搜索算法:IVF、HNSW 和 DiskANN
- 基于 vCore 的 Azure Cosmos DB for MongoDB 提供 99.995% 的可用性保证,并提供两种矢量搜索算法:IVF 和 HNSW(DiskANN 即将发布)
有关这些 API 的可用性保证的信息,请参阅服务 SLA。
实施示例
本节探讨如何在一个游轮旅行应用程序中实现自主代理以处理旅行者的问询和预订。
聊天机器人概念由来已久,但 AI 代理正在超越基本的人类对话,执行基于自然语言的任务。 这些任务传统上需要编码逻辑。 本实现示例中的 AI 旅行代理使用 LangChain 代理框架来规划代理、了解工具使用情况和感知。
该 AI 旅行代理的统一记忆系统使用 Azure Cosmos DB 的矢量数据库和文档存储功能来处理旅行者查询并促进旅行预订。 使用 Azure Cosmos DB 实现此目的有助于确保速度、缩放性和简单性,如之前所述。
示例代理在 Python FastAPI 后端中运行。 它支持通过 React JavaScript 用户界面进行用户交互。
先决条件
- Azure 订阅。 如果你还没有的话,可以免费试用 Azure Cosmos DB 30 天,而无需创建 Azure 帐户。 免费试用版不需要信用卡,并且试用期后没有承诺。
- 用于使用 OpenAI API 或 Azure OpenAI 服务的帐户。
- 在 Azure Cosmos DB for MongoDB 中的 vCore 群集。 可以按照本快速入门创建一个。
- 集成开发环境,如 Visual Studio Code。
- 开发环境中安装的 Python 3.11.4。
下载项目
此 GitHub 存储库中提供了所有代码和示例数据集。 存储库包含以下文件夹:
- loader:此文件夹包含用于在 Azure Cosmos DB 中加载示例文档和矢量嵌入的 Python 代码。
- api:此文件夹包含用于托管 AI 旅行代理的 Python FastAPI 项目。
- web:此文件夹包含 React Web 界面的代码。
将旅行文档加载到 Azure Cosmos DB
该 GitHub 存储库在 loader 目录中包含了一个 Python 项目。 它用于将示例旅行文档加载到 Azure Cosmos DB 中。
设置环境
通过运行以下命令在 loader 目录中设置 Python 虚拟环境:
python -m venv venv
激活环境并在 loader 目录中安装依赖项:
venv\Scripts\activate
python -m pip install -r requirements.txt
在 loader 目录中创建一个名为 .env 的文件,用于存储以下环境变量:
OPENAI_API_KEY="<your OpenAI key>"
MONGO_CONNECTION_STRING="mongodb+srv:<your connection string from Azure Cosmos DB>"
加载文档和矢量
Python 文件 main.py 用作将数据加载到 Azure Cosmos DB 的中央入口点。 此代码处理来自 GitHub 存储库的示例旅行数据,包括有关船舶和目的地的信息。 该代码还会为每艘邮轮和目的地生成旅行行程套餐,让旅行者可以使用 AI 代理进行预订。 CosmosDBLoader 工具负责在 Azure Cosmos DB 实例中创建集合、矢量嵌入和索引。
下面是 main.py 的内容:
from cosmosdbloader import CosmosDBLoader
from itinerarybuilder import ItineraryBuilder
import json
cosmosdb_loader = CosmosDBLoader(DB_Name='travel')
#read in ship data
with open('documents/ships.json') as file:
ship_json = json.load(file)
#read in destination data
with open('documents/destinations.json') as file:
destinations_json = json.load(file)
builder = ItineraryBuilder(ship_json['ships'],destinations_json['destinations'])
# Create five itinerary packages
itinerary = builder.build(5)
# Save itinerary packages to Cosmos DB
cosmosdb_loader.load_data(itinerary,'itinerary')
# Save destinations to Cosmos DB
cosmosdb_loader.load_data(destinations_json['destinations'],'destinations')
# Save ships to Cosmos DB, create vector store
collection = cosmosdb_loader.load_vectors(ship_json['ships'],'ships')
# Add text search index to ship name
collection.create_index([('name', 'text')])
通过从 loader 目录运行以下命令,即可加载文档、加载矢量并创建索引:
python main.py
下面是 main.py 的输出:
--build itinerary--
--load itinerary--
--load destinations--
--load vectors ships--
使用 Python FastAPI 构建 AI 旅行代理
该 AI 旅行代理通过 Python FastAPI 托管在后端 API 中,便于与前端用户界面集成。 API 项目将 LLM 提示与数据层(特别是 Azure Cosmos DB 中的矢量和文档)联系起来,以处理代理请求。
该代理还会使用各种工具,特别是 API 服务层提供的 Python 函数。 本文重点介绍 API 代码中 AI 代理所需的代码。
GitHub 存储库中的 API 项目结构如下:
- 数据建模组件使用 Pydantic 模型。
- Web 层组件负责路由请求和管理通信。
- 服务层组件负责主要业务逻辑和与数据层、LangChain Agent 和代理工具的交互。
- 数据层组件负责与 Azure Cosmos DB for MongoDB 交互以进行文档存储和矢量搜索。
设置 API 环境
我们使用 Python 版本 3.11.4 进行 API 的开发和测试。
在 api 目录中设置 Python 虚拟环境:
python -m venv venv
使用 api 目录中的 requirements 文件激活环境并安装依赖项:
venv\Scripts\activate
python -m pip install -r requirements.txt
在 api 目录中创建一个名为 .env 的文件,用于存储环境变量:
OPENAI_API_KEY="<your Open AI key>"
MONGO_CONNECTION_STRING="mongodb+srv:<your connection string from Azure Cosmos DB>"
配置环境并设置变量后,请从 api 目录运行以下命令以启动服务器:
python app.py
默认情况下,FastAPI 服务器在 localhost 环回 127.0.0.1 端口 8000 上启动。 可以使用以下 localhost 地址访问 Swagger 文档:http://127.0.0.1:8000/docs
。
将会话用于 AI 代理记忆
旅行代理必须能够在正在进行的对话中引用先前提供的信息。 在 LLM 的上下文中,此功能通常称为记忆。
为了实现此目标,请使用存储在 Azure Cosmos DB 实例中的聊天消息历史记录。 每个聊天会话的历史记录都通过会话 ID 存储,以确保只有当前对话会话中的消息可访问。 这一必要性是 API 中存在 Get Session
方法的原因。 它是一种用于管理 Web 会话的占位符方法,用于说明聊天消息历史记录的使用。
对 /session/
选择“试用”。
{
"session_id": "0505a645526f4d68a3603ef01efaab19"
}
对于该 AI 代理,你只需要模拟一个会话。 存根方法仅返回生成的会话 ID 以跟踪消息历史记录。 在实际实施中,此会话将存储在 Azure Cosmos DB 中,并可能存储在 React localStorage
中。
下面是 Web/session.py 的内容:
@router.get("/")
def get_session():
return {'session_id':str(uuid.uuid4().hex)}
开始与 AI 旅行代理对话
使用从上一步获取的会话 ID 开始与 AI 代理的新对话,以便可以验证其功能。 通过提交以下短语进行测试:“我想度过一个轻松的假期。”
对 /agent/agent_chat
选择“试用”。
使用此示例参数:
{
"input": "I want to take a relaxing vacation.",
"session_id": "0505a645526f4d68a3603ef01efaab19"
}
初始执行结果推荐了 Tranquil Breeze Cruise 和 Fantasy Seas Adventure Cruise,因为代理预计它们是通过矢量搜索可获得的最轻松的游轮巡游。 这些文档在 API data.mongodb.travel.similarity_search()
的数据层中调用的 similarity_search_with_score
中得分最高。
出于调试目的,相似性搜索分数显示为 API 的输出。 下面是调用 data.mongodb.travel.similarity_search()
后的输出:
0.8394561085977978
0.8086545112328692
2
提示
如果未返回用于矢量搜索的文档,请根据需要在 data.mongodb.travel.similarity_search()
中修改 similarity_search_with_score
限制或分数筛选器值 ([doc for doc, score in docs if score >=.78]
)。
首次调用 agent_chat
时会在 Azure Cosmos DB 中创建一个名为 history
的新集合,以按会话存储对话。 此调用使代理能够根据需要访问存储的聊天消息历史记录。 使用相同参数的后续 agent_chat
执行会产生不同的结果,因为它会从记忆中提取结果。
演练 AI 代理
将 AI 代理集成到 API 中时,Web 搜索组件负责发起所有请求。 紧接着 Web 搜索组件的是搜索服务,最后是数据组件。
在此特定例子下,你使用连接到 Azure Cosmos DB 的 MongoDB 数据搜索。 这些层通过驻留在服务层中的 AI 代理和 AI 代理工具代码促进模型组件的交换。 此方法可实现数据源的无缝互换性。 它还会使用其他更复杂的功能或工具扩展 AI 代理的能力。
服务层
服务层是核心业务逻辑的基石。 在此特定方案中,服务层充当 LangChain Agent 代码存储库的关键角色。 它有助于将用户提示与适用于 AI 代理的 Azure Cosmos DB 数据、聊天内存和代理函数无缝集成。
服务层使用单一数据库模式模块来处理 init.py 文件中与代理相关的初始化。 下面是 service/init.py 的内容:
from dotenv import load_dotenv
from os import environ
from langchain.globals import set_llm_cache
from langchain_openai import ChatOpenAI
from langchain_mongodb.chat_message_histories import MongoDBChatMessageHistory
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.runnables.history import RunnableWithMessageHistory
from langchain.agents import AgentExecutor, create_openai_tools_agent
from service import TravelAgentTools as agent_tools
load_dotenv(override=False)
chat : ChatOpenAI | None=None
agent_with_chat_history : RunnableWithMessageHistory | None=None
def LLM_init():
global chat,agent_with_chat_history
chat = ChatOpenAI(model_name="gpt-3.5-turbo-16k",temperature=0)
tools = [agent_tools.vacation_lookup, agent_tools.itinerary_lookup, agent_tools.book_cruise ]
prompt = ChatPromptTemplate.from_messages(
[
(
"system",
"You are a helpful and friendly travel assistant for a cruise company. Answer travel questions to the best of your ability providing only relevant information. In order to book a cruise you will need to capture the person's name.",
),
MessagesPlaceholder(variable_name="chat_history"),
("user", "Answer should be embedded in html tags. {input}"),
MessagesPlaceholder(variable_name="agent_scratchpad"),
]
)
#Answer should be embedded in HTML tags. Only answer questions related to cruise travel, If you can not answer respond with \"I am here to assist with your travel questions.\".
agent = create_openai_tools_agent(chat, tools, prompt)
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
agent_with_chat_history = RunnableWithMessageHistory(
agent_executor,
lambda session_id: MongoDBChatMessageHistory( database_name="travel",
collection_name="history",
connection_string=environ.get("MONGO_CONNECTION_STRING"),
session_id=session_id),
input_messages_key="input",
history_messages_key="chat_history",
)
LLM_init()
init.py 文件使用 load_dotenv(override=False)
方法从 .env 文件启动环境变量的加载。 然后会为代理实例化名为 agent_with_chat_history
的全局变量。 此代理旨在通过 TravelAgent.py 使用。
在模块初始化期间调用 LLM_init()
方法,通过 API Web 层配置 AI 代理以进行对话。 OpenAI chat
对象通过 GPT-3.5 模型实例化,并包含模型名称和温度等特定参数。 chat
对象、工具列表和提示模板组合在一起以生成 AgentExecutor
,作为 AI 旅行代理运行。
具有历史记录 agent_with_chat_history
的代理通过具有聊天历史记录 (MongoDBChatMessageHistory
) 的 RunnableWithMessageHistory
建立。 此操作使它能够通过 Azure Cosmos DB 维护完整的聊天历史记录。
提示
LLM 提示最初以简单的陈述“你是一家邮轮公司的乐于助人且友好的旅行助手”开头。但是,测试表明,你可以通过加入“以你的最佳能力回答旅行问题”的说明来获得更一致的结果,只提供相关的信息。 要预订游轮,记录人员姓名至关重要。”结果以 HTML 格式显示,以增强 Web 界面的视觉吸引力。
代理工具
工具是代理可以用来与世界互动的界面,通常通过函数调用来完成。
创建代理时,必须为其提供一组它可使用的工具。 @tool
修饰器提供了定义自定义工具的最直接方法。
默认情况下,修饰器使用函数名称作为工具名称,但你可以通过提供字符串作为第一个参数来替换它。 该修饰器使用函数的文档字符串作为工具的说明,因此它需要预配文档字符串。
下面是 service/TravelAgentTools.py 的内容:
from langchain_core.tools import tool
from langchain.docstore.document import Document
from data.mongodb import travel
from model.travel import Ship
@tool
def vacation_lookup(input:str) -> list[Document]:
"""find information on vacations and trips"""
ships: list[Ship] = travel.similarity_search(input)
content = ""
for ship in ships:
content += f" Cruise ship {ship.name} description: {ship.description} with amenities {'/n-'.join(ship.amenities)} "
return content
@tool
def itinerary_lookup(ship_name:str) -> str:
"""find ship itinerary, cruise packages and destinations by ship name"""
it = travel.itnerary_search(ship_name)
results = ""
for i in it:
results += f" Cruise Package {i.Name} room prices: {'/n-'.join(i.Rooms)} schedule: {'/n-'.join(i.Schedule)}"
return results
@tool
def book_cruise(package_name:str, passenger_name:str, room: str )-> str:
"""book cruise using package name and passenger name and room """
print(f"Package: {package_name} passenger: {passenger_name} room: {room}")
# LLM defaults empty name to John Doe
if passenger_name == "John Doe":
return "In order to book a cruise I need to know your name."
else:
if room == '':
return "which room would you like to book"
return "Cruise has been booked, ref number is 343242"
TravelAgentTools.py 文件定义了三个工具:
vacation_lookup
针对 Azure Cosmos DB 执行矢量搜索。 它使用similarity_search
检索具有相关性的旅行相关材料。itinerary_lookup
检索指定游轮的游轮套餐详情和时间表。book_cruise
为乘客预订游轮套餐。
可能需要特定说明(“为了预订游轮,我需要知道你的姓名”)以确保获取乘客的姓名和房间号来预订游轮套餐,即便你在 LLM 提示中加入了此类说明。
AI 代理
代理的基本概念是使用语言模型来选择要执行的操作序列。
下面是 service/TravelAgent.py 的内容:
from .init import agent_with_chat_history
from model.prompt import PromptResponse
import time
from dotenv import load_dotenv
load_dotenv(override=False)
def agent_chat(input:str, session_id:str)->str:
start_time = time.time()
results=agent_with_chat_history.invoke(
{"input": input},
config={"configurable": {"session_id": session_id}},
)
return PromptResponse(text=results["output"],ResponseSeconds=(time.time() - start_time))
TravelAgent.py 文件很简单,因为 agent_with_chat_history
及其依赖项(工具、提示和 LLM)在 init.py 文件中初始化和配置。 此文件使用从用户收到的输入以及用于对话记忆的会话 ID 来调用代理。 之后,将返回 PromptResponse
(模型/提示)以及代理的输出和响应时间。
AI 代理与 React 用户界面的集成
通过 API 成功加载数据和 AI 代理的可访问性后,你现在可以通过为你的旅游网站建立 Web 用户界面(使用 React)来完成该解决方案。 使用 React 的功能有助于展示 AI 代理与旅行网站的无缝集成。 此集成可实现用于处理问询和预订的对话旅行助手,从而增强用户体验。
为 React 设置环境
在测试 React 接口之前,安装 Node.js 和依赖项。
从 web 目录运行以下命令以执行项目依赖项的干净安装。 安装可能需要一些时间。
npm ci
接下来,在 web 目录中创建一个名为 .env 的文件,以帮助存储环境变量。 在新创建的 .env 文件中加入以下详细信息:
REACT_APP_API_HOST=http://127.0.0.1:8000
现在,从 web 目录运行以下命令以启动 React Web 用户界面:
npm start
运行上一个命令将打开 React web 应用程序。
演练 React web 界面
GitHub 存储库的 web 项目是一个简单的应用程序,它可以促进用户与 AI 代理的交互。 与代理对话所需的主要组件是 TravelAgent.js 和 ChatLayout.js。 Main.js 文件用作中央模块或用户登录页面。
主要
主组件充当应用程序的中心管理器。 它充当路由的指定入口点。 在渲染函数中,它生成 JSX 代码来描绘主页布局。 此布局包含应用程序的占位符元素(例如徽标和链接)、一个包含旅行代理组件的分区,以及包含关于应用程序性质的示例免责声明的页脚。
下面是 main.js 的内容:
import React, { Component } from 'react'
import { Stack, Link, Paper } from '@mui/material'
import TravelAgent from './TripPlanning/TravelAgent'
import './Main.css'
class Main extends Component {
constructor() {
super()
}
render() {
return (
<div className="Main">
<div className="Main-Header">
<Stack direction="row" spacing={5}>
<img src="/mainlogo.png" alt="Logo" height={'120px'} />
<Link
href="#"
sx={{ color: 'white', fontWeight: 'bold', fontSize: 18 }}
underline="hover"
>
Ships
</Link>
<Link
href="#"
sx={{ color: 'white', fontWeight: 'bold', fontSize: 18 }}
underline="hover"
>
Destinations
</Link>
</Stack>
</div>
<div className="Main-Body">
<div className="Main-Content">
<Paper elevation={3} sx={{p:1}} >
<Stack
direction="row"
justifyContent="space-evenly"
alignItems="center"
spacing={2}
>
<Link href="#">
<img
src={require('./images/destinations.png')} width={'400px'} />
</Link>
<TravelAgent ></TravelAgent>
<Link href="#">
<img
src={require('./images/ships.png')} width={'400px'} />
</Link>
</Stack>
</Paper>
</div>
</div>
<div className="Main-Footer">
<b>Disclaimer: Sample Application</b>
<br />
Please note that this sample application is provided for demonstration
purposes only and should not be used in production environments
without proper validation and testing.
</div>
</div>
)
}
}
export default Main
旅行代理
旅行代理组件的用途很简单:捕获用户输入并显示响应。 它在管理与后端 AI 代理的集成方面发挥着关键作用,主要是通过捕获会话并将用户提示转发到 FastAPI 服务。 生成的响应存储在一个数组中以供显示,由聊天布局组件支持。
以下是 TripPlanning/TravelAgent.js 的内容:
import React, { useState, useEffect } from 'react'
import { Button, Box, Link, Stack, TextField } from '@mui/material'
import SendIcon from '@mui/icons-material/Send'
import { Dialog, DialogContent } from '@mui/material'
import ChatLayout from './ChatLayout'
import './TravelAgent.css'
export default function TravelAgent() {
const [open, setOpen] = React.useState(false)
const [session, setSession] = useState('')
const [chatPrompt, setChatPrompt] = useState(
'I want to take a relaxing vacation.',
)
const [message, setMessage] = useState([
{
message: 'Hello, how can I assist you today?',
direction: 'left',
bg: '#E7FAEC',
},
])
const handlePrompt = (prompt) => {
setChatPrompt('')
setMessage((message) => [
...message,
{ message: prompt, direction: 'right', bg: '#E7F4FA' },
])
console.log(session)
fetch(process.env.REACT_APP_API_HOST + '/agent/agent_chat', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ input: prompt, session_id: session }),
})
.then((response) => response.json())
.then((res) => {
setMessage((message) => [
...message,
{ message: res.text, direction: 'left', bg: '#E7FAEC' },
])
})
}
const handleSession = () => {
fetch(process.env.REACT_APP_API_HOST + '/session/')
.then((response) => response.json())
.then((res) => {
setSession(res.session_id)
})
}
const handleClickOpen = () => {
setOpen(true)
}
const handleClose = (value) => {
setOpen(false)
}
useEffect(() => {
if (session === '') handleSession()
}, [])
return (
<Box>
<Dialog onClose={handleClose} open={open} maxWidth="md" fullWidth="true">
<DialogContent>
<Stack>
<Box sx={{ height: '500px' }}>
<div className="AgentArea">
<ChatLayout messages={message} />
</div>
</Box>
<Stack direction="row" spacing={0}>
<TextField
sx={{ width: '80%' }}
variant="outlined"
label="Message"
helperText="Chat with AI Travel Agent"
defaultValue="I want to take a relaxing vacation."
value={chatPrompt}
onChange={(event) => setChatPrompt(event.target.value)}
></TextField>
<Button
variant="contained"
endIcon={<SendIcon />}
sx={{ mb: 3, ml: 3, mt: 1 }}
onClick={(event) => handlePrompt(chatPrompt)}
>
Submit
</Button>
</Stack>
</Stack>
</DialogContent>
</Dialog>
<Link href="#" onClick={() => handleClickOpen()}>
<img src={require('.././images/planvoyage.png')} width={'400px'} />
</Link>
</Box>
)
}
选择“轻松计划航程”以打开旅行助手。
Chat layout
聊天布局组件负责监督聊天的排列。 它可以系统地处理聊天消息并实现 message
JSON 对象中指定的格式。
下面是 TripPlanning/ChatLayout.js 的内容:
import React from 'react'
import { Box, Stack } from '@mui/material'
import parse from 'html-react-parser'
import './ChatLayout.css'
export default function ChatLayout(messages) {
return (
<Stack direction="column" spacing="1">
{messages.messages.map((obj, i = 0) => (
<div className="bubbleContainer" key={i}>
<Box
key={i++}
className="bubble"
sx={{ float: obj.direction, fontSize: '10pt', background: obj.bg }}
>
<div>{parse(obj.message)}</div>
</Box>
</div>
))}
</Stack>
)
}
用户提示位于右侧,颜色为蓝色。 AI 旅行代理的响应位于左侧,颜色为绿色。 如下图所示,HTML 格式的响应在对话中得到了考虑。
当你的 AI 代理准备好进入生产环境时,你可以使用语义缓存将查询性能提高 80%,并降低 LLM 推理和 API 调用成本。 若要实现语义缓存,请参阅 Stochastic Coder 博客上的这篇文章。