Los LLM locales que se ejecutan en Ollama o llama.cpp carecen de acceso a Internet de forma predeterminada. Cuando los usuarios preguntan sobre eventos actuales, precios o cualquier tema urgente, el modelo alucina o se niega a responder. Agregar una herramienta de búsqueda web resuelve esto. La API de Scavio actúa como un punto final de búsqueda HTTP liviano que devuelve JSON estructurado, que es lo suficientemente pequeño como para caber en la ventana de contexto de cualquier modelo local. Este tutorial conecta una herramienta de búsqueda a un agente de Ollama usando Python, para que el modelo pueda decidir de forma autónoma cuándo buscar y basar sus respuestas en datos en vivo. No se necesita LangChain ni un marco pesado.
Requisitos previos
- Ollama instalado con un modelo con capacidad para herramientas (llama3.1, mistral, etc.)
- Python 3.10+
- solicita biblioteca instalada
- Una clave API de Scavio de scavio.dev
Guia paso a paso
Paso 1: Definir el esquema de la herramienta de búsqueda
Cree una definición de herramienta que le indique al LLM qué hace la función de búsqueda y qué parámetros acepta. Ollama utiliza el formato de herramienta compatible con OpenAI.
import os
import requests
import json
API_KEY = os.environ['SCAVIO_API_KEY']
SEARCH_TOOL = {
'type': 'function',
'function': {
'name': 'web_search',
'description': 'Search the web for current information. Use this when the user asks about recent events, prices, news, or anything you do not have up-to-date knowledge about.',
'parameters': {
'type': 'object',
'properties': {
'query': {'type': 'string', 'description': 'The search query'}
},
'required': ['query']
}
}
}Paso 2: Implementar la función de búsqueda
La función llama a la API de Scavio y devuelve una cadena condensada de resultados que cabe cómodamente en la ventana de contexto del modelo.
def web_search(query):
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'})
results = resp.json().get('organic_results', [])[:5]
lines = []
for r in results:
lines.append(f"{r['title']}: {r.get('snippet', '')} ({r['link']})")
return '\n'.join(lines) if lines else 'No results found.'Paso 3: Ejecute el bucle del agente con Ollama
Envía el mensaje de usuario a Ollama con la definición de la herramienta. Si el modelo llama a la herramienta, ejecute la búsqueda y envíe el resultado para obtener la respuesta final.
def chat_with_search(user_message, model='llama3.1'):
messages = [{'role': 'user', 'content': user_message}]
resp = requests.post('http://localhost:11434/api/chat', json={
'model': model, 'messages': messages, 'tools': [SEARCH_TOOL], 'stream': False
}).json()
msg = resp['message']
if msg.get('tool_calls'):
for tc in msg['tool_calls']:
if tc['function']['name'] == 'web_search':
args = tc['function']['arguments']
result = web_search(args['query'])
messages.append(msg)
messages.append({'role': 'tool', 'content': result})
final = requests.post('http://localhost:11434/api/chat', json={
'model': model, 'messages': messages, 'stream': False
}).json()
return final['message']['content']
return msg['content']Paso 4: Prueba con una pregunta en tiempo real
Pregúntele al agente algo que no pueda responder únicamente con los datos de entrenamiento. El modelo debería llamar a web_search y sintetizar los resultados.
answer = chat_with_search('What are the top trending Python libraries released in 2026?')
print(answer)Ejemplo en Python
import os, requests, json
API_KEY = os.environ['SCAVIO_API_KEY']
SEARCH_TOOL = {
'type': 'function',
'function': {
'name': 'web_search',
'description': 'Search the web for current information.',
'parameters': {
'type': 'object',
'properties': {'query': {'type': 'string', 'description': 'Search query'}},
'required': ['query']
}
}
}
def web_search(query):
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'})
results = resp.json().get('organic_results', [])[:5]
return '\n'.join(f"{r['title']}: {r.get('snippet', '')}" for r in results) or 'No results.'
def chat(user_msg, model='llama3.1'):
messages = [{'role': 'user', 'content': user_msg}]
resp = requests.post('http://localhost:11434/api/chat', json={
'model': model, 'messages': messages, 'tools': [SEARCH_TOOL], 'stream': False
}).json()
msg = resp['message']
if msg.get('tool_calls'):
for tc in msg['tool_calls']:
result = web_search(tc['function']['arguments']['query'])
messages.append(msg)
messages.append({'role': 'tool', 'content': result})
return requests.post('http://localhost:11434/api/chat', json={
'model': model, 'messages': messages, 'stream': False
}).json()['message']['content']
return msg['content']
print(chat('What Python libraries were released in 2026?'))Ejemplo en JavaScript
const API_KEY = process.env.SCAVIO_API_KEY;
const SEARCH_TOOL = {
type: 'function',
function: {
name: 'web_search',
description: 'Search the web for current information.',
parameters: {
type: 'object',
properties: { query: { type: 'string', description: 'Search query' } },
required: ['query']
}
}
};
async function webSearch(query) {
const r = 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' })
}).then(r => r.json());
return (r.organic_results || []).slice(0, 5)
.map(r => `${r.title}: ${r.snippet || ''}`).join('\n') || 'No results.';
}
async function chat(userMsg, model = 'llama3.1') {
const messages = [{ role: 'user', content: userMsg }];
let resp = await fetch('http://localhost:11434/api/chat', {
method: 'POST',
body: JSON.stringify({ model, messages, tools: [SEARCH_TOOL], stream: false })
}).then(r => r.json());
if (resp.message.tool_calls) {
for (const tc of resp.message.tool_calls) {
const result = await webSearch(tc.function.arguments.query);
messages.push(resp.message, { role: 'tool', content: result });
}
resp = await fetch('http://localhost:11434/api/chat', {
method: 'POST',
body: JSON.stringify({ model, messages, stream: false })
}).then(r => r.json());
}
return resp.message.content;
}
chat('Latest AI news in 2026?').then(console.log).catch(console.error);Salida esperada
User: What Python libraries were released in 2026?
[Agent calls web_search("new python libraries released 2026")]
[Search returns 5 results with titles and snippets]
Agent: Based on web search results, several notable Python libraries
launched in 2026 including... The agent synthesizes the search
results into a grounded, accurate answer.