跳至主要內容

Dify-3-工作流

程序员李某某大约 35 分钟

Dify-3-工作流

基本介绍

工作流通过将复杂的任务分解成较小的步骤(节点)降低系统复杂度,减少了对提示词技术和模型推理能力的依赖,提高了 LLM 应用面向复杂任务的性能,提升了系统的可解释性、稳定性和容错性。

Dify 工作流分为两种类型:

  • Chatflow:面向对话类情景,包括客户服务、语义搜索、以及其他需要在构建响应时进行多步逻辑的对话式应用程序。
  • Workflow:面向自动化和批处理情景,适合高质量翻译、数据分析、内容生成、电子邮件自动化等应用程序。

为解决自然语言输入中用户意图识别的复杂性,Chatflow 提供了问题理解类节点。相对于 Workflow 增加了 Chatbot 特性的支持,如:对话历史(Memory)、标注回复、Answer 节点等。

为解决自动化和批处理情景中复杂业务逻辑,工作流提供了丰富的逻辑节点,如代码节点、IF/ELSE 节点、模板转换、迭代节点等,除此之外也将提供定时和事件触发的能力,方便构建自动化流程。

常见案例

  • 客户服务

通过将 LLM 集成到您的客户服务系统中,您可以自动化回答常见问题,减轻支持团队的工作负担。 LLM 可以理解客户查询的上下文和意图,并实时生成有帮助且准确的回答。

  • 内容生成

无论您需要创建博客文章、产品描述还是营销材料,LLM 都可以通过生成高质量内容来帮助您。只需提供一个大纲或主题,LLM将利用其广泛的知识库来制作引人入胜、信息丰富且结构良好的内容。

  • 任务自动化

可以与各种任务管理系统集成,如 Trello、Slack、Lark、以自动化项目和任务管理。通过使用自然语言处理,LLM 可以理解和解释用户输入,创建任务,更新状态和分配优先级,无需手动干预。

  • 数据分析和报告

可以用于分析大型数据集并生成报告或摘要。通过提供相关信息给 LLM,它可以识别趋势、模式和洞察力,将原始数据转化为可操作的智能。对于希望做出数据驱动决策的企业来说,这尤其有价值。

  • 邮件自动化处理

LLM 可以用于起草电子邮件、社交媒体更新和其他形式的沟通。通过提供简要的大纲或关键要点,LLM 可以生成一个结构良好、连贯且与上下文相关的信息。这样可以节省大量时间,并确保您的回复清晰和专业。

如何开始

  • 从一个空白的工作流开始构建或者使用系统模版帮助你开始;
  • 熟悉基础操作,包括在画布上创建节点、连接和配置节点、调试工作流、查看运行历史等;
  • 保存并发布一个工作流;
  • 在已发布应用中运行或者通过 API 调用工作流;

关键概念

节点:节点是工作流的关键构成,通过连接不同功能的节点,执行工作流的一系列操作。

变量:变量用于串联工作流内前后节点的输入与输出,实现流程中的复杂处理逻辑,包含环境变量、环境变量和会话变量。

可用节点差异

  1. End 节点属于 Workflow 的结束节点,仅可在流程结束时选择。
  2. Answer 节点属于 Chatflow ,用于流式输出文本内容,并支持在流程中间步骤输出。
  3. Chatflow 内置聊天记忆(Memory),用于存储和传递多轮对话的历史消息,可在 LLM 、问题分类等节点内开启,Workflow 无 Memory 相关配置,无法开启。
  4. Chatflow 的开始节点内置变量包括:sys.querysys.filessys.conversation_idsys.user_id。Workflow 的开始节点内置变量包括:sys.filessys.user_id

变量

Workflow 和 Chatflow 类型应用由独立节点相构成。大部分节点设有输入和输出项,但每个节点的输入信息不一致,各个节点所输出的答复也不尽相同。

如何用一种固定的符号指代动态变化的内容? 变量作为一种动态数据容器,能够存储和传递不固定的内容,在不同的节点内被相互引用,实现信息在节点间的灵活通信。

系统变量指的是在 Chatflow / Workflow 应用内预设的系统级参数,可以被其它节点全局读取。系统级变量均以 sys 开头。其中带 "*" 标识的为只读变量。

Workflow 系统变量

Workflow 类型应用提供以下系统变量:

变量名称数据类型说明备注
sys.filesArray[File]文件参数,存储用户初始使用应用时上传的图片图片上传功能需在应用编排页右上角的 “功能” 处开启
*sys.user_idString用户 ID,每个用户在使用工作流应用时,系统会自动向用户分配唯一标识符,用以区分不同的对话用户

Chatflow 系统变量

