跳到主要内容

管线插件系统

管线插件系统是 RadStudio 的扩展机制,允许你将自定义节点(数据处理、特征提取、模型、评估等)注册到工作流编辑器中。插件可以是 Python 代码、第三方工具包装,也可以是 AI 引擎的自定义扩展。

插件能做什么?

通过插件,你可以扩展 RadStudio 的以下能力:

扩展方向示例
新的数据源读取专有影像格式、连接 PACS 系统
自定义预处理私有图像增强算法、特定模态的标准化
新模型接入接入你自己的 PyTorch 模型
自定义评估指标领域特定的评估方法
输出格式扩展导出到特定软件格式

插件架构

RadStudio 工作流编辑器
|
v
管线引擎 (apps/backend/app/plugins.py)
|
+-- 内置插件(标准节点)
| +-- DICOM 导入
| +-- PyRadiomics 特征提取
| +-- MONAI 模型
| +-- 评估节点
|
+-- 用户插件(自定义节点)
+-- 由用户注册
+-- 运行时动态加载

快速开始:创建你的第一个插件

1. 定义节点

在项目中创建一个 Python 文件,例如 my_plugin.py,定义节点类:

from radstudio.plugins import PipelineNode, NodeInput, NodeOutput
from radstudio.types import ImageData, LabelData

class MyNormalizationNode(PipelineNode):
"""自定义图像标准化节点"""

name = "my_normalization"
display_name = "自定义标准化"
category = "preprocess"

inputs = [
NodeInput(name="image", type=ImageData, required=True),
]
outputs = [
NodeOutput(name="normalized_image", type=ImageData),
]

params = {
"method": {"type": "choice", "choices": ["zscore", "minmax", "custom"], "default": "zscore"},
"clip_range": {"type": "float_range", "min": -5.0, "max": 5.0, "default": (-3.0, 3.0)},
}

async def execute(self, inputs, params):
image = inputs["image"]
method = params["method"]

if method == "zscore":
mean = image.mean()
std = image.std()
normalized = (image - mean) / (std + 1e-8)
elif method == "minmax":
normalized = (image - image.min()) / (image.max() - image.min() + 1e-8)
else:
normalized = image

clip_min, clip_max = params["clip_range"]
normalized = normalized.clip(clip_min, clip_max)

return {"normalized_image": normalized}

2. 注册插件

from radstudio.plugins import register_plugin

register_plugin(MyNormalizationNode)

注册后,新节点会自动出现在工作流编辑器的「预处理」分类中。

3. 在工作流中使用

  1. 打开工作流编辑器
  2. 在左侧节点面板中找到「预处理」分类
  3. 拖拽「自定义标准化」节点到画布
  4. 连接数据源节点并配置参数
  5. 运行工作流

节点参数类型

插件系统支持丰富的参数类型,自动生成对应的编辑器 UI 控件:

参数类型UI 控件示例定义
int数字输入框{"type": "int", "default": 100, "min": 1}
float数字输入框{"type": "float", "default": 1e-4}
float_range范围滑块{"type": "float_range", "min": 0, "max": 1}
choice下拉菜单{"type": "choice", "choices": ["A", "B", "C"]}
bool开关{"type": "bool", "default": true}
str文本输入框{"type": "str", "default": ""}
file_path文件选择器{"type": "file_path", "extensions": [".nii.gz"]}
dictJSON 编辑器{"type": "dict", "default": {}}

接入外部模型

如果你有预训练的 PyTorch 模型,可以通过插件接入:

import torch
from radstudio.plugins import PipelineNode, NodeInput, NodeOutput

class ExternalModelNode(PipelineNode):
"""接入外部预训练模型"""

name = "external_model"
display_name = "外部模型"
category = "model"

inputs = [
NodeInput(name="image", type=ImageData, required=True),
]
outputs = [
NodeOutput(name="segmentation", type=LabelData),
]

params = {
"model_path": {"type": "file_path", "extensions": [".pt", ".pth"], "required": True},
"device": {"type": "choice", "choices": ["cuda", "cpu"], "default": "cuda"},
}

async def execute(self, inputs, params):
model_path = params["model_path"]
device = params["device"]

model = torch.jit.load(model_path, map_location=device)
model.eval()

image_tensor = torch.from_numpy(inputs["image"]).to(device)

with torch.no_grad():
result = model(image_tensor)

return {"segmentation": result.cpu().numpy()}

插件生命周期管理

操作说明
注册插件在服务启动时自动注册
发现工作流编辑器自动发现已注册的插件
更新修改插件代码后重启服务即可生效
禁用可通过配置禁用特定插件
卸载移除注册代码并重启服务

最佳实践

  • 命名规范 — 使用描述性的 namedisplay_name,避免与内置节点冲突
  • 错误处理 — 在 execute() 中捕获异常并返回有意义的错误信息
  • 参数校验 — 利用参数类型系统进行输入校验,减少运行时错误
  • 性能考虑 — 对于耗时操作,考虑使用异步执行或提交到 Celery Worker
  • 版本管理 — 记录插件的版本号和兼容的 RadStudio 版本

下一步