LangGraphJS 实战:如何实现自定义数据流式传输
langgraphjs 项目地址: https://gitcode.com/gh_mirrors/la/langgraphjs
前言
在现代应用开发中,流式传输(Streaming)技术已经成为提升用户体验的关键技术之一。LangGraphJS 作为一款强大的图计算框架,提供了灵活的流式传输能力,不仅支持常见的LLM令牌流式传输,还能实现自定义数据的流式处理。本文将深入探讨如何在LangGraphJS中实现自定义数据的流式传输。
基础概念
在开始之前,我们需要了解几个关键概念:
- 流式传输(Streaming):一种数据传输方式,允许数据在生成过程中逐步传输,而不需要等待所有数据准备完毕
- 节点(Node):LangGraphJS中的基本计算单元,可以执行特定任务
- 图(Graph):由节点和边组成的计算结构,定义了数据流动的路径
准备工作
首先确保已安装必要的依赖包:
npm install @langchain/langgraph @langchain/core
方法一:使用.stream方法实现自定义流
构建图结构
我们首先创建一个简单的图,其中包含一个自定义节点:
import {
StateGraph,
MessagesAnnotation,
LangGraphRunnableConfig,
} from "@langchain/langgraph";
const myNode = async (
_state: typeof MessagesAnnotation.State,
config: LangGraphRunnableConfig
) => {
const chunks = [
"Four",
"score",
"and",
"seven",
"years",
"ago",
"our",
"fathers",
"...",
];
for (const chunk of chunks) {
// 使用streamMode=custom模式写入要流式传输的数据块
config.writer?.(chunk);
}
return {
messages: [{
role: "assistant",
content: chunks.join(" "),
}],
};
};
const graph = new StateGraph(MessagesAnnotation)
.addNode("model", myNode)
.addEdge("__start__", "model")
.compile();
流式传输实现
使用.stream
方法并设置streamMode: "custom"
参数来实现流式传输:
const inputs = [{
role: "user",
content: "What are you thinking about?",
}];
const stream = await graph.stream(
{ messages: inputs },
{ streamMode: "custom" }
);
for await (const chunk of stream) {
console.log(chunk);
}
执行结果会逐步输出:
Four
score
and
seven
years
ago
our
fathers
...
多模式流式传输
在实际应用中,我们可能需要同时获取自定义数据和状态更新:
const streamMultiple = await graph.stream(
{ messages: inputs },
{ streamMode: ["custom", "updates"] }
);
for await (const chunk of streamMultiple) {
console.log(chunk);
}
输出结果会包含两种类型的数据:
[ 'custom', 'Four' ]
[ 'custom', 'score' ]
...
[ 'updates', { model: { messages: [Array] } } ]
方法二:使用.streamEvents实现自定义流
构建图结构
另一种方式是使用dispatchCustomEvent
方法:
import { dispatchCustomEvent } from "@langchain/core/callbacks/dispatch";
const graphNode = async (_state: typeof MessagesAnnotation.State) => {
const chunks = [
"Four",
"score",
"and",
"seven",
"years",
"ago",
"our",
"fathers",
"...",
];
for (const chunk of chunks) {
await dispatchCustomEvent("my_custom_event", { chunk });
}
return {
messages: [{
role: "assistant",
content: chunks.join(" "),
}],
};
};
const graphWithDispatch = new StateGraph(MessagesAnnotation)
.addNode("model", graphNode)
.addEdge("__start__", "model")
.compile();
流式传输实现
使用.streamEvents
方法捕获自定义事件:
const eventStream = await graphWithDispatch.streamEvents(
{
messages: [{
role: "user",
content: "What are you thinking about?",
}]
},
{
version: "v2",
},
);
for await (const { event, name, data } of eventStream) {
if (event === "on_custom_event" && name === "my_custom_event") {
console.log(`${data.chunk}|`);
}
}
输出结果为:
Four|
score|
and|
seven|
years|
ago|
our|
fathers|
...|
应用场景分析
自定义数据流式传输在以下场景中特别有用:
- 长任务进度监控:当执行耗时较长的任务时,可以通过流式传输实时报告进度
- 用户界面更新:前端应用可以接收流式数据并实时更新UI
- 调试与日志:开发过程中可以流式传输调试信息
- 多阶段任务:复杂任务的不同阶段可以通过自定义事件进行区分
性能考量
在使用流式传输时,需要注意以下几点:
- 网络开销:频繁的小数据包传输可能增加网络负担
- 错误处理:需要妥善处理流式传输过程中可能出现的网络中断
- 背压管理:当消费者处理速度跟不上生产者时,需要有适当的背压机制
总结
LangGraphJS提供了两种灵活的方式来实现自定义数据的流式传输:
- .stream方法:简单直接,适合需要快速实现流式传输的场景
- .streamEvents方法:功能更强大,适合需要精细控制事件流的场景
开发者可以根据具体需求选择合适的方式。对于大多数应用场景,.stream
方法已经足够;而对于需要更复杂事件处理的场景,.streamEvents
方法提供了更大的灵活性。
通过合理利用流式传输技术,可以显著提升应用的响应性和用户体验,特别是在处理长时间运行的任务时。
langgraphjs 项目地址: https://gitcode.com/gh_mirrors/la/langgraphjs
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考