Dify 通过导入 DSL 文件创建 Workflow 过程及实现

本文使用 Dify v0.9.2 版本,主要介绍 Dify 通过导入 DSL(或 URL)文件创建(或导出)Workflow 的操作过程及源码分析实现过程。Dify通过导入DSL文件创建Workflow过程及实现:https://z0yrmerhgi8.feishu.cn/wiki/KVIWwrcPMiOdDhk4FngcHrlgnJc

一.导入 DSL 文件创建 Workflow 过程

1.导入操作过程

点击"导入 DSL 文件"后,会弹出"导入 DSL"框,如下所示:

可以选择从文件导入,也可以选择从 URL 导入,如下所示:
在这里插入图片描述

2.导入操作 API

通过浏览器 Network 可看到,本子调用为 http://localhost:5001/console/api/apps/import 接口,如下所示:

该接口具体返回结果(Preview),如下所示:

该接口具体返回结果(json),如下所示:

{
    "id": "24a1f8d6-aad0-4099-b724-0cdd15d39dde",
    "name": "20240930_\u6a21\u578b\u7ade\u6280\u573a\uff08\u7b80\u5355\u5e76\u884c\uff09_v1",
    "description": "20240930_\u6a21\u578b\u7ade\u6280\u573a\uff08\u7b80\u5355\u5e76\u884c\uff09_v1",
    "mode": "advanced-chat",
    "icon_type": null,
    "icon": "\ud83e\udd16",
    "icon_background": "#FFEAD5",
    "icon_url": null,
    "enable_site": true,
    "enable_api": true,
    "model_config": null,
    "workflow": {
        "id": "c9721caf-6d43-413d-8447-136b1ba8ede0",
        "created_by": "12ab7619-6406-4df2-b2a4-c581e033d7fb",
        "created_at": 1729144453,
        "updated_by": null,
        "updated_at": null
    },
    "site": {
        "access_token": "PZ63qIcMMjL3W1Aa",
        "code": "PZ63qIcMMjL3W1Aa",
        "title": "20240930_\u6a21\u578b\u7ade\u6280\u573a\uff08\u7b80\u5355\u5e76\u884c\uff09_v1",
        "icon_type": null,
        "icon": "\ud83e\udd16",
        "icon_background": "#FFEAD5",
        "icon_url": null,
        "description": null,
        "default_language": "en-US",
        "chat_color_theme": null,
        "chat_color_theme_inverted": false,
        "customize_domain": null,
        "copyright": null,
        "privacy_policy": null,
        "custom_disclaimer": null,
        "customize_token_strategy": "not_allow",
        "prompt_public": false,
        "app_base_url": "http://127.0.0.1:3000",
        "show_workflow_steps": true,
        "use_icon_as_answer_icon": false,
        "created_by": "12ab7619-6406-4df2-b2a4-c581e033d7fb",
        "created_at": 1729144453,
        "updated_by": "12ab7619-6406-4df2-b2a4-c581e033d7fb",
        "updated_at": 1729144453
    },
    "api_base_url": "http://127.0.0.1:5001/v1",
    "use_icon_as_answer_icon": false,
    "created_by": "12ab7619-6406-4df2-b2a4-c581e033d7fb",
    "created_at": 1729144453,
    "updated_by": "12ab7619-6406-4df2-b2a4-c581e033d7fb",
    "updated_at": 1729144453,
    "deleted_tools": []
}

3.导出操作过程

因为导出 DSL 文件比较简单就不再详细介绍,主要实现为 api.add_resource(AppExportApi, "/apps/<uuid:app_id>/export"){"data": AppDslService.export_dsl(app_model=app_model, include_secret=args["include_secret"])}

二.导入 DSL 文件创建 Workflow 实现

0.整体实现流程

首先通过(伪)流程图方式分析"导入 DSL 文件"的函数调用流程,如下所示:

1.第 1 部分源码分析

主要是通过 DSL 文件导入,以及 URL 导入的路由,如下所示:

2.第 2 部分源码分析

最核心的是根据 AppMode 类型的不同,导入 DSL 文件,然后创建 App。如下所示:

