yukee1992 commited on
Commit
b67422e
·
verified ·
1 Parent(s): 86cfbb7

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +46 -84
app.py CHANGED
@@ -3,6 +3,7 @@ import uuid
3
  import httpx
4
  import torch
5
  import logging
 
6
  from typing import Dict, Optional
7
  from fastapi import FastAPI, Request, BackgroundTasks, HTTPException
8
  from fastapi.responses import JSONResponse
@@ -10,6 +11,7 @@ from transformers import AutoTokenizer, AutoModelForCausalLM
10
  import uvicorn
11
  from contextlib import asynccontextmanager
12
  from pydantic import BaseModel
 
13
 
14
  # Configuration
15
  MODEL_ID = "google/gemma-1.1-2b-it"
@@ -56,17 +58,18 @@ class ScriptGenerator:
56
  ).to(DEVICE)
57
  self.loaded = True
58
  logger.info("Model loaded successfully")
59
- self.send_telegram_notification("🤖 Model loaded and ready to generate scripts!")
60
  except Exception as e:
61
  error_msg = f"Model loading failed: {str(e)}"
62
  logger.error(error_msg)
63
  self.send_telegram_notification(f"❌ {error_msg}")
64
  raise
65
 
 
66
  async def send_telegram_notification(self, message: str):
67
- """Send notification to Telegram"""
68
  if not TELEGRAM_BOT_TOKEN or not TELEGRAM_CHAT_ID:
69
- logger.warning("Telegram credentials not configured")
70
  return
71
 
72
  try:
@@ -77,11 +80,17 @@ class ScriptGenerator:
77
  "parse_mode": "Markdown"
78
  }
79
 
80
- async with httpx.AsyncClient() as client:
81
- await client.post(url, json=payload, timeout=10.0)
 
 
 
 
 
82
 
83
  except Exception as e:
84
  logger.error(f"Telegram notification failed: {str(e)}")
 
85
 
86
  # Lifespan handler
87
  @asynccontextmanager
@@ -89,11 +98,18 @@ async def lifespan(app: FastAPI):
89
  generator = ScriptGenerator()
90
  generator.load_model()
91
  yield
92
- # Cleanup if needed
93
 
94
  app = FastAPI(lifespan=lifespan)
95
  generator = ScriptGenerator()
96
 
 
 
 
 
 
 
 
 
97
  def generate_script(topic: str) -> str:
98
  """Generate script with error handling"""
99
  try:
@@ -101,11 +117,11 @@ def generate_script(topic: str) -> str:
101
  generator.load_model()
102
 
103
  prompt = (
104
- f"Create a 1-minute engaging video script about: {topic[:80]}\n\n"
105
  "Structure:\n"
106
- "1) Hook (5-10 seconds - grab attention)\n"
107
- "2) Main Content (40-45 seconds - valuable information)\n"
108
- "3) CTA (5-10 seconds - clear call-to-action)\n\n"
109
  "Script:"
110
  )
111
 
@@ -130,132 +146,78 @@ async def process_job(job_id: str, topic: str, callback_url: str = None):
130
  """Background task to process job"""
131
  try:
132
  await generator.send_telegram_notification(
133
- f"⏳ *Job Started*\n"
134
- f"ID: `{job_id}`\n"
135
- f"Topic: _{topic}_"
136
  )
137
 
138
  script = generate_script(topic)
139
- jobs[job_id] = {
140
- "status": "complete",
141
- "result": script
142
- }
143
 
144
  if callback_url:
145
  try:
146
  async with httpx.AsyncClient() as client:
147
  response = await client.post(
148
  callback_url,
149
- json={
150
- "job_id": job_id,
151
- "status": "complete",
152
- "result": script
153
- },
154
  timeout=30.0
155
  )
156
-
157
  if response.status_code == 200:
158
  await generator.send_telegram_notification(
159
- f"✅ *Job Completed*\n"
160
- f"ID: `{job_id}`\n"
161
- f"Callback successful"
162
- )
163
- else:
164
- error_msg = f"Callback failed with status {response.status_code}"
165
- logger.error(error_msg)
166
- await generator.send_telegram_notification(
167
- f"⚠️ *Callback Failed*\n"
168
- f"ID: `{job_id}`\n"
169
- f"Error: _{error_msg}_"
170
  )
171
-
172
  except Exception as e:
