UI控件 (UI Schema)
本章节系统介绍 GdiSDK 中用于描述模块参数 UI 交互的 UI Schema / AttributeSchema 体系,
以及它与 GDIM 平台之间的关系。对应代码主要位于
gdisdk.pipeline.pipeData 和 gdisdk.pipeline.pipeline 中的若干 Pydantic 模型,
例如 gdisdk.pipeline.pipeData.UIAttributeSchema 及其子类。
总体来看:
ui schema 的直接作用:让 Pipeline / 模块的「Python 参数」映射成一组结构化的 UI 控件;
ui schema 与 GDIM 的关系:GDIM 在加载
.pipe文件时,会读取这些 ui schema,自动生成参数表单, 让最终用户可以在 Web 端安全地配置模块参数,而无需理解底层代码;额外能力:在上传 Pipeline 后,GDIM 还支持通过可视化拖拽控件的方式设计参数区和结果区的布局, ui schema 提供「字段和控件的语义」,GDIM 则负责「编排和排版」。
什么是 UI Schema?
在 gdisdk.pipeline.pipeline.PipeModule 中,可以选择性地重写
update_ui_schema,
返回一个以「参数名」为键、以 UIAttributeSchema 派生类为值的字典,用来描述
「这个参数应该如何在 UI 中展示和编辑」:
from gdisdk.pipeline.pipeData import UIAttributeSchema, FloatAttributeSchema
def update_ui_schema(self, reset: bool = False) -> dict[str, UIAttributeSchema]:
return {
"threshold": FloatAttributeSchema(
title="阈值",
default=self.threshold,
minimum=None,
maximum=None,
),
}
当 Pipeline 被保存为 .pipe 并上传到 GDIM 后:
GDIM 会读取通过
PipeLine.add_attribute注册到 Pipeline 属性中的 ui schema,基于这些属性生成参数控件(输入框、下拉、多选、文件选择等); 模块内部的update_ui_schema只是提供了一份「默认定义」,真正生效的是 Pipeline 属性上的 ui schema,且可以在add_attribute(..., ui_schema_overrides=...)中被重写;应用配置者还可以在 GDIM 管理端使用可视化拖拽方式,调整这些控件和结果展示组件的布局, 例如把某些参数放在同一分组、将主结果图表放在首屏等。
因此可以理解为: ui schema 是为了让 Pipeline 能够在 GDIM / 其他前端上「可视化运行」而生的, 它把模块的内部参数暴露为结构化表单字段,方便非开发者安全地修改参数。
常用 UIAttributeSchema 类型概览
除 CustomAttributeSchema 外,其他具体控件类型均继承自
gdisdk.pipeline.pipeData.BaseAttributeSchema。
该基类中包含了一组通用字段,例如:
title:在 UI 中显示的标题;default:默认值;required:是否必填;visible/readonly:是否在 UI 中可见、是否只读;units:物理量单位(通常来自gdisdk.dataclass.terminologies中的Units);selections/selections_name:枚举 / 下拉值列表及其显示名;depends_on:依赖的模块参数或端口名(如"InputToken"),用于动态更新选项;widget:建议使用的前端控件类型(如"select"、"textarea"等);widget_attributes:补充的控件配置(例如「下拉启用搜索」「多选」等)。
在此基础上,常见的子类包括(均定义在 gdisdk.pipeline.pipeData 中):
StringAttributeSchema文本输入;可通过selections/selections_name配置为下拉框 / 单选框等。IntegerAttributeSchema/FloatAttributeSchema整数 / 浮点数输入;支持minimum/maximum/exclude_minimum/exclude_maximum等数值约束。BooleanAttributeSchema布尔开关,一般在 UI 中表现为滑动开关。ArrayAttributeSchema列表 / 多选类控件,常见场景包括「多选表名」「多选列名」等; 通过items指定单个元素的 Schema(通常是StringAttributeSchema), 并可使用min_items/max_items控制长度。ObjectAttributeSchema复杂嵌套对象;通过properties定义子字段,用于「结构化配置」场景,例如多字段组合参数。FileAttributeSchema文件或 GDIM 文件对象配置;通常对应「文件选择 / 上传 / 下载」类控件, 常见于需要用户选择报告模板、上传 Excel、下载生成文件等场景。CustomAttributeSchema``(``vtype="general") 自定义 UI,不由 GDIM 自动生成控件。用于地图选点、专用编辑器等需要前后端单独约定的场景。 仅可作为顶层 Pipeline 属性使用,不能嵌套在object/array/table中。 通过title、description、``default``(示例值)等字段与前端开发者对齐数据结构; 实际取值校验由模块代码负责。
与 PipeLine 属性及 GDIM UI 的协同
在模块内部定义好 update_ui_schema 之后,通常会通过
PipeLine.add_attribute
把关键参数提升为 Pipeline 属性,供 GDIM 或其他前端统一配置,例如:
pipeline.add_attribute(
attr_name="tpl_number",
module_name="QueryTable",
param_name="tpl_number",
attr_title="沉降点编号",
)
这里:
模块
QueryTable的update_ui_schema定义了tpl_number字段的 ui schema (值类型、下拉选项、是否多选等);add_attribute则把它映射为 Pipeline 层的一个属性tpl_number, 让 GDIM 可以在「应用配置界面」中展示为一个可编辑控件;运行时,GDIM 会把用户在表单里填写的值写回 Pipeline,再由 Pipeline 写回对应模块参数。
add_attribute 还支持 ui_schema_overrides 参数,可以在 不改动模块源码 的前提下,
对字段的 ui schema 做二次定制,例如:
from gdisdk.llm.promptTemplates import SystemDomainPrompt
pipeline.add_attribute(
attr_name="system_prompt",
module_name="TableAnalyzer",
param_name="system_prompt",
attr_title="智能助手角色",
ui_schema_overrides={
"default": SystemDomainPrompt.GEOLOGICAL.value,
"selections": [
SystemDomainPrompt.GEOLOGICAL.value,
SystemDomainPrompt.GEOTECHNICAL_ENGINEERING.value,
SystemDomainPrompt.HYDROGEOLOGY.value,
SystemDomainPrompt.GROUNDWATER_CONTAMINATION.value,
],
"selections_name": [
"地质专家",
"岩土工程专家",
"水文地质专家",
"地下水污染专家",
],
},
)
当需要 完全自定义 某个 Pipeline 属性的 UI schema 时(而不是在模块已有
schema 上做字段级微调),应使用 add_attribute(..., ui_schema_function_name=...)。
此时模块预设的 ui schema 与 ui_schema_overrides 都会被忽略,由本地函数直接返回
一个完整的 UIAttributeSchema。
典型场景包括:
需要换成另一种控件类型 /
vtype``(例如模块内置是 ``StringAttributeSchema, 当前应用要用FloatAttributeSchema)。ui_schema_overrides无法 修改vtype,因为它只会在 原有 schema 类型 上更新字段,不会换成另一类 schema;选项、默认值等依赖上游模块输出或其他 Pipeline 上下文,需要运行时动态生成;
模块本身没有可用的
ui_schema,必须自行提供完整定义。
注意:写在 add_attribute 上的本地函数约定,与 PythonCoder 模块上的
ui_schema_function_name 不同,请勿混用。
方式一:写在 add_attribute 上(Pipeline 级,按属性)
适用于非 PythonCoder 模块,或需要在 Pipeline 层 整体替换 某参数 UI schema 的场景。
函数由
PipeLine.add_attribute/get_attribute_info调用;第一个参数是
pipeline``(``PipeLine实例),不是模块;返回值是单个
UIAttributeSchema``(不是 ``dict);文件方式下函数须用
@local_function装饰,并通过pipeline.local_functions_path加载;也可直接传入 inline callable。
from gdisdk.pipeline.nameSpace import local_function
from gdisdk.pipeline.pipeData import StringAttributeSchema
@local_function
def dynamic_soil_schema(pipeline, **kwargs) -> StringAttributeSchema:
"""按上游模块输出动态生成下拉选项。"""
data_module = pipeline.get_module("DataReader")
# 输出端口:使用 module["OutputXxx"] 公开写法
soil_types = data_module["OutputSoilTypes"] if data_module else []
return StringAttributeSchema(
title="土层类型",
selections=soil_types or [],
# 依赖输入端口时,GDIM 会在上游数据就绪后刷新该属性的 schema
depends_on=["InputSoilData"],
)
pipeline.add_attribute(
attr_name="soil_type",
module_name="SoilModule",
param_name="type",
attr_title="土层类型",
ui_schema_function_name="dynamic_soil_schema",
)
需要读取目标模块的 输入端口 数据时,请使用 module._ports_in["InputXxx"].data
(module.InputXxx.data / module["InputXxx"] 走的是输出端口 API,对输入端口不适用)。
例如从 LineChart 的 InputData 生成 y_columns 选项:
@local_function
def factor_ui_schema(pipeline, **kwargs) -> StringAttributeSchema:
line_chart = pipeline.get_module("LineChart")
table = None
if line_chart is not None:
in_port = line_chart._ports_in.get("InputData")
table = in_port.data if in_port is not None else None
factor_names: list[str] = []
factor_titles: list[str] = []
if table is not None:
factor_names = [
col
for col in table.columns
if table.get_field_metadata(col).data_format == "pollutantConcentration"
]
factor_titles = [
table.get_field_metadata(col).title for col in factor_names
]
schema = StringAttributeSchema(
title="检测因子名称",
default="硫酸盐",
selections=factor_names,
selections_name=factor_titles,
depends_on=["InputData"],
)
schema.widget = "select"
return schema
方式二:写在 PythonCoder 模块上(模块级,一次覆盖全部自定义属性)
适用于 PythonCoder.add_attributes(...) 声明的自定义参数:把
coder.ui_schema_function_name = "my_ui_schema" 设在模块上,再对每个参数调用
pipeline.add_attribute(...) 时 不要 再传 ui_schema_function_name。
函数由模块的
update_ui_schema调用;第一个参数是 ``module``(该 PythonCoder 实例);
返回值是
dict[str, UIAttributeSchema],键为全部自定义属性名;建议签名:
def my_ui_schema(module, reset: bool = False, **kwargs): ...。
from gdisdk.pipeline.nameSpace import local_function
from gdisdk.pipeline.pipeData import FloatAttributeSchema, IntegerAttributeSchema
@local_function
def terrain_ui_schema(module, reset: bool = False, **kwargs):
return {
"vertical_exaggeration": FloatAttributeSchema(
title="竖向放大系数",
default=getattr(module, "vertical_exaggeration", 1.0),
minimum=0.1,
maximum=10.0,
),
"contour_count": IntegerAttributeSchema(
title="等值线数量",
default=getattr(module, "contour_count", 12),
minimum=1,
maximum=100,
),
}
coder.ui_schema_function_name = "terrain_ui_schema"
pipeline.add_attribute(
attr_name="vertical_exaggeration",
module_name="TerrainBuilder",
param_name="vertical_exaggeration",
attr_title="竖向放大系数",
)
两种方式的对比:
场景 |
设置位置 |
函数约定 |
|---|---|---|
完全自定义 schema(含更换 |
|
|
PythonCoder 自定义属性的静态/模块内 UI |
模块 |
|
仅在 同一 schema 类型上改默认值、选项、可见性等 |
|
无需本地函数(不能改 |
Note
上传 GDIM 时,ui_schema_function_name 应优先使用 **字符串函数名**(配合
pipeline.local_functions_path),避免 inline callable 无法随 .pipe 序列化。
PythonCoder 侧更完整的说明见 modules.widgets 模块帮助。
这套机制的配合效果是:
模块作者 只需在
update_ui_schema中声明字段类型和基本 UI 行为;Pipeline 作者 / 应用配置者 可以在不改源码的情况下,针对具体应用场景调整默认值、选项、可见性等, 或通过
ui_schema_function_name按上游数据动态生成控件;GDIM 平台 则基于这些结构化信息,把参数和结果以表单 + 组件的形式「编排」成应用界面, 包括通过拖拽来调整布局、分组、标签页等。
若属性配置了 auto_bind,前端不再按该属性的 ui_schema 渲染控件,
ui_schema_overrides / ui_schema_function_name 会被忽略;attr_schema 仍会随
get_attribute_info() 返回。两种取值:
auto_bind="poi_field":GDIM 地图类应用 兴趣点弹窗二次开发。前端隐藏控件, 从当前兴趣点数据行按 ``bind_field``(字段名或标题;缺省为 POI 标签)取值并写入该属性。auto_bind="pk_field":数字模型 「自定义数据更新」 中的子表按主表主键更新。 子表场景下前端用自有的「更新范围」下拉框注入主键; 运行时值始终是list[主键数据类型]``(例如 ``["ZK1"]或[]),不会是标量。 不要设置bind_field。主表上该机制会被忽略,属性按普通控件渲染。
详见 用户指南 (User Guide) 中「自动绑定属性(auto_bind)」一节。
更多示例与推荐阅读
用户指南 (User Guide) 中的「如何定义Pipeline的UI交互」「如何定义模块的UI交互」两节, 展示了 ui schema 与 Pipeline 属性、GDIM 前端之间的完整闭环流程;
modules.widgets 模块帮助 中
PythonCoder的 UI Schema 本地函数与reset参数说明;gdisdk.modules.readers中的GdimTableReader、gdisdk.modules.widgets中的PythonCoder等模块,包含了更多动态控件、复杂对象配置的实际写法;gdisdk.pipeline.pipeline中PipeLine.add_attribute方法。