| import os |
| import ast |
| import io |
| import sys |
| import numpy as np |
| import pandas as pd |
| import scipy |
|
|
| from pathlib import Path |
| import mimetypes |
| import base64 |
|
|
| from google import genai |
| import requests |
|
|
| ALLOWED_MODULES = {"numpy", "pandas", "scipy"} |
| GEMINI_API_KEY = os.getenv("GEMINI_TOKEN") |
| GEMINI_MODEL_NAME = "gemini-2.0-flash" |
|
|
| def interpret_python_math_code(python_code: str) -> str: |
| """ |
| Interprets a string of Python code to perform math calculations. |
| |
| Security Note: This function uses exec(). While it attempts to restrict |
| imports to numpy, pandas, and scipy, and runs with a restricted |
| global scope, executing arbitrary code always carries risks. Ensure |
| that input code is from a trusted source or properly sanitized. |
| |
| The code must only import modules from the allowed list: numpy, pandas, scipy. |
| Submodules of these (e.g., numpy.linalg, scipy.stats) are permitted. |
| For example: |
| 'import numpy as np' is allowed. |
| 'from scipy.stats import norm' is allowed. |
| 'import os' is NOT allowed. |
| |
| To return a result, the code should either: |
| 1. End with an expression (e.g., '1 + 1' or 'np.array([1,2,3]).sum()'). |
| 2. Assign the result to a variable named '_result' (e.g., '_result = my_calculation'). |
| |
| Print statements will also be captured and returned along with the result. |
| """ |
| |
| try: |
| tree = ast.parse(python_code) |
| for node in tree.body: |
| if isinstance(node, ast.Import): |
| for alias in node.names: |
| root_module = alias.name.split('.')[0] |
| if root_module not in ALLOWED_MODULES: |
| return (f"Error: Import of '{alias.name}' is not allowed. " |
| f"Only modules from {list(ALLOWED_MODULES)} are permitted.") |
| elif isinstance(node, ast.ImportFrom): |
| if node.module: |
| root_module = node.module.split('.')[0] |
| if root_module not in ALLOWED_MODULES: |
| return (f"Error: Import from '{node.module}' is not allowed. " |
| f"Only modules from {list(ALLOWED_MODULES)} are permitted.") |
| except SyntaxError as e: |
| return f"Syntax Error in input code: {e}" |
|
|
| |
| restricted_globals = { |
| "__builtins__": { |
| "print": print, |
| "abs": abs, "round": round, "min": min, "max": max, "sum": sum, "len": len, |
| "range": range, "zip": zip, "enumerate": enumerate, |
| "int": int, "float": float, "str": str, "list": list, "dict": dict, "tuple": tuple, "set": set, |
| "True": True, "False": False, "None": None, |
| "__import__": __import__, |
| } |
| |
| |
| |
| } |
| local_vars = {} |
|
|
| |
| old_stdout = sys.stdout |
| redirected_output = io.StringIO() |
| sys.stdout = redirected_output |
|
|
| |
| calculated_value = None |
| result_source = "" |
| output_str = "" |
|
|
| try: |
| compiled_code = compile(python_code, '<string>', 'exec') |
| exec(compiled_code, restricted_globals, local_vars) |
| |
| |
| if "_result" in local_vars: |
| calculated_value = local_vars["_result"] |
| result_source = "variable '_result'" |
| |
| elif tree.body and isinstance(tree.body[-1], ast.Expr): |
| |
| if isinstance(tree.body[-1].value, ast.AST): |
| last_expr_ast = ast.Expression(body=tree.body[-1].value) |
| |
| compiled_expr = compile(last_expr_ast, '<string>', 'eval') |
| |
| calculated_value = eval(compiled_expr, restricted_globals, local_vars) |
| result_source = "last expression" |
| |
| sys.stdout = old_stdout |
| output_str = redirected_output.getvalue() |
|
|
| if calculated_value is not None: |
| return f"Result (from {result_source}):\n{calculated_value}\n\nCaptured Output:\n{output_str}".strip() |
| else: |
| return f"Executed successfully.\n\nCaptured Output:\n{output_str}\n(No specific result value found via '_result' variable or last expression evaluation.)".strip() |
|
|
| except Exception as e: |
| if sys.stdout == redirected_output: |
| sys.stdout = old_stdout |
| output_str = redirected_output.getvalue() |
| return f"Execution Error: {type(e).__name__}: {e}\n\nCaptured Output:\n{output_str}".strip() |
| finally: |
| |
| if sys.stdout == redirected_output: |
| sys.stdout = old_stdout |
|
|
|
|
| |
| def convert_audio_to_text(path_to_audio: str) -> str: |
| """ |
| Converts speech from an audio file into text. |
| Args: |
| path_to_audio (str): The path to the audio file to be transcribed. An URL can also be used. |
| Returns: |
| str: The transcribed text content of the audio file. |
| """ |
| |
| client = genai.Client(api_key=GEMINI_API_KEY) |
|
|
| myfile = client.files.upload(file=path_to_audio) |
|
|
| transcription = client.models.generate_content( |
| model=GEMINI_MODEL_NAME, contents=["Provide a transcription of this audio file.", myfile] |
| ) |
| |
|
|
| return transcription.text |
|
|
| |
| def image_understanding(url_to_image: str, question: str) -> str: |
| """ |
| Analyzes an image and generates a response to a given question based on the image's content. An URL needs to be used. |
| |
| Args: |
| path_to_image (str): The URL to the image file to be analyzed. |
| question (str): The question to be answered, based on the contents of the image. |
| |
| Returns: |
| str: The response from a VLM, typically a textual analysis or description based on the image. |
| """ |
|
|
| client = genai.Client(api_key=GEMINI_API_KEY) |
|
|
| image_bytes = requests.get(url_to_image).content |
| image = genai.types.Part.from_bytes(data=image_bytes, mime_type="image/jpeg") |
|
|
| response = client.models.generate_content( |
| model=GEMINI_MODEL_NAME, |
| contents=[question, image], |
| ) |
|
|
| return response.text |
|
|
| |
| def video_understanding(url_to_video: str, question: str) -> str: |
| """ |
| Analyzes a video and generates a response to a given question based on the video's content. |
| |
| Args: |
| url_to_video (str): The URL to the video file to be analyzed (example:YouTube). |
| question (str): The question to be answered, based on the contents of the video. |
| |
| Returns: |
| str: The response from a VLM, typically a textual analysis or description based on the video. |
| """ |
|
|
| client = genai.Client(api_key=GEMINI_API_KEY) |
|
|
| response = client.models.generate_content( |
| model=GEMINI_MODEL_NAME, |
| contents=genai.types.Content( |
| parts=[ |
| genai.types.Part( |
| file_data=genai.types.FileData(file_uri=url_to_video) |
| ), |
| genai.types.Part(text=question) |
| ] |
| ) |
| ) |
|
|
| return response.text |
| |
| |
| def read_csv_file(path_to_csv: str) -> str: |
| """ |
| Reads a CSV file from the specified path and returns its content as plain text. |
| |
| Args: |
| path_to_csv (str): The file path to the CSV file. |
| |
| Returns: |
| str: Content of the CSV file as plain text. |
| """ |
| try: |
| |
| df = pd.read_csv(path_to_csv) |
| |
| |
| return df.to_string(index=False) |
| except Exception as e: |
| return f"Error reading the CSV file: {e}" |
|
|
| |
| def read_xlsx_file(path_to_xlsx: str) -> str: |
| """ |
| Reads a XLSX file from the specified path and returns its content as plain text. |
| |
| Args: |
| path_to_xlsx (str): The file path to the XLSX file. |
| |
| Returns: |
| str: Content of the XLSX file as plain text. |
| """ |
| try: |
| |
| df = pd.read_excel(path_to_xlsx) |
| |
| |
| return df.to_string(index=False) |
| except Exception as e: |
| return f"Error reading the XLSX file: {e}" |
| |
| |
| if __name__ == "__main__": |
| |
| |
| print(image_understanding("https://i.etsystatic.com/28810262/r/il/2fc5e0/5785166966/il_1140xN.5785166966_nvy4.jpg", "What does this image represent?")) |