173
- error_msg = f"Callback error: {str(e)}"
174
- logger.error(error_msg)
175
- await generator.send_telegram_notification(
176
- f"⚠️ *Callback Error*\n"
177
- f"ID: `{job_id}`\n"
178
- f"Error: _{error_msg}_"
179
- )
180
 
181
  except Exception as e:
182
  error_msg = f"Job failed: {str(e)}"
183
- logger.error(error_msg)
184
- jobs[job_id] = {
185
- "status": "failed",
186
- "error": error_msg
187
- }
188
-
189
  await generator.send_telegram_notification(
190
- f"❌ *Job Failed*\n"
191
- f"ID: `{job_id}`\n"
192
- f"Error: _{error_msg}_"
193
  )
194
-
195
- if callback_url:
196
- try:
197
- await httpx.post(
198
- callback_url,
199
- json={
200
- "job_id": job_id,
201
- "status": "failed",
202
- "error": error_msg
203
- }
204
- )
205
- except Exception as e:
206
- logger.error(f"Failed to send failure callback: {str(e)}")
207
 
208
  @app.post("/api/submit")
209
  async def submit_job(request: Request, background_tasks: BackgroundTasks):
210
- """Endpoint to submit new job"""
211
  try:
212
  data = await request.json()
213
  job_id = str(uuid.uuid4())
214
 
215
- # Validate input
216
  if not data.get("topic"):
217
- raise HTTPException(status_code=400, detail="Topic is required")
218
 
219
- callback_url = data.get("callback_url")
220
-
221
  jobs[job_id] = {
222
  "status": "processing",
223
- "result": None,
224
- "callback_url": callback_url
225
  }
226
 
227
  background_tasks.add_task(
228
  process_job,
229
  job_id,
230
  data["topic"],
231
- callback_url
232
  )
233
 
234
- return JSONResponse({
235
- "job_id": job_id,
236
- "status": "queued",
237
- "message": "Job is being processed"
238
- })
239
 
240
  except Exception as e:
241
  logger.error(f"Submission error: {str(e)}")
242
- await generator.send_telegram_notification(
243
- f"🚨 *Submission Error*\n"
244
- f"Error: _{str(e)}_"
245
- )
246
- raise HTTPException(status_code=400, detail=str(e))
247
 
248
  @app.get("/api/status/{job_id}")
249
  async def get_status(job_id: str):
250
  """Check job status"""
251
  if job_id not in jobs:
252
- raise HTTPException(status_code=404, detail="Job not found")
253
  return jobs[job_id]
254
 
255
  @app.get("/health")
256
  async def health_check():
257
  """Health check endpoint"""
258
- return {"status": "healthy", "model_loaded": generator.loaded}
 
 
 
 
 
259
 
260
  if __name__ == "__main__":
261
  uvicorn.run(
 
3
  import httpx
4
  import torch
5
  import logging
6
+ import socket
7
  from typing import Dict, Optional
8
  from fastapi import FastAPI, Request, BackgroundTasks, HTTPException
9
  from fastapi.responses import JSONResponse
 
11
  import uvicorn
12
  from contextlib import asynccontextmanager
13
  from pydantic import BaseModel
14
+ from tenacity import retry, stop_after_attempt, wait_exponential
15
 
16
  # Configuration
17
  MODEL_ID = "google/gemma-1.1-2b-it"
 
58
  ).to(DEVICE)
59
  self.loaded = True
60
  logger.info("Model loaded successfully")
61
+ self.send_telegram_notification("🤖 Model loaded and ready!")
62
  except Exception as e:
63
  error_msg = f"Model loading failed: {str(e)}"
64
  logger.error(error_msg)
65
  self.send_telegram_notification(f"❌ {error_msg}")
66
  raise
67
 
68
+ @retry(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=4, max=10))
69
  async def send_telegram_notification(self, message: str):
70
+ """Send notification to Telegram with retry logic"""
71
  if not TELEGRAM_BOT_TOKEN or not TELEGRAM_CHAT_ID:
72
+ logger.warning("Telegram not configured")
73
  return
74
 
75
  try:
 
80
  "parse_mode": "Markdown"
81
  }
82
 
