Startseite / Artikel / Praktische Hinweise: 5 Techniken zur Neubewertung in RAG – von schneller Suche bis zu präziser Ergebnisbereitstellung

Praktische Hinweise: 5 Techniken zur Neubewertung in RAG – von schneller Suche bis zu präziser Ergebnisbereitstellung

Schritt-für-Schritt-Anleitung zu den Praktischen Hinweisen: 5 Techniken zur Neubewertung in RAG – von schneller Suche bis zu präzisen Ergebnissen: Verträge, Überprüfungen sowie Code-Blöcke für Teams, die dieses Muster einsetzen.

2586 Wörter

Dieser Leitfaden zeigt den Weg von Rohstoffen bis zu einem funktionsfähigen System für: 5 Reranking-Techniken in RAG: Von schneller Abrufung bis zu präzisem Kontext. Der Schwerpunkt liegt auf umsetzbaren Schritten, expliziten Überprüfungen sowie Code, den Sie ohne Rätseln über die Absicht direkt in ein Repository einfügen können. In der Übersichtsphase sollten Sie die Eingaben, den Verantwortlichen für den Schritt sowie die Abbruchkriterien definieren, bevor Sie Code ändern. Die Operator sollten in der Lage sein, den Schritt von einem bekannten Checkpoint aus erneut auszuführen, ohne auf versteckte Zustände schließen zu müssen. Erhalten Sie neben den funktionalen Ergebnissen auch Aufzeichnungen der Laufzeiten sowie der Kosten für Tokens oder Abfragen. Eine frühzeitige Sichtbarkeit der Kosten verhindert überraschende Rechnungen, wenn der Prozess von einer Demo in gemeinsam genutzte Umgebungen übergeht.

Das Abruf-Bottleneck, über das niemand spricht

Wenn Sie die Phase „The Retrieval Bottleneck Nobody“ durcharbeiten, notieren Sie zunächst den Vertrag: erforderliche Eingaben, Erfolgsignal sowie das Vorgehen bei teilweisen Fehlern. Diese Checkliste sorgt dafür, dass spätere Codeänderungen transparent bleiben. Bewahren Sie die Konfiguration außerhalb des Anwendungscode auf. Umgebungsdateien, Geheimdatenspeicher und Feature-Flags sollten an einem Ort gesammelt sein, den Betreiber ohne das Durchlesen des gesamten Systems überprüfen können. Messen Sie die Recall-Rate anhand eines festgelegten Fragebogens, bevor Sie die Prompts anpassen. Eine häufige Anpassung der Prompts behebt selten ein schwaches Retrieval-System.

Was ist Reranking?

Beim Bearbeiten der Phase „Was ist Reranking?“ sollten Sie zunächst den Vertrag aufschreiben: erforderliche Eingaben, Erfolgsindikator sowie das Vorgehen bei teilweisen Fehlern. Diese Checkliste sorgt dafür, dass spätere Codeänderungen transparent bleiben. Dokumentieren Sie gemeinsam den erfolgreichen Ablauf sowie den Wiederherstellungsprozess. Wiederholte Versuche, menschliche Überprüfungen und die Handhabung von Fehlern gehören zum Produkt selbst, nicht zu späteren Optimierungen. Messen Sie die Trefferquote anhand eines festgelegten Fragekatalogs, bevor Sie die Anfragenanweisungen anpassen – eine häufige Änderung dieser Anweisungen behebt in der Regel nicht ein schwaches Suchsystem.

Suchen vs. Reranking

