zhangjinyang
2025-05-07 622dde272b2f762a4a3fb84574586098768c4b94
docs: 工作流自定义节点文档
1个文件已修改
1个文件已添加
151 ■■■■■ 已修改文件
docs/.vitepress/config.mts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/zh/development/ai/custom-node.md 148 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/.vitepress/config.mts
@@ -149,6 +149,9 @@
                {text: '知识库', link: '/ai/knowledge'},
                {text: 'apiKey', link: '/ai/apiKey'},
                {text: 'Ollama', link: '/ai/ollama'},
                {text: '工作流', collapsed: false, items: [
                    {text: '自定义节点', link: '/ai/custom-node'},
                    ]},
            ]
        },
    ]
docs/zh/development/ai/custom-node.md
New file
@@ -0,0 +1,148 @@
# 自定义节点
自定义节点,需要前端添加节点信息后,后端也要新增对应的处理逻辑和方法。
## 前端
在  `src/pages/ai/workflowDesign/customNode` 文件夹下预置了一些自定义节点,可作为参考,
下面介绍一下怎么添加自定义节点。
### 新增节点信息
在 `src/pages/ai/workflowDesign/customNode` 文件夹下新建一个 `yourNode.ts` 文件,里面包含了节点信息,如下:
```typescript
export default {
    'your-node': { // 节点唯一标识
        title: '节点名称',
        description: '描述', // 描述
        icon: ' svg 图标', // 图标,可到 https://remixicon.com 获取
        sortNo: 100, // 节点排序
        group: 'base', // 节点位置: 'base' 基础节点 | 'tools' 业务节点,
        rootClass: '', // 根节点容器的样式类名
        rootStyle: '', // 根节点容器的样式。
        parameters: [ // 输入参数
            {
                name: 'paramName', // 参数名称
                nameDisabled: true, // 是否禁用修改参数名称
                title: 'paramTitle', // 参数标题
                dataType: 'String', // 参数类型
                required: true, // 是否必填
                description: '描述', // 参数描述
            },
        ],
        parametersEnable: true, // 是否启用输入参数
        parametersAddEnable: true, // 是否允许添加输入参数
        outputDefs: [], // 输出参数,同输入参数
        outputDefsEnable: true, // 是否启用输出参数
        outputDefsAddEnable: true, // 是否允许添加输出参数
        render: (parent, node, flowInstance) => { // 节点渲染函数
            parent.innerHTML =
                `<select style="width: 100%">
                    <option>test</option>
                    <option>test1</option>
                    <option>test2</option>
                </select>`;
            parent.querySelector('select')
                ?.addEventListener('change', (e) => {
                    console.log('select change: ', e);
                    flowInstance.updateNodeData(node.id, {
                        attrName: e.target.value
                    });
                })
            ;
            console.log('render: ', node, flowInstance);
        },
        onUpdate: (parent, node) => { // 监听节点数据更新
            console.log('onUpdate: ', node);
        },
        forms: [  // 节点表单
            {
                type: 'heading', // 'input' | 'textarea' | 'select' | 'slider' | 'heading'
                label: '表单头',
            },
            {
                type: 'select',
                label: '文件类型',
                description: '请选择生成的文件类型',
                name: 'suffix', // 属性名称
                defaultValue: 'docx',
                options: [
                    {
                        label: 'docx',
                        value: 'docx'
                    }
                ]
            }
        ],
    }
}
```
### 引用节点信息
将新增的节点信息添加到同目录下的 `index.ts` 文件中。
```
import yourNode from './yourNode.ts'
export default {
    ...yourNode,
}
```
## 后端
后端使用了 [tinyflow](https://www.tinyflow.cn/zh/) 和 [agents-flex](https://agentsflex.com) 作为工作流的实现,可点击查看对应文档。
### 继承 BaseNode 类
继承 `com.agentsflex.core.chain.node.BaseNode` 类,并实现 `execute` 方法。
```java
public class YourNode extends BaseNode {
    @Override
    protected Map<String, Object> execute(Chain chain) {
        Map<String, Object> res = new HashMap<>();
        // 获取输入参数
        Map<String, Object> map = chain.getParameterValues(this);
        // 获取输出参数定义
        List<Parameter> outputDefs = getOutputDefs();
        // 执行节点逻辑,并将结果放入 res 中返回。
        return res;
    }
}
```
### 继承 BaseNodeParser 类
继承 `dev.tinyflow.core.parser.BaseNodeParser` 类,并实现 `parse` 方法。
```java
public class YourNodeParser extends BaseNodeParser {
    @Override
    public ChainNode parse(JSONObject jsonObject, Tinyflow tinyflow) {
        // 获取节点数据
        JSONObject data = getData(jsonObject);
        // 创建自定义节点
        YourNode yourNode = new YourNode();
        // 添加输入参数
        addParameters(yourNode, data);
        // 添加输出参数
        addOutputDefs(yourNode, data);
        return docNode;
    }
    // 节点名称,要和前端节点名称保持一致
    public String getNodeName() {
        return "your-node";
    }
}
```
### 注册节点
找到 `tech.aiflowy.ai.utils.TinyFlowConfigService` 类的 `setExtraNodeParser` 方法。
添加如下代码:
```java
YourNodeParser yourNodeParser = new YourNodeParser();
chainParser.addNodeParser(yourNodeParser.getNodeName(), yourNodeParser);
```