Uso de la API de búsqueda web de Ollama en Python

Crea agentes de búsqueda con IA en Python y Ollama

Índice

La librería de Python de Ollama ahora incluye capacidades nativas de búsqueda web de Ollama. Con solo unas pocas líneas de código, puedes enriquecer tus LLM locales con información en tiempo real de la web, reduciendo alucinaciones y mejorando la precisión.

espacio digital

Introducción

¿Cómo instalo la librería de Python de Ollama para búsqueda web? Instala la versión 0.6.0 o superior utilizando pip install 'ollama>=0.6.0'. Esta versión incluye las funciones web_search y web_fetch.

pip install 'ollama>=0.6.0'

Para gestionar entornos y paquetes de Python, considera usar uv, un gestor de paquetes de Python rápido, o configura un entorno virtual usando venv para mantener tus dependencias aisladas.

Crea una clave API desde tu cuenta de Ollama y establécela como variable de entorno:

export OLLAMA_API_KEY="your_api_key"

En Windows PowerShell:

$env:OLLAMA_API_KEY = "your_api_key"

Búsqueda Web Básica

La forma más sencilla de buscar en la web con Ollama:

import ollama

# Simple web search
response = ollama.web_search("What is Ollama?")
print(response)

Salida:

results = [
    {
        "title": "Ollama",
        "url": "https://ollama.com/",
        "content": "Cloud models are now available in Ollama..."
    },
    {
        "title": "What is Ollama? Features, Pricing, and Use Cases",
        "url": "https://www.walturn.com/insights/what-is-ollama",
        "content": "Our services..."
    },
    {
        "title": "Complete Ollama Guide: Installation, Usage & Code Examples",
        "url": "https://collabnix.com/complete-ollama-guide",
        "content": "Join our Discord Server..."
    }
]

Controlando la Cantidad de Resultados

import ollama

# Get more results
response = ollama.web_search("latest AI news", max_results=10)

for result in response.results:
    print(f"📌 {result.title}")
    print(f"   {result.url}")
    print(f"   {result.content[:100]}...")
    print()

Recuperando el Contenido Completo de una Página

¿Cuál es la diferencia entre web_search y web_fetch en Ollama Python? web_search consulta internet y devuelve múltiples resultados de búsqueda con títulos, URLs y fragmentos de texto. web_fetch recupera el contenido completo de una URL específica, devolviendo el título de la página, el contenido en markdown y los enlaces. El contenido en markdown devuelto por web_fetch es perfecto para un procesamiento adicional: si necesitas convertir HTML a markdown en otros contextos, consulta nuestra guía sobre conversion de HTML a Markdown con Python.

from ollama import web_fetch

result = web_fetch('https://ollama.com')
print(result)

Salida:

WebFetchResponse(
    title='Ollama',
    content='[Cloud models](https://ollama.com/blog/cloud-models) are now available in Ollama\n\n**Chat & build with open models**\n\n[Download](https://ollama.com/download) [Explore models](https://ollama.com/models)\n\nAvailable for macOS, Windows, and Linux',
    links=['https://ollama.com/', 'https://ollama.com/models', 'https://github.com/ollama/ollama']
)

Combinando Búsqueda y Recuperación

Un patrón común es buscar primero y luego recuperar el contenido completo de los resultados relevantes:

from ollama import web_search, web_fetch

# Search for information
search_results = web_search("Ollama new features 2025")

# Fetch full content from the first result
if search_results.results:
    first_url = search_results.results[0].url
    full_content = web_fetch(first_url)
    
    print(f"Title: {full_content.title}")
    print(f"Content: {full_content.content[:500]}...")
    print(f"Links found: {len(full_content.links)}")

Construyendo un Agente de Búsqueda