Beim Arbeiten in der Phase „Retrieval vs Reranking“ sollte man zunächst den Vertrag festhalten: erforderliche Eingaben, Erfolgszeichen sowie das Vorgehen bei teilweisen Fehlern. Diese Checkliste sorgt dafür, dass spätere Codeänderungen transparent bleiben. Man sollte kleine, testbare Einheiten vor umfangreichen Skripten bevorzugen. Wenn ein Schritt fehlschlägt, sollte der Fehler auf eine einzige Verantwortung verweisen und nicht auf ein verworrenes Ablaufschema. Messen Sie die Trefferquote anhand eines festgelegten Fragekatalogs, bevor Sie die Anfragen anpassen. Häufige Änderungen der Anfragen beheben selten ein schwaches Retrieval-System. Beim Arbeiten in der Phase „Retrieval vs Reranking“ sollte man zunächst den Vertrag festhalten: erforderliche Eingaben, Erfolgszeichen sowie das Vorgehen bei teilweisen Fehlern. Diese Checkliste sorgt dafür, dass spätere Codeänderungen transparent bleiben. Notieren Sie die Laufzeiten sowie die Kosten pro Token oder Abfrage neben den funktionalen Ergebnissen. Eine frühzeitige Sichtbarkeit der Kosten verhindert überraschende Rechnungen, wenn der Prozess von einer Demo-Umgebung in gemeinsam genutzte Umgebungen übergeht.

| Aspect              | Initial Retrieval        | Reranking                     |
| ------------------- | ------------------------ | ----------------------------- |
| Goal                | Find candidates fast     | Judge true relevance          |
| Speed               | Milliseconds             | Tens to hundreds of milliseconds |
| Input               | Query + index            | Query + top-k candidates      |
| Scoring depth       | Shallow (embedding dot product) | Deep (cross-attention, token interaction) |
| Cost                | Low (local compute)      | Higher (model inference)      |
| When to use         | Every query              | On top-k candidates only      |

Die fünf Techniken zur Neubewertung

Die Phase der fünf Techniken zur Neubewertung funktioniert am besten, wenn sie als messbare Struktur betrachtet wird. Erfassen Sie ein gelungenes Beispiel, einen Fehlerfall sowie die Notizen zur Rücksetzung, bevor Sie den Umfang erweitern. Bewahren Sie die Konfiguration außerhalb des Anwendungscode auf. Umgebungsdateien, Geheimdatenspeicher sowie Feature-Flags sollten an einem Ort gesammelt sein, den Betreuer ohne Durchsicht des gesamten Systems prüfen können. Trennen Sie die Strategie zur Aufteilung in Blöcke von der Strategie zur Abfrage. Ein Änderungs an einer sollte nicht dazu führen, dass die andere neu geschrieben werden muss, wenn sich die Qualitätsmetriken ändern.

1. Cross-Encoder Neubewertung

Die 1. Cross-Encoder-Reranking-Ebene funktioniert am besten, wenn sie als messbare Größe betrachtet wird. Erfassen Sie vor der Erweiterung des Umfangs ein erfolgreiches Beispiel, einen Fehlerfall sowie die Notizen zur Rücksetzung. Dokumentieren Sie gemeinsam den erfolgreichen Ablauf sowie den Notfallweg. Wiederholungsversuche, menschliche Überprüfungen und die Handhabung von Fehlern gehören zum Produkt selbst, nicht zu späteren Optimierungen. Trennen Sie die Chunking-Strategie von der Retrieval-Strategie – ein Änderung in einer sollte nicht dazu führen, dass die andere neu geschrieben werden muss, wenn sich die Qualitätsmetriken ändern.

from sentence_transformers import CrossEncoder

# Load a cross-encoder reranker
# ms-marco-MiniLM-L-6-v2 is fast and accurate for general use
cross_encoder = CrossEncoder("cross-encoder/ms-marco-MiniLM-L-6-v2")

def rerank_with_cross_encoder(query: str, retrieved_docs: list[str], top_k: int = 5):
    """
    Rerank retrieved documents using a cross-encoder.

    Args:
        query: The user question
        retrieved_docs: List of document chunks from initial retrieval
        top_k: Number of documents to return after reranking

    Returns:
        List of (document, score) tuples, sorted by relevance
    """
    # Create query-document pairs
    pairs = [[query, doc] for doc in retrieved_docs]

    # Get relevance scores
    scores = cross_encoder.predict(pairs)

    # Combine docs with scores and sort
    scored_docs = list(zip(retrieved_docs, scores))
    scored_docs.sort(key=lambda x: x[1], reverse=True)

    return scored_docs[:top_k]