# import dsl and create app
app_mode = AppMode.value_of(app_data.get("mode"))
if app_mode in {AppMode.ADVANCED_CHAT, AppMode.WORKFLOW}:
    app = cls._import_and_create_new_workflow_based_app(
        tenant_id=tenant_id,
        app_mode=app_mode,
        workflow_data=import_data.get("workflow"),
        account=account,
        name=name,
        description=description,
        icon_type=icon_type,
        icon=icon,
        icon_background=icon_background,
        use_icon_as_answer_icon=use_icon_as_answer_icon,
    )
elif app_mode in {AppMode.CHAT, AppMode.AGENT_CHAT, AppMode.COMPLETION}:
    app = cls._import_and_create_new_model_config_based_app(
        tenant_id=tenant_id,
        app_mode=app_mode,
        model_config_data=import_data.get("model_config"),
        account=account,
        name=name,
        description=description,
        icon_type=icon_type,
        icon=icon,
        icon_background=icon_background,
        use_icon_as_answer_icon=use_icon_as_answer_icon,
    )

3.第 3 部分源码分析

针对 AppMode.ADVANCED_CHAT, AppMode.WORKFLOW 的 AppMode 类型,导入 DSL 文件,创建 App 过程。主要是创建 App,并且初始化草稿 Workflow,如下所示:

(1)创建 App

app = cls._create_app(
    tenant_id=tenant_id,
    app_mode=app_mode,
    account=account,
    name=name,
    description=description,
    icon_type=icon_type,
    icon=icon,
    icon_background=icon_background,
    use_icon_as_answer_icon=use_icon_as_answer_icon,
)

首先创建 app,然后在 apps 数据表中插入记录,如下所示:

当 app 创建时,发送 app_was_created 事件,如下所示:

具体 app_was_created 事件执行逻辑,如下所示:

这段代码是一个事件处理器,用于在应用程序创建时自动创建一个已安装的应用实例。具体功能如下:

  • 监听 app_was_created 事件,当新应用被创建时触发。
  • 通过事件的发送者(即新创建的应用)获取相关信息(如租户 ID 和应用 ID)。
  • 创建一个 InstalledApp 实例,包含应用的租户 ID、应用 ID 及应用拥有者的租户 ID。
  • 将该实例添加到数据库会话中,并提交更改,以保存新创建的已安装应用记录。

这段代码实现了在应用程序创建时,自动生成一个站点记录的功能。具体概述如下:

  • 监听 app_was_created 事件:当一个新的应用被创建时触发。
  • 获取发送者和账户信息:sender 是触发事件的应用,kwargs 用于获取传递的账户信息(如界面语言)。
  • 创建 Site 实例:使用发送者(应用)的信息创建一个站点记录,包含应用的 ID、名称、图标信息、语言设置、自定义令牌策略等。
  • 生成站点代码:调用 Site.generate_code(16) 生成 16 位长度的唯一代码。
  • 记录创建者和更新者:存储应用的创建者和更新者信息。
  • 保存到数据库:将创建的站点记录添加到数据库会话中,并提交保存,以确保站点信息被持久化。

(2)初始化草稿 Workflow(同步工作流)

draft_workflow = workflow_service.sync_draft_workflow(
    app_model=app,
    graph=workflow_data.get("graph", {}),
    features=workflow_data.get("../core/app/features", {}),
    unique_hash=None,
    account=account,
    environment_variables=environment_variables,
    conversation_variables=conversation_variables,
)  # 同步草稿工作流

在 sync_draft_workflow()方法中,判断 draft workflow 是否存在,若不存在则创建,若存在则更新,并保存到 workflows 数据表中。然后触发 app_draft_workflow_was_synced 事件,如下所示:

app_draft_workflow_was_synced 事件的具体执行逻辑,如下所示:

在这里插入图片描述

这段代码实现了在草稿工作流同步完成后,对工具节点的管理功能。具体功能概述如下:

  • 监听 app_draft_workflow_was_synced 事件:当草稿工作流同步完成时触发。
  • 获取应用和节点数据:sender 代表触发事件的应用,kwargs 中包含同步的草稿工作流节点数据。
  • 遍历节点:从同步的工作流中获取所有节点,逐个检查其类型。
  • 处理工具节点:如果节点类型为工具节点:尝试将节点数据转换为 ToolEntity 实例;使用工具实体的信息获取工具的运行时;创建一个 ToolParameterConfigurationManager 实例,用于管理该工具的参数配置;删除该工具的参数缓存,以确保使用最新的参数配置。
  • 异常处理:如果在处理过程中发生异常(如工具不存在),捕获并忽略该异常。

