ChenyuRabbitLove commited on
Commit
ad78edb
·
1 Parent(s): e61e906

feat: implement DALL-E fallback mechanism in image generation service to handle API failures and enhance error logging

Browse files
backend/app/main.py CHANGED
@@ -72,7 +72,7 @@ async def health_check():
72
 
73
 
74
  # OpenAI connection test endpoint
75
- @app.get("/test-openai")
76
  async def test_openai():
77
  """Test OpenAI connection without making actual API calls"""
78
  try:
 
72
 
73
 
74
  # OpenAI connection test endpoint
75
+ @app.get("/api/test-openai")
76
  async def test_openai():
77
  """Test OpenAI connection without making actual API calls"""
78
  try:
backend/app/services/image_service.py CHANGED
@@ -40,6 +40,57 @@ class ImageGenerationService:
40
  if not os.path.exists(self.output_dir):
41
  os.makedirs(self.output_dir)
42
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43
  async def generate_image(
44
  self,
45
  prompt: str,
@@ -153,9 +204,9 @@ class ImageGenerationService:
153
  continue
154
 
155
  if not generated_filenames:
156
- raise Exception(
157
- "Failed to generate any images - all attempts returned text or failed"
158
- )
159
 
160
  logger.info(
161
  f"Successfully generated {len(generated_filenames)}/{n} images"
 
40
  if not os.path.exists(self.output_dir):
41
  os.makedirs(self.output_dir)
42
 
43
+ async def _fallback_to_dalle(self, prompt: str, size: str, n: int, model: str) -> dict:
44
+ """
45
+ Fallback to regular DALL-E when responses API is blocked
46
+ This sacrifices reference image capability but ensures the app works on Hugging Face
47
+ """
48
+ try:
49
+ logger.info("Using DALL-E fallback (reference image will be ignored)")
50
+
51
+ response = self.client.images.generate(
52
+ model=model,
53
+ prompt=prompt,
54
+ n=n,
55
+ size=size,
56
+ response_format="b64_json",
57
+ )
58
+
59
+ generated_filenames = []
60
+
61
+ for i, image_data in enumerate(response.data):
62
+ try:
63
+ image_bytes = base64.b64decode(image_data.b64_json)
64
+
65
+ # Generate unique filename and save
66
+ filename = f"{uuid.uuid4()}.png"
67
+ filepath = os.path.join(self.output_dir, filename)
68
+
69
+ with open(filepath, "wb") as f:
70
+ f.write(image_bytes)
71
+
72
+ generated_filenames.append(filename)
73
+ logger.info(f"Fallback image {i+1} saved successfully: {filename}")
74
+
75
+ except Exception as e:
76
+ logger.warning(f"Failed to save fallback image {i+1}: {str(e)}")
77
+ continue
78
+
79
+ if generated_filenames:
80
+ return {
81
+ "success": True,
82
+ "message": f"Generated {len(generated_filenames)}/{n} images using DALL-E fallback (reference image ignored due to network restrictions)",
83
+ "filename": generated_filenames[0],
84
+ "filenames": generated_filenames,
85
+ "count": len(generated_filenames),
86
+ }
87
+ else:
88
+ raise Exception("Fallback also failed to generate any images")
89
+
90
+ except Exception as e:
91
+ logger.error(f"Fallback to DALL-E also failed: {str(e)}")
92
+ raise Exception(f"Both responses API and DALL-E fallback failed: {str(e)}")
93
+
94
  async def generate_image(
95
  self,
96
  prompt: str,
 
204
  continue
205
 
206
  if not generated_filenames:
207
+ # If responses API failed due to network restrictions, try fallback to regular DALL-E
208
+ logger.warning("Responses API failed, attempting fallback to regular DALL-E")
209
+ return await self._fallback_to_dalle(prompt, size, n, model)
210
 
211
  logger.info(
212
  f"Successfully generated {len(generated_filenames)}/{n} images"