# Example usage
query = "What are the side effects of amoxicillin?"
retrieved = [
    "Amoxicillin is a penicillin antibiotic used to treat bacterial infections.",
    "Common side effects include nausea, vomiting, and diarrhea.",
    "The drug was first discovered in 1958 by researchers at Beecham.",
    "Patients with penicillin allergies should avoid amoxicillin.",
    "Side effects may include rash, itching, and in rare cases, anaphylaxis.",
]

top_docs = rerank_with_cross_encoder(query, retrieved, top_k=3)
for doc, score in top_docs:
    print(f"Score: {score:.4f} | {doc}")

2. Reciprocal Rank Fusion (RRF)

Die Stufe der 2-fachen gegenseitigen Rangfusionsverarbeitung funktioniert am besten, wenn sie als messbare Ebene betrachtet wird. Erfassen Sie vor der Erweiterung des Umfangs ein „goldenes“ Transkript, einen Fehlerfall sowie eine Notiz zur Rücksetzung. Ziehen Sie kleine, testbare Einheiten vor umfangreichen Skripten vor. Wenn ein Schritt fehlschlägt, sollte der Fehler auf eine einzige Verantwortung verweisen und nicht auf ein verworrenes Ablaufverfahren. Trennen Sie die Strategie zur Aufteilung in Blöcke von der Strategie zum Abrufen. Eine Änderung sollte nicht dazu führen, dass die andere neu geschrieben werden muss, wenn sich die Qualitätsmetriken ändern. Die Stufe der 2-fachen gegenseitigen Rangfusionsverarbeitung funktioniert am besten, wenn sie als messbare Ebene betrachtet wird. Erfassen Sie vor der Erweiterung des Umfangs ein „goldenes“ Transkript, einen Fehlerfall sowie eine Notiz zur Rücksetzung. Erhalten Sie neben den funktionalen Ergebnissen auch Aufzeichnungen zu Zeiten sowie Kosten pro Token oder Abfrage. Eine frühzeitige Sichtbarkeit der Kosten verhindert überraschende Rechnungen, wenn der Prozess von einer Demo in gemeinsame Umgebungen übergeht.

def reciprocal_rank_fusion(rankings: list[list[str]], k: int = 60) -> list[tuple[str, float]]:
    """
    Merge multiple document rankings using Reciprocal Rank Fusion.

    Args:
        rankings: List of rankings, where each ranking is a list of document IDs
                  ordered from most to least relevant
        k: RRF constant (default 60, as recommended in the original paper)

    Returns:
        List of (document_id, rrf_score) tuples, sorted by fused score
    """
    scores = {}

    for ranking in rankings:
        for rank, doc_id in enumerate(ranking, start=1):
            if doc_id not in scores:
                scores[doc_id] = 0.0
            # RRF formula: 1 / (k + rank)
            scores[doc_id] += 1.0 / (k + rank)

    # Sort by score descending
    return sorted(scores.items(), key=lambda x: x[1], reverse=True)

# Example: merging BM25 and vector search results
bm25_results = ["doc_5", "doc_2", "doc_8", "doc_1", "doc_9"]
vector_results = ["doc_1", "doc_5", "doc_3", "doc_8", "doc_7"]

fused = reciprocal_rank_fusion([bm25_results, vector_results])

print("Fused ranking:")
for doc_id, score in fused:
    print(f"  {doc_id}: {score:.4f}")

# Notice: doc_5 and doc_1 appear in both retrievers and get boosted to the top

3. Cohere Rerank API

Für die 3. Phase der Cohere Rerank API sollten Eingaben, Verantwortliche für die jeweiligen Schritte sowie Abbruchkriterien vor dem Ändern des Codes definiert werden. Die Operator sollten in der Lage sein, den Schritt von einem bekannten Checkpoint aus erneut auszuführen, ohne auf versteckte Zustände schließen zu müssen. Die Konfiguration sollte außerhalb des Anwendungscode gespeichert werden. Umgebungsdateien, Geheimdatenspeicher sowie Feature-Flags sollten an einem Ort zusammengefasst sein, den die Operator überprüfen können, ohne den gesamten Codeverlauf durchlesen zu müssen. Zitieren Sie die Passagen, auf denen die Antwort tatsächlich beruht. Ohne Zitate können die Operator nicht zwischen Halluzinationen und Lücken im Indexing unterscheiden.

