Resumen
Este pipeline agrega web search grounding to local LLMs (Ollama, vLLM, llama.cpp) con un TTL-based cache layer to reduce API costs. Cuando un usuario asks un question, el pipeline verifica el cache for reciente resultados. Si cached resultados exist dentro de el TTL window (default 1 hora), they son usado sin un llamada un API. Si no, Scavio es queried y resultados son cached. Este hace local LLM search grounding affordable for high-traffic deployments.
Desencadenador
On cada local LLM consulta ese necesita web grounding
Programación
On-demand per local LLM consulta
Pasos del flujo de trabajo
Recibir consulta de local LLM
Accept el user's question y determine if web search grounding es necesario.
Verificar search cache
Look up el consulta in el local cache. Si resultados exist y TTL tiene no expired, return cached datos.
Consulta Scavio on cache miss
Si cache es empty o expired, consulta Scavio API for fresh resultados con AI Overview.
Actualizar cache
Almacenar el fresh resultados in cache con el actual marca de tiempo for TTL calculation.
Format context y return
Format resultados de busqueda as un context block for el local LLM prompt.
Implementacion en Python
import requests
import json
import hashlib
from datetime import datetime, timedelta
from pathlib import Path
API_KEY = "your_scavio_api_key"
CACHE_DIR = Path("search_cache")
CACHE_DIR.mkdir(exist_ok=True)
CACHE_TTL = timedelta(hours=1)
def cache_key(query: str) -> str:
return hashlib.md5(query.lower().strip().encode()).hexdigest()
def get_cached(query: str) -> dict | None:
path = CACHE_DIR / f"{cache_key(query)}.json"
if not path.exists():
return None
data = json.loads(path.read_text())
cached_at = datetime.fromisoformat(data["cached_at"])
if datetime.utcnow() - cached_at > CACHE_TTL:
return None
return data
def search_with_cache(query: str) -> dict:
cached = get_cached(query)
if cached:
return {**cached, "source": "cache"}
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()
result = {
"query": query,
"ai_overview": data.get("ai_overview", {}).get("text", ""),
"results": [{"title": r.get("title", ""), "snippet": r.get("snippet", "")} for r in data.get("organic", [])[:5]],
"cached_at": datetime.utcnow().isoformat(),
}
path = CACHE_DIR / f"{cache_key(query)}.json"
path.write_text(json.dumps(result, indent=2))
return {**result, "source": "api"}
def format_context(search_result: dict) -> str:
parts = []
if search_result.get("ai_overview"):
parts.append(f"AI Overview: {search_result['ai_overview']}")
for r in search_result.get("results", []):
parts.append(f"- {r['title']}: {r['snippet']}")
return "\n".join(parts)
def run():
queries = ["latest ollama version 2026", "best local llm model 2026", "latest ollama version 2026"]
for q in queries:
result = search_with_cache(q)
print(f" [{result['source']}] {q}: {len(result['results'])} results")
if __name__ == "__main__":
run()Implementacion en JavaScript
const API_KEY = "your_scavio_api_key";
const cache = new Map();
const TTL = 3600000; // 1 hour
async function searchCached(query) {
const key = query.toLowerCase().trim();
const cached = cache.get(key);
if (cached && Date.now() - cached.ts < TTL) return { ...cached.data, source: "cache" };
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();
const result = {
query,
aiOverview: data.ai_overview?.text ?? "",
results: (data.organic ?? []).slice(0, 5).map((r) => ({ title: r.title ?? "", snippet: r.snippet ?? "" })),
};
cache.set(key, { data: result, ts: Date.now() });
return { ...result, source: "api" };
}
for (const q of ["latest ollama version 2026", "best local llm 2026", "latest ollama version 2026"]) {
const r = await searchCached(q);
console.log(`[${r.source}] ${q}: ${r.results.length} results`);
}Plataformas utilizadas
Búsqueda web con grafo de conocimiento, PAA y resúmenes de IA