(3)初始化草稿 Workflow(发布工作流)

workflow_service.publish_workflow(app_model=app, account=account, draft_workflow=draft_workflow)  # 发布工作流

首先创建新的 workflow,记录到数据表 workflows 中。然后触发 app_published_workflow_was_updated 事件。如下所示:

app_published_workflow_was_updated 事件的具体执行逻辑,如下所示:

这段代码实现了在应用发布工作流更新时,对工作流中数据集的管理和同步功能。具体功能概述如下:

  • 监听 app_published_workflow_was_updated 事件:当应用发布的工作流被更新时触发。
  • 获取应用和工作流信息:sender 代表触发事件的应用,published_workflow 是更新后的工作流数据,并将其类型转换为 Workflow
  • 提取数据集 ID:通过 get_dataset_ids_from_workflow 函数,从更新后的工作流中提取与知识检索节点相关的数据集 ID,并返回一个包含数据集 ID 的集合。
  • 查询应用数据集关联:从数据库中查询该应用当前的 AppDatasetJoin 关联数据集。
  • 计算新增和移除的数据集 ID。如果应用没有任何关联数据集,则所有提取的 ID 为新增数据集;如果有现有的数据集关联,则计算出新增的数据集 ID(added_dataset_ids)和需要移除的数据集 ID(removed_dataset_ids)。
  • 更新数据库。对于需要移除的数据集 ID,从 AppDatasetJoin 中删除相应记录;对于需要添加的数据集 ID,创建新的 AppDatasetJoin 记录,并添加到数据库。
  • 提交更改:最终将所有数据集的变更(新增或删除)提交到数据库以完成更新。

4.第 4 部分源码分析

针对 AppMode.CHAT, AppMode.AGENT_CHAT, AppMode.COMPLETION 的 AppMode 类型,导入 DSL 文件,创建 App 过程。如下所示:

(1)创建 App

app = cls._create_app(
    tenant_id=tenant_id,
    app_mode=app_mode,
    account=account,
    name=name,
    description=description,
    icon_type=icon_type,
    icon=icon,
    icon_background=icon_background,
    use_icon_as_answer_icon=use_icon_as_answer_icon,
)

首先创建 app,然后在 apps 数据表中插入记录。当 app 创建时,发送 app_was_created 事件。该部分代码逻辑和第 3 部分源码分析(创建 App)相同,就不再赘述。

(2)触发事件

app_model_config_was_updated.send(app, app_model_config=app_model_config)

触发 app_model_config_was_updated 事件,如下所示:

app_model_config_was_updated 事件的具体执行逻辑,如下所示:

这段代码的功能是在应用程序的模型配置更新时,根据新的模型配置同步与数据集的关联。具体功能概述如下:

  • 监听 app_model_config_was_updated 事件:当应用的模型配置更新时触发。
  • 获取应用和模型配置信息:sender 代表触发事件的应用,kwargs 中的 app_model_config 包含更新后的模型配置。
  • 提取数据集 ID:通过 get_dataset_ids_from_model_config 函数,从模型配置中提取与工具和数据集配置相关的 ID,包括代理模式中的工具以及数据集配置中的数据集,返回一个包含数据集 ID 的集合。
  • 查询现有的应用数据集关联:从数据库中查询该应用当前的 AppDatasetJoin 关联的数据集。
  • 计算新增和移除的数据集 ID。如果没有现有数据集关联,则所有提取的 ID 为新增数据集;如果有现有数据集关联,则计算出新增的数据集 ID(added_dataset_ids)和需要移除的数据集 ID(removed_dataset_ids)。
  • 更新数据库。对于需要移除的数据集 ID,从 AppDatasetJoin 表中删除相应的关联记录;对于需要添加的数据集 ID,创建新的 AppDatasetJoin 记录并添加到数据库。
  • 提交数据库会话:最终将所有对数据集关联的变更(新增或删除)提交到数据库。