¿Qué modelos de Python funcionan mejor para agentes de búsqueda de Ollama? Los modelos con fuertes capacidades de uso de herramientas funcionan mejor, incluyendo qwen3, gpt-oss y modelos en la nube como qwen3:480b-cloud y deepseek-v3.1-cloud. Para casos de uso más avanzados que requieren salidas estructuradas de estos modelos, echa un vistazo a nuestra guía sobre LLMs con Salida Estructurada usando Ollama y Qwen3. Una vez que las herramientas o el modo JSON devuelven cargas de trabajo que deseas confiar, validación de salida estructurada de LLM en Python que se sostiene cubre el análisis, las comprobaciones de Pydantic, los reintentos y las pruebas en el lado de la aplicación.

Primero, descarga un modelo capaz:

ollama pull qwen3:4b

Agente de Búsqueda Simple

Aquí tienes un agente de búsqueda básico que puede decidir de forma autónoma cuándo buscar:

from ollama import chat, web_fetch, web_search

available_tools = {'web_search': web_search, 'web_fetch': web_fetch}

messages = [{'role': 'user', 'content': "what is ollama's new engine"}]

while True:
    response = chat(
        model='qwen3:4b',
        messages=messages,
        tools=[web_search, web_fetch],
        think=True
    )
    
    if response.message.thinking:
        print('🧠 Thinking:', response.message.thinking[:200], '...')
    
    if response.message.content:
        print('💬 Response:', response.message.content)
    
    messages.append(response.message)
    
    if response.message.tool_calls:
        print('🔧 Tool calls:', response.message.tool_calls)
        for tool_call in response.message.tool_calls:
            function_to_call = available_tools.get(tool_call.function.name)
            if function_to_call:
                args = tool_call.function.arguments
                result = function_to_call(**args)
                print('📥 Result:', str(result)[:200], '...')
                # Truncate result for limited context lengths
                messages.append({
                    'role': 'tool', 
                    'content': str(result)[:2000 * 4], 
                    'tool_name': tool_call.function.name
                })
            else:
                messages.append({
                    'role': 'tool', 
                    'content': f'Tool {tool_call.function.name} not found', 
                    'tool_name': tool_call.function.name
                })
    else:
        break

¿Cómo manejo grandes resultados de búsqueda web en Python? Recorta los resultados para que quepan en los límites de contexto. El enfoque recomendado es cortar la cadena de resultados a aproximadamente 8000 caracteres (2000 tokens × 4 caracteres) antes de pasarla al modelo.

Agente de Búsqueda Avanzado con Manejo de Errores

Aquí tienes una versión mejorada con un mejor manejo de errores:

from ollama import chat, web_fetch, web_search
import json

class SearchAgent:
    def __init__(self, model: str = 'qwen3:4b'):
        self.model = model
        self.tools = {'web_search': web_search, 'web_fetch': web_fetch}
        self.messages = []
        self.max_iterations = 10
        
    def query(self, question: str) -> str:
        self.messages = [{'role': 'user', 'content': question}]
        
        for iteration in range(self.max_iterations):
            try:
                response = chat(
                    model=self.model,
                    messages=self.messages,
                    tools=[web_search, web_fetch],
                    think=True
                )
            except Exception as e:
                return f"Error during chat: {e}"
            
            self.messages.append(response.message)
            
            # If no tool calls, we have a final answer
            if not response.message.tool_calls:
                return response.message.content or "No response generated"
            
            # Execute tool calls
            for tool_call in response.message.tool_calls:
                result = self._execute_tool(tool_call)
                self.messages.append({
                    'role': 'tool',
                    'content': result,
                    'tool_name': tool_call.function.name
                })
        
        return "Max iterations reached without final answer"
    
    def _execute_tool(self, tool_call) -> str:
        func_name = tool_call.function.name
        args = tool_call.function.arguments
        
        if func_name not in self.tools:
            return f"Unknown tool: {func_name}"
        
        try:
            result = self.tools[func_name](**args)
            # Truncate for context limits
            result_str = str(result)
            if len(result_str) > 8000:
                result_str = result_str[:8000] + "... [truncated]"
            return result_str
        except Exception as e:
            return f"Tool error: {e}"

