Si tu chat tiene "busqueda web" activada pero el modelo igual se inventa una receta de pastel de chocolate, es que el interruptor no tiene ningun backend seleccionado y no esta haciendo nada. Un LLM solo genera texto. No puede abrir una pagina. La extension de busqueda web de SillyTavern, Open WebUI o LibreChat necesita un backend real (Selenium, una API SERP o visita por URL) elegido en su desplegable. Si ese desplegable esta vacio, el interruptor esta encendido pero ninguna peticion sale de tu maquina, y el modelo rellena el hueco con lo que suene bien. La solucion es apuntarlo a un backend de busqueda real que devuelva resultados que tu inyectas en el prompt.
Requisitos previos
- Un chat funcionando: SillyTavern, Open WebUI o LibreChat
- Una clave de API de Scavio (50 creditos gratis al registrarte, sin tarjeta)
- Python 3.9+ o Node 18+ si conectas la busqueda como herramienta propia
- Saber editar la configuracion de extensiones/herramientas de tu interfaz
Guia paso a paso
Paso 1: Confirma que el desplegable del backend esta puesto
Abre los ajustes de la extension de busqueda web. La extension de SillyTavern tiene un desplegable "Source" (Selenium, SerpApi, Visit by URL, etc.). Open WebUI tiene un selector de motor en Admin > Settings > Web Search. LibreChat lee el proveedor desde su configuracion. Si el selector esta vacio o apunta a un backend que nunca configuraste, el interruptor no hace nada: nunca lanza una peticion y el modelo se inventa la respuesta. Elige una fuente real y dale credenciales antes que nada.
# Symptom of an empty backend: toggle ON, but no outbound request,
# and the model 'answers' from training data instead of live results.
# Check your UI's network log or extension console - if nothing
# is sent when you ask a fresh question, the backend is unset.Paso 2: Consigue una API de busqueda con resultados limpios
Necesitas un backend que convierta una consulta en resultados reales. Una API SERP lo hace en una llamada. El endpoint de Google de Scavio es POST https://api.scavio.dev/api/v1/google, con token Bearer. Devuelve un array de resultados organicos que puedes formatear como contexto. Una llamada a Google cuesta 1 credito por defecto; pon light_request:false (2 creditos) si tambien quieres people-also-ask, knowledge graph y busquedas relacionadas en la misma respuesta.
curl -X POST https://api.scavio.dev/api/v1/google \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"query": "easy chocolate cake recipe"}'Paso 3: Formatea los resultados en un bloque de contexto
Toma las primeras entradas del array results y aplana cada una en titulo, fragmento y enlace. Eso es un bloque de contexto que antepones al turno del usuario. El modelo ahora responde con el texto que le diste, no con su memoria. Manten 3 a 5 resultados: suficiente para fundamentar la mayoria de respuestas sin agotar el contexto.
Web search results for: easy chocolate cake recipe
[1] One-Bowl Chocolate Cake
Moist cake from flour, sugar, cocoa, baking soda... 35 min at 350F.
https://example.com/one-bowl-cake
[2] Best Moist Chocolate Cake
Hot water thins the batter for a tender crumb...
https://example.com/moist-cake
Use these results to answer. Cite the source number.Paso 4: Inyecta el bloque y arregla el corte aparte
Envia el bloque de contexto como mensaje de sistema (o antepuesto al mensaje del usuario) justo antes de generar. El corte a mitad de frase es otro fallo: casi siempre es max_tokens demasiado bajo o una conexion de streaming que se cae, no un problema de busqueda. Sube el limite de tokens de respuesta en los ajustes de generacion y confirma que el streaming termina. Busqueda y truncado son dos interruptores distintos: arregla los dos.
messages = [
{"role": "system", "content": grounding_block},
{"role": "user", "content": user_query},
]
# In your UI: raise max_tokens / response length so the answer
# doesn't get chopped mid-sentence. That's unrelated to search.Ejemplo en Python
import os
import requests
API_KEY = os.environ["SCAVIO_API_KEY"]
def search_web(query: str, top_k: int = 4) -> str:
"""Call a SERP API and return a clean grounding block."""
resp = requests.post(
"https://api.scavio.dev/api/v1/google",
headers={"Authorization": f"Bearer {API_KEY}"},
json={"query": query},
timeout=30,
)
resp.raise_for_status()
results = resp.json().get("results", [])[:top_k]
lines = [f"Web search results for: {query}", ""]
for i, r in enumerate(results, 1):
title = r.get("title", "")
snippet = r.get("snippet", "")
link = r.get("link", "")
lines.append(f"[{i}] {title}\n{snippet}\n{link}\n")
lines.append("Use these results to answer. Cite the source number.")
return "\n".join(lines)
def build_messages(user_query: str) -> list:
grounding = search_web(user_query)
return [
{"role": "system", "content": grounding},
{"role": "user", "content": user_query},
]
if __name__ == "__main__":
msgs = build_messages("easy chocolate cake recipe")
print(msgs[0]["content"])
# Pass msgs to your model. The model now answers from real
# results instead of inventing a recipe to fill the silence.Ejemplo en JavaScript
const API_KEY = process.env.SCAVIO_API_KEY;
async function searchWeb(query, topK = 4) {
const resp = await fetch("https://api.scavio.dev/api/v1/google", {
method: "POST",
headers: {
Authorization: `Bearer ${API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ query }),
});
if (!resp.ok) throw new Error(`Search failed: ${resp.status}`);
const data = await resp.json();
const results = (data.results || []).slice(0, topK);
const lines = [`Web search results for: ${query}`, ""];
results.forEach((r, i) => {
lines.push(`[${i + 1}] ${r.title || ""}\n${r.snippet || ""}\n${r.link || ""}\n`);
});
lines.push("Use these results to answer. Cite the source number.");
return lines.join("\n");
}
async function buildMessages(userQuery) {
const grounding = await searchWeb(userQuery);
return [
{ role: "system", content: grounding },
{ role: "user", content: userQuery },
];
}
buildMessages("easy chocolate cake recipe").then((msgs) => {
console.log(msgs[0].content);
// Pass msgs to your model - it answers from real results now.
});Salida esperada
Web search results for: easy chocolate cake recipe
[1] One-Bowl Chocolate Cake
Moist cake from flour, sugar, cocoa, baking soda. 35 min at 350F.
https://example.com/one-bowl-cake
[2] Best Moist Chocolate Cake
Hot water thins the batter for a tender crumb.
https://example.com/moist-cake
Use these results to answer. Cite the source number.