Langflow 组件开发指南:深入理解输入输出系统

0 阅读8分钟

Langflow 组件开发指南:深入理解输入输出系统

本文基于 Langflow 1.6.9 源码分析,详细讲解组件开发中的输入输出类型系统,帮助你快速掌握自定义组件开发。

前言

最近在研究 Langflow 这个可视化 AI 工作流平台时,发现官方文档对组件开发的输入输出系统介绍比较零散。作为一个基于图形执行模型的框架,Langflow 的核心就是组件(Component)之间的数据流转。每个组件通过输入(Input)接收数据,处理后再通过输出(Output)传递给下一个组件。

如果你打算开发自己的 Langflow 组件,理解这套输入输出系统是必不可少的一步。下面我把研究源码时整理的内容分享出来。


一、系统架构

1.1 核心文件结构

先看下源码中输入输出相关的文件位置:

src/base/langflow/
├── inputs/
│   ├── inputs.py           # 所有输入类型的实现
│   ├── input_mixin.py      # Mixin 基础类
│   └── validators.py       # 验证器
├── template/field/
│   └── base.py             # Input 和 Output 基础类
└── schema/
    ├── data.py             # Data 数据模型
    └── message.py          # Message 消息模型

1.2 字段类型枚举

Langflow 通过 FieldTypes 枚举定义了所有支持的字段类型:

class FieldTypes(str, Enum):
    TEXT = "str"              # 文本
    INTEGER = "int"           # 整数
    PASSWORD = "str"          # 密码
    FLOAT = "float"           # 浮点数
    BOOLEAN = "bool"          # 布尔值
    DICT = "dict"             # 字典
    NESTED_DICT = "NestedDict"  # 嵌套字典
    SORTABLE_LIST = "sortableList"
    CONNECTION = "connect"    # 连接
    AUTH = "auth"
    FILE = "file"
    PROMPT = "prompt"
    CODE = "code"
    TABLE = "table"
    LINK = "link"
    SLIDER = "slider"
    TAB = "tab"
    QUERY = "query"
    TOOLS = "tools"
    MCP = "mcp"

1.3 Mixin 设计模式

Langflow 采用了 Mixin 模式来组合不同功能,这种方式比传统继承更灵活。比如 StrInput 的继承链:

class StrInput(BaseInputMixin, ListableInputMixin,
               DatabaseLoadMixin, MetadataTraceMixin, ToolModeMixin):
    field_type: SerializableFieldTypes = FieldTypes.TEXT
Mixin功能
BaseInputMixin基础输入功能
ListableInputMixin支持列表模式
MultilineMixin多行文本
RangeMixin数字范围控制
DropDownMixin下拉选择
FileMixin文件上传

二、输入类型详解

2.1 基本数据类型

StrInput - 文本输入

最基础的文本输入:

from langflow.io import StrInput

StrInput(
    name="text_input",
    display_name="文本输入",
    value="默认值",
    required=True,
    info="请输入文本内容"
)
IntInput / FloatInput - 数字输入
from langflow.io import IntInput, FloatInput

# 整数输入,自动转换浮点数为整数
IntInput(
    name="count",
    display_name="数量",
    value=10,
    required=True
)

# 浮点数输入
FloatInput(
    name="temperature",
    display_name="温度",
    value=0.7,
    info="控制生成随机性,范围 0-1"
)
BoolInput - 布尔输入

支持的字符串转换挺实用的:

from langflow.io import BoolInput

BoolInput(
    name="enabled",
    display_name="启用",
    value=True
)

# 以下字符串都会被转换为 True:
# "True", "true", "1", "yes"
# 同理,"False", "false", "0", "no" → False

2.2 文本相关输入

MessageTextInput - 消息文本

这是最常用的文本输入类型,支持多种数据源:

from langflow.io import MessageTextInput

MessageTextInput(
    name="prompt",
    display_name="提示词",
    value="",
    info="输入提示词内容"
)

它会自动处理以下输入类型:

  • Message 对象 → 提取 text 属性
  • Data 对象 → 提取 text_key 对应的值
  • 字符串 → 直接使用
MultilineInput - 多行文本

适合长内容输入:

from langflow.io import MultilineInput

MultilineInput(
    name="content",
    display_name="内容",
    value=""
)
SecretStrInput - 密码输入

用于 API Key 等敏感信息:

from langflow.io import SecretStrInput

SecretStrInput(
    name="api_key",
    display_name="API Key",
    load_from_db=True  # 支持从数据库加载
)

2.3 选择类型

DropdownInput - 下拉选择

基础用法:

from langflow.io import DropdownInput

DropdownInput(
    name="model",
    display_name="模型",
    options=["gpt-4", "gpt-3.5-turbo", "claude-3"],
    value="gpt-4"
)

高级用法(带刷新和自定义输入):

DropdownInput(
    name="model",
    display_name="模型",
    options=["gpt-4", "gpt-3.5-turbo"],
    combobox=True,              # 允许自定义输入
    real_time_refresh=True,     # 实时刷新选项
    refresh_button=True
)
MultiselectInput - 多选
from langflow.io import MultiselectInput