import cohere
from dotenv import load_dotenv
import os

load_dotenv()

# Initialize Cohere client
co = cohere.Client(os.getenv("COHERE_API_KEY"))

def rerank_with_cohere(query: str, documents: list[str], top_k: int = 5):
    """
    Rerank documents using Cohere's managed Rerank API.

    Args:
        query: The user question
        documents: List of document chunks from initial retrieval
        top_k: Number of documents to return

    Returns:
        List of (document, relevance_score) tuples
    """
    response = co.rerank(
        model="rerank-v3.5",
        query=query,
        documents=documents,
        top_n=top_k,
        return_documents=True
    )

    results = []
    for result in response.results:
        results.append((
            result.document.text,
            result.relevance_score
        ))

    return results

# Example usage
query = "How do I handle authentication in a FastAPI app?"
docs = [
    "FastAPI is a modern web framework for building APIs with Python.",
    "To add authentication, use OAuth2PasswordBearer and JWT tokens.",
    "Pydantic models in FastAPI provide automatic request validation.",
    "The OAuth2PasswordBearer class expects a token URL endpoint.",
    "FastAPI was created by Sebastián Ramírez and released in 2018.",
]

ranked = rerank_with_cohere(query, docs, top_k=3)
for doc, score in ranked:
    print(f"Score: {score:.4f} | {doc}")

4. ColBERT

Für die 4. ColBERT-Phase sollten vor dem Ändern des Codes die Eingaben, der Verantwortliche für den Schritt sowie die Abbruchkriterien definiert werden. Die Operator sollten in der Lage sein, den Schritt von einem bekannten Checkpoint aus erneut auszuführen, ohne auf versteckte Zustände schließen zu müssen. Dokumentieren Sie sowohl den erfolgreichen Ablauf als auch den Notfallweg gemeinsam. Wiederholungsversuche, menschliche Überprüfungen sowie die Handhabung von Fehlern gehören zum Produkt selbst und nicht zu späteren Optimierungen. Zitieren Sie die Passagen, die tatsächlich die Antwort untermauern – ohne Zitate können die Operator keine Halluzinationen von Lücken in der Indizierung unterscheiden.

from colbert import Searcher
from colbert.infra import Run, RunConfig

def setup_colbert_searcher(index_path: str, checkpoint: str):
    """
    Initialize a ColBERT searcher for late-interaction reranking.

    Args:
        index_path: Path to the pre-built ColBERT index
        checkpoint: Path to the ColBERT model checkpoint

    Returns:
        Configured Searcher instance
    """
    with Run().context(RunConfig(nranks=1, experiment="reranking")):
        searcher = Searcher(
            index=index_path,
            checkpoint=checkpoint
        )
    return searcher

def rerank_with_colbert(searcher, query: str, doc_ids: list[str], top_k: int = 5):
    """
    Rerank documents using ColBERT's late interaction.

    Args:
        searcher: Initialized ColBERT Searcher
        query: The user question
        doc_ids: List of document IDs from initial retrieval
        top_k: Number of documents to return

    Returns:
        List of (doc_id, score) tuples
    """
    # Search within the candidate set
    results = searcher.search(
        query,
        k=top_k,
        filter_fn=lambda pid: pid in doc_ids  # Only rerank candidates
    )

    return list(zip(results[0], results[2]))  # doc_ids, scores

# Note: ColBERT requires a pre-built index and model checkpoint.
# For production use, build the index once and load it at startup.

5. LLM-as-a-Judge

