Spaces:
Running
Running
Update main.py
Browse files
main.py
CHANGED
@@ -1,4 +1,4 @@
|
|
1 |
-
# main.py (
|
2 |
import os
|
3 |
import re
|
4 |
import logging
|
@@ -89,7 +89,6 @@ GEMINI_API_KEY = get_secret('GEMINI_API_KEY')
|
|
89 |
|
90 |
OPENROUTER_MODEL = os.environ.get("OPENROUTER_MODEL", "deepseek/deepseek-chat-v3-0324:free")
|
91 |
APIFY_ACTOR_ID = os.environ.get("APIFY_ACTOR_ID", "karamelo~youtube-transcripts")
|
92 |
-
# *** FIX: Update default Gemini model to gemini-2.0-flash ***
|
93 |
GEMINI_MODEL = os.environ.get("GEMINI_MODEL", "gemini-2.0-flash")
|
94 |
|
95 |
if not TELEGRAM_TOKEN: logger.critical("❌ FATAL: TELEGRAM_TOKEN not found."); raise RuntimeError("Exiting: Telegram token missing.")
|
@@ -163,7 +162,7 @@ async def get_transcript_via_supadata(video_id: str, api_key: str) -> Optional[s
|
|
163 |
if not video_id: logger.error("[Supadata] No video_id provided"); return None
|
164 |
if not api_key: logger.error("[Supadata] API key missing."); return None
|
165 |
logger.info(f"[Supadata] Attempting fetch for video ID: {video_id}")
|
166 |
-
api_endpoint = "https://api.supadata.ai/v1/youtube/transcript"
|
167 |
params = {"videoId": video_id, "format": "text"}; headers = {"X-API-Key": api_key}
|
168 |
try:
|
169 |
async with httpx.AsyncClient(timeout=30.0) as client:
|
@@ -334,23 +333,18 @@ async def generate_summary_gemini(text: str, summary_type: str) -> str:
|
|
334 |
MAX_INPUT_LENGTH = 1000000
|
335 |
if len(text) > MAX_INPUT_LENGTH: logger.warning(f"[Gemini Fallback] Input length ({len(text)}) exceeds limit ({MAX_INPUT_LENGTH}). Truncating."); text = text[:MAX_INPUT_LENGTH] + "... (Content truncated)"
|
336 |
full_prompt = f"{prompt}\n\n{text}"
|
337 |
-
|
338 |
# *** FIX: Set all safety settings to BLOCK_NONE ***
|
339 |
safety_settings = {
|
340 |
HarmCategory.HARM_CATEGORY_HARASSMENT: HarmBlockThreshold.BLOCK_NONE,
|
341 |
HarmCategory.HARM_CATEGORY_HATE_SPEECH: HarmBlockThreshold.BLOCK_NONE,
|
342 |
HarmCategory.HARM_CATEGORY_SEXUALLY_EXPLICIT: HarmBlockThreshold.BLOCK_NONE,
|
343 |
HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT: HarmBlockThreshold.BLOCK_NONE,
|
344 |
-
#
|
345 |
-
# but setting it won't hurt if the HarmCategory exists.
|
346 |
-
# If it causes an error later, remove this line.
|
347 |
getattr(HarmCategory, 'HARM_CATEGORY_CIVIC_INTEGRITY', None): HarmBlockThreshold.BLOCK_NONE
|
348 |
}
|
349 |
-
# Filter out None keys in case CIVIC_INTEGRITY doesn't exist
|
350 |
safety_settings = {k: v for k, v in safety_settings.items() if k is not None}
|
351 |
logger.debug(f"[Gemini Fallback] Using safety settings: {safety_settings}")
|
352 |
|
353 |
-
|
354 |
try:
|
355 |
logger.debug(f"[Gemini Fallback] Initializing model {GEMINI_MODEL}")
|
356 |
model = genai.GenerativeModel(GEMINI_MODEL)
|
@@ -359,21 +353,12 @@ async def generate_summary_gemini(text: str, summary_type: str) -> str:
|
|
359 |
response = await model.generate_content_async( full_prompt, safety_settings=safety_settings, request_options=request_options )
|
360 |
logger.info("[Gemini Fallback] Received response from Gemini.")
|
361 |
|
362 |
-
|
363 |
-
if response.prompt_feedback.block_reason: logger.warning(f"[Gemini Fallback] Request blocked unexpectedly. Reason: {response.prompt_feedback.block_reason}"); # Changed to warning
|
364 |
-
# Check candidates for safety blocks as well
|
365 |
for cand in response.candidates:
|
366 |
-
if cand.finish_reason == 'SAFETY':
|
367 |
-
logger.warning(f"[Gemini Fallback] Candidate blocked due to SAFETY. Ratings: {cand.safety_ratings}")
|
368 |
|
369 |
-
|
370 |
-
|
371 |
-
try:
|
372 |
-
summary = response.text
|
373 |
-
except ValueError as e:
|
374 |
-
# Handle cases where accessing response.text raises ValueError (e.g., blocked content)
|
375 |
-
logger.warning(f"[Gemini Fallback] Error accessing response text (likely blocked content): {e}")
|
376 |
-
summary = None # Ensure summary is None
|
377 |
|
378 |
if summary: logger.info(f"[Gemini Fallback] Success generating summary. Output len: {len(summary)}"); return summary.strip().replace('_', r'\_').replace('*', r'\*').replace('[', r'\[').replace('`', r'\`')
|
379 |
else: logger.warning(f"[Gemini Fallback] Gemini returned empty summary or content was blocked. Finish reason: {response.candidates[0].finish_reason if response.candidates else 'N/A'}"); return "Sorry, the fallback AI model did not provide a summary (possibly due to content filters)."
|
@@ -392,7 +377,7 @@ async def generate_summary(text: str, summary_type: str) -> str:
|
|
392 |
if len(text) > MAX_INPUT_LENGTH: logger.warning(f"[Primary Summary] Input length ({len(text)}) exceeds limit ({MAX_INPUT_LENGTH}). Truncating."); text = text[:MAX_INPUT_LENGTH] + "... (Content truncated)"
|
393 |
full_prompt = f"{prompt}\n\n{text}"
|
394 |
headers = { "Authorization": f"Bearer {OPENROUTER_API_KEY}", "Content-Type": "application/json" }; payload = { "model": OPENROUTER_MODEL, "messages": [{"role": "user", "content": full_prompt}] }; openrouter_api_endpoint = "https://openrouter.ai/api/v1/chat/completions"
|
395 |
-
api_timeouts = httpx.Timeout(15.0, read=10.0, write=15.0, pool=60.0)
|
396 |
response = None
|
397 |
|
398 |
try:
|
@@ -421,7 +406,10 @@ async def generate_summary(text: str, summary_type: str) -> str:
|
|
421 |
elif response.status_code == 429: logger.warning("[Primary Summary] OpenRouter Rate Limit Exceeded (429)."); return "Sorry, primary AI model is busy. Try again."
|
422 |
elif response.status_code == 500: logger.error(f"[Primary Summary] OpenRouter Internal Server Error (500). Resp:{response.text[:500]}"); return "Sorry, primary AI service internal error."
|
423 |
else:
|
424 |
-
error_info = "";
|
|
|
|
|
|
|
425 |
logger.error(f"[Primary Summary] Unexpected status {response.status_code} from OpenRouter. Error: '{error_info}' Resp:{response.text[:500]}");
|
426 |
return f"Sorry, primary AI service returned unexpected status ({response.status_code})."
|
427 |
|
|
|
1 |
+
# main.py (Correcting SyntaxError at line 424)
|
2 |
import os
|
3 |
import re
|
4 |
import logging
|
|
|
89 |
|
90 |
OPENROUTER_MODEL = os.environ.get("OPENROUTER_MODEL", "deepseek/deepseek-chat-v3-0324:free")
|
91 |
APIFY_ACTOR_ID = os.environ.get("APIFY_ACTOR_ID", "karamelo~youtube-transcripts")
|
|
|
92 |
GEMINI_MODEL = os.environ.get("GEMINI_MODEL", "gemini-2.0-flash")
|
93 |
|
94 |
if not TELEGRAM_TOKEN: logger.critical("❌ FATAL: TELEGRAM_TOKEN not found."); raise RuntimeError("Exiting: Telegram token missing.")
|
|
|
162 |
if not video_id: logger.error("[Supadata] No video_id provided"); return None
|
163 |
if not api_key: logger.error("[Supadata] API key missing."); return None
|
164 |
logger.info(f"[Supadata] Attempting fetch for video ID: {video_id}")
|
165 |
+
api_endpoint = "https://api.supadata.ai/v1/youtube/transcript" # Corrected URL
|
166 |
params = {"videoId": video_id, "format": "text"}; headers = {"X-API-Key": api_key}
|
167 |
try:
|
168 |
async with httpx.AsyncClient(timeout=30.0) as client:
|
|
|
333 |
MAX_INPUT_LENGTH = 1000000
|
334 |
if len(text) > MAX_INPUT_LENGTH: logger.warning(f"[Gemini Fallback] Input length ({len(text)}) exceeds limit ({MAX_INPUT_LENGTH}). Truncating."); text = text[:MAX_INPUT_LENGTH] + "... (Content truncated)"
|
335 |
full_prompt = f"{prompt}\n\n{text}"
|
|
|
336 |
# *** FIX: Set all safety settings to BLOCK_NONE ***
|
337 |
safety_settings = {
|
338 |
HarmCategory.HARM_CATEGORY_HARASSMENT: HarmBlockThreshold.BLOCK_NONE,
|
339 |
HarmCategory.HARM_CATEGORY_HATE_SPEECH: HarmBlockThreshold.BLOCK_NONE,
|
340 |
HarmCategory.HARM_CATEGORY_SEXUALLY_EXPLICIT: HarmBlockThreshold.BLOCK_NONE,
|
341 |
HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT: HarmBlockThreshold.BLOCK_NONE,
|
342 |
+
# getattr used for safety in case the category doesn't exist in the SDK version
|
|
|
|
|
343 |
getattr(HarmCategory, 'HARM_CATEGORY_CIVIC_INTEGRITY', None): HarmBlockThreshold.BLOCK_NONE
|
344 |
}
|
|
|
345 |
safety_settings = {k: v for k, v in safety_settings.items() if k is not None}
|
346 |
logger.debug(f"[Gemini Fallback] Using safety settings: {safety_settings}")
|
347 |
|
|
|
348 |
try:
|
349 |
logger.debug(f"[Gemini Fallback] Initializing model {GEMINI_MODEL}")
|
350 |
model = genai.GenerativeModel(GEMINI_MODEL)
|
|
|
353 |
response = await model.generate_content_async( full_prompt, safety_settings=safety_settings, request_options=request_options )
|
354 |
logger.info("[Gemini Fallback] Received response from Gemini.")
|
355 |
|
356 |
+
if response.prompt_feedback.block_reason: logger.warning(f"[Gemini Fallback] Request blocked unexpectedly. Reason: {response.prompt_feedback.block_reason}");
|
|
|
|
|
357 |
for cand in response.candidates:
|
358 |
+
if cand.finish_reason == 'SAFETY': logger.warning(f"[Gemini Fallback] Candidate blocked due to SAFETY. Ratings: {cand.safety_ratings}")
|
|
|
359 |
|
360 |
+
try: summary = response.text
|
361 |
+
except ValueError as e: logger.warning(f"[Gemini Fallback] Error accessing response text (likely blocked content): {e}"); summary = None
|
|
|
|
|
|
|
|
|
|
|
|
|
362 |
|
363 |
if summary: logger.info(f"[Gemini Fallback] Success generating summary. Output len: {len(summary)}"); return summary.strip().replace('_', r'\_').replace('*', r'\*').replace('[', r'\[').replace('`', r'\`')
|
364 |
else: logger.warning(f"[Gemini Fallback] Gemini returned empty summary or content was blocked. Finish reason: {response.candidates[0].finish_reason if response.candidates else 'N/A'}"); return "Sorry, the fallback AI model did not provide a summary (possibly due to content filters)."
|
|
|
377 |
if len(text) > MAX_INPUT_LENGTH: logger.warning(f"[Primary Summary] Input length ({len(text)}) exceeds limit ({MAX_INPUT_LENGTH}). Truncating."); text = text[:MAX_INPUT_LENGTH] + "... (Content truncated)"
|
378 |
full_prompt = f"{prompt}\n\n{text}"
|
379 |
headers = { "Authorization": f"Bearer {OPENROUTER_API_KEY}", "Content-Type": "application/json" }; payload = { "model": OPENROUTER_MODEL, "messages": [{"role": "user", "content": full_prompt}] }; openrouter_api_endpoint = "https://openrouter.ai/api/v1/chat/completions"
|
380 |
+
api_timeouts = httpx.Timeout(15.0, read=10.0, write=15.0, pool=60.0)
|
381 |
response = None
|
382 |
|
383 |
try:
|
|
|
406 |
elif response.status_code == 429: logger.warning("[Primary Summary] OpenRouter Rate Limit Exceeded (429)."); return "Sorry, primary AI model is busy. Try again."
|
407 |
elif response.status_code == 500: logger.error(f"[Primary Summary] OpenRouter Internal Server Error (500). Resp:{response.text[:500]}"); return "Sorry, primary AI service internal error."
|
408 |
else:
|
409 |
+
error_info = "";
|
410 |
+
try: # Correct Indentation
|
411 |
+
error_info = response.json().get("error", {}).get("message", "")
|
412 |
+
except Exception: pass
|
413 |
logger.error(f"[Primary Summary] Unexpected status {response.status_code} from OpenRouter. Error: '{error_info}' Resp:{response.text[:500]}");
|
414 |
return f"Sorry, primary AI service returned unexpected status ({response.status_code})."
|
415 |
|