三.删除 Workflow 过程

1.删除操作过程

(1)删除操作

因为 workflow 本质还是 app,所以删除 workflow 本质上还是删除 app,如下所示:

(2)调用接口

删除 workflow 调用接口为 http://localhost:5001/console/api/apps/3c32956e-96bd-4e19-9c47-fd06bb4c5890,如下所示:

(3)接口日志

在 PyCharm 控制台上可看到调用接口的日志,如下所示:

(4)任务日志

在 PyCharm 控制台上可看到执行异步任务(remove_app_and_related_data_task)的日志,如下所示:

2.删除操作实现

(1)任务执行逻辑

触发 remove_app_and_related_data_task 异步任务,具体执行逻辑如下所示:

(2)任务日志记录

执行异步任务(remove_app_and_related_data_task)的过程,本质上就是从相关数据表中删除 app 及相关数据,这个过程中产生的日志记录(日志级别为 INFO),如下所示:

[2024-10-18 13:46:30,516: INFO/MainProcess] Task tasks.remove_app_and_related_data_task.remove_app_and_related_data_task[e401ada0-bd53-4626-ac6d-fd69ba58f686] received
[2024-10-18 13:46:30,517: INFO/MainProcess] Start deleting app and related data: 7bdb51d6-f390-4b23-a59e-9cdbe2e93136:3c32956e-96bd-4e19-9c47-fd06bb4c5890
[2024-10-18 13:46:30,739: INFO/MainProcess] Deleted site cf995800-1808-4109-960c-f6246cbdb26f
[2024-10-18 13:46:30,758: INFO/MainProcess] Deleted installed app e125a5c8-b4a5-462d-bc9f-254abd1ab8eb
[2024-10-18 13:46:30,784: INFO/MainProcess] Deleted workflow 592fd414-204a-48aa-9ad5-7c1ac814d85d
[2024-10-18 13:46:30,789: INFO/MainProcess] Deleted workflow 782f46e7-4ee8-4064-9941-afcda22a6397
[2024-10-18 13:46:30,821: INFO/MainProcess] Deleted conversation variables for app 3c32956e-96bd-4e19-9c47-fd06bb4c5890
[2024-10-18 13:46:30,821: INFO/MainProcess] App and related data deleted: 3c32956e-96bd-4e19-9c47-fd06bb4c5890 latency: 0.30396559997461736
[2024-10-18 13:46:30,822: INFO/MainProcess] Task tasks.remove_app_and_related_data_task.remove_app_and_related_data_task[e401ada0-bd53-4626-ac6d-fd69ba58f686] succeeded in 0.3130000000819564s: None

(3)@shared_task 装饰器

@shared_task(queue="app_deletion", bind=True, max_retries=3) 代码是使用 Celery 定义一个共享任务的装饰器。定义了一个 Celery 任务,指定了其在处理应用删除操作时的队列、上下文绑定以及最大重试次数,便于实现异步任务管理和失败处理。具体含义和功能如下:

  • @shared_task:这是 Celery 的一个装饰器,用于将一个函数定义为可以被 Celery 调用的任务。它可在不同的模块中被共享和调用。
  • queue=“app_deletion”:指定任务将被发送到名为 app_deletion 的队列。这样可通过队列管理任务的执行,适用于需要异步处理的操作。队列包括 dataset、generation、mail、ops_trace 和 app_deletion。
  • bind=True:允许任务访问其上下文信息,特别是可以访问任务实例本身(通过 self 参数)。这对于任务重试、状态更新等操作很有用。
  • max_retries=3:定义任务最大重试次数。如果任务执行失败,Celery 会自动重新调度该任务,最多重试 3 次。如果超过这个次数,任务将标记为失败。

参考文献

[1] Dify 编排节点:https://docs.dify.ai/zh-hans/guides/workflow/orchestrate-node

[2] Dify通过导入DSL文件创建Workflow过程及实现:https://z0yrmerhgi8.feishu.cn/wiki/KVIWwrcPMiOdDhk4FngcHrlgnJc

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/917964.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Redis五大基本类型——List列表命令详解(命令用法详解+思维导图详解)

