Skip to main content
与 AI 代理的对话很少是线性的。你可能想要重新表述一个问题、重新生成一个你不满意的响应,或者探索一条完全不同的对话路径,而不会丢失之前的工作。分支聊天将版本控制语义引入你的聊天界面。每次编辑都会创建一个新分支,你可以自由地在它们之间导航。
此功能需要 LangGraph Agent Server。请在本地使用 langgraph dev 运行您的代理,或将其部署到 LangSmith 以使用此模式。

什么是分支聊天?

分支聊天将对话视为一棵树,而不是一个列表。每条消息都是一个节点,编辑消息或重新生成响应会从该点创建一个分叉。原始路径作为同级分支被保留,因此用户可以在不同的对话轨迹之间来回切换。 关键功能:
  • 编辑任何用户消息: 重写之前的提示,并从该点重新运行代理
  • 重新生成任何 AI 响应: 要求代理为相同的输入产生不同的答案
  • 导航分支: 使用每条消息的分支控件在对话的不同版本之间切换

设置带历史记录的 useStream

要启用分支功能,请传递 fetchStateHistory: true,以便 useStream 检索分支操作所需的检查点元数据。 定义一个与你的代理状态模式匹配的 TypeScript 接口,并将其作为类型参数传递给 useStream,以实现对状态值的类型安全访问。在下面的示例中,将 typeof myAgent 替换为你的接口名称:

理解消息元数据

getMessagesMetadata(msg) 函数返回每条消息的分支信息:
当一条消息只有一个版本时,branchOptions 包含一个条目。在编辑或重新生成后,新的分支 ID 会被添加到 branchOptions,你可以在它们之间导航。

编辑消息

要编辑用户消息并创建新分支:
  1. 从消息的元数据中获取 parent_checkpoint
  2. 使用该检查点提交编辑后的消息
  3. 代理从该点重新运行,创建一个新分支
编辑后:
  • 消息的 branchOptions 获得一个新条目
  • 视图自动切换到新分支
  • 代理从分叉点使用更新后的消息重新运行
  • 原始版本被保留,并可通过分支切换器访问

重新生成响应

要在不更改输入的情况下重新生成 AI 响应:
  1. 从 AI 消息的元数据中获取 parent_checkpoint
  2. 使用 undefined 输入和父检查点提交
  3. 代理产生一个新的响应,创建一个新分支
每次重新生成都会为该位置的 AI 消息创建一个新分支。然后用户可以使用分支切换器来比较不同的响应。
重新生成对于非确定性代理很有用。由于 LLM 输出随温度变化,重新生成相同的提示通常会产生有意义的不同响应。

构建分支切换器

当一条消息有多个分支时,显示一个紧凑的内联控件,包含当前版本索引和导航箭头:
当用户点击分支箭头时,调用 stream.setBranch(branchId) 将对话视图切换到该分支。这是即时的,因为所有分支数据已通过 fetchStateHistory: true 加载。
切换分支不仅影响目标消息,还影响所有后续消息。如果你切换到消息 3 的不同版本,消息 4、5、6 等也将更新以反映跟随该版本的对话。

分支在底层如何工作

LangGraph 将每个状态转换持久化为一个检查点。当你使用 checkpoint 参数提交时,后端从该点分叉,而不是追加到当前对话。结果是一个树结构:
每个分支都是对话树中的一条独立路径。切换分支会更新显示的消息,但不会删除任何数据。所有分支都持久化在检查点存储中。

完整的消息组件

这是一个结合了消息显示、编辑、重新生成和分支切换的完整组件:

与乐观更新结合

将分支与乐观更新结合,以实现无缝的编辑体验。当用户保存编辑时,在服务器响应之前乐观地显示更新后的消息:

添加键盘导航

为高级用户添加键盘快捷键来导航分支:
Alt + ← / Alt + → 是分支导航的自然映射,因为它反映了浏览器的后退/前进导航。

最佳实践

  • 始终启用 fetchStateHistory:没有它,getMessagesMetadata 无法返回分支信息。
  • 仅在存在多个分支时显示分支切换器1/1 指示器会增加杂乱而没有价值。
  • 在悬停时显示分支控件:分支导航箭头和编辑按钮应在悬停时出现,以保持界面整洁。
  • 保持分支切换器紧凑:它内联于消息控件中,不应主导界面。
  • 保留滚动位置:切换分支时,尝试将视口锚定到已更改的消息。
  • 指示活动分支:使用微妙的视觉提示(例如,彩色点或分支标签),以便用户知道他们正在查看哪个分支。
  • 在流式传输时禁用控件:在代理主动流式传输响应时,不允许编辑或重新生成。在启用这些操作之前,请检查 stream.isLoading
  • 取消时保留编辑文本:如果用户开始编辑然后取消,请将文本区域重置为原始消息内容。
  • 使用深层分支树进行测试:频繁编辑和重新生成的用户可能会创建许多分支。确保分支切换器和数据处理保持高性能。