# Usage
agent = SearchAgent(model='qwen3:4b')
answer = agent.query("What are the latest features in Ollama?")
print(answer)

Búsqueda Web Asíncrona

¿Puedo usar la búsqueda web de Ollama Python con código asíncrono? Sí, la librería de Python de Ollama soporta operaciones asíncronas. Usa AsyncClient para operaciones de búsqueda y recuperación web no bloqueantes en aplicaciones asíncronas.

import asyncio
from ollama import AsyncClient

async def async_search():
    client = AsyncClient()
    
    # Perform multiple searches concurrently
    tasks = [
        client.web_search("Ollama features"),
        client.web_search("local LLM tools"),
        client.web_search("AI search agents"),
    ]
    
    results = await asyncio.gather(*tasks)
    
    for i, result in enumerate(results):
        print(f"Search {i + 1}:")
        for r in result.results[:2]:
            print(f"  - {r.title}")
        print()

# Run async search
asyncio.run(async_search())

Agente de Búsqueda Asíncrono

import asyncio
from ollama import AsyncClient

async def async_research_agent(question: str):
    client = AsyncClient()
    messages = [{'role': 'user', 'content': question}]
    
    while True:
        response = await client.chat(
            model='qwen3:4b',
            messages=messages,
            tools=[client.web_search, client.web_fetch],
        )
        
        messages.append(response.message)
        
        if not response.message.tool_calls:
            return response.message.content
        
        # Execute tool calls concurrently
        tool_tasks = []
        for tool_call in response.message.tool_calls:
            if tool_call.function.name == 'web_search':
                task = client.web_search(**tool_call.function.arguments)
            elif tool_call.function.name == 'web_fetch':
                task = client.web_fetch(**tool_call.function.arguments)
            else:
                continue
            tool_tasks.append((tool_call.function.name, task))
        
        # Gather results
        for tool_name, task in tool_tasks:
            result = await task
            messages.append({
                'role': 'tool',
                'content': str(result)[:8000],
                'tool_name': tool_name
            })

# Run
answer = asyncio.run(async_research_agent("What's new in Python 3.13?"))
print(answer)

Longitud de Contexto y Rendimiento

¿Qué longitud de contexto debo establecer para agentes de búsqueda en Python? Establece la longitud de contexto en aproximadamente 32000 tokens para un rendimiento razonable. Los agentes de búsqueda funcionan mejor con la longitud de contexto completa ya que web_search y web_fetch pueden devolver miles de tokens.

from ollama import chat, web_search

# Set higher context for search-heavy tasks
response = chat(
    model='qwen3:4b',
    messages=[{'role': 'user', 'content': 'Research the latest AI developments'}],
    tools=[web_search],
    options={
        'num_ctx': 32768,  # 32K context
    }
)

Integración con Servidores MCP

Ollama proporciona un servidor MCP de Python que permite la búsqueda web en cualquier cliente MCP. Para una guía completa sobre la construcción de servidores MCP en Python con capacidades de búsqueda web y raspado (scraping), consulta nuestro tutorial detallado sobre Construcción de Servidores MCP en Python.

Integración con Cline

Configura los servidores MCP en los ajustes de Cline:

Gestionar Servidores MCP → Configurar Servidores MCP → Añadir:

{
  "mcpServers": {
    "web_search_and_fetch": {
      "type": "stdio",
      "command": "uv",
      "args": ["run", "path/to/web-search-mcp.py"],
      "env": { "OLLAMA_API_KEY": "your_api_key_here" }
    }
  }
}

Integración con Codex

Añade a ~/.codex/config.toml:

[mcp_servers.web_search]
command = "uv"
args = ["run", "path/to/web-search-mcp.py"]
env = { "OLLAMA_API_KEY" = "your_api_key_here" }

Creando tu Propio Servidor MCP

#!/usr/bin/env python3
"""Simple MCP server for Ollama web search."""

import os
from mcp.server import Server
from mcp.types import Tool, TextContent
from ollama import web_search, web_fetch

app = Server("ollama-web-search")

