注意:这是一篇由 Fiverr 技术主管 Elisha Kramer 撰写的客座博客文章。他也是 Assaf Elovic 领导的 gpt-researcher
Github 顶级项目的贡献者之一。
在体验了新的 LangGraph Cloud 功能后,我们非常兴奋,不得不写一篇关于它的文章。下面,我们将展示我们如何部署 LangGraph Cloud Host 并从 GPT Researcher 前端 (NextJS) 查询它。
什么是 GPT Researcher?
GPT Researcher 是一个开源的自主代理,旨在对各种任务进行全面的在线研究。该开源项目在过去一年中越来越受欢迎,拥有超过 1.3 万颗星和 4 千多名开发人员的社区。
GPT Researcher 也随着时间的推移不断发展,最初是一个成功的 RAG 实现,现在使用带有流行的 LangGraph 框架的多代理。
但仍然缺少一块。GPT Researcher 还没有一个顶级的前端应用程序,仍然基于简单的 HTML 和 CSS 构建。我们很高兴推出我们最新的客户端,它使用 NextJS 构建,旨在提供最佳的研究体验!在此处查看演示。
LangGraph 如何融入其中?
当我们开始尝试构建能够通过问题进行推理的上下文感知 AI 代理时,我们发现了 LangChain 库和 LangGraph。
具体来说,我们对 LangGraph 的概念着迷:一个框架,可以使我们构建复杂的多代理流程,其中 AI 代理与其他代理协调,带来他们独特的视角并审查彼此的工作。
事实证明,LangGraph 非常适合!并且能够轻松地将我们的新前端连接到基于云的 GPT Researcher 版本,这听起来好得令人难以置信。
什么是 LangGraph Cloud?
LangGraph Cloud Host 背后的概念与 GraphQL API Server 背后的概念非常相似。
GraphQL API 服务器
- 可以帮助抽象化对数据库的访问
- 可以利用服务器语言的任何库
同样,LangGraph API 服务器也可以
- 抽象化对 LangGraph 的访问
- 利用 LangGraph 中使用的任何 pip 包
本质上,您正在部署一个 Python 服务器,其中内置了 LangGraph。在您进行此操作时,您会免费获得很多东西;以下是 LangGraph Cloud Host 上自动公开的 API 端点,以实现轻松的任务触发和图编辑。
我们部署了什么?
在我们的案例中,大部分工作是由 GPT-Researcher 的创始人 Assaf 完成的,当时他构建了一个利用 LangGraph 的多代理工作流程。(随意阅读这篇早期文章中的冒险经历:如何使用多代理协作构建终极 AI 自动化。)
一旦使用 LangGraph 构建了该多代理流程,就为未来的一些轻松胜利奠定了基础。几周后,Harrison(LangChain 的 CEO)介入并创建了一个拉取请求,使我们能够轻松部署 Assaf 预构建的 LangGraph:这是 GPT Researcher PR。
该 PR 的美妙之处在于,它使我们的 GPT-Researcher LangGraph 可以轻松地通过 API 调用进行部署、编辑和使用自定义参数触发。哇!只需 4 个更改的文件即可从我们的开发环境转变为可扩展的生产就绪服务!
查询 LangGraph API 服务器
我花了一段时间才完全理解前 2 个步骤的简单性。触发多代理 LLM 工作流程不可能如此简单...对吧?
事实证明,就是这么简单。
在 Assaf 和 Harrison 代码的基础上,我们所需要做的就是以下步骤。
步骤 1:观看 Harrison 的部署教程
步骤 2:通过 LangSmith GUI 的“Deployments”选项卡部署我们的自定义 LangGraph。
在我们的案例中,我选择了我的 GPT Researcher 项目 fork,并指向 GPT Researcher multi_agents 目录中的 langgraph.json 配置文件(见下文)
步骤 3:将我的环境变量添加到我的 LangGraph Cloud 部署中。
这些应该足够了
请注意,在上面的屏幕截图中,LangGraph Cloud 将自动为我创建一个“Tracing Project”。
这意味着我们可以获得与 MVP 多代理流程相同的 LangSmith 跟踪优势。以下是它的外观
这是您获得的功能 - 一个强大的工具,用于
- 使用户能够可视化和检查后端数据流
- 质量保证调试 - 即,我们的 AI 流程的输入或输出在哪些方面可以改进
步骤 4:查询新部署的 LangGraph。
这是一个 React 代码示例
import { getHost } from '../../helpers/getHost';
import { Client } from "@langchain/langgraph-sdk";
import { task } from '../../config/task';
export async function startLanggraphResearch(newQuestion, report_source) {
// Update the task query with the new question
task.task.query = newQuestion;
task.task.source = report_source;
const host = getHost({purpose: 'langgraph-gui'});
const client = new Client({apiUrl: host});
// List all assistants
const assistants = await client.assistants.search({
metadata: null,
offset: 0,
limit: 10,
});
const agent = assistants[0];
// Start a new thread
const thread = await client.threads.create();
// Start a streaming run
const input = task;
const streamResponse = client.runs.stream(
thread["thread_id"],
agent["assistant_id"],
{
input,
},
);
return {streamResponse, host, thread_id: thread["thread_id"]};
}
在文件顶部导入的 task 对象可以被视为我们的 API 请求对象。它实际上与 Assaf 的 LangGraph 使用的 task.json 文件 完全相同。
getHost 函数返回 localhost:8123(对于 langgraph-cli 服务)或我们部署到的 LangGraph Cloud 服务器的域名。
这就是全部内容。上面的代码使我们能够在 LangGraph 服务器上触发运行 - 这在 LangSmith 用户界面上是完全可观察的!以下是上述代码的延续,它向用户显示 LangGraph 状态(每个任务)的状态,因为我们的多代理流程按部就班地运行
const langsmithGuiLink = `https://smith.langchain.com/studio/thread/${thread_id}?baseUrl=${host}`;
let previousChunk = null;
for await (const chunk of streamResponse) {
console.log(chunk);
if (chunk.data.report != null && chunk.data.report != "Full report content here") {
setOrderedData((prevOrder) => [...prevOrder, { ...chunk.data, output: chunk.data.report, type: 'report' }]);
setLoading(false);
} else if (previousChunk) {
const differences = findDifferences(previousChunk, chunk);
setOrderedData((prevOrder) => [...prevOrder, { type: 'differences', content: 'differences', output: JSON.stringify(differences) }]);
}
previousChunk = chunk;
}
}
请注意,在早期的代码片段中,我们使用了 client.runs.stream
方法。
这意味着 LangGraph API 服务器将以块的形式向我们反馈更新。这些块可以包含:当前正在运行的作业的更新状态或我们的 Python 脚本在已部署的 LangGraph 服务器上遇到的任何自定义错误。
在我们的案例中,我们希望向用户展示 LangGraph API 作业的自定义逐场记录 - 因此,我们还添加了一个 findDifferences
函数,其作用是计算两个 JavaScript 对象之间的差异。
如果 Graph 完成报告,则该报告将显示给用户。
如果 Graph 实时进行了一些字段编辑,则 Graph 中的这些差异将显示给用户。
总结
在这篇博文中,我们展示了如何通过 React 和 LangGraph Cloud 触发我们的 LangGraph 多代理流程。这些流程模仿人类推理,使其非常复杂。但是,正如上面的演练所示,一个优雅的 API 简化了流程,并使一切都轻松就位。