Frontend
想深度使用 LangGraph 的所有原生高级功能,并愿意自己写 UI?选 useStream。
想在 React 中快速、省力地搭建一个高级 AI 聊天界面,不纠结 UI 细节?用 @assistant-ui/react 来消费 useStream 就是最佳实践。
pnpm add @langchain/react @langchain/core
@assistant-ui/react 提供了 CLI 工具(npx assistant-ui@latest create)来直接生成一个完整、独立、开箱即用的新项目 ,但它本身是一个组件库,并非只能用于生成项目。
LangGraph Platform 是 LangChain 公司提供的商业化云服务,useStream 是为这个平台设计的,自己写的后端不能用这个
问题, 如果不能使用useStream 那么关于langgraph 返回的所有内容, 思考内容 tools内容,都是通过前后端约定的形式来渲染展示是吗
基于你提供的 LangChain 前端文档,其核心心智模型可以总结为:以“流”为管道,以“状态”为中心的单向数据流架构。
这个模型可以用下面这个逻辑图来理解:
状态-流-UI
这个心智模型主要由四个核心概念组成:
⚙️ 1. 后端(Agent):状态的唯一源头
后端通过 createAgent 创建一个编译好的状态图。这个 Agent 不直接控制 UI,它的全部职责是:
- 管理状态:维护一个包含消息列表等信息的
State对象。 - 暴露流:将这个状态的变化以**流(Stream)**的形式暴露出来。
📡 2. 流(Stream):实时通信管道
这是连接前后端的“脐带”。它是一个全双工通道:
- 后端→前端:实时推送状态更新(新的消息片段、工具调用结果、中断事件等 )。
- 前端→后端:发送用户输入或对中断的响应(如批准、拒绝)。
🎣 3. 前端(Hook):状态的消费者与UI的驱动者
前端通过 useStream 这个 Hook 连接到后端流。它是整个前端的“大脑”,核心职责是:
- 订阅状态:它不直接处理原始数据流,而是将流式数据组装成一个响应式的、完整的应用状态对象,供你直接使用。你通过它访问
stream.messages、stream.toolCalls等属性。 - 驱动交互:提供
submit()等方法,让 UI 可以方便地将用户操作发回后端。
🧩 4. 模式(Patterns):状态驱动的UI渲染
这是心智模型中最“可见”的一层。文档中所有模式(Markdown消息、工具调用、人在回路、时间旅行)都不是孤立的功能,它们本质上都是在回答同一个问题:“如何将 useStream 提供的不同形态的状态,渲染成对应的UI组件?”
- 渲染消息:
stream.messages变化了,就渲染聊天泡泡。 - 展示工具调用:
stream.messages中出现了tool_call,就渲染成一个工具卡片。 - 人在回路:状态中出现
interrupt类型,就渲染一个审批框。
总结来说,这个心智模型的核心在于关注点分离:后端只负责计算和产出状态,前端只负责订阅状态并渲染UI。而“流”是两者之间那个声明式的、隐藏了网络细节的桥梁。
文档中的 Patterns(模式)可分为三大类,核心都是如何将 useStream 提供的不同状态渲染成具体的 UI 组件。
1. 渲染消息与输出
- Markdown 消息:解析并格式化渲染流式 Markdown,支持代码高亮。
- 结构化输出:将 Agent 返回的类型化数据渲染为自定义 UI 组件,而非纯文本。
- 推理过程:在可折叠区域中展示模型的“思考链”。
- 生成式 UI:根据自然语言描述,让 AI 动态生成用户界面。
2. 展示 Agent 行为
- 工具调用:将工具调用信息展示为带加载、错误状态的富媒体卡片。
- 人在回路:Agent 暂停等待人工审批时,渲染批准、拒 绝或编辑的操作界面。
3. 管理对话
- 分支聊天:支持编辑历史消息并重新生成回复,导航不同对话分支。
- 消息队列:用户可连续发送多条消息,Agent 按顺序依次处理。
额外:高级流
- 断线重连:从运行中的 Agent 流断开后可重新连接,不丢失进度。
- 时间旅行:查看并导航对话历史中的任意检查点,可从中恢复执行。
用这个架构理解“人在回路”和“时间旅行”其实很简单:
人在回路(Human-in-the-Loop):后端状态在关键时刻 “冻结” ,通过流发一个 “中断信号” 给前端。前端就显示一个“批准/拒绝”卡片。等你操作后,信号原路返回,状态 “解冻” 继续运行。
时间旅行(Time Travel):后端像个游戏,会自动存档(保存状态快照)。前端拿到 “存档列表” 让你选。你选一个旧存档,后端状态就回滚到那个点。你之后的操作,会从那里长出一条 “新分支” ,不影响原存档。
一句话总结:流里跑的不只是消息文本,更是 Agent 的“运行状态”。显示什么、怎么交互,全由这个状态决定。