ai-chatbot/docs/worldlabs-proxy-provider-requirements.md
Your Name dd2b06f10f
Some checks failed
Lint / build (20) (push) Has been cancelled
Playwright Tests / test (push) Has been cancelled
fix: harden worldlabs asset loading
2026-05-25 17:27:25 +08:00

317 lines
7.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# World Labs 3D 世界生成中转接口兼容要求
本文档用于说明我方系统接入 World Labs 3D 世界生成功能时,对第三方中转服务的接口兼容要求。
## 核心原则
我方系统会按照 World Labs 官方 API 协议发起请求:
```text
{baseUrl} + /marble/v1/...
```
中转服务需要兼容官方路径、请求体、响应体和错误格式。请不要要求我方把 `baseUrl` 配置成某个完整接口地址。
正确示例:
```text
http://your-proxy-domain.com
```
错误示例:
```text
http://your-proxy-domain.com/marble/v1/worlds:generate
```
## 我方请求方式
我方后台会在请求中携带:
```http
WLT-Api-Key: {配置的 API Key}
Accept: application/json
Content-Type: application/json
```
中转服务应支持 `WLT-Api-Key` 请求头。如果中转服务内部自行管理官方 Key,也可以将该字段作为租户标识或鉴权凭据,但不应要求我方改成其他 header。
## 必须兼容的接口
### 1. 准备上传素材
```http
POST {baseUrl}/marble/v1/media-assets:prepare_upload
```
请求体示例:
```json
{
"file_name": "input.jpg",
"extension": "jpg",
"kind": "image",
"metadata": {
"mime_type": "image/jpeg",
"uploaded_from": "canvas_world_mode"
}
}
```
响应必须包含可用的上传信息:
```json
{
"media_asset": {},
"upload_info": {
"upload_url": "https://...",
"upload_method": "PUT",
"required_headers": {}
}
}
```
要求:
- `upload_url` 必须可由我方服务器直接访问。
- `upload_method` 如为 `PUT`,必须支持 `PUT` 上传文件二进制。
- `required_headers` 中返回的 header,我方会原样带上。
- 上传成功时,上传地址必须返回 `2xx`。
### 2. 创建世界生成任务
```http
POST {baseUrl}/marble/v1/worlds:generate
```
请求体示例:
```json
{
"display_name": "",
"model": "marble-1.1",
"permission": {
"public": false
},
"world_prompt": {
"type": "image",
"image_prompt": {
"source": "media_asset",
"media_asset_id": "media_asset_id_here"
}
}
}
```
响应需兼容官方 operation 结构,至少包含:
```json
{
"operation_id": "task-id",
"done": false,
"metadata": {
"progress": {
"status": "RUNNING"
}
}
}
```
要求:
- `operation_id` 必须稳定,后续查询状态必须使用同一个 id。
- 不要在创建成功但任务未完成时返回业务失败。
- 如果余额不足、Key 无效,应返回明确 HTTP 状态码和错误信息。
### 3. 查询任务状态
```http
GET {baseUrl}/marble/v1/operations/{operation_id}
```
运行中响应示例:
```json
{
"operation_id": "task-id",
"done": false,
"metadata": {
"progress": {
"status": "RUNNING",
"description": "World generation in progress"
}
}
}
```
成功响应示例:
```json
{
"operation_id": "task-id",
"done": true,
"error": null,
"metadata": {
"progress": {
"status": "SUCCEEDED"
},
"world_id": "world-id"
},
"response": {
"world_id": "world-id",
"world_marble_url": "https://marble.worldlabs.ai/world/...",
"assets": {
"mesh": {
"collider_mesh_url": "https://cdn.marble.worldlabs.ai/.../model.glb"
},
"imagery": {
"pano_url": "https://cdn.marble.worldlabs.ai/.../rgb_0.png"
},
"thumbnail_url": "https://cdn.marble.worldlabs.ai/.../thumbnail.webp",
"splats": {
"spz_urls": {
"100k": "https://cdn.marble.worldlabs.ai/...100k.spz",
"150k": "https://cdn.marble.worldlabs.ai/...150k.spz",
"500k": "https://cdn.marble.worldlabs.ai/...500k.spz",
"full_res": "https://cdn.marble.worldlabs.ai/...full.spz"
}
}
}
}
}
```
失败响应示例:
```json
{
"operation_id": "task-id",
"done": true,
"error": {
"message": "Insufficient account balance"
}
}
```
要求:
- `done=false` 表示任务仍在运行。
- `done=true` 且 `error=null` 表示任务成功。
- `done=true` 且 `error.message` 存在表示任务失败。
- 不要把运行中的任务返回为 HTTP 404。
- 不要因为任务未完成就返回 `Operation not found`。
### 4. 查询世界详情
```http
GET {baseUrl}/marble/v1/worlds/{world_id}
```
当 `operations` 成功响应中资产不完整时,我方会调用该接口补充详情。响应应包含与 `response` 内 world 对象兼容的数据结构。
## 错误码要求
建议按以下语义返回:
| 场景 | HTTP 状态码 | message 示例 |
| --- | --- | --- |
| API Key 缺失或无效 | `401` | `Unauthorized` |
| 权限不足 | `403` | `Forbidden` |
| 余额不足 | `402` 或 `403` | `Insufficient account balance` |
| 请求体错误 | `400` | `Invalid request body` |
| 任务不存在 | `404` | `Operation not found` |
| 上游超时 | `504` | `Upstream timeout` |
| 上游异常 | `502` | `Upstream error` |
响应体建议:
```json
{
"message": "Insufficient account balance"
}
```
或:
```json
{
"error": {
"message": "Insufficient account balance"
}
}
```
## 超时与稳定性要求
- `prepare_upload` 建议 30 秒内返回。
- `worlds:generate` 建议 60 秒内返回 operation,而不是等待生成完成。
- `operations/{id}` 建议 10 秒内返回当前状态。
- 生成任务本身可异步运行,前端会轮询状态。
- 同一个 `operation_id` 多次查询必须返回同一个任务状态,不应随机切换账号或路由。
## 上传地址要求
`prepare_upload` 返回的 `upload_url` 可以是官方签名地址,也可以是中转服务自己的上传地址,但必须满足:
- 我方服务器可直接访问。
- 支持返回的 `upload_method`。
- 支持上传原始文件二进制。
- 上传成功返回 `2xx`。
- 上传完成后,后续 `worlds:generate` 使用的 `media_asset_id` 必须可用。
## 安全要求
- 不要在错误信息中返回完整官方 API Key。
- 日志中建议只记录 Key 前后少量字符,例如 `sk-****abcd`。
- 中转服务如保存官方 Key,应加密存储。
- 上传 URL 如有签名,应设置合理过期时间。
- 不要允许用户通过 `baseUrl` 或 path 注入访问内网地址。
## 我方验收用例
中转服务上线前,请至少通过以下链路:
1. `POST /marble/v1/media-assets:prepare_upload` 返回 `media_asset_id` 和可上传 URL。
2. 使用返回的 `upload_url` 上传图片,返回 `2xx`。
3. `POST /marble/v1/worlds:generate` 返回稳定 `operation_id`。
4. `GET /marble/v1/operations/{operation_id}` 在运行中返回 `done=false`。
5. 任务完成后返回 `done=true`、`error=null`、`world_id` 和资产 URL。
6. 资产 URL 中至少应包含 thumbnail、pano、mesh 或 spz 中的一种,最好完整返回。
7. `GET /marble/v1/worlds/{world_id}` 可返回完整 world 详情。
## 配置示例
我方系统中的 API 地址应填写中转根地址:
```text
http://23.169.168.133:8080
```
最终我方会请求:
```text
http://23.169.168.133:8080/marble/v1/media-assets:prepare_upload
http://23.169.168.133:8080/marble/v1/worlds:generate
http://23.169.168.133:8080/marble/v1/operations/{operation_id}
http://23.169.168.133:8080/marble/v1/worlds/{world_id}
```
如果切回官方接口,配置为:
```text
https://api.worldlabs.ai
```
最终请求:
```text
https://api.worldlabs.ai/marble/v1/media-assets:prepare_upload
https://api.worldlabs.ai/marble/v1/worlds:generate
https://api.worldlabs.ai/marble/v1/operations/{operation_id}
https://api.worldlabs.ai/marble/v1/worlds/{world_id}
```
## 结论
中转服务需要做的是兼容 World Labs 官方 API 协议,而不是要求我方修改接口路径。只要中转根地址完整支持 `/marble/v1/...`,我方系统就可以在官方接口和中转接口之间无缝切换。