feat: Agrega primera version de template (revisar archivo de documentacion - docs.md)

This commit is contained in:
Francisco Pineda
2026-03-15 08:44:25 +01:00
parent d433942981
commit 4d6152a9fe
45 changed files with 1151 additions and 0 deletions

1
app/__init__.py Normal file
View File

@@ -0,0 +1 @@

Binary file not shown.

Binary file not shown.

1
app/api/v1/__init__.py Normal file
View File

@@ -0,0 +1 @@
"""API v1 package"""

Binary file not shown.

View File

@@ -0,0 +1,38 @@
"""
Gateway de IA de Qualidot - Módulo de Procesamiento de Audio
Propósito:
Este endpoint recibe un audio y lo convierte a texto usando inteligencia artificial.
Homologación:
Sin importar qué proveedor de IA se utilice, el resultado siempre se entrega en el mismo formato estándar para Qualidot.
"""
from dotenv import load_dotenv
from fastapi import APIRouter, Depends, UploadFile, File, HTTPException
from fastapi.security import APIKeyHeader
from app.api.v1.endpoints import router
from app.schemas.audio_standard import StandardTranscriptionResult, AudioRequestFile
from app.services.audio.transcription_adapters import transcribe_audio_with_provider
# Inicializar el router de FastAPI para este módulo
audio_router_transcription = APIRouter()
@audio_router_transcription.post("/transcripts/", response_model=StandardTranscriptionResult)
async def transcribe_audio(audio_request: AudioRequestFile = Depends()) -> StandardTranscriptionResult:
"""
Endpoint para transcribir audio simple infiriendo el proveedor de IA
Args:
audio_request: Objeto AudioRequestFile que contiene el archivo de audio,
el proveedor, el modelo y las opciones de diarización, marcas de tiempo y análisis de sentimiento.
Returns:
StandardTranscriptionResult: Resultado de la transcripción en formato estándar de Qualidot
"""
try:
# Transcribir usando el adaptador de transcripción que infiere el proveedor
transcription_result = await transcribe_audio_with_provider(audio_request)
return transcription_result
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))

View File

@@ -0,0 +1,39 @@
"""
Gateway de IA de Qualidot - Módulo de Procesamiento de Imágenes con una rubrica de análisis
Propósito:
Este endpoint recibe una imagen y la analiza usando una rúbrica de evaluación basada en inteligencia artificial.
Homologación:
Sin importar qué proveedor de IA se utilice, el resultado siempre se entrega en el mismo formato estándar para Qualidot.
"""
from dotenv import load_dotenv
from fastapi import APIRouter, Depends, UploadFile, File, HTTPException
from fastapi.security import APIKeyHeader
from app.api.v1.endpoints import router
from app.schemas.image_standard import StandardImageAnalysisResult, ImageRequestFile
from app.services.image.evaluations_adapters import evaluate_image_with_provider
# Inicializar el router de FastAPI para este módulo
image_router_analysis = APIRouter()
@image_router_analysis.post("/evaluations/", response_model=StandardImageAnalysisResult)
async def evaluate_image(image_request: ImageRequestFile = Depends()) -> StandardImageAnalysisResult:
"""
Endpoint para analizar imágenes usando una rúbrica de evaluación infiriendo el proveedor de IA
Args:
image_request: Objeto ImageRequestFile que contiene la imagen,
el proveedor, el modelo y las opciones de análisis.
Returns:
StandardImageAnalysisResult: Resultado del análisis de imágenes en formato estándar de Qualidot
"""
try:
# Analizar imagen usando el adaptador de análisis de imagen que infiere el proveedor
analysis_result = await evaluate_image_with_provider(image_request)
return analysis_result
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))

View File

@@ -0,0 +1,61 @@
"""
Gateway de IA de Qualidot - Módulo maestro de endpoints de procesamiento.
Propósito:
Este módulo actúa como el punto central de enrutamiento para todos los
endpoints relacionados con el procesamiento de audio, imágenes,
documentos, video, etc.
Homologación:
Sin importar qué proveedor de IA se utilice, el resultado siempre se
entrega en el mismo formato estándar para Qualidot.
"""
from dotenv import load_dotenv
from fastapi import APIRouter, UploadFile, File, HTTPException
from fastapi.security import APIKeyHeader
# Importar los routers específicos de cada módulo
from app.api.v1.endpoints.audio.transcription import audio_router_transcription # Endpoint de transcripción de audio
from app.api.v1.endpoints.texto.resume import text_router_summary # Endpoint de resumen de texto
from app.api.v1.endpoints.texto.rubricated_analysis import text_router_analysis # Endpoint de análisis rubricado de texto
from app.api.v1.endpoints.video.transcription import video_router_transcription # Endpoint de transcripción de video
from app.api.v1.endpoints.image.rubricated_analysis import image_router_analysis # Endpoint de análisis rubricado de imágenes
# Inicializar el router de FastAPI para los módulos de procesamiento
api_router_audio = APIRouter()
api_router_text = APIRouter()
api_router_video = APIRouter()
api_router_image = APIRouter()
api_router_audio.include_router(
audio_router_transcription,
prefix="/audio",
tags=["Procesamiento de Audio"]
)
api_router_text.include_router(
text_router_summary,
prefix="/text",
tags=["Procesamiento de Texto"]
)
api_router_text.include_router(
text_router_analysis,
prefix="/text",
tags=["Procesamiento de Texto"]
)
api_router_video.include_router(
video_router_transcription,
prefix="/video",
tags=["Procesamiento de Video"]
)
api_router_image.include_router(
image_router_analysis,
prefix="/image",
tags=["Procesamiento de Imágenes"]
)

