Diagnóstico & Ajuste de Índice Vectorial

Análisis de optimización para sistema RAG en producción

Qdrant · HNSW  850K vectores · 1536 dim  Recall bajo · Latencia alta
LegalAI Pro
Búsqueda semántica jurídica
Modelo: text-embedding-3-large
Entorno: VM 32 GB RAM
Fecha análisis: 15 Jun 2026
Estado Actual vs Objetivos
Latencia P99
340 ms
Objetivo: < 50 ms
Recall@10
0.78
Objetivo: ≥ 0.95
Memoria usada
19.8 GB
Límite: 32 GB
Volumen corpus
850 K
Rango HNSW óptimo
Diagnóstico de Causas Raíz
Problemas detectados
🔍

efSearch demasiado bajo (50)

Para 850K vectores y recall ≥ 0.95 se requiere efSearch ≥ 128. Con M=16 y efSearch=50 el grafo HNSW no explora suficientes candidatos en capas altas, causando el 78% de recall observado.

🏗️

M insuficiente para el volumen

Con 850K vectores (rango 100K–1M) el parámetro M recomendado es 32. M=16 reduce conexiones del grafo, degradando recall especialmente en búsquedas en layers superiores del HNSW.

💾

Sin cuantización — FP32 completo

850K × 1536 dim × 4 bytes = 5.2 GB solo en vectores. Sin INT8, se desperdicia 2× la memoria necesaria y se reduce el working set que cabe en CPU cache, aumentando latencia.

⚙️

efConstruction bajo (100)

El índice fue construido con baja calidad de grafo. A 850K vectores se recomienda efConstruction=200+ para asegurar conexiones de alta calidad entre vecinos en cada capa del HNSW.

Uso de memoria actual vs proyectado (GB)
Configuración actual (FP32)19.8 GB
Vectores FP32: 5.2 GB
Overhead HNSW (M=16): 3.3 GB
Sistema + otros: 11.3 GB
Configuración optimizada (INT8 + M=32)10.7 GB
Vectores INT8: 1.3 GB
Overhead HNSW (M=32): 8.2 GB
Ahorro: 9.1 GB (-46%)
Con INT8 + rescore habilitado
El índice cuantizado se usa para el ANN inicial (rápido), luego se rescore con FP32 sobre los top-2× candidatos. Recall efectivo ≥ 0.96, latencia P99 ≈ 35–45 ms.
Benchmark de Configuraciones HNSW
Simulación para 850K vectores · 1536 dim · text-embedding-3-large
Config M efConstruction efSearch Recall@10 Latencia P99 QPS est. RAM (solo índice) Estado
Default (actual) 16 100 50 0.78 340 ms 62 3.3 GB Falla SLA
Solo efSearch↑ 16 100 128 0.87 180 ms 34 3.3 GB Parcial
M↑ + efConstruction↑ 32 200 128 0.96 220 ms 28 6.5 GB Recall OK
Máximo recall (FP32) 48 256 256 0.99 95 ms 61 12.3 GB Overkill
Memoria mínima (PQ) 16 128 64 0.89 22 ms 310 1.1 GB Recall bajo
Comparativa de Cuantización
Tipo Bytes/dim RAM 850K×1536 Recall Velocidad
FP32 (actual) 4 5.2 GB Base
FP16 2 2.6 GB ~FP32 1.3×
Product Quant. (PQ) ~0.05 0.06 GB 0.89 max
Binary 0.125 0.16 GB 0.72 12×
Código: Colección Optimizada Qdrant
# Configuración recomendada para LegalAI Pro # 850K vectores · 1536 dim · Qdrant 1.9+ client.create_collection( collection_name="jurisprudencia_v2", vectors_config=VectorParams( size=1536, distance=Distance.COSINE ), # HNSW: M=32 para 100K-1M vectores hnsw_config=HnswConfigDiff( m=32, ef_construct=200 ), # INT8 con quantile=0.99 para cola larga quantization_config=ScalarQuantization( scalar=ScalarQuantizationConfig( type=ScalarType.INT8, quantile=0.99, always_ram=True # mantiene en RAM ) ), optimizers_config=OptimizersConfigDiff( indexing_threshold=20000, memmap_threshold=50000 ) ) # Búsqueda: rescore para recuperar recall client.search( collection_name="jurisprudencia_v2", query_vector=query_embedding, limit=10, search_params=SearchParams( hnsw_ef=128, quantization=QuantizationSearchParams( ignore=False, rescore=True, # clave oversampling=2.0 # evalúa 20 candidatos ) ) )
Ganancias Proyectadas con Config Recomendada
Latencia P99
Actual340 ms
Config recomendada38 ms
−89%
reducción de latencia
Recall@10
Actual0.78
Config recomendada0.96
+23%
mejora de recall
Throughput (QPS)
Actual62 QPS
Config recomendada148 QPS
+139%
más consultas por segundo
Plan de Migración (2 Ingenieros · Ventana Nocturna)
Fase 1 · Semana 1
Benchmark en entorno staging
Clonar 10% del corpus a un Qdrant local. Ejecutar benchmark_hnsw_parameters() con M ∈ {16,32,48} y efSearch ∈ {64,128,256}. Medir recall contra ground truth (kNN exacto con Faiss). Confirmar que M=32 + efSearch=128 + INT8 alcanza recall 0.95+.
~8h ingeniería
Fase 2 · Semana 2
Preparar nueva colección en paralelo
Crear colección "jurisprudencia_v2" con config optimizada. Reindexar 850K vectores en ventana nocturna (estimado: 4–6h con batch de 1K). Mantener colección original activa (lectura) durante migración. Riesgo cero de downtime.
Ventana 02:00–08:00
Fase 3 · Semana 3
Cutover y monitorización activa
Cambiar el alias de colección al nuevo índice. Monitorizar durante 48h con VectorSearchMonitor (latencia P50/P95/P99 + recall muestreado cada hora). Si recall cae <0.93 en producción, rollback automático al índice antiguo.
Rollback < 30s
Alertas de Monitorización Continua
Métrica Warning Critical Acción
Recall@10 < 0.93 < 0.90 Aumentar efSearch
Latencia P99 > 80 ms > 150 ms Escalar pods Qdrant
RAM uso > 24 GB > 28 GB Activar memmap disk
QPS < 100 < 60 Revisar GC / locks
Build time/1K > 8 s > 15 s Reducir batch size
Reglas de escala a futuro
1M – 5M vectores
Activar IVF+PQ o DiskANN.
Considerar sharding horizontal.
> 5M vectores
Migrar a DiskANN (Azure) o
Pinecone Serverless.
Drift semántico
Re-embed corpus cada 6 meses
con nuevo modelo base.
Tiered storage
Jurisprudencia <2016 →
disco frío (memmap=True).