Intermediate6 min read8 of 40

HyDE - Hypothetical Document Embeddings

Generate hypothetical ideal answers, embed them, and use those embeddings to find better source documents. Improves retrieval for complex queries.

Read first:Simple RAG

Overview

HyDE (Hypothetical Document Embeddings) flips traditional RAG: instead of embedding the query, generate a hypothetical ideal answer, embed that, and use it to find similar documents. This bridges the semantic gap between short queries and long documents.

Pattern #5 in the 37 RAG Patterns Collection

The Problem

Query: "How does attention mechanism work?" → Embedding matches poorly with detailed technical docs HyDE Solution: Query → Generate hypothetical answer → Embed answer → Find similar docs

Architecture

graph TB
    A[User Query] --> B[LLM: Generate Hypothetical Answer]
    B --> C[Embed Hypothetical Answer]
    C --> D[Vector Search]
    D --> E[Retrieve Similar Docs]
    E --> F[LLM: Generate Final Answer]
    F --> G[Response]
    
    H[Vector DB] --> D
    
    style A fill:#f9f,stroke:#333
    style B fill:#ff9,stroke:#333
    style F fill:#9f9,stroke:#333

Why It Works

Query vs Document Mismatch

  • Query: "What is RAG?"
  • Document: "Retrieval-Augmented Generation (RAG) combines retrieval systems with large language models to provide..."

Queries are short, documents are detailed. Embeddings don't align well.

HyDE Solution

  1. Generate hypothetical answer (document-like)
  2. Embed the hypothetical answer
  3. Find documents semantically similar to the answer
  4. Use real documents to generate final response

Implementation

Step 1: Generate Hypothetical Document

python
def generate_hypothetical_answer(query):
    """Generate a hypothetical ideal answer"""
    prompt = f"""Write a detailed, technical answer to this question:

{query}

Be specific and comprehensive."""

    response = bedrock.invoke_model(
        modelId="meta.llama3-70b-instruct-v1:0",
        body=json.dumps({
            "prompt": prompt,
            "max_gen_len": 512,
            "temperature": 0.7
        })
    )
    
    return parse_response(response)

Step 2: Embed and Search

python
def hyde_retrieval(query, vector_store):
    # Generate hypothetical answer
    hypothetical = generate_hypothetical_answer(query)
    
    # Embed the hypothetical answer
    embedding = get_embedding(hypothetical)
    
    # Search with hypothetical embedding
    results = vector_store.search(
        embedding=embedding,
        top_k=5
    )
    
    return results

Step 3: Generate Final Answer

python
def hyde_rag(query):
    # Retrieve using HyDE
    docs = hyde_retrieval(query, vector_store)
    
    # Create context from real documents
    context = "\n\n".join([doc['content'] for doc in docs])
    
    # Generate final answer with real context
    response = bedrock.invoke_model(
        modelId="meta.llama3-70b-instruct-v1:0",
        body=json.dumps({
            "prompt": f"""Context: {context}

Question: {query}

Answer based on the context provided."""
        })
    )
    
    return response

Complete Notebook

🚀 Run the full implementation:

📓 HyDE AWS Notebook

Includes:

  • Complete HyDE pipeline
  • Prompt engineering for hypothetical generation
  • Comparison with standard RAG
  • Performance benchmarks
  • Cost analysis

Performance

MetricHyDEStandard RAG
Accuracy85%72%
Latency~600ms~300ms
Cost/query$0.15$0.08
Best forComplex queriesSimple Q&A

When to Use

Best For

  • Complex, technical queries requiring domain expertise
  • Ambiguous questions needing interpretation
  • Research applications where precision matters
  • Domain-specific search (medical, legal, scientific)

Avoid When

  • Simple factual queries (unnecessary overhead)
  • Real-time requirements (adds LLM generation latency)
  • Budget constraints (2x LLM calls per query)

Optimization Tips

1. Cache Hypothetical Answers

python
import hashlib

cache = {}

def hyde_with_cache(query):
    query_hash = hashlib.md5(query.encode()).hexdigest()
    
    if query_hash not in cache:
        cache[query_hash] = generate_hypothetical_answer(query)
    
    return cache[query_hash]

2. Multi-Hypothetical HyDE

python
def multi_hyde(query, n=3):
    """Generate multiple hypothetical answers for diversity"""
    hypotheticals = [
        generate_hypothetical_answer(query)
        for _ in range(n)
    ]
    
    # Search with all hypotheticals
    all_results = []
    for hyp in hypotheticals:
        results = vector_store.search(get_embedding(hyp))
        all_results.extend(results)
    
    # Deduplicate and rank
    return deduplicate_and_rank(all_results)

3. Hybrid: HyDE + Direct Query

python
def hybrid_hyde(query):
    # Get results from both methods
    hyde_results = hyde_retrieval(query)
    direct_results = vector_store.search(get_embedding(query))
    
    # Combine with fusion
    combined = reciprocal_rank_fusion([hyde_results, direct_results])
    return combined

Comparison

ApproachProsCons
Standard RAGFast, cheapPoor for complex queries
HyDEBetter accuracySlower, more expensive
Hybrid HyDEBalancedMore complex

Related Papers

Next Steps

  1. Try it: Run the HyDE notebook
  2. Combine: Use with Reranking (#4) for best results
  3. Optimize: Add Multi-Query (#9) for diversity
  4. Compare: Benchmark against your baseline

Part of: 37 RAG Patterns Collection
See also: Visual Architecture Guide

Go Deeper With Live Instruction

Covered in depth in our llm engineering program.