Files
Agents-Flex1/docs/zh/core/chain.md
2025-08-27 19:57:21 +08:00

274 lines
8.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Chain 执行链
执行链Chain是由多个节点Node按照一定顺序编排、组合而成的链条用于实现复杂任务的自动化执行。
在执行链中,通常包含开始节点、中间节点和结束节点。通过合理组织这些节点,可以实现各种复杂的业务逻辑。
在 agents-flex 中,内置了多种节点类型,可以满足不同场景的需求。此外,还可以与 [Tinyflow](https://www.tinyflow.cn/zh/core/node.html) 结合使用,进一步扩展节点功能,获取更多强大的节点类型。关于两者结合的具体案例,可以参考 [AIFlowy](https://aiflowy.tech/zh/product/workflow/what_is_workflow.html) 工作流部分的文档。
## 简单示例
以下是一个简单的执行链示例,展示了如何创建包含开始节点、中间节点和结束节点的执行链,并设置节点之间的连接关系,最后执行该执行链:
```java
public static void main(String[] args) {
// 创建执行链
Chain chain = new Chain();
// 创建开始节点
StartNode startNode = new StartNode();
startNode.setId("1");
chain.addNode(startNode);
// 创建中间节点(动态代码节点)
JsExecNode jsExecNode = new JsExecNode();
jsExecNode.setId("2");
jsExecNode.setCode("console.log('hello world')");
chain.addNode(jsExecNode);
// 创建结束节点
EndNode endNode = new EndNode();
endNode.setId("3");
endNode.setMessage("success");
chain.addNode(endNode);
// 创建 1-2 的边
ChainEdge edge12 = new ChainEdge();
edge12.setSource("1");
edge12.setTarget("2");
chain.addEdge(edge12);
// 创建 2-3 的边
ChainEdge edge23 = new ChainEdge();
edge23.setSource("2");
edge23.setTarget("3");
chain.addEdge(edge23);
// 执行执行链
Map<String, Object> result = chain.executeForResult(new HashMap<>());
System.out.println(result);
}
```
## 节点
在 agents-flex 中,所有节点都继承自 `com.agentsflex.core.chain.node.BaseNode` 类。除了公共参数外,每个节点类型还具有各自的特定参数。以下是两种常见节点类型的介绍:
### 大模型节点LlmNode
大模型节点用于调用大型语言模型LLM实现如文本生成、问答等复杂功能。其主要参数包括
- `llm`:大模型实例。
- `chatOptions`:聊天参数,默认为 `ChatOptions.DEFAULT`
- `userPrompt`:用户提示词。
- `userPromptTemplate`:用户提示词模板。
- `systemPrompt`:系统提示词。
- `systemPromptTemplate`:系统提示词模板。
- `outType`:输出类型,可选值包括 `text``markdown``json` 等。
代码如下:
```java
public class LlmNode extends BaseNode {
protected Llm llm;
protected ChatOptions chatOptions = ChatOptions.DEFAULT;
protected String userPrompt;
protected TextPromptTemplate userPromptTemplate;
protected String systemPrompt;
protected TextPromptTemplate systemPromptTemplate;
protected String outType = "text"; //text markdown json
// 其他相关代码...
}
```
### 动态代码节点CodeNode
动态代码节点允许用户编写自定义代码逻辑,并在执行链中动态执行,从而增加了执行链的灵活性。
其核心参数为 `code`,表示要执行的代码。代码如下:
```java
public abstract class CodeNode extends BaseNode {
protected String code;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
@Override
protected Map<String, Object> execute(Chain chain) {
if (StringUtil.noText(code)) {
throw new IllegalStateException("Code is null or blank.");
}
return executeCode(this.code, chain);
}
// 不同语言有不同的实现
protected abstract Map<String, Object> executeCode(String code, Chain chain);
}
```
目前支持以下几种语言:
- JavaScript`com.agentsflex.chain.node.JsExecNode`
- Groovy`com.agentsflex.chain.node.GroovyExecNode`
- QLExpress`com.agentsflex.chain.node.QLExpressExecNode`
## 边ChainEdge
边(`com.agentsflex.core.chain.ChainEdge`)用于连接节点,确保节点按照指定的顺序执行。可以通过调用 `setCondition` 方法为边设置执行条件,只有当满足条件时,才会执行下一个节点。
## 异步执行
`ChainNode` 中有一个属性 `async`,用于设置节点是否为异步执行,默认值为 `false`
设置为 `true` 后,节点将运行在单独的线程中。
## 循环执行
在 agents-flex 中,节点可以设置成循环执行,即重复执行该节点直到满足条件为止。
节点配置属性如下:
```java
// 是否启用循环执行
protected boolean loopEnable = false;
// 循环间隔时间(毫秒)
protected long loopIntervalMs = 1000;
// 跳出循环的条件表达式Groovy/SpEL 表达式)
protected NodeCondition loopBreakCondition;
// 0 表示不限制循环次数
protected int maxLoopCount = 0;
```
示例代码:
```java
public static void main(String[] args) {
Chain chain = new Chain();
ChainNode a = new ChainNode() {
@Override
protected Map<String, Object> execute(Chain chain) {
System.out.println("a 节点 >>> execute!");
return Maps.of();
}
};
a.setId("a");
chain.addNode(a);
ChainNode b = new ChainNode() {
@Override
protected Map<String, Object> execute(Chain chain) {
System.out.println("b 节点 >>> execute!");
// 模拟请求执行结果,并存入内存。
getMemory().put("result", getRes());
return Maps.of();
}
};
b.setId("b");
// 节点 b 开启循环执行
b.setLoopEnable(true);
// 循环间隔 500ms
b.setLoopIntervalMs(500);
// 设置循环结束条件
b.setLoopBreakCondition(new NodeCondition() {
@Override
public boolean check(Chain chain, NodeContext context) {
ContextMemory memory = context.getCurrentNode().getMemory();
// 当结果为5时结束循环。
return (int) memory.get("result") == 5;
}
});
chain.addNode(b);
ChainEdge ab = new ChainEdge();
ab.setSource("a");
ab.setTarget("b");
chain.addEdge(ab);
chain.executeForResult(new HashMap<>());
}
public static int getRes() {
return new Random().nextInt(10);
}
```
## 执行条件
在 agents-flex 中,节点和边都可以设置执行条件。执行条件通过 `com.agentsflex.core.chain.JsCodeCondition` 类实现,这意味着可以直接使用 JavaScript 代码来定义条件逻辑。
示例:
```java
public static void main(String[] args) {
Chain chain = new Chain();
TestNode a = new TestNode();
a.setId("a");
chain.addNode(a);
TestNode b = new TestNode(){
@Override
protected Map<String, Object> execute(Chain chain) {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("b");
return Maps.of();
}
};
b.setId("b");
// 设置 b 节点为异步执行
b.setAsync(true);
chain.addNode(b);
TestNode c = new TestNode();
c.setId("c");
chain.addNode(c);
TestNode d = new TestNode() {
@Override
protected Map<String, Object> execute(Chain chain) {
System.out.println("d: "+ Thread.currentThread().getId());
return Maps.of();
}
};
d.setId("d");
// 此处设置 d 节点的条件为上游节点执行完毕后才执行
d.setCondition(new JavascriptStringCondition("_context.isUpstreamFullyExecuted()"));
chain.addNode(d);
ChainEdge ab = new ChainEdge();
ab.setSource("a");
ab.setTarget("b");
chain.addEdge(ab);
ChainEdge ac = new ChainEdge();
ac.setSource("a");
ac.setTarget("c");
chain.addEdge(ac);
ChainEdge bd = new ChainEdge();
bd.setSource("b");
bd.setTarget("d");
chain.addEdge(bd);
ChainEdge cd = new ChainEdge();
cd.setSource("c");
cd.setTarget("d");
chain.addEdge(cd);
/**
* 最终执行顺序:
* B
* ↗ ↘
* A D
* ↘ ↗
* C
*/
chain.executeForResult(new HashMap<>());
}
```