Chatflow 类型应用提供以下系统变量:

变量名称数据类型说明备注
sys.queryString用户在对话框中初始输入的内容
sys.filesArray[File]用户在对话框内上传的图片图片上传功能需在应用编排页右上角的 “功能” 处开启
*sys.dialogue_countNumber用户在与 Chatflow 类型应用交互时的对话轮数。每轮对话后自动计数增加 1,可以和 if-else 节点搭配出丰富的分支逻辑。例如到第 X 轮对话时,回顾历史对话并给出分析
*sys.conversation_idString对话框交互会话的唯一标识符,将所有相关的消息分组到同一个对话中,确保 LLM 针对同一个主题和上下文持续对话
*sys.user_idString分配给每个应用用户的唯一标识符,用以区分不同的对话用户

环境变量

环境变量用于保护工作流内所涉及的敏感信息,例如运行工作流时所涉及的 API 密钥、数据库密码等。它们被存储在工作流程中,而不是代码中,以便在不同环境中共享。

支持以下三种数据类型:

  • String 字符串
  • Number 数字
  • Secret 密钥

环境变量拥有以下特性:

  • 环境变量可在大部分节点内全局引用;
  • 环境变量命名不可重复;
  • 环境变量为只读变量,不可写入;

会话变量

会话变量面向多轮对话场景,而 Workflow 类型应用的交互是线性而独立的,不存在多次对话交互的情况,因此会话变量仅适用于 Chatflow 类型(聊天助手 → 工作流编排)应用。

会话变量允许应用开发者在同一个 Chatflow 会话内,指定需要被临时存储的特定信息,并确保在当前工作流内的多轮对话内都能够引用该信息,如上下文、上传至对话框的文件(即将上线)、 用户在对话过程中所输入的偏好信息等。好比为 LLM 提供一个可以被随时查看的“备忘录”,避免因 LLM 记忆出错而导致的信息偏差。

例如你可以将用户在首轮对话时输入的语言偏好存储至会话变量中,LLM 在回答时将参考会话变量中的信息,并在后续的对话中使用指定的语言回复用户。

会话变量支持以下六种数据类型:

  • String 字符串
  • Number 数值
  • Object 对象
  • Array[string] 字符串数组
  • Array[number] 数值数组
  • Array[object] 对象数组

会话变量具有以下特性:

  • 会话变量可在大部分节点内全局引用;
  • 会话变量的写入需要使用变量赋值open in new window节点;
  • 会话变量为可读写变量;

关于如何将会话变量与变量赋值节点配合使用,请参考变量赋值open in new window节点说明。

上下文变量

上下文变量是 LLM 节点内定义的特殊变量类型,用于在提示词内插入外部检索的文本内容。

在常见的知识库问答应用中,知识库检索的下游节点一般为 LLM 节点,知识检索的 输出变量 result 需要配置在 LLM 节点中的 上下文变量 内关联赋值。关联后在提示词的合适位置插入 上下文变量 ,可以将外部检索到的知识插入到提示词中。

该变量除了可以作为 LLM 回复问题时的提示词上下文作为外部知识引入,由于其数据结构中包含了分段引用信息,同时可以支持应用端的 引用与归属open in new window 功能。

若上下文变量关联赋值的是上游节点的普通变量,例如开始节点的字符串类型变量,则上下文的变量同样可以作为外部知识引入,但 引用与归属 功能将会失效。

注意事项

  • 为避免变量名重复,节点命名不可重复
  • 节点的输出变量一般为固定变量,不可编辑

核心节点

开始(Start)

定义一个 workflow 流程启动的初始参数。

为启动工作流设置初始参数。

在开始节点中,您可以自定义启动工作流的输入变量。每个工作流都需要一个开始节点。

开始节点支持定义四种类型输入变量:

  • 文本
  • 段落
  • 下拉选项
  • 数字
  • 文件(即将推出)

配置完成后,工作流在执行时将提示您提供开始节点中定义的变量值。

Tip: 在Chatflow中,开始节点提供了内置系统变量:sys.querysys.files

sys.query 用于对话应用中的用户输入问题。

sys.files 用于对话中的文件上传,如上传图片,这需要与图片理解模型配合使用。

结束(End)

定义一个 workflow 流程结束的最终输出内容。

每一个工作流在完整执行后都需要至少一个结束节点,用于输出完整执行的最终结果。

结束节点为流程终止节点,后面无法再添加其他节点,工作流应用中只有运行到结束节点才会输出执行结果。若流程中出现条件分叉,则需要定义多个结束节点。

结束节点需要声明一个或多个输出变量,声明时可以引用任意上游节点的输出变量

Chatflow 内不支持结束节点

