序列代理

本指南全面概述了Nvmme中的序列代理人工智能(Sequential Agent AI)系统架构,探讨了其核心组件和工作流设计原则。

{% 提示 样式="警告" %} 免责声明:本文档旨在帮助Nvmme用户理解并使用Sequential Agent系统架构构建对话工作流程。它并非旨在成为LangGraph框架的全面技术参考,也不应被视为定义行业标准或核心LangGraph概念。 {% 结束提示 %}

概念

Nvmme的Sequential Agents架构建立在LangGraph之上,通过将工作流程构建为有向循环图(DCG),促进了对话智能体系统的开发,实现了受控循环和迭代过程。

这张由相互连接的节点组成的图表,定义了信息和动作的顺序流程,使智能体能够以结构化的方式处理输入、执行任务并生成响应。

理解顺序智能体(Sequential Agents)的DCG架构

该架构通过其DCG结构定义了一个清晰易懂的操作序列,从而简化了复杂会话工作流的管理。

让我们来探讨一下这种方法的一些关键要素:

标签页

  • 基于节点的处理:图中的每个节点代表一个离散的处理单元,包含其自身的功能,如语言处理、工具执行或条件逻辑。

  • 数据流作为连接:图中的边表示节点之间的数据流,其中一个节点的输出成为后续节点的输入,从而形成一系列处理步骤。

  • 状态管理:状态作为共享对象进行管理,在整个会话过程中保持不变。这使得节点能够在工作流进行过程中访问相关信息。

  • **流程(Flow):**工作流中数据的移动或流向。它描述了会话过程中信息如何在节点之间传递。

  • 工作流程:系统的整体设计与结构。它是定义节点顺序、节点连接以及协调对话流程逻辑的蓝图。

  • 状态(State):一个共享的数据结构,表示对话的当前快照。它包括对话历史state.messages以及用户定义的任何自定义状态变量。

  • 自定义状态:添加到状态对象中的用户定义的键值对,用于存储与工作流相关的其他信息。

  • 工具:一种外部系统、API或服务,可由工作流访问和执行,以执行特定任务,如检索信息、处理数据或与其他应用程序交互。

  • **人机交互(HITL):**一种允许人类在工作流程中(主要是在工具执行期间)进行干预的功能。它使人类审阅者能够在工具调用执行前批准或拒绝该调用。

  • 并行节点执行:它指的是通过使用分支机制,在工作流中并行执行多个节点的能力。这意味着,即使整体执行流程仍然是顺序的,工作流的不同分支也可以同时处理信息或与工具交互。


顺序智能体与多智能体

虽然Nvmme中的多智能体系统和顺序智能体系统均基于LangGraph框架构建,并遵循相同的基本原理,但顺序智能体架构提供了较低层次的抽象[^1],能够对工作流程的每个步骤进行更精细的控制。

多智能体系统,其特点是具有分层结构,由中央监督智能体将任务委托给专门的工作智能体,擅长通过将复杂工作流程分解为可管理的子任务来处理。这种子任务分解是通过预先配置核心系统元素(如条件节点)实现的,而在顺序智能体系统中,这些元素需要手动设置。因此,用户可以更容易地构建和管理智能体团队。

相比之下,顺序智能体系统就像一条流水线,数据按顺序通过一系列节点,这使得它们非常适合需要精确操作顺序和增量数据优化的任务。与多智能体系统相比,它对底层工作流结构的低级访问使其从根本上更具灵活性和可定制性,提供并行节点执行和对系统逻辑的完全控制,将条件、状态和循环节点纳入工作流中,从而创建新的动态分支功能。

介绍状态节点、循环节点和条件节点

Nvmme的Sequential Agents为创建对话系统提供了新功能,这些系统能够适应用户输入,根据上下文做出决策,并执行迭代任务。

这些功能得益于四个新核心节点的引入,即状态节点、循环节点和两个条件节点。

  • 状态节点:我们将“状态”定义为一种共享数据结构,它代表我们的应用程序或工作流的当前状态快照。状态节点允许我们从对话开始时向工作流中添加自定义状态。工作流中的其他节点可以访问和修改此自定义状态,从而实现动态行为和数据共享。

  • 循环节点:该节点在顺序智能体工作流中引入受控循环,支持迭代过程,即可以根据特定条件重复一系列节点。这使得智能体能够优化输出、从用户那里收集更多信息,或多次执行任务。

  • 条件节点:条件和条件智能体节点为创建具有分支路径的复杂对话流提供了必要的控制。条件节点直接评估条件,而条件智能体节点则使用智能体的推理能力来确定分支逻辑。这使我们能够根据用户输入、自定义状态或其他节点执行的操作结果来动态引导对话流的行为。

选择合适的系统

为您的应用选择理想的系统,取决于对特定工作流程需求的了解。任务复杂性、并行处理需求以及您对数据流的控制程度等都是关键考虑因素。

  • **为简化说明:**若您的工作流程相对简单,任务可依次完成,因此无需并行节点执行或人机在环(HITL),则多智能体方法使用方便,设置快捷。

  • **灵活性方面:如果您的流程需要并行执行、动态对话、自定义状态管理以及能够融入人机交互(Human-in-the-Loop,HITL)功能,那么顺序智能体(Sequential Agent)**方法能够提供必要的灵活性和控制能力。

以下表格对比了Flowise中的多智能体和顺序智能体实现,突出了关键差异和设计考量因素:

多智能体
顺序智能体

结构

分层;主管将任务委托给专门的工人。

线性、循环和/或 分支;节点按顺序连接,并使用条件逻辑进行分支。

工作流程

灵活;设计用于将复杂任务分解为一系列子任务,依次完成。

高度灵活;支持并行节点执行,复杂的对话流,分支逻辑,以及单个对话回合内的循环。

并行节点执行

;主管一次处理一个任务。

;可以在单次运行中并行触发多个操作。

状态管理

隐式;状态存在,但不由开发者显式管理。

显式;状态存在,开发者可以使用状态节点和各种节点中的“更新状态”字段定义和管理初始或自定义状态。

工具使用

工人可以根据需要访问和使用工具。

工具通过智能体节点工具节点进行访问和执行。

人机交互(HITL)

HITL 不受支持。

通过智能体节点和工具节点的“需要批准”功能支持,允许人工审查和批准或拒绝工具执行。

复杂性

更高层次的抽象;简化工作流程设计。

更低层次的抽象;更复杂的工作流程设计,需要仔细规划节点交互、自定义状态管理和条件逻辑。

理想用例

  • 自动化线性流程(例如,数据提取、潜在客户开发)。

  • 需要依次完成子任务的情况。

  • 构建具有动态流的对话系统。

  • 需要并行节点执行或分支逻辑的复杂工作流程。

  • 需要在对话中的多个点进行决策的情况。

{% 提示 样式="信息" %} 注意:尽管从技术上讲,多智能体系统是建立在顺序智能体架构之上的更高层次,但它们提供了独特的用户体验和工作流设计方法。上述比较将它们视为独立的系统,以帮助您根据特定需求选择最佳选项。 {% 结束提示 %}


顺序智能体节点

序列式智能体为Nvmme带来了全新的维度,引入了10个专用节点,每个节点都服务于特定目的,从而让我们能更好地控制对话智能体与用户交互、处理信息、做出决策和执行操作的方式。

以下部分旨在全面介绍每个节点的功能、输入、输出和最佳实践,最终使您能够为各种应用构建复杂的会话工作流程。


1. 启动节点

顾名思义,起始节点是顺序智能体架构中所有工作流的入口点。它接收初始用户查询,初始化对话状态,并启动流程。

理解起始节点

起始节点确保我们的对话工作流程具备正确运行所需的必要设置和上下文。它负责设置将在工作流程其余部分使用的关键功能

  • **定义默认大型语言模型(LLM):**开始节点要求我们指定一个与函数调用兼容的聊天模型(LLM),以使工作流中的智能体能够与工具和外部系统进行交互。这将是工作流中默认使用的大型语言模型。

  • 初始化内存:我们可以选择连接一个智能体内存节点来存储和检索对话历史,从而实现更多上下文感知的响应。

  • 设置自定义状态:默认情况下,状态包含一个不可变的state.messages数组,该数组作为用户与智能体之间对话的记录或历史。通过添加状态节点,起始节点允许您将自定义状态连接到工作流中,从而能够存储与您的工作流相关的其他信息

  • 启用内容审核功能:我们可以选择连接输入内容审核功能,以分析用户的输入内容,并防止可能有害的内容被发送给大型语言模型(LLM)。

输入

必填
描述

聊天模型

默认的大型语言模型(LLM),将驱动对话。仅与能够进行函数调用的模型兼容。

智能体内存节点

连接智能体内存节点以启用持久化和上下文保留

状态节点

连接状态节点以设置自定义状态,这是一个共享上下文,可由工作流中的其他节点访问和修改。

输入审核

连接审核节点以过滤内容,通过检测可能生成有害输出的文本,防止其被发送到LLM。

输出

起始节点可以作为输出连接到以下节点:

  • 智能体节点:连接到智能体节点进行处理。

  • LLM节点:将对话流转发至LLM节点进行处理和响应生成。

  • 条件智能体节点:连接到条件智能体节点,以根据智能体对会话的评估实现分支逻辑。

  • 条件节点:与条件节点连接,以根据预定义的条件实现分支逻辑。

最佳实践

选项卡

选择合适的聊天模型