Zur Phase „5 LLM-as-a-Judge“ sollten die Eingaben, der Verantwortliche für den Schritt sowie die Abbruchkriterien vor dem Ändern des Codes definiert werden. Die Operator sollten in der Lage sein, den Schritt von einem bekannten Checkpoint aus erneut auszuführen, ohne auf versteckte Zustände schließen zu müssen. Bevorzugen Sie kleine, testbare Einheiten statt umfangreicher Skripte. Wenn ein Schritt fehlschlägt, sollte der Fehler auf eine einzige Verantwortung verweisen und nicht auf ein verworrenes Pipeline-System. Wählen Sie bei dem nächsten Schritt, der aus Code oder einem Toolaufruf besteht, strukturierte Ausgaben mit Schema-Validierung statt freier Prosa. Zur Phase „5 LLM-as-a-Judge“ sollten die Eingaben, der Verantwortliche für den Schritt sowie die Abbruchkriterien vor dem Ändern des Codes definiert werden. Die Operator sollten in der Lage sein, den Schritt von einem bekannten Checkpoint aus erneut auszuführen, ohne auf versteckte Zustände schließen zu müssen. Erhalten Sie neben den funktionalen Ergebnissen auch Aufzeichnungen der Laufzeiten sowie der Kosten für Tokens oder Abfragen. Eine frühzeitige Sichtbarkeit der Kosten verhindert überraschende Rechnungen, wenn der Ablauf von einer Demo in gemeinsame Umgebungen übergeht.

You are evaluating documents for a retrieval system.

Query: {query}
Document: {document}

Rate how relevant this document is for answering the query.
Respond with a single integer from 1 to 10, where 10 means perfectly relevant.

Relevance score:
from openai import OpenAI
import os
from dotenv import load_dotenv

load_dotenv()
client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))

def score_document_with_llm(query: str, document: str) -> int:
    """
    Ask an LLM to score a document's relevance to a query.

    Args:
        query: The user question
        document: A candidate document chunk

    Returns:
        Integer relevance score from 1-10
    """
    prompt = f"""You are evaluating documents for a retrieval system.

Query: {query}
Document: {document}

Rate how relevant this document is for answering the query.
Respond with a single integer from 1 to 10, where 10 means perfectly relevant.
Be strict: only give high scores to documents that directly help answer the query.

Relevance score:"""

    response = client.chat.completions.create(
        model="gpt-4.1-mini",
        messages=[{"role": "user", "content": prompt}],
        temperature=0,
        max_tokens=5
    )

    try:
        score = int(response.choices[0].message.content.strip())
        return max(1, min(10, score))  # Clamp to 1-10
    except ValueError:
        return 5  # Default on parse failure

def rerank_with_llm_judge(query: str, documents: list[str], top_k: int = 3):
    """
    Rerank documents using an LLM as a relevance judge.

    Args:
        query: The user question
        documents: List of candidate document chunks
        top_k: Number of documents to return

    Returns:
        List of (document, score) tuples, sorted by relevance
    """
    scored = []
    for doc in documents:
        score = score_document_with_llm(query, doc)
        scored.append((doc, score))

    scored.sort(key=lambda x: x[1], reverse=True)
    return scored[:top_k]

# Example usage
query = "What are the tax implications of RSU vesting for employees in California?"
docs = [
    "RSUs are restricted stock units granted to employees as part of compensation.",
    "In California, RSU income is taxed as ordinary income at vesting, not at grant.",
    "Employers typically withhold federal and state taxes at vesting time.",
    "Stock options and RSUs have different tax treatments under IRS rules.",
    "California has one of the highest state income tax rates in the US.",
]

ranked = rerank_with_llm_judge(query, docs, top_k=3)
for doc, score in ranked:
    print(f"Score: {score}/10 | {doc}")

Welchen sollten Sie verwenden?

Beim Bearbeiten der Phase „Welchen sollten Sie verwenden?“ sollten Sie zunächst den Vertrag aufschreiben: erforderliche Eingaben, Erfolgsindikatoren sowie das Vorgehen bei teilweisen Fehlern. Diese Checkliste sorgt dafür, dass spätere Codeänderungen transparent bleiben. Bewahren Sie die Konfiguration außerhalb des Anwendungscode auf. Umgebungsdateien, Geheimdatenspeicher und Feature-Flags sollten an einem Ort gesammelt sein, den Betreiber überprüfen können, ohne den gesamten Code durchzulesen. Messen Sie die Trefferquote anhand einer festgelegten Fragestellung, bevor Sie die Anfragen anpassen. Eine Änderung der Anfragen behebt selten ein schwaches Abrufverhalten.

