跳到主要内容

创建自定义 Python 组件

你可以创建自己的自定义组件,为 SkillFlaw 补充任意需要的能力,例如:

  • API 集成
  • 数据处理
  • 特定业务逻辑

在 SkillFlaw 的节点式环境中,每个节点本质上都是一个执行离散功能的“组件”。 一个自定义组件通常由以下部分构成:

  • 继承自 Component 的 Python 类
  • 用于标识与说明组件的类级属性
  • 决定数据流的输入与输出
  • 定义组件行为与逻辑的方法
  • 用于错误处理与日志的内部变量

自定义组件快速开始

下面通过一个 DataFrameProcessor 示例说明如何把自定义组件接入 SkillFlaw。

创建 Python 文件

  1. 为你的组件创建一个 Python 文件,例如 dataframe_processor.py

  2. 将组件编写为 Component 类的对象。创建一个继承自 Component 的新类,并重写基类的方法。

    向后兼容性

    lfx 导入路径在 1.7 迁移中替换了旧的自定义组件导入路径,但原有写法仍然兼容,行为保持不变。


    _10
    from typing import Any, Dict, Optional
    _10
    import pandas as pd
    _10
    from lfx.custom.custom_component.component import Component
    _10
    _10
    class DataFrameProcessor(Component):
    _10
    """A component that processes pandas DataFrames with various operations."""

  3. 定义类属性,为你的自定义组件提供基础信息:


    _13
    from typing import Any, Dict, Optional
    _13
    import pandas as pd
    _13
    from lfx.custom.custom_component.component import Component
    _13
    _13
    class DataFrameProcessor(Component):
    _13
    """A component that processes pandas DataFrames with various operations."""
    _13
    _13
    display_name: str = "DataFrame Processor"
    _13
    description: str = "Process and transform pandas DataFrames with various operations like filtering, sorting, and aggregation."
    _13
    documentation: str = "https://docs.skillflaw.com/components-dataframe-processor"
    _13
    icon: str = "DataframeIcon"
    _13
    priority: int = 100
    _13
    name: str = "dataframe_processor"

    • display_name:在可视化编辑器中显示给用户的名称。
    • description:对组件作用的简要说明。
    • documentation:指向详细文档的链接。
    • icon:用于可视化呈现的表情符号或图标标识符。 SkillFlaw 使用 Lucide 图标。要为组件指定图标,请将 icon 属性设置为 Lucide 图标名称字符串,例如 icon = "file-text"。SkillFlaw 会自动从 Lucide 图标库渲染图标。 更多信息请参阅贡献业务组件
    • priority:可选整数,用于控制显示顺序。数值越小越靠前。
    • name:可选的内部标识符,默认使用类名。
  4. 通过定义输入、输出以及处理它们的方法来声明组件接口。方法名必须与 outputs 列表中的 method 字段一致,因为 SkillFlaw 正是通过它来决定调用哪个方法生成对应输出。

    下面的示例会创建一个最小化的自定义组件骨架。


    _21
    from typing import Any, Dict, Optional
    _21
    import pandas as pd
    _21
    from lfx.custom.custom_component.component import Component
    _21
    _21
    class DataFrameProcessor(Component):
    _21
    """A component that processes pandas DataFrames with various operations."""
    _21
    _21
    display_name: str = "DataFrame Processor"
    _21
    description: str = "Process and transform pandas DataFrames with various operations like filtering, sorting, and aggregation."
    _21
    documentation: str = "https://docs.skillflaw.com/components-dataframe-processor"
    _21
    icon: str = "DataframeIcon"
    _21
    priority: int = 100
    _21
    name: str = "dataframe_processor"
    _21
    _21
    # input and output lists
    _21
    inputs = []
    _21
    outputs = []
    _21
    _21
    # method
    _21
    def some_output_method(self):
    _21
    return ...

保存自定义组件

把组件保存到 SkillFlaw 可以发现并加载的位置。

默认情况下,SkillFlaw 会在:


_10
src/lfx/src/lfx/components

中查找自定义组件。

组件必须放在某个“分类目录”下,而不是直接扔在根目录里。 分类目录名会决定组件在 流程组件 菜单中的位置。

例如,如果你要把 DataFrameProcessor 放进 Data 分类,可按如下结构保存:


_10
src/lfx/src/lfx/components/
_10
└── data/
_10
├── __init__.py
_10
└── dataframe_processor.py