目录 一、List列表类型介绍 二、常见命令 1、LPUSH 2、LPUSHX 3、RPUSH 4、RPUSHX 5、LRANGE 6、LPOP 7、RPOP 8、LREM 9、LSET 10、LINDEX 11、LINSERT 12、LLEN 13、阻塞版本命令 BLPOP BRPOP 三、命令小结 相关内容&#xff1a; Redis五大基本类型——Ha…

有序数组的平方(leetcode 977)

一个数组&#xff0c;返回一个所有元素的平方之后依然是一个有序数组。&#xff08;数组中含负数&#xff09; 解法一&#xff1a;暴力解法 所有元素平方后再使用快速排序法重新排序&#xff0c;时间复杂度为O(nlogn)。 class Solution { public:vector<int> sortedSqu…

调用门提权

在我写的2.保护模式&#xff0b;段探测这篇文章中&#xff0c;我们提到了S位对于段描述符的控制&#xff0c;之前我们已经介绍了代码段和数据段&#xff0c;现在我们来把目光转到系统段 在这么多中结构里面&#xff0c;我们今天要介绍的就是编号为12的&#xff0c;32位调用门 结…

Web Service 学习笔记

Web Service 学习笔记 Web Service 基本概念 Web Service 即 web 服务&#xff0c;它是一种跨编程语言和跨操作系统平台的远程调用技术。 Java 中共有三种 Web Service 规范&#xff1a; JAX-WS(JAX-RPC): 基于 xml 数据JAXM&SAAJJAX-RS&#xff1a;基于 xml 或 json 数…

爬虫——JSON数据处理

第三节&#xff1a;JSON数据处理 在爬虫开发中&#xff0c;JSON&#xff08;JavaScript Object Notation&#xff09;是最常见的数据格式之一&#xff0c;特别是在从API或动态网页中抓取数据时。JSON格式因其结构简单、可读性强、易于与其他系统交互而广泛应用于前端与后端的数…

计算机编程中的设计模式及其在简化复杂系统设计中的应用

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 计算机编程中的设计模式及其在简化复杂系统设计中的应用 计算机编程中的设计模式及其在简化复杂系统设计中的应用 计算机编程中的…

【Tealscale + Headscale + 自建服务器】异地组网笔记

文章目录 效果为什么要用 Headscale云服务器安装 Headscale配置 config.yaml创建反向代理搭建管理 UI授权管理 UI添加互联设备参考 效果 首先是连接情况&#xff0c;双端都连接上自建的 Headscale&#xff0c; 手机使用移动流量&#xff0c;测试一下 ping 值 再试试进入游戏 可…

单片机学习笔记 2. LED灯闪烁

目录 0、实现的功能 1、Keil工程 2、代码实现 0、实现的功能 LED灯闪烁 1、Keil工程 闪烁原理&#xff1a;需要进行软件延时达到人眼能分辨出来的效果。常用的延时方法有软件延时和定时器延时。此次先进行软件延时 具体操作步骤和之前的笔记一致。此次主要利用无符号整型的范…

【Cesium】自定义材质,添加带有方向的滚动路线

【Cesium】自定义材质&#xff0c;添加带有方向的滚动路线 &#x1f356; 前言&#x1f3b6;一、实现过程✨二、代码展示&#x1f3c0;三、运行结果&#x1f3c6;四、知识点提示 &#x1f356; 前言 【Cesium】自定义材质&#xff0c;添加带有方向的滚动路线 &#x1f3b6;一、…

Vue之插槽(slot)

插槽是vue中的一个非常强大且灵活的功能&#xff0c;在写组件时&#xff0c;可以为组件的使用者预留一些可以自定义内容的占位符。通过插槽&#xff0c;可以极大提高组件的客服用和灵活性。 插槽大体可以分为三类&#xff1a;默认插槽&#xff0c;具名插槽和作用域插槽。 下面…

从零开始深度学习:全连接层、损失函数与梯度下降的详尽指南

引言 在深度学习的领域&#xff0c;全连接层、损失函数与梯度下降是三块重要的基石。如果你正在踏上深度学习的旅程&#xff0c;理解它们是迈向成功的第一步。这篇文章将从概念到代码、从基础到进阶&#xff0c;详细剖析这三个主题&#xff0c;帮助你从小白成长为能够解决实际…

