Volver a la wiki

HyDE Opcional en Retrieval (ArcRift cherry-pick #1)

Qué es

HyDE (Hypothetical Document Embeddings) es una técnica de retrieval que, en vez de embeber la pregunta del usuario directamente, genera un pasaje hipotético que la respondería — redactado como si fuera un fragmento de la documentación — y embebe ese pasaje. El vector resultante cae más cerca de los chunks relevantes en el espacio BGE-M3, mejorando el recall.

Ventaja principal

Costo


Arquitectura

Flujo de query

  1. Pregunta del usuario → buildQueryVec(env, question, { hyde: true })
  2. buildQueryVec llama a generateHyDE(apiKey, question) si hyde=true
  3. generateHyDE usa Gemma con responseSchema (JSON limpio, descarta scratchpad CoT) para generar 2-4 frases de pasaje hipotético
  4. Si generateHyDE falla → fallback a embedding normal de la pregunta (degradation path)
  5. El vector resultado se usa en searchChunks y retrieve como siempre

Lugar de integración

Evaluación

El harness bib_eval_retrieval se amplia con variantes:

La métrica overlap_vs_baseline (proporción de chunks en común con baseline) se generaliza para todas las variantes.


Decisiones de diseño

¿Por qué responseSchema en HyDE?

Gemma 4 tiende a generar CoT (chain-of-thought) scratchpad antes de la respuesta. El responseSchema fuerza una salida JSON limpia y descarta el scratchpad automáticamente, evitando el “footgun s52” (concatenar scratchpad confunde el vector). Mismo patrón que en synthesizeAnswer.

¿Por qué concatenación y no solo pasaje?

¿Por qué OFF por defecto?

Latencia sensible en Help Widget (cliente en navegador). El toggle (RETRIEVAL_HYDE=1) permite A/B testing en stage antes de rollout.


Implementación

generateHyDE(apiKey, question): Promise<string>

Ubicación: functions/api/mcp/handlers/archivo-core.ts, línea 641

Parámetros:

Proceso:

  1. Detecta idioma (ES o EN)
  2. Genera prompt bilingüe pidiendo pasaje hipotético (2-4 frases, concreto, sin disclaimers)
  3. Llama a Gemma (SYNTHESIS_MODEL) con responseSchema para forzar JSON
  4. Timeout: 15s
  5. Parsea JSON; si falla, retorna texto crudo; si está vacío, retorna cadena vacía

Salida: string de pasaje (o vacío si falla)

buildQueryVec(env, question, opts): Promise<{vec, hyde?}>

Ubicación: functions/api/mcp/handlers/archivo-core.ts, línea 694

Parámetros:

Lógica:

  1. Si opts.hyde=true y hay API key:
    • Llama a generateHyDE(apiKey, question)
    • Si éxito y pasaje no vacío: embebe "${question}\n\n${hyp}" → retorna {vec, hyde: hyp}
    • Si falla: catch silencioso, fallback a paso 2
  2. Caso por defecto (sin HyDE o fallo): embebe solo la pregunta → retorna {vec}

Salida: {vec: number[], hyde?: string}

Flag RETRIEVAL_HYDE

Ubicación: functions/types.ts, línea 27

Tipo: RETRIEVAL_HYDE?: string

Comportamiento:


Testing y validación

Antes de merge

✅ tsc --noEmit pasa

Post-merge (harness)

bib_eval_retrieval({
  variants: ["baseline", "hyde", "hyde+trim"],
  top_k: 5,
  trim_threshold: 0.38
})

Métricas a recopilar:

Criterio de activación

Si overlap_hyde > baseline + 5% Y latencia acceptable → considerar activar en Oráculo (backend menos sensible a +1-2s que Help Widget).


Véase también

Subir