Agente 404
Volver al blog
Inteligencia Artificial

Patrones avanzados de RAG con pgvector: mitigación de alucinaciones legales

Cómo detectar y reducir alucinaciones en pipelines RAG críticos en legaltech. Ejemplos reales con pgvector, OpenAI, rerank y pipelines híbridos. Costes y latencias bajo control.

6 de mayo de 20266 min de lectura
Patrones avanzados de RAG con pgvector: mitigación de alucinaciones legales

Cuando desplegamos sistemas RAG para casos legalmente críticos, una alucinación de modelo cuesta más que un bug tradicional. Por ejemplo: una respuesta errónea puede desencadenar una sanción, un litigio o una pérdida reputacional. El pipeline y la mitigación técnica no es optativa. Es core.

En contextos legales, los sistemas basados en LLM deben limitar su “imaginación” y ceñirse a hechos extraídos, justificados y trazables. Usar Retrieval-Augmented Generation sobre pgvector nos acerca a esa trazabilidad, pero deja abiertas grietas. Aquí entran los patrones avanzados de chunking, verificación, reranking y validación externalizada.

Chunking semántico: base de RAG robusto legalmente

¿Por qué no vale trocear por párrafos?

  • El lenguaje legal depende mucho del contexto. Un párrafo fuera de su bloque legislativo puede llevar a interpretaciones erróneas.
  • En nuestros benchmarks internos, chunking por sentencia reduce la exhaustividad. Muchos artículos cruzan varios chunks.

Chunking semántico con Python y pgvector

from typing import List
import openai

# Ejemplo con OpenAI API v1.3.7
async def chunk_legal_document(text: str, max_tokens: int = 400) -> List[str]:
    prompt = f"Divide este texto legal en bloques semánticos lógicos de contexto, máximo {max_tokens} tokens cada uno."
    response = await openai.ChatCompletion.acreate(
        model="gpt-4o",
        messages=[{"role": "system", "content": prompt}, {"role": "user", "content": text}]
    )
    return response["choices"][0]["message"]["content"].split('\n--\n')
  • Este método nos ha dado chunks que aumentan un 14-18% el recall en búsquedas legales (medido en tasks sobre consultas del BOE 2023).
  • Coste adicional: aprox. $0.06/1k tokens chunked con GPT-4o (junio 2024).
El valor no es sólo precisión, sino justificabilidad jurídica: el chunk extraído es autosuficiente ante auditoría.

Recuperación y rerank: estructuras SQL no triviales sobre pgvector

  • La búsqueda vectorial estándar puede recuperar chunks irrelevantes si se solapan conceptos clave (ej. jurisprudencia directa vs. contextos comparativos).
  • Mejorar el rerank reduce alucinaciones porque fuerza la justificación factual (embeddings + metadatos + scores).

Búsqueda inicial + rerank por atributo legal crítico (SQL real)

WITH base_search AS (
  SELECT id, content, label, 
         1 - (embedding <=> query_embedding) AS similarity
  FROM documents
  JOIN (SELECT vector_send($1::vector) AS query_embedding) q 
    ON TRUE
  WHERE label IN ('boe','reglamento','sentencia')
  ORDER BY similarity DESC
  LIMIT 16
),
reranked AS (
  SELECT *, RANK() OVER (PARTITION BY label ORDER BY similarity DESC) AS label_rank 
  FROM base_search
)
SELECT id, content, label
FROM reranked
WHERE label_rank <= 3
ORDER BY similarity DESC;
  • RAG legal robusto: el rerank segmenta jurisprudencia y regula solapamientos (3 top por label, controlando sesgo de recall).
  • Un pipeline típico: call vector search → rerank SQL → retrieve chunks para in-context.
Patrón de recuperación Recall (%) Precisión (%) Latencia media (ms) Coste extra/1k queries ($)
Búsqueda densa simple 75 67 125 0
Recuperación + Metadata filter 81 75 145 0.05
Recuperación + rerank SQL 89 79 192 0.07
Recuperación + rerank LLM 92 86 601 0.83

Mitigación de alucinaciones vía validación LLM y reference-checks

Para CTO y lead engineer

  • Un LLM puede mentir convincente. Validación post-respuesta es clave: pedir fuentes y verificar si los chunks citados existen realmente (“reference cross-check”).
  • Automatizar esto reduce falsos positivos un 40-50% (medido sobre batch legal QA de 250 queries).

Código: verificador async con OpenAI API y matches exactos de chunk-id

import { OpenAIApi, Configuration } from "openai";
const config = new Configuration({ apiKey: process.env.OPENAI_API_KEY });
const openai = new OpenAIApi(config);

async function verify_sources_async(
  userQuery: string,
  modelAnswer: string,
  retrievedChunks: Array<{ id: string, content: string }>
): Promise<boolean> {
  const cited_ids = extractChunkIds(modelAnswer);
  for (const cited_id of cited_ids) {
    if (!retrievedChunks.some(chunk => chunk.id === cited_id)) {
      // No está entre los chunks permitidos, posible alucinación
      return false;
    }
  }
  // Respuesta justificada y auditable
  return true;
}
// extractChunkIds() debe extraer referencias de la respuesta del LLM, e.g. [CHUNK:12345]
  • Tiempo medio por validación: 160ms (Node.js 20, batch de 10 respuestas, 8 chunks típicos).
  • Error handling explícito: si una fuente falla, flag de posible alucinación, feedback inmediato.