确保您选择的LLM(大型语言模型)支持函数调用,这是实现智能体-工具交互的关键功能。此外,请选择一个与您的应用程序复杂度和需求相匹配的LLM。如有必要,您可以在智能体/LLM/条件智能体节点级别设置默认LLM,以覆盖其默认设置。

考虑上下文和持久性

如果您的用例有此需求,请利用Agent Memory Node来保持上下文并个性化交互。

聊天模型(LLM)选择错误

  • **问题:**在起始节点中选择的聊天模型不适合工作流的预期任务或功能,导致性能不佳或响应不准确。

  • 示例:一个工作流程需要一个具有强大总结能力的聊天模型,但起始节点选择了一个针对代码生成优化的模型,导致总结不充分。

  • 解决方案: 选择一个符合您工作流程特定需求的聊天模型。考虑模型的优点、缺点以及它擅长的任务类型。查阅相关文档,并尝试不同的模型,以找到最适合的模型。

忽略智能体内存节点配置

  • **问题:**智能体内存节点未正确连接或配置,导致会话之间的对话历史数据丢失。

  • **示例:**您打算使用持久内存来存储用户偏好,但智能体内存节点未连接到起始节点,导致每次新对话时偏好都会重置。

  • 解决方案: 确保智能体内存节点已连接到起始节点,并配置了适当的数据库(SQLite)。对于大多数用例,默认的SQLite数据库就足够了。

输入审核不足

  • 问题:“输入审核”功能未启用或配置不当,导致可能有害或不适当的用户输入能够到达大型语言模型(LLM)并生成不良响应。

  • **示例:**用户提交了冒犯性语言,但输入审核未能检测到,或者根本没有设置输入审核,导致该查询到达了大型语言模型(LLM)。

  • 解决方案: 在起始节点中添加并配置一个输入审核节点,以过滤掉可能有害或不恰当的语言。根据您的特定需求和使用场景,自定义审核设置。

  1. 智能体内存节点

智能体内存节点提供了一种持久内存存储机制,使顺序智能体工作流能够保留对话历史state.messages以及之前在多次交互中定义的任何自定义状态

这种长期记忆对于智能体从之前的交互中学习、在长时间的对话中保持上下文连贯性以及提供更相关的回应至关重要。

数据记录的位置

默认情况下,Nvmme利用其内置的SQLite数据库来存储对话历史和自定义状态数据,并创建一个名为“checkpoints”的表来管理这些持久信息。

了解“检查点”表的结构和数据格式

此表存储会话期间系统状态在不同时间点的快照,从而支持会话历史的持久化和检索。每一行代表工作流执行过程中的一个特定点或“检查点”。

表结构

  • thread_id: 一个唯一标识符,代表特定的会话会话,即我们的会话ID。它将与单个工作流执行相关的所有检查点组合在一起。

  • checkpoint_id:工作流中每个执行步骤(节点执行)的唯一标识符。它有助于跟踪操作的顺序并识别每个步骤的状态。

  • parent_id: 表示导致当前检查点的上一个执行步骤的检查点_id。这建立了检查点之间的层级关系,从而可以重建工作流的执行流程。

  • **检查点:**包含一个JSON字符串,表示在该特定检查点的工作流当前状态。这包括变量值、交换的消息以及在执行过程中该点捕获的任何其他相关数据。

  • 元数据(metadata):提供关于检查点的额外上下文信息,特别是与节点操作相关的内容。

工作原理

在执行顺序智能体工作流时,系统会在此表中为每个重要步骤记录一个检查点。这种机制具有多个优点:

  • 执行跟踪:检查点使系统能够了解工作流中的执行路径和操作顺序。

  • 状态管理:检查点会存储工作流在每个步骤的状态,包括变量值、对话历史以及任何其他相关数据。这使得系统能够保持上下文感知,并根据当前状态做出明智的决策。

  • 工作流恢复:如果工作流被暂停或中断(例如,由于系统错误或用户请求),系统可以使用存储的检查点从最后记录的状态恢复执行。这确保对话或任务从暂停处继续进行,保留用户的进度并防止数据丢失。

输入

智能体记忆节点没有特定的输入连接

节点设置

必填
描述

Database

用于存储对话历史的数据库类型。目前,仅支持SQLite

附加参数

必填
描述

数据库文件路径

SQLite数据库文件的文件路径。若未提供,系统将使用默认位置

输出

智能体记忆节点仅与起始节点交互,从而使对话历史从工作流程的一开始就可用。

最佳实践

标签页

战略运用

仅在必要时使用智能体记忆(Agent Memory)。对于简单的、无状态的交互,使用智能体记忆可能有些过度。将其保留用于需要在回合或会话之间保留信息的场景。

不必要的开销

  • 问题所在: 即使在不需要的情况下,对每次交互都使用智能体记忆(Agent Memory)会引入不必要的存储和处理开销。这会降低响应速度并增加资源消耗。

  • 示例:一个基于单个用户请求提供信息的简单天气聊天机器人无需存储对话历史。 解决方案:分析系统的需求,仅在持久数据存储对功能或用户体验至关重要时,才使用智能体内存。


3. 状态节点

状态节点只能连接到开始节点,它提供了一种机制,用于从对话开始时将用户定义或自定义的状态设置到我们的工作流程中。这个自定义状态是一个JSON对象,它被共享并可由图中的节点更新,随着流程的进行从一个节点传递到另一个节点。

理解状态节点

默认情况下,状态包含一个state.messages数组,该数组充当我们的对话历史记录。此数组存储用户与智能体或工作流中的任何其他参与者之间交换的所有消息,并在整个工作流执行过程中保留这些消息。

由于state.messages数组从定义上就是不可变的,无法进行修改,状态节点的目的是让我们能够定义自定义的键值对,从而扩展状态对象以包含与我们的工作流程相关的任何额外信息。

信息提示 当未使用智能体内存节点时,状态在内存中运行,并且不会持久化以供将来使用。

输入

状态节点没有特定的输入连接

输出

状态节点只能连接到起始节点,从而允许从工作流的开始设置自定义状态,并允许其他节点访问并可能修改这个共享的自定义状态。

附加参数

必填
描述

自定义状态

一个JSON对象,表示工作流的初始自定义状态。此对象可以包含与应用程序相关的任何键值对。

如何设置自定义状态

为状态对象指定操作类型默认值。操作类型可以是“替换”或“追加”。

  • 替换

    1. 用新值替换现有值。

    2. 如果新值为空,则保留现有值。

  • 附加

    1. 将新值附加到现有值后面。

    2. 默认值可以为空或一个数组。例如:[“a”,“b”]

    3. 最终值是一个数组。

使用JavaScript的示例

```javascript

/// 译文内容:

根据上面的信息,执行如下指令: 你是个专业的翻译,负责把英语内容翻译成中文内容,请帮我翻译一下原文内容 { 聚合:{ value: (x, y) => x.concat(y), // 在这里,我们将新消息附加到现有消息之后 默认值:() => [] } }

{% 结束编码 %}

#### 使用表格的示例

要在状态节点中使用表格界面定义自定义状态,请按照以下步骤操作:

1. **添加项:** 点击“+ 添加项”按钮,向表格中添加行。每一行代表自定义状态中的一个键值对。
2. **指定键值:** 在“键”列中,输入您要在状态对象中定义的每个键的名称。例如,您可能拥有如“userName”、“userLocation”等键。
3. **选择操作:**在“操作”列中,为每个键选择所需的操作。您有两个选项:
   * **替换**:这将用节点提供的新值替换键的现有值。如果新值为空,则保留现有值。
   * **Append:** 这会将新值追加到键的现有值后面。最终值将是一个数组。
4. **设置默认值:**在“默认值”列中,为每个键输入初始值。如果没有其他节点为该键提供值,则将使用此值。默认值可以为空或一个数组。

#### 示例表格

| 键      | 操作 | 默认值 |
| -------- | --------- | ------------- |
| userName | Replace   | null          |

<figure><img src="../../../.gitbook/assets/seq-14.png" alt="" width="375"><figcaption></figcaption></figure>

1. 此表在自定义状态中定义了一个键:`userName`。
2. `userName`键将使用“替换”操作,这意味着每当节点提供新值时,其值都会被更新。
3. `userName`键的默认值为_null_,表示它没有初始值。

信息提示框
请记住,这种基于表格的方法是使用JavaScript定义自定义状态的一种替代方法。这两种方法都能达到相同的效果。
{% 结束提示 %}

#### 使用API的示例

```json

/// 译文内容:
---
根据上面的信息,执行如下指令:
缺失译文,请检查输入
{
    "问题":"你好",
    "overrideConfig": {
        "stateMemory": [
            {
                "键":"userName",
                “操作”:“替换”,
                “默认值”:“somevalue”
            }
        ]
    }
}

最佳实践

选项卡

规划您的自定义状态结构

在构建工作流程之前,请先设计自定义状态的结构。一个组织良好的自定义状态将使您的工作流程更易于理解、管理和调试。

使用有意义的键名

选择具有描述性且一致的关键字名称,以明确表明它们所包含数据的用途。这将提高代码的可读性,并使他人(或未来的你)更容易理解自定义状态的使用方式。

保持自定义状态最小化

仅将对于工作流逻辑和决策至关重要的信息存储在自定义状态中。

考虑状态持久化

如果你需要在多个会话会话中保留状态(例如,用户偏好、订单历史等),请使用智能体内存节点将状态存储在持久性数据库中。

