Spaces:
Running
Running
Update main.py
Browse files
main.py
CHANGED
@@ -844,38 +844,51 @@ async def _call_groq(text: str, summary_type: str) -> Tuple[Optional[str], Optio
|
|
844 |
|
845 |
async def _call_gemini(text: str, summary_type: str, model_name: str) -> Tuple[Optional[str], Optional[str]]:
|
846 |
"""Internal function to call Gemini API. Returns (summary, error_message)."""
|
847 |
-
|
|
|
848 |
if not _gemini_api_enabled:
|
849 |
logger.error(f"[Gemini {model_name}] Called but API is disabled.");
|
850 |
return None, f"Error: AI service (Gemini API) not configured/available."
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
851 |
logger.info(f"[Gemini {model_name}] Generating {summary_type} summary using {model_name}. Input length: {len(text)}")
|
852 |
|
853 |
prompt = PROMPT_PARAGRAPH if summary_type == "paragraph" else PROMPT_POINTS
|
854 |
-
# Determine max input length based on model - Flash Preview is likely 1M like Flash 2.0, Pro Exp is 2M
|
855 |
-
# Use a conservative estimate for safety, but larger than Llama/Deepseek
|
856 |
MAX_INPUT_LENGTH_GEMINI = 900000
|
857 |
-
if 'pro-exp' in model_name.lower(): MAX_INPUT_LENGTH_GEMINI = 1800000
|
858 |
|
859 |
if len(text) > MAX_INPUT_LENGTH_GEMINI:
|
860 |
logger.warning(f"[Gemini {model_name}] Input length ({len(text)}) exceeds estimated limit ({MAX_INPUT_LENGTH_GEMINI}). Truncating.");
|
861 |
text = text[:MAX_INPUT_LENGTH_GEMINI] + "... (Content truncated)"
|
862 |
full_prompt = f"{prompt}\n\n{text}"
|
863 |
|
864 |
-
# Define safety_settings
|
865 |
-
# This satisfies the requirement "make sure that all safety censors are set to none".
|
866 |
try:
|
|
|
867 |
safety_settings = {
|
868 |
HarmCategory.HARM_CATEGORY_HARASSMENT: HarmBlockThreshold.BLOCK_NONE,
|
869 |
HarmCategory.HARM_CATEGORY_HATE_SPEECH: HarmBlockThreshold.BLOCK_NONE,
|
870 |
HarmCategory.HARM_CATEGORY_SEXUALLY_EXPLICIT: HarmBlockThreshold.BLOCK_NONE,
|
871 |
HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT: HarmBlockThreshold.BLOCK_NONE,
|
872 |
-
HarmCategory.HARM_CATEGORY_CIVIC_INTEGRITY: HarmBlockThreshold.BLOCK_NONE, # Present in previous code
|
873 |
}
|
874 |
logger.debug(f"[Gemini {model_name}] Using safety settings: { {k.name: v.name for k, v in safety_settings.items()} }")
|
875 |
-
|
876 |
-
|
877 |
-
|
878 |
-
|
|
|
|
|
|
|
|
|
879 |
try:
|
880 |
logger.debug(f"[Gemini {model_name}] Initializing model {model_name}")
|
881 |
model = genai.GenerativeModel(model_name)
|
@@ -931,24 +944,39 @@ async def _call_gemini(text: str, summary_type: str, model_name: str) -> Tuple[O
|
|
931 |
# This can happen if the response structure changes or expected fields are missing
|
932 |
logger.error(f"[Gemini {model_name}] AttributeError during Gemini response processing: {ae}. SDK might be incompatible or response structure unexpected.", exc_info=True);
|
933 |
return None, f"Sorry, there was an issue processing the response from the AI service ({model_name}). Attribute error."
|
|
|
|
|
|
|
|
|
934 |
except google.api_core.exceptions.InvalidArgument as iae:
|
935 |
# Catch specific InvalidArgument, often related to safety settings or model params
|
936 |
logger.error(f"[Gemini {model_name}] Invalid Argument error from Gemini API: {iae}", exc_info=False) # Don't need full stack trace often
|
937 |
error_detail = str(iae)
|
938 |
user_message = f"Sorry, the AI service ({model_name}) reported an invalid argument."
|
|
|
939 |
if "safety_settings" in error_detail: user_message += " (Safety Settings issue)."
|
940 |
elif "temperature" in error_detail: user_message += " (Generation Parameter issue)."
|
|
|
941 |
return None, user_message
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
942 |
except google.api_core.exceptions.GoogleAPIError as gae:
|
943 |
-
# Catch other potential Google API errors
|
944 |
logger.error(f"[Gemini {model_name}] Google API error during Gemini call: {gae}", exc_info=False)
|
945 |
-
status_code = getattr(gae, 'code', 'Unknown')
|
946 |
user_message = f"Sorry, the AI service ({model_name}) encountered an API error (Code: {status_code})."
|
947 |
-
|
948 |
-
|
|
|
949 |
return None, user_message
|
950 |
except Exception as e:
|
951 |
-
# General catch-all for unexpected issues
|
952 |
logger.error(f"[Gemini {model_name}] Unexpected error during Gemini API call: {e}", exc_info=True);
|
953 |
error_msg = f"Sorry, an unexpected error occurred while using the AI service ({model_name})."
|
954 |
return None, error_msg
|
|
|
844 |
|
845 |
async def _call_gemini(text: str, summary_type: str, model_name: str) -> Tuple[Optional[str], Optional[str]]:
|
846 |
"""Internal function to call Gemini API. Returns (summary, error_message)."""
|
847 |
+
# Initial check (already present)
|
848 |
+
global _gemini_api_enabled, HarmCategory, HarmBlockThreshold
|
849 |
if not _gemini_api_enabled:
|
850 |
logger.error(f"[Gemini {model_name}] Called but API is disabled.");
|
851 |
return None, f"Error: AI service (Gemini API) not configured/available."
|
852 |
+
|
853 |
+
# --- ADDED EXPLICIT CHECK ---
|
854 |
+
# Double-check if the necessary types were imported correctly, even if _gemini_api_enabled is True.
|
855 |
+
# This guards against cases where the SDK might be partially available or the import didn't fully register.
|
856 |
+
if HarmCategory is None or HarmBlockThreshold is None:
|
857 |
+
logger.error(f"[Gemini {model_name}] Safety setting types (HarmCategory/HarmBlockThreshold) are None. SDK might be partially loaded or initial import failed.")
|
858 |
+
# Provide a user-facing error that points to configuration/internal issue
|
859 |
+
return None, f"Sorry, an internal configuration error occurred with the AI service ({model_name}). Safety types missing."
|
860 |
+
# --- END ADDED CHECK ---
|
861 |
+
|
862 |
logger.info(f"[Gemini {model_name}] Generating {summary_type} summary using {model_name}. Input length: {len(text)}")
|
863 |
|
864 |
prompt = PROMPT_PARAGRAPH if summary_type == "paragraph" else PROMPT_POINTS
|
|
|
|
|
865 |
MAX_INPUT_LENGTH_GEMINI = 900000
|
866 |
+
if 'pro-exp' in model_name.lower(): MAX_INPUT_LENGTH_GEMINI = 1800000
|
867 |
|
868 |
if len(text) > MAX_INPUT_LENGTH_GEMINI:
|
869 |
logger.warning(f"[Gemini {model_name}] Input length ({len(text)}) exceeds estimated limit ({MAX_INPUT_LENGTH_GEMINI}). Truncating.");
|
870 |
text = text[:MAX_INPUT_LENGTH_GEMINI] + "... (Content truncated)"
|
871 |
full_prompt = f"{prompt}\n\n{text}"
|
872 |
|
873 |
+
# Define safety_settings - Now guarded by the explicit check above
|
|
|
874 |
try:
|
875 |
+
# These constants should now be valid if the check above passed
|
876 |
safety_settings = {
|
877 |
HarmCategory.HARM_CATEGORY_HARASSMENT: HarmBlockThreshold.BLOCK_NONE,
|
878 |
HarmCategory.HARM_CATEGORY_HATE_SPEECH: HarmBlockThreshold.BLOCK_NONE,
|
879 |
HarmCategory.HARM_CATEGORY_SEXUALLY_EXPLICIT: HarmBlockThreshold.BLOCK_NONE,
|
880 |
HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT: HarmBlockThreshold.BLOCK_NONE,
|
881 |
+
HarmCategory.HARM_CATEGORY_CIVIC_INTEGRITY: HarmBlockThreshold.BLOCK_NONE, # Present in previous code and docs
|
882 |
}
|
883 |
logger.debug(f"[Gemini {model_name}] Using safety settings: { {k.name: v.name for k, v in safety_settings.items()} }")
|
884 |
+
# Keep the original NameError/AttributeError check as a final fallback,
|
885 |
+
# though the explicit None check should ideally prevent reaching here with this specific error.
|
886 |
+
except (NameError, AttributeError) as e:
|
887 |
+
# Log with more context if this somehow still happens
|
888 |
+
logger.error(f"[Gemini {model_name}] Unexpected error defining safety settings ({type(e).__name__}): {e}. HarmCategory/HarmBlockThreshold might be invalid despite passing initial checks.", exc_info=True)
|
889 |
+
return None, f"Sorry, an internal error occurred configuring the AI service ({model_name}). Safety settings definition failed unexpectedly."
|
890 |
+
|
891 |
+
# --- Rest of the function (API call, response handling) remains the same as the previous version ---
|
892 |
try:
|
893 |
logger.debug(f"[Gemini {model_name}] Initializing model {model_name}")
|
894 |
model = genai.GenerativeModel(model_name)
|
|
|
944 |
# This can happen if the response structure changes or expected fields are missing
|
945 |
logger.error(f"[Gemini {model_name}] AttributeError during Gemini response processing: {ae}. SDK might be incompatible or response structure unexpected.", exc_info=True);
|
946 |
return None, f"Sorry, there was an issue processing the response from the AI service ({model_name}). Attribute error."
|
947 |
+
# Use google.api_core.exceptions if available, otherwise use general Exception
|
948 |
+
except ImportError: # Handle if google.api_core isn't available for some reason
|
949 |
+
logger.warning("[Gemini] google.api_core.exceptions not available for specific error handling.")
|
950 |
+
pass # Fall through to general Exception
|
951 |
except google.api_core.exceptions.InvalidArgument as iae:
|
952 |
# Catch specific InvalidArgument, often related to safety settings or model params
|
953 |
logger.error(f"[Gemini {model_name}] Invalid Argument error from Gemini API: {iae}", exc_info=False) # Don't need full stack trace often
|
954 |
error_detail = str(iae)
|
955 |
user_message = f"Sorry, the AI service ({model_name}) reported an invalid argument."
|
956 |
+
# Add more specific messages based on common InvalidArgument errors
|
957 |
if "safety_settings" in error_detail: user_message += " (Safety Settings issue)."
|
958 |
elif "temperature" in error_detail: user_message += " (Generation Parameter issue)."
|
959 |
+
elif "API key not valid" in error_detail: user_message = f"Error: The API key for the AI service ({model_name}) is invalid."
|
960 |
return None, user_message
|
961 |
+
except google.api_core.exceptions.PermissionDenied as pde:
|
962 |
+
logger.error(f"[Gemini {model_name}] Permission Denied error from Gemini API: {pde}", exc_info=False)
|
963 |
+
user_message = f"Error: Access denied for the AI service ({model_name}). Check API key permissions."
|
964 |
+
return None, user_message
|
965 |
+
except google.api_core.exceptions.ResourceExhausted as ree:
|
966 |
+
logger.error(f"[Gemini {model_name}] Resource Exhausted (Quota/Rate Limit) error from Gemini API: {ree}", exc_info=False)
|
967 |
+
user_message = f"Sorry, the AI model ({model_name}) is busy or quota exceeded. Please try again later."
|
968 |
+
return None, user_message
|
969 |
except google.api_core.exceptions.GoogleAPIError as gae:
|
970 |
+
# Catch other potential Google API errors
|
971 |
logger.error(f"[Gemini {model_name}] Google API error during Gemini call: {gae}", exc_info=False)
|
972 |
+
status_code = getattr(gae, 'code', 'Unknown') # Use code if available
|
973 |
user_message = f"Sorry, the AI service ({model_name}) encountered an API error (Code: {status_code})."
|
974 |
+
# Add specific known codes if needed, ResourceExhausted (429) handled above
|
975 |
+
if status_code == 500: user_message = f"Sorry, the AI service ({model_name}) had an internal server error."
|
976 |
+
elif status_code == 400: user_message = f"Sorry, there was a bad request sending data to the AI service ({model_name})." # Often model name typo or bad input structure
|
977 |
return None, user_message
|
978 |
except Exception as e:
|
979 |
+
# General catch-all for unexpected issues (e.g., network errors not caught by httpx inside SDK)
|
980 |
logger.error(f"[Gemini {model_name}] Unexpected error during Gemini API call: {e}", exc_info=True);
|
981 |
error_msg = f"Sorry, an unexpected error occurred while using the AI service ({model_name})."
|
982 |
return None, error_msg
|