163 lines
7.0 KiB
Python
163 lines
7.0 KiB
Python
"""
|
|
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 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.image_standard import ImageRequestFile, StandardImageAnalysisResult, ImageEvaluationRubric
|
|
from app.core import config
|
|
from app.utilities.image_utilities import json_to_rubric, encode_image_from_bytes
|
|
from app.services.image.prompt_builder import build_image_evaluation_prompt
|
|
|
|
# Función de adaptador principal que infiere el proveedor y llama al adaptador específico
|
|
async def evaluate_image_with_provider(image_request: ImageRequestFile) -> StandardImageAnalysisResult:
|
|
"""
|
|
Función de adaptador para evaluar imágenes usando el proveedor de IA configurado.
|
|
"""
|
|
provider = image_request.provider.lower()
|
|
|
|
content = await image_request.rubric.read()
|
|
rubric_dict = json.loads(content)
|
|
rubric = json_to_rubric(rubric_dict)
|
|
prompt = build_image_evaluation_prompt(rubric)
|
|
|
|
match provider:
|
|
case "openai":
|
|
return await evaluate_with_openai(image_request, prompt)
|
|
case "clarifai":
|
|
return await evaluate_with_clarifai(image_request, prompt)
|
|
case "claude":
|
|
return await evaluate_with_claude(image_request, prompt)
|
|
case _:
|
|
raise ValueError(f"Proveedor de IA no soportado: {image_request.provider}")
|
|
|
|
# Función de adaptador para evaluar imágenes usando OpenAI
|
|
async def evaluate_with_openai(image_request: ImageRequestFile, prompt: str) -> StandardImageAnalysisResult:
|
|
"""
|
|
Función de adaptador para evaluar imágenes usando OpenAI.
|
|
(Plantilla para futuras implementaciones)
|
|
"""
|
|
|
|
client = AsyncOpenAI(api_key=settings.OPENAI_API_KEY)
|
|
|
|
image_bytes = await image_request.file.read()
|
|
base64_image = encode_image_from_bytes(image_bytes)
|
|
|
|
try:
|
|
response = await client.chat.completions.create(
|
|
model=image_request.model,
|
|
messages=[
|
|
{"role": "user", "content": [
|
|
{"type": "text", "text": prompt},
|
|
{
|
|
"type": "image_url",
|
|
"image_url": {
|
|
"url": f"data:image/jpeg;base64,{base64_image}"
|
|
}
|
|
}
|
|
]}
|
|
],
|
|
response_format={"type": "json_object"}
|
|
)
|
|
|
|
resultado = json.loads(response.choices[0].message.content)
|
|
return StandardImageAnalysisResult(**resultado)
|
|
except Exception as e:
|
|
# Capturamos cualquier error de OpenAI o de lectura de archivos
|
|
raise HTTPException(
|
|
status_code=500,
|
|
detail=f"Error evaluando la imagen: {str(e)}"
|
|
)
|
|
# PASOS A SEGUIR PARA IMPLEMENTAR LA LÓGICA DE EVALUACIÓN CON OPENAI:
|
|
# 1. Validar la imagen de entrada (tamaño, formato, etc.)
|
|
# 2. Configurar el cliente de OpenAI con la clave API
|
|
# 3. Llamar a la API de OpenAI para evaluar la imagen
|
|
# 4. Convertir la respuesta de OpenAI al formato estándar de evaluación de imágenes de Qualidot
|
|
# 5. Manejar errores y excepciones adecuadamente
|
|
raise NotImplementedError("La función evaluate_with_openai aún no está implementada.")
|
|
|
|
async def evaluate_with_clarifai(image_request: ImageRequestFile, rubric: ImageEvaluationRubric, prompt: str) -> StandardImageAnalysisResult:
|
|
"""
|
|
Función de adaptador para evaluar imágenes usando Clarifai con un modelo Multimodal.
|
|
"""
|
|
try:
|
|
# 1. Obtener el token de configuración (PAT)
|
|
pat = settings.CLARIFAI_API_KEY
|
|
if not pat:
|
|
raise ValueError("La clave CLARIFAI_API_KEY no está configurada en el entorno.")
|
|
|
|
# 2. Obtener la URL del modelo enviada en la petición
|
|
model_url = image_request.model
|
|
|
|
# Inicializar el modelo de Clarifai
|
|
model = Model(url=model_url, pat=pat)
|
|
|
|
# 3. Leer los bytes de la imagen subida
|
|
image_bytes = await image_request.file.read()
|
|
|
|
if not image_bytes:
|
|
raise ValueError("El archivo de imagen recibido está vacío.")
|
|
|
|
# 4. Preparar el input multimodal para Clarifai combinando la imagen y el prompt de evaluación
|
|
multimodal_input = Inputs.get_multimodal_input(
|
|
input_id="image_evaluation",
|
|
image_bytes=image_bytes,
|
|
raw_text=prompt
|
|
)
|
|
|
|
# 5. Llamar a la API de Clarifai para evaluar la imagen
|
|
predict_response = model.predict([multimodal_input])
|
|
|
|
# Extraer el texto crudo de la respuesta del modelo
|
|
raw_output = predict_response.outputs[0].data.text.raw
|
|
|
|
# 6. Limpiar la respuesta y convertirla a JSON
|
|
# Los LLMs suelen devolver el JSON envuelto en bloques de markdown (```json ... ```)
|
|
clean_json = raw_output.replace("```json", "").replace("```", "").strip()
|
|
|
|
# Convertir el string limpio a un diccionario de Python
|
|
parsed_data = json.loads(clean_json)
|
|
|
|
# 7. Retornar el resultado validado contra tu esquema estándar de Pydantic
|
|
return StandardImageAnalysisResult(**parsed_data)
|
|
|
|
except json.JSONDecodeError as e:
|
|
# Error específico si el modelo alucinó texto extra y no devolvió un JSON válido
|
|
raise HTTPException(
|
|
status_code=500,
|
|
detail=f"El modelo de Clarifai no devolvió un JSON válido. Error: {str(e)} | Respuesta cruda: {raw_output if 'raw_output' in locals() else 'N/A'}"
|
|
)
|
|
except Exception as e:
|
|
# Captura cualquier otro error (problemas de red, token inválido, URL incorrecta, etc.)
|
|
raise HTTPException(
|
|
status_code=500,
|
|
detail=f"Error interno al evaluar con Clarifai: {str(e)}"
|
|
)
|
|
|
|
async def evaluate_with_claude(image_request: ImageRequestFile, prompt: str) -> StandardImageAnalysisResult:
|
|
"""
|
|
Función de adaptador para evaluar imágenes usando Claude.
|
|
(Plantilla para futuras implementaciones)
|
|
"""
|
|
|
|
# PASOS A SEGUIR PARA IMPLEMENTAR LA LÓGICA DE EVALUACIÓN CON CLAUDE:
|
|
# 1. Validar la imagen de entrada (tamaño, formato, etc.)
|
|
# 2. Configurar el cliente de Claude con la clave API
|
|
# 3. Llamar a la API de Claude para evaluar la imagen
|
|
# 4. Convertir la respuesta de Claude al formato estándar de evaluación de imágenes de Qualidot
|
|
# 5. Manejar errores y excepciones adecuadamente
|
|
raise NotImplementedError("La función evaluate_with_claude aún no está implementada.")
|