Las canalizaciones de RAG fallan silenciosamente cuando el almacén de vectores no contiene documentos relevantes: el LLM recibe un contexto deficiente y genera una respuesta que suena plausible pero incorrecta. Una alternativa de búsqueda en vivo detecta estas fallas verificando la confianza de la recuperación y dirigiendo a la búsqueda web cuando el almacén de vectores se queda corto. Este tutorial agrega una capa alternativa a cualquier canal RAG existente que detecta recuperación de baja calidad y cambia de forma transparente a datos SERP en vivo. El respaldo se activa solo cuando es necesario, manteniendo los costos mínimos en $0,005 por llamada de búsqueda.
Requisitos previos
- Python 3.9+ instalado
- Una tubería RAG existente con un almacén de vectores
- solicita biblioteca instalada
- Una clave API de Scavio de scavio.dev
Guia paso a paso
Paso 1: Construir la función de puntuación de confianza
Califique qué tan bien los resultados de su recuperación de vectores coinciden con la consulta. Las puntuaciones bajas desencadenan el retroceso de la búsqueda. Utilice puntuaciones de similitud de su tienda de vectores o una heurística simple.
def score_retrieval_quality(query: str, documents: list, scores: list = None) -> float:
"""Score retrieval quality from 0 (terrible) to 1 (excellent)."""
if not documents:
return 0.0
# If vector store provides similarity scores, use them
if scores:
avg_score = sum(scores) / len(scores)
return min(avg_score, 1.0)
# Heuristic: check keyword overlap between query and docs
query_words = set(query.lower().split())
total_overlap = 0
for doc in documents:
doc_words = set(doc.lower().split()[:200]) # first 200 words
overlap = len(query_words & doc_words) / max(len(query_words), 1)
total_overlap += overlap
avg_overlap = total_overlap / len(documents)
return min(avg_overlap, 1.0)
# Example:
score = score_retrieval_quality(
'latest python version 2026',
['Python 3.12 was released in October 2023 with improved performance.']
)
print(f'Retrieval confidence: {score:.2f}') # Low because doc is outdatedPaso 2: Construya la función alternativa de búsqueda
Cuando la confianza de recuperación esté por debajo de un umbral, obtenga resultados de búsqueda en vivo y formatéelos como documentos para el contexto LLM.
import requests, os
API_KEY = os.environ['SCAVIO_API_KEY']
def search_fallback(query: str, k: int = 5) -> list:
"""Fetch live search results as fallback documents."""
resp = requests.post('https://api.scavio.dev/api/v1/search',
headers={'x-api-key': API_KEY, 'Content-Type': 'application/json'},
json={'query': query, 'country_code': 'us'})
resp.raise_for_status()
results = resp.json().get('organic_results', [])[:k]
return [{
'content': f'{r["title"]}\n{r.get("snippet", "")}',
'source': r['link'],
'retriever': 'live_search'
} for r in results]
# Test:
fallback_docs = search_fallback('latest python version 2026')
for doc in fallback_docs[:2]:
print(f'[{doc["retriever"]}] {doc["content"][:80]}...')Paso 3: Cree la función de recuperación con reconocimiento de respaldo
Envuelva su recuperación de vectores existente con la verificación de confianza y la lógica alternativa. Esta es la única función que necesita cambiar en su canalización.
CONFIDENCE_THRESHOLD = 0.3 # below this, trigger fallback
def retrieve_with_fallback(query: str, vector_store, k: int = 5) -> dict:
"""Retrieve from vector store; fall back to search if confidence is low."""
# Step 1: Try vector retrieval
vector_results = vector_store.similarity_search_with_score(query, k=k)
docs = [doc.page_content for doc, score in vector_results]
scores = [score for doc, score in vector_results]
confidence = score_retrieval_quality(query, docs, scores)
# Step 2: Decide retrieval strategy
if confidence >= CONFIDENCE_THRESHOLD and docs:
return {
'documents': [{'content': d, 'retriever': 'vector'} for d in docs],
'strategy': 'vector',
'confidence': round(confidence, 3),
'search_cost': 0
}
# Step 3: Fallback to live search
search_docs = search_fallback(query, k=k)
return {
'documents': search_docs + [{'content': d, 'retriever': 'vector'} for d in docs[:2]],
'strategy': 'search_fallback',
'confidence': round(confidence, 3),
'search_cost': 0.005
}Paso 4: Intégrelo en su cadena RAG existente
Reemplace su paso de recuperación actual con la versión alternativa. El resto de su proceso (construcción rápida, llamada LLM, análisis de resultados) permanece igual.
def rag_with_fallback(query: str, vector_store, llm) -> dict:
# Retrieve with fallback
retrieval = retrieve_with_fallback(query, vector_store)
documents = retrieval['documents']
# Build context
context = '\n\n'.join(d['content'] for d in documents)
sources = [d.get('source', 'vector store') for d in documents if d.get('source')]
# Generate answer
prompt = f"""Answer based on the following context. If using web results, cite the URLs.
Context:
{context}
Question: {query}
Answer:"""
# Assuming llm is a callable that returns text
answer = llm(prompt)
return {
'answer': answer,
'strategy': retrieval['strategy'],
'confidence': retrieval['confidence'],
'sources': sources,
'cost': retrieval['search_cost']
}
# Usage stays the same as before:
# result = rag_with_fallback(user_query, my_vector_store, my_llm)
# print(result['answer'])
# print(f'Strategy: {result["strategy"]}, Cost: ${result["cost"]}')Paso 5: Supervisar las tasas y los costos de respaldo
Realice un seguimiento de la frecuencia con la que se activa el respaldo para comprender las brechas de cobertura de su tienda de vectores y las mejoras del plan.
from collections import defaultdict
fallback_stats = defaultdict(int)
def tracked_rag(query: str, vector_store, llm) -> dict:
result = rag_with_fallback(query, vector_store, llm)
fallback_stats['total'] += 1
fallback_stats[result['strategy']] += 1
fallback_stats['total_cost'] += result['cost']
return result
def print_fallback_report():
total = fallback_stats['total']
if total == 0:
print('No queries tracked yet.')
return
vector_pct = fallback_stats.get('vector', 0) / total * 100
fallback_pct = fallback_stats.get('search_fallback', 0) / total * 100
print(f'RAG Fallback Report:')
print(f' Total queries: {total}')
print(f' Vector retrieval: {vector_pct:.0f}%')
print(f' Search fallback: {fallback_pct:.0f}%')
print(f' Total search cost: ${fallback_stats["total_cost"]:.2f}')
print(f' Avg cost/query: ${fallback_stats["total_cost"] / total:.4f}')
if fallback_pct > 30:
print(f' NOTE: High fallback rate. Consider adding more documents to your vector store.')
# After running many queries:
# print_fallback_report()Ejemplo en Python
import os, requests
API_KEY = os.environ['SCAVIO_API_KEY']
def search_fallback(query, k=5):
resp = requests.post('https://api.scavio.dev/api/v1/search',
headers={'x-api-key': API_KEY, 'Content-Type': 'application/json'},
json={'query': query, 'country_code': 'us'})
return [{'content': f'{r["title"]}\n{r.get("snippet", "")}', 'source': r['link']}
for r in resp.json().get('organic_results', [])[:k]]
def retrieve(query, vector_docs, confidence):
if confidence >= 0.3 and vector_docs:
return {'docs': vector_docs, 'strategy': 'vector', 'cost': 0}
fallback = search_fallback(query)
return {'docs': fallback + vector_docs[:2], 'strategy': 'fallback', 'cost': 0.005}
# Simulate low-confidence retrieval:
result = retrieve('Python 3.14 release date 2026', ['Python 3.12 docs...'], 0.15)
print(f'Strategy: {result["strategy"]}, docs: {len(result["docs"])}, cost: ${result["cost"]}')Ejemplo en JavaScript
const API_KEY = process.env.SCAVIO_API_KEY;
async function searchFallback(query, k = 5) {
const resp = await fetch('https://api.scavio.dev/api/v1/search', {
method: 'POST',
headers: { 'x-api-key': API_KEY, 'Content-Type': 'application/json' },
body: JSON.stringify({ query, country_code: 'us' })
});
const data = await resp.json();
return (data.organic_results || []).slice(0, k)
.map(r => ({ content: `${r.title}\n${r.snippet || ''}`, source: r.link }));
}
async function retrieve(query, vectorDocs, confidence) {
if (confidence >= 0.3 && vectorDocs.length) {
return { docs: vectorDocs, strategy: 'vector', cost: 0 };
}
const fallback = await searchFallback(query);
return { docs: [...fallback, ...vectorDocs.slice(0, 2)], strategy: 'fallback', cost: 0.005 };
}
retrieve('Python 3.14 release 2026', ['old docs'], 0.1)
.then(r => console.log(`Strategy: ${r.strategy}, docs: ${r.docs.length}`));Salida esperada
Retrieval confidence: 0.12
[live_search] Python Release Python 3.14.0 -- Python 3.14.0 was released on...
[live_search] What's New In Python 3.14 -- This article explains the new...
Strategy: search_fallback, docs: 7, cost: $0.005
RAG Fallback Report:
Total queries: 100
Vector retrieval: 72%
Search fallback: 28%
Total search cost: $0.14
Avg cost/query: $0.0014