状态更新不一致

  • 问题: 在没有明确策略的情况下更新多个节点中的自定义状态,可能会导致不一致和意外行为。

  • 示例

    1. 智能体1将orderStatus更新为“付款已确认”。

    2. 位于不同分支的智能体2,在未检查先前状态的情况下,将orderStatus更新为“订单完成”。

  • 解决方案: 使用条件节点来控制自定义状态更新的流程,并确保自定义状态转换以逻辑清晰且一致的方式发生。


4. 智能体节点

智能体节点是顺序智能体架构的核心组件。它在我们工作流程中扮演着决策者和协调者的角色。

理解智能体节点

在接收到来自前序节点的输入后(该输入始终包含完整的对话历史state.messages以及执行过程中的任何自定义状态),智能体节点将使用其由系统提示建立的已定义“角色”,来判断是否需要借助外部工具来满足用户的请求。

  • 如果需要工具,智能体节点会自主选择并执行合适的工具。执行过程可以是自动的,或者对于敏感任务,在继续执行之前需要人工批准(人机交互式学习,HITL)。工具完成操作后,智能体节点会接收结果,使用指定的聊天模型(大型语言模型,LLM)进行处理,并生成全面的响应。

  • 在无需工具的情况下,智能体节点直接利用聊天模型(LLM)根据当前对话上下文生成响应。

输入

是否必需
描述

外部工具

为智能体节点提供访问一系列外部工具的权限,使其能够执行操作和检索信息。

聊天模型

添加一个新的聊天模型以覆盖工作流的默认聊天模型(大型语言模型,LLM)。仅兼容能够进行函数调用的模型。

启动节点

从启动节点接收初始用户输入,以及自定义状态(如果已设置)和默认的state.messages数组的其余部分。

条件节点

接收来自前一个条件节点的输入,使智能体节点能够根据条件节点评估的结果执行操作或引导对话

条件智能体节点

接收来自前一个条件智能体节点的输入,使智能体节点能够根据条件智能体节点评估的结果执行操作或引导对话

智能体节点

接收来自前一个智能体节点的输入,支持链式智能体操作并保持对话上下文。

LLM节点

接收LLM节点的输出,使智能体节点能够处理LLM的响应

工具节点

接收工具节点的输出,使智能体节点能够处理工具的输出并将其整合到响应中

提示框(样式为“信息”) 智能体节点至少需要以下节点中的一个连接:启动节点、智能体节点、条件节点、条件智能体节点、大型语言模型(LLM)节点或工具节点。

输出

智能体节点可以作为输出连接到以下节点:

  • 智能体节点:将控制权传递给后续的智能体节点,从而实现在工作流中串联多个智能体操作。这使得对话流程和任务编排更为复杂。

  • LLM节点:将智能体的输出传递给LLM节点,从而能够基于智能体的动作和洞察进行进一步的语言处理、响应生成或决策制定。

  • 条件智能体点:将流程引导至条件智能体节点。该节点评估智能体节点的输出及其预定义的条件,以确定工作流中适当的下一步操作。

  • 条件节点:与条件智能体节点类似,条件节点使用预定义的条件来评估智能体节点的输出,并根据结果将流程导向不同的分支。

  • 结束节点:结束对话流程。

  • 循环节点:将流程重定向回上一个节点,从而在工作流中实现迭代或循环过程。这对于需要多个步骤或涉及根据先前交互来优化结果的任务非常有用。例如,您可能会循环回到之前的智能体节点或大型语言模型(LLM)节点,以收集更多信息或根据当前智能体节点的输出来优化对话流程。

节点设置

必填
描述

Agent Name

为智能体节点添加一个描述性名称,以提高工作流的可读性,并在工作流中使用循环时轻松定位它

System Prompt

定义智能体的“角色”指导其行为。例如,“您是一名专门从事技术支持的客户服务智能体 [...].”

Require Approval

激活人机交互(HITL)功能。如果设置为'True',则智能体节点在执行任何工具之前会请求人工批准。这对于敏感操作或需要人工监督的情况特别有价值。默认为'False',允许智能体节点自主执行工具。

附加参数

必填
描述

人工提示

此提示作为人工消息附加到state.messages数组中。它允许我们在智能体节点处理完输入后,在下一个节点接收到智能体节点的输出之前,将类似人类的消息注入到对话流中

批准提示

HITL功能激活时,向人工审核者展示的可自定义提示。此提示提供了关于工具执行的上下文,包括工具的名称和用途。提示中的变量{tools}将动态替换为智能体建议的实际工具列表,确保人工审核者拥有做出明智决策所需的所有必要信息。

批准按钮文本

自定义HITL界面中批准工具执行按钮上显示的文本。这使得可以根据特定上下文调整语言,并确保人工审核者能够清晰理解。

拒绝按钮文本

自定义HITL界面中拒绝工具执行按钮上显示的文本。与批准按钮文本类似,此自定义增强了清晰度,并为人工审核者提供了一个明确的操作选项,如果他们认为工具执行不必要或可能有害。

更新状态

提供了一种在工作流中修改共享自定义状态对象的机制。这对于存储智能体收集的信息或影响后续节点的行为非常有用。

最大迭代次数

限制了单个工作流执行中智能体节点可以进行的迭代次数

最佳实践

选项卡

清除系统提示

设计一个简洁明了且无歧义的系统提示,准确反映智能体的角色和能力。这将指导智能体的决策,并确保其行动在其定义范围内。

战略工具选择

为智能体节点选择并配置可用工具,确保这些工具与智能体的用途和工作流程的总体目标相一致。

敏感任务的HITL(人机交互训练)

对于涉及敏感数据、需要人工判断或存在产生意外后果风险的任务,请使用“需要审批”选项。

利用自定义状态更新

策略性地更新自定义状态对象,以存储收集到的信息或影响下游节点的行为。

因工具过载导致智能体不作为

  • **问题:**当智能体节点在单个工作流执行过程中能够访问大量工具时,它可能难以决定使用哪个工具最合适,即使某个工具显然是必需的。这可能导致智能体根本无法调用任何工具,从而导致响应不完整或不准确。

  • 示例:设想一位客户支持智能体,其设计初衷是处理各种咨询问题。你为其配备了订单追踪、账单信息、产品退货、技术支持等工具。一位用户询问:“我的订单状态如何?”但该智能体被众多潜在工具所淹没,仅以通用回答回应:“我可以帮你处理。你的订单号是多少?”而实际上并未使用订单追踪工具。

  • 解决方案

    1. **优化系统提示:**在智能体节点的系统提示中提供更清晰的说明和示例,以引导其选择正确的工具。如有必要,强调每种工具的具体功能以及它们应适用的场景。

    2. 限制每个节点的工具选择:如果可能的话,将复杂的工作流程分解成更小、更易于管理的部分,每个部分使用一组更专注的工具。这有助于减轻智能体的认知负荷,并提高其工具选择的准确性。

在敏感任务中忽视HITL

  • **问题:**在涉及敏感信息、关键决策或可能产生现实世界后果的行动的任务中,未能利用智能体节点的“需要批准”(HITL)功能,可能会导致意外结果或损害用户信任。

  • **示例:**您的旅行预订智能体能够访问用户的支付信息,并自动预订航班和酒店。若没有HITL(人机交互任务学习),用户意图的误解或智能体理解上的错误都可能导致预订出错或未经授权使用用户的支付信息。

  • 解决方案

    1. **识别敏感操作:**分析您的工作流程,并识别出任何涉及访问或处理敏感数据(如支付信息、个人详细信息)的操作。

    2. 启用“需审批”功能:对于这些敏感操作,请在智能体节点中启用“需审批”选项。这可以确保在访问任何敏感数据或执行任何不可逆操作之前,人工审核智能体提出的操作及相关上下文。

    3. 设计清晰的审批提示:为人工审核人员提供清晰简洁的提示,概述智能体的意图、拟采取的行动以及审核人员做出明智决策所需的相关信息。

系统提示不明确或不完整

  • 问题: 提供给智能体节点的系统提示缺乏必要的具体性和上下文,无法有效指导智能体执行其预定任务。模糊或过于笼统的提示可能导致响应不相关、难以理解用户意图,以及无法适当利用工具或数据。

  • 示例:你正在构建一个旅行预订智能体,而你的系统提示只是简单地说“你是一个乐于助人的AI助手”。这缺乏具体指令和上下文,使得智能体无法有效地引导用户进行航班搜索、酒店预订和行程规划。

  • 解决方案: 制定一个详细且情境感知的系统提示:

``` 你是一名旅行预订智能体。你的主要目标是协助用户规划和预订他们的旅行。 - 指导他们搜索航班、查找住宿并探索目的地。 - 保持礼貌,耐心,并根据他们的喜好提供旅行建议。 - 利用现有工具获取航班数据、酒店可用性以及目的地信息。 ``` {% 结束编码 %}


5. LLM节点

与智能体节点一样,大型语言模型(LLM)节点是顺序智能体架构的核心组件。默认情况下,这两个节点都使用相同的聊天模型(LLM),提供相同的基本语言处理能力,但大型语言模型节点在这些关键领域有所不同。

LLM节点的关键优势

虽然本节提供了LLM节点和智能体节点之间的详细比较,但这里简要概述一下LLM节点的关键优势

  • 结构化数据:LLM节点提供了一个专用功能,用于为其输出定义JSON模式。这使得从LLM的响应中提取结构化信息并将该数据传递给工作流中的后续节点变得异常简单。智能体节点则没有这种内置的JSON模式功能

  • **HITL(人机交互工具层):**虽然两个节点都支持HITL以执行工具,但LLM节点将此控制权交由工具节点本身,从而在工作流设计中提供了更大的灵活性。

输入

是否必需
描述

聊天模型