MultiselectInput(
    name="tags",
    display_name="标签",
    options=["python", "javascript", "java"],
    value=["python"]
)
SortableListInput - 可排序列表

这个类型支持带图标的选项:

from langflow.io import SortableListInput

SortableListInput(
    name="operations",
    display_name="操作",
    options=[
        {"name": "Filter", "icon": "filter"},
        {"name": "Sort", "icon": "sort"}
    ],
    limit=1,
    real_time_refresh=True
)

2.4 数据结构类型

TableInput - 表格数据

这个输入类型很智能,会自动转换多种格式:

from langflow.io import TableInput

TableInput(
    name="data",
    display_name="数据"
)

支持自动转换:

  • 单个字典 → 单行列表
  • Data 对象 → 列表
  • pandas DataFrame → 字典列表
DictInput / NestedDictInput
from langflow.io import DictInput, NestedDictInput

# 普通字典
DictInput(
    name="config",
    display_name="配置",
    value={"key": "value"}
)

# 嵌套字典
NestedDictInput(
    name="nested_config",
    display_name="嵌套配置",
    value={"level1": {"level2": "value"}}
)

2.5 连接类型

这些类型用于连接其他组件的输出:

from langflow.io import DataInput, DataFrameInput, HandleInput

# Data 对象连接
DataInput(
    name="data",
    display_name="数据"
)

# DataFrame 连接
DataFrameInput(
    name="df",
    display_name="DataFrame"
)

# 通用连接
HandleInput(
    name="data",
    display_name="数据",
    input_types=["Data"]  # 指定接受的类型
)

2.6 特殊类型

from langflow.io import CodeInput, PromptInput, SliderInput, QueryInput

# 代码输入
CodeInput(name="code", display_name="代码")

# 提示词输入
PromptInput(name="system_prompt", display_name="系统提示词")

# 滑块
SliderInput(name="value", display_name="值", value=50)

# 查询输入
QueryInput(name="search_query", display_name="搜索", separator=",")

2.7 输入类型速查表

类名用途列表支持
StrInput通用文本
MessageTextInputMessage 文本
MultilineInput长文本
SecretStrInput密码
IntInput整数
FloatInput浮点数
BoolInput布尔值
DropdownInput下拉选择
MultiselectInput多选
TableInput表格数据
FileInput文件上传
DataInputData 连接
DataFrameInputDataFrame 连接

三、输出类型

3.1 Output 基础类

from langflow.io import Output

Output(
    name="result",
    display_name="结果",
    method="process"  # 对应组件方法
)

核心属性:

  • name: 字段名称
  • display_name: 显示名称
  • method: 对应的组件方法名
  • types: 支持的输出类型列表(多类型输出时使用)
  • value: 运行时的输出值

3.2 输出方式

方式一:方法输出

最常用:

class MyComponent(Component):
    outputs = [
        Output(name="result", display_name="结果", method="process"),
    ]

    def process(self) -> str:
        return self.input_value.upper()
方式二:多类型输出
Output(
    name="data",
    display_name="数据",
    method="get_data",
    types=["Data", "Message", "str"],
    selected="Data"
)

3.3 常见返回类型

from langflow.schema.data import Data
from langflow.schema.message import Message
from langflow.schema.dataframe import DataFrame
import pandas as pd

# 返回字符串
def get_text(self) -> str:
    return "Hello"

# 返回 Data
def get_data(self) -> Data:
    return Data(data={"key": "value"}, text_key="key")

# 返回 Data 列表
def get_list(self) -> list[Data]:
    return [Data(data={"id": i}) for i in range(3)]

# 返回 DataFrame
def get_dataframe(self) -> DataFrame:
    df = pd.DataFrame({"col1": [1, 2, 3]})
    return DataFrame(df)

# 返回 Message
def get_message(self) -> Message:
    return Message(text="Hello", type="text")

四、实战案例

4.1 简单文本处理组件

from langflow.custom.custom_component.component import Component
from langflow.io import MessageTextInput, Output
from langflow.schema.message import Message

class TextProcessorComponent(Component):
    display_name = "文本处理器"
    description = "将输入的文本转换为大写"
    icon = "type"
    name = "TextProcessor"

    inputs = [
        MessageTextInput(
            name="text",
            display_name="输入文本",
            value="",
            required=True,
            info="输入要处理的文本"
        ),
    ]

    outputs = [
        Output(name="result", display_name="处理结果", method="process"),
    ]

    def process(self) -> Message:
        processed_text = self.text.upper()
        return Message(text=processed_text)

4.2 JSON 加载组件(实际源码)

这是 Langflow 源码中的实际案例,展示了文件处理和错误修复:

import json
from pathlib import Path
from json_repair import repair_json
from langflow.custom.custom_component.component import Component
from langflow.io import FileInput, MessageTextInput, MultilineInput, Output
from langflow.schema.data import Data