View File

@@ -0,0 +1,39 @@
"""
Gateway de IA de Qualidot - Módulo de Procesamiento de Texto para Resumen
Propósito:
Este endpoint recibe un texto y lo resume usando inteligencia artificial.
Homologación:
Sin importar qué proveedor de IA se utilice, el resultado siempre se entrega en el mismo formato estándar para Qualidot.
"""
from dotenv import load_dotenv
from fastapi import APIRouter, Depends, UploadFile, File, HTTPException
from fastapi.security import APIKeyHeader
from app.api.v1.endpoints import router
from app.schemas.text_standard import StandardTextAnalysisResult, TextRequestFile
#from app.services.transcription_adapters import transcribe_audio_with_provider
from app.services.text.resume_adapters import summarize_text_with_provider
# Inicializar el router de FastAPI para este módulo
text_router_summary = APIRouter()
@text_router_summary.post("/summaries/", response_model=StandardTextAnalysisResult)
async def summarize_text(text_request: TextRequestFile = Depends()) -> StandardTextAnalysisResult:
"""
Endpoint para resumir texto simple infiriendo el proveedor de IA
Args:
text_request: Objeto TextRequestFile que contiene el archivo de texto,
el proveedor, el modelo y las opciones de diarización, marcas de tiempo y análisis de sentimiento.
Returns:
StandardTextAnalysisResult: Resultado del análisis de texto en formato estándar de Qualidot
"""
try:
# Resumir texto usando el adaptador de resumen de texto que infiere el proveedor
analysis_result = await summarize_text_with_provider(text_request)
return analysis_result
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))

View File

@@ -0,0 +1,39 @@
"""
Gateway de IA de Qualidot - Módulo de Procesamiento de Texto para Análisis Rubricado
Propósito:
Este endpoint recibe un texto y lo analiza usando una rúbrica de evaluación basada en inteligencia artificial.
Homologación:
Sin importar qué proveedor de IA se utilice, el resultado siempre se entrega en el mismo formato estándar para Qualidot.
"""
from dotenv import load_dotenv
from fastapi import APIRouter, Depends, UploadFile, File, HTTPException
from fastapi.security import APIKeyHeader
from app.api.v1.endpoints import router
from app.schemas.text_standard import StandardTextAnalysisResult, TextRequestFile
#from app.services.transcription_adapters import transcribe_audio_with_provider
from app.services.text.evaluations_adapters import evaluate_text_with_provider
# Inicializar el router de FastAPI para este módulo
text_router_analysis = APIRouter()
@text_router_analysis.post("/evaluations/", response_model=StandardTextAnalysisResult)
async def evaluate_text(text_request: TextRequestFile = Depends()) -> StandardTextAnalysisResult:
"""
Endpoint para analizar texto usando una rúbrica de evaluación infiriendo el proveedor de IA
Args:
text_request: Objeto TextRequestFile que contiene el archivo de texto,
el proveedor, el modelo y las opciones de diarización, marcas de tiempo y análisis de sentimiento.
Returns:
StandardTextAnalysisResult: Resultado del análisis de texto en formato estándar de Qualidot
"""
try:
# Analizar texto usando el adaptador de análisis de texto que infiere el proveedor
analysis_result = await evaluate_text_with_provider(text_request)
return analysis_result
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))

View File