添加一个新的聊天模型以覆盖工作流的默认聊天模型(大型语言模型,LLM)。仅兼容能够进行函数调用的模型。

起始节点

接收初始用户输入,以及自定义状态(如果已设置)和来自起始节点的默认state.messages数组的其余部分。

智能体节点

接收来自智能体节点的输出,其中可能包括工具执行结果或智能体生成的响应。

条件节点

接收来自前一个条件节点的输入,使大型语言模型节点能够根据条件节点评估的结果采取行动或引导对话

条件智能体节点

接收来自前一个条件智能体节点的输入,使大型语言模型节点能够根据条件智能体节点评估的结果采取行动或引导对话

大型语言模型节点

接收来自另一个大型语言模型节点的输出,实现链式推理或跨多个大型语言模型节点的信息处理。

工具节点

接收来自工具节点的输出,提供工具执行的结果以供进一步处理或生成响应。

信息提示框 LLM节点至少需要以下节点中的一个连接:启动节点、智能体节点、条件节点、条件智能体节点、LLM节点或工具节点。 {% 结束提示 %}

节点设置

必填
描述

LLM 节点名称

为 LLM 节点添加一个描述性名称,以提高工作流的可读性,并在工作流中使用循环时轻松定位它

输出

LLM节点可以作为输出连接到以下节点:

  • 智能体节点:将大型语言模型(LLM)的输出传递给智能体节点,该节点随后可以使用这些信息来决定采取行动、执行工具或引导对话流程。

  • LLM节点:将输出传递给后续的LLM节点,从而实现多个LLM操作的串联。这对于细化文本生成、执行多项分析或将复杂的语言处理分解为多个阶段等任务非常有用。

  • 工具节点:将输出传递给工具节点,从而能够根据大型语言模型(LLM)节点的指令执行特定工具。

  • 条件智能体节点:将流程引导至条件智能体节点。该节点评估大型语言模型(LLM)节点的输出及其预定义条件,以确定工作流程中适当的下一步。

  • 条件节点:与条件智能体节点类似,条件节点使用预定义的条件来评估大型语言模型(LLM)节点的输出,并根据结果将流程导向不同的分支。

  • 结束节点:结束对话流程。

  • 循环节点:将流程重定向回上一个节点,从而在工作流中实现迭代或循环过程。这可用于在多次迭代中优化大型语言模型(LLM)的输出。

附加参数

是否必填
描述

系统提示

定义智能体的“角色”并指导其行为。例如,“您是一名专门从事技术支持的客户服务智能体 [...].”

人工提示

此提示作为人工消息附加到state.messages数组中。它允许我们在大型语言模型(LLM)节点处理完输入后,在下一个节点接收到LLM节点的输出之前,将类似人类的消息注入到对话流中

JSON结构化输出

指示LLM(聊天模型)以JSON结构模式提供输出(键、类型、枚举值、描述)。

更新状态

提供一种在工作流中修改共享自定义状态对象的机制。这对于存储LLM节点收集的信息或影响后续节点的行为非常有用。

最佳实践

选项卡

清除系统提示

设计一个简洁且明确的系统提示,准确反映大型语言模型(LLM)节点的角色和能力。这将指导大型语言模型节点的决策,并确保其在其定义范围内行事。

针对结构化输出进行优化

让你的JSON模式尽可能简洁明了,重点关注基本数据元素。仅当需要从大型语言模型(LLM)的响应中提取特定数据点或下游节点需要JSON输入时,才启用JSON结构化输出。

战略工具选择

选择并配置LLM节点可用的工具(通过工具节点),确保这些工具与应用程序的目的和工作流的总体目标相一致。

敏感任务的HITL(人机交互训练)

对于涉及敏感数据、需要人工判断或存在产生意外后果风险的任务,请使用“需审批”选项。

利用状态更新

策略性地更新自定义状态对象,以存储收集到的信息或影响下游节点的行为。

因HITL设置错误导致的工具意外执行

  • **问题:**虽然大型语言模型(LLM)节点可以触发工具节点,但它依赖于工具节点的配置来进行人机交互(HITL)审批。若未能为敏感操作正确配置HITL,则可能导致工具在未经人工审查的情况下执行,从而可能引发意想不到的后果。

  • 示例:您的LLM节点旨在与一个可更改用户数据的工具进行交互。您打算在执行前让人类审核这些更改,但所连接的工具节点的“需要批准”选项未启用。这可能导致工具仅根据LLM的输出自动修改用户数据,而没有任何人为监督。

  • 解决方案

    1. 仔细检查工具节点设置: 在处理敏感操作的任何工具节点的设置中,始终确保启用“需要审批”选项。

    2. **全面测试人机交互(HITL)流程:**在部署工作流程之前,请测试人机交互流程,确保人工审核步骤按预期触发,且审批/拒绝机制正常运行。

过度使用或误解JSON结构化输出

  • **问题:**尽管大型语言模型(LLM)节点的JSON结构化输出功能十分强大,但若误用或未能充分理解其含义,则可能导致数据出错。

  • 示例:尽管下游任务只需要一个简单的文本响应,但你仍为大型语言模型(LLM)节点的输出定义了一个复杂的JSON模式。这增加了不必要的复杂性,使你的工作流程更难理解和维护。此外,如果LLM的输出不符合定义的架构,可能会导致后续节点出错。

  • 解决方案

    1. **策略性地使用JSON输出:**仅当您明确需要从大型语言模型(LLM)的响应中提取特定数据点,或者下游工具节点需要JSON输入时,才启用JSON结构化输出。

    2. 保持模式简洁:设计你的JSON模式时,要尽可能简单明了,只关注任务中绝对必要的数据元素。


6. 工具节点

工具节点是Flowise顺序智能体系统的重要组成部分,能够在对话工作流程中集成和执行外部工具。它充当大型语言模型(LLM)节点的基于语言处理与外部工具、应用程序编程接口(API)或服务的专用功能之间的桥梁。

了解工具节点

工具节点的主要功能是根据从大型语言模型(LLM)节点接收到的指令来执行外部工具,并在工具执行过程中为人在环(HITL)干预提供灵活性

下面分步解释其工作原理

  1. 工具调用接收:工具节点接收来自大型语言模型(LLM)节点的输入。如果LLM的输出包含tool_calls属性,则工具节点将继续执行工具操作。

  2. **执行:**工具节点直接将大型语言模型(LLM)的tool_calls(包括工具名称和任何所需参数)传递给指定的外部工具。否则,工具节点不会在该特定工作流执行中执行任何工具。它不会以任何方式处理或解释LLM的输出。

  3. **人机协作(HITL):**工具节点支持可选的人机协作,允许在工具执行前由人工进行审核、批准或拒绝。

  4. 输出传递:工具执行完毕后(无论是自动执行还是经过人机交互(HITL)批准后),工具节点会接收工具的输出并将其传递到工作流中的下一个节点。如果工具节点的输出未连接到后续节点,则工具的输出将返回至原始大型语言模型(LLM)节点以进行进一步处理。

输入

必填
描述

LLM节点

接收来自LLM节点的输出,该输出可能包含也可能不包含tool_calls属性。如果存在,工具节点将使用它们来执行指定的工具。

外部工具

为工具节点提供对一套外部工具的访问权限,使其能够执行操作和检索信息。

节点设置

必填
描述

工具节点名称

为工具节点添加描述性名称,以提高工作流的可读性。

需要审批(HITL)

激活人机协作(HITL)功能。如果设置为'True',则工具节点在执行任何工具之前会请求人工审批。这在敏感操作或需要人工监督时特别有价值。默认为'False',允许工具节点自主执行工具。

输出

工具节点可以作为输出连接到以下节点:

  • 智能体节点:将工具节点的输出(即执行工具的结果)传递给智能体节点。智能体节点随后可以使用这些信息来决定采取何种行动、执行其他工具或引导对话流程。

  • LLM节点:将输出传递给后续的LLM节点。这使得工具结果能够融入LLM的处理流程中,从而可以根据工具的输出进一步分析或优化对话流程。

  • 条件智能体节点:将流程引导至条件工具节点。该节点评估工具节点的输出及其预定义的条件,以确定工作流中适当的下一步操作。

  • 条件节点:与条件智能体节点类似,条件节点使用预定义的条件来评估工具节点的输出,并根据结果将流程导向不同的分支。

  • 结束节点:结束对话流程。

  • 循环节点:将流程重定向回上一个节点,从而在工作流中实现迭代或循环过程。这可用于需要多次执行工具或需要根据工具结果优化对话的任务。

附加参数

必填
描述

审批提示

HITL功能激活时,向人工审核者展示的可自定义提示。该提示提供有关工具执行的上下文信息,包括工具的名称和用途。提示中的变量{tools}将动态替换为LLM节点建议的实际工具列表,确保人工审核者拥有做出明智决策所需的所有必要信息。

批准按钮文本

自定义HITL界面中批准工具执行按钮上显示的文本。这允许根据特定上下文调整语言,并确保人工审核者能够清晰理解。

拒绝按钮文本

自定义HITL界面中拒绝工具执行按钮上显示的文本。与批准按钮文本类似,此自定义功能增强了清晰度,并为人工审核者提供了一个明确的操作选项,以便在认为工具执行不必要或可能有害时采取行动。

更新状态

提供一种在工作流中修改自定义状态对象的机制。这对于存储工具节点(在工具执行后)收集的信息或影响后续节点的行为非常有用。

最佳实践

选项卡

战略性HITL布局

考虑哪些工具需要人工监督(HITL),并相应地启用“需要审批”选项。

