mgbam commited on
Commit
51d35a8
·
verified ·
1 Parent(s): 89db8f5

Update modules/utils.py

Browse files
Files changed (1) hide show
  1. modules/utils.py +107 -0
modules/utils.py CHANGED
@@ -0,0 +1,107 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # modules/utils.py
2
+ """
3
+ A toolbox of essential, reusable utility functions for Project Asclepius.
4
+ This module helps with common tasks like data cleaning, formatting, and
5
+ safe string evaluation, promoting code reuse and maintainability.
6
+ """
7
+ import ast
8
+ from PIL import Image
9
+ import io
10
+ import base64
11
+
12
+ def clean_user_input(text: str) -> str:
13
+ """
14
+ Sanitizes user input by removing leading/trailing whitespace and excessive newlines.
15
+ This is a basic but important step to ensure consistent input for the APIs and AI models.
16
+
17
+ Args:
18
+ text (str): The raw user input string.
19
+
20
+ Returns:
21
+ str: The cleaned string.
22
+ """
23
+ if not isinstance(text, str):
24
+ return ""
25
+ return " ".join(text.strip().split())
26
+
27
+ def safe_literal_eval(s: str) -> list | dict | None:
28
+ """
29
+ Safely evaluates a string that should contain a Python literal (like a list or dict).
30
+ Uses `ast.literal_eval` to prevent arbitrary code execution, which is a major
31
+ security risk with the standard `eval()` function.
32
+
33
+ This is crucial for parsing the string-based list output from Gemini's
34
+ term extraction prompt.
35
+
36
+ Args:
37
+ s (str): The string to evaluate.
38
+
39
+ Returns:
40
+ list | dict | None: The parsed Python object, or None if evaluation fails.
41
+ """
42
+ try:
43
+ return ast.literal_eval(s)
44
+ except (ValueError, SyntaxError, TypeError, MemoryError, KeyError):
45
+ # Catches a wide range of potential parsing errors
46
+ print(f"Warning: safe_literal_eval failed to parse string: {s}")
47
+ return None
48
+
49
+ def format_list_as_markdown(items: list[str]) -> str:
50
+ """
51
+ Converts a simple Python list of strings into a formatted Markdown bulleted list.
52
+
53
+ Args:
54
+ items (list[str]): A list of strings.
55
+
56
+ Returns:
57
+ str: A Markdown formatted string.
58
+ """
59
+ if not items:
60
+ return "N/A"
61
+ return "\n".join(f"- {item}" for item in items)
62
+
63
+
64
+ def create_placeholder_image(width: int = 400, height: int = 300, text: str = "Awaiting Image") -> Image.Image:
65
+ """
66
+ Generates a simple placeholder PIL Image.
67
+ Useful for testing the vision pipeline without needing actual images.
68
+
69
+ Args:
70
+ width (int): The width of the placeholder image.
71
+ height (int): The height of the placeholder image.
72
+ text (str): The text to display on the placeholder.
73
+
74
+ Returns:
75
+ Image.Image: A PIL Image object.
76
+ """
77
+ # This function would typically use a library like Pillow's ImageDraw
78
+ # to create an image from scratch. For simplicity in this example,
79
+ # we'll assume a pre-made placeholder or skip detailed implementation.
80
+ # For a real implementation, you'd do:
81
+ # from PIL import Image, ImageDraw, ImageFont
82
+ # img = Image.new('RGB', (width, height), color = (73, 109, 137))
83
+ # d = ImageDraw.Draw(img)
84
+ # d.text((10,10), text, fill=(255,255,0))
85
+ # return img
86
+
87
+ # Returning a simple blank image for now
88
+ return Image.new('RGB', (width, height), 'grey')
89
+
90
+
91
+ def image_to_base64(image: Image.Image, format: str = "PNG") -> str:
92
+ """
93
+ Encodes a PIL Image into a Base64 string.
94
+ Useful for embedding images directly in Markdown or HTML if needed,
95
+ though our current approach sends the PIL object directly to Gemini.
96
+
97
+ Args:
98
+ image (Image.Image): The PIL image to encode.
99
+ format (str): The image format (e.g., "PNG", "JPEG").
100
+
101
+ Returns:
102
+ str: The Base64 encoded string.
103
+ """
104
+ buffered = io.BytesIO()
105
+ image.save(buffered, format=format)
106
+ img_str = base64.b64encode(buffered.getvalue()).decode("utf-8")
107
+ return f"data:image/{format.lower()};base64,{img_str}"