83
+ transport = httpx.AsyncHTTPTransport(retries=3)
84
+ timeout = httpx.Timeout(15.0, connect=10.0)
85
+
86
+ async with httpx.AsyncClient(transport=transport, timeout=timeout) as client:
87
+ response = await client.post(url, json=payload)
88
+ response.raise_for_status()
89
+ logger.info(f"Telegram notification sent")
90
 
91
  except Exception as e:
92
  logger.error(f"Telegram notification failed: {str(e)}")
93
+ raise
94
 
95
  # Lifespan handler
96
  @asynccontextmanager
 
98
  generator = ScriptGenerator()
99
  generator.load_model()
100
  yield
 
101
 
102
  app = FastAPI(lifespan=lifespan)
103
  generator = ScriptGenerator()
104
 
105
+ def check_dns():
106
+ """Check DNS resolution"""
107
+ try:
108
+ socket.gethostbyname('api.telegram.org')
109
+ return True
110
+ except socket.gaierror:
111
+ return False
112
+
113
  def generate_script(topic: str) -> str:
114
  """Generate script with error handling"""
115
  try:
 
117
  generator.load_model()
118
 
119
  prompt = (
120
+ f"Create a 1-minute video script about: {topic[:80]}\n\n"
121
  "Structure:\n"
122
+ "1) Hook (5-10 seconds)\n"
123
+ "2) Main Content (40-45 seconds)\n"
124
+ "3) CTA (5-10 seconds)\n\n"
125
  "Script:"
126
  )
127
 
 
146
  """Background task to process job"""
147
  try:
148
  await generator.send_telegram_notification(
149
+ f"⏳ Job Started\nID: `{job_id}`\nTopic: _{topic}_"
 
 
150
  )
151
 
152
  script = generate_script(topic)
153
+ jobs[job_id] = {"status": "complete", "result": script}
 
 
 
154
 
155
  if callback_url:
156
  try:
157
  async with httpx.AsyncClient() as client:
158
  response = await client.post(
159
  callback_url,
160
+ json={"job_id": job_id, "status": "complete", "result": script},
 
 
 
 
161
  timeout=30.0
162
  )
 
163
  if response.status_code == 200:
164
  await generator.send_telegram_notification(
165
+ f"✅ Job Complete\nID: `{job_id}`"
 
 
 
 
 
 
 
 
 
 
166
  )
 
167
  except Exception as e:
168
+ logger.error(f"Callback failed: {str(e)}")
 
 
 
 
 
 
169
 
170
  except Exception as e:
171
  error_msg = f"Job failed: {str(e)}"
172
+ jobs[job_id] = {"status": "failed", "error": error_msg}
 
 
 
 
 
173
  await generator.send_telegram_notification(
174
+ f"❌ Job Failed\nID: `{job_id}`\nError: _{error_msg}_"
 
 
175
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
176
 
177
  @app.post("/api/submit")
178
  async def submit_job(request: Request, background_tasks: BackgroundTasks):
179
+ """Submit new job"""
180
  try:
181
  data = await request.json()
182
  job_id = str(uuid.uuid4())
183
 
 
184
  if not data.get("topic"):
185
+ raise HTTPException(400, detail="Topic is required")
186
 
 
 
187
  jobs[job_id] = {
188
  "status": "processing",
189
+ "callback_url": data.get("callback_url")
 
190
  }
191
 
192
  background_tasks.add_task(
193
  process_job,
194
  job_id,
195
  data["topic"],
196
+ data.get("callback_url")
197
  )
198
 
199
+ return {"job_id": job_id, "status": "queued"}
 
 
 
 
200
 
201
  except Exception as e:
202
  logger.error(f"Submission error: {str(e)}")
203
+ raise HTTPException(400, detail=str(e))
 
 
 
 
204
 
205
  @app.get("/api/status/{job_id}")
206
  async def get_status(job_id: str):
207
  """Check job status"""
208
  if job_id not in jobs:
209
+ raise HTTPException(404, detail="Job not found")
210
  return jobs[job_id]
211
 
212
  @app.get("/health")
213
  async def health_check():
214
  """Health check endpoint"""
215
+ return {
216
+ "status": "healthy",
217
+ "model_loaded": generator.loaded,
218
+ "dns_working": check_dns(),
219
+ "telegram_configured": bool(TELEGRAM_BOT_TOKEN and TELEGRAM_CHAT_ID)
220
+ }
221
 
222
  if __name__ == "__main__":
223
  uvicorn.run(