@@ -0,0 +1,36 @@
"""
Gateway de IA de Qualidot - Módulo de Procesamiento de Videos
Propósito:
Este endpoint recibe un video y lo convierte a texto usando inteligencia artificial.
Homologación:
Sin importar qué proveedor de IA se utilice, el resultado siempre se entrega en el mismo formato estándar para Qualidot.
"""
from dotenv import load_dotenv
from fastapi import APIRouter, Depends, UploadFile, File, HTTPException
from app.schemas.video_standard import StandardTranscriptionResult, VideoRequestFile
from app.services.video.transcription_adapters import transcribe_video_with_provider
# Inicializar el router de FastAPI para este módulo
video_router_transcription = APIRouter()
@video_router_transcription.post("/transcripts/", response_model=StandardTranscriptionResult)
async def transcribe_video(video_request: VideoRequestFile = Depends()) -> StandardTranscriptionResult:
"""
Endpoint para transcribir video simple infiriendo el proveedor de IA
Args:
video_request: Objeto VideoRequestFile que contiene el archivo de video,
el proveedor, el modelo y las opciones de diarización, marcas de tiempo y análisis de sentimiento.
Returns:
StandardTranscriptionResult: Resultado de la transcripción en formato estándar de Qualidot
"""
try:
# Transcribir usando el adaptador de transcripción que infiere el proveedor
transcription_result = await transcribe_video_with_provider(video_request)
return transcription_result
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))

Binary file not shown.

26
app/core/config.py Normal file
View File

@@ -0,0 +1,26 @@
import os
from dotenv import load_dotenv
load_dotenv()
class Settings:
# Configuración para las claves de API de los proveedores de IA
# ---------------------------------------------------------------
# Proveedores de Audio
# ---------------------------------------------------------------
# OpenAI
OPENAI_API_KEY: str = os.getenv("OPENAI_API_KEY", "")
#AssemblyAI
ASSEMBLYAI_API_KEY: str = os.getenv("ASSEMBLYAI_API_KEY", "")
# Deepgram
DEEPGRAM_API_KEY: str = os.getenv("DEEPGRAM_API_KEY", "")
# ---------------------------------------------------------------
# Proveedores de Imagen
# ---------------------------------------------------------------
settings = Settings()

60
app/main.py Normal file
View File

