Spaces:
Sleeping
Sleeping
File size: 7,096 Bytes
f729bac 4cc8f6d f729bac 4cc8f6d f729bac 7d90935 85e8be9 f729bac 7d90935 f729bac | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 | """
MIT License
Autor: Fernando Lafuente
Proyecto: Ejercicio opcional NLP - Chunking y Recuperación
Descripción: Configuración centralizada de parámetros del sistema
Este módulo centraliza todos los parámetros configurables del sistema de chunking
y recuperación semántica. Permite modificar el comportamiento sin tocar el código
principal, siguiendo principios de arquitectura limpia.
"""
import os
from pathlib import Path
from dotenv import load_dotenv
# Cargar variables de entorno desde archivo .env
load_dotenv()
# =============================================================================
# CONFIGURACIÓN DE RUTAS Y ARCHIVOS
# =============================================================================
# Directorio raíz del proyecto
PROJECT_ROOT = Path(__file__).parent.absolute()
# Directorio donde se almacenan los archivos PDF
PDF_DIRECTORY = PROJECT_ROOT / "data" / "pdf"
# Crear directorio si no existe
PDF_DIRECTORY.mkdir(parents=True, exist_ok=True)
# =============================================================================
# CONFIGURACIÓN DE OPENAI EMBEDDINGS
# =============================================================================
# Clave de API de OpenAI (debe configurarse como variable de entorno)
# Ejecutar: export OPENAI_API_KEY="tu_clave_aqui"
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
# Modelo de embeddings de OpenAI a utilizar
# Opciones: "text-embedding-3-small", "text-embedding-3-large", "text-embedding-ada-002"
OPENAI_EMBEDDING_MODEL = "text-embedding-3-large" # Más económico y eficiente
# Dimensionalidad de los embeddings de OpenAI (text-embedding-3-large)
EMBEDDING_DIMENSION = 3072
EMBEDDING_DIMENSIONS = 3072 # Alias for compatibility
# =============================================================================
# CONFIGURACIÓN DE QDRANT
# =============================================================================
# URL de conexión a Qdrant (leer de entorno si existe)
# Prioriza variables de entorno definidas en .env o en el entorno de ejecución
QDRANT_URL = os.getenv("QDRANT_URL", "https://4f31fdeb-269a-4aaf-bb34-f93214bf332f.europe-west3-0.gcp.cloud.qdrant.io:6333")
QDRANT_API_KEY = os.getenv("QDRANT_API_KEY", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2Nlc3MiOiJtIn0.E5XdnXbENZYRKHwhgVXYvZE3VtbWQc91Jbdr85aNenc")
# Nombre de la colección donde se almacenan los vectores
QDRANT_COLLECTION_NAME = "chunks_collection"
# Política de inserción al procesar documentos:
# True = reemplazar colección del método (limpiar y reinsertar)
# False = anexar (append) a la colección existente
REPLACE_COLLECTION_ON_PROCESS = bool(int(os.getenv("REPLACE_COLLECTION_ON_PROCESS", "1")))
# =============================================================================
# CONFIGURACIÓN DE CHUNKING
# =============================================================================
# Método de chunking a utilizar
# Opciones: "fixed", "sentence", "adaptive"
CHUNKING_METHOD = "adaptive"
# Parámetros para chunking fijo
FIXED_CHUNK_SIZE = 500 # caracteres por chunk
FIXED_CHUNK_OVERLAP = 50 # caracteres de solapamiento
# Parámetros para chunking por oraciones
SENTENCE_MIN_LENGTH = 50 # longitud mínima de oración en caracteres
SENTENCE_MAX_CHUNK_SIZE = 800 # tamaño máximo de chunk en caracteres
# Parámetros para chunking adaptativo
ADAPTIVE_SIMILARITY_THRESHOLD = 0.7 # umbral de similitud coseno (0-1)
ADAPTIVE_MIN_CHUNK_SIZE = 100 # tamaño mínimo de chunk en caracteres
ADAPTIVE_MAX_CHUNK_SIZE = 1000 # tamaño máximo de chunk en caracteres
# Lista de métodos de chunking soportados por el sistema
CHUNKING_METHODS = ["fixed", "sentence", "adaptive"]
# =============================================================================
# CONFIGURACIÓN DE BÚSQUEDA Y RETRIEVAL
# =============================================================================
# Número de chunks más relevantes a retornar
TOP_K_RESULTS = 10
# Puntuación mínima de similitud para considerar un resultado relevante
MIN_SIMILARITY_SCORE = 0.5
# =============================================================================
# CONFIGURACIÓN DE LOGGING
# =============================================================================
# Nivel de logging
# Opciones: "DEBUG", "INFO", "WARNING", "ERROR"
LOG_LEVEL = "DEBUG"
# Formato de los mensajes de log
LOG_FORMAT = "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
# =============================================================================
# CONFIGURACIÓN DE PROCESAMIENTO DE TEXTO
# =============================================================================
# Caracteres a eliminar durante la limpieza de texto
CHARS_TO_REMOVE = ["\n\n", "\t", "\r"]
# Caracteres a reemplazar por espacios
CHARS_TO_REPLACE = {"\n": " ", " ": " "}
# Longitud mínima de texto válido después de limpieza
MIN_TEXT_LENGTH = 10
# =============================================================================
# VALIDACIÓN DE CONFIGURACIÓN
# =============================================================================
def validate_settings():
"""
Valida que la configuración sea correcta antes de ejecutar el sistema.
Raises:
ValueError: Si algún parámetro es inválido
FileNotFoundError: Si no se encuentra el directorio de PDFs
"""
# Validar que existe el directorio de PDFs
if not PDF_DIRECTORY.exists():
raise FileNotFoundError(f"Directorio de PDFs no encontrado: {PDF_DIRECTORY}")
# Validar que hay al menos un PDF en el directorio
pdf_files = list(PDF_DIRECTORY.glob("*.pdf"))
if not pdf_files:
raise FileNotFoundError(f"No se encontraron archivos PDF en: {PDF_DIRECTORY}")
# Validar clave de API de OpenAI
if not OPENAI_API_KEY:
raise ValueError("Variable de entorno OPENAI_API_KEY no configurada")
# Validar método de chunking
valid_methods = ["fixed", "sentence", "adaptive"]
if CHUNKING_METHOD not in valid_methods:
raise ValueError(f"Método de chunking inválido: {CHUNKING_METHOD}. "
f"Opciones válidas: {valid_methods}")
# Validar parámetros numéricos
if TOP_K_RESULTS <= 0:
raise ValueError("TOP_K_RESULTS debe ser mayor que 0")
if MIN_SIMILARITY_SCORE < 0 or MIN_SIMILARITY_SCORE > 1:
raise ValueError("MIN_SIMILARITY_SCORE debe estar entre 0 y 1")
# Validar umbrales de chunking adaptativo
if ADAPTIVE_SIMILARITY_THRESHOLD < 0 or ADAPTIVE_SIMILARITY_THRESHOLD > 1:
raise ValueError("ADAPTIVE_SIMILARITY_THRESHOLD debe estar entre 0 y 1")
def get_pdf_file():
"""
Obtiene el primer archivo PDF encontrado en el directorio configurado.
Returns:
Path: Ruta al archivo PDF
Raises:
FileNotFoundError: Si no se encuentra ningún PDF
"""
pdf_files = list(PDF_DIRECTORY.glob("*.pdf"))
if not pdf_files:
raise FileNotFoundError(f"No se encontraron archivos PDF en: {PDF_DIRECTORY}")
# Retorna el primer PDF encontrado
return pdf_files[0] |