回复(Answer)

定义一个 Chatflow 流程中的回复内容。

你可以在文本编辑器中自由定义回复格式,包括自定义一段固定的文本内容、使用前置步骤中的输出变量作为回复内容、或者将自定义文本与变量组合后回复。

可随时加入节点将内容流式输出至对话回复,支持所见即所得配置模式并支持图文混排,如:

  1. 输出 LLM 节点回复内容
  2. 输出生成图片
  3. 输出纯文本

直接回复节点可以不作为最终的输出节点,作为流程过程节点时,可以在中间步骤流式输出结果。

大语言模型(LLM)

调用大语言模型回答问题或者对自然语言进行处理。

LLM 是 Chatflow/Workflow 的核心节点,利用大语言模型的对话/生成/分类/处理等能力,根据给定的提示词处理广泛的任务类型,并能够在工作流的不同环节使用。

应用场景

  • 意图识别,在客服对话情景中,对用户问题进行意图识别和分类,导向下游不同的流程。
  • 文本生成,在文章生成情景中,作为内容生成的节点,根据主题、关键词生成符合的文本内容。
  • 内容分类,在邮件批处理情景中,对邮件的类型进行自动化分类,如咨询/投诉/垃圾邮件。
  • 文本转换,在文本翻译情景中,将用户提供的文本内容翻译成指定语言。
  • 代码生成,在辅助编程情景中,根据用户的要求生成指定的业务代码,编写测试用例。
  • RAG,在知识库问答情景中,将检索到的相关知识和用户问题重新组织回复问题。
  • 图片理解,使用 vision 能力的多模态模型,能对图像内的信息进行理解和问答。

选择合适的模型,编写提示词,你可以在 Chatflow/Workflow 中构建出强大、可靠的解决方案。

配置步骤

  1. 选择模型,Dify 提供了全球主流模型的支持open in new window,包括 OpenAI 的 GPT 系列、Anthropic 的 Claude 系列、Google 的 Gemini 系列等,选择一个模型取决于其推理能力、成本、响应速度、上下文窗口等因素,你需要根据场景需求和任务类型选择合适的模型。
  2. 配置模型参数,模型参数用于控制模型的生成结果,例如温度、TopP,最大标记、回复格式等,为了方便选择系统同时提供了 3 套预设参数:创意,平衡和精确。
  3. 编写提示词,LLM 节点提供了一个易用的提示词编排页面,选择聊天模型或补全模型,会显示不同的提示词编排结构。
  4. 高级设置,可以开关记忆,设置记忆窗口,使用 Jinja-2 模版语言来进行更复杂的提示词等。

如果你是初次使用 Dify ,在 LLM 节点选择模型之前,需要在 系统设置—模型供应商 内提前完成模型配置open in new window

