Resumen
Este pipeline agrega un confiable search fallback layer to OpenWebUI deployments. Cuando el primary SearXNG instance returns empty resultados, times out, o encounters limites de tasa, el pipeline automaticamente falls a traves de to Scavio API for structured Google resultados including AI Overviews. El fallback es transparent to el usuario y activa dentro de 3 segundos of un SearXNG failure. Logs rastrear cual backend served cada consulta for monitoreo SearXNG health sobre time.
Desencadenador
On cada OpenWebUI search solicitud
Programación
On-demand per search solicitud
Pasos del flujo de trabajo
Recibir consulta de busqueda de OpenWebUI
Intercept el search solicitud de OpenWebUI's search toggle o RAG pipeline.
Consulta SearXNG primary backend
Forward el consulta to el local SearXNG instance con un 8-segundo timeout.
Evaluar SearXNG respuesta calidad
Verificar if SearXNG returned at least 3 resultados. Si menos, mark as low-quality y activar fallback.
Fallback to Scavio API
Consulta Scavio con el same search terms, requesting AI Overview datos for richer grounding context.
Format y return resultados
Normalize el respuesta formato y return structured resultados to OpenWebUI con fuente attribution.
Implementacion en Python
import requests
import time
from datetime import datetime
API_KEY = "your_scavio_api_key"
SEARXNG_URL = "http://localhost:8888/search"
MIN_RESULTS = 3
def search_with_fallback(query: str) -> dict:
start = time.time()
source = "searxng"
# Try SearXNG
try:
res = requests.get(
SEARXNG_URL,
params={"q": query, "format": "json"},
timeout=8,
)
res.raise_for_status()
searxng_results = res.json().get("results", [])
if len(searxng_results) >= MIN_RESULTS:
return {
"source": "searxng",
"results": [{"title": r["title"], "link": r["url"], "snippet": r.get("content", "")} for r in searxng_results[:10]],
"latency_ms": int((time.time() - start) * 1000),
}
except Exception:
pass
# Fallback to Scavio
source = "scavio"
res = requests.post(
"https://api.scavio.dev/api/v1/search",
headers={"x-api-key": API_KEY},
json={"platform": "google", "query": query, "ai_overview": True},
timeout=15,
)
res.raise_for_status()
data = res.json()
results = [{"title": r.get("title", ""), "link": r.get("link", ""), "snippet": r.get("snippet", "")} for r in data.get("organic", [])[:10]]
return {
"source": source,
"ai_overview": data.get("ai_overview", {}).get("text", ""),
"results": results,
"latency_ms": int((time.time() - start) * 1000),
}
def run():
queries = ["latest openwebui release 2026", "best self-hosted LLM tools", "searxng vs commercial search api"]
for q in queries:
result = search_with_fallback(q)
print(f" [{result['source']}] {q}: {len(result['results'])} results ({result['latency_ms']}ms)")
if __name__ == "__main__":
run()Implementacion en JavaScript
const API_KEY = "your_scavio_api_key";
async function searchWithFallback(query) {
const start = Date.now();
try {
const res = await fetch(`http://localhost:8888/search?q=${encodeURIComponent(query)}&format=json`, { signal: AbortSignal.timeout(8000) });
const data = await res.json();
if ((data.results ?? []).length >= 3) {
return { source: "searxng", results: data.results.slice(0, 10).map((r) => ({ title: r.title, link: r.url, snippet: r.content ?? "" })), ms: Date.now() - start };
}
} catch {}
const res = await fetch("https://api.scavio.dev/api/v1/search", {
method: "POST",
headers: { "x-api-key": API_KEY, "content-type": "application/json" },
body: JSON.stringify({ platform: "google", query, ai_overview: true }),
});
const data = await res.json();
return { source: "scavio", results: (data.organic ?? []).slice(0, 10).map((r) => ({ title: r.title ?? "", link: r.link ?? "", snippet: r.snippet ?? "" })), ms: Date.now() - start };
}
for (const q of ["latest openwebui release 2026", "best self-hosted LLM tools"]) {
const r = await searchWithFallback(q);
console.log(`[${r.source}] ${q}: ${r.results.length} results (${r.ms}ms)`);
}Plataformas utilizadas
Búsqueda web con grafo de conocimiento, PAA y resúmenes de IA