网站首页 > 博客文章 正文
前言
老顾前面介绍了《老顾深度解析【字节跳动的AI项目DeerFlow】源码(一)》、《老顾深度解析【字节跳动的AI项目DeerFlow】源码之协调者(二)》、《老顾深度解析【字节跳动的AI项目DeerFlow】源码之规划者(三)》、今天老顾给大家介绍另一个角色:人。
此角色就是需要人进行干预,需要补充一些相关信息。然后再重点介绍一下前后端的交互逻辑。
用户提出的问题:作为40岁的男人,如何减肥?规划者Planner会结合背景调查进行分析,规划者Planner分析后,会在前端界面上显示【Edit plan】和【Start research】;提示用户是Edit Plan进行人工中断来修改计划 或者 直接Start Research调用执行者。
这里我们就介绍人工中断的场景:“再增加运动器材的推荐”。
Agent流程图
我们先来看看整体的LangGraph的流程图,先上源码
这个源码就是我们前一篇文章中介绍的交互流程。我们看一下人工中断human_feedback在哪个位置
builder.add_node("human_feedback", human_feedback_node)
我们发现这里只有定义,那是怎么流转到人工中断节点的呢?
下面是规划者的方法节点,里面定了返回的节点,一个是人工中断,一个是报告。
def planner_node(
state: State, config: RunnableConfig
) -> Command[Literal["human_feedback", "reporter"]]:
前一篇文章介绍规划者Planner时,介绍了人工中断的逻辑,这里就不作重复介绍了。
人工中断Agent
来看看源码
我们来分析一下代码
current_plan = state.get("current_plan", "")
获得规划者设计的内容current_plan 。
auto_accepted_plan = state.get("auto_accepted_plan", False)
上面代码是获取【是否自动接受规划者的内容】的配置,这个配置代表是否不需要人工中断,直接调用执行者就行了。
if not auto_accepted_plan:
feedback = interrupt("Please Review the Plan.")
符合人工中断条件,会调用interrupt方法,这个方法会暂停整个Graph执行,等待用户在前端的输入
前端交互
用户在前端进行咨询时,请求的接口是/api/chat/stream
上面的代码就是请求的入口
thread_id = request.thread_id
if thread_id == "__default__":
thread_id = str(uuid4())
thread_id代表session会话,也是通过thread_id对不同的用户咨询进行隔离的。
我们继续往下看,
_astream_workflow_generator方法
上面的红色框的if条件,如果用户没有点击Edit Plan这个按钮,这段红色框架就不会执行。
那我们看看如果用户点击了Edit Plan按钮,进行计划补充信息,然后再咨询提交“再增加运动器材的推荐”,我们看看请求的参数
里面有个interrupt_feedback参数,对应的值为edit_plan;在看看messages参数就是用户补充的内容。
我们再看看入口请求的代码
if not auto_accepted_plan and interrupt_feedback:
resume_msg = f"[{interrupt_feedback}]"
# add the last message to the resume message
if messages:
resume_msg += f" {messages[-1]['content']}"
logger.info(f"Resume message: {resume_msg}")
input_ = Command(resume=resume_msg)
interrupt_feedback变量的值为edit_plan了,那条件为真,进入if分支。
resume_msg变量就是edit_plan加上用户的补充内容{messages[-1]['content']}。
最后resume_msg的值为: [edit_plan] 再增加运动器材的推荐
后面就是最主要的对象Command了,创建它并赋予resume参数。就是命令对象,resume参数是表示中断恢复。
执行graph
但是在上次中断的节点处恢复,也就是下面图中的红箭头标识的interrupt处。
中断恢复
我们继续往下看中断恢复后的代码
if feedback and str(feedback).upper().startswith("[EDIT_PLAN]"):
return Command(
update={
"messages": [
HumanMessage(content=feedback, name="feedback"),
],
},
goto="planner",
)
如果用户选择的是修改计划补充相关的信息,就再此调用Planner规划者Agent。
Start Research
如果用户不选择Edit Plan,那另一个选择就是Start Research
我来看看请求参数是什么样子
interrupt_feedback变量的值为accepted了,那我们看看下面的代码
如果是accepted表示接收规划者计划的内容,后面就goto=research_team流转到了执行者Agent
总结
上面就是人工中断的整体逻辑,更偏向工程化,没有和大模型进行交互,所以没有提示词。
上面讲解大家一定不要忘了有一个thread_id参数,这个参数的作用就是代表一次的咨询。
到这里人工中断Agent就介绍完了,后面会带来比较核心的执行者Agent。
好了,今天就介绍到这里,谢谢大家,记得关注老顾哦!!!
老顾的动力,藏在你的关注里 —— 精品文章,持续上新,别错过~
【相关系列文章】
老顾深度解析【字节跳动的AI项目DeerFlow】源码(一)
猜你喜欢
- 2025-07-28 告别频繁登录!Nuxt3 + TS + Vue3实战:双Token无感刷新方案全解析
- 2025-07-28 SpringBoot实现单点登录(SSO)的4种方案
- 2025-07-28 随机密聊 匿名聊天室程序源码(随机匿名聊天在线)
- 2025-07-28 SpringBoot大文件上传卡死?分块切割术搞定GB级传输,速度飙升!
- 2025-07-28 Java 微服务从源码实战开始 | Gitee 项目推荐
- 2025-07-28 轻量级埋点sdk搭建,便捷更全面(埋点sdk是什么)
- 2025-07-28 Spring Boot 实现文件秒传功能(springboot上传文件到指定文件夹)
- 2025-07-28 项目中不用redis分布式锁,怎么防止用户重复提交?
- 2025-07-28 SpringBoot项目日志打印traceId生成
- 2025-07-28 如何实现PC端网站扫码登录操作?(网页 扫码)
你 发表评论:
欢迎- 08-06nginx 反向代理
- 08-06跨表插入连续的日期,sheetsname函数#excel技巧
- 08-06初中生也能学的编程,不走弯路,先用后学
- 08-06find命令的“七种武器”:远不止-name和-type
- 08-06恶意代码常见的编程方式
- 08-06kali2021ping 外网不通
- 08-06因为一个函数strtok踩坑,我被老工程师无情嘲笑了
- 08-06hadoop集群搭建详细方法
- 23℃nginx 反向代理
- 最近发表
- 标签列表
-
- ifneq (61)
- 字符串长度在线 (61)
- googlecloud (64)
- powershellfor (73)
- messagesource (71)
- plsql64位 (73)
- vueproxytable (64)
- npminstallsave (63)
- #NAME? (61)
- promise.race (63)
- 2019cad序列号和密钥激活码 (62)
- window.performance (66)
- qt删除文件夹 (72)
- mysqlcaching_sha2_password (64)
- nacos启动失败 (64)
- ssh-add (70)
- yarnnode (62)
- abstractqueuedsynchronizer (64)
- source~/.bashrc没有那个文件或目录 (65)
- springboot整合activiti工作流 (70)
- jmeter插件下载 (61)
- 抓包分析 (60)
- idea创建mavenweb项目 (65)
- qcombobox样式表 (68)
- pastemac (61)
本文暂时没有评论,来添加一个吧(●'◡'●)