编写提示词

  • 在 LLM 节点内,你可以自定义模型输入提示词。

  • 如果选择聊天模型(Chat model),你可以自定义系统提示词(SYSTEM)/用户(USER)/助手(ASSISTANT)三部分内容。

  • 提示生成器:如果在编写系统提示词(SYSTEM)时没有好的头绪,也可以使用提示生成器功能,借助 AI 能力快速生成适合实际业务场景的提示词。

  • 在提示词编辑器中,你可以通过输入 “/” 或者 “{” 呼出 变量插入菜单,将 特殊变量块 或者 上游节点变量 插入到提示词中作为上下文内容。

上下文变量

高级功能

  • 记忆: 开启记忆后问题分类器的每次输入将包含对话中的聊天历史,以帮助 LLM 理解上文,提高对话交互中的问题理解能力。

  • 记忆窗口: 记忆窗口关闭时,系统会根据模型上下文窗口动态过滤聊天历史的传递数量;打开时用户可以精确控制聊天历史的传递数量(对数)。

  • 对话角色名设置: 由于模型在训练阶段的差异,不同模型对于角色名的指令遵循程度不同,如 Human/Assistant,Human/AI,人类/助手等等。为适配多模型的提示响应效果,系统提供了对话角色名的设置,修改对话角色名将会修改会话历史的角色前缀。

  • Jinja-2 模板: LLM 的提示词编辑器内支持 Jinja-2 模板语言,允许你借助 Jinja2 这一强大的 Python 模板语言,实现轻量级数据转换和逻辑处理,参考官方文档open in new window

知识检索(Knowledge Retrieval)

从知识库中检索与用户问题相关的文本内容,可作为下游 LLM 节点的上下文。

常见情景:构建基于外部数据/知识的 AI 问答系统(RAG)。

最基础的知识库问答应用的执行逻辑

  • 知识库检索作为 LLM 节点的前置步骤,在用户问题传递至 LLM 节点之前,先在知识检索节点内将匹配用户问题最相关的文本内容并召回
  • 随后在 LLM 节点内将用户问题与检索到的上下文一同作为输入,让 LLM 根据检索内容来回复问题。

配置流程

  1. 选择查询变量,用于作为输入来检索知识库中的相关文本分段,在常见的对话类应用中一般将开始节点的 sys.query 作为查询变量;
  2. 选择需要查询的知识库,可选知识库需要在 Dify 知识库内预先创建;
  3. 指定召回模式。自 9 月 1 日后,知识库的召回模式将自动切换为多路召回,不再建议使用 N 选 1 召回模式;
  4. 连接并配置下游节点,一般为 LLM 节点;

建议将知识库的召回模式切换为多路召回,详细说明请参考《在应用内集成知识库》open in new window

输出变量:知识检索的输出变量 result 为从知识库中检索到的相关文本分段。

  • 分段内容 -- content
  • 标题 -- title
  • 链接 -- url
  • 图标 -- icon
  • 元数据信息 -- metadata

配置下游节点

在常见的对话类应用中,知识库检索的下游节点一般为 LLM 节点,知识检索的输出变量 result 需要配置在 LLM 节点中的 上下文变量 内关联赋值。关联后你可以在提示词的合适位置插入 上下文变量

当用户提问时,若在知识检索中召回了相关文本,文本内容会作为上下文变量中的值填入提示词,提供 LLM 回复问题;若未在知识库检索中召回相关的文本,上下文变量值为空,LLM 则会直接回复用户问题。

该变量除了可以作为 LLM 回复问题时的提示词上下文作为外部知识参考引用,另外由于其数据结构中包含了分段引用信息,同时可以支持应用端的 引用与归属open in new window 功能。

问题分类(Question Classifier)

通过定义分类描述,问题分类器能够根据用户输入推理与之相匹配的分类并输出分类结果。

常见的使用情景包括客服对话意图分类、产品评价分类、邮件批量分类等。

在一个典型的产品客服问答场景中,问题分类器可以作为知识库检索的前置步骤,对用户输入问题意图进行分类处理,分类后导向下游不同的知识库查询相关的内容,以精确回复用户的问题。

场景示例

产品客服场景的示例:

  • 分类 1 :与售后相关的问题
  • 分类 2:与产品操作使用相关的问题
  • 分类 3 :其他问题

当用户输入不同的问题时,问题分类器会根据已设置的分类标签/描述自动完成分类:

  • “iPhone 14 如何设置通讯录联系人?” —> “与产品操作使用相关的问题”
  • “保修期限是多久?” —> 与售后相关的问题
  • “今天天气怎么样?” —> 其他问题

配置步骤:

  1. 选择输入变量,指用于分类的输入内容,客服问答场景下一般为用户输入的问题 sys.query;
  2. 选择推理模型,问题分类器基于大语言模型的自然语言分类和推理能力,选择合适的模型将有助于提升分类效果;
  3. 编写分类标签/描述,你可以手动添加多个分类,通过编写分类的关键词或者描述语句,让大语言模型更好的理解分类依据。
  4. **选择分类对应的下游节点,**问题分类节点完成分类之后,可以根据分类与下游节点的关系选择后续的流程路径。

高级设置

  • **指令:**你可以在 高级设置-指令 里补充附加指令,比如更丰富的分类依据,以增强问题分类器的分类能力。

  • **记忆:**开启记忆后问题分类器的每次输入将包含对话中的聊天历史,以帮助 LLM 理解上文,提高对话交互中的问题理解能力。

  • **记忆窗口:**记忆窗口关闭时,系统会根据模型上下文窗口动态过滤聊天历史的传递数量;打开时用户可以精确控制聊天历史的传递数量(对数)。

**输出变量:**class_name --- 即分类之后输出的分类名。你可以在下游节点需要时使用分类结果变量。

条件分支(IF/ELSE)

允许你根据 if/else 条件将 workflow 拆分成两个分支。

条件分支节点有六个部分:

  • IF 条件:选择变量,设置条件和满足条件的值;
  • IF 条件判断为 True,执行 IF 路径;
  • IF 条件判断为 False,执行 ELSE 路径;
  • ELIF 条件判断为 True,执行 ELIF 路径;
  • ELIF 条件判断为 False,继续判断下一个 ELIF 路径或执行最后的 ELSE 路径;

条件类型

  • 包含(Contains)
  • 不包含(Not contains)
  • 开始是(Start with)
  • 结束是(End with)
  • 是(Is)
  • 不是(Is not)
  • 为空(Is empty)
  • 不为空(Is not empty)

场景示例

文本总结工作流作为示例说明各个条件:

  • IF 条件: 选择开始节点中的 summarystyle 变量,条件为包含 技术
  • IF 条件判断为 True,执行 IF 路径,通过知识检索节点查询技术相关知识再到 LLM 节点回复
  • IF 条件判断为 False,但添加了 ELIF 条件,即 summarystyle 变量输入不包含技术,但 ELIF 条件内包含 科技,会检查 ELIF 内的条件是否为 True,然后执行路径内定义的步骤;
  • ELIF 内的条件为 False,即输入变量既不不包含 技术,也不包含 科技,继续判断下一个 ELIF 路径或执行最后的 ELSE 路径;
  • IF 条件判断为 False,即 summarystyle 变量输入不包含 技术,执行 ELSE 路径,通过 LLM2 节点进行回复(图中下半部分);

多重条件判断

涉及复杂的条件判断时,可以设置多重条件判断,在条件之间设置AND或者OR,即在条件之间取交集或者并集

代码执行(Code)

运行 Python / NodeJS 代码以在工作流程中执行数据转换等自定义逻辑。

它可以简化您的工作流程,适用于Arithmetic、JSON transform、文本处理等情景。

该节点极大地增强了开发人员的灵活性,使他们能够在工作流程中嵌入自定义的 Python 或 Javascript 脚本,并以预设节点无法达到的方式操作变量。通过配置选项,你可以指明所需的输入和输出变量,并撰写相应的执行代码:

如果您需要在代码节点中使用其他节点的变量,您需要在输入变量中定义变量名,并引用这些变量

结构化数据处理

在工作流中,经常要面对非结构化的数据处理,如JSON字符串的解析、提取、转换等。最典型的例子就是HTTP节点的数据处理,在常见的API返回结构中,数据可能会被嵌套在多层JSON对象中,而我们需要提取其中的某些字段。代码节点可以帮助您完成这些操作,下面是一个简单的例子,它从HTTP节点返回的JSON字符串中提取了data.name字段:

def main(http_response: str) -> str:
    import json
    data = json.loads(http_response)
    return {
        # 注意在输出变量中声明result
        'result': data['data']['name'] 
    }

数学计算

当工作流中需要进行一些复杂的数学计算时,也可以使用代码节点。例如,计算一个复杂的数学公式,或者对数据进行一些统计分析。下面是一个简单的例子,它计算了一个数组的平方差:

复制

def main(x: list) -> float:
    return {
        # 注意在输出变量中声明result
        'result' : sum([(i - sum(x) / len(x)) ** 2 for i in x]) / len(x)
    }

拼接数据

有时,也许您需要拼接多个数据源,如多个知识检索、数据搜索、API调用等,代码节点可以帮助您将这些数据源整合在一起。下面是一个简单的例子,它将两个知识库的数据合并在一起:

复制

def main(knowledge1: list, knowledge2: list) -> list:
    return {
        # 注意在输出变量中声明result
        'result': knowledge1 + knowledge2
    }

模板转换(Template)

允许借助 Jinja2 的 Python 模板语言灵活地进行数据转换、文本处理等。

模板节点允许你借助 Jinja2 这一强大的 Python 模板语言,在工作流内实现轻量、灵活的数据转换,适用于文本处理、JSON 转换等情景。例如灵活地格式化并合并来自前面步骤的变量,创建出单一的文本输出。这非常适合于将多个数据源的信息汇总成一个特定格式,满足后续步骤的需求。

**示例1:**将多个输入(文章标题、介绍、内容)拼接为完整文本

{{title}}
{{intro}}
{{body}}

**示例2:**将知识检索节点获取的信息及其相关的元数据,整理成一个结构化的 Markdown 格式

复制

{% for item in chunks %}
## Chunk {{ loop.index }}. 
## Similarity: {{ item.metadata.score | default('N/A') }}

### {{ item.title }}

#### Content
{{ item.content | replace('\n', '\n\n') }}

---
{% endfor %}

变量聚合(Variable Aggregator)

将多路分支的变量聚合为一个变量,以实现下游节点统一配置。

变量聚合节点(原变量赋值节点)是工作流程中的一个关键节点,它负责整合不同分支的输出结果,确保无论哪个分支被执行,其结果都能通过一个统一的变量来引用和访问。这在多分支的情况下非常有用,可将不同分支下相同作用的变量映射为一个输出变量,避免下游节点重复定义。

  • 问题分类聚合
  • 条件分支聚合

变量聚合器支持聚合多种数据类型,包括字符串(String)、数字(Number)、对象(Object)以及数组(Array)。

变量聚合器只能聚合同一种数据类型的变量。若第一个添加至变量聚合节点内的变量数据格式为 String,后续连线时会自动过滤可添加变量为 String 类型。

聚合分组

v0.6.10 版本之后已支持聚合分组。

开启聚合分组后,变量聚合器可以聚合多组变量,各组内聚合时要求同一种数据类型。

参数提取器(Parameter Extractor)

利用 LLM 从自然语言推理并提取结构化参数,用于后置的工具调用或 HTTP 请求。

Dify 工作流内提供了丰富的工具open in new window选择,其中大多数工具的输入为结构化参数,参数提取器可以将用户的自然语言转换为工具可识别的参数,方便工具调用。

工作流内的部分节点有特定的数据格式传入要求,如迭代节点的输入要求为数组格式,参数提取器可以方便的实现结构化参数的转换open in new window

场景示例

  • 从自然语言中提供工具所需的关键参数提取,如构建一个简单的对话式 Arxiv 论文检索应用。

在该示例中:Arxiv 论文检索工具的输入参数要求为 论文作者论文编号,参数提取器从问题“这篇论文中讲了什么内容:2405.10739”中提取出论文编号 2405.10739,并作为工具参数进行精确查询。

  • 将文本转换为结构化数据,如长故事迭代生成应用中,作为迭代节点的前置步骤,将文本格式的章节内容转换为数组格式,方便迭代节点进行多轮生成处理。
  • 提取结构化数据并使用 HTTP 请求open in new window ,可请求任意可访问的 URL ,适用于获取外部检索结果、webhook、生成图片等情景。

配置步骤

  1. 选择输入变量,一般为用于提取参数的变量输入
  2. 选择模型,参数提取器的提取依靠的是 LLM 的推理和结构化生成能力
  3. 定义提取参数,可以手动添加需要提取的参数,也可以从已有工具中快捷导入
  4. 编写指令,在提取复杂的参数时,编写示例可以帮助 LLM 提升生成的效果和稳定性

高级设置

  • 推理模式:部分模型同时支持两种推理模式,通过函数/工具调用或是纯提示词的方式实现参数提取,在指令遵循能力上有所差别。例如某些模型在函数调用效果欠佳的情况下可以切换成提示词推理。

    • Function Call/Tool Call

    • Prompt

  • 记忆:开启记忆后问题分类器的每次输入将包含对话中的聊天历史,以帮助 LLM 理解上文,提高对话交互中的问题理解能力。

  • 输出变量

    • 提取定义的变量

    • 节点内置变量

      • __is_success Number 提取是否成功 成功时值为 1,失败时值为 0。

      • __reason String 提取错误原因

迭代(Iteration)

对数组执行多次步骤直至输出所有结果。是一个容器节点,里面可以放其他节点

迭代步骤在列表中的每个条目(item)上执行相同的步骤。使用迭代的条件是确保输入值已经格式化为列表对象。迭代节点允许 AI 工作流处理更复杂的处理逻辑,迭代节点是循环节点的友好版本,它在自定义程度上做出了一些妥协,以便非技术用户能够快速入门。

场景示例

示例1:长文章迭代生成器

  1. 开始节点 内输入故事标题和大纲
  2. 使用 LLM 节点= 基于用户输入的故事标题和大纲,让 LLM 开始编写内容
  3. 使用 参数提取节点 将 LLM 输出的完整内容转换成数组格式
  4. 通过 迭代节点 包裹的 LLM 节点 循环多次生成各章节内容
  5. 直接回复 节点添加在迭代节点内部,实现在每轮迭代生成之后流式输出

具体配置步骤

  1. 开始节点 配置故事标题(title)和大纲(outline);

  2. 通过 LLM 节点 基于故事标题与大纲撰写文本;

  3. 通过 参数提取节点,将故事文本转换成为数组(Array)结构。提取参数为 sections ,参数类型为 Array[Object]

    参数提取效果受模型推理能力和指令影响,使用推理能力更强的模型,在指令内增加示例可以提高参数提取的效果。

  4. 将数组格式的故事大纲作为迭代节点的输入,在迭代节点内部使用 LLM 节点 进行处理

    在 LLM 节点内配置输入变量 GenerateOverallOutline/outputIteration/item

    迭代的内置变量:items[object]index[number]

    items[object] 代表以每轮迭代的输入条目;
    index[number] 代表当前迭代的轮次;
    
  5. 在迭代节点内部配置 直接回复节点 ,可以实现在每轮迭代生成之后流式输出。

示例 2:长文章迭代生成器(另一种编排方式)

  • 开始节点 内输入故事标题和大纲
  • 使用 LLM 节点 生成文章小标题,以及小标题对应的内容
  • 使用 代码节点 将完整内容转换成数组格式
  • 通过 迭代节点 包裹的 LLM 节点 循环多次生成各章节内容
  • 使用 模板转换 节点将迭代节点输出的字符串数组转换为字符串
  • 在最后添加 直接回复节点 将转换后的字符串直接输出

列表是一种特定的数据类型,其中的元素用逗号分隔,以 [ 开头,以 ] 结尾。例如:

数字型:

[0,1,2,3,4,5]

字符串型:

["monday", "Tuesday", "Wednesday", "Thursday"]

JSON 对象:

[
    {
        "name": "Alice",
        "age": 30,
        "email": "alice@example.com"
    },
    {
        "name": "Bob",
        "age": 25,
        "email": "bob@example.com"
    },
    {
        "name": "Charlie",
        "age": 35,
        "email": "charlie@example.com"
    }
]

支持返回数组的节点

  • 代码节点
  • 参数提取
  • 知识库检索
  • 迭代
  • 工具
  • HTTP 请求

如何获取数组格式的内容

  • 使用 CODE 节点返回

  • 使用 参数提取 节点返回

如何将数组转换为文本

迭代节点的输出变量为数组格式,无法直接输出。你可以使用一个简单的步骤将数组转换回文本。

  • 使用代码节点转换

    def main(articleSections: list):
        data = articleSections
        return {
            "result": "\n".join(data)
        }
    
  • 使用模板节点转换

    {{ articleSections | join("\n") }}
    

HTTP 请求(HTTP Request)

允许通过 HTTP 协议发送服务器请求,适用于获取外部检索结果、webhook、生成图片等情景。

它让你能够向指定的网络地址发送定制化的 HTTP 请求,实现与各种外部服务的互联互通。

该节点支持常见的 HTTP 请求方法:

  • GET,用于请求服务器发送某个资源。
  • POST,用于向服务器提交数据,通常用于提交表单或上传文件。
  • HEAD,类似于 GET 请求,但服务器不返回请求的资源主体,只返回响应头。
  • PATCH,用于在请求-响应链上的每个节点获取传输路径。
  • PUT,用于向服务器上传资源,通常用于更新已存在的资源或创建新的资源。
  • DELETE,用于请求服务器删除指定的资源。

你可以通过配置 HTTP 请求的包括 URL、请求头、查询参数、请求体内容以及认证信息等。

这个节点的一个实用特性是能够根据场景需要,在请求的不同部分动态插入变量。比如在处理客户评价请求时,你可以将用户名或客户ID、评价内容等变量嵌入到请求中,以定制化自动回复信息或获取特定客户信息并发送相关资源至特定的服务器。

HTTP 请求的返回值包括响应体、状态码、响应头和文件。值得注意的是,如果响应中包含了文件(目前仅支持图片类型),这个节点能够自动将文件保存下来,供流程后续步骤使用。这样的设计不仅提高了处理效率,也使得处理带有文件的响应变得简单直接。

变量赋值(Variable Assigner)

变量赋值节点用于向可写入变量(例如会话变量)进行变量赋值。

目前只支持会话变量

用法:通过变量赋值节点,你可以将工作流内的变量赋值到会话变量中用于临时存储,并可以在后续对话中持续引用。

使用场景示例

通过变量赋值节点,你可以将会话过程中的上下文、上传至对话框的文件(即将上线)、用户所输入的偏好信息等写入至会话变量,并在后续对话中引用已存储的信息导向不同的处理流程或者进行回复。

场景 1

自动判断提取并存储对话中的信息,在会话内通过会话变量数组记录用户输入的重要信息,并在后续对话中让 LLM 基于会话变量中存储的历史信息进行个性化回复。

示例:开始对话后,LLM 会自动判断用户输入是否包含需要记住的事实、偏好或历史记录。如果有,LLM 会先提取并存储这些信息,然后再用这些信息作为上下文来回答。如果没有新的信息需要保存,LLM 会直接使用自身的相关记忆知识来回答问题。

配置流程:

  1. 设置会话变量:首先设置一个会话变量数组 memories,类型为 array[object],用于存储用户的事实、偏好和历史记录。
  2. 判断和提取记忆
    • 添加一个条件判断节点,使用 LLM 来判断用户输入是否包含需要记住的新信息。
    • 如果有新信息,走上分支,使用 LLM 节点提取这些信息。
    • 如果没有新信息,走下分支,直接使用现有记忆回答。
  3. 变量赋值/写入
    • 在上分支中,使用变量赋值节点,将提取出的新信息追加(append)到 memories 数组中。
    • 使用转义功能将 LLM 输出的文本字符串转换为适合存储在 array[object] 中的格式。
  4. 变量读取和使用
    • 在后续的 LLM 节点中,将 memories 数组中的内容转换为字符串,并插入到 LLM 的提示词 Prompts 中作为上下文。
    • LLM 使用这些历史信息来生成个性化回复。
  • code 节点代码如下:

    • 将字符串转义为 object
    import json
    
    def main(arg1: str) -> object:
        try:
            # Parse the input JSON string
            input_data = json.loads(arg1)
            
            # Extract the memory object
            memory = input_data.get("memory", {})
            
            # Construct the return object
            result = {
                "facts": memory.get("facts", []),
                "preferences": memory.get("preferences", []),
                "memories": memory.get("memories", [])
            }
            
            return {
                "mem": result
            }
        except json.JSONDecodeError:
            return {
                "result": "Error: Invalid JSON string"
            }
        except Exception as e:
            return {
                "result": f"Error: {str(e)}"
            }
    
    • 将 object 转义为字符串
    import json
    
    def main(arg1: list) -> str:
        try:
            # Assume arg1[0] is the dictionary we need to process
            context = arg1[0] if arg1 else {}
            
            # Construct the memory object
            memory = {"memory": context}
            
            # Convert the object to a JSON string
            json_str = json.dumps(memory, ensure_ascii=False, indent=2)
            
            # Wrap the JSON string in <answer> tags
            result = f"<answer>{json_str}</answer>"
            
            return {
                "result": result
            }
        except Exception as e:
            return {
                "result": f"<answer>Error: {str(e)}</answer>"
            }
    

场景 2

记录用户的初始偏好信息,在会话内记住用户输入的语言偏好,在后续对话中持续使用该语言类型进行回复。

示例:用户在对话开始前,在 language 输入框内指定了 “中文”,该语言将会被写入会话变量,LLM 在后续进行答复时会参考会话变量中的信息,在后续对话中持续使用“中文”进行回复。

配置流程:

  • 设置会话变量:首先设置一个会话变量 language,在会话流程开始时添加一个条件判断节点,用来判断 language 变量的值是否为空。

  • 变量写入/赋值:首轮对话开始时,若 language 变量值为空,则使用 LLM 节点来提取用户输入的语言,再通过变量赋值节点将该语言类型写入到会话变量 language 中。

  • 变量读取:在后续对话轮次中 language 变量已存储用户语言偏好。在后续对话中,LLM 节点通过引用 language 变量,使用用户的偏好语言类型进行回复。

场景 3

辅助 Checklist 检查,在会话内通过会话变量记录用户的输入项,更新 Checklist 中的内容,并在后续对话中检查遗漏项。

示例:开始对话后,LLM 会要求用户在对话框内输入 Checklist 所涉及的事项,用户一旦提及了 Checklist 中的内容,将会更新并存储至会话变量内。LLM 会在每轮对话后提醒用户继续补充遗漏项。

配置流程:

  • 设置会话变量: 首先设置一个会话变量 ai_checklist,在 LLM 内引用该变量作为上下文进行检查。

  • 变量赋值/写入: 每一轮对话时,在 LLM 节点内检查 ai_checklist 内的值并比对用户输入,若用户提供了新的信息,则更新 Checklist 并将输出内容通过变量赋值节点写入到 ai_checklist 内。

  • 变量读取: 每一轮对话读取 ai_cheklist 内的值并比对用户输入直至所有 checklist 完成。

使用方式

点击节点右侧 + 号,选择“变量赋值”节点,填写“赋值的变量”和“设置变量”。

  • 赋值的变量:选择被赋值变量,即指定需要被赋值的目标会话变量。

  • 设置变量:选择需要赋值的变量,即指定需要被转换的源变量。

  • 写入模式:

    • 覆盖,将源变量的内容覆盖至目标会话变量
    • 追加,指定变量为 Array 类型时
    • 清空,清空目标会话变量中的内容

工具(Tools)

工作流内提供丰富的工具选择,工具分为三种类型:

  • 内置工具,Dify 第一方提供的工具
  • 自定义工具,通过 OpenAPI/Swagger 标准格式导入或配置的工具
  • 工作流,已发布为工具的工作流

使用内置工具之前,你可能需要先给工具进行 授权

若内置工具无法满足使用需求,你可以在 Dify 菜单导航 --工具 内先创建自定义工具。

你也可以编排一个更加复杂的工作流,并将其发布为工具。

配置工具节点一般分为两个步骤:

  1. 对工具授权/创建自定义工具/将工作流发布为工具
  2. 配置工具输入和参数

预览与调试

  • 预览与运行
  • 单步调试
  • 对话、运行日志
  • 检查清单
  • 运行历史

应用发布

上次编辑于:
贡献者: 李元昊