IB_Robot 统一模型推理架构:策略、感知、TTS 与抓取模型共享的 ModelRuntimeHandle 控制面
IB_Robot 统一模型推理架构:策略、感知、TTS 与抓取模型共享的 ModelRuntimeHandle 控制面
IB_Robot(openEuler Embedded 面向具身智能场景的 AI 机器人执行框架)当前已实现一套统一模型推理架构:策略模型、感知模型、TTS 模型和抓取模型共享同一套运行时控制面,模型差异被隔离在 model-type executor、adapter、ModelSession 与设备 runtime 层。本文以 docs/unify.md 为核心,结合 inference_manifest、inference_service、perception_service、manipulation_service 等模块的源码实现,完整讲解这一架构的设计结论、总体架构、Manifest 身份模型、三大业务 Facade、生命周期与所有权、配置入口以及扩展规则,帮助读者掌握「如何用一个统一控制面承载多模型、多后端、多业务入口」的工程化方案。
设计结论:构造路径与请求路径
统一架构围绕两个关键问题展开:一个模型如何被描述(构造路径)与一个推理请求如何被执行(请求路径)。两者在源码中对应 inference_manifest 包与 inference_service 包中的 unified_runtime 模块。
构造路径(谁负责描述模型、校验部署、组装运行时):
Inference Manifest v3 + named deployment
-> RuntimeContext
-> BackendRegistry validation + SessionBuilderRegistry / RuntimeAssemblerRegistry
-> RuntimeAssembly(runtime_executor + owned components)
-> ModelRuntimeHandle
请求路径(三类业务入口如何收敛到统一执行边界):
Policy: Global Scheduler -> InferencePipeline policy facade -> ModelRuntimeHandle
Plugin: Typed ROS request -> ModelServicePlugin -> ModelRuntimeHandle
Local: grasp request -> LocalPipelineBackend -> ModelRuntimeHandle
ModelRuntimeHandle.execute(ModelRequest, ExecutionContext)
-> RuntimeAssembly-selected runtime_executor
-> SequentialModelExecutor / ModelSession resource
-> ModelSession-owned vendor model resources
-> Device Runtime
核心约束(也是本架构的灵魂)可以归纳为以下几条:
Inference Manifest v3是模型身份、语义契约、部署和编译 ABI 的唯一事实来源(SSOT),任何业务代码都不应绕过 Manifest 直接指定后端或设备;model.interface、model.model_type和model.operation三者共同构成稳定的 dispatch identity——一个模型可以有多个服务契约,但它们的身份三元组必须唯一且稳定;- 业务代码只能选择 Manifest 中存在的 named deployment,不能传入裸 backend 或 fallback;
BackendRegistry同时校验 backend、model_type、target、deployment 和ConformanceEvidence,校验路径是 SDK-free 的;ModelRuntimeHandle统一承担生命周期、准入、并发限制、deadline、cancellation、health 和 diagnostics,而ModelSession只执行模型调用并持有、释放 vendor 模型资源;- Global Scheduler 负责跨 pipeline 的 product session、请求路由、fallback、幂等 ledger、deadline reservation 和公开容量,它不执行模型循环,也不替代 handle 的 runtime 生命周期;
- scheduler 的
SESSION_CONTROL和ACTION_GENERATION是统一的 work class,priority-0 请求保留独立容量,调度 priority 由策略 facade 写入ModelRequestmetadata,并由具体ModelSession映射到设备能力; - product session 的 Open/Close barrier、generation fencing、lease 和 quarantine 由纯 Python
ProductSessionController实现,ROS action 只做协议适配; - 编译 model_type 的迭代循环由共享
IterativeStage驱动,不允许回到 backend 私有循环; - 感知插件、TTS plugin 和本地 GraspGen 路径必须通过
RuntimeAssembly构造ModelRuntimeHandle,并调用handle.execute(ModelRequest, ExecutionContext);不得直接驱动ModelSession或GraspGenSampler。
从源码看,上述职责划分与代码结构严格对应:unified_runtime/handle.py 中的 ModelRuntimeHandle 类注释即 "Lifecycle owner and public execution boundary for unified runtimes"(统一运行时的生命周期所有者与公共执行边界),而 model_sessions/base.py 等 session 实现只负责模型资源本身。
总体架构
进程与节点视图
架构图清晰地划分了六层:ROS 进程与业务入口、全局调度与产品会话、进程内 native runtime、模型执行运行时、感知与抓取运行时、模型部署与配置 SSOT。
ENTRY: ScheduledActionDispatcherNode / GlobalInferenceSchedulerNode /
PipelinePolicyNode × N / ModelServiceNode × N / GraspPlannerNode / PureInferenceNode
SCHEDULING: GlobalSchedulerCore / ProductSessionController / InferenceServingStatus / Open·Dispatch·Close actions
NATIVE_RUNTIME: InferencePipelineManager / InferencePipeline / RuntimeAssembly × N / ModelRuntimeHandle × N
MODEL_RUNTIME: SequentialModelExecutor / ModelStage·IterativeStage / ModelSession / BackendRegistry + registries
PERCEPTION_RUNTIME: ModelServicePlugin / GraspGenWrapper / LocalPipelineBackend
SSOT: robot_config / Inference Manifest v3 / ModelDescriptor / SemanticIdentity / Named Deployment / Device Links
几个关键协作关系必须准确理解:
GlobalInferenceSchedulerNode是唯一的全局调度进程,负责逻辑 product session、pipeline 路由、fallback、幂等 ledger 和 deadline admission。ProductSessionController位于每个启用 scheduled serving 的PipelinePolicyNode内,负责该 pipeline 的本地 session barrier、generation fencing、lease 和容量。- 两者不是父子函数调用关系:Global Scheduler 通过 Open/Dispatch/Close 下游 ROS action 驱动 pipeline,PipelinePolicyNode 通过
InferenceServingStatustopic 回报本地状态;Global Scheduler 根据状态完成绑定、就绪判断和路由。因此图中同时保留两条协议关系,表达"全局逻辑会话"与"pipeline-local 会话"的协作边界。 ModelServiceNode和ModelServicePlugin位于inference_service,是模型无关的 typed ROS service 宿主;感知和 TTS 只在各自 plugin 中实现请求/响应映射与领域适配。ModelRuntimeHandle是共享的模型无关控制边界。- 策略由
InferencePipelinefacade 持有 handle;感知 plugin、TTS plugin 和本地 GraspGen wrapper 各自把ModelSession作为 runtime executor 和 owned component 放入RuntimeAssembly,再将所有权转移给独立 handle。它们的 ROS 协议和业务 facade 保持不同。 - 当前 Global Scheduler 的 candidate 只包含
PipelinePolicyNode的 open/dispatch/close/status endpoints,因此只调度 policy pipeline;感知、TTS 和本地 GraspGen runtime 不进入 Scheduler。 SessionBuilderRegistry、RuntimeAssemblerRegistry和BackendRegistry只参与启动期的 manifest/deployment 校验、session 构造和RuntimeAssembly组装,不是业务请求路径。SequentialModelExecutor、stages 和具体ModelSession是 handle 后方的执行与资源层。
调度与执行的边界
调度的调用链是:
GlobalInferenceSchedulerNode
-> GlobalSchedulerCore
-> candidate PipelinePolicyNode
-> ProductSessionController
-> InferencePipeline facade
-> ModelRuntimeHandle
-> SequentialModelExecutor / ModelSession resource
这条链路的边界规则非常明确:
- Global Scheduler 只处理跨 pipeline 的资源、session、路由和协议,不接触模型 tensor 或 family 语义;
- 当前 Scheduler candidate 是
PipelinePolicyNode,不调度ModelServiceNode或 GraspGen pipeline; ModelServiceNode可承载 perception、TTS 和其他 typed model plugin;它不属于 policy scheduler candidate,每个 plugin 拥有独立的ModelRuntimeHandle生命周期边界;PipelinePolicyNode只拥有 pipeline-scoped ROS interface;scheduled monolithic 模式通过priority_scheduling构造统一 pipeline context;ModelRuntimeHandleadmission 是最终的进程内执行边界;Ascend priority stream pool 作为 vendor 资源属于AscendOmModelSession,不是 Global Scheduler 的执行旁路;- 通用 priority 必须从 scheduler request 经策略 facade 透传到
ModelRequest.metadata["priority"],再由ModelSession映射到设备能力;不允许在 ROS node 中另建 priority 到设备的映射。
从源码看,scheduler/global_scheduler_core.py 中的 GlobalSchedulerCore 是 "Thread-safe lifecycle, binding, fencing, and quarantine owner",scheduler/session_controller.py 中的 ProductSessionController 则是 "pipeline-side product-session state machine",二者都与 ROS 解耦(模块注释明确标注 "pure-Python, ROS-free"),这保证了生命周期/栅栏/租约/容量规则可以被确定性单元测试覆盖。相关测试可见 test_scheduler_global_core.py 与 test_scheduler_session_controller.py。
Manifest 身份模型
身份字段
Manifest v3 的身份模型是 dispatch 的基石,五个核心字段的含义如下:
| 字段 | 含义 |
|---|---|
interface |
policy 或 tensor_model |
model_type |
全局唯一的具体模型身份,例如 sam2、grounding_dino |
operation |
模型类型的服务契约;policy 固定为 predict |
inputs / outputs |
与 deployment 无关的公共语义 tensor |
semantic_identity |
模型 revision、预处理、输出语义和 embedding space |
model_type 与 operation 的分离
model_type 和 operation 必须分离:一个模型身份可以有多个服务契约。文档给出了五个模型的 Family/Operation/业务契约对照:
| Family | Operation | 业务契约 |
|---|---|---|
sam2 |
automatic |
自动掩码生成 |
sam2 |
prompt |
box-prompt segmentation |
grounding_dino |
detect |
Torch 或编译 Grounding DINO detection |
ram_plus |
recognize_tags |
标签识别 |
siglip2 |
encode |
图像/文本双编码器 |
graspgen |
generate_grasps |
6-DoF grasp generation |
因此 prompt、dual-encoder 和 compiled detection 变体不再生成独立 model_type 或 registry key。编译拓扑由 deployment 的 execution、bindings 和 device_links 描述,服务差异由 operation 描述。
源码层面,inference_manifest/models.py 中的 ModelIdentity 校验逻辑完整落实了这一规则:policy 的 operation 必须精确为 predict,combined/raw 等 legacy operation variant 被拒绝,vla 被明确拒绝为运行时身份("vla is a classification label, not a runtime identity")。CANONICAL_MODEL_MAPPING 还给出了完整规范模型清单:act、pi05、smolvla、ram_plus、sam2、siglip2、grounding_dino、yolox_person、pear_parameter_network、graspgen、dummy_echo、zipvoice、fullsubnet、silero_vad、sherpa_onnx、speech_direction 等。
Manifest 采用严格的 Pydantic 模型(StrictFrozenModel,extra="forbid"、frozen=True、strict=True),拒绝类型强转与未知字段;InferenceManifest 顶层固定 schema_version: Literal[3]、bundle、model、deployments。部署名、role、语义 tensor、state link 等都有严格的正则与语义约束(例如 rank-4 图像 tensor 必须声明 NCHW/NHWC layout)。DeviceLink 的语义必须以 internal. 开头,且强制 producer 先于 consumer 执行、producer_binding="input" 时 owner 必须为 producer。
策略 Facade
InferencePipeline 是 ModelRuntimeHandle 上的策略 facade,负责把既有 policy 请求/结果契约适配为 ModelRequest、ExecutionContext 和 ModelResult,并处理 LeRobot processor、policy codec、prompt、action 校验和策略错误映射。
策略执行链路:
ROS Observations -> InferencePipeline facade
-> ModelRuntimeHandle.execute (ModelRequest + ExecutionContext)
-> SequentialModelExecutor
-> LeRobot preprocess + policy codec
-> Model stage plan
-> Torch / single-role: ModelStage + ModelSession
-> Compiled iterative family: IterativeStage + ModelStage
-> ModelSession -> Raw Action
-> Action decode + validation + postprocess
-> ModelResult -> PipelineResult
关键设计点:
- 策略 facade 不拥有独立的 executor 或控制状态;processor、codec binding、模型/迭代 stage、action decode 和 postprocess 组成同一个
SequentialModelExecutorstage 序列; - PI0.5 Ascend/HMM 和 SmolVLA HMM/RKNN 使用
IterativeStage,Host embedding、time preparation、denoising schedule 和 state update 都属于该 executor 的 stage/resource; - Torch、Ascend 与 RKNN 的旧 policy backend 已删除;registry descriptor 只负责兼容性校验,实例构造由 session factory registry 负责。
源码佐证:pipeline/executor.py 中的 SequentialModelExecutor 是 "fixed InferenceStage sequence" 的具体实现,其 execute() 通过 _execute_stages() 依次执行 stage 并用 ResultAdapter.adapt(frame) 产出结果。pipeline/stages.py 提供了 stage 协议族:PreprocessStage、ModelStage、HostComputeStage、HostRoleStage、PostprocessStage,以及 IterativeStage(重复执行 deployment-derived stage body)与 EulerIterationStateAdapter / DirectIterationStateAdapter 两种迭代状态适配器。其中 EulerIterationStateAdapter 用 float32 Euler 更新语义循环状态(noise + velocity → action),正是 denoising schedule 的共享实现,迭代模型不会再回落到 backend 私有循环。
感知 Facade
构造模式
所有 _SessionPlugin 都从 SessionBuilderRegistry 获取单模型资源,把它放入 RuntimeAssembly,再将 assembly 所有权转移给 ModelRuntimeHandle:
session = SessionBuilderRegistry.create(RuntimeContext(...))
assembly = RuntimeAssembly(runtime_executor=session, session=session, ...)
handle = ModelRuntimeHandle(assembly)
handle.load(RuntimeContext(...))
handle.execute(ModelRequest(...), ExecutionContext(request_id))
请求执行链路:
Typed ROS Request -> ModelServicePlugin
-> PerceptionAdapter.preprocess
-> ModelRequest + ExecutionContext
-> ModelRuntimeHandle
-> ModelSession resource -> ModelResult
-> PerceptionAdapter.postprocess
-> Typed ROS Response
成功结果只发布 ModelResult,失败由 ExecutionFailureFactory 规范化;本地异常 cause 不进入 ROS 序列化。插件生命周期、准入、健康与取消通过 handle 的 load()、execute()、close() 和 diagnostics() 管理;session 只加载、执行并释放具体 vendor 资源。
源码层面,model_service_plugin.py 定义了 ModelServicePlugin 抽象基类(handle / runtime_status / close 三个抽象方法),model_service_node.py 提供通用宿主节点,负责从配置字符串加载 plugin 类与 ROS service 类型,并校验 response 必须具备 model、inference_time_ms、success、message 公共字段。perception_service/model_service_plugins.py 中的 _SessionPlugin 基类展示了标准构造流程:校验 identity → 构造 adapter → 从 SessionBuilderRegistry 创建 session → 组装 RuntimeAssembly → 构造并 load() ModelRuntimeHandle,且明确拒绝 backend、device、model_backend、fallback 等裸参数出现在 options 中("plugins accept only a validated named deployment; raw backend/device/fallback is forbidden")。
感知支持矩阵
五个感知 model_type 均在 Torch 和 Ascend registry 中声明并提供 ConformanceEvidence。这表示 model_type 具备两类后端能力,不表示同一 operation 或 artifact 可跨后端互换:
| Family | Torch | Ascend OM | Operation / 说明 |
|---|---|---|---|
RAM++ ram_plus |
torch_cpu, torch_cuda |
ascend_310p, ascend_310b |
单一标签识别契约 |
SAM2 sam2 |
automatic |
prompt |
同一 model_type 的两个服务契约 |
SigLIP2 siglip2 |
torch_cpu, torch_cuda |
ascend_310p, ascend_310b |
公共 embedding space |
Grounding DINO grounding_dino |
detect |
detect |
deployment/bindings 表达 Torch 组合或 Ascend 图 |
GraspGen graspgen |
generate_grasps |
generate_grasps |
同一点云和 grasp 输出语义 |
该矩阵与 backends/registry.py 中 STATIC_BACKEND_DESCRIPTORS 的声明完全对应:BackendRegistry 是 "immutable registry whose validation path is SDK-free and v3 keyed",导入它不会引入 ACL、RKNNLite、TCIM、Torch 或 worker 可执行文件。ConformanceEvidence 会同时匹配 identity(interface/model_type/operation)、profile 类型、target runtime/soc 与 device,确保"有证据才可部署"。
RAM++
RGB Image -> RAMPlusAdapter (resize 384 + normalize)
-> ModelRuntimeHandle
-> Named Deployment 选择
-> Torch: TorchModelSession (RAMPlus module)
-> Ascend: AscendOmModelSession (RAM++ OM)
-> 4585 class logits
-> sigmoid + threshold + sort
-> tags + scores
对应实现为 RAMPlusRecognizeTagsPlugin(ibrobot_msgs/srv/RecognizeTags,operation=recognize_tags):先对整图推理,再对每个 mask crop 批量推理,最终按 score_threshold、excluded_labels、max_mask_candidates 汇总标签。
SAM2
model_type = sam2 -> model.operation 选择
-> automatic: TorchModelSession (Automatic Mask Generator)
-> masks + boxes + scores + stability
-> prompt: AscendOmModelSession
-> Encoder OM -> image embeddings via device links
-> Prompt Decoder OM -> mask logits + IoU
SegmentDetectionsPlugin 按 Manifest 中 decoder 固定 batch 拆分 detection;请求尾部填充,但只返回真实 detection 对应的 mask。SAM2GenerateMasksPlugin 则对应 automatic 契约(ibrobot_msgs/srv/GenerateMasks),后处理还会执行最小像素、面积比、重叠比过滤。
SigLIP2
Masked Images + Text -> SigLIP2 Adapter -> ModelRuntimeHandle
-> Torch: TorchModelSession (SigLIP2 Transformer)
-> Ascend: SigLIP2AscendSession
-> Vision Encoder OM (one image per invocation)
-> Text Encoder OM (fixed compiled batch)
-> image embeddings / text embeddings
-> L2 normalize -> cosine similarity
SigLIP2AscendSession 把动态图像 batch 拆成单图 vision 调用,将动态文本 batch 按编译 batch 补零和切片。host.siglip2.* semantic 隔离公共模型契约与 OM ABI。SigLIP2EncodeEmbeddingsPlugin(ibrobot_msgs/srv/EncodeEmbeddings)还限制了 candidate-label 批不超过 16 个。
Grounding DINO
model_type = grounding_dino -> model.operation=detect
-> Torch: TorchModelSession (Grounding DINO + SAM2)
-> boxes + scores + labels + masks
-> Ascend: AscendOmModelSession
-> Text Encoder OM + Vision Backbone + Flatten OM
-> Encoder 0..5 OM -> Proposal OM -> Decoder OM
-> Detection Head OM -> pred logits + pred boxes
-> Optional SAM2 prompt service
Torch 组合路径与 Ascend 图路径共用 detect operation,具体拓扑完全由 deployment 的 execution、bindings、device_links 描述——这正是"编译拓扑由 deployment 表达"的典型例子。
GraspGen 本地抓取运行时
GraspGen bundle 同时包含 torch_cuda 和 Ascend compiled deployment。GraspPlannerNode 的 local_cuda 与 ascend_local 都由 LocalPipelineBackend 加载 Manifest,构造 session、RuntimeAssembly 和 ModelRuntimeHandle;AscendLocalBackend 仅保留为兼容别名。
Object Point Cloud -> GraspGenAdapter.prepare (clean + center + kappa scale)
-> LocalPipelineBackend -> ModelRuntimeHandle
-> Named Deployment 选择
-> torch_cuda: TorchModelSession -> GraspGen Torch Callable -> GraspGenSampler.run_inference
-> ascend: GraspGenAscendSession
-> Generator + Discriminator roles
-> Host FPS + Ball Query
-> Host DDPM loop -> Denoiser OM (循环) -> Discriminator Head OM
-> grasp poses + confidence
-> GraspGenAdapter.postprocess -> GraspCandidateArray
Torch callable 在调用上游 sampler 前恢复其预期点云尺度。Ascend session 持有持续随机流并执行八个 OM role;本地 backend 负责多 batch 聚合和全局 top-k,但不持有模型语义。
源码层面,graspgen_wrapper.py 中 LocalPipelineBackend 的 docstring 明确说明:"This class only drives that pair in-process; it holds no GraspGen semantics of its own"——语义全部在 perception_service.GraspGenAdapter(点云准备与 grasp 解码),所选 session 只负责 Torch CUDA 或八-role Ascend 执行。sample() 在 _sample_lock 下对多 batch 执行连续请求,保持一个不中断的随机流;OM 文件静态 batch 为 1000 时,最后不完整 batch 只保留请求数量的原始样本。GraspGenWrapper.__init__ 支持 inference_backend="local_cuda" | "ascend_local"、local_manifest_path、local_deployment_name、ascend_local_manifest_path、ascend_local_deployment_name、ascend_local_device_id、ascend_local_random_seed 等参数(见 graspgen_wrapper.py)。
生命周期与所有权
ModelRuntimeHandle 的状态机如下:
[*] -> Created
Created -> Loading: handle.load()
Loading -> Ready: resources loaded
Loading -> Failed: rollback on error
Ready -> Ready: handle.execute(request, context)
Ready -> ResetRequired: uncertain failure
Ready -> Resetting: handle.reset()
ResetRequired -> Resetting: handle.reset()
Resetting -> Ready: reset completed
Resetting -> Failed: reset failed
Ready -> Closing: handle.close()
ResetRequired -> Closing: handle.close()
Failed -> Closing: handle.close()
Closing -> Closed: drain + reverse cleanup
Closed -> [*]
三条所有权规则:
ModelRuntimeHandle接受RuntimeAssembly的所有权转移,统一加载 executor 与 owned components;加载失败 rollback,关闭时停止准入、等待 active execution,并按反向顺序幂等释放资源;ModelSession是 assembly 中的资源,只拥有 vendor 模型对象、设备 lease、buffer、worker 和专用 host 资产;它不拥有公开准入、runtime 生命周期、健康、取消或关闭等待;ModelRequest提供只读语义输入和 metadata;同一个ExecutionContext把 request ID、deadline 和 cancellation token 传过 executor、stage 与 session resource;device_links的 producer buffer、consumer input 和 inference lifetime 由 Manifest 声明;- plugin 只负责 ROS message 转换、adapter 调用和 typed response 组装。
源码佐证非常完整:unified_runtime/handle.py 定义了合法的状态转移表(_LEGAL_TRANSITIONS),任何非法迁移都会抛 RuntimeError;load() 失败时按反向顺序释放已加载 entries 并转入 FAILED;close() 先停止准入(_admission_open=False)、进入 CLOSING 等待 quiescent(active executions / loading / stream openings 归零),再反向释放资源并转入 CLOSED。RuntimeAssembly(unified_runtime/assembly.py)提供 claim_ownership() 一次性所有权转移,component_entries() 按获取顺序生成释放列表(provider lease 先于 session/executor 获取,因此反向清理先释放 session/worker 再释放 lease)。ExecutionContext、Deadline、CancellationToken、OutcomeEvidence、ModelResult、RuntimeHealth、RuntimeDiagnostics 等契约类型都定义在依赖中立的 unified_runtime/contracts.py,该模块刻意不导入 ROS、模型 SDK 或 legacy backend 契约。
值得强调的是 OutcomeEvidence 机制:成功与失败统一携带 state(not_started/started/completed)、outcome_known、state_mutated、phase 证据;当一次已启动且 outcome 未知的执行失败时,handle 会进入 fail-closed 的 RESET_REQUIRED 状态(可 reset)或 FAILED(需 reload),这是"不确定失败必须恢复"语义的落地。
配置入口
策略 pipeline 配置
策略 pipeline 由 robot_config 控制模式配置(文档示例):
control_modes:
model_inference:
inference:
enabled: true
pipelines:
policy:
model_path: models/so101_act
deployment: rk3588
execution_mode: monolithic
runtime_options: {}
仓库中的真实配置示例:dev_rtp_single_camera.yaml 展示了 development 环境的最小配置(execution_mode: distributed、deployment: cpu)。从源码看,robot_config 的校验器(inference_config.py)会解析 control_modes.<mode>.inference.pipelines.<name>,并支持 executor.inference_fallback_chain、executor.inference_priority=0 等扩展字段;default_control_mode 默认为 model_inference。
GraspGen 本地部署配置
GraspGen 本地部署使用 Manifest 和 named deployment(文档示例):
grasp_execution:
planner_node:
inference_backend: local_cuda
local_manifest_path: models/grasp/graspgen_bundle
local_deployment_name: torch_cuda
Ascend 配置可使用 ascend_local_manifest_path、ascend_local_deployment_name、device ID 和随机种子;Manifest/deployment 是最终事实来源。
真实配置参考 lekiwi_handeye_realsense_grasp.yaml:
grasp_execution:
planner_node:
inference_backend: ascend_local
local_manifest_path: "$(env WORKSPACE)/models/graspgen"
local_deployment_name: ascend_310p
ascend_local_manifest_path: "$(env WORKSPACE)/models/graspgen"
ascend_local_deployment_name: ascend_310p
ascend_local_device_id: 0
ascend_local_random_seed: 0
startup_warmup: true
host_runtime:
omp_threads: 4
blas_threads: 1
num_grasps: 5000
...
grasp_execution_config.py 的 schema 校验强制:inference_backend 只能是 local_cuda 或 ascend_local;local_cuda 必须有 local_manifest_path,ascend_local 必须有 ascend_local_manifest_path;topk_num_grasps 不得超过 num_grasps。
扩展与禁止项
新增模型的最小流程
- 定义
interface、全局唯一model_type、operation和公共 tensor 语义; - 定义 named deployment、artifacts、execution、bindings 和 device links;
- 增加 registry 声明和
ConformanceEvidence; - 实现 adapter;只有存在 host orchestration 时才新增专用
ModelSession; - 使用现有 stage 组合 executor;迭代模型使用
IterativeStage; - 策略通过
InferencePipelinefacade 调用ModelRuntimeHandle;plugin/local wrapper 构造RuntimeAssembly和 handle,不得直接驱动 session/backend; - 增加 Manifest、registry、session resource、handle lifecycle 和 typed service 测试。
禁止重新引入的旁路
Perception/TTS Plugin -> ModelSession.execute()
GraspPlannerNode -> GraspGenSampler
GraspPlannerNode -> GraspGenAscendSession
Compiled PI0.5/SmolVLA -> backend-owned iterative loop
业务参数 -> raw backend/device/fallback selection
这些"禁止项"与源码中的防御性校验一一对应:插件构造时拒绝 raw backend/device/fallback 参数;ModelRuntimeHandle._validate_configuration() 拒绝 execution_structure / orchestration_visibility / state_scope / cancellation_granularity 的非法组合;Manifest 的 ModelIdentity 拒绝所有 legacy 身份与 operation 变体;注册表校验拒绝 evidence_overclaims_support。
最终原则
策略、感知、TTS 和抓取模型共享
ModelRuntimeHandle控制面;handle 负责准入、生命周期、健康和取消,模型与硬件差异只能通过 Manifest、executor stage、作为资源的ModelSession与设备 runtime 表达。
这一原则保证了:业务侧(ROS 协议、adapter、facade)模型无关,资源侧(vendor model、设备 lease、编译 ABI)通过 Manifest 与 session 隔离,控制侧(准入、生命周期、健康、取消、deadline)完全统一。从 unify.md 到 inference_manifest 与 inference_service 的源码实现,这一统一模型推理架构已经从设计文档完整落地为可运行的工程代码。