Add prototype gameplay loop with character/battlefield assets and server game APIs.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+905
@@ -0,0 +1,905 @@
|
||||
# LLM3DGraphics · 跨项目 / AI 调用指南
|
||||
|
||||
给**其他项目、其他开发者、自动化 Agent**用:如何把自然语言需求编排成对 `LLM3DGraphics` HTTP API 的调用,产出图片、Unity 图片素材、网格、(可选)绑骨角色与骨骼动画。
|
||||
|
||||
- 服务默认:`http://192.168.130.16:8008`
|
||||
- OpenAPI:`http://192.168.130.16:8008/docs`
|
||||
- **DGX 绑骨/动画规范**见 **[DGX3D生成说明.md](./DGX3D生成说明.md)**;本文偏「怎么编排调用」
|
||||
- 引擎可选:`dgx`(Spark 绑骨+动作)、`hunyuan`(混元官网网页)
|
||||
- 本地图像入口:`http://192.168.130.16:8008/#local-images`;当前仅保留 **Qwen-Image-2.1-Turbo BF16**,文字生成、多参考图编辑、批量草稿见 **§4.4**。
|
||||
|
||||
---
|
||||
|
||||
## 0. 一分钟结论
|
||||
|
||||
| 用户说法(示例) | AI 应做的事 |
|
||||
|------------------|------------|
|
||||
| 「用这张图做一个会动的狼,再给 idle / 跑」 | **`engine=dgx`**:图 → 绑骨 → 多次 `/animate` |
|
||||
| 「官网混元出个模型就行 / 走混元网页」 | **`engine=hunyuan`**:先确认微信已登录 → 出 `model` / `model_ex`(**无绑骨、无 animate**) |
|
||||
| 「做一个石灯道具」 | 优先 `dgx` + `character_type=static`;或 `hunyuan` 只要网格 |
|
||||
| 「做一个士兵,再套走路」 | **`engine=dgx`** + `humanoid` → Step2 Kimodo |
|
||||
| 「写段文字直接出 3D」 | 先通过 §4.4 本地 Turbo 生成参考图 → 再选 3D 引擎 |
|
||||
| 「文字出图 / 多图生成新图 / 批量草稿」 | **§4.4 本地 Turbo**:提交图片批次 → 轮询 → 下载 PNG / Unity ZIP |
|
||||
| 「照这个画风换成运动装男孩,再做 3D」 | §4.4 上传风格参考图并写清修改要求 → 选定生成图片 → 上传 `/api/jobs` |
|
||||
|
||||
**硬约束(调用前必读)**
|
||||
|
||||
1. 先选引擎(§引擎选择):要绑骨/动作 → **只能 `dgx`**;只要官网质量网格 → 可用 **`hunyuan`**。
|
||||
2. 无参考图时优先走 **`POST /api/local-images/jobs` 本地 Turbo**(§4.4);用户选择云端生图时走 **`POST /api/image/generate` 转接**(§4.1),勿直连上游、勿带 Key。
|
||||
3. `dgx` 可驱动角色 = **两步**:`/api/jobs` → `/api/jobs/{id}/animate`;多动作多次 animate(注意覆盖)。
|
||||
4. `hunyuan` / `dgx`+`static`:**禁止** `/animate`(会 422)。
|
||||
5. `hunyuan` 必须当前浏览器客户端已登录混元官网(`hunyuan_logged_in`);首次登录在客户端页面扫码。
|
||||
6. 3D 队列同时 `queued`+`running` ≤ 5;本地图像最多排队 4 批、每批 1–16 张。轮询间隔 ≥ 2s;单任务可能数分钟~数十分钟。
|
||||
7. Turbo 可与混元共同驻留,**图像与 DGX 3D/对比/动作任务仍串行执行**。图像队列结束后才能转入 DGX 3D;不要绕过本机调度器直接调用 DGXA 的 8090 worker。
|
||||
|
||||
---
|
||||
|
||||
## 1. 前置:服务与能力探测
|
||||
|
||||
```http
|
||||
GET /api/capabilities
|
||||
```
|
||||
|
||||
关注字段(名称以实际 JSON 为准):
|
||||
|
||||
| 字段 | 含义 |
|
||||
|------|------|
|
||||
| `image_generate_ready` | 本机生图转接是否可用 |
|
||||
| `hunyuan_logged_in` / `hunyuan_status` | 混元官网微信登录态 |
|
||||
| `image_ready` | 混元网页是否已登录 |
|
||||
| `dgx_ready` / `dgx.hy3d_ready` | DGX Spark 图生高模 |
|
||||
| `dgx.tokenrig_ready`(或 `unirig_ready`) | 能否绑骨(`static` / 混元路径不需要) |
|
||||
| `dgx.unimate_ready` | 非人形文生动画 |
|
||||
| Mixamo 数量相关字段 | 人形动作库是否非空 |
|
||||
|
||||
未就绪时:**不要硬调**,向用户报告缺哪一段。
|
||||
|
||||
本地 Turbo 的能力单独探测,不用 `image_generate_ready` 判断:
|
||||
|
||||
```http
|
||||
GET /api/local-images/status
|
||||
```
|
||||
|
||||
检查 `connected`、`ready` 和 `models.turbo.installed`;当前模型 ID 应为 `Qwen/Qwen-Image-2.1-Turbo`。`loaded_model=turbo` 表示已加载,`busy=true` 且 `loaded_model=null` 时通常正在首次加载,应先等待。`co_resident`、`hy3d_paused`、`available_gb` 用于观察驻留和内存状态。混元因图像模式暂时暂停时,图像队列空闲后先调用 `POST /api/local-images/prepare-3d`,再重新探测 DGX 能力。
|
||||
|
||||
### 1.1 Windows 跨机器部署:Hunyuan 绿灯、TokenRig/Kimodo 红灯
|
||||
|
||||
状态探测在 **运行 LLM3D 后端的 Windows 机器与账号**中执行,不在打开网页的浏览器机器执行。复制工程和 `config.json` 不会自动配置该账号的 SSH 别名、密钥授权、SSH Agent 和 `known_hosts`。
|
||||
|
||||
| 状态灯 | 当前探测内容 |
|
||||
|--------|--------------|
|
||||
| Hunyuan3D | HTTP GET `dgx.hy3d_url` 首页,5秒内状态码小于500算通过;没有执行造型推理 |
|
||||
| TokenRig | SSH 到 `dgx.ssh_host`,检查 SkinTokens 的入口脚本、可执行Python和两个固定权重文件;远程失败时另检查本机环境 |
|
||||
| Kimodo | SSH 到同一个主机,检查 `kimodo_gen`、Llama文本编码器目录和LLM2Vec配置;没有执行动作推理 |
|
||||
|
||||
因此模型可以仍在 DGXA 正常安装,却因新 Windows 后端的 SSH 环境不完整而显示红灯。绿灯也不表示权重已加载到 GPU。当前每个远程探测约12秒超时,SSH错误统一折叠为 `false`,状态缓存20秒;多个SSH失败串行发生时,能力接口可能等待约48秒。
|
||||
|
||||
在**部署机上,用启动 LLM3D 的同一个账号**,从 `LLM3DGraphics` 目录运行只读自检:
|
||||
|
||||
```powershell
|
||||
.\.venv\Scripts\python.exe .\deploy\check_dgx_connection.py --output .\outputs\dgx_connection_check.json
|
||||
```
|
||||
|
||||
脚本:[check_dgx_connection.py](./LLM3DGraphics/deploy/check_dgx_connection.py)。它检查账号、SSH解析配置、认证、远端各个文件及混元HTTP连接,不加载模型、不修改密钥或服务,不读取/打印私钥和API Key内容。
|
||||
|
||||
| 报告项 / 错误 | 排查方向 |
|
||||
|---------------|----------|
|
||||
| `account` | 是否确实为运行后端的账号;管理员终端和计划任务/服务账号可能不同 |
|
||||
| `resolved_ssh` | `hostname`、`user`、`port`、`identityfile` 是否指向该机可用的连接配置 |
|
||||
| `Could not resolve hostname` | 当前账号未配置 `DGXA` 别名,或DNS无法解析 |
|
||||
| `Permission denied (publickey)` | SSH用户、密钥文件、Agent或DGXA上的公钥授权不匹配 |
|
||||
| `Connection timed out/refused` | 地址、端口、路由、防火墙、代理或SSH服务问题 |
|
||||
| `Host key verification failed` | 用该账号交互登录并核对服务器指纹,完成主机身份确认 |
|
||||
| `remote.checks.*.ok=false` | SSH已连通;按报告中的具体路径检查文件或执行权限 |
|
||||
|
||||
若采用 `dgx.ssh_host=DGXA`,该Windows账号的 `%USERPROFILE%\.ssh\config` 必须有对应连接设置;使用新机器自己的已授权密钥,例如:
|
||||
|
||||
```text
|
||||
Host DGXA
|
||||
HostName <DGXA实际可达地址>
|
||||
User spark
|
||||
Port 22
|
||||
IdentityFile ~/.ssh/id_ed25519
|
||||
```
|
||||
|
||||
`IdentityFile` 以部署机实际密钥为准,DGXA需已授权对应公钥。先确认该账号执行 `ssh -o BatchMode=yes DGXA "echo READY"` 成功,再重启/刷新后端状态。私钥不放进工程或说明文件。部署机访问混元HTTP成功,不代表它能用SSH访问DGXA。
|
||||
|
||||
---
|
||||
|
||||
## 2. 引擎选择
|
||||
|
||||
`POST /api/jobs` 的 `engine` 二选一:
|
||||
|
||||
| `engine` | 高模从哪来 | 绑骨 / 动作 | 典型用途 |
|
||||
|----------|------------|-------------|----------|
|
||||
| **`dgx`** | Spark Hunyuan3D 2.1 | TokenRig + `/animate`(或 `static` 跳过) | 角色可驱动、要动作、DGX 静物 |
|
||||
| **`hunyuan`** | 腾讯混元3D**官方网页**(Playwright 自动化) | **无** | 只要官网网格质量;不依赖 Spark |
|
||||
|
||||
决策提示:
|
||||
|
||||
- 用户明确说「混元官网 / 混元网页 / 微信混元」→ `hunyuan`
|
||||
- 用户要「会动 / 绑骨 / Mixamo / UniMate」→ **必须 `dgx`**
|
||||
- 只要静物网格且 DGX 忙/未就绪 → 可降级 `hunyuan`
|
||||
- `character_type` **仅 `engine=dgx` 生效**;混元任务里该字段会被忽略
|
||||
|
||||
---
|
||||
|
||||
## 3. 混元3D 官方网页流程(`engine=hunyuan`)
|
||||
|
||||
走 [3d.hunyuan.tencent.com](https://3d.hunyuan.tencent.com/):服务端用 Playwright(Edge)提交图片生成;微信登录二维码显示在发起登录的客户端页面,由用户用自己的微信扫码。登录态按浏览器客户端隔离。
|
||||
|
||||
### 3.1 登录(客户端页面扫码,会话按客户端复用)
|
||||
|
||||
```http
|
||||
GET /api/hunyuan/status # logged_in?
|
||||
POST /api/hunyuan/login # 服务端启动登录;客户端页面显示二维码(约 3 分钟内)
|
||||
GET /api/hunyuan/login/qr # 读取当前客户端的二维码图片
|
||||
POST /api/hunyuan/logout # 清除当前客户端会话
|
||||
```
|
||||
|
||||
后端仍在服务机运行 Playwright,但不会要求用户去服务机窗口扫码。扫码二维码由客户端页面请求并显示。每个浏览器客户端通过独立的 HttpOnly Cookie 标识登录会话,服务端分别保存到 `data/hunyuan/clients/<客户端标识>/storage_state.json`。同一浏览器刷新后会复用登录态;不同设备、浏览器或无痕窗口需要分别扫码。生成任务使用提交请求的客户端登录态,退出登录只清除该客户端的会话。旧版共享文件 `data/hunyuan/storage_state.json` 不再使用。
|
||||
|
||||
Agent 侧:
|
||||
|
||||
1. 读 `capabilities.hunyuan_logged_in`(或 `/api/hunyuan/status`)
|
||||
2. 若为 `false`:让用户在要使用的浏览器客户端打开工作台并点击「微信登录」,在该页面显示的二维码上用自己的微信扫码;轮询该客户端的 status 至 `logged_in`。不要让用户去服务机窗口扫码。
|
||||
3. 未登录时提交 `engine=hunyuan` 会 **401**
|
||||
|
||||
直接用 HTTP 客户端接入时,必须在 `status`、`login`、`login/qr` 和生成请求之间保留同一个服务端下发的 HttpOnly Cookie;否则请求会被识别为不同客户端。需要把二维码安全地呈现给真人扫码,单纯的无状态 curl/Agent 调用不能代替用户完成登录。
|
||||
|
||||
### 3.2 生成任务
|
||||
|
||||
```http
|
||||
POST /api/jobs
|
||||
Content-Type: multipart/form-data
|
||||
|
||||
engine=hunyuan
|
||||
mode=image
|
||||
image=@ref.png
|
||||
source_faces=50000
|
||||
target_faces=5000
|
||||
texture_size=1024
|
||||
output_format=glb
|
||||
```
|
||||
|
||||
| 字段 | 说明 |
|
||||
|------|------|
|
||||
| `mode` | **仅 `image`**(混元网页引擎不接受 text) |
|
||||
| `source_faces` | 官网高模档:`5000`(5k)/ `20000`(20k)/ `50000`(50k)/ `500000` / `1000000`;常用 `50000`。5k 与 20k 页面无按钮,提交时改写 `faceCount` |
|
||||
| `target_faces` | 本机低模目标;`<500000` 且低于高模面数时触发 Blender 烘培 → `model_ex` |
|
||||
| `texture_size` | 低模烘培贴图:`512` / `1024` / `2048` |
|
||||
| `output_format` | `glb` 或 `fbx`(fbx 时额外打 ZIP) |
|
||||
| `character_type` | **无效**(不要指望混元出绑骨) |
|
||||
|
||||
轮询 `GET /api/jobs/{id}` → `status=completed`。
|
||||
|
||||
### 3.3 产物(网格 only)
|
||||
|
||||
| 下载键 | 含义 |
|
||||
|--------|------|
|
||||
| `glb` / `fbx` | 官网高模 |
|
||||
| `glb_ex` / `fbx_ex` | 本机低模+烘培(若触发) |
|
||||
| `preview_url` | 网页预览 |
|
||||
|
||||
**不要**调用 `/animate`。若后续仍要动作:把混元网格当作参考图/资产另开 `engine=dgx` 流程(当前无「混元网格直接喂 TokenRig」的一键接口;需要绑骨请直接用 DGX 图生)。
|
||||
|
||||
### 3.4 耗时与依赖
|
||||
|
||||
- 官网生成常见数分钟~约 20 分钟;另加本机低模烘培时间
|
||||
- 依赖:服务端 Playwright + Edge 通道、当前客户端有效的微信登录态、可选 Blender(低模/FBX)
|
||||
- 与 DGX 共用同一任务队列(≤5)
|
||||
|
||||
### 3.5 curl 示例
|
||||
|
||||
```bash
|
||||
BASE=http://192.168.130.16:8008
|
||||
|
||||
# 确认登录
|
||||
curl -s "$BASE/api/hunyuan/status"
|
||||
|
||||
# 未登录时:先在工作台当前客户端点击「微信登录」,再由真人扫描页面上的二维码。
|
||||
# 纯 curl 示例需要持久化 Cookie,并自行将二维码呈现给真人;不要只靠无状态 curl 完成扫码登录。
|
||||
# curl -s -X POST "$BASE/api/hunyuan/login"
|
||||
|
||||
curl -s -X POST "$BASE/api/jobs" -F engine=hunyuan -F mode=image -F source_faces=50000 -F target_faces=5000 -F texture_size=1024 -F image=@ref.png
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. 生成参考图:本地 Turbo 与云端转接
|
||||
|
||||
DGX **不能直接文生 3D**。用户只给文字外貌时,先通过 **§4.4 本地 Turbo** 生成图片,再交给 §6 的 DGX 编排剧本。用户选择云端生图时使用下述 §4.1–4.3 转接接口;两条生图路径都通过 LLM3DGraphics 调度。
|
||||
|
||||
| 角色 | 说明 |
|
||||
|------|------|
|
||||
| **外部项目 / Agent** | 云端路径只调 `POST /api/image/generate`,**不要**拿上游 Key、**不要**直连 grsai;本地路径见 §4.4 |
|
||||
| **本机服务** | 用 `config.json` → `dgx.grsai`(或环境变量 `GRSAI_API_KEY`)调上游,并把结果缓存到本机 |
|
||||
| 运维配置参考 | [生成路径.md](./生成路径.md)、[HelpDoc/gpt-image_doc.md](./HelpDoc/gpt-image_doc.md)(仅服务器侧) |
|
||||
|
||||
探测:`GET /api/capabilities` → `image_generate_ready == true`。
|
||||
|
||||
### 4.1 转接接口
|
||||
|
||||
```http
|
||||
POST {BASE}/api/image/generate
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"prompt": "一只棕色四足狼,全身正面三视图感,纯白背景,游戏概念设定图,无文字水印",
|
||||
"aspect_ratio": "1:1",
|
||||
"quality": "auto",
|
||||
"images": []
|
||||
}
|
||||
```
|
||||
|
||||
| 字段 | 必填 | 说明 |
|
||||
|------|------|------|
|
||||
| `prompt` | 是 | 外貌描述,≤4000 字 |
|
||||
| `aspect_ratio` | 否 | 默认用服务端 `dgx.grsai.aspect_ratio`(常见 `1:1`) |
|
||||
| `quality` | 否 | 默认 `auto` |
|
||||
| `images` | 否 | 图生图参考:URL 或 data URL / base64,最多 4 张 |
|
||||
|
||||
成功响应(**不含**上游 URL / API Key):
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "a1b2c3...",
|
||||
"status": "succeeded",
|
||||
"url": "/api/image/a1b2c3...",
|
||||
"content_type": "image/png",
|
||||
"bytes": 123456,
|
||||
"model": "gpt-image-2.5",
|
||||
"aspect_ratio": "1:1"
|
||||
}
|
||||
```
|
||||
|
||||
下载图片:
|
||||
|
||||
```http
|
||||
GET {BASE}/api/image/{id}
|
||||
```
|
||||
|
||||
将该文件作为后续 `POST /api/jobs` 的 `image` 上传即可。
|
||||
|
||||
**给 DGX 的构图建议**(提高绑骨成功率):
|
||||
|
||||
- 主体居中、轮廓清晰;尽量白底或简单底
|
||||
- 全身可见;角色类避免极端透视 / 大面积遮挡
|
||||
- 提示词写清物种、体态、材质;少杂乱场景文字
|
||||
|
||||
### 4.2 curl / Python 示例(外部只打本机)
|
||||
|
||||
```bash
|
||||
BASE=http://192.168.130.16:8008
|
||||
|
||||
curl -s -X POST "$BASE/api/image/generate" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{
|
||||
"prompt": "石质庭院灯笼,白色背景,产品设定图",
|
||||
"aspect_ratio": "1:1"
|
||||
}'
|
||||
|
||||
# 记下返回的 id / url,再下载:
|
||||
curl -L -o prop.png "$BASE/api/image/<id>"
|
||||
```
|
||||
|
||||
```python
|
||||
import requests
|
||||
from pathlib import Path
|
||||
|
||||
BASE = "http://192.168.130.16:8008"
|
||||
|
||||
def text_to_image(prompt: str, out_path: Path, aspect_ratio: str = "1:1") -> Path:
|
||||
r = requests.post(
|
||||
f"{BASE}/api/image/generate",
|
||||
json={"prompt": prompt, "aspect_ratio": aspect_ratio},
|
||||
timeout=300,
|
||||
)
|
||||
r.raise_for_status()
|
||||
data = r.json()
|
||||
if data.get("status") != "succeeded" or not data.get("url"):
|
||||
raise RuntimeError(data)
|
||||
url = data["url"]
|
||||
if url.startswith("/"):
|
||||
url = BASE + url
|
||||
img = requests.get(url, timeout=120)
|
||||
img.raise_for_status()
|
||||
out_path.write_bytes(img.content)
|
||||
return out_path
|
||||
```
|
||||
|
||||
### 4.3 服务器侧配置(仅运维,不对外部暴露)
|
||||
|
||||
在本机 `LLM3DGraphics/config.json`(已 gitignore)中配置,例如:
|
||||
|
||||
```json
|
||||
"dgx": {
|
||||
"grsai": {
|
||||
"api_key": "<密钥,见生成路径.md>",
|
||||
"model": "gpt-image-2.5",
|
||||
"bases": ["https://grsai.dakka.com.cn", "https://grsaiapi.com"],
|
||||
"aspect_ratio": "1:1",
|
||||
"quality": "auto"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
也可用环境变量 `GRSAI_API_KEY` / `GPT_IMAGE_API_KEY`。外部调用方**无需**知道这些。
|
||||
|
||||
### 4.4 本地图像生成:Qwen-Image-2.1-Turbo BF16(当前推荐流程)
|
||||
|
||||
更新于 **2026-10-13**。当前只安装 `Qwen/Qwen-Image-2.1-Turbo`,原生 8 步采样、CFG=1,支持文生图、最多 10 张参考图编辑和 RGBA 输出。Qwen-Image-2512、Qwen-Image-2.1 标准版及专用缓存已移除;不要提交 `model=quality` 或重新安装退役模型。
|
||||
|
||||
网页入口:`{BASE}/#local-images`。图片和任务记录保存在 Windows `LLM3DGraphics/data/_local_images/<批次ID>/`,推理在 DGXA 的 `/home/spark/llm3d-local-images/` 中运行。调用方只访问 **Windows LLM3DGraphics API**,本地路径不需要云端 Key。
|
||||
|
||||
#### 4.4.1 页面操作与提示词方法
|
||||
|
||||
1. 打开「本地图像生成」,确认 Turbo 已安装并完成首次加载。
|
||||
2. 选择素材用途,填写画面描述。纯文字生成不上传参考图;参考编辑上传实际图片文件,按输入顺序写明“图1提供造型、图2提供配色、图3提供风格”。
|
||||
3. 先用 512–1024 分辨率、4–8 张草稿选方向;固定 seed 便于迭代,每张图的 seed 自动递增。
|
||||
4. 点击“作为参考继续编辑”将选中的生成图作为新参考,提高分辨率并描述局部修改;“复用参数”可恢复原批次的提示词、参考图、用途、尺寸和种子。
|
||||
5. 需要 3D 时选择一张轮廓清晰的完整主体图,点击“送到 DGX 3D”,再按 §6 选择 `character_type` 并提交 3D。这个按钮负责填入图片,不会直接开始 3D 生成。
|
||||
6. 需要 2D 素材时勾选图片并导出 Unity ZIP,见 §4.4.4。
|
||||
|
||||
提示词按“参考图职责 → 主体 → 画风/摄影 → 姿势与构图 → 背景 → 保持项与修改项”组织。负面限制也写进主提示词,`negative_prompt` 留空。
|
||||
|
||||
| 需求 | 提示词重点与用途 |
|
||||
|------|----------------|
|
||||
| 换角色、保留参考画风 | “保留图1的画风与构图,将角色改为……;重新绘制脸、头发、衣服和年龄特征。”明确哪些保持、哪些改变 |
|
||||
| 人形 3D 参考图 | “正面全身 T-pose,双臂水平伸直,头、手指、鞋完整入画,四周留白,纯白背景,无道具和遮挡。”严格正面姿势可用 `sprite` 并明确完整角色;`concept` 会追加三分之四视角要求 |
|
||||
| 真人街角照片 | “真实街头摄影,自然儿童/成人比例,日常便服,自然站姿,街角建筑和路面,真实肤色与布料纹理。”选择 `background`,避免追加白底设定图要求 |
|
||||
| 透明图标/精灵 | 选择 `sprite`、`transparent=true`,说明独立主体、透明背景、轮廓清楚;下载后检查实际 Alpha |
|
||||
|
||||
后端会追加所选用途的提示词,因此用途必须与目标一致。白底不是透明背景;页面显示的“含透明像素”才来自实际 Alpha 检查。街角场景照片适合作为图片素材或视觉参考;要生成独立 3D 角色时另生成简单背景、完整主体的参考图。
|
||||
|
||||
#### 4.4.2 图片任务接口与参数
|
||||
|
||||
```http
|
||||
POST {BASE}/api/local-images/jobs
|
||||
Content-Type: multipart/form-data
|
||||
|
||||
model=turbo
|
||||
profile=sprite
|
||||
prompt=保留图1的二维手绘风格,改为10岁运动装小男孩,正面全身T-pose,双手和鞋完整入画,纯白背景,无文字
|
||||
width=1024
|
||||
height=1504
|
||||
count=4
|
||||
seed=314159
|
||||
transparent=false
|
||||
negative_prompt=
|
||||
images=@style_reference.png
|
||||
```
|
||||
|
||||
| 字段 | 默认 / 范围 | 说明 |
|
||||
|------|-------------|------|
|
||||
| `model` | `turbo`,唯一支持值 | 对应 `Qwen/Qwen-Image-2.1-Turbo` BF16;步数和采样由 worker 固定,不传 `quality`、CFG 或步数 |
|
||||
| `prompt` | 必填,1–4000 字 | 画面与编辑要求;限制条件也写在这里 |
|
||||
| `profile` | 默认 `concept` | `concept`:完整 3D 主体、三分之四视角、纯色背景;`sprite`:独立精灵/UI、居中留白;`albedo`:平铺 base color;`background`:场景背景 |
|
||||
| `width` / `height` | 默认 1024;256–2048 | 都必须为 32 的倍数;人物竖图可用 1024×1504 |
|
||||
| `count` | 默认 4;1–16 | 一个批次逐张生成;最多同时排队 4 批 |
|
||||
| `seed` | 默认 -1;-1 或 0–4294967280 | -1 随机起点;第 i 张使用起点+i,i 从 0 开始 |
|
||||
| `transparent` | 默认 `false` | `true` 追加透明 RGBA 要求,仍需检查实际 Alpha |
|
||||
| `negative_prompt` | 空字符串 | CFG=1 不使用负面提示词;非空返回 422 |
|
||||
| `images` | 可省略,最多 10 个同名文件字段 | 传 PNG/JPEG/WebP 实际文件,不传 URL/base64 字符串;每张 ≤12MB、≤1600万像素,归一化最长边1536并保留 Alpha |
|
||||
|
||||
纯文生图省略 `images` 即可;无文件时也支持表单编码,**不是 JSON 请求体**。提交返回 **202** 和图片批次 `id`,轮询 `GET /api/local-images/jobs/{id}` 至 `completed` / `failed`。该 `id` 与之后创建的 3D job ID 不同。
|
||||
|
||||
结果从 `images` 数组取,不从 3D 的 `downloads` 取:每项含 `index`、实际 `seed`、`has_alpha`、`url`。PNG 路径为 `/api/local-images/jobs/{id}/images/{index}`;参考图路径为 `/api/local-images/jobs/{id}/references/{index}`。`failed` 批次也可能已有可下载图片,应保存结果和错误记录。
|
||||
|
||||
#### 4.4.3 curl 与 Python:生成、下载、转入 3D
|
||||
|
||||
```bash
|
||||
BASE=http://192.168.130.16:8008
|
||||
|
||||
curl -s "$BASE/api/local-images/status"
|
||||
|
||||
# 多参考图编辑;纯文生图时省略两个 images 字段
|
||||
curl -s -X POST "$BASE/api/local-images/jobs" \
|
||||
-F model=turbo -F profile=sprite \
|
||||
-F 'prompt=图1提供角色造型,图2提供配色。生成完整角色的正面全身T-pose,纯白背景,无文字。' \
|
||||
-F width=1024 -F height=1504 -F count=4 -F seed=314159 \
|
||||
-F transparent=false \
|
||||
-F 'images=@shape.png' -F 'images=@palette.png'
|
||||
|
||||
# IMG_JOB 替换为图片批次 id;轮询间隔至少2秒
|
||||
curl -s "$BASE/api/local-images/jobs/$IMG_JOB"
|
||||
curl -fL -o selected.png "$BASE/api/local-images/jobs/$IMG_JOB/images/0"
|
||||
|
||||
# 所有图像批次结束后准备DGX 3D;返回409时等待,不绕过保护
|
||||
curl -s -X POST "$BASE/api/local-images/prepare-3d"
|
||||
curl -s -X POST "$BASE/api/jobs" \
|
||||
-F engine=dgx -F mode=image -F character_type=humanoid \
|
||||
-F target_faces=5000 -F texture_size=1024 -F output_format=glb \
|
||||
-F 'image=@selected.png'
|
||||
```
|
||||
|
||||
Windows PowerShell 使用 `curl.exe` 或下述 Python 示例,避免将 PowerShell 的 `curl` 别名当作上述 Bash 命令。
|
||||
|
||||
```python
|
||||
import json
|
||||
import mimetypes
|
||||
import time
|
||||
from contextlib import ExitStack
|
||||
from pathlib import Path
|
||||
|
||||
import requests
|
||||
|
||||
BASE = "http://192.168.130.16:8008"
|
||||
|
||||
|
||||
def local_images(prompt, out_dir, references=(), *, profile="sprite",
|
||||
width=1024, height=1504, count=4, seed=314159,
|
||||
transparent=False, timeout=1800):
|
||||
with requests.Session() as session:
|
||||
response = session.get(f"{BASE}/api/local-images/status", timeout=20)
|
||||
response.raise_for_status()
|
||||
state = response.json()
|
||||
if not (state.get("connected") and state.get("ready")
|
||||
and state.get("models", {}).get("turbo", {}).get("installed")):
|
||||
raise RuntimeError(state)
|
||||
load_deadline = time.monotonic() + timeout
|
||||
while state.get("busy") and not state.get("loaded_model"):
|
||||
if time.monotonic() > load_deadline:
|
||||
raise TimeoutError("Turbo 尚未完成首次加载")
|
||||
time.sleep(2)
|
||||
response = session.get(f"{BASE}/api/local-images/status", timeout=20)
|
||||
response.raise_for_status()
|
||||
state = response.json()
|
||||
data = dict(model="turbo", prompt=prompt, profile=profile,
|
||||
width=width, height=height, count=count, seed=seed,
|
||||
transparent=str(transparent).lower(), negative_prompt="")
|
||||
with ExitStack() as stack:
|
||||
files = []
|
||||
for item in references:
|
||||
path = Path(item)
|
||||
mime = mimetypes.guess_type(path.name)[0] or "application/octet-stream"
|
||||
files.append(("images", (path.name, stack.enter_context(path.open("rb")), mime)))
|
||||
response = session.post(f"{BASE}/api/local-images/jobs",
|
||||
data=data, files=files or None, timeout=30)
|
||||
response.raise_for_status()
|
||||
job = response.json()
|
||||
folder = Path(out_dir) / job["id"]
|
||||
folder.mkdir(parents=True, exist_ok=True)
|
||||
record = folder / "job.json"
|
||||
deadline = time.monotonic() + timeout
|
||||
while True:
|
||||
record.write_text(json.dumps(job, ensure_ascii=False, indent=2), encoding="utf-8")
|
||||
if job["status"] in ("completed", "failed"):
|
||||
break
|
||||
if time.monotonic() > deadline:
|
||||
raise TimeoutError(f"图片任务仍在运行,记录见 {record}")
|
||||
time.sleep(2)
|
||||
response = session.get(f"{BASE}/api/local-images/jobs/{job['id']}", timeout=30)
|
||||
response.raise_for_status()
|
||||
job = response.json()
|
||||
paths = []
|
||||
for image in job["images"]:
|
||||
response = session.get(BASE + image["url"], timeout=120)
|
||||
response.raise_for_status()
|
||||
path = folder / f"image_{image['index']}_seed_{image['seed']}.png"
|
||||
path.write_bytes(response.content)
|
||||
paths.append(path)
|
||||
if job["status"] != "completed":
|
||||
raise RuntimeError(f"{job.get('error')};已保存 {len(paths)} 张图片,记录见 {record}")
|
||||
return job, paths
|
||||
|
||||
|
||||
# 多参考编辑:references=["style.png", "colors.png"];文生图不传 references。
|
||||
# image_job, paths = local_images(
|
||||
# "蓝色运动装小男孩,二维手绘,正面全身T-pose,纯白背景,无文字",
|
||||
# "generated", references=["style.png"], count=4)
|
||||
# 人工或上游选定 paths 中一张,再交给 §9.2 create_rigged。
|
||||
# 转入DGX前:requests.post(f"{BASE}/api/local-images/prepare-3d", timeout=360).raise_for_status()
|
||||
# rig_job = create_rigged(paths[0], "humanoid")
|
||||
```
|
||||
|
||||
图片下载后逐张检查主体、年龄/物种、姿势、手脚完整度、背景和伪影。批量固定种子是便于复现,不保证每张满足全部要求。需要精确 `#FFFFFF` 背景时另做背景清理,并保留原始输出。真人测试使用 `profile=background`,例如“约10岁小女孩,日常便服,自然站姿,真实街角建筑与人行道,午后自然光,真实肤色和服装纹理”。
|
||||
|
||||
#### 4.4.4 Unity 导出与 3D 转接
|
||||
|
||||
下载选中图片和参数:`GET /api/local-images/jobs/{id}/unity?selected=0,2`。`selected` 是以逗号分隔的图片索引;省略时导出该批次全部已生成图片。
|
||||
|
||||
ZIP 内含 `Assets/LLM3DGenerated/<批次ID>/` 下的 PNG、参考图和 `manifest.json`,以及 `Assets/Editor/LLM3DImageImporter.cs`。将 Assets 合并到 Unity 工程,保留目录结构:
|
||||
|
||||
| 用途 | Unity 导入设置 |
|
||||
|------|----------------|
|
||||
| `sprite` | Sprite / Single,sRGB,Clamp,不生成 Mipmap,PPU=100,保留 Alpha |
|
||||
| `albedo` | Default,sRGB,Repeat,生成 Mipmap;检查平铺接缝 |
|
||||
| `concept` / `background` | Default,sRGB,Clamp,不生成 Mipmap,Max Size 2048 |
|
||||
|
||||
若导入顺序导致设置尚未应用,选中生成图片后执行 `Assets > LLM3D > Apply image import settings`。这是 ZIP 素材包,不是 `.unitypackage`;生成色彩图不是完整 PBR,也不是自动切片的 Sprite Sheet。3D 贴图继续走现有 UV、烘焙和 PBR 流程。
|
||||
|
||||
转入 3D 必须下载 PNG 后作为 `/api/jobs` 的 `image` 文件上传;图片批次 id 不能替代 3D job id。`prepare-3d` 只检查/恢复资源,不创建 3D 任务;§6 的建模、绑骨和动作步骤照常执行。
|
||||
|
||||
#### 4.4.5 共同驻留、内存兜底与实测耗时
|
||||
|
||||
当前配置为 `auto_switch=true`、`co_resident=true`。用户级服务 `llm3d-qwen.service` 启动时在后台预加载 Turbo;已有工作忙碌时跳过预加载。Turbo GPU 常驻约 32GiB。**共同驻留不等于并行生成**:混元、ComfyUI 和本机图像队列均通过预约与队列保护串行使用;图像批次结束后释放预约。
|
||||
|
||||
| 场景 | 当前策略 |
|
||||
|------|----------|
|
||||
| 图像生成,Turbo 已加载 | 可用内存至少 24GiB 时保留混元;不足时释放 ComfyUI 缓存并暂停本流程拥有的混元服务 |
|
||||
| 首次加载 Turbo | 共享模式要求可用内存至少为 Turbo 权重大小 + 12GiB |
|
||||
| 准备 DGX 3D,混元已运行 | 可用内存至少 32GiB 时保留 Turbo;不足则先释放 Turbo |
|
||||
| 需要启动被暂停的混元 | 至少 72GiB 可用内存才同时保留 Turbo,否则先释放 Turbo |
|
||||
| 3D/动作加载期间出现内存压力 | 每秒检查;可用内存低于16GiB且 Turbo 空闲、无图像预约时自动释放 Turbo |
|
||||
|
||||
调用方通过 `POST /api/local-images/prepare-3d` 让调度器决定,响应 `images_retained=true` 表示本次准备保留了 Turbo。需要手动释放时,在图像队列空闲后调用 `POST /api/local-images/unload`。不要停止其他用户任务、手动操作 Docker 或绕过 8090 的资源保护。
|
||||
|
||||
2026-10-13 的实测(不是固定 SLA):
|
||||
|
||||
| 测试 | 耗时口径 |
|
||||
|------|----------|
|
||||
| 512×512,多参考透明图标 | 8步去噪约6–7秒/张,不含加载和编码/解码 |
|
||||
| 1024×1504,全身角色参考图编辑 | 8步去噪约21秒/张 |
|
||||
| 1024×1504,真人街角文生图 | 8步去噪约18秒;该次含换模加载总耗时约226秒 |
|
||||
| Turbo 已加载、与混元共同驻留,连续两张512×512文生图 | 提交至保存合计约8.2秒,无参考图 |
|
||||
| 同时保留 Turbo,混元造型+贴图 | 128抽取分辨率、静态分支约158秒,40,000面带贴图GLB;采样最低可用内存约31.9GiB |
|
||||
|
||||
首次加载可能需要数分钟;参考图数量、提示词长度、分辨率和场景都会改变耗时。上述3D测试没有调用 TokenRig/UniMate,不能据此保证所有动作模型或最高分辨率都能同时驻留,它们仍沿用按需加载。
|
||||
|
||||
详细部署、服务维护和验证说明见 [本地图像生成与 Unity 素材流程](./LLM3DGraphics/docs/local-image-generation.md);本次证据见 [常驻验证说明](./LLM3DGraphics/outputs/turbo_residency_20261013/常驻验证说明.txt)。服务机维护脚本在 `LLM3DGraphics/deploy/local_images/`,运行记录为 DGXA 的 `worker.log`;维护需等待相关队列空闲。Turbo 使用研究/评估许可,许可链接及商业使用约束见上述模型说明。
|
||||
|
||||
---
|
||||
|
||||
## 5. 意图 → 参数映射(给 Agent 的决策表)
|
||||
|
||||
从用户描述里抽出:`asset_kind`、`character_type`、`reference_image`、`motions[]`。
|
||||
|
||||
### 5.1 资产类型
|
||||
|
||||
| 判断 | `character_type` | 后续 |
|
||||
|------|------------------|------|
|
||||
| 道具 / 建筑 / 静物 / 「不要骨骼」 | `static` | 只 Step1,下载 `glb` / `glb_ex` |
|
||||
| 标准双足人、士兵、NPC 人型 | `humanoid` | Step1 + Step2(Kimodo 文生) |
|
||||
| 四足、怪、非标拓扑生物 | `non_humanoid` | Step1 + Step2(UniMate 文生) |
|
||||
|
||||
不确定时:有四肢且明显非人 → `non_humanoid`;明确是人 → `humanoid`;无生命 / 场景件 → `static`。
|
||||
|
||||
### 5.2 参考图从哪来
|
||||
|
||||
| 情况 | 做法 |
|
||||
|------|------|
|
||||
| 用户已给图 | 直接作 `POST /api/jobs` 的 `image` |
|
||||
| 用户只有文字外貌 | **§4.4 本地 Turbo** → 选图 → 再选 `dgx` / `hunyuan`;选择云端时用 §4.1 |
|
||||
| 用户给多张风格/造型参考 | §4.4 按顺序上传 `images`,描述各图职责 → 选图 → 上传到 3D |
|
||||
| 只要图片、图标或场景背景 | §4.4 → PNG / Unity ZIP,流程在图片阶段结束 |
|
||||
| 既要外貌又要动作 | §4.4 文生图 → **必须 `engine=dgx`** → Step1 → Step2 |
|
||||
| 明确要混元官网质量、不要骨骼 | §4(如需)→ **`engine=hunyuan`**(§3) |
|
||||
|
||||
### 5.3 动作列表
|
||||
|
||||
- 用户说「idle、跑、跳」→ 拆成 `motions = ["idle 待机", "四足原地跑步", "原地跳跃"]`(示例),**每个一条** `motion_prompt`。
|
||||
- 人形:交给 Kimodo,写清动作(走、跑、挥手等)。
|
||||
- 非人形:写清主体与动作,可加「原地」「可循环」;中文即可(服务端会规范成英文)。
|
||||
|
||||
---
|
||||
|
||||
## 6. 标准编排剧本(主要为 engine=dgx)
|
||||
|
||||
### 剧本 A — 角色模型 + 若干动作(最常见)
|
||||
|
||||
```
|
||||
输入: reference_image, character_type, motions[1..N], (可选) target_faces
|
||||
输出: rigged 角色 + 每个动作对应的 animated 文件(注意覆盖问题)
|
||||
```
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
A[参考图] --> B["POST /api/jobs<br/>engine=dgx"]
|
||||
B --> C{轮询 completed<br/>ready_for_motion}
|
||||
C --> D["POST .../animate<br/>motion_prompt_1"]
|
||||
D --> E[下载 animated.*]
|
||||
E --> F["animate motion_2 ..."]
|
||||
```
|
||||
|
||||
**Step 1**
|
||||
|
||||
```http
|
||||
POST /api/jobs
|
||||
Content-Type: multipart/form-data
|
||||
|
||||
engine=dgx
|
||||
mode=image
|
||||
character_type=non_humanoid # 或 humanoid
|
||||
output_format=glb # Unity 需要网格 FBX 包时用 fbx
|
||||
target_faces=5000 # 游戏向低模;只要高模可调极大面数跳过减面
|
||||
texture_size=1024
|
||||
image=@character.png
|
||||
```
|
||||
|
||||
响应 `202` → 记下 `id`。轮询:
|
||||
|
||||
```http
|
||||
GET /api/jobs/{id}
|
||||
```
|
||||
|
||||
直到 `status == "completed"` 且 `ready_for_motion == true`。
|
||||
|
||||
推荐下载(角色):
|
||||
|
||||
| 用途 | `downloads` 键 / 路径 |
|
||||
|------|------------------------|
|
||||
| 非人形 Unity 角色 | `rigged_fbx`(ZIP,内含 `model.fbx`)或 `rigged_glb` |
|
||||
| 人形 | `mixamo_glb` / 对应 mixamo FBX |
|
||||
| 网页预览 | `preview_url` |
|
||||
|
||||
**Step 2(每个动作一次)**
|
||||
|
||||
```http
|
||||
POST /api/jobs/{id}/animate
|
||||
Content-Type: multipart/form-data
|
||||
|
||||
motion_prompt=四足动物原地跑步,可循环
|
||||
```
|
||||
|
||||
再轮询至 `completed`,下载:
|
||||
|
||||
| 用途 | 键 |
|
||||
|------|-----|
|
||||
| Unity 动画(骨架+动画,无角色网格) | `animated_fbx` / `animated_glb` |
|
||||
| 带皮预览(可选) | `anim_preview_url` |
|
||||
|
||||
**多动作注意**:服务端同一 job 目录里 `animated.glb` / `animated.fbx` 会被**覆盖**。Agent 应:
|
||||
|
||||
1. 每个动作完成后立刻下载并重命名保存(如 `{job_id}_run.fbx`);或
|
||||
2. 告知用户「当前接口一次只保留最新动画」,由上游自行归档。
|
||||
|
||||
### 剧本 B — 静态物体(道具)
|
||||
|
||||
```http
|
||||
POST /api/jobs
|
||||
engine=dgx
|
||||
mode=image
|
||||
character_type=static
|
||||
target_faces=20000
|
||||
image=@prop.png
|
||||
```
|
||||
|
||||
完成标志:`status=completed`,`ready_for_motion=false`,有 `downloads.glb`(及可选 `glb_ex`)。
|
||||
**禁止**调用 `/animate`。
|
||||
|
||||
### 剧本 C — 「一句话」端到端(文生图 + 角色 + 动作)
|
||||
|
||||
伪代码(给 Agent / 编排层):
|
||||
|
||||
```text
|
||||
parse(user_text) -> {
|
||||
appearance_prompt, # 外貌,给文生图
|
||||
character_type, # static | humanoid | non_humanoid
|
||||
motions[] # 可为空
|
||||
}
|
||||
|
||||
image_job, image_paths = local_images(appearance_prompt, "generated") # §4.4函数已轮询并下载
|
||||
image = select_image(image_paths) # 从保存的PNG中选一张;底层下载地址为images[].url
|
||||
wait_until_all_image_batches_idle()
|
||||
POST /api/local-images/prepare-3d # 内存允许时保留Turbo,否则自动切换
|
||||
# 用户选择云端时,上述生图步骤改用 §4.1 POST /api/image/generate
|
||||
|
||||
job = POST /api/jobs (engine=dgx, image=image, character_type=...)
|
||||
wait_until(job, completed)
|
||||
|
||||
if character_type == static:
|
||||
return download(job, ["glb", "glb_ex"])
|
||||
|
||||
assert job.ready_for_motion
|
||||
assets = { "rig": download(job, ["rigged_fbx", "rigged_glb"]) }
|
||||
|
||||
for m in motions:
|
||||
POST /api/jobs/{id}/animate (motion_prompt=m)
|
||||
wait_until(job, completed)
|
||||
assets[m] = download(job, ["animated_fbx", "animated_glb"]) # 立刻另存
|
||||
|
||||
return assets
|
||||
```
|
||||
|
||||
### 剧本 D — 只要模型、稍后再加动作
|
||||
|
||||
1. 只跑 Step1(`engine=dgx`),把 `job_id` 存进你们的数据库。
|
||||
2. 之后任意时刻对**同一** `job_id` 调 `/animate`(任务须已 `completed` 且仍有绑骨文件)。
|
||||
|
||||
### 剧本 E — 混元官网只要网格
|
||||
|
||||
```
|
||||
确认 hunyuan_logged_in
|
||||
→(可选)§4 文生图
|
||||
→ POST /api/jobs engine=hunyuan
|
||||
→ 下载 glb / glb_ex
|
||||
→ 禁止 animate
|
||||
```
|
||||
|
||||
细节见 §3。
|
||||
|
||||
---
|
||||
|
||||
## 7. 轮询与状态机
|
||||
|
||||
| `status` | 含义 | Agent 行为 |
|
||||
|----------|------|------------|
|
||||
| `queued` / `running` | 进行中 | 读 `stage`、`progress` 展示;继续轮询 |
|
||||
| `completed` | 成功 | 读 `downloads` / `ready_for_motion` |
|
||||
| `failed` | 失败 | 拉 `GET /api/jobs/{id}/log`;部分文件可能仍可下 |
|
||||
|
||||
建议:`sleep(2~5s)`;Step1(含 HY3D+TokenRig)常 5–20+ 分钟;UniMate 动画常 10–40+ 分钟。设超时并向上游报 `stage`。
|
||||
|
||||
本地图像批次也使用 `queued/running/completed/failed`,但轮询路径是 `/api/local-images/jobs/{id}`,输出读取 `images[].url`。即使 `failed` 也保存已完成图片和 `error`;超时只停止调用方等待,不会取消服务端任务,不要立即重复提交。转入 DGX 前,等待所有图像批次空闲;`prepare-3d` 返回409时继续等待。
|
||||
|
||||
---
|
||||
|
||||
## 8. 下载键速查
|
||||
|
||||
相对路径:`GET /api/jobs/{id}/files/{format}`(或直接用响应里的 `downloads.*` URL)。
|
||||
|
||||
| format | 内容 | 典型消费者 |
|
||||
|--------|------|------------|
|
||||
| `glb` | 高模 | 预览 / 静态 |
|
||||
| `glb_ex` | 低模+烘培 | 游戏 / 静态低模 |
|
||||
| `rigged_glb` | 绑骨+蒙皮 | 非人形预览 / 再动画 |
|
||||
| `rigged_fbx` | ZIP:`model.fbx`+贴图 | Unity 角色 |
|
||||
| `mixamo_glb` | 人形可驱动 | 人形再动画 |
|
||||
| `animated_glb` / `animated_fbx` | 骨架+动画(精简) | Unity Animator |
|
||||
| (`anim_preview_url`) | 蒙皮动画预览 | 仅预览,勿当生产动画源 |
|
||||
|
||||
Unity 非人形:**角色**用 `rigged_fbx` 内 `model.fbx`,**动画**用精简 `animated.fbx`,骨架路径对齐 `Armature/bone_*`。细节见 `DGX3D生成说明.md` §5。
|
||||
|
||||
---
|
||||
|
||||
## 9. 调用示例
|
||||
|
||||
### 9.1 curl(DGX,已有参考图)
|
||||
|
||||
```bash
|
||||
BASE=http://192.168.130.16:8008
|
||||
|
||||
# Step 1
|
||||
curl -s -X POST "$BASE/api/jobs" \
|
||||
-F engine=dgx -F mode=image \
|
||||
-F character_type=non_humanoid \
|
||||
-F target_faces=5000 -F texture_size=1024 \
|
||||
-F image=@./wolf.png
|
||||
|
||||
# 轮询(把 JOB 换成返回的 id)
|
||||
curl -s "$BASE/api/jobs/$JOB"
|
||||
|
||||
# Step 2
|
||||
curl -s -X POST "$BASE/api/jobs/$JOB/animate" \
|
||||
-F "motion_prompt=四足动物原地跑步,可循环"
|
||||
|
||||
# 下载
|
||||
curl -L -o wolf_rig.zip "$BASE/api/jobs/$JOB/files/rigged_fbx"
|
||||
curl -L -o wolf_run.fbx "$BASE/api/jobs/$JOB/files/animated_fbx"
|
||||
```
|
||||
|
||||
### 9.2 Python(文生图 + DGX 最小编排)
|
||||
|
||||
```python
|
||||
import time, requests
|
||||
from pathlib import Path
|
||||
|
||||
# 本地生图函数 local_images 见 §4.4.3;云端函数 text_to_image 见 §4.2。
|
||||
BASE = "http://192.168.130.16:8008"
|
||||
|
||||
def wait_job(job_id, timeout=7200):
|
||||
t0 = time.time()
|
||||
while time.time() - t0 < timeout:
|
||||
j = requests.get(f"{BASE}/api/jobs/{job_id}").json()
|
||||
if j["status"] in ("completed", "failed"):
|
||||
return j
|
||||
time.sleep(3)
|
||||
raise TimeoutError(job_id)
|
||||
|
||||
def create_rigged(image_path, character_type="non_humanoid"):
|
||||
with open(image_path, "rb") as f:
|
||||
r = requests.post(
|
||||
f"{BASE}/api/jobs",
|
||||
files={"image": f},
|
||||
data={
|
||||
"engine": "dgx",
|
||||
"mode": "image",
|
||||
"character_type": character_type,
|
||||
"target_faces": "5000",
|
||||
"texture_size": "1024",
|
||||
"output_format": "glb",
|
||||
},
|
||||
)
|
||||
r.raise_for_status()
|
||||
job_id = r.json()["id"]
|
||||
job = wait_job(job_id)
|
||||
if job["status"] != "completed" or not job.get("ready_for_motion"):
|
||||
raise RuntimeError(job.get("error") or job)
|
||||
return job
|
||||
|
||||
def animate_and_save(job_id, motion_prompt, out_fbx):
|
||||
r = requests.post(
|
||||
f"{BASE}/api/jobs/{job_id}/animate",
|
||||
data={"motion_prompt": motion_prompt},
|
||||
)
|
||||
r.raise_for_status()
|
||||
job = wait_job(job_id)
|
||||
if job["status"] != "completed":
|
||||
raise RuntimeError(job.get("error") or job)
|
||||
url = job["downloads"]["animated_fbx"]
|
||||
if url.startswith("/"):
|
||||
url = BASE + url
|
||||
out_fbx.write_bytes(requests.get(url).content)
|
||||
return job
|
||||
|
||||
# 示例:文字外貌 → 图 → 角色 → 两个动作
|
||||
# image_job, images = local_images("棕色四足狼,完整主体,白底设定图", "generated", profile="concept", count=4)
|
||||
# 选定 images 中一张;全部图像批次空闲后:
|
||||
# requests.post(f"{BASE}/api/local-images/prepare-3d", timeout=360).raise_for_status()
|
||||
# job = create_rigged(images[0], "non_humanoid")
|
||||
# animate_and_save(job["id"], "四足待机,轻微呼吸", Path("idle.fbx"))
|
||||
# animate_and_save(job["id"], "四足动物原地跑步,可循环", Path("run.fbx"))
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 10. 给 AI Agent 的系统提示词片段(可复制)
|
||||
|
||||
可把下面段落贴进你们项目的 Agent system prompt / skill:
|
||||
|
||||
```text
|
||||
你通过 HTTP 调用本机 LLM3DGraphics(BASE 见调用指南顶部)生成 3D。
|
||||
|
||||
规则:
|
||||
- 先选 engine:要绑骨/动作 → dgx;用户要混元官网网页 → hunyuan。
|
||||
- 图片生成优先使用本地Turbo:GET {BASE}/api/local-images/status,确认connected/ready/models.turbo.installed。
|
||||
POST {BASE}/api/local-images/jobs,model=turbo,表单请求;多参考图用按顺序重复的images文件字段(最多10张)。
|
||||
宽高256–2048且为32倍数;count=1–16;negative_prompt留空,把限制写进prompt;不使用已退役的quality/2512模型。
|
||||
轮询图片批次至completed,读取images[].url并保存PNG;只要2D素材时可导出unity ZIP。
|
||||
按目标选择profile:3D主体concept,严格正面角色可用sprite并说明完整角色,真实街景background,平铺颜色albedo。
|
||||
无参考图时省略images;用户选择云端生图时改用POST {BASE}/api/image/generate,再GET返回url。
|
||||
所有生图请求通过本机服务;禁止直连上游、传播API Key或直接调用DGXA的8090 worker绕过调度。
|
||||
- hunyuan:先确认当前客户端的 hunyuan_logged_in;否则让用户在工作台当前客户端点击「微信登录」并扫描页面二维码。直接 HTTP 接入须保留同一 HttpOnly Cookie,并把二维码呈现给真人。
|
||||
提交 engine=hunyuan, mode=image;只要 model/model_ex;禁止 /animate。
|
||||
- dgx 角色:POST /api/jobs → ready_for_motion → POST .../animate;多动作多次 animate 并立刻下载。
|
||||
- dgx 静物:character_type=static,禁止 animate。
|
||||
- character_type 仅对 dgx 有效:人→humanoid;四足/怪→non_humanoid;静物→static。
|
||||
- 先 GET /api/capabilities,缺能力则说明,不要硬调。
|
||||
- 图片与DGX 3D/对比/动作串行:等待全部图片批次结束,POST /api/local-images/prepare-3d后再提交DGX。
|
||||
共同驻留由服务端决定,内存不足会释放Turbo;不要假设所有模型或所有分辨率都能一起驻留。
|
||||
- 不要假设文生 3D;不要走已废弃 TopoCap/GIF 路径。
|
||||
- Unity(dgx):角色 rigged_fbx,动画 animated_fbx。
|
||||
|
||||
详细:DGX3D_AI调用指南.md;DGX 深度规范:DGX3D生成说明.md。
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 11. 错误与排错(调用侧)
|
||||
|
||||
| 现象 | 处理 |
|
||||
|------|------|
|
||||
| 422「静态物体…不生成动作」 | 用错类型;静态只下网格 |
|
||||
| 422「请先完成角色绑骨」 | Step1 未成功或类型不对 |
|
||||
| 503 UniMate / Kimodo | 能力未就绪;人形要 Kimodo,其他类型要 UniMate |
|
||||
| 409 任务仍在处理 | 等 `completed` 再 animate |
|
||||
| 429 队列已满 | 退避重试 |
|
||||
| `failed` | `GET /api/jobs/{id}/log`;规范文档 Checklist 日志顺序 |
|
||||
| 503 生图转接未配置 | 运维在本机 `config.json` 配 `dgx.grsai.api_key` |
|
||||
| 502 生图转接失败 | 改写 prompt;运维查上游 / Key;外部仍勿直连 grsai |
|
||||
| 422 本地图像模型/尺寸/数量/参考图无效 | 仅 `model=turbo`;宽高为32倍数;count≤16;images≤10;negative_prompt为空 |
|
||||
| 409 本地图像与 DGX 任务冲突 / 正在恢复3D | 等待已有任务结束或恢复完成,再提交;勿停掉其他任务 |
|
||||
| 429 本地图像队列已满 | 图像队列最多4批,退避后重试,不反复创建同一批次 |
|
||||
| 本地图像状态未连接或模型未安装 | 检查 `/api/local-images/status`;服务机运维检查 `llm3d-qwen.service` 与 `worker.log` |
|
||||
| 本地图像批次 `failed`,仍有 `images` | 保存已生成PNG与job.json;修正错误后按需要提交新批次 |
|
||||
| 本地首次加载较慢 / 内存不足 | 查看busy/loaded_model/available_gb,等待预加载或让调度器执行内存兜底;勿自行改BF16精度 |
|
||||
| 401 请先微信登录混元3D | 在发起请求的客户端工作台点击「微信登录」并扫码;确认 status 与任务请求使用同一客户端 Cookie;或改用 `dgx` |
|
||||
| 422 混元仅支持图片 | `engine=hunyuan` 时 `mode` 必须为 `image` |
|
||||
| 422 仅 DGX 支持动作 | 对 hunyuan 任务误调了 `/animate` |
|
||||
|
||||
跨域:浏览器页面直连时服务有 Origin 限制;**服务端 / Agent / curl** 调 API 不受网页同源限制影响。
|
||||
|
||||
---
|
||||
|
||||
## 12. 与规范文档的分工
|
||||
|
||||
| 文档 | 读者 | 内容 |
|
||||
|------|------|------|
|
||||
| **本文** `DGX3D_AI调用指南.md` | 其他项目、编排 AI | 本地Turbo生图、多参考编辑、批量与Unity导出、引擎选择、云端转接、DGX剧本 |
|
||||
| `LLM3DGraphics/docs/local-image-generation.md` | 图像流程实现 / 运维 | Turbo部署、共同驻留、资源保护、Unity导入与实测 |
|
||||
| `DGX3D生成说明.md` | 本仓库实现 / 深度排错 | DGX 阶段、产物、UniMate、Unity、禁忌 |
|
||||
| `生成路径.md` | **仅运维** | 上游模型与 Key(勿发给外部 Agent) |
|
||||
| `HelpDoc/gpt-image_doc.md` | **仅运维** | 上游画图字段细节 |
|
||||
|
||||
服务变更时:外部调用顺序以本文为准;产物与内部阶段以 `DGX3D生成说明.md` 为准;上游 Key 只放本机 `config.json`。
|
||||
Reference in New Issue
Block a user