生成图片(同步返回) Args: at: Access Token project_id: 项目ID prompt: 提示词 model_name: NARWHAL / GEM_PIX / GEM_PIX_2 / IMAGEN_3_5 aspect_ratio: 图片宽高比 image_inputs: 参考图片列表(图生图时使用) Returns: (result, session_id, p
(
self,
at: str,
project_id: str,
prompt: str,
model_name: str,
aspect_ratio: str,
image_inputs: Optional[List[Dict]] = None,
token_id: Optional[int] = None,
token_image_concurrency: Optional[int] = None,
progress_callback: Optional[Callable[[str, int], Awaitable[None]]] = None,
)
| 1575 | # ========== 图片生成 (使用AT) - 同步返回 ========== |
| 1576 | |
| 1577 | async def generate_image( |
| 1578 | self, |
| 1579 | at: str, |
| 1580 | project_id: str, |
| 1581 | prompt: str, |
| 1582 | model_name: str, |
| 1583 | aspect_ratio: str, |
| 1584 | image_inputs: Optional[List[Dict]] = None, |
| 1585 | token_id: Optional[int] = None, |
| 1586 | token_image_concurrency: Optional[int] = None, |
| 1587 | progress_callback: Optional[Callable[[str, int], Awaitable[None]]] = None, |
| 1588 | ) -> tuple[dict, str, Dict[str, Any]]: |
| 1589 | """生成图片(同步返回) |
| 1590 | |
| 1591 | Args: |
| 1592 | at: Access Token |
| 1593 | project_id: 项目ID |
| 1594 | prompt: 提示词 |
| 1595 | model_name: NARWHAL / GEM_PIX / GEM_PIX_2 / IMAGEN_3_5 |
| 1596 | aspect_ratio: 图片宽高比 |
| 1597 | image_inputs: 参考图片列表(图生图时使用) |
| 1598 | |
| 1599 | Returns: |
| 1600 | (result, session_id, perf_trace) |
| 1601 | result: 上游返回的生成结果 |
| 1602 | session_id: 本次成功图片生成请求使用的 sessionId |
| 1603 | perf_trace: 生成重试与链路耗时轨迹 |
| 1604 | """ |
| 1605 | url = f"{self.api_base_url}/projects/{project_id}/flowMedia:batchGenerateImages" |
| 1606 | |
| 1607 | # 403/reCAPTCHA 重试逻辑 |
| 1608 | max_retries = config.flow_max_retries |
| 1609 | last_error = None |
| 1610 | perf_trace: Dict[str, Any] = { |
| 1611 | "max_retries": max_retries, |
| 1612 | "generation_attempts": [], |
| 1613 | } |
| 1614 | |
| 1615 | for retry_attempt in range(max_retries): |
| 1616 | attempt_trace: Dict[str, Any] = { |
| 1617 | "attempt": retry_attempt + 1, |
| 1618 | "recaptcha_ok": False, |
| 1619 | } |
| 1620 | attempt_started_at = time.time() |
| 1621 | # 每次重试都重新获取 reCAPTCHA token |
| 1622 | recaptcha_started_at = time.time() |
| 1623 | if progress_callback is not None: |
| 1624 | await progress_callback("solving_image_captcha", 38) |
| 1625 | launch_gate_acquired = False |
| 1626 | launch_ok, launch_queue_ms, launch_stagger_ms = await self._acquire_image_launch_gate( |
| 1627 | token_id=token_id, |
| 1628 | token_image_concurrency=token_image_concurrency, |
| 1629 | ) |
| 1630 | attempt_trace["launch_queue_ms"] = launch_queue_ms |
| 1631 | attempt_trace["launch_stagger_ms"] = launch_stagger_ms |
| 1632 | if not launch_ok: |
| 1633 | last_error = Exception("Image launch queue wait timeout") |
| 1634 | attempt_trace["success"] = False |
no test coverage detected