@@ -0,0 +1,60 @@
from fastapi import FastAPI
from app.api.v1.endpoints.router import api_router_audio, api_router_text, api_router_image, api_router_video
app = FastAPI(
title="Template de API de Procesamiento general",
description="Template de API para procesamiento de audio, imagenes, documento, video, etc",
version="1.0.0"
)
app.include_router(api_router_audio, prefix="/api/v1", tags=["Procesamiento de Audio"])
app.include_router(api_router_text, prefix="/api/v1", tags=["Procesamiento de Texto"])
app.include_router(api_router_image, prefix="/api/v1", tags=["Procesamiento de Imágenes"])
app.include_router(api_router_video, prefix="/api/v1", tags=["Procesamiento de Video"])
@app.get("/")
def root():
"""
Endpoint raíz para verificar que la API está corriendo y proporcionar información básica sobre los endpoints disponibles.
Returns:
dict: Un mensaje de bienvenida y un resumen de los endpoints disponibles en la API.
"""
return {
"message": "Template de API de Procesamiento general está corriendo con normalidad",
"docs": "/docs",
"endpoints": {
"audio": {
"transcripción de audio": "/api/v1/audio/transcripts/",
},
"texto": {
"resumen de texto": "/api/v1/text/summaries/",
"análisis rubricado": "/api/v1/text/evaluations/"
},
"imágenes": {
"análisis rubricado": "/api/v1/image/evaluations/",
},
"video": {
"transcripción de video": "/api/v1/video/transcripts/"
}
},
"modelos_disponibles": {
"audio": {
"openai": [
"gpt-4o-transcribe",
"whisper-1"
],
"assemblyai": ["universal-3-pro", "universal-2"]
},
"texto": {
"pendiente de agregar proveedores y modelos específicos para procesamiento de texto"
},
"imágenes": {
"pendiente de agregar proveedores y modelos específicos para procesamiento de imágenes"
},
"video": {
"pendiente de agregar proveedores y modelos específicos para procesamiento de video"
}
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,92 @@
"""
Esquema de resultado esperado de modelos de transcripción.
Propósito:
Define el formato estándar de los resultados devueltos por los modelos de transcripción
de audio, independientemente del proveedor de IA utilizado.
Homologación:
Garantiza que el resultado de la transcripción siempre se entregue en el mismo
formato estándar para Qualidot.
Pendiente (recomendación personal):
- Definir mejor la estructura de cada segmento según las opciones avanzadas (diarization, timestamps, sentiment)
- Delimitar los proveedores de IA soportados inicialmente
"""
from fastapi import UploadFile
from fastapi.params import File, Form
from pydantic import BaseModel, Field
from typing import List, Optional
class AudioRequestFile:
"""Modelo de solicitud para transcripción de audio."""
def __init__(
self,
file: UploadFile = File(..., description="Archivo de audio a procesar (ej. mp3, wav)"),
provider: str = Form(..., description="Proveedor de IA a utilizar (ej. openai, assemblyai)"),
model: str = Form(..., description="Modelo de IA a utilizar (ej. whisper-1)"),
diarization: Optional[bool] = Form(False, description="Activa la separación e identificación de múltiples hablantes"),
timestamps: Optional[bool] = Form(False, description="Activa las marcas de tiempo exactas por cada segmento hablado"),
sentiment: Optional[bool] = Form(False, description="Activa el análisis de sentimiento (POSITIVO/NEGATIVO) por segmento")
):
self.file = file
self.provider = provider
self.model = model
self.diarization = diarization
self.timestamps = timestamps
self.sentiment = sentiment
class TranscriptionSegment(BaseModel):
"""Modelo que representa un segmento de transcripción de audio detallado."""
text: str = Field(
...,
description="Texto transcrito en este fragmento específico"
)
speaker: Optional[str] = Field(
None,
description="Identificador del hablante (ej. 'Speaker A') si diarization está activo"
)
start_time: Optional[float] = Field(
None,
description="Marca de tiempo en segundos donde inicia el segmento"
)
end_time: Optional[float] = Field(
None,
description="Marca de tiempo en segundos donde termina el segmento"
)
sentiment: Optional[str] = Field(
None,
description="Sentimiento detectado en el segmento (ej. 'POSITIVE', 'NEGATIVE')"
)
class StandardTranscriptionResult(BaseModel):
"""Modelo que representa el resultado estándar de una transcripción de audio para Qualidot."""
status: str = Field(
...,
description="Estado final de la petición ('success' o 'error')"
)
original_filename: str = Field(
...,
description="Nombre original del archivo de audio procesado"
)
provider_used: str = Field(
...,
description="Proveedor de IA que ejecutó la transcripción (ej. OpenAI)"
)
model_used: str = Field(
...,
description="Modelo específico utilizado para el proceso"
)
full_transcript: Optional[str] = Field(
None,
description="Texto completo y continuo de toda la transcripción"
)
segments: Optional[List[TranscriptionSegment]] = Field(
None,
description="Lista detallada de segmentos si se solicitaron opciones avanzadas (diarization, timestamps, sentiment)"
)
confidence_score: Optional[float] = Field(
None,
description="Nivel de certeza global del modelo (valor entre 0.0 y 1.0)"
)

View File

@@ -0,0 +1,44 @@
"""
Esquema de resultado esperado de modelos de análisis de imágenes.
Propósito:
Define el formato estándar de los resultados devueltos por los modelos de análisis
de imágenes, independientemente del proveedor de IA utilizado.
Homologación:
Garantiza que el resultado del análisis de imágenes siempre se entregue en el mismo
formato estándar para Qualidot.
"""
from fastapi import UploadFile
from fastapi.params import File, Form
from pydantic import BaseModel, Field
from typing import List, Optional
class ImageRequestFile:
"""Modelo de solicitud para análisis de imágenes."""
def __init__(
self,
file: UploadFile = File(..., description="Archivo de imagen a procesar (ej. jpg, png)"),
provider: str = Form(..., description="Proveedor de IA a utilizar (ej. openai, google)"),
model: str = Form(..., description="Modelo de IA a utilizar (ej. vision-1)"),
rubric: Optional[str] = Form(None, description="Rúbrica de evaluación personalizada para el análisis")
):
self.file = file
self.provider = provider
self.model = model
self.rubric = rubric
class StandardImageAnalysisResult(BaseModel):
"""Modelo que representa el resultado estándar de un análisis de imágenes para Qualidot."""
status: str = Field(
...,
description="Estado del análisis (ej. 'success', 'error')"
)
analysis: Optional[dict] = Field(
None,
description="Resultados detallados del análisis de la imagen, estructurados según la rúbrica si se proporcionó"
)
error: Optional[str] = Field(
None,
description="Mensaje de error en caso de que el análisis haya fallado"
)

View File

@@ -0,0 +1,44 @@
"""
Esquema de resultado esperado de modelos de análisis de texto (JSON).
Propósito:
Define el formato estándar de los resultados devueltos por los modelos de análisis
de texto, independientemente del proveedor de IA utilizado.
Homologación:
Garantiza que el resultado del análisis de texto siempre se entregue en el mismo
formato estándar para Qualidot.
"""
from fastapi import UploadFile
from fastapi.params import File, Form
from pydantic import BaseModel, Field
from typing import List, Optional
class TextRequestFile:
"""Modelo de solicitud para análisis de texto."""
def __init__(
self,
file: UploadFile = File(..., description="Archivo de texto a procesar (ej. txt, json)"),
provider: str = Form(..., description="Proveedor de IA a utilizar (ej. openai, google)"),
model: str = Form(..., description="Modelo de IA a utilizar (ej. text-1)"),
rubric: Optional[str] = Form(None, description="Rúbrica de evaluación personalizada para el análisis")
):
self.file = file
self.provider = provider
self.model = model
self.rubric = rubric
class StandardTextAnalysisResult(BaseModel):
"""Modelo que representa el resultado estándar de un análisis de texto para Qualidot."""
status: str = Field(
...,
description="Estado del análisis (ej. 'success', 'error')"
)
analysis: Optional[dict] = Field(
None,
description="Resultados detallados del análisis de texto, estructurados según la rúbrica si se proporcionó"
)
error: Optional[str] = Field(
None,
description="Mensaje de error en caso de que el análisis haya fallado"
)

View File

@@ -0,0 +1,65 @@
"""
Esquema de resultado esperado de modelos de transcripción de video.
Propósito:
Define el formato estándar de los resultados devueltos por los modelos de transcripción
de video, independientemente del proveedor de IA utilizado.
Homologación:
Garantiza que el resultado de la transcripción siempre se entregue en el mismo
formato estándar para Qualidot.
"""
from fastapi import UploadFile
from fastapi.params import File, Form
from pydantic import BaseModel, Field
from typing import List, Optional
class VideoRequestFile:
"""Modelo de solicitud para transcripción de video."""
def __init__(
self,
file: UploadFile = File(..., description="Archivo de video a procesar (ej. mp4, mov)"),
provider: str = Form(..., description="Proveedor de IA a utilizar (ej. openai, assemblyai)"),
model: str = Form(..., description="Modelo de IA a utilizar (ej. whisper-1)"),
diarization: Optional[bool] = Form(False, description="Activa la separación e identificación de múltiples hablantes"),
timestamps: Optional[bool] = Form(False, description="Activa las marcas de tiempo exactas por cada segmento hablado"),
sentiment: Optional[bool] = Form(False, description="Activa el análisis de sentimiento (POSITIVO/NEGATIVO) por segmento")
):
self.file = file
self.provider = provider
self.model = model
self.diarization = diarization
self.timestamps = timestamps
self.sentiment = sentiment
class StandardTranscriptionResult(BaseModel):
"""Modelo que representa el resultado estándar de una transcripción de video para Qualidot."""
status: str = Field(
...,
description="Estado final de la petición ('success' o 'error')"
)
original_filename: str = Field(
...,
description="Nombre original del archivo de video procesado"
)
provider_used: str = Field(
...,
description="Proveedor de IA que ejecutó la transcripción (ej. OpenAI)"
)
model_used: str = Field(
...,
description="Modelo específico utilizado para el proceso"
)
full_transcript: Optional[str] = Field(
None,
description="Texto completo y continuo de toda la transcripción"
)
segments: Optional[List[dict]] = Field( ##Queda pendiente definir mejor la estructura de cada segmento según las opciones avanzadas
None,
description="Lista detallada de segmentos si se solicitaron opciones avanzadas (diarization, timestamps, sentiment)"
)
confidence_score: Optional[float] = Field(
None,
description="Nivel de certeza global del modelo (valor entre 0.0 y 1.0)"
)

View File

@@ -0,0 +1,163 @@
"""
Gateway de IA de Qualidot - Módulo de Adaptadores de Transcripción
Propósito:
Este módulo contiene funciones de adaptadores que permiten transcribir audio 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 transcripción de Qualidot.
"""
import tempfile
import os
from fastapi import HTTPException
from openai import OpenAI, AsyncOpenAI
import assemblyai as aai
from app.core.config import settings
from app.schemas.audio_standard import AudioRequestFile
from app.schemas.audio_standard import StandardTranscriptionResult
from app.utilities.audio_utilities import validate_audio_file, validate_audio_size, validate_audio_request
from app.core import config
# Función de adaptador principal que infiere el proveedor y llama al adaptador específico
async def transcribe_audio_with_provider(audio_request: AudioRequestFile) -> StandardTranscriptionResult:
"""
Función de adaptador para transcribir audio usando el proveedor de IA configurado.
"""
provider = audio_request.provider.lower()
match provider:
case "openai":
return await transcribe_with_openai(audio_request)
case "assemblyai":
return await transcribe_with_assemblyai(audio_request)
case _:
raise ValueError(f"Proveedor de IA no soportado: {audio_request.provider}")
# Función de adaptador para transcribir audio usando OpenAI
async def transcribe_with_openai(audio_request: AudioRequestFile) -> StandardTranscriptionResult:
"""
Función de adaptador para transcribir audio usando OpenAI.
"""
client = AsyncOpenAI(api_key=settings.OPENAI_API_KEY)
audio_content = await audio_request.file.read()
temp_audio_path = None # Inicializamos la variable fuera del try
# Validar el audio antes de continuar
validate_audio_request(audio_request, audio_content)
try:
# Crear archivo temporal para el audio
with tempfile.NamedTemporaryFile(
delete=False,
suffix=os.path.splitext(audio_request.file.filename)[1]
) as temp_audio:
temp_audio.write(audio_content)
temp_audio_path = temp_audio.name
with open(temp_audio_path, "rb") as audio_file_obj:
transcription = await client.audio.transcriptions.create(
model=audio_request.model,
file=audio_file_obj,
response_format="text"
)
result = StandardTranscriptionResult(
status="success",
original_filename=audio_request.file.filename,
full_transcript=transcription,
model_used=audio_request.model,
provider_used="OpenAI",
confidence_score=None
)
return result
except Exception as e:
# Capturamos cualquier error de OpenAI o de lectura de archivos
raise HTTPException(
status_code=500,
detail=f"Error transcribiendo el audio: {str(e)}"
)
finally:
if temp_audio_path and os.path.exists(temp_audio_path):
try:
os.unlink(temp_audio_path)
except Exception:
pass
# Función de adaptador para transcribir audio usando AssemblyAI
async def transcribe_with_assemblyai(audio_request: AudioRequestFile) -> StandardTranscriptionResult:
"""
Función de adaptador para transcribir audio usando AssemblyAI.
"""
aai.settings.api_key = settings.ASSEMBLYAI_API_KEY
audio_content = await audio_request.file.read()
temp_audio_path = None
# Validar el audio antes de continuar
validate_audio_request(audio_request, audio_content)
try:
# Crear archivo temporal para el audio
with tempfile.NamedTemporaryFile(
delete=False,
suffix=os.path.splitext(audio_request.file.filename)[1]
) as temp_audio:
temp_audio.write(audio_content)
temp_audio_path = temp_audio.name
#Definimos el modelo a usar
config = aai.TranscriptionConfig(language_code="es", speaker_labels=audio_request.diarization,
sentiment_analysis=audio_request.sentiment)
transcription_obj = aai.Transcriber(config=config).transcribe(temp_audio_path)
iterable = transcription_obj.sentiment_analysis if audio_request.sentiment else transcription_obj.utterances
if transcription_obj.status == aai.TranscriptStatus.error:
raise Exception(f"AssemblyAI Error: {transcription_obj.error}")
assemblyaiSegment = "utterances" if not audio_request.sentiment else "sentiment_analysis"
result = StandardTranscriptionResult(
status="success",
original_filename=audio_request.file.filename,
full_transcript=transcription_obj.text,
model_used=audio_request.model,
provider_used="AssemblyAI",
confidence_score=None,
segments=[
{
"text": segment.text,
"speaker": segment.speaker if audio_request.diarization else None,
"start_time": segment.start if audio_request.timestamps else None,
"end_time": segment.end if audio_request.timestamps else None,
"sentiment": segment.sentiment if audio_request.sentiment else None
}
for segment in iterable
] if (audio_request.diarization or audio_request.timestamps or audio_request.sentiment) else None
)
return result
except Exception as e:
# Capturamos cualquier error de OpenAI o de lectura de archivos
raise HTTPException(
status_code=500,
detail=f"Error transcribiendo el audio: {str(e)}"
)
finally:
if temp_audio_path and os.path.exists(temp_audio_path):
try:
os.unlink(temp_audio_path)
except Exception:
pass
# Aquí iría la implementación específica para AssemblyAI, similar a la de OpenAI pero usando su SDK y formato de respuesta
pass

View File

@@ -0,0 +1,68 @@
"""
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 tempfile
import os
from fastapi import HTTPException
from openai import OpenAI, AsyncOpenAI
import assemblyai as aai
from app.core.config import settings
from app.schemas.image_standard import ImageRequestFile, StandardImageAnalysisResult
from app.core import config
# 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()
match provider:
case "openai":
return await evaluate_with_openai(image_request)
case "inserte nombre de otra ia aqui":
return await evaluate_with_ai_model2(image_request)
# AGREGAR OTROS CASOS PARA DIFERENTES PROVEEDORES DE IA AQUÍ
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) -> StandardImageAnalysisResult:
"""
Función de adaptador para evaluar imágenes usando OpenAI.
(Plantilla para futuras implementaciones)
"""
client = AsyncOpenAI(api_key=settings.OPENAI_API_KEY)
# 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_ai_model2(image_request: ImageRequestFile) -> StandardImageAnalysisResult:
"""
Función de adaptador para transcribir video usando otra AI.
(Plantilla para futuras implementaciones)
"""
# PASOS A SEGUIR PARA IMPLEMENTAR LA LÓGICA DE TRANSCRIPCIÓN CON IA (ELEGIR MODELO):
# 1. Validar el video de entrada (tamaño, formato, etc.)
# 2. Configurar el cliente de OpenAI con la clave API
# 3. Llamar a la API de OpenAI para transcribir el video
# 4. Convertir la respuesta de OpenAI al formato estándar de resumen de texto de Qualidot
# 5. Manejar errores y excepciones adecuadamente
raise NotImplementedError("La función transcribe_with_ai_model2 aún no está implementada.")
# Otros modelos de IA

View File

@@ -0,0 +1,50 @@
"""
Gateway de IA de Qualidot - Módulo de Adaptadores de Resumen de Texto
Propósito:
Este módulo contiene funciones de adaptadores que permiten resumir texto 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 resumen de texto de Qualidot.
"""
import tempfile
import os
from fastapi import HTTPException
from openai import OpenAI, AsyncOpenAI
import assemblyai as aai
from app.core.config import settings
from app.schemas.text_standard import TextRequestFile, StandardTextAnalysisResult
from app.core import config
# Función de adaptador principal que infiere el proveedor y llama al adaptador específico
async def evaluate_text_with_provider(text_request: TextRequestFile) -> StandardTextAnalysisResult:
"""
Función de adaptador para evaluar texto usando el proveedor de IA configurado.
"""
provider = text_request.provider.lower()
match provider:
case "openai":
return await evaluate_with_openai(text_request)
# AGREGAR OTROS CASOS PARA DIFERENTES PROVEEDORES DE IA AQUÍ
case _:
raise ValueError(f"Proveedor de IA no soportado: {text_request.provider}")
# Función de adaptador para evaluar texto usando OpenAI
async def evaluate_with_openai(text_request: TextRequestFile) -> StandardTextAnalysisResult:
"""
Función de adaptador para evaluar texto usando OpenAI.
(Plantilla para futuras implementaciones)
"""
client = AsyncOpenAI(api_key=settings.OPENAI_API_KEY)
# PASOS A SEGUIR PARA IMPLEMENTAR LA LÓGICA DE EVALUACIÓN CON OPENAI:
# 1. Validar el texto 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 el texto
# 4. Convertir la respuesta de OpenAI al formato estándar de evaluación de texto de Qualidot
# 5. Manejar errores y excepciones adecuadamente
raise NotImplementedError("La función evaluate_with_openai aún no está implementada.")
# Otros modelos de IA

View File

@@ -0,0 +1,50 @@
"""
Gateway de IA de Qualidot - Módulo de Adaptadores de Resumen de Texto
Propósito:
Este módulo contiene funciones de adaptadores que permiten resumir texto 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 resumen de texto de Qualidot.
"""
import tempfile
import os
from fastapi import HTTPException
from openai import OpenAI, AsyncOpenAI
import assemblyai as aai
from app.core.config import settings
from app.schemas.text_standard import TextRequestFile, StandardTextAnalysisResult
from app.core import config
# Función de adaptador principal que infiere el proveedor y llama al adaptador específico
async def summarize_text_with_provider(text_request: TextRequestFile) -> StandardTextAnalysisResult:
"""
Función de adaptador para resumir texto usando el proveedor de IA configurado.
"""
provider = text_request.provider.lower()
match provider:
case "openai":
return await summarize_with_openai(text_request)
# AGREGAR OTROS CASOS PARA DIFERENTES PROVEEDORES DE IA AQUÍ
case _:
raise ValueError(f"Proveedor de IA no soportado: {text_request.provider}")
# Función de adaptador para resumir texto usando OpenAI
async def summarize_with_openai(text_request: TextRequestFile) -> StandardTextAnalysisResult:
"""
Función de adaptador para resumir texto usando OpenAI.
(Plantilla para futuras implementaciones)
"""
client = AsyncOpenAI(api_key=settings.OPENAI_API_KEY)
# PASOS A SEGUIR PARA IMPLEMENTAR LA LÓGICA DE RESUMEN CON OPENAI:
# 1. Validar el texto de entrada (tamaño, formato, etc.)
# 2. Configurar el cliente de OpenAI con la clave API
# 3. Llamar a la API de OpenAI para resumir el texto
# 4. Convertir la respuesta de OpenAI al formato estándar de resumen de texto de Qualidot
# 5. Manejar errores y excepciones adecuadamente
raise NotImplementedError("La función summarize_with_openai aún no está implementada.")
# Otros modelos de IA

View File

@@ -0,0 +1,67 @@
"""
Gateway de IA de Qualidot - Módulo de Adaptadores de Transcripción de Video
Propósito:
Este módulo contiene funciones de adaptadores que permiten resumir texto 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 resumen de texto de Qualidot.
"""
import tempfile
import os
from fastapi import HTTPException
from openai import OpenAI, AsyncOpenAI
import assemblyai as aai
from app.core.config import settings
from app.schemas.video_standard import VideoRequestFile, StandardTranscriptionResult
from app.core import config
# Función de adaptador principal que infiere el proveedor y llama al adaptador específico
async def transcribe_video_with_provider(video_request: VideoRequestFile) -> StandardTranscriptionResult:
"""
Función de adaptador para transcribir video usando el proveedor de IA configurado.
"""
provider = video_request.provider.lower()
match provider:
case "nombre de la ia 1 aqui":
return await transcribe_with_ai_model1(video_request)
case "nombre de la ia 2 aqui":
return await transcribe_with_ai_model2(video_request)
# AGREGAR OTROS CASOS PARA DIFERENTES PROVEEDORES DE IA AQUÍ
case _:
raise ValueError(f"Proveedor de IA no soportado: {video_request.provider}")
# Función de adaptador para transcribir video usando OpenAI
async def transcribe_with_ai_model1(video_request: VideoRequestFile) -> StandardTranscriptionResult:
"""
Función de adaptador para transcribir video usando OpenAI.
(Plantilla para futuras implementaciones)
"""
# PASOS A SEGUIR PARA IMPLEMENTAR LA LÓGICA DE TRANSCRIPCIÓN CON IA (ELEGIR MODELO):
# 1. Validar el video de entrada (tamaño, formato, etc.)
# 2. Configurar el cliente de OpenAI con la clave API
# 3. Llamar a la API de OpenAI para transcribir el video
# 4. Convertir la respuesta de OpenAI al formato estándar de resumen de texto de Qualidot
# 5. Manejar errores y excepciones adecuadamente
raise NotImplementedError("La función transcribe_with_ai_model1 aún no está implementada.")
async def transcribe_with_ai_model2(video_request: VideoRequestFile) -> StandardTranscriptionResult:
"""
Función de adaptador para transcribir video usando OpenAI.
(Plantilla para futuras implementaciones)
"""
# PASOS A SEGUIR PARA IMPLEMENTAR LA LÓGICA DE TRANSCRIPCIÓN CON IA (ELEGIR MODELO):
# 1. Validar el video de entrada (tamaño, formato, etc.)
# 2. Configurar el cliente de OpenAI con la clave API
# 3. Llamar a la API de OpenAI para transcribir el video
# 4. Convertir la respuesta de OpenAI al formato estándar de resumen de texto de Qualidot
# 5. Manejar errores y excepciones adecuadamente
raise NotImplementedError("La función transcribe_with_ai_model2 aún no está implementada.")
# Otros modelos de IA

View File

@@ -0,0 +1,62 @@
"""
Validadores comunes para los endpoints de audio.
"""
import os
from fastapi import UploadFile, HTTPException
from app.schemas.audio_standard import AudioRequestFile
# Configuración de validaciones
ALLOWED_AUDIO_FORMATS = ["audio/mpeg", "audio/wav", "audio/x-wav", "audio/mp4", "audio/x-m4a"]
ALLOWED_EXTENSIONS = [".mp3", ".wav", ".m4a"]
MAX_AUDIO_SIZE_MB = 25 # Tamaño máximo en MB
MAX_AUDIO_SIZE_BYTES = MAX_AUDIO_SIZE_MB * 1024 * 1024
def validate_audio_file(audio_file: UploadFile) -> None:
"""
Valida el formato y tamaño del archivo de audio.
Args:
audio_file: Archivo de audio a validar
Raises:
HTTPException: Si el archivo no cumple con los requisitos
"""
# Validar formato (content-type)
if audio_file.content_type not in ALLOWED_AUDIO_FORMATS:
raise HTTPException(
status_code=400,
detail=f"Formato de audio no válido. Solo se permiten: MP3, WAV, M4A"
)
# Validar extensión del archivo
file_extension = os.path.splitext(audio_file.filename)[1].lower()
if file_extension not in ALLOWED_EXTENSIONS:
raise HTTPException(
status_code=400,
detail=f"Extensión de archivo no válida. Solo se permiten: .mp3, .wav, .m4a"
)
def validate_audio_size(audio_content: bytes) -> None:
"""
Valida el tamaño del contenido del audio.
Args:
audio_content: Contenido del archivo de audio en bytes
Raises:
HTTPException: Si el archivo excede el tamaño máximo
"""
if len(audio_content) > MAX_AUDIO_SIZE_BYTES:
raise HTTPException(
status_code=400,
detail=f"El archivo excede el tamaño máximo permitido de {MAX_AUDIO_SIZE_MB}MB"
)
def validate_audio_request(audio_request: AudioRequestFile, audio_content: bytes):
# Validar el archivo de audio
validate_audio_file(audio_request.file)
# Validar tamaño del archivo
validate_audio_size(audio_content)