面试记录:有做过智能体规划吗?
前言
智能体规划,也称agent planning
,是指智能体在某个状态下,如何进行规划,如何进行选择,如何进行执行,如何进行反馈,如何进行更新。
但是呢,如果直接从LangGraph
开始,可能对这个概念并没有特别清楚,我们先一步步来。
智能体规划
规划方法其实有很多种,这里就介绍一下相对来说比较复杂的一种:P&E
,也就是Planning and Execution
。
该方法本质上也是构建一个有向、无环的工作流结构(也称DAG
),每个节点即为大模型智能体的一次处理过程,期间输出一个JSON
,要求有着严格的输出格式。
其中,格式虽然可以自定义,但是本质上包含:
id
:任务索引,用于维持任务的唯一性;name
:任务名称,用于描述任务的内容;dependes_on
:任务依赖,用于描述当前任务依赖的节点;output
:任务输出,用于描述当前任务输出的内容;accept
:任务接收条件,用于检测最终输出结果是否满足要求;
如果你还希望在每个节点给出更神奇的操作,可以继续添加一个tool
属性。
当然,无论是accept
还是tool
,可选是其中一个特点,另一个特点就是可以直接使用本地脚本或者lambda
方法,可以大幅提升自定义程度。
一个流程简单但也麻烦的一个例子
我们用一个小例子尝试一下。
这个例子流程上没多少节点,但是比较麻烦:
第一步:
检测所有大写字母
若大写字母数量低于一半 → 输出原串全小写并结束;
若大写字母多于(或等于)一半 → 输出“进入第二步”,并进入第二步;
第二步:
比较【检测得到的大写串】与【找出的小写串】的长度,谁长输出谁。
用人脑智能判断当然是简单的,用Python
脚本写起来也没有那么麻烦的。
于是,首先,我们先规定一下流程:
graph LR A(开始)-->B[输入]-->C[大写字母数量]-->D{少于一半?}--是-->E[[输出原串小写]]-->F(结束) D--否-->G[小写字母数量]-->H{大写多?}--是-->I[[输出大写部分]]-->F C-->H--否-->J[[输出小写部分]]-->F
粗暴的面向过程解决方案
如果面向过程去写这个东西,会让事情变得非常简单:
1 | def detect_upper(s: str) -> str: |
P&E
如果按照P&E
模板完成这件事的话,接下来就首先按照流程图给出JSON
格式的DAS
,如下:
1 | def planner(input_text: str) -> Dict[str, Any]: |
接下来,我们将根据这个JSON
实现其中的逻辑,包括每个节点的tool
,节点的args
,以及进入节点后跳转的route
。
整段代码放在这里:
1 | from __future__ import annotations |
看上去虽然有点乱乱的,但是根据这样一个JSON
,最终也能逐步完成流程。
LangGraph
当然,这只是一种实现方法。如果每个任务都这样配置,未免也还是有点太奇怪了。如果我们要更方便地完成这个项目,其实LangGraph
有着得天独厚的优势,那就是,它本身就自带DAS
构建库。
所以,本质上,我们用LangGraph
配置add_node(node)
和add_edge(START, node)
的时候,我们就是在用类似P&E
的格式创建这样一张DAS
。只不过,LangGraph
相对而言更成体系一些,而且中间状态流转有着更强大的引擎支撑,不需要过于纠结中间过程的规范。就像这样:
1 | from __future__ import annotations |
总的来说,代码量差距不大,只是LangGraph
有引擎支撑,P&E
没有罢了。