Spaces:
Sleeping
Sleeping
| """ | |
| Utility functions for the Gemini AI Agent. | |
| """ | |
| import re | |
| import logging | |
| from typing import Optional | |
| logger = logging.getLogger(__name__) | |
| def sanitize_input(text: str) -> str: | |
| """ | |
| Sanitize user input by removing potentially harmful content. | |
| Args: | |
| text: Raw input text | |
| Returns: | |
| str: Sanitized text | |
| """ | |
| if not isinstance(text, str): | |
| return str(text) | |
| # Remove excessive whitespace | |
| text = re.sub(r'\s+', ' ', text.strip()) | |
| # Remove potential injection attempts (basic protection) | |
| text = text.replace('\\n', '\n').replace('\\t', '\t') | |
| return text | |
| def format_response(response: str) -> str: | |
| """ | |
| Format the AI response for better readability. | |
| Args: | |
| response: Raw response from the AI model | |
| Returns: | |
| str: Formatted response | |
| """ | |
| if not response: | |
| return "No response generated." | |
| # Clean up the response | |
| response = response.strip() | |
| # Ensure proper spacing after periods | |
| response = re.sub(r'\.([A-Z])', r'. \1', response) | |
| # Fix common formatting issues | |
| response = re.sub(r'\n\s*\n\s*\n', '\n\n', response) # Multiple newlines | |
| response = re.sub(r'([.!?])\s*([A-Z])', r'\1 \2', response) # Spacing after punctuation | |
| return response | |
| def truncate_text(text: str, max_length: int = 1000) -> str: | |
| """ | |
| Truncate text to a maximum length while preserving word boundaries. | |
| Args: | |
| text: Text to truncate | |
| max_length: Maximum length allowed | |
| Returns: | |
| str: Truncated text | |
| """ | |
| if len(text) <= max_length: | |
| return text | |
| # Find the last space before the max_length | |
| truncated = text[:max_length] | |
| last_space = truncated.rfind(' ') | |
| if last_space > max_length * 0.8: # If space is reasonably close to end | |
| return truncated[:last_space] + "..." | |
| else: | |
| return truncated + "..." | |
| def extract_code_blocks(text: str) -> list: | |
| """ | |
| Extract code blocks from markdown-formatted text. | |
| Args: | |
| text: Text containing potential code blocks | |
| Returns: | |
| list: List of code blocks found | |
| """ | |
| code_pattern = r'```(\w+)?\n(.*?)\n```' | |
| matches = re.findall(code_pattern, text, re.DOTALL) | |
| return [{'language': match[0] or 'text', 'code': match[1]} for match in matches] | |
| def validate_question(question: str) -> tuple[bool, Optional[str]]: | |
| """ | |
| Validate if a question is appropriate and well-formed. | |
| Args: | |
| question: The question to validate | |
| Returns: | |
| tuple: (is_valid, error_message) | |
| """ | |
| if not question or not question.strip(): | |
| return False, "Question cannot be empty." | |
| if len(question.strip()) < 3: | |
| return False, "Question is too short. Please provide more detail." | |
| if len(question) > 5000: | |
| return False, "Question is too long. Please keep it under 5000 characters." | |
| return True, None | |
| def format_error_message(error: Exception) -> str: | |
| """ | |
| Format error messages for user display. | |
| Args: | |
| error: The exception that occurred | |
| Returns: | |
| str: User-friendly error message | |
| """ | |
| error_type = type(error).__name__ | |
| # Map common errors to user-friendly messages | |
| error_messages = { | |
| 'ConnectionError': 'Unable to connect to the AI service. Please check your internet connection.', | |
| 'TimeoutError': 'The request timed out. Please try again with a shorter question.', | |
| 'ValueError': 'Invalid input provided. Please check your question format.', | |
| 'KeyError': 'Configuration error. Please check your API settings.', | |
| 'PermissionError': 'Access denied. Please check your API key permissions.' | |
| } | |
| user_message = error_messages.get(error_type, f"An unexpected error occurred: {str(error)}") | |
| logger.error(f"Error formatted for user: {error_type} - {str(error)}") | |
| return user_message |