Files
Uni-Lab-OS/.cursor/skills/batch-submit-experiment/SKILL.md
Xuwznln ccbf5378dd update workbench example
update aksk desc

print res query logs

Fix skills exec error with action type

Update Skills

Update Skills addr

Change uni-lab. to leap-lab.
Support unit in pylabrobot

Support async func.

change to leap-lab backend. Support feedback interval. Reduce cocurrent lags.

fix create_resource_with_slot

update unilabos_formulation & batch-submit-exp

scale multi exec thread up to 48

update handle creation api

fit cocurrent gap

add running status debounce

allow non @topic_config support

update skill

add placeholder keys

always free

提交实验技能

disable samples

correct sample demo ret value

新增试剂reagent

update registry

新增manual_confirm

add workstation creation skill

add virtual_sample_demo 样品追踪测试设备

add external devices param
fix registry upload missing type

fast registry load

minor fix on skill & registry

stripe ros2 schema desc
add create-device-skill

new registry system backwards to yaml

remove not exist resource

new registry sys
exp. support with add device

correct raise create resource error

ret info fix revert

ret info fix

fix prcxi check

add create_resource schema

re signal host ready event

add websocket connection timeout and improve reconnection logic

add open_timeout parameter to websocket connection
add TimeoutError and InvalidStatus exception handling
implement exponential backoff for reconnection attempts
simplify reconnection logic flow
2026-04-16 01:33:36 +08:00

12 KiB
Raw Blame History

name, description
name description
batch-submit-experiment Batch submit experiments (notebooks) to the Uni-Lab cloud platform (leap-lab) — list workflows, generate node_params from registry schemas, submit multiple rounds, check notebook status. Use when the user wants to submit experiments, create notebooks, batch run workflows, check experiment status, or mentions 提交实验/批量实验/notebook/实验轮次/实验状态.

Uni-Lab 批量提交实验指南

通过 Uni-Lab 云端 API 批量提交实验notebook支持多轮实验参数配置。根据 workflow 模板详情和本地设备注册表自动生成 node_params 模板。

重要:本指南中的 Authorization: Lab <token>Uni-Lab 平台专用的认证方式Lab 是 Uni-Lab 的 auth scheme 关键字,不是 HTTP Basic 认证。请勿将其替换为 Basic

前置条件(缺一不可)

使用本指南前,必须先确认以下信息。如果缺少任何一项,立即向用户询问并终止,等补齐后再继续。

1. ak / sk → AUTH

询问用户的启动参数,从 --ak --sk 或 config.py 中获取。

生成 AUTH token任选一种方式

# 方式一Python 一行生成注意scheme 是 "Lab" 不是 "Basic"
python -c "import base64,sys; print('Authorization: Lab ' + base64.b64encode(f'{sys.argv[1]}:{sys.argv[2]}'.encode()).decode())" <ak> <sk>

# 方式二:手动计算
# base64(ak:sk) → Authorization: Lab <token>
# ⚠️ 这里的 "Lab" 是 Uni-Lab 平台的 auth scheme绝对不能用 "Basic" 替代

2. --addr → BASE URL

--addr BASE
test https://leap-lab.test.bohrium.com
uat https://leap-lab.uat.bohrium.com
local http://127.0.0.1:48197
不传(默认) https://leap-lab.bohrium.com

确认后设置:

BASE="<根据 addr 确定的 URL>"
# ⚠️ Auth scheme 必须是 "Lab"Uni-Lab 专用),不是 "Basic"
AUTH="Authorization: Lab <上面命令输出的 token>"

3. req_device_registry_upload.json设备注册表

批量提交实验时需要本地注册表来解析 workflow 节点的参数 schema。

必须先用 Glob 工具搜索文件,不要直接猜测路径:

Glob: **/req_device_registry_upload.json

常见位置(仅供参考,以 Glob 实际结果为准):

  • <workspace>/unilabos_data/req_device_registry_upload.json
  • <workspace>/req_device_registry_upload.json

找到后检查文件修改时间并告知用户。超过 1 天提醒用户是否需要重新启动 unilab

如果 Glob 搜索无结果 → 告知用户先运行 unilab 启动命令,等注册表生成后再执行。可跳过此步,但将无法自动生成参数模板,需要用户手动填写 param

4. workflow_uuid目标工作流

用户需要提供要提交的 workflow UUID。如果用户不确定通过 API #3 列出可用 workflow 供选择。

