optchunkopt / settings.py
FLAFUENTE's picture
Fix embeddings pipeline initialization: restore default Qdrant API key fallback and enhance explainability prompts with theoretical explanations
85e8be9
Raw History Blame Contribute Delete
7.1 kB
"""
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]