knnn11 commited on
Commit
2bc9b59
Β·
verified Β·
1 Parent(s): 9151ed7

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +49 -28
app.py CHANGED
@@ -9,20 +9,35 @@ import logging
9
  from datetime import datetime
10
 
11
  # Configure logging
12
- logging.basicConfig(level=logging.DEBUG)
13
  logger = logging.getLogger(__name__)
14
 
15
  class Config:
16
  RUNPOD_API_KEY = os.getenv("RUNPOD_API_KEY", "")
17
- RUNPOD_ENDPOINT = os.getenv("RUNPOD_ENDPOINT", "").replace("/run", "/runsync") # Force sync endpoint
18
  PORT = 7860
19
- TIMEOUT = 120
20
  MAX_RETRIES = 2
21
  IMAGE_SIZE = (768, 768)
22
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
  class RunPodClient:
24
  async def generate_image(self, prompt, negative_prompt=""):
25
- """Enhanced response handler with direct status checking"""
 
 
26
  for attempt in range(Config.MAX_RETRIES):
27
  try:
28
  async with aiohttp.ClientSession() as session:
@@ -37,58 +52,63 @@ class RunPodClient:
37
  }
38
  }
39
 
 
 
40
  async with session.post(
41
  Config.RUNPOD_ENDPOINT,
42
  headers={"Authorization": f"Bearer {Config.RUNPOD_API_KEY}"},
43
  json=payload,
44
  timeout=Config.TIMEOUT
45
  ) as response:
 
 
 
 
 
 
 
 
46
  data = await response.json()
47
- logger.debug(f"Full API response: {data}")
48
 
49
- # Handle job ID response (async)
50
- if data.get("id"):
51
  job_id = data["id"]
52
- status_url = f"{Config.RUNPOD_ENDPOINT.replace('/runsync', '')}/status/{job_id}"
53
  return await self._check_job_status(session, status_url)
54
 
55
- # Handle direct output (sync)
56
- if data.get("status") == "COMPLETED":
57
- if isinstance(data.get("output"), list):
58
- return data["output"][0], None
59
- return None, "❌ Completed but no output URL found"
60
-
61
- return None, f"❌ Unexpected response: {data.get('error', str(data))}"
62
 
63
  except Exception as e:
64
  logger.error(f"Attempt {attempt + 1} failed: {str(e)}")
65
  if attempt == Config.MAX_RETRIES - 1:
66
  return None, f"πŸ”₯ Connection error: {str(e)}"
67
- await asyncio.sleep(2 ** attempt)
68
 
69
  async def _check_job_status(self, session, status_url):
70
  """Poll job status for async endpoints"""
71
- retries = 10
72
- while retries > 0:
73
  async with session.get(
74
  status_url,
75
  headers={"Authorization": f"Bearer {Config.RUNPOD_API_KEY}"},
76
  timeout=Config.TIMEOUT
77
  ) as response:
78
  data = await response.json()
79
- logger.debug(f"Job status check: {data}")
80
-
81
  if data.get("status") == "COMPLETED":
82
- if isinstance(data.get("output"), list) and len(data["output"]) > 0:
83
  return data["output"][0], None
84
- return None, "❌ Job completed but no output URL"
85
 
86
  if data.get("status") == "FAILED":
87
  return None, f"❌ Job failed: {data.get('error', 'Unknown error')}"
88
 
89
  await asyncio.sleep(2)
90
- retries -= 1
91
-
92
  return None, "βŒ› Timeout waiting for job completion"
93
 
94
  def create_interface():
@@ -118,6 +138,7 @@ def create_interface():
118
  return None, "❌ Please enter a prompt"
119
 
120
  try:
 
121
  client = RunPodClient()
122
  image_url, error = await client.generate_image(prompt, negative)
123
 
@@ -142,11 +163,11 @@ def create_interface():
142
 
143
  if __name__ == "__main__":
144
  try:
 
145
  if not Config.RUNPOD_API_KEY:
146
- raise ValueError("RUNPOD_API_KEY not set")
147
- if not Config.RUNPOD_ENDPOINT:
148
- raise ValueError("RUNPOD_ENDPOINT not set")
149
-
150
  app = create_interface()
