建模 SDK
用世界模型把一段文字、一张照片、一张 360° 全景、同一空间的几张照片或一段视频,变成可以走进去的 3D 世界(高斯溅射 + 碰撞网格 + 全景),再把世界里的位置绑到公司的业务对象上——设备、工位、传感器——这是数字孪生的地基。上游是 World Labs 的 Marble 世界模型(World API);所有调用都经过 AIDC:额度、并发、复用、留痕、账单都在平台这一侧,浏览器里拿不到上游密钥。
import { modeling } from "/developer/sdk/v1/aidc.js";
| 做什么 | SDK | CLI |
|---|---|---|
| 看价钱(不联网) | modeling.estimate(model, input) |
aidc modeling estimate |
| 生成一个世界 | modeling.generate(spec) → modeling.wait(id) |
aidc modeling generate |
| 看 / 找世界 | modeling.get(id) · modeling.list() |
aidc modeling get · list |
| 在网页里走进去 | modeling.viewer(el, world) |
— |
| 绑业务对象(孪生) | modeling.setAnchors(id, anchors) |
aidc modeling anchors |
| 导出 / 下载到本机 | modeling.exportAsset(id, …) |
aidc modeling export · download |
| 额度 | modeling.budget() |
aidc modeling budget |
公开展示:世界模型 · 空间建模(只读展示,不接受生成请求)。
1. 先看价钱
World Labs 按 credits 计费,1,250 credits = 1 美元。一次生成 = 全景生成(按输入类型;给现成全景则免)+ 世界生成(按模型):
| 模型 | 文字 | 单张图片 | 360° 全景 | 多张图片 / 视频 | 适合 |
|---|---|---|---|---|---|
marble-1.0-draft(缺省) |
230($0.18) | 230($0.18) | 150($0.12) | 250($0.20) | 试提示词、看构图 |
marble-1.1 |
1,580($1.26) | 1,580($1.26) | 1,500($1.20) | 1,600($1.28) | 正式质量,价格固定 |
marble-1.1-plus |
1,580–3,080 | 1,580–3,080 | 1,500–3,000 | 1,600–3,100(≤ $2.48) | 最大的世界,按规模加收 |
另外:HQ 网格导出每个世界 3,500 credits($2.80,同一世界只收一次);PLY 高斯溅射导出、上传输入、查询进度都不收钱。
modeling.estimate("marble-1.1", "video");
// { maxCredits: 1600, maxUsd: 1.28, lines: [{ name: "全景生成(视频)", credits: 100 }, { name: "世界生成", credits: 1500 }] }
aidc modeling estimate -m marble-1.1-plus --input multi-image # 本机算,不用登录
2. 费用控制:闸在平台这一侧
World Labs 不按单次成本拦截请求——余额不够照样执行、月底按超额补扣,自动充值也不设上限。所以 AIDC 在调上游之前就把钱的事判完,按这个顺序:
- 估价:按最坏情况(Plus 的浮动部分按上限)算这一次最多花多少。
- 策略:模型是否开放、是否超过单次上限;调用方可以再给一个更严的
maxCredits。 - 复用:同一公司里同样的请求(模型 + 输入 + seed)已有结果 → 直接返回那个世界,不花钱(
regenerate: true才重新生成)。 - 幂等:必须带
Idempotency-Key(SDK / CLI 自动生成);网络重试用同一个 Key,拿到的是同一个世界。 - dry-run 到此为止:返回估价、额度、将发给上游的载荷,不调上游、不落库。
- 每小时次数(每公司)→ 同时在跑的上限(全平台、每公司)→ 月度额度(全平台总闸 + 公司额度 + 应用每日额度):在同一把事务锁里判完并按最坏情况预留,并发请求不会一起挤过去。
- 调上游:明确失败 → 释放预留;结果不明(超时 / 断网,上游可能已受理)→ 预留不释放,按已花费计。
- 结账:完成时按上游结算的
cost.total_credits结账(拿不到就按预留,宁多不少),同时在用量台账记一行(与模型通道同一本账,按公司计费)。
缺省策略(平台 env AIDC_MODELING_POLICY 可以部分覆盖;写坏了就停止一切花费):
| 项 | 缺省 |
|---|---|
| 开放的模型 | marble-1.0-draft、marble-1.1(Plus 浮动计价,缺省不开) |
| 单次上限 | 1,600 credits(挡住 Plus 与 HQ 网格导出) |
| 全平台每月 | 6,250 credits($5) |
| 公司每月 | AIDC 6,250;其他公司 0 = 只能看,要开通找 AIDC 平台 |
| HQ 网格导出 | 关闭 |
| 同时在跑 | 全平台 3 个、每公司 2 个;每公司每小时 10 次 |
应用里生成要在清单写每日额度 limits.worldCreditsPerDay(不写 = 0 = 只看);只读访客(分享链接 / viewer)不能生成。官方公开应用(namespace public)永远不能生成、上传、导出或改锚点——公开展示只看不花钱,这条写死在平台里,不靠清单。
const plan = await modeling.generate({ input: { kind: "text", text: "一个整洁的汽车零部件装配工位" } }, { dryRun: true });
plan.plan.estimate.maxCredits; // 230
plan.plan.decision; // { ok: true } 或 { ok: false, message: "…本月的世界模型额度不够…" }
await modeling.budget(); // { month, company: { cap, settled, reserved, remaining } }
3. 生成一个世界
const { world, reused } = await modeling.generate({
input: { kind: "text", text: "一个整洁的汽车零部件装配工位:右侧白色六轴机械臂,前方红色检测台,黄色安全围栏" },
model: "marble-1.0-draft", // 先试稿;满意了再 marble-1.1
displayName: "装配工位(试稿)",
maxCredits: 300, // 这一次的硬上限
});
const done = await modeling.wait(world.id, { onProgress: (w) => console.log(w.progress?.description) }); // 约 5 分钟
aidc modeling generate --text "一个整洁的装配工位…" --dry-run # 先看估价与额度
aidc modeling generate --text "一个整洁的装配工位…" -m marble-1.1 # 等到完成,打印资产与坐标系
aidc modeling generate --image cell.jpg --text "保留机械臂与检测台的位置" # 本地文件自动直传 World Labs
aidc modeling generate --image a.jpg --image b.jpg --image c.jpg --reconstruct # 同一空间多图重建
aidc modeling generate --video walk.mp4 --no-wait # 立即返回,稍后 aidc modeling wait <id>
输入 input.kind |
写法 | 建议(World Labs 官方与 AIDC 09-14 实测) |
|---|---|---|
text |
{ kind: "text", text } |
≤ 2,000 字,描述一个地点而不是一个物件 |
image |
{ kind: "image", image: { mediaId } | { url }, text? } |
长边 ≥ 1024、≤ 20 MB;要有地面 / 墙面 / 纵深;人物、特写、强反光效果差 |
pano |
{ kind: "pano", image, text? } |
2:1 等距柱状 360° 全景(约 2560 宽);空间布局最准,不收全景生成费 |
multi-image |
{ kind: "multi-image", images: [{ mediaId | url, azimuth? }], reconstruct } |
reconstruct: true:2–8 张同一空间、同一宽高比、相邻有重叠的照片;不开时最多 4 张按方位角拼 |
video |
{ kind: "video", video, text? } |
≤ 30 秒 / 100 MB(mp4 / mov / webm);稳、慢、一镜到底,覆盖 180°–360°;锁焦距与曝光;画面里别有人走动 |
text 是可选的文字引导(图片类输入不给就由上游自动描述);recaption: false 让上游原样使用你的文字。seed 固定随机性。
生成的是「看起来合理」的空间,不是测绘。 照片没拍到的背面、遮挡处由模型补全;侧向移动时细杆、线缆、近处物件会拉伸或模糊;标牌文字不可信。AIDC 09-14 的四组实测(文字、单张照片、视频、四图重建)结论一致:适合工位导览、空间入口、培训与方案沟通;不能用于尺寸验收、碰撞安全、机器人离线编程——那需要标定、实测尺寸或 CAD。
4. 世界里有什么
world.assets.splats["500k"]; // 高斯溅射 SPZ:100k / 150k / 500k / full_res(约 1.4 / 2.5 / 8 / 30 MB)
world.assets.collider; // 碰撞网格 GLB(低模,用于走动、拾取、物理)
world.assets.pano; // 生成用的全景图
world.assets.thumbnail; // 缩略图
world.caption; // 上游对世界的描述
world.frame; // AIDC 空间坐标系(下一节)
world.cost; // { estimatedCredits, settledCredits, usd, lines }
资产放在 World Labs 的 CDN(cdn.marble.worldlabs.ai)上,地址本身就是访问凭证(不可猜的长路径)——只交给有权看这个世界的人。平台只存地址、坐标系与锚点,不存文件。
5. AIDC 空间坐标系
Marble 的原始坐标是 OpenCV 约定(Y 向下、任意单位)。平台按每个世界的尺度信息换成统一的空间坐标系:米、Y 向上、地面 y = 0;生成视点在 (0, groundPlaneOffset, 0),初始视线朝 -Z。锚点、测距、以后接进来的设备位姿都在这个坐标系里。
const frame = modeling.frameOf(world); // { metricScaleFactor, groundPlaneOffset, metric }
modeling.toMetric([0.2, 0.6, 1.1], frame); // 原始坐标(SPZ / 碰撞网格顶点)→ 米
modeling.fromMetric([1.2, 0.8, -3.4], frame); // 米 → 原始坐标
modeling.distance(a, b); // 米
换算:米 = [s·x, g − s·y, −s·z](s = metricScaleFactor,g = groundPlaneOffset)。碰撞网格与 SPZ 同一套原始坐标,用同一个换算。frame.metric = false 的老世界没有尺度信息(按 1 / 0 处理);即使有,生成的尺度也是估计值,没有标定过。
6. 在网页里走进去:查看器
查看器用 World Labs 维护的高斯溅射渲染器 Spark(2.2.0)+ three.js(0.180.0),钉死版本、从 jsDelivr 加载。页面先放 import map(在任何 module 脚本之前),清单 sdk 登记 modeling、cdn 登记 cdn.jsdelivr.net——平台据此给应用的 CSP 放行 World Labs 资产与 WebAssembly 编译:
<script type="importmap">
{ "imports": {
"three": "https://cdn.jsdelivr.net/npm/three@0.180.0/build/three.module.js",
"three/addons/": "https://cdn.jsdelivr.net/npm/three@0.180.0/examples/jsm/",
"@sparkjsdev/spark": "https://cdn.jsdelivr.net/npm/@sparkjsdev/spark@2.2.0/dist/spark.module.js" } }
</script>
<div id="stage" style="height: 70vh"></div>
<script type="module">
import { modeling } from "/developer/sdk/v1/aidc.js";
const [world] = await modeling.list({ status: "succeeded" });
const view = await modeling.viewer(document.querySelector("#stage"), world, {
quality: "500k", // 手机上用 "100k"
collider: true, // 加载碰撞网格,支持 pick()
onAnchor: (anchor) => console.log(anchor.object),
});
view.view("top"); // home / side / back / top
stage.addEventListener("dblclick", async (e) => console.log(await view.pick(e.clientX, e.clientY))); // → [x, y, z](米)
</script>
modeling.importMap() 返回同一份 import map。左键拖动旋转、滚轮缩放、右键平移;focus(anchor) 飞到锚点;setQuality() 换精度;snapshot() 截图;dispose() 释放 WebGL 资源。需要 WebGL2。
7. 锚点:数字孪生的地基
世界只是空间;锚点把空间里的位置绑到业务对象上。每个锚点:位置(米)、名称、类型(equipment / sensor / zone / camera / note)、静态属性(型号、编号…),以及可选的语义层对象(object: { type, pk },类型必须在本公司语义层里)。
await modeling.setAnchors(world.id, [
{ id: "robot-1", label: "焊接机械臂 R-01", kind: "equipment", position: [1.2, 0.8, -3.4],
object: { type: "production.equipment", pk: "R-01" }, meta: { 型号: "ER20" }, verified: true },
{ id: "fence-a", label: "安全围栏 A 区", kind: "zone", position: [0, 0, -2] },
], { ifRev: world.anchorsRev });
整组替换(幂等),ifRev 做乐观并发(别人改过就 409)。verified 标明位置与身份是否经人工核验——生成的世界有模型补全,未核验的锚点在查看器里是空心点,只能当示意。
把锚点接到实时数据,就是一个最小的数字孪生:
import { modeling, data } from "/developer/sdk/v1/aidc.js";
const view = await modeling.viewer(stage, world, {
onAnchor: async (anchor) => {
if (!anchor.object) return;
const { object } = await data.table(anchor.object.type).get(anchor.object.pk); // 语义层里的设备:状态、报警、工单…
panel.textContent = `${anchor.label}:${object.props.status}`;
},
});
data.watch({ types: ["production.equipment"] }, { onChange: () => refreshPanels() }); // 数据一变就更新
8. 导出与下载
aidc modeling export <id> --ply --resolution full_res # 高斯溅射 PLY(免费、立即完成)
aidc modeling export <id> --mesh --dry-run # HQ 网格 GLB:3,500 credits,缺省策略关闭
aidc modeling download <id> --out ./cell-01 # SPZ + 碰撞网格 + 缩略图 + world.json(坐标系与锚点)
下载下来的 SPZ / PLY 可以进 Unity、Unreal、Blender、Houdini(各引擎的高斯溅射插件),按 world.json 里的坐标系摆正。
9. 输入媒体与数据边界
const { mediaId } = await modeling.upload(file); // 先向平台换签名地址,字节直传 World Labs,不经过 AIDC
await modeling.generate({ input: { kind: "image", image: { mediaId }, text: "保留设备位置" } });
- 上传的照片 / 视频发给第三方模型服务 World Labs(美国)处理。只上传有权提供的现场内容;避免人脸、证件、屏幕上的敏感信息;客户现场的内容要客户同意。
mediaId登记在上传它的命名空间,生成时只认本命名空间的(别的公司引用不到)。浏览器直传若被存储桶跨域拦下,改用aidc modeling upload或给公开的 https 地址。- 平台存:提示文字、媒体引用(id / 地址,不存字节)、资产地址、坐标系、锚点、成本;删除世界 = 平台打墓碑,
purge同时删除 World Labs 上的原件(只对经平台生成的世界)。 - 官方公开命名空间(public)只放不含客户内容的世界(文字生成、或已获授权的内容)。
10. 清单与 API
{
"sdk": ["modeling", "ui"],
"cdn": ["cdn.jsdelivr.net"],
"limits": { "dailyTokens": 1000000, "requestsPerMinute": 30, "realtimeSessionsPerDay": 0, "worldCreditsPerDay": 1600 }
}
| 方法 | 路径 | 做什么 |
|---|---|---|
| GET | /api/v1/developer/modeling |
目录:模型、价目、策略、上游是否已配置(公开) |
| GET | /api/v1/developer/modeling/{ns}/budget |
本月额度 |
| GET / POST | /api/v1/developer/modeling/{ns}/worlds |
列表 / 生成(Idempotency-Key 必填,支持 dry-run) |
| GET / DELETE | /api/v1/developer/modeling/{ns}/worlds/{id} |
详情(进行中会同步进度)/ 删除(?purge=1) |
| PUT | /api/v1/developer/modeling/{ns}/worlds/{id}/anchors |
锚点(整组替换,ifRev) |
| POST | /api/v1/developer/modeling/{ns}/worlds/{id}/exports |
导出 PLY / HQ 网格 |
| POST | /api/v1/developer/modeling/{ns}/media |
上传输入:换签名地址 |
| POST | /api/v1/developer/modeling/{ns}/imports |
登记已有的 Marble 世界(AIDC 平台账号) |
{ns} = public 或 cell-…。public 的世界谁都能读(只列已完成的、不带发起人)。错误码:quota_exhausted(额度 / 单次上限,details.scope 说明是哪一层)、rate_limited、idempotency_key_required、idempotency_conflict、media_not_found、world_not_found、modeling_unconfigured(平台还没配置上游)、model_upstream_failed。
11. 接下来:从空间到孪生
世界(空间底座)+ 锚点(空间 ↔ 对象)+ 语义层(对象的状态)+ 数据流(实时)+ 工作流(联动)= 数字孪生。建模 SDK 先把前两块做成稳定的契约:统一的空间坐标系、按公司隔离的世界与锚点、可控的成本。下一步:同一工位的环拍采集规范与实测尺寸标定、设备位姿接入、世界版本对比、World Labs 新模型(Atlas 的多视图重建与相机控制)开放后接入。
本页由 developer/docs/modeling.md 生成 · Markdown 原文 · llms.txt