Spaces:
Sleeping
Sleeping
| # modules/utils.py | |
| """ | |
| A toolbox of essential, reusable utility functions for Project Asclepius. | |
| This module helps with common tasks like data cleaning, formatting, and | |
| safe string evaluation, promoting code reuse and maintainability. | |
| """ | |
| import ast | |
| from PIL import Image | |
| import io | |
| import base64 | |
| def clean_user_input(text: str) -> str: | |
| """ | |
| Sanitizes user input by removing leading/trailing whitespace and excessive newlines. | |
| This is a basic but important step to ensure consistent input for the APIs and AI models. | |
| Args: | |
| text (str): The raw user input string. | |
| Returns: | |
| str: The cleaned string. | |
| """ | |
| if not isinstance(text, str): | |
| return "" | |
| return " ".join(text.strip().split()) | |
| def safe_literal_eval(s: str) -> list | dict | None: | |
| """ | |
| Safely evaluates a string that should contain a Python literal (like a list or dict). | |
| Uses `ast.literal_eval` to prevent arbitrary code execution, which is a major | |
| security risk with the standard `eval()` function. | |
| This is crucial for parsing the string-based list output from Gemini's | |
| term extraction prompt. | |
| Args: | |
| s (str): The string to evaluate. | |
| Returns: | |
| list | dict | None: The parsed Python object, or None if evaluation fails. | |
| """ | |
| try: | |
| return ast.literal_eval(s) | |
| except (ValueError, SyntaxError, TypeError, MemoryError, KeyError): | |
| # Catches a wide range of potential parsing errors | |
| print(f"Warning: safe_literal_eval failed to parse string: {s}") | |
| return None | |
| def format_list_as_markdown(items: list[str]) -> str: | |
| """ | |
| Converts a simple Python list of strings into a formatted Markdown bulleted list. | |
| Args: | |
| items (list[str]): A list of strings. | |
| Returns: | |
| str: A Markdown formatted string. | |
| """ | |
| if not items: | |
| return "N/A" | |
| return "\n".join(f"- {item}" for item in items) | |
| def create_placeholder_image(width: int = 400, height: int = 300, text: str = "Awaiting Image") -> Image.Image: | |
| """ | |
| Generates a simple placeholder PIL Image. | |
| Useful for testing the vision pipeline without needing actual images. | |
| Args: | |
| width (int): The width of the placeholder image. | |
| height (int): The height of the placeholder image. | |
| text (str): The text to display on the placeholder. | |
| Returns: | |
| Image.Image: A PIL Image object. | |
| """ | |
| # This function would typically use a library like Pillow's ImageDraw | |
| # to create an image from scratch. For simplicity in this example, | |
| # we'll assume a pre-made placeholder or skip detailed implementation. | |
| # For a real implementation, you'd do: | |
| # from PIL import Image, ImageDraw, ImageFont | |
| # img = Image.new('RGB', (width, height), color = (73, 109, 137)) | |
| # d = ImageDraw.Draw(img) | |
| # d.text((10,10), text, fill=(255,255,0)) | |
| # return img | |
| # Returning a simple blank image for now | |
| return Image.new('RGB', (width, height), 'grey') | |
| def image_to_base64(image: Image.Image, format: str = "PNG") -> str: | |
| """ | |
| Encodes a PIL Image into a Base64 string. | |
| Useful for embedding images directly in Markdown or HTML if needed, | |
| though our current approach sends the PIL object directly to Gemini. | |
| Args: | |
| image (Image.Image): The PIL image to encode. | |
| format (str): The image format (e.g., "PNG", "JPEG"). | |
| Returns: | |
| str: The Base64 encoded string. | |
| """ | |
| buffered = io.BytesIO() | |
| image.save(buffered, format=format) | |
| img_str = base64.b64encode(buffered.getvalue()).decode("utf-8") | |
| return f"data:image/{format.lower()};base64,{img_str}" |