Spaces:
Runtime error
Runtime error
# managers/gemini_manager.py | |
# AducSdr: Uma implementação aberta e funcional da arquitetura ADUC-SDR | |
# Copyright (C) 4 de Agosto de 2025 Carlos Rodrigues dos Santos | |
# | |
# Contato: | |
# Carlos Rodrigues dos Santos | |
# [email protected] | |
# Rua Eduardo Carlos Pereira, 4125, B1 Ap32, Curitiba, PR, Brazil, CEP 8102025 | |
# | |
# Repositórios e Projetos Relacionados: | |
# GitHub: https://github.com/carlex22/Aduc-sdr | |
# | |
# PENDING PATENT NOTICE: Please see NOTICE.md. | |
# | |
# Version: 1.1.1 | |
# | |
# This file defines the GeminiManager, a specialist responsible for raw communication | |
# with the Google Gemini API. It acts as a lean API client, handling requests, | |
# parsing responses, and managing API-level errors. It does not contain any | |
# high-level prompt engineering or creative logic. | |
import os | |
import logging | |
import json | |
from pathlib import Path | |
import gradio as gr | |
from PIL import Image | |
import google.generativeai as genai | |
import re | |
from typing import List, Union, Any | |
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') | |
logger = logging.getLogger(__name__) | |
def robust_json_parser(raw_text: str) -> dict: | |
""" | |
Parses a JSON object from a string that might contain extra text, | |
such as Markdown code blocks from an LLM's response. | |
""" | |
clean_text = raw_text.strip() | |
try: | |
match = re.search(r'```json\s*(\{.*?\})\s*```', clean_text, re.DOTALL) | |
if match: | |
json_str = match.group(1) | |
return json.loads(json_str) | |
start_index = clean_text.find('{') | |
end_index = clean_text.rfind('}') | |
if start_index != -1 and end_index != -1 and end_index > start_index: | |
json_str = clean_text[start_index : end_index + 1] | |
return json.loads(json_str) | |
else: | |
raise ValueError("No valid JSON object could be found in the AI's response.") | |
except json.JSONDecodeError as e: | |
logger.error(f"Failed to decode JSON. The AI returned the following text:\n---\n{raw_text}\n---") | |
raise ValueError(f"The AI returned an invalid JSON format: {e}") | |
class GeminiManager: | |
""" | |
Manages raw interactions with the Google Gemini API. | |
""" | |
def __init__(self): | |
self.api_key = os.environ.get("GEMINI_API_KEY") | |
if self.api_key: | |
genai.configure(api_key=self.api_key) | |
self.model = genai.GenerativeModel('gemini-2.5-flash') | |
logger.info("GeminiManager (Communication Layer) initialized successfully.") | |
else: | |
self.model = None | |
logger.warning("Gemini API key not found. GeminiManager disabled.") | |
def _check_model(self): | |
"""Raises an error if the Gemini API is not configured.""" | |
if not self.model: | |
raise gr.Error("The Google Gemini API key is not configured (GEMINI_API_KEY).") | |
def _generate_content(self, prompt_parts: List[Any]) -> str: | |
"""Internal method to make the API call.""" | |
self._check_model() | |
logger.info("Calling Gemini API...") | |
response = self.model.generate_content(prompt_parts) | |
logger.info(f"Gemini responded with raw text: {response.text}") | |
return response.text | |
def get_raw_text(self, prompt_parts: List[Any]) -> str: | |
""" | |
Sends a prompt to the Gemini API and returns the raw text response. | |
Args: | |
prompt_parts (List[Any]): A list containing strings and/or PIL.Image objects. | |
Returns: | |
str: The raw string response from the API. | |
""" | |
try: | |
return self._generate_content(prompt_parts) | |
except Exception as e: | |
logger.error(f"Gemini API call failed: {e}", exc_info=True) | |
raise gr.Error(f"Gemini API communication failed: {e}") | |
def get_json_object(self, prompt_parts: List[Any]) -> dict: | |
""" | |
Sends a prompt to the Gemini API, expects a JSON response, parses it, and returns a dictionary. | |
Args: | |
prompt_parts (List[Any]): A list containing strings and/or PIL.Image objects. | |
Returns: | |
dict: The parsed JSON object from the API response. | |
""" | |
try: | |
raw_response = self._generate_content(prompt_parts) | |
return robust_json_parser(raw_response) | |
except Exception as e: | |
logger.error(f"Gemini API call or JSON parsing failed: {e}", exc_info=True) | |
raise gr.Error(f"Gemini API communication or response parsing failed: {e}") | |
# --- Singleton Instance --- | |
gemini_manager_singleton = GeminiManager() |