""" Gateway de IA de Qualidot - Módulo de Adaptadores de Evaluación de Imágenes Propósito: Este módulo contiene funciones de adaptadores que permiten evaluar imágenes usando diferentes proveedores de IA. Cada función de adaptador se encarga de interactuar con un proveedor específico (como OpenAI, AssemblyAI, Deepgram, etc.) y de convertir la respuesta del proveedor al formato estándar de evaluación de imágenes de Qualidot. """ import json import mimetypes import mimetypes import tempfile import os from fastapi import HTTPException from matplotlib import image from openai import OpenAI, AsyncOpenAI import assemblyai as aai from pyparsing.common import Any from app.core.config import settings from app.schemas.document_standard import DocumentRequestFile, StandardDocumentAnalysisResult from app.core import config from app.utilities.document_utilities import json_to_rubric, encode_document_from_bytes from app.services.document.prompt_builder import build_document_evaluation_prompt from anthropic import Anthropic from app.utilities.image_utilities import encode_image_from_bytes # Función de adaptador principal que infiere el proveedor y llama al adaptador específico async def evaluate_document_with_provider(document_request: DocumentRequestFile) -> StandardDocumentAnalysisResult: """ Función de adaptador para evaluar documentos usando el proveedor de IA configurado. """ provider = document_request.provider.lower() content = await document_request.rubric.read() rubric_dict = json.loads(content) rubric = json_to_rubric(rubric_dict) prompt = build_document_evaluation_prompt(rubric) match provider: case "openai": return await evaluate_with_openai(document_request, prompt) case "claude": return await evaluate_with_claude(document_request, prompt) case "gemini": return await evaluate_with_gemini(document_request, prompt) case _: raise ValueError(f"Proveedor de IA no soportado: {document_request.provider}") # Función de adaptador para evaluar documentos usando OpenAI async def evaluate_with_openai(document_request: DocumentRequestFile, prompt: str) -> StandardDocumentAnalysisResult: """ Función de adaptador para evaluar documentos usando OpenAI. """ client = AsyncOpenAI(api_key=settings.OPENAI_API_KEY) document_bytes = await document_request.file.read() base64_document = encode_document_from_bytes(document_bytes) media_type = document_request.file.content_type try: response = await client.chat.completions.create( model=document_request.model, messages=[ {"role": "user", "content": [ {"type": "text", "text": prompt}, { "type": "file", "file": { "file_data": f"data:{media_type};base64,{base64_document}", "filename": document_request.file.filename } } ]} ], response_format={"type": "json_object"} ) resultado = json.loads(response.choices[0].message.content) return StandardDocumentAnalysisResult( status="success", original_filename=document_request.file.filename, provider_used="openai", model_used=document_request.model, **resultado ) except Exception as e: raise HTTPException( status_code=500, detail=f"Error evaluando el documento: {str(e)}" ) # Función de adaptador para evaluar documentos usando Claude async def evaluate_with_claude(document_request: DocumentRequestFile, prompt: str) -> StandardDocumentAnalysisResult: """ Función de adaptador para evaluar documentos usando Claude. """ client = Anthropic(api_key=os.environ.get("ANTHROPIC_API_KEY")) document_bytes = await document_request.file.read() base64_document = encode_document_from_bytes(document_bytes) media_type = document_request.file.content_type if media_type not in ["application/pdf", "application/msword", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"]: raise ValueError(f"Tipo de documento no soportado por Anthropic: {media_type}") try: messages = [ { "role": "user", "content": [ { "type": "document", "source": { "type": "base64", "media_type": media_type, "data": base64_document }, }, {"type": "text", "text": prompt} ], } ] response = client.messages.create( model=document_request.model, max_tokens=4096, messages=messages, ) json_string = response.content[0].text parsed_data = json.loads(json_string) return StandardDocumentAnalysisResult( status="success", original_filename=document_request.file.filename, provider_used="Claude", model_used=document_request.model, **parsed_data ) except Exception as e: raise HTTPException( status_code=500, detail=f"Error evaluando el documento: {str(e)}" ) # Función de adaptador para evaluar documentos usando Gemini async def evaluate_with_gemini(document_request: DocumentRequestFile, prompt: str) -> StandardDocumentAnalysisResult: """ Función de adaptador para evaluar documentos usando Gemini. (Plantilla para futuras implementaciones) """ # Aquí iría la implementación específica para Gemini pass