nano_banana_task.py 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. import logging
  2. import time
  3. from app.config import settings
  4. from app.service.task.base_task import BaseTask
  5. from app.service.task.task_param import TaskParam
  6. from app.service.task.task_result import TaskResult
  7. from app.util.http_util import logged_client
  8. logger = logging.getLogger(__name__)
  9. class NanoBananaTask(BaseTask):
  10. def get_type(self) -> str:
  11. return "nano_banana"
  12. def execute(self, param: TaskParam) -> TaskResult:
  13. endpoint = f"{settings.gemini_base_url}/models/{settings.gemini_nano_banana_model}:generateContent"
  14. headers = {
  15. "x-goog-api-key": settings.gemini_api_key,
  16. "Content-Type": "application/json",
  17. }
  18. logger.info("[nano_banana] Calling Gemini API: POST %s", endpoint)
  19. t0 = time.time()
  20. try:
  21. with logged_client(timeout=120) as client:
  22. resp = client.post(endpoint, headers=headers, json=param.inputs)
  23. elapsed = time.time() - t0
  24. logger.info("[nano_banana] Response: status=%d, elapsed=%.2fs, body_size=%d",
  25. resp.status_code, elapsed, len(resp.content))
  26. resp.raise_for_status()
  27. data = resp.json()
  28. except Exception as e:
  29. elapsed = time.time() - t0
  30. logger.error("[nano_banana] Request failed in %.2fs: %s", elapsed, e)
  31. return TaskResult.failure(f"submit execute fail: {e}")
  32. candidates = data.get("candidates")
  33. if not candidates:
  34. logger.warning("[nano_banana] No candidates in response")
  35. return TaskResult.failure("submit execute fail !")
  36. encoded_files: list[str] = []
  37. parts = candidates[0].get("content", {}).get("parts", [])
  38. for part in parts:
  39. text = part.get("text")
  40. if text:
  41. logger.info("[nano_banana] Text part: %s", text[:200])
  42. inline_data = part.get("inlineData")
  43. if inline_data and inline_data.get("data"):
  44. encoded_files.append(inline_data["data"])
  45. logger.info("[nano_banana] Completed: %d images generated", len(encoded_files))
  46. return TaskResult.success({"images": encoded_files})