name: fiftyone-develop-plugin description: 从零开始开发自定义FiftyOne插件(操作符和面板)。当用户想要创建新插件、用自定义操作符扩展FiftyOne、构建交互式面板或将外部API集成到FiftyOne时使用。指导需求、设计、编码、测试和迭代的全过程。
开发FiftyOne插件
概述
创建自定义FiftyOne插件,提供全生命周期支持:需求收集、代码生成、本地测试和迭代优化。
在以下情况使用此技能:
- 用户要求创建/构建/开发FiftyOne插件
- 用户想要向FiftyOne应用添加自定义功能
- 用户需要集成外部API或服务
前提条件
- 已安装FiftyOne(
pip install fiftyone) - Python 3.8+(用于Python插件)
- Node.js 16+(仅用于JavaScript面板)
关键指令
始终遵循以下规则:
1. 先理解后编码
询问澄清问题。切勿假设插件应该做什么。
2. 先规划后实施
展示文件结构和设计。在生成代码前获得用户批准。
3. 搜索现有插件以获取模式
list_plugins(enabled=True)
list_operators(builtin_only=False)
get_operator_schema(operator_uri="@voxel51/brain/compute_similarity")
4. 完成前在本地测试
安装插件并在FiftyOne应用中验证其工作。
5. 根据反馈迭代
优化直到插件按预期工作。
工作流程
阶段1:需求
询问以下问题:
- “您的插件应该做什么?”(一句话描述)
- “操作符(动作)还是面板(交互式UI)?”
- “需要用户提供什么输入?”
- “输出/结果是什么?”
- “需要外部API或密钥吗?”
- “长时间任务需要后台执行吗?”
阶段2:设计
- 搜索现有插件以获取类似模式
- 创建包含以下内容的计划:
- 插件名称(
@组织/插件名称) - 文件结构
- 操作符/面板规范
- 输入/输出定义
- 插件名称(
- 在编码前获得用户批准
有关文件格式,请参阅PLUGIN-STRUCTURE.md。
阶段3:生成代码
创建以下文件:
| 文件 | 必需 | 用途 |
|---|---|---|
fiftyone.yml |
是 | 插件清单 |
__init__.py |
是 | Python操作符/面板 |
requirements.txt |
如有依赖 | Python依赖项 |
package.json |
仅JS | Node.js元数据 |
src/index.tsx |
仅JS | React组件 |
参考文档:
阶段4:安装与测试
# 查找插件目录
python -c "import fiftyone as fo; print(fo.config.plugins_dir)"
# 复制插件
cp -r ./my-plugin ~/.fiftyone/plugins/
# 验证检测
python -c "import fiftyone as fo; print(fo.plugins.list_plugins())"
在应用中测试:
launch_app(dataset_name="test-dataset")
# 按Cmd/Ctrl + `打开操作符浏览器
# 搜索您的操作符
阶段5:迭代
- 获取用户反馈
- 修复问题
- 重新复制到插件目录
- 如果需要则重启应用
- 重复直到正常工作
快速参考
插件类型
| 类型 | 语言 | 使用场景 |
|---|---|---|
| 操作符 | Python | 数据处理、计算 |
| 面板 | Python | 简单交互式UI |
| 面板 | JavaScript | 丰富的基于React的UI |
操作符配置选项
| 选项 | 效果 |
|---|---|
dynamic=True |
更改时重新计算输入 |
execute_as_generator=True |
流式进度 |
allow_delegated_execution=True |
后台执行 |
unlisted=True |
从浏览器隐藏 |
输入类型
| 类型 | 方法 |
|---|---|
| 文本 | inputs.str() |
| 数字 | inputs.int() / inputs.float() |
| 布尔值 | inputs.bool() |
| 下拉菜单 | inputs.enum() |
| 文件 | inputs.file() |
| 视图 | inputs.view_target() |
最小示例
fiftyone.yml:
name: "@myorg/hello-world"
type: plugin
operators:
- hello_world
init.py:
import fiftyone.operators as foo
import fiftyone.operators.types as types
class HelloWorld(foo.Operator):
@property
def config(self):
return foo.OperatorConfig(
name="hello_world",
label="Hello World"
)
def resolve_input(self, ctx):
inputs = types.Object()
inputs.str("message", label="消息", default="你好!")
return types.Property(inputs)
def execute(self, ctx):
print(ctx.params["message"])
return {"status": "完成"}
def register(p):
p.register(HelloWorld)
故障排除
插件未出现:
- 检查插件根目录中是否存在
fiftyone.yml - 验证位置:
~/.fiftyone/plugins/ - 检查Python语法错误
- 重启FiftyOne应用
找不到操作符:
- 验证操作符是否在
fiftyone.yml中列出 - 检查
register()函数 - 运行
list_operators()进行调试
密钥不可用:
- 在
fiftyone.yml的secrets:下添加 - 在启动FiftyOne前设置环境变量
资源
许可证
版权所有 2017-2025, Voxel51, Inc. Apache 2.0许可证