信息性审批提示

在使用HITL(人机交互测试)时,为人工审核人员设计清晰且信息量大的提示。从对话中提供足够的上下文,并总结工具的预期操作。

未处理的工具输出格式

  • **问题:**工具节点输出的数据格式不符合工作流中后续节点的预期或处理要求,从而导致错误或处理不当。

  • **示例:**一个工具节点从API以JSON格式检索数据,但接下来的LLM节点需要文本输入,这导致了解析错误。 **解决方案:**确保外部工具的输出格式与连接到工具节点输出的节点的输入要求相兼容。


7. 条件节点

条件节点作为顺序智能体工作流中的决策点,评估一组预定义的条件以确定流程的下一步路径。

理解条件节点

条件节点对于构建适应不同情况和用户输入的工作流至关重要。它会检查当前的对话状态,包括所有已交换的消息以及之前定义的任何自定义状态变量。然后,根据节点设置中指定的条件评估结果,条件节点会将流程导向其某个输出。

例如,在智能体或大型语言模型(LLM)节点提供响应后,条件节点可以检查该响应是否包含特定关键词,或者在自定义状态下是否满足特定条件。如果满足,流程可能会被引导至智能体节点以执行进一步操作。如果不满足,则可能会进入不同的路径,例如结束对话或向用户提出更多问题。

这使我们能够在工作流程中创建分支,而分支的路径取决于系统中流动的数据。

以下是其工作原理的详细步骤说明

  1. 条件节点接收来自任何前导节点的输入:起始节点、智能体节点、大型语言模型(LLM)节点或工具节点。

  2. 它能够访问完整的对话历史记录和自定义状态(如果有的话),从而拥有充足的上下文信息可供处理。

  3. 我们定义了一个节点将评估的条件。这可能是检查关键字、比较状态中的值,或者我们可以通过JavaScript实现的任何其他逻辑。

  4. 根据条件评估的结果是还是,条件节点会将其流程发送到预定义的输出路径之一。这为我们的工作流程创建了一个“岔路口”或分支。

如何设置条件

条件节点允许我们在工作流中定义动态分支逻辑,通过选择基于表格的界面JavaScript代码编辑器来定义控制对话流程的条件。

使用CODE的条件

条件节点使用JavaScript来评估对话流程中的特定条件。

我们可以根据关键词、状态变化或其他因素设置条件,以便根据对话的上下文动态地将工作流程引导至不同的分支。以下是一些示例:

关键词条件

这用于检查对话历史记录中是否存在特定的单词或短语。

  • **示例:**我们想检查用户在最后一条消息中是否说了“是”。


/// 译文内容:
---
根据上面的信息,执行如下指令:
缺失译文,请检查输入
const lastMessage = $flow.state.messages[$flow.state.messages.length - 1].content;;
如果 lastMessage 包含 "yes",则返回 "Output 1",否则返回 "Output 2";
  1. 此代码从state.messages中获取最后一条消息,并检查其中是否包含“yes”。

  2. 如果判断结果为“是”,则流程进入“输出1”;否则,进入“输出2”。

状态变化条件

这用于检查自定义状态中的特定值是否已更改为所需值。

  • 示例:我们正在跟踪自定义状态中的orderStatus变量,并想检查它是否已变为“confirmed”。


/// 译文内容:
---
根据上面的信息,执行如下指令:
缺失译文,请检查输入
如果$flow.state.orderStatus为"confirmed",则返回"Output 1",否则返回"Output 2";

这段代码直接将我们自定义状态中的orderStatus值与“confirmed”进行比较。 2. 如果匹配,流程将转到“输出1”;否则,将转到“输出2”。

使用表格的条件

条件节点允许我们使用用户友好的表格界面来定义条件,从而轻松创建动态工作流,而无需编写JavaScript代码。

你可以根据关键词、状态变化或其他因素设置条件,以引导对话流程沿着不同的分支进行。以下是一些示例:

关键词条件

这用于检查对话历史记录中是否存在特定的单词或短语。

  • **示例:**我们想检查用户在最后一条消息中是否说了“是”。

  • 设置

    变量

    操作

    输出名称

    $flow.state.messages[-1].content

    Is

    Yes

    输出1

    1. 此表条目检查state.messages中最后一条消息([-1])的内容(.content)是否等于“Yes”。

    2. 如果条件满足,流程将转到“输出1”。否则,工作流将被定向到默认的“结束”输出。

状态变化条件

这用于检查我们自定义状态中的特定值是否已更改为所需值。

  • **示例:**我们正在自定义状态中跟踪一个名为orderStatus的变量,并想检查它是否已变为“confirmed”。

  • 设置

    变量

    操作

    输出名称

    $flow.state.orderStatus

    Is

    Confirmed

    输出1

    1. 此表格条目用于检查自定义状态中的orderStatus值是否等于“confirmed”。

    2. 如果条件满足,流程将转到“输出1”。否则,工作流将被定向到默认的“结束”输出。

使用表格界面定义条件

这种可视化方法使您能够轻松设置规则,根据用户输入、对话的当前状态或其他节点执行操作的结果等因素,确定对话流程的走向。

基于表格:条件节点
  • 更新日期:2024年8月9日

    描述
    选项/语法

    变量

    要在条件中评估的变量或数据元素。

    - $flow.state.messages.length(总消息数) - $flow.state.messages[0].con(第一条消息内容) - $flow.state.messages[-1].con(最后一条消息内容) - $vars.(全局变量)

    操作

    要对变量执行的对比或逻辑操作。

    - 包含 - 不包含 - 以...开头 - 以...结尾 - 是 - 不是 - 为空 - 非空 - 大于 - 小于 - 等于 - 不等于 - 大于或等于 - 小于或等于

    与变量进行比较的值。

    - 取决于变量的数据类型和所选操作。 - 示例:"yes", 10, "Hello"

    输出名称

    如果条件评估为true,则遵循的输出路径的名称。

    - 用户定义的名称(例如,"Agent1", "End", "Loop")

输入

是否必需
描述

起始节点

从起始节点接收状态。这使得条件节点能够根据对话的初始上下文(包括任何自定义状态)评估条件

智能体节点

接收智能体节点的输出。这使得条件节点能够根据智能体的动作和对话历史(包括任何自定义状态)做出决策

大型语言模型(LLM)节点

接收大型语言模型(LLM)节点的输出。这使得条件节点能够根据LLM的响应和对话历史(包括任何自定义状态)评估条件

工具节点

接收工具节点的输出。这使得条件节点能够根据工具执行的结果和对话历史(包括任何自定义状态)做出决策

{% 提示 样式="信息" %} 条件节点至少需要与以下节点中的一个建立连接:开始节点智能体节点大型语言模型(LLM)节点工具节点。 {% 结束提示 %}

输出

条件节点根据预定义的条件动态确定其输出路径,使用基于表格的界面或JavaScript。这为根据条件评估来指导工作流提供了灵活性。

条件评估逻辑

  • 基于表格的条件:表格中的条件会从上到下依次评估。第一个评估为真的条件会触发其对应的输出。如果所有预定义的条件都不满足,则工作流将跳转到默认的“结束”输出。

  • 基于代码的条件:在使用JavaScript时,我们必须明确返回所需输出路径的名称,包括默认“结束”输出的名称。

  • 单输出路径:一次仅激活一个输出路径。即使可能有多个条件为真,也仅由第一个匹配的条件决定流程。

连接输出

每个预定义的输出,包括默认的“End”输出,都可以连接到以下任何节点:

  • 智能体节点:与智能体继续对话,可能根据条件的结果采取行动。

  • LLM节点:使用大型语言模型(LLM)处理当前状态和对话历史,生成响应或做出进一步决策。

  • 结束节点:用于终止会话流程。如果任何输出(包括默认的“结束”输出)连接到结束节点,则条件节点将输出前一个节点的最后一条响应,并结束工作流。

  • 循环节点:将流程重定向回之前的顺序节点,从而根据条件结果启用迭代流程。

节点设置

必填
描述

条件节点名称

这是一个可选的、人类可读的名称,用于描述正在评估的条件。这有助于一目了然地理解工作流程。

条件

这是我们定义将评估以确定输出路径的逻辑的地方。

最佳实践

选项卡

清晰的条件命名

为你的条件使用描述性名称(例如,“如果用户未满18岁,则启用策略顾问智能体”,“如果订单已确认,则结束节点”),以便使你的工作流程更易于理解和调试。

优先考虑简单条件

从简单的条件开始,并根据需要逐步增加复杂性。这样会使你的工作流程更易于管理,并降低出错的风险。

条件逻辑与工作流设计不匹配

  • **问题:**您在条件节点中定义的条件未能准确反映您工作流程的预期逻辑,从而导致意外的分支或错误的执行路径。

  • 示例:您设置了一个条件来检查用户的年龄是否大于18岁,但该条件的输出路径却指向了一个专为18岁以下用户设计的部分。

  • 解决方案: 检查您的条件,确保与每个条件相关的输出路径与预期的工作流逻辑相匹配。为输出使用清晰且具有描述性的名称,以避免混淆。

状态管理不足

  • **问题:**条件节点依赖于一个自定义状态变量,但该变量未正确更新,导致条件评估不准确,分支错误。

  • 示例:您正在自定义状态中跟踪一个名为“userLocation”的变量,但当用户提供其位置时,该变量并未更新。条件节点基于过时的值评估条件,从而导致错误的路径。 **解决方案:**确保在条件中使用的任何自定义状态变量在整个工作流程中都能正确更新。


