Capa de embeddings
src/indexing/embeddings.py transforma texto en vectores con sentence-transformers.
No almacena vectores ni realiza búsquedas.
Contrato
EmbeddingService(settings=None, model=None, batch_size=32)carga una vez el modelo configurado.modelpermite inyectar un modelo para pruebas. El tamaño de lote controla memoria y rendimiento, no el tamaño de los chunks.embed_documents(embedding_texts)recibe textos ya preparados y devuelve una lista de vectores en el mismo orden. No añade ni elimina prefijos o contexto.embed_chunks(chunks)adapta los chunks usando exclusivamenteembedding_text.embed_query(query)recibe una pregunta sin preparar, recorta espacios exteriores y añadequery:. No pasar consultas que ya tengan el prefijo de preparación.get_embedding_service()reutiliza una instancia por proceso. En una aplicación con varios procesos cada uno tendrá su modelo. Reiniciar al cambiar configuración.
Ambas rutas solicitan normalización L2 y devuelven listas de números Python.
Los textos vacíos y lotes vacíos producen errores. Se comprueba la longitud con
el tokenizer del modelo, incluyendo prefijo y tokens especiales, antes de inferir.
El límite efectivo es el menor entre max_seq_length del ejecutor y el límite
configurado si existe. Los excesos producen un error, nunca truncamiento silencioso.
La validación de longitud no modifica la estrategia ni la interfaz de chunking.
from src.indexing.embeddings import get_embedding_service
service = get_embedding_service()
# chunks procede de chunk_document(...)
vectors = service.embed_chunks(chunks)
question_vector = service.embed_query('¿Qué gastos puedo deducir?')
E5 es la opción provisional actual. Si se cambia el modelo, revisar las convenciones
para consultas y documentos; el prefijo de consulta implementado aquí es el de E5.
Se usa encode(..., prompt="", normalize_embeddings=True) para impedir que un
prompt por defecto del modelo duplique los prefijos ya preparados.
Dependencias y pruebas
Se añade sentence-transformers>=3.4,<4, compatible con el rango actual
transformers>=4.45,<5. El entorno de pruebas se instala con uv a partir de
requirements.txt; esto no migra el proyecto a uv.lock ni modifica su .venv existente.
Pruebas ordinarias, sin descargar pesos:
python -m pytest tests/test_embeddings.py -q
python -m pytest tests/ -q
Integración real opcional (descarga pesos E5 en la caché local y ejecuta en CPU):
$env:RUN_EMBEDDINGS_INTEGRATION='1'
python -m pytest tests/test_embeddings_integration.py -q
Remove-Item Env:RUN_EMBEDDINGS_INTEGRATION
La integración comprueba conexión con chunking, dimensiones, valores finitos, normalización y equivalencia con llamadas directas al modelo. No evalúa retrieval. El CI normal la omite y los tests unitarios inyectan un modelo simulado.
Referencias: