129 lines
6.2 KiB
Python
129 lines
6.2 KiB
Python
"""
|
|
Modelos Pydantic para las operaciones de chunking.
|
|
"""
|
|
from pydantic import BaseModel, Field, validator
|
|
from typing import List, Dict, Any, Optional
|
|
|
|
|
|
# Request Models
|
|
|
|
class ChunkingPreviewRequest(BaseModel):
|
|
"""Request para generar preview de chunks"""
|
|
file_name: str = Field(..., description="Nombre del archivo PDF")
|
|
tema: str = Field(..., description="Tema/carpeta del archivo")
|
|
max_tokens: int = Field(default=950, ge=100, le=2000, description="Límite máximo de tokens por chunk")
|
|
target_tokens: int = Field(default=800, ge=100, le=2000, description="Tokens objetivo")
|
|
chunk_size: int = Field(default=1000, ge=100, le=3000, description="Tamaño del chunk")
|
|
chunk_overlap: int = Field(default=200, ge=0, le=1000, description="Solapamiento entre chunks")
|
|
use_llm: bool = Field(default=True, description="Usar LLM (Gemini) para procesamiento inteligente")
|
|
custom_instructions: str = Field(default="", description="Instrucciones personalizadas (solo si use_llm=True)")
|
|
|
|
@validator("custom_instructions")
|
|
def validate_custom_instructions(cls, v, values):
|
|
"""Valida que custom_instructions solo se use con LLM habilitado"""
|
|
if v and not values.get("use_llm", True):
|
|
raise ValueError("custom_instructions solo puede usarse cuando use_llm=True")
|
|
return v
|
|
|
|
@validator("target_tokens")
|
|
def validate_target_tokens(cls, v, values):
|
|
"""Valida que target_tokens sea menor que max_tokens"""
|
|
if "max_tokens" in values and v >= values["max_tokens"]:
|
|
raise ValueError("target_tokens debe ser menor que max_tokens")
|
|
return v
|
|
|
|
|
|
class ChunkingProcessRequest(BaseModel):
|
|
"""Request para procesar PDF completo"""
|
|
file_name: str = Field(..., description="Nombre del archivo PDF")
|
|
tema: str = Field(..., description="Tema/carpeta del archivo")
|
|
collection_name: str = Field(..., description="Nombre de la colección en Qdrant")
|
|
max_tokens: int = Field(default=950, ge=100, le=2000, description="Límite máximo de tokens por chunk")
|
|
target_tokens: int = Field(default=800, ge=100, le=2000, description="Tokens objetivo")
|
|
chunk_size: int = Field(default=1000, ge=100, le=3000, description="Tamaño del chunk")
|
|
chunk_overlap: int = Field(default=200, ge=0, le=1000, description="Solapamiento entre chunks")
|
|
use_llm: bool = Field(default=True, description="Usar LLM (Gemini) para procesamiento inteligente")
|
|
custom_instructions: str = Field(default="", description="Instrucciones personalizadas (solo si use_llm=True)")
|
|
|
|
@validator("custom_instructions")
|
|
def validate_custom_instructions(cls, v, values):
|
|
"""Valida que custom_instructions solo se use con LLM habilitado"""
|
|
if v and not values.get("use_llm", True):
|
|
raise ValueError("custom_instructions solo puede usarse cuando use_llm=True")
|
|
return v
|
|
|
|
@validator("target_tokens")
|
|
def validate_target_tokens(cls, v, values):
|
|
"""Valida que target_tokens sea menor que max_tokens"""
|
|
if "max_tokens" in values and v >= values["max_tokens"]:
|
|
raise ValueError("target_tokens debe ser menor que max_tokens")
|
|
return v
|
|
|
|
|
|
# Response Models
|
|
|
|
class ChunkPreview(BaseModel):
|
|
"""Modelo para un chunk de preview"""
|
|
index: int = Field(..., description="Índice del chunk")
|
|
text: str = Field(..., description="Contenido del chunk")
|
|
page: int = Field(..., description="Número de página")
|
|
file_name: str = Field(..., description="Nombre del archivo")
|
|
tokens: int = Field(..., description="Número aproximado de tokens")
|
|
|
|
|
|
class ChunkingPreviewResponse(BaseModel):
|
|
"""Response para preview de chunks"""
|
|
success: bool = Field(default=True, description="Indica si la operación fue exitosa")
|
|
file_name: str = Field(..., description="Nombre del archivo procesado")
|
|
tema: str = Field(..., description="Tema del archivo")
|
|
chunks: List[ChunkPreview] = Field(..., description="Lista de chunks de preview (hasta 3)")
|
|
message: str = Field(default="Preview generado exitosamente", description="Mensaje descriptivo")
|
|
|
|
@validator("chunks")
|
|
def validate_chunk_count(cls, v):
|
|
"""Valida que haya al menos 1 chunk y máximo 3 chunks en el preview"""
|
|
if len(v) < 1:
|
|
raise ValueError("El preview debe contener al menos 1 chunk")
|
|
if len(v) > 3:
|
|
raise ValueError("El preview no puede contener más de 3 chunks")
|
|
return v
|
|
|
|
|
|
class ChunkingProcessResponse(BaseModel):
|
|
"""Response para procesamiento completo"""
|
|
success: bool = Field(..., description="Indica si la operación fue exitosa")
|
|
collection_name: str = Field(..., description="Nombre de la colección")
|
|
file_name: str = Field(..., description="Nombre del archivo procesado")
|
|
total_chunks: int = Field(..., description="Total de chunks generados")
|
|
chunks_added: int = Field(..., description="Chunks agregados a Qdrant")
|
|
message: str = Field(..., description="Mensaje descriptivo")
|
|
|
|
|
|
# Profile Models
|
|
|
|
class ChunkingProfile(BaseModel):
|
|
"""Perfil de configuración predefinido para chunking"""
|
|
id: str = Field(..., description="ID del perfil")
|
|
name: str = Field(..., description="Nombre del perfil")
|
|
description: str = Field(..., description="Descripción del perfil")
|
|
max_tokens: int = Field(..., description="Límite máximo de tokens")
|
|
target_tokens: int = Field(..., description="Tokens objetivo")
|
|
chunk_size: int = Field(..., description="Tamaño del chunk")
|
|
chunk_overlap: int = Field(..., description="Solapamiento")
|
|
use_llm: bool = Field(..., description="Si usa LLM")
|
|
|
|
|
|
class ChunkingProfilesResponse(BaseModel):
|
|
"""Response con perfiles disponibles"""
|
|
profiles: List[ChunkingProfile] = Field(..., description="Lista de perfiles disponibles")
|
|
|
|
|
|
# Progress Models (para WebSockets)
|
|
|
|
class ChunkingProgress(BaseModel):
|
|
"""Modelo para reportar progreso de chunking"""
|
|
status: str = Field(..., description="Estado actual: downloading, chunking, embedding, uploading, completed, error")
|
|
progress: int = Field(..., ge=0, le=100, description="Progreso en porcentaje")
|
|
message: Optional[str] = Field(None, description="Mensaje adicional")
|
|
error: Optional[str] = Field(None, description="Mensaje de error si status=error")
|