8. 条件智能体节点

条件智能体节点在顺序智能体流中提供动态且智能的路由。它结合了大型语言模型(LLM)节点(大型语言模型和JSON结构化输出)和条件节点(用户定义的条件)的功能,使我们能够在单个节点内利用基于智能体的推理和条件逻辑。

主要功能

  • 基于统一智能体的路由选择:将智能体推理、结构化输出和条件逻辑融合于单个节点中,简化了工作流程设计。

  • 情境感知:智能体在评估条件时会考虑整个对话历史和任何自定义状态。

  • 灵活性:在满足不同用户偏好和技能水平的需求时,提供基于表格和基于代码的两种条件定义选项。

设置条件智能体节点

条件智能体节点作为一个专门的智能体,既能处理信息,也能做出路由决策。以下是配置方法:

  1. 定义智能体人的角色

    • 在“系统提示”字段中,提供清晰简洁的描述,说明智能体人的角色以及为进行条件路由所需执行的任务。此提示将指导智能体人理解对话内容及其决策过程。

  2. 构建智能体的输出结构(可选)

    • 如果您希望智能体程序生成结构化输出,请使用“JSON结构化输出”功能。为输出定义所需的模式,指定键、数据类型和任何枚举值。智能体程序在评估条件时将使用此结构化输出。

  3. 定义条件

    • 选择基于表格的界面或JavaScript代码编辑器来定义决定路由行为的条件。

      • 基于表格的界面:在表格中添加行,指定要检查的变量、比较操作、比较值以及条件满足时的输出名称。

      • **JavaScript代码:**编写自定义JavaScript代码片段来评估条件。使用return语句根据条件的结果指定要遵循的输出路径的名称。

  4. 连接输出

    • 将每个预定义的输出(包括默认的“结束”输出)连接到工作流中相应的后续节点。这可以是智能体节点、大型语言模型(LLM)节点、循环节点或结束节点。

如何设置条件

条件智能体节点允许我们在工作流中定义动态分支逻辑,通过选择基于表格的界面JavaScript代码编辑器来定义控制对话流程的条件。

使用CODE的条件

条件智能体节点与条件节点一样,使用JavaScript代码来评估对话流程中的特定条件

然而,条件智能体节点可以根据更广泛的因素来评估条件,包括关键字、状态变化以及其自身输出内容(无论是自由文本还是结构化JSON数据)。这使得能够做出更细致入微且上下文感知的路由决策。以下是一些示例:

关键词条件

这用于检查对话历史记录中是否存在特定的单词或短语。

  • **示例:**我们想检查用户在最后一条消息中是否说了“是”。


/// 译文内容:
---
根据上面的信息,执行如下指令:
缺失译文,请检查输入
const lastMessage = $flow.state.messages[$flow.state.messages.length - 1].content;;
如果 lastMessage 包含 "yes",则返回 "Output 1",否则返回 "Output 2";
  1. 这段代码从state.messages中获取最后一条消息,并检查其是否包含“yes”。

  2. 如果判断结果为“是”,则流程进入“输出1”;否则,进入“输出2”。

状态变化条件

这用于检查自定义状态中的特定值是否已更改为所需的值。

  • **示例:**我们正在跟踪自定义状态中的orderStatus变量,并想检查它是否已变为“confirmed”。

