fix: parse nested image generation tasks
This commit is contained in:
@@ -9,6 +9,97 @@ import httpx
|
||||
from app.integrations.model_router import ModelRouter
|
||||
|
||||
|
||||
DIAGNOSTIC_SCALAR_KEYS = {
|
||||
"code",
|
||||
"error",
|
||||
"error_code",
|
||||
"error_message",
|
||||
"id",
|
||||
"is_final",
|
||||
"message",
|
||||
"msg",
|
||||
"state",
|
||||
"status",
|
||||
"status_group",
|
||||
"task_id",
|
||||
"type",
|
||||
}
|
||||
|
||||
|
||||
def safe_response_diagnostic(payload: Any) -> dict[str, Any]:
|
||||
"""Describe provider payload shape without persisting images, URLs, or secrets."""
|
||||
|
||||
signals: dict[str, Any] = {}
|
||||
|
||||
def shape(value: Any, path: str = "root", depth: int = 0) -> Any:
|
||||
if depth > 4:
|
||||
return type(value).__name__
|
||||
if isinstance(value, dict):
|
||||
result: dict[str, Any] = {}
|
||||
for key, child in list(value.items())[:40]:
|
||||
child_path = f"{path}.{key}"
|
||||
if key in DIAGNOSTIC_SCALAR_KEYS and isinstance(child, (str, int, float, bool)):
|
||||
rendered = str(child)
|
||||
signals[child_path] = rendered[:500]
|
||||
if key in {"url", "result_url", "b64_json", "data", "inlineData", "inline_data"}:
|
||||
if isinstance(child, list):
|
||||
result[key] = {"type": "list", "length": len(child)}
|
||||
elif isinstance(child, dict):
|
||||
result[key] = {"type": "object", "keys": list(child)[:30]}
|
||||
elif isinstance(child, str):
|
||||
result[key] = {"type": "string", "length": len(child)}
|
||||
else:
|
||||
result[key] = type(child).__name__
|
||||
if isinstance(child, (dict, list)):
|
||||
nested = shape(child, child_path, depth + 1)
|
||||
result[f"{key}_shape"] = nested
|
||||
continue
|
||||
result[key] = shape(child, child_path, depth + 1)
|
||||
return result
|
||||
if isinstance(value, list):
|
||||
return {
|
||||
"type": "list",
|
||||
"length": len(value),
|
||||
"items": [shape(item, f"{path}[{index}]", depth + 1) for index, item in enumerate(value[:3])],
|
||||
}
|
||||
if value is None:
|
||||
return "null"
|
||||
if isinstance(value, str):
|
||||
return {"type": "string", "length": len(value)}
|
||||
return type(value).__name__
|
||||
|
||||
return {"shape": shape(payload), "signals": signals}
|
||||
|
||||
|
||||
def extract_task_id(payload: Any) -> str | int | None:
|
||||
if not isinstance(payload, dict):
|
||||
return None
|
||||
direct = payload.get("task_id")
|
||||
if direct not in (None, ""):
|
||||
return direct
|
||||
data = payload.get("data")
|
||||
if isinstance(data, dict):
|
||||
nested = data.get("task_id")
|
||||
if nested not in (None, ""):
|
||||
return nested
|
||||
for key in ("task_ids", "任务ids"):
|
||||
candidates = data.get(key)
|
||||
if isinstance(candidates, list) and candidates:
|
||||
return candidates[0]
|
||||
return None
|
||||
|
||||
|
||||
def unwrap_media_status(payload: Any) -> dict[str, Any]:
|
||||
if not isinstance(payload, dict):
|
||||
raise RuntimeError("AIGC 状态接口返回的不是 JSON 对象。")
|
||||
data = payload.get("data")
|
||||
if isinstance(data, dict) and any(
|
||||
key in data for key in ("state", "is_final", "result_url", "error", "progress")
|
||||
):
|
||||
return {**payload, **data}
|
||||
return payload
|
||||
|
||||
|
||||
class OpenAICompatibleGateway:
|
||||
"""Adapter for independently configured OpenAI-compatible model-pool items."""
|
||||
|
||||
@@ -75,7 +166,11 @@ class OpenAICompatibleGateway:
|
||||
json=payload,
|
||||
)
|
||||
response.raise_for_status()
|
||||
return response.json()
|
||||
created = response.json()
|
||||
task_id = extract_task_id(created)
|
||||
if task_id is not None:
|
||||
return await self._poll_aigc_media(client, item, task_id, created)
|
||||
return created
|
||||
|
||||
async def edit_image(
|
||||
self,
|
||||
@@ -128,8 +223,8 @@ class OpenAICompatibleGateway:
|
||||
)
|
||||
response.raise_for_status()
|
||||
created = response.json()
|
||||
task_id = created.get("task_id") if isinstance(created, dict) else None
|
||||
if not task_id:
|
||||
task_id = extract_task_id(created)
|
||||
if task_id is None:
|
||||
return created
|
||||
return await self._poll_aigc_media(client, item, task_id, created)
|
||||
|
||||
@@ -148,7 +243,7 @@ class OpenAICompatibleGateway:
|
||||
params={"task_id": task_id},
|
||||
)
|
||||
response.raise_for_status()
|
||||
status = response.json()
|
||||
status = unwrap_media_status(response.json())
|
||||
if not status.get("is_final"):
|
||||
continue
|
||||
if status.get("state") != "success":
|
||||
|
||||
Reference in New Issue
Block a user