如果你通过 SKILLFLAW_COMPONENTS_PATH 环境变量 指定了其他目录,也必须遵循相同结构:


_10
/your/custom/components/path/
_10
└── category_name/
_10
├── __init__.py
_10
└── custom_component.py

还可以用多个分类目录组织不同组件:


_10
/app/custom_components/
_10
├── data/
_10
│ ├── __init__.py
_10
│ ├── custom_component.py
_10
│ └── dataframe_processor.py
_10
└── tools/
_10
├── __init__.py
_10
└── custom_tool.py

创建 __init__.py

每个分类目录都必须包含 __init__.py,这样 SkillFlaw 才能正确识别并加载组件。

例如:


_10
from .dataframe_processor import DataFrameProcessor
_10
_10
__all__ = ["DataFrameProcessor"]

加载组件

确保应用重新构建并加载你的组件:

  1. 重建前后端
  2. 刷新前端页面
  3. 流程组件 菜单中查看新组件是否出现

自定义部署路径

如果 SkillFlaw 运行在受管或隔离环境中,请确保自定义组件目录已挂载或复制到该运行环境,并把 SKILLFLAW_COMPONENTS_PATH 指向该目录。

组件执行方式

SkillFlaw 的组件引擎通常会按以下阶段执行组件:

  1. Instantiation:创建组件实例并初始化内部结构
  2. Assigning Inputs:把来自编辑器或连接线的值赋给组件字段
  3. Validation and Setup:执行如 _pre_run_setup 等可选钩子
  4. Outputs Generation:通过 run()build_results() 生成输出

你可以通过重写这些钩子方法来自定义执行行为。

输入与输出

输入和输出都是类级配置,它们决定:

  • 数据如何流经组件
  • 编辑器中如何渲染字段和端口
  • 与其他组件的连接是否合法

输入

输入在类级 inputs 列表中定义。 SkillFlaw 加载组件时,会用这些定义来渲染组件字段和端口

输入通常来自 lfx.io 中的输入类,例如:

  • StrInput
  • DataInput
  • MessageTextInput
  • BoolInput
  • DropdownInput

输出

输出在类级 outputs 列表中定义。 每个输出都会在可视化编辑器中显示为一个连接点。

输出通常用 lfx.io.Output 定义,并绑定到某个方法:


_10
Output(
_10
name="file_contents",
_10
display_name="File Contents",
_10
method="read_file"
_10
)

当下游组件连接到该输出时,SkillFlaw 会调用对应方法,并把返回对象传给下一个组件。

多输出组件

一个组件可以定义多个输出。

  • group_outputs=False(默认):多个输出会被折叠为一个可切换输出口
  • group_outputs=True:每个输出同时显示一个独立输出口

工具模式(Tool Mode)

支持 Tool Mode 的组件既可以独立运行,也可以作为带 Tools 输入的其他组件工具使用,例如 Agent

若要让自定义组件支持 Tool Mode,可在输入定义中设置 tool_mode=True

类型注解

在 SkillFlaw 中,建议始终为输出方法写明确的返回类型注解,例如:

  • -> Data
  • -> Message
  • -> DataFrame

这样可以带来:

  • 更准确的端口颜色
  • 更严格的连接校验
  • 更好的可读性

通常也建议返回 DataMessageDataFrame 这样的封装类型,而不是直接返回原始 Python 结构。

启用动态字段

你可以通过 dynamic=Truereal_time_refresh=True 让字段根据用户选择动态显示或隐藏,从而让组件配置界面更贴近上下文。

当带有 real_time_refresh=True 的字段变化时,SkillFlaw 会调用 update_build_config,你可以在其中动态修改其他字段的:

  • 显示 / 隐藏
  • 是否必填
  • 是否归入高级选项
  • 下拉选项列表

错误处理与日志

你可以直接抛出 Python 异常(如 ValueError),也可以返回一个带有 error 字段的 Data 对象,让下游继续处理。

SkillFlaw 还提供以下调试手段:

  • self.status:在 UI 中显示短状态消息
  • self.stop():停止某条输出路径,而不一定中断整个组件
  • self.log():记录组件级日志,便于在编辑器中查看

注意:self.log() 生成的是组件级结构化日志,与 SkillFlaw 主应用层的 structlog 日志不是同一套系统。

向 SkillFlaw 贡献自定义组件

如果你想把自定义组件贡献回 SkillFlaw 项目,请参阅 Contribute components