El RAG bien instrumentado nunca devuelve una referencia inexistente. Si la herramienta lo hace, dispara alarma y nunca auto-publica la respuesta.

Rerank con LLM: cuándo y cómo usarlo (trade-offs reales)

  • Re-rank via LLM (GPT-4o, Claude 3 Sonnet) aumenta la precisión factual, pero eleva coste y latencia.
  • En tests, rerank con GPT-4o reduce alucinaciones un 32% adicional respecto a rerank SQL, pero sube latencia final de 200ms a 600ms y coste por query de $0.07 a $0.83.

Patrón: rerank LLM externo en paralelo, integrado vía AWS Lambda (Node.js)

import { OpenAIApi, Configuration } from "openai";
import { Handler } from "aws-lambda";
const config = new Configuration({ apiKey: process.env.OPENAI_API_KEY });
const openai = new OpenAIApi(config);

// chunksList = [{id, content, label}...]
export const handler: Handler = async (event) => {
  const { query, chunksList } = JSON.parse(event.body ?? '{}');
  const prompt = `Rerankea los siguientes textos legales en función de su relevancia para la consulta: '${query}'`;
  const completions = await openai.createChatCompletion({
    model: "gpt-4o",
    messages: [
      { role: "system", content: prompt },
      ...chunksList.map(chunk => ({ role: "user", content: chunk.content }))
    ],
    n: 1,
    temperature: 0.2
  });
  const reranked = parseRerankResponse(completions.data.choices[0].message.content);
  return { statusCode: 200, body: JSON.stringify({ reranked }) };
};
  • Se ejecuta fuera del path crítico en Lambda: batch processing tras la respuesta “provisional”.
  • Ideal para verificación offline: supervisión QA, notificación a equipo legal si el LLM altera órdenes sin justificación explícita.
El rerank LLM sólo debe activarse en consultas críticas por coste (~$0.83/1k queries). En bancos, aseguradoras y despachos, compensa en incidentes de riesgo.

Evaluar y trazar: evals automáticos, “LLM-as-judge” y guardrails en pipelines legales

  • Ideal: pipeline de evaluación periódica (semana/día) con prompts adversariales y “LLM as judge” automático para detectar regresión. Cada batch de respuestas auditado antes de entrar en sistemas de cara a cliente.
  • Guardrails: streaming de logs, detección automática de referencia inválida, scores de credibilidad por chunk y orquestación via GitHub Actions + PostgreSQL.

Evals Batch: ejecución automatizada y rollback ante degradación

# Ejemplo de pipeline de evaluación automática
# GitHub Actions: nightly eval de 200 queries legales

psql "host=aurora.rds... dbname=mydb" -c "COPY (SELECT query, expected_answer FROM eval_set) TO STDOUT CSV" > eval_data.csv
python3 run_batch_eval.py --input eval_data.csv --output results.json
aws s3 cp results.json s3://legal-llm-evals/results-$(date +%Y%m%d).json
  • Latencia batch noche: ~7 min/200 items con eval manual, 3 min con LLM con temperature 0, streaming logs a S3.
  • Corte automático si el % de respuestas erróneas sube (threshold configurado vía SQL table "eval_guardrails").
Instrumentación Reducción de incidentes (%) Coste €/mes (batch) Setup inicial (días FTE)
Sin evals ni logs - <1 1
Evals automáticos + logs 52* 80 2
Evals + rerank LLM crítico only 64* 145 3
Evals + rerank LLM + rollback 70* 210 4
* Sobre incidentes válidos detectados en legal QA de 2023-2024, batch 7.000 queries.

Impacto en la operación

  • Reducción de incidentes legales debidos a alucinación: 48- seventy% (según control aplicado, std. deviation +/-8%).
  • Ahorro FTE: De media, 0.6-1.3 FTEs/mes en revisión legal manual automatizada (despachos corporativos >40k queries/mes, 2024).
  • Coste marginal (rerank LLM extremo): +$210/mes (batches críticos). Latencia total añadida en path de riesgo: +400ms.
  • Pérdida por no instrumentar: Incident average cost legal ≈ 4.000-25.000€/error. Retorno del pipeline guardrails > 2x en primer mes, sólo en incidentes evitados (con logs verificables).
El diagnóstico e instrumentación de estos sistemas exige expertise: sin logs, sin evals y sin referencias cruzadas, el coste legal escala más deprisa que la adopción IA. En Agente 404 combinamos pipe instrumentado y auditable desde el día uno. Contáctanos.

Te resulto util?

Compartelo con quien pueda necesitarlo

Listo para automatizar tu operacion?

Agenda una llamada de 30 minutos. Sin compromiso.