151
  app.launch(
152
  server_name="0.0.0.0",
 
9
  from datetime import datetime
10
 
11
  # Configure logging
12
+ logging.basicConfig(level=logging.INFO)
13
  logger = logging.getLogger(__name__)
14
 
15
  class Config:
16
  RUNPOD_API_KEY = os.getenv("RUNPOD_API_KEY", "")
17
+ RUNPOD_ENDPOINT = os.getenv("RUNPOD_ENDPOINT", "").rstrip('/') # Clean endpoint URL
18
  PORT = 7860
19
+ TIMEOUT = 90
20
  MAX_RETRIES = 2
21
  IMAGE_SIZE = (768, 768)
22
 
23
+ @classmethod
24
+ def validate_endpoint(cls):
25
+ """Ensure endpoint has correct format"""
26
+ if not cls.RUNPOD_ENDPOINT:
27
+ raise ValueError("RUNPOD_ENDPOINT not set")
28
+
29
+ # Normalize endpoint URL
30
+ if not cls.RUNPOD_ENDPOINT.endswith(('/run', '/runsync')):
31
+ cls.RUNPOD_ENDPOINT = f"{cls.RUNPOD_ENDPOINT}/runsync"
32
+
33
+ if not cls.RUNPOD_ENDPOINT.startswith('https://api.runpod.ai/v2/'):
34
+ raise ValueError("Invalid endpoint format. Should be: https://api.runpod.ai/v2/ENDPOINT_ID/[run|runsync]")
35
+
36
  class RunPodClient:
37
  async def generate_image(self, prompt, negative_prompt=""):
38
+ """Handle both sync and async endpoints"""
39
+ Config.validate_endpoint()
40
+
41
  for attempt in range(Config.MAX_RETRIES):
42
  try:
43
  async with aiohttp.ClientSession() as session:
 
52
  }
53
  }
54
 
55
+ logger.debug(f"Sending request to: {Config.RUNPOD_ENDPOINT}")
56
+
57
  async with session.post(
58
  Config.RUNPOD_ENDPOINT,
59
  headers={"Authorization": f"Bearer {Config.RUNPOD_API_KEY}"},
60
  json=payload,
61
  timeout=Config.TIMEOUT
62
  ) as response:
63
+
64
+ # Handle text/plain responses
65
+ content_type = response.headers.get('Content-Type', '')
66
+ if 'text/plain' in content_type:
67
+ text_response = await response.text()
68
+ logger.error(f"Text response received: {text_response}")
69
+ raise ValueError(f"Unexpected text response: {text_response[:100]}...")
70
+
71
  data = await response.json()
72
+ logger.debug(f"API response: {data}")
73
 
74
+ # Handle async job response
75
+ if data.get("id") and not Config.RUNPOD_ENDPOINT.endswith('/runsync'):
76
  job_id = data["id"]
77
+ status_url = f"{Config.RUNPOD_ENDPOINT.rsplit('/', 1)[0]}/status/{job_id}"
78
  return await self._check_job_status(session, status_url)
79
 
80
+ # Handle direct output
81
+ if data.get("status") == "COMPLETED" and data.get("output"):
82
+ return data["output"][0], None
83
+
84
+ return None, f"❌ Unexpected response format: {data}"
 
 
85
 
86
  except Exception as e:
87
  logger.error(f"Attempt {attempt + 1} failed: {str(e)}")
88
  if attempt == Config.MAX_RETRIES - 1:
89
  return None, f"πŸ”₯ Connection error: {str(e)}"
90
+ await asyncio.sleep(1)
91
 
92
  async def _check_job_status(self, session, status_url):
93
  """Poll job status for async endpoints"""
94
+ for _ in range(10): # Max 10 checks
 
95
  async with session.get(
96
  status_url,
97
  headers={"Authorization": f"Bearer {Config.RUNPOD_API_KEY}"},
98
  timeout=Config.TIMEOUT
99
  ) as response:
100
  data = await response.json()
101
+
 
102
  if data.get("status") == "COMPLETED":
103
+ if data.get("output"):
104
  return data["output"][0], None
105
+ return None, "❌ Job completed but no output"
106
 
107
  if data.get("status") == "FAILED":
108
  return None, f"❌ Job failed: {data.get('error', 'Unknown error')}"
109
 
110
  await asyncio.sleep(2)
111
+
 
112
  return None, "βŒ› Timeout waiting for job completion"
113
 
114
  def create_interface():
 
138
  return None, "❌ Please enter a prompt"
139
 
140
  try:
141
+ Config.validate_endpoint()
142
  client = RunPodClient()
143
  image_url, error = await client.generate_image(prompt, negative)
144
 
 
163
 
164
  if __name__ == "__main__":
165
  try:
166
+ # Validate configuration before starting
167
  if not Config.RUNPOD_API_KEY:
168
+ raise ValueError("RUNPOD_API_KEY environment variable not set")
169
+ Config.validate_endpoint()
170
+
 
171
  app = create_interface()
172
  app.launch(
173
  server_name="0.0.0.0",