| Technique             | Best For                                          | Latency      | Cost           |
| --------------------- | ------------------------------------------------- | ------------ | -------------- |
| Cross-Encoder         | Maximum quality on top-k candidates               | 50-200ms     | Local GPU/CPU  |
| RRF                   | Hybrid retrieval without adding model inference   | ~0ms         | Free           |
| Cohere Rerank API     | Speed without operational overhead                | 100-300ms    | Per API call   |
| ColBERT               | Large-scale, low-latency use cases                | 20-100ms     | Index + GPU    |
| LLM-as-a-Judge        | Complex, high-value queries (medical, legal)      | 1-5 seconds  | Per API call   |

Fazit

Während der Phase der abschließenden Überlegungen sollte man zunächst den Vertrag aufschreiben: die erforderlichen Eingaben, das Erfolgszeichen sowie das Vorgehen bei teilweisen Fehlern. Diese Checkliste sorgt dafür, dass spätere Codeänderungen transparent bleiben. Dokumentieren Sie sowohl den erfolgreichen Ablauf als auch den Notfallplan gemeinsam. Wiederholte Versuche, menschliche Überprüfungen sowie die Handhabung von Fehlern gehören zum Produkt selbst und nicht zu späteren Optimierungen. Messen Sie die Trefferquote anhand eines festgelegten Fragebogens, bevor Sie die Anfragenanweisungen anpassen – eine häufige Änderung dieser Anweisungen behebt in der Regel nicht ein schwaches Suchsystem.

Operative Checkliste

Die Phase der operativen Checkliste funktioniert am besten, wenn sie als messbarer Prozess betrachtet wird. Erfassen Sie vor der Erweiterung des Umfangs ein Beispiel für einen erfolgreichen Ablauf, einen Fehlfall sowie eine Notiz zur Rücksetzung. Betrachten Sie diese Phase als Vertrag zwischen den Eingaben und den validierten Ausgaben. Benennen Sie die relevanten Dokumente, definieren Sie Erfolgskriterien und lehnen Sie stille, teilweise abgeschlossene Abläufe ab.

Trennen Sie die Strategie zur Aufteilung in Blöcke von der Strategie zum Abrufen. Ein Änderungsantrag an einer Seite sollte nicht dazu führen, dass die andere neu geschrieben werden muss, wenn sich die Qualitätsmetriken ändern.

Bewerten Sie Antworten in einer einzigen Interaktion sowie mehrstufige Abläufe getrennt voneinander. Die Aggregation der Chat-Bewertungen überdeckt Fehler im Tool-Loop-Prozess.

Schreiben Sie ein kurzes Handbuch: Wie man Schlüssel rotiert, wie man die Warteschlange leert und wie man den letzten Eingang rückgängig macht.

Dokumentieren Sie sowohl den erfolgreichen Ablauf als auch den Notfallplan gemeinsam. Wiederholte Versuche, menschliche Überprüfungen sowie die Handhabung von Fehlern gehören zum Produkt selbst und nicht zu späteren Optimierungen.

Vor der Einführung des gesamten Systems sollten Sie Versionen einfrieren, ein „goldenes Transkript“ für den kritischen Ablauf erstellen und die Schritte zum Rückschalten überprüfen. Gemeinsam genutzte Umgebungen benötigen Rate Limits, Überprüfungen der Nutzerrechte sowie einen klaren Verantwortlichen für die Rotation von Geheimnissen. Wählen Sie langweilige Zuverlässigkeit statt cleverer, einmaliger Demonstrationen.

Batch-Hinweis für 16f80a919c4e: Halten Sie die Anbieter-Schlüssel außerhalb des Repositories, legen Sie eine Obergrenze für Tokens pro Sitzung fest und speichern Sie die Transkripte neben den Evaluierungs-Dateien, damit spätere Modellwechsel vergleichbar bleiben.