@app.tool()
async def search_web(query: str, max_results: int = 5) -> str:
    """Search the web for information."""
    results = web_search(query, max_results=max_results)
    
    output = []
    for r in results.results:
        output.append(f"**{r.title}**\n{r.url}\n{r.content}\n")
    
    return "\n---\n".join(output)

@app.tool()
async def fetch_page(url: str) -> str:
    """Fetch the full content of a web page."""
    result = web_fetch(url)
    return f"# {result.title}\n\n{result.content}"

if __name__ == "__main__":
    app.run()

Ejemplos Prácticos

Estos ejemplos demuestran aplicaciones del mundo real de la API de búsqueda web de Ollama. Puedes extender estos patrones para construir sistemas más complejos: por ejemplo, combinando resultados de búsqueda con generación de PDF en Python para crear informes de investigación.

Resumen de Noticias

from ollama import chat, web_search

def summarize_news(topic: str) -> str:
    # Search for recent news
    results = web_search(f"{topic} latest news", max_results=5)
    
    # Format search results for the model
    news_content = "\n\n".join([
        f"**{r.title}**\n{r.content}"
        for r in results.results
    ])
    
    # Ask the model to summarize
    response = chat(
        model='qwen3:4b',
        messages=[{
            'role': 'user',
            'content': f"Summarize these news items about {topic}:\n\n{news_content}"
        }]
    )
    
    return response.message.content

summary = summarize_news("artificial intelligence")
print(summary)

Asistente de Investigación

from ollama import chat, web_search, web_fetch
from dataclasses import dataclass

@dataclass
class ResearchResult:
    question: str
    sources: list
    answer: str

def research(question: str) -> ResearchResult:
    # Search for relevant information
    search_results = web_search(question, max_results=3)
    
    # Fetch full content from top sources
    sources = []
    full_content = []
    
    for result in search_results.results[:3]:
        try:
            page = web_fetch(result.url)
            sources.append(result.url)
            full_content.append(f"Source: {result.url}\n{page.content[:2000]}")
        except:
            continue
    
    # Generate comprehensive answer
    context = "\n\n---\n\n".join(full_content)
    
    response = chat(
        model='qwen3:4b',
        messages=[{
            'role': 'user',
            'content': f"""Based on the following sources, answer this question: {question}

Sources:
{context}

Provide a comprehensive answer with citations to the sources."""
        }]
    )
    
    return ResearchResult(
        question=question,
        sources=sources,
        answer=response.message.content
    )

# Usage
result = research("How does Ollama's new model scheduling work?")
print(f"Question: {result.question}")
print(f"Sources: {result.sources}")
print(f"Answer: {result.answer}")

Modelos Recomendados

Modelo Parámetros Mejor Para
qwen3:4b 4B Búsquedas locales rápidas
qwen3 8B Agente de uso general
gpt-oss Varios Tareas de investigación
qwen3:480b-cloud 480B Razonamiento complejo (nube)
gpt-oss:120b-cloud 120B Investigación extensa (nube)
deepseek-v3.1-cloud - Análisis avanzado (nube)

Mejores Prácticas

  1. Recortar Resultados: Recorta siempre los resultados web para que quepan en los límites de contexto (~8000 caracteres)
  2. Manejo de Errores: Envuelve las llamadas a herramientas en try/except para fallas de red
  3. Limitación de Tasa: Respeta los límites de tasa de la API de Ollama para la búsqueda web
  4. Longitud de Contexto: Usa ~32000 tokens para agentes de búsqueda
  5. Asíncrono para Escala: Usa AsyncClient para operaciones concurrentes
  6. Pruebas: Escribe pruebas unitarias para tus agentes de búsqueda para garantizar la confiabilidad
  7. Básicos de Python: Ten a mano una hoja de referencia de Python para referencia rápida sobre sintaxis y patrones comunes

Enlaces Útiles

Suscribirse

Recibe nuevas publicaciones sobre sistemas, infraestructura e ingeniería de IA.