```javascript

/// 译文内容:

根据上面的信息,执行如下指令: 缺失译文,请检查输入 如果$flow.state.orderStatus为"confirmed",则返回"Output 1",否则返回"Output 2";

{% 结束编码 %}

这段代码直接将我们自定义状态中的`orderStatus`值与“confirmed”进行比较。
2. 如果匹配,流程将转到“输出1”;否则,将转到“输出2”。

</details>

<details>

<summary>使用 TABLE 的条件</summary>

条件智能体节点还提供了一个**用户友好的表格界面来定义条件**,这与条件节点类似。您可以基于关键字、状态变化或智能体自身的输出来设置条件,从而无需编写JavaScript代码即可创建动态工作流。

这种基于表格的方法简化了条件管理,并使得分支逻辑的呈现更加直观。以下是一些示例:

**关键词条件**

这用于检查对话历史记录中是否存在特定的单词或短语。

* **示例:**我们想检查用户在最后一条消息中是否说了“是”。
* **设置**

    <table data-header-hidden><thead><tr><th width="305"></th><th width="116"></th><th width="99"></th><th></th></tr></thead><tbody><tr><td><strong>变量</strong></td><td><strong>操作</strong></td><td><strong>值</strong></td><td><strong>输出名称</strong></td></tr><tr><td>$flow.state.messages[-1].content</td><td>Is</td><td>Yes</td><td>输出1</td></tr></tbody></table>

    此表条目用于检查`state.messages`中最后一条消息(\[-1\])的内容(.content)是否等于“Yes”。
    2. 如果条件满足,流程将转到“输出1”。否则,工作流将被定向到默认的“结束”输出。

**状态变化条件**

这用于检查我们自定义状态中的特定值是否已更改为所需值。

* **示例:**我们正在自定义状态中跟踪一个orderStatus变量,并想检查它是否已变为“confirmed”。
* **设置**

    <table data-header-hidden><thead><tr><th width="266"></th><th width="113"></th><th></th><th></th></tr></thead><tbody><tr><td><strong>变量</strong></td><td><strong>操作</strong></td><td><strong>值</strong></td><td><strong>输出名称</strong></td></tr><tr><td>$flow.state.orderStatus</td><td>Is</td><td>Confirmed</td><td>输出1</td></tr></tbody></table>

    1. 此表条目用于检查自定义状态中的orderStatus值是否等于“confirmed”。
    2. 如果条件满足,流程将转到“输出1”。否则,工作流将被定向到默认的“结束”输出。

</details>

### 使用表格界面定义条件

这种可视化方法使您能够轻松设置规则,根据用户输入、对话的当前状态或其他节点执行操作的结果等因素,确定对话流程的走向。

<details>

<summary>基于表格:条件智能体节点</summary>

* **更新日期:2024年8月9日**

    <table><thead><tr><th width="125"></th><th width="186">描述</th><th>选项/语法</th></tr></thead><tbody><tr><td><strong>变量</strong></td><td>要在条件中评估的变量或数据元素。这可以包括来自智能体输出的数据。</td><td>- <code>$flow.output.content</code>(智能体输出 - 字符串)<br>- <code>$flow.output.<replace-with-key></code>(智能体的JSON键输出 - 字符串/数字)<br>- <code>$flow.state.messages.length</code>(总消息数)<br>- <code>$flow.state.messages[0].con</code>(第一条消息内容)<br>- <code>$flow.state.messages[-1].con</code>(最后一条消息内容)<br>- <code>$vars.<variable-name></code>(全局变量)</td></tr><tr><td><strong>操作</strong></td><td>要对变量执行的比较或逻辑操作。</td><td>- 包含<br>- 不包含<br>- 以...开头<br>- 以...结尾<br>- 是<br>- 不是<br>- 为空<br>- 非空<br>- 大于<br>- 小于<br>- 等于<br>- 不等于<br>- 大于或等于<br>- 小于或等于</td></tr><tr><td><strong>值</strong></td><td>要与变量进行比较的值。</td><td>- 取决于变量的数据类型和所选操作。<br>- 示例:"yes", 10, "Hello"</td></tr><tr><td><strong>输出名称</strong></td><td>如果条件评估为<code>true</code>,则要遵循的输出路径的名称。</td><td>- 用户定义的名称(例如,"Agent1", "End", "Loop")</td></tr></tbody></table>

</details>

### 输入

<table><thead><tr><th width="167"></th><th width="118">是否必需</th><th>描述</th></tr></thead><tbody><tr><td>起始节点</td><td>是</td><td>从起始节点接收状态。这使得条件智能体节点能够<strong>根据对话的初始上下文(包括任何自定义状态)评估条件</strong>。</td></tr><tr><td>智能体节点</td><td>是</td><td>接收智能体节点的输出。这使得条件智能体节点能够<strong>根据智能体的动作和对话历史(包括任何自定义状态)做出决策</strong>。</td></tr><tr><td>LLM节点</td><td>是</td><td>接收LLM节点的输出。这使得条件智能体节点能够<strong>根据LLM的响应和对话历史(包括任何自定义状态)评估条件</strong>。</td><tr><td>工具节点</td><td>是</td><td>接收工具节点的输出。这使得条件智能体节点能够<strong>根据工具执行的结果和对话历史(包括任何自定义状态)做出决策</strong>。</td></tr></tbody></table>

{% 提示 样式="信息" %}

**条件智能体节点**至少需要来自以下节点的连接:启动节点、智能体节点、LLM节点或工具节点。

</div>

### 节点设置

<table><thead><tr><th width="178">参数</th><th width="110">必填</th><th>描述</th></tr></thead><tbody><tr><td>Name</td><td>否</td><td>为条件智能体节点添加一个描述性名称,以提高工作流的可读性和易用性。</td></tr><tr><td>Condition</td><td><strong>是</strong></td><td>这是我们<strong>定义将评估以确定输出路径的逻辑</strong>的地方。</td></tr></tbody></table>

### 输出

与条件节点一样,条件智能体节点使用基于表格的界面或JavaScript,**根据定义的条件动态确定其输出路径**。这为根据条件评估来指导工作流提供了灵活性。

#### 条件评估逻辑

* **基于表格的条件**:表格中的条件会从上到下依次评估。第一个评估为真的条件会触发其对应的输出。如果所有预定义的条件都不满足,则工作流将跳转到默认的“结束”输出。
* **基于代码的条件**:在使用JavaScript时,我们必须明确返回所需输出路径的名称,包括默认“结束”输出的名称。
* **单一输出路径**:一次仅激活一个输出路径。即使可能有多个条件为真,也仅由第一个匹配的条件决定流程。

#### 连接输出

每个预定义的输出,包括默认的“End”输出,都可以连接到以下任意节点:

* **智能体节点**:与智能体继续对话,可能根据条件的结果采取行动。
* **LLM节点**:使用大型语言模型(LLM)处理当前状态和对话历史,生成响应或做出进一步决策。
* **结束节点**:用于终止对话流程。如果默认的“结束”输出连接到结束节点,则条件节点将输出前一个节点的最后一条响应,并结束对话。
* **循环节点**:将流程重定向回之前的顺序节点,从而根据条件结果启用迭代流程。

#### 与条件节点的关键区别

* 条件 **智能体节点将智能体的推理**和结构化输出纳入条件评估过程。
* 它为基于智能体的条件路由提供了一种更为集成的方法。

### 附加参数

<table><thead><tr><th width="180"></th><th width="111">必填</th><th>描述</th></tr></thead><tbody><tr><td>系统提示</td><td>否</td><td><strong>定义条件智能体的“角色”,并指导其做出路由决策的行为。</strong>例如:“您是一名专门从事技术支持的客户服务智能体。您的目标是帮助客户解决与我们产品相关的技术问题。根据用户的查询,确定具体的技术问题(例如,连接问题、软件错误、硬件故障)。”</td></tr><tr><td>人工提示</td><td>否</td><td>此提示作为人工消息附加到<code>state.messages</code>数组中。它允许我们在条件智能体节点处理完输入后,在下一个节点接收到条件智能体节点的输出之前,<strong>将类似人类的消息注入到对话流中</strong>。</td></tr><tr><td>JSON结构化输出</td><td>否</td><td>指示条件智能体节点<strong>以JSON结构模式提供输出</strong>(键、类型、枚举值、描述)。</td></tr></tbody></table>

### 最佳实践

标签页

<div data-gb-custom-block data-tag="tab" data-title='专业提示'>

**设计一个清晰且目标明确的系统提示**

在系统提示中为智能体提供一个定义明确的人物角色和清晰的指令。这将引导其推理过程,并帮助其针对条件逻辑生成相关输出。

**可靠条件下的结构输出**

使用JSON结构化输出功能为条件智能体的输出定义一个模式。这将确保输出的一致性和易解析性,使其在条件评估中的使用更加可靠。

</div>

<div data-gb-custom-block data-tag="tab" data-title='潜在陷阱'>

**因输出无结构化而导致路由不可靠**

* **问题:**条件智能体节点未配置为输出结构化JSON数据,导致输出格式不可预测,从而难以定义可靠的条件。
* **示例**:条件智能体节点被要求确定用户情绪(积极、消极、中性),但其评估结果以自由文本字符串的形式输出。由于智能体语言存在变异性,因此在条件表或代码中创建精确的条件颇具挑战性。
* **解决方案:** 使用JSON结构化输出功能为智能体的输出定义一个模式。例如,指定一个“sentiment”键,其枚举值为“positive”、“negative”和“neutral”。这将确保智能体的输出结构一致,从而更容易创建可靠的条件。

</div>

</div>

***

## 9. 循环节点

循环节点允许我们在对话流程中创建循环,**将对话重定向回特定点**。这在需要根据用户输入或特定条件重复特定操作序列或问题的场景中非常有用。

<figure><img src="../../../.gitbook/assets/sa-loop.png" alt="" width="335"><figcaption></figcaption></figure>

### 理解循环节点

循环节点起到连接器的作用,将流程重定向回图中的特定点,从而允许我们在对话流程中创建循环。**它将当前状态传递给我们的目标节点,该状态包括循环节点之前节点的输出。**这种数据传输使我们的目标节点能够处理来自循环前一次迭代的信息,并相应地调整其行为。

例如,假设我们正在构建一个帮助用户预订航班的聊天机器人。我们可能会使用一个循环,根据用户反馈来迭代优化搜索条件。

#### 循环节点使用方法如下

1. **大型语言模型节点(初始搜索):**大型语言模型节点接收用户的初始航班请求(例如,“查找7月份从马德里飞往纽约的航班”)。它向航班搜索API发出查询,并返回可能的航班列表。
2. **智能体节点(显示选项):**智能体节点向用户展示航班选项,并询问他们是否希望进一步细化搜索(例如,“您想按价格、航空公司还是出发时间进行筛选?”)。
3. **条件智能体节点**:条件智能体节点检查用户的响应,并有两个输出:
   * **如果用户想要细化搜索:**流程将进入“细化搜索”大型语言模型(LLM)节点。
   * **如果用户对结果满意:**流程将进入预订环节。
4. **大型语言模型(LLM)节点(细化搜索):**此LLM节点收集用户的细化条件(例如,“只显示价格低于500美元的航班”),并使用新的搜索参数更新状态。
5. **循环节点**:循环节点将流程重定向回初始的LLM节点(“初始搜索”)。它将传递更新后的状态,该状态现在包含了已优化的搜索条件。
6. **迭代:**初始的大型语言模型(LLM)节点使用细化后的标准进行新的搜索,并从步骤2开始重复该过程。

**在此示例中,循环节点实现了迭代搜索细化过程。**系统可以持续循环并细化搜索结果,直至用户对呈现的选项感到满意。

### 输入

<table><thead><tr><th width="197"></th><th width="104">是否必需</th><th>描述</th></tr></thead><tbody><tr><td>智能体节点</td><td><strong>是</strong></td><td>接收前一个智能体节点的输出。然后,这些数据会被发送回“循环至”参数中指定的目标节点。</td></tr><tr><td>LLM节点</td><td><strong>是</strong></td><td>接收前一个LLM节点的输出。然后,这些数据会被发送回“循环至”参数中指定的目标节点。</td></tr><tr><td>工具节点</td><td><strong>是</strong></td><td>接收前一个工具节点的输出。然后,这些数据会被发送回“循环至”参数中指定的目标节点。</td><tr><td>条件节点</td><td><strong>是</strong></td><td>接收前一个条件节点的输出。然后,这些数据会被发送回“循环至”参数中指定的目标节点。</td><tr><td>条件智能体节点</td><td><strong>是</strong></td><td>接收前一个条件智能体节点的输出。然后,这些数据会被发送回“循环至”参数中指定的目标节点。</td></tr></tbody></table>

信息提示框
**循环节点至少需要以下节点中的一个连接**:智能体节点、LLM节点、工具节点、条件节点或条件智能体节点。

</div>

### 节点设置

<table><thead><tr><th width="125"></th><th width="109">必填</th><th>描述</th></tr></thead><tbody><tr><td>循环目标</td><td><strong>是</strong></td><td>循环节点要求我们<strong>指定目标节点</strong>(“循环目标”),会话流程应重定向至此节点。此目标节点必须是<strong>智能体节点</strong>或<strong>大型语言模型(LLM)节点</strong>。</td></tr></tbody></table>

### 输出

**循环节点**没有任何直接输出连接。它将流程重定向回图中的特定顺序节点。

### 最佳实践

选项卡

<div data-gb-custom-block data-tag="tab" data-title='专业小技巧'>

**明确循环目的**

为工作流程中的每个循环设定一个明确的目的。如果可能的话,用便签纸记录下你希望通过这个循环达到的目标。

</div>

<div data-gb-custom-block data-tag="tab" data-title='潜在陷阱'>

**工作流程结构混乱**

* **问题:**循环过多或设计不当会使工作流程难以理解和维护。
* **示例**:你使用了多个嵌套的循环,但没有明确的目的或标签,使得对话的流程难以理解。
* **解决方案:** 谨慎使用循环,仅在必要时使用。清晰地记录循环节点及其连接的节点。

**因缺少退出条件或退出条件错误导致的无限循环**

* **问题:**循环永远不会终止,因为触发循环退出的条件缺失或定义错误。
* **示例**:循环节点用于迭代收集用户信息。然而,工作流程中缺少条件智能体节点来检查是否已收集到所有必要信息。因此,循环会无限期地继续,反复要求用户提供相同的信息。
**解决方案:**始终为循环定义清晰准确的退出条件。使用条件节点来检查状态变量、用户输入或其他指示循环何时应终止的因素。

</div>

</div>

***

## 10. 结束节点

终结节点标志着顺序智能体工作流程中对话的最终**终止点**。它表示不需要进行进一步的处理、操作或交互。

<figure><img src="../../../.gitbook/assets/seq-end-node.png" alt="" width="375"><figcaption></figcaption></figure>

### 理解端节点

终结节点在Flowise的顺序智能体架构中起到信号作用,**表明对话已达到预期结论**。当到达终结节点时,系统“理解”对话目标已达成,流程中无需进一步操作或交互。

### 输入

<table><thead><tr><th width="212"></th><th width="103">是否必需</th><th>描述</th></tr></thead><tbody><tr><td>智能体节点</td><td><strong>是</strong></td><td>接收来自前一个智能体节点的最终输出,表示智能体处理结束。</td></tr><tr><td>大型语言模型(LLM)节点</td><td><strong>是</strong></td><td>接收来自前一个大型语言模型(LLM)节点的最终输出,表示LLM节点处理结束。</td></tr><tr><td>工具节点</td><td><strong>是</strong></td><td>接收来自前一个工具节点的最终输出,表示工具节点执行完成。</td></tr><tr><td>条件节点</td><td><strong>是</strong></td><td>接收来自前一个条件节点的最终输出,表示条件节点执行结束。</td><tr><tr><td>条件智能体节点</td><td><strong>是</strong></td><td>接收来自前一个条件节点的最终输出,表示条件智能体节点处理完成。</td></tr></tbody></table>

<div data-gb-custom-block data-tag="hint" data-style='info'>

**端节点**至少需要以下节点中的一个连接:智能体节点、大型语言模型(LLM)节点或工具节点。

</div>

### 输出

**终端节点**没有任何输出连接,因为它标志着信息流的终止。

### 最佳实践

选项卡

<div data-gb-custom-block data-tag="tab" data-title='专业提示'>

**提供最终回复**

如果合适的话,将终端节点连接到专用的LLM(大型语言模型)或智能体节点,为用户生成最终消息或摘要,从而结束对话。

</div>

<div data-gb-custom-block data-tag="tab" data-title='潜在陷阱'>

**对话提前终止**

* **问题:**结束节点在工作流中的位置设置过早,导致对话在所有必要步骤完成或用户请求得到充分处理之前就结束了。
* **示例**:一个旨在收集用户反馈的聊天机器人在用户给出第一条评论后就结束了对话,没有给他们机会提供更多反馈或提出问题。
**解决方案:**检查您的工作流逻辑,确保仅在所有必要步骤完成后或用户明确表示结束对话的意图后,才放置结束节点。

**用户缺乏关闭功能**

**问题:**对话在没有向用户发出明确信号或给出让人感觉结束的最后信息的情况下突然结束。
* **示例:**一个客户支持聊天机器人在解决问题后立即结束对话,既没有与用户确认解决方案,也没有提供进一步的帮助。
* **解决方案:** 将终端节点连接至专用大型语言模型(LLM)或智能体节点,以生成最终响应,该响应总结对话内容、确认所采取的任何行动,并为用户提供一种结束感。

</div>

</div>

***

## 条件节点与条件智能体节点

在Flowise的顺序智能体架构中,条件和条件智能体节点对于创建动态对话体验至关重要。

这些节点能够支持自适应工作流程,对用户输入、上下文和复杂决策做出响应,但在条件评估的方法和复杂程度上有所不同。

<details>

<summary><strong>条件节点</strong></summary>

**目的**

根据简单的、预定义的逻辑条件创建分支。

**条件评估**

使用基于表格的界面或JavaScript代码编辑器来定义根据自定义状态和/或完整对话历史记录进行核查的条件。

**输出行为**

* 支持多个输出路径,每个路径都与特定条件相关联。
* 条件按顺序进行评估。第一个匹配的条件决定输出结果。
* 如果条件都不满足,流程将遵循默认的“结束”输出。

**最适合**

* 基于易于定义的条件,做出直接的路由决策。
* 那些逻辑可以通过简单比较、关键字检查或自定义状态变量值来表达的工作流。

</details>

<details>

<summary><strong>条件智能体节点</strong></summary>

**目的**

根据智能体对对话的分析及其结构化输出,创建动态路由。

**条件评估**

* 如果未连接聊天模型,它将使用默认的系统大型语言模型(来自起始节点)来处理对话历史和任何自定义状态。
* 它能生成结构化输出,这些输出随后被用于条件评估。
* 使用基于表格的界面或JavaScript代码编辑器来定义根据智能体自身输出(无论是否结构化)进行核查的条件。

**输出行为**

与条件节点相同:

* 支持多个输出路径,每个路径都与特定条件相关联。
* 条件按顺序进行评估。第一个匹配的条件决定输出结果。
* 如果条件都不满足,流程将遵循默认的“结束”输出。

**最适合**

* 更复杂的路由决策,需要理解对话上下文、用户意图或细微因素。
* 简单的逻辑条件不足以捕捉到所需路由逻辑的情况。
* **示例**:一个聊天机器人需要判断用户的问题是否与特定产品类别相关。可以使用条件智能体节点来分析用户的查询,并输出一个包含“类别”字段的JSON对象。然后,条件智能体节点可以使用这个结构化输出来将用户路由到相应的产品专家。

</details>

### 总结

<table><thead><tr><th width="218"></th><th width="258">条件节点</th><th>条件智能体节点</th></tr></thead><tbody><tr><td><strong>决策逻辑</strong></td><td>基于预定义的逻辑条件。</td><td>基于智能体的推理和结构化输出。</td></tr><tr><td><strong>智能体参与</strong></td><td>条件评估中不涉及智能体。</td><td>使用智能体处理上下文并为条件生成输出。</td></tr><tr><td><strong>结构化输出</strong></td><td>不可能。</td><td>可能且鼓励用于可靠的条件评估。</td></tr><tr><td><strong>条件评估</strong></td><td>仅定义针对完整对话历史检查的条件。</td><td>可以定义针对智能体自身输出(无论是否结构化)检查的条件。</td></tr><tr><td><strong>复杂性</strong></td><td>适用于简单的分支逻辑。</td><td>处理更细致和上下文感知的路由。</td></tr><tr><td><strong>理想用例</strong></td><td><ul><li>基于用户年龄或对话中的关键词进行路由。</li></ul></td><td><ul><li>基于用户情绪、意图或复杂上下文因素进行路由。</li></ul></td></tr></tbody></table>

### 选择正确的节点

* **条件节点**:当您的路由逻辑涉及基于易于定义的条件进行的直接决策时,请使用条件节点。例如,它非常适合用于检查特定关键字、比较状态中的值或评估其他简单的逻辑表达式。
* **条件智能体节点**:然而,当您的路由需求需要对对话的细微差别有更深入的理解时,条件智能体节点是更好的选择。该节点充当您的智能路由助手,利用大型语言模型(LLM)分析对话,根据上下文做出判断,并提供结构化输出,从而推动更复杂、更动态的路由。

***

## 智能体节点与大型语言模型(LLM)节点

重要的是要理解,在我们的系统中,**大型语言模型(LLM)节点和智能体节点都可以被视为智能体实体**,因为它们都利用了大型语言模型(LLM)或聊天模型的能力。

然而,尽管这两个节点都能处理语言并与工具交互,但它们在工作流程中被设计用于不同的目的。

<details>

<summary>智能体节点</summary>

**专注**

智能体节点的主要目标是模拟人类智能体在对话情境中的行为和决策过程。

它作为工作流程中的高级协调器,将语言理解、工具执行和决策制定融合在一起,以创造更接近人类的对话体验。

**优势**

* 有效管理多个工具的执行,并整合其结果。
* 提供对人机协作(HITL)的内置支持,使敏感操作能够得到人工审核和批准。

**最适合**

* 在这些工作流程中,智能体需要引导用户、收集信息、做出选择,并管理整个对话流程。
* 需要与多个外部工具集成的场景。
* 涉及敏感数据或需要人工监督以利执行的任务,如批准金融交易

</details>

<details>

<summary>LLM节点</summary>

**专注**

与智能体节点类似,但通过工具节点在使用工具和人机在环(HITL)时提供了更大的灵活性。

**优势**

* 支持定义JSON模式来构建大型语言模型(LLM)的输出结构,从而更便于提取特定信息。
* 提供工具集成的灵活性,允许执行更复杂的LLM和工具调用序列,并对HITL功能进行精细控制。

**最适合**

* 需要从大型语言模型(LLM)的响应中提取结构化数据的场景。
* 需要自动化和人工审核工具执行相结合的工作流程。例如,一个大型语言模型(LLM)节点可能会调用一个工具来检索产品信息(自动化),然后调用另一个工具来处理付款,这需要人机交互(HITL)的批准。

</details>

### 总结

<table><thead><tr><th width="206"></th><th width="253">智能体节点</th><th>LLM节点</th></tr></thead><tbody><tr><td><strong>工具交互</strong></td><td>直接调用和管理多个工具,内置HITL。</td><td>通过工具节点触发工具,在工具级别进行精细的HITL控制。</td></tr><tr><td><strong>人机交互(HITL)</strong></td><td>HITL在智能体节点级别控制(所有连接的工具均受影响)。</td><td>HITL在单个工具节点级别管理(更具灵活性)。</td></tr><tr><td><strong>结构化输出</strong></td><td>依赖于LLM的自然输出格式。</td><td>依赖于LLM的自然输出格式,但如果需要,可提供JSON模式定义以结构化LLM输出。</td></tr><tr><td><strong>理想用例</strong></td><td><ul><li>具有复杂工具编排的工作流程。</li><li>智能体级别的简化HITL。</li></ul></td><td><ul><li>从LLM输出中提取结构化数据</li><li>具有复杂LLM和工具交互的工作流程,需要混合HITL级别。</li></ul></td></tr></tbody></table>

### 选择正确的节点

* **选择智能体节点(Agent Node):** 当您需要创建一个能够管理多个工具执行的对话系统时,请使用智能体节点,所有这些工具都共享相同的HITL设置(整个智能体节点启用或禁用)。智能体节点也非常适合处理需要一致类智能体行为的复杂多步骤对话。
* **选择LLM节点**:另一方面,当您需要使用JSON模式功能从LLM的输出中提取结构化数据时,请使用LLM节点,这是智能体节点所不具备的能力。LLM节点还擅长在单个工具级别对HITL进行精细控制,从而协调工具执行,使您能够通过使用连接到LLM节点的多个工具节点,混合自动化和人工审核的工具执行。

[^1]:在当前上下文中,较低的抽象层次指的是一个向开发者展示更多实现细节的系统。

Last updated