Spaces:
Running
Running
Update main.py
Browse files
main.py
CHANGED
@@ -336,16 +336,16 @@ async def _call_gemini(text: str, summary_type: str) -> Tuple[Optional[str], Opt
|
|
336 |
return None, "Error: Primary AI service (Gemini) not configured/available."
|
337 |
logger.info(f"[Gemini Primary] Generating {summary_type} summary using {GEMINI_MODEL}. Input length: {len(text)}")
|
338 |
|
339 |
-
# Define prompts
|
340 |
if summary_type == "paragraph": prompt = ("You are an AI model designed to provide concise summaries using British English spellings. Your output MUST be:\n" "β’ Clear and simple language suitable for someone unfamiliar with the topic.\n" "β’ Uses British English spellings throughout.\n" "β’ Straightforward and understandable vocabulary; avoid complex terms.\n" "β’ Presented as ONE SINGLE PARAGRAPH.\n" "β’ No more than 85 words maximum; but does not have to be exactly 85.\n" "β’ Considers the entire text content equally.\n" "β’ Uses semicolons (;) instead of em dashes (β or β).\n\n" "Here is the text to summarise:")
|
341 |
else: # points summary
|
342 |
-
prompt = ("You are an AI model designed to provide concise summaries using British English spellings. Your output MUST strictly follow this
|
343 |
"β’ For each distinct topic or section identified in the text, create a heading.\n"
|
344 |
-
"β’ Each heading MUST be
|
345 |
"β’ Immediately following each heading, list the key points as a bulleted list.\n"
|
346 |
"β’ Each bullet point MUST start with a hyphen and a space (- ) on a new line.\n"
|
347 |
"β’ The text within each bullet point should NOT contain any bold formatting.\n"
|
348 |
-
"β’ IMPORTANT: Never use bold formatting (double asterisks) within the text of the bullet points themselves.\n"
|
349 |
"β’ Use clear, simple, and straightforward language suitable for someone unfamiliar with the topic.\n"
|
350 |
"β’ Use British English spellings throughout.\n"
|
351 |
"β’ Avoid overly complex or advanced vocabulary.\n"
|
@@ -401,9 +401,10 @@ async def _call_gemini(text: str, summary_type: str) -> Tuple[Optional[str], Opt
|
|
401 |
|
402 |
if summary:
|
403 |
logger.info(f"[Gemini Primary] Success generating summary. Output len: {len(summary)}");
|
404 |
-
# Escape Markdown for Telegram
|
405 |
-
escaped_summary = summary.strip().replace('_', r'\_').replace('*', r'\*').replace('[', r'\[').replace('`', r'\`')
|
406 |
-
|
|
|
407 |
else:
|
408 |
finish_reason = response.candidates[0].finish_reason if response.candidates else 'N/A'
|
409 |
logger.warning(f"[Gemini Primary] Gemini returned empty summary or content was blocked. Finish reason: {finish_reason}");
|
@@ -421,16 +422,16 @@ async def _call_openrouter(text: str, summary_type: str) -> Tuple[Optional[str],
|
|
421 |
return None, "Error: Fallback AI service (OpenRouter) not configured/available."
|
422 |
logger.info(f"[OpenRouter Fallback] Generating {summary_type} summary using {OPENROUTER_MODEL}. Input length: {len(text)}")
|
423 |
|
424 |
-
# Define prompts
|
425 |
if summary_type == "paragraph": prompt = ("You are an AI model designed to provide concise summaries using British English spellings. Your output MUST be:\n" "β’ Clear and simple language suitable for someone unfamiliar with the topic.\n" "β’ Uses British English spellings throughout.\n" "β’ Straightforward and understandable vocabulary; avoid complex terms.\n" "β’ Presented as ONE SINGLE PARAGRAPH.\n" "β’ No more than 85 words maximum; but does not have to be exactly 85.\n" "β’ Considers the entire text content equally.\n" "β’ Uses semicolons (;) instead of em dashes (β or β).\n\n" "Here is the text to summarise:")
|
426 |
else: # points summary
|
427 |
-
prompt = ("You are an AI model designed to provide concise summaries using British English spellings. Your output MUST strictly follow this
|
428 |
"β’ For each distinct topic or section identified in the text, create a heading.\n"
|
429 |
-
"β’ Each heading MUST be
|
430 |
"β’ Immediately following each heading, list the key points as a bulleted list.\n"
|
431 |
"β’ Each bullet point MUST start with a hyphen and a space (- ) on a new line.\n"
|
432 |
"β’ The text within each bullet point should NOT contain any bold formatting.\n"
|
433 |
-
"β’ IMPORTANT: Never use bold formatting (double asterisks) within the text of the bullet points themselves.\n"
|
434 |
"β’ Use clear, simple, and straightforward language suitable for someone unfamiliar with the topic.\n"
|
435 |
"β’ Use British English spellings throughout.\n"
|
436 |
"β’ Avoid overly complex or advanced vocabulary.\n"
|
@@ -470,9 +471,9 @@ async def _call_openrouter(text: str, summary_type: str) -> Tuple[Optional[str],
|
|
470 |
summary = message.get("content")
|
471 |
if summary:
|
472 |
logger.info(f"[OpenRouter Fallback] Success via OpenRouter. Output len: {len(summary)}")
|
473 |
-
# Escape Markdown for Telegram
|
474 |
-
escaped_summary = summary.strip().replace('_', r'\_').replace('*', r'\*').replace('[', r'\[').replace('`', r'\`')
|
475 |
-
return
|
476 |
else:
|
477 |
logger.warning(f"[OpenRouter Fallback] OpenRouter success but content empty. Resp: {data}")
|
478 |
return None, "Sorry, the fallback AI model returned an empty summary."
|
@@ -513,6 +514,7 @@ async def _call_openrouter(text: str, summary_type: str) -> Tuple[Optional[str],
|
|
513 |
async def generate_summary(text: str, summary_type: str) -> str:
|
514 |
"""
|
515 |
Generates summary using Gemini (Primary) and falls back to OpenRouter if needed.
|
|
|
516 |
"""
|
517 |
global _gemini_primary_enabled, _openrouter_fallback_enabled, GEMINI_MODEL, OPENROUTER_MODEL
|
518 |
logger.info(f"[Summary Generation] Starting process. Primary: Gemini ({GEMINI_MODEL}), Fallback: OpenRouter ({OPENROUTER_MODEL})")
|
@@ -526,6 +528,7 @@ async def generate_summary(text: str, summary_type: str) -> str:
|
|
526 |
final_summary, error_message = await _call_gemini(text, summary_type)
|
527 |
if final_summary:
|
528 |
logger.info(f"[Summary Generation] Success with primary AI (Gemini).")
|
|
|
529 |
return final_summary
|
530 |
else:
|
531 |
logger.warning(f"[Summary Generation] Primary AI (Gemini) failed or returned unusable result. Error: {error_message}. Proceeding to fallback.")
|
@@ -539,6 +542,7 @@ async def generate_summary(text: str, summary_type: str) -> str:
|
|
539 |
fallback_summary, fallback_error = await _call_openrouter(text, summary_type)
|
540 |
if fallback_summary:
|
541 |
logger.info(f"[Summary Generation] Success with fallback AI (OpenRouter).")
|
|
|
542 |
return fallback_summary
|
543 |
else:
|
544 |
logger.error(f"[Summary Generation] Fallback AI (OpenRouter) also failed. Error: {fallback_error}")
|
@@ -602,8 +606,10 @@ async def process_summary_task( user_id: int, chat_id: int, message_id_to_edit:
|
|
602 |
if final_summary.startswith("Error:") or final_summary.startswith("Sorry,"): user_feedback_message = final_summary; logger.warning(f"[Task {task_id}] Summary generation failed: {final_summary}")
|
603 |
else:
|
604 |
max_length = 4096; summary_parts = [final_summary[i:i+max_length] for i in range(0, len(final_summary), max_length)]
|
605 |
-
|
606 |
-
|
|
|
|
|
607 |
success = True; logger.info(f"[Task {task_id}] Successfully sent summary ({len(summary_parts)} parts)."); user_feedback_message = None
|
608 |
elif user_feedback_message: logger.warning(f"[Task {task_id}] Sending failure feedback: {user_feedback_message}"); await retry_bot_operation( bot.send_message, chat_id=chat_id, text=user_feedback_message, link_preview_options={'is_disabled': True} )
|
609 |
except Exception as e:
|
|
|
336 |
return None, "Error: Primary AI service (Gemini) not configured/available."
|
337 |
logger.info(f"[Gemini Primary] Generating {summary_type} summary using {GEMINI_MODEL}. Input length: {len(text)}")
|
338 |
|
339 |
+
# Define prompts
|
340 |
if summary_type == "paragraph": prompt = ("You are an AI model designed to provide concise summaries using British English spellings. Your output MUST be:\n" "β’ Clear and simple language suitable for someone unfamiliar with the topic.\n" "β’ Uses British English spellings throughout.\n" "β’ Straightforward and understandable vocabulary; avoid complex terms.\n" "β’ Presented as ONE SINGLE PARAGRAPH.\n" "β’ No more than 85 words maximum; but does not have to be exactly 85.\n" "β’ Considers the entire text content equally.\n" "β’ Uses semicolons (;) instead of em dashes (β or β).\n\n" "Here is the text to summarise:")
|
341 |
else: # points summary
|
342 |
+
prompt = ("You are an AI model designed to provide concise summaries using British English spellings. Your output MUST strictly follow this format:\n\n"
|
343 |
"β’ For each distinct topic or section identified in the text, create a heading.\n"
|
344 |
+
"β’ Each heading MUST be plain text without any formatting (e.g., Section Title).\n" # MODIFIED HERE
|
345 |
"β’ Immediately following each heading, list the key points as a bulleted list.\n"
|
346 |
"β’ Each bullet point MUST start with a hyphen and a space (- ) on a new line.\n"
|
347 |
"β’ The text within each bullet point should NOT contain any bold formatting.\n"
|
348 |
+
"β’ IMPORTANT: Never use bold formatting (double asterisks) within the text of the bullet points themselves.\n"
|
349 |
"β’ Use clear, simple, and straightforward language suitable for someone unfamiliar with the topic.\n"
|
350 |
"β’ Use British English spellings throughout.\n"
|
351 |
"β’ Avoid overly complex or advanced vocabulary.\n"
|
|
|
401 |
|
402 |
if summary:
|
403 |
logger.info(f"[Gemini Primary] Success generating summary. Output len: {len(summary)}");
|
404 |
+
# Escape Markdown for Telegram only if necessary (Removed escaping as it might conflict with plain heading)
|
405 |
+
# escaped_summary = summary.strip().replace('_', r'\_').replace('*', r'\*').replace('[', r'\[').replace('`', r'\`')
|
406 |
+
# Let's see if the AI respects the instruction without further escaping. If not, we might need selective escaping.
|
407 |
+
return summary.strip(), None
|
408 |
else:
|
409 |
finish_reason = response.candidates[0].finish_reason if response.candidates else 'N/A'
|
410 |
logger.warning(f"[Gemini Primary] Gemini returned empty summary or content was blocked. Finish reason: {finish_reason}");
|
|
|
422 |
return None, "Error: Fallback AI service (OpenRouter) not configured/available."
|
423 |
logger.info(f"[OpenRouter Fallback] Generating {summary_type} summary using {OPENROUTER_MODEL}. Input length: {len(text)}")
|
424 |
|
425 |
+
# Define prompts
|
426 |
if summary_type == "paragraph": prompt = ("You are an AI model designed to provide concise summaries using British English spellings. Your output MUST be:\n" "β’ Clear and simple language suitable for someone unfamiliar with the topic.\n" "β’ Uses British English spellings throughout.\n" "β’ Straightforward and understandable vocabulary; avoid complex terms.\n" "β’ Presented as ONE SINGLE PARAGRAPH.\n" "β’ No more than 85 words maximum; but does not have to be exactly 85.\n" "β’ Considers the entire text content equally.\n" "β’ Uses semicolons (;) instead of em dashes (β or β).\n\n" "Here is the text to summarise:")
|
427 |
else: # points summary
|
428 |
+
prompt = ("You are an AI model designed to provide concise summaries using British English spellings. Your output MUST strictly follow this format:\n\n"
|
429 |
"β’ For each distinct topic or section identified in the text, create a heading.\n"
|
430 |
+
"β’ Each heading MUST be plain text without any formatting (e.g., Section Title).\n" # MODIFIED HERE
|
431 |
"β’ Immediately following each heading, list the key points as a bulleted list.\n"
|
432 |
"β’ Each bullet point MUST start with a hyphen and a space (- ) on a new line.\n"
|
433 |
"β’ The text within each bullet point should NOT contain any bold formatting.\n"
|
434 |
+
"β’ IMPORTANT: Never use bold formatting (double asterisks) within the text of the bullet points themselves.\n"
|
435 |
"β’ Use clear, simple, and straightforward language suitable for someone unfamiliar with the topic.\n"
|
436 |
"β’ Use British English spellings throughout.\n"
|
437 |
"β’ Avoid overly complex or advanced vocabulary.\n"
|
|
|
471 |
summary = message.get("content")
|
472 |
if summary:
|
473 |
logger.info(f"[OpenRouter Fallback] Success via OpenRouter. Output len: {len(summary)}")
|
474 |
+
# Escape Markdown for Telegram only if necessary (Removed escaping)
|
475 |
+
# escaped_summary = summary.strip().replace('_', r'\_').replace('*', r'\*').replace('[', r'\[').replace('`', r'\`')
|
476 |
+
return summary.strip(), None
|
477 |
else:
|
478 |
logger.warning(f"[OpenRouter Fallback] OpenRouter success but content empty. Resp: {data}")
|
479 |
return None, "Sorry, the fallback AI model returned an empty summary."
|
|
|
514 |
async def generate_summary(text: str, summary_type: str) -> str:
|
515 |
"""
|
516 |
Generates summary using Gemini (Primary) and falls back to OpenRouter if needed.
|
517 |
+
Ensures point-based summaries have plain text headings.
|
518 |
"""
|
519 |
global _gemini_primary_enabled, _openrouter_fallback_enabled, GEMINI_MODEL, OPENROUTER_MODEL
|
520 |
logger.info(f"[Summary Generation] Starting process. Primary: Gemini ({GEMINI_MODEL}), Fallback: OpenRouter ({OPENROUTER_MODEL})")
|
|
|
528 |
final_summary, error_message = await _call_gemini(text, summary_type)
|
529 |
if final_summary:
|
530 |
logger.info(f"[Summary Generation] Success with primary AI (Gemini).")
|
531 |
+
# Return directly - prompt handles formatting
|
532 |
return final_summary
|
533 |
else:
|
534 |
logger.warning(f"[Summary Generation] Primary AI (Gemini) failed or returned unusable result. Error: {error_message}. Proceeding to fallback.")
|
|
|
542 |
fallback_summary, fallback_error = await _call_openrouter(text, summary_type)
|
543 |
if fallback_summary:
|
544 |
logger.info(f"[Summary Generation] Success with fallback AI (OpenRouter).")
|
545 |
+
# Return directly - prompt handles formatting
|
546 |
return fallback_summary
|
547 |
else:
|
548 |
logger.error(f"[Summary Generation] Fallback AI (OpenRouter) also failed. Error: {fallback_error}")
|
|
|
606 |
if final_summary.startswith("Error:") or final_summary.startswith("Sorry,"): user_feedback_message = final_summary; logger.warning(f"[Task {task_id}] Summary generation failed: {final_summary}")
|
607 |
else:
|
608 |
max_length = 4096; summary_parts = [final_summary[i:i+max_length] for i in range(0, len(final_summary), max_length)]
|
609 |
+
# Sending potentially unescaped summary directly - assuming AI follows instructions
|
610 |
+
# ParseMode.MARKDOWN might interpret unintended things, test needed. Consider ParseMode=None if issues arise.
|
611 |
+
await retry_bot_operation( bot.send_message, chat_id=chat_id, text=summary_parts[0], parse_mode=None, link_preview_options={'is_disabled': True} )
|
612 |
+
for part in summary_parts[1:]: await asyncio.sleep(0.5); await retry_bot_operation( bot.send_message, chat_id=chat_id, text=part, parse_mode=None, link_preview_options={'is_disabled': True} )
|
613 |
success = True; logger.info(f"[Task {task_id}] Successfully sent summary ({len(summary_parts)} parts)."); user_feedback_message = None
|
614 |
elif user_feedback_message: logger.warning(f"[Task {task_id}] Sending failure feedback: {user_feedback_message}"); await retry_bot_operation( bot.send_message, chat_id=chat_id, text=user_feedback_message, link_preview_options={'is_disabled': True} )
|
615 |
except Exception as e:
|