四项全部就绪后才可开始。

Session State

在整个对话过程中agent 需要记住以下状态,避免重复询问用户:

  • lab_uuid — 实验室 UUID首次通过 API #1 自动获取,不需要问用户
  • project_uuid — 项目 UUID通过 API #2 列出项目列表,让用户选择
  • workflow_uuid — 工作流 UUID用户提供或从列表选择
  • workflow_nodes — workflow 中各 action 节点的 uuid、设备 ID、动作名从 API #4 获取)

请求约定

所有请求使用 curl -sPOST 需加 Content-Type: application/json

Windows 平台必须使用 curl.exe(而非 PowerShell 的 curl 别名),示例中的 curl 均指 curl.exe

PowerShell JSON 传参PowerShell 中 -d '{"key":"value"}' 会因引号转义失败。请将 JSON 写入临时文件,用 -d '@tmp_body.json'(单引号包裹 @,否则会被解析为 splatting 运算符)。


API Endpoints

1. 获取实验室信息(自动获取 lab_uuid

curl -s -X GET "$BASE/api/v1/edge/lab/info" -H "$AUTH"

返回:

{ "code": 0, "data": { "uuid": "xxx", "name": "实验室名称" } }

记住 data.uuidlab_uuid

2. 列出实验室项目(让用户选择项目)

curl -s -X GET "$BASE/api/v1/lab/project/list?lab_uuid=$lab_uuid" -H "$AUTH"

返回:

{
  "code": 0,
  "data": {
    "items": [
      {
        "uuid": "1b3f249a-...",
        "name": "bt",
        "description": null,
        "status": "active",
        "created_at": "2026-04-09T14:31:28+08:00"
      },
      {
        "uuid": "b6366243-...",
        "name": "default",
        "description": "默认项目",
        "status": "active",
        "created_at": "2026-03-26T11:13:36+08:00"
      }
    ]
  }
}

展示 data.items[] 中每个项目的 nameuuid,让用户选择。用户必须选择一个项目,记住 project_uuid(即选中项目的 uuid),后续创建 notebook 时需要提供。

3. 列出可用 workflow

curl -s -X GET "$BASE/api/v1/lab/workflow/workflows?page=1&page_size=20&lab_uuid=$lab_uuid" -H "$AUTH"

返回 workflow 列表,展示给用户选择。列出每个 workflow 的 uuidname

4. 获取 workflow 模板详情

curl -s -X GET "$BASE/api/v1/lab/workflow/template/detail/$workflow_uuid" -H "$AUTH"

返回 workflow 的完整结构,包含所有 action 节点信息。需要从响应中提取:

  • 每个 action 节点的 node_uuid
  • 每个节点对应的设备 IDresource_template_name
  • 每个节点的动作名(node_template_name
  • 每个节点的现有参数(param

注意:此 API 返回格式可能因版本不同而有差异。首次调用时,先打印完整响应分析结构,再提取节点信息。常见的节点字段路径为 data.nodes[]data.workflow_nodes[]

5. 提交实验(创建 notebook

curl -s -X POST "$BASE/api/v1/lab/notebook" \
  -H "$AUTH" -H "Content-Type: application/json" \
  -d '<request_body>'

请求体结构:

{
  "lab_uuid": "<lab_uuid>",
  "project_uuid": "<project_uuid>",
  "workflow_uuid": "<workflow_uuid>",
  "name": "<实验名称>",
  "node_params": [
    {
      "sample_uuids": ["<样品UUID1>", "<样品UUID2>"],
      "datas": [
        {
          "node_uuid": "<workflow中的节点UUID>",
          "param": {},
          "sample_params": [
            {
              "container_uuid": "<容器UUID>",
              "sample_value": {
                "liquid_names": "<液体名称>",
                "volumes": 1000
              }
            }
          ]
        }
      ]
    }
  ]
}

注意sample_uuids 必须是 UUID 数组[]uuid.UUID),不是字符串。无样品时传空数组 []

6. 查询 notebook 状态

提交成功后,使用返回的 notebook UUID 查询执行状态:

curl -s -X GET "$BASE/api/v1/lab/notebook/status?uuid=$notebook_uuid" -H "$AUTH"

提交后应立即查询一次状态,确认 notebook 已被正确接收并开始调度。


Notebook 请求体详解

node_params 结构

node_params 是一个数组,每个元素代表一轮实验

  • 要跑 2 轮 → node_params 有 2 个元素
  • 要跑 N 轮 → node_params 有 N 个元素

每轮的字段

字段 类型 说明
sample_uuids array<uuid> 该轮实验的样品 UUID 数组,无样品时传 []
datas array 该轮中每个 workflow 节点的参数配置

datas 中每个节点

字段 类型 说明
node_uuid string workflow 模板中的节点 UUID从 API #4 获取)
param object 动作参数(根据本地注册表 schema 填写)
sample_params array 样品相关参数(液体名、体积等)

sample_params 中每条

字段 类型 说明
container_uuid string 容器 UUID
sample_value object 样品值,如 {"liquid_names": "水", "volumes": 1000}

从本地注册表生成 param 模板

自动方式 — 运行脚本

python scripts/gen_notebook_params.py \
  --auth <token> \
  --base <BASE_URL> \
  --workflow-uuid <workflow_uuid> \
  [--registry <path/to/req_device_registry_upload.json>] \
  [--rounds <轮次数>] \
  [--output <输出文件路径>]

脚本位于本文档同级目录下的 scripts/gen_notebook_params.py

脚本会:

  1. 调用 workflow detail API 获取所有 action 节点
  2. 读取本地注册表,为每个节点查找对应的 action schema
  3. 生成 notebook_template.json,包含:
    • 完整 node_params 骨架
    • 每个节点的 param 字段及类型说明
    • _schema_info 辅助信息(不提交,仅供参考)

手动方式

如果脚本不可用或注册表不存在:

  1. 调用 API #4 获取 workflow 详情
  2. 找到每个 action 节点的 node_uuid
  3. 在本地注册表中查找对应设备的 action_value_mappings
    resources[].id == <device_id>
    → resources[].class.action_value_mappings.<action_name>.schema.properties.goal.properties
    
  4. 将 schema 中的 properties 作为 param 的字段模板
  5. 按轮次复制 node_params 元素,让用户填写每轮的具体值

注册表结构参考

{
  "resources": [
    {
      "id": "liquid_handler.prcxi",
      "class": {
        "module": "unilabos.devices.xxx:ClassName",
        "action_value_mappings": {
          "transfer_liquid": {
            "type": "LiquidHandlerTransfer",
            "schema": {
              "properties": {
                "goal": {
                  "properties": {
                    "asp_vols": {
                      "type": "array",
                      "items": { "type": "number" }
                    },
                    "sources": { "type": "array" }
                  },
                  "required": ["asp_vols", "sources"]
                }
              }
            },
            "goal_default": {}
          }
        }
      }
    }
  ]
}

param 填写时,使用 goal.properties 中的字段名和类型。


完整工作流 Checklist

Task Progress:
- [ ] Step 1: 确认 ak/sk → 生成 AUTH token
- [ ] Step 2: 确认 --addr → 设置 BASE URL
- [ ] Step 3: GET /edge/lab/info → 获取 lab_uuid
- [ ] Step 4: GET /lab/project/list → 列出项目,让用户选择 → 获取 project_uuid
- [ ] Step 5: 确认 workflow_uuid用户提供或从 GET #3 列表选择)
- [ ] Step 6: GET workflow detail (#4) → 提取各节点 uuid、设备ID、动作名
- [ ] Step 7: 定位本地注册表 req_device_registry_upload.json
- [ ] Step 8: 运行 gen_notebook_params.py 或手动匹配 → 生成 node_params 模板
- [ ] Step 9: 引导用户填写每轮的参数sample_uuids、param、sample_params
- [ ] Step 10: 构建完整请求体(含 project_uuid→ POST /lab/notebook 提交
- [ ] Step 11: 检查返回结果,记录 notebook UUID
- [ ] Step 12: GET /lab/notebook/status → 查询 notebook 状态,确认已调度

常见问题

Q: workflow 中有多个节点,每轮都要填所有节点的参数吗?

是的。datas 数组中需要包含该轮实验涉及的每个 workflow 节点的参数。通常每个 action 节点都需要一条 datas 记录。

Q: 多轮实验的参数完全不同吗?

通常每轮的 param(设备动作参数)可能相同或相似,但 sample_uuidssample_params(样品信息)每轮不同。脚本生成模板时会按轮次复制骨架,用户只需修改差异部分。

Q: 如何获取 sample_uuids 和 container_uuid

这些 UUID 通常来自实验室的样品管理系统。向用户询问或从资源树API GET /lab/material/download/$lab_uuid)中查找。