Python 绘图工具详解:使用 Matplotlib、Seaborn 和 Pyecharts 绘制散点图

目录 数据可视化1.使用 matplotlib 库matplotlib 库 2 .使用 seaborn 库seaborn 库 3 .使用 pyecharts库pyecharts库 注意1. 确保安装了所有必要的库2. 检查Jupyter Notebook的版本3. 使用render()方法保存为HTML文件4. 使用IFrame在Notebook中显示HTML文件5. 检查是否有其他输…

【C++】vector 类模拟实现:探索动态数组的奥秘

&#x1f31f; 快来参与讨论&#x1f4ac;&#xff0c;点赞&#x1f44d;、收藏⭐、分享&#x1f4e4;&#xff0c;共创活力社区。&#x1f31f; 如果你对string&#xff0c;vector还存在疑惑&#xff0c;欢迎阅读我之前的作品 &#xff1a; 之前文章&#x1f525;&#x1f52…

【ubuntu18.04】vm虚拟机复制粘贴键不能用-最后无奈换版本

我是ubuntu16版本的 之前费老大劲安装的vmware tools结果不能用 我又卸载掉&#xff0c;安装了open-vm-tools 首先删除VMware tools sudo vmware-uninstall-tools.pl sudo rm -rf /usr/lib/vmware-tools sudo apt-get autoremove open-vm-tools --purge再下载open-vm-tools s…

使用原生 OpenTelemetry 解锁各种可能性:优先考虑可靠性,而不是专有限制

作者&#xff1a;来自 Elastic Bahubali Shetti•Miguel Luna Elastic 现在支持使用 OTel Operator 在 Kubernetes 上部署和管理 Elastic Distributions of OpenTelemetry (EDOT)。SRE 现在可以访问开箱即用的配置和仪表板&#xff0c;这些配置和仪表板旨在通过 Elastic Observ…

【freertos】FreeRTOS信号量的介绍及使用

FreeRTOS信号量 一、概述二、PV原语三、函数接口1.创建一个计数信号量2.删除一个信号量3.信号量释放4.在中断释放信号量5.获取一个信号量&#xff0c;可以是二值信号量、计数信号量、互斥量。6.在中断获取一个信号量&#xff0c;可以是二值信号量、计数信号量7.创建一个二值信号…

【生物服务器】数据分析//论文润色/组学技术服务 、表观组分析、互作组分析、遗传转化实验、生物医学

DNA亲和纯化测序&#xff08;DAP-seq&#xff09;和组蛋白甲基化修饰是表观遗传学研究中两个重要的技术手段&#xff0c;它们在揭示基因表达调控机制和染色质结构动态变化中发挥着关键作用。然而&#xff0c;在实践过程中&#xff0c;这两种技术也存在一些痛点和挑战。 DNA亲和…

丹摩征文活动| 摩智云端深度解析:Faster R-CNN模型的训练与测试实战指南

目录 丹摩简介 文章前言Faster R-CNN的简介Faster RCNN的训练与测试提前准备1.1 mobaxterm&#xff08;远程连接服务器&#xff09;1.2 本文的源码下载 目标检测模型 Faster-Rcnn2.1云服务器平台 数据上传内置JupyterLab的使用本地连接使用DAMODEL实例获取实例的SSH访问信息通过…

二叉搜索树介绍

⼆叉搜索树 二叉搜索树的概念二叉搜索树的性能分析查找性能插入性能删除性能 二叉搜索树的插入二叉搜索树的查找二叉搜索树的删除⼆叉搜索树的实现代码测试代码 二叉搜索树key和key/value使⽤场景key搜索场景key/value搜索场景key/value⼆叉搜索树代码实现测试代码 二叉搜索树的…

7.揭秘C语言输入输出内幕:printf与scanf的深度剖析

揭秘C语言输入输出内幕&#xff1a;printf与scanf的深度剖析 C语言往期系列文章目录 往期回顾&#xff1a; VS 2022 社区版C语言的安装教程&#xff0c;不要再卡在下载0B/s啦C语言入门&#xff1a;解锁基础概念&#xff0c;动手实现首个C程序C语言概念之旅&#xff1a;解锁关…