class JSONToDataComponent(Component):
    display_name = "Load JSON"
    description = "Convert JSON to Data object"
    icon = "braces"
    name = "JSONtoData"

    inputs = [
        FileInput(name="json_file", display_name="JSON File", file_types=["json"]),
        MessageTextInput(name="json_path", display_name="JSON File Path"),
        MultilineInput(name="json_string", display_name="JSON String"),
    ]

    outputs = [
        Output(name="data", display_name="Data", method="convert_json_to_data"),
    ]

    def convert_json_to_data(self) -> Data | list[Data]:
        # 确保只有一个输入
        if sum(bool(field) for field in [self.json_file, self.json_path, self.json_string]) != 1:
            raise ValueError("Please provide exactly one input")

        # 加载数据
        if self.json_file:
            json_data = Path(self.resolve_path(self.json_file)).read_text(encoding="utf-8")
        elif self.json_path:
            json_data = Path(self.json_path).read_text(encoding="utf-8")
        else:
            json_data = self.json_string

        # 解析 JSON(带自动修复)
        try:
            parsed_data = json.loads(json_data)
        except json.JSONDecodeError:
            repaired_json_string = repair_json(json_data)
            parsed_data = json.loads(repaired_json_string)

        # 转换为 Data 对象
        if isinstance(parsed_data, list):
            return [Data(data=item) for item in parsed_data]
        return Data(data=parsed_data)

4.3 动态表单组件

这个案例展示如何根据选择动态显示不同输入:

from langflow.custom.custom_component.component import Component
from langflow.io import (
    DataFrameInput, DropdownInput, StrInput, Output
)
from langflow.schema.dataframe import DataFrame

class DynamicComponent(Component):
    display_name = "动态表单"
    name = "DynamicComponent"

    inputs = [
        DropdownInput(
            name="mode",
            display_name="模式",
            options=["简单", "高级"]
        ),
        StrInput(
            name="simple_param",
            display_name="简单参数",
            dynamic=True
        ),
        StrInput(
            name="advanced_param",
            display_name="高级参数",
            dynamic=True,
            show=False  # 初始隐藏
        ),
    ]

    outputs = [
        Output(name="output", display_name="输出", method="process"),
    ]

    def update_build_config(self, build_config, field_value, field_name=None):
        """根据选择动态更新配置"""
        if field_name == "mode":
            if field_value == "高级":
                build_config["simple_param"]["show"] = False
                build_config["advanced_param"]["show"] = True
            else:
                build_config["simple_param"]["show"] = True
                build_config["advanced_param"]["show"] = False
        return build_config

    def process(self) -> str:
        if self.mode == "高级":
            return f"高级模式: {self.advanced_param}"
        return f"简单模式: {self.simple_param}"

五、高级技巧

5.1 列表输入

所有输入类型都支持列表模式:

StrInput(
    name="tags",
    display_name="标签",
    is_list=True,
    value=["tag1", "tag2"]
)

5.2 状态管理

使用 self.status 反馈执行状态:

def process(self):
    try:
        result = self.do_something()
        self.status = "处理成功"
        return result
    except Exception as e:
        self.status = f"处理失败: {str(e)}"
        raise

5.3 输入验证

自定义验证逻辑:

from pydantic import field_validator

class ValidatedInput(StrInput):
    @field_validator("value")
    @classmethod
    def validate_value(cls, v: Any, info):
        if v and len(v) < 3:
            raise ValueError("输入至少需要 3 个字符")
        return v

5.4 组件继承模板

from langflow.custom.custom_component.component import Component
from langflow.io import Output, MessageTextInput
from langflow.schema.message import Message

class MyComponent(Component):
    """组件开发模板"""

    # 组件元数据
    display_name = "组件显示名称"
    description = "组件功能描述"
    icon = "icon-name"  # lucide-react 图标名
    name = "MyComponent"

    # 输入定义
    inputs = [
        MessageTextInput(
            name="input_name",
            display_name="输入显示名",
            value="默认值",
            required=True,
            info="帮助提示文本"
        ),
    ]

    # 输出定义
    outputs = [
        Output(
            name="output_name",
            display_name="输出显示名",
            method="method_name"
        ),
    ]

    def method_name(self) -> ReturnType:
        """处理逻辑"""
        # 访问输入: self.input_name
        # 设置状态: self.status = "状态消息"
        return result

六、总结

Langflow 的输入输出系统设计得相当灵活,核心要点:

  1. Mixin 模式:通过组合不同 Mixin 实现功能复用
  2. 类型安全:基于 Pydantic 的强类型验证
  3. 自动转换:输入输出支持多种格式的自动转换
  4. 动态配置:支持根据用户选择动态显示/隐藏字段
  5. 状态反馈:通过 self.status 提供执行状态反馈

快速参考

需求使用类型
文本输入StrInput, MessageTextInput
长文本MultilineInput
密码SecretStrInput
数字IntInput, FloatInput
开关BoolInput
选择DropdownInput, MultiselectInput
文件FileInput
数据连接DataInput, DataFrameInput
表格数据TableInput
输出Output

开发建议

  1. 始终提供清晰的 display_nameinfo
  2. 使用 required 标记必填项
  3. 合理使用 advanced 隐藏复杂参数
  4. 使用 self.status 反馈处理状态
  5. 添加适当的错误处理
  6. 使用类型提示提高代码可读性

相关资源