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

Construya agentes de búsqueda de IA con Python y Ollama

Índice

La biblioteca de Python de Ollama ahora incluye capacidades nativas de búsqueda web de OLLama. Con solo unas pocas líneas de código, puedes mejorar tus LLMs locales con información en tiempo real desde la web, reduciendo las alucinaciones e incrementando la precisión.

espacio digital

Comenzando

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

pip install 'ollama>=0.6.0'

Para administrar entornos y paquetes de Python, considere usar uv, un rápido administrador de paquetes de Python, o configure un entorno virtual usando venv para aislar sus dependencias.

Cree una clave API desde su cuenta de Ollama y establezcala como una variable de entorno:

export OLLAMA_API_KEY="your_api_key"

En PowerShell de Windows:

$env:OLLAMA_API_KEY = "your_api_key"

Búsqueda Web Básica

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

import ollama

# Búsqueda web simple
response = ollama.web_search("¿Qué es Ollama?")
print(response)

Salida:

results = [
    {
        "title": "Ollama",
        "url": "https://ollama.com/",
        "content": "Los modelos en la nube ahora están disponibles en Ollama..."
    },
    {
        "title": "¿Qué es Ollama? Características, Precios y Casos de Uso",
        "url": "https://www.walturn.com/insights/what-is-ollama",
        "content": "Nuestros servicios..."
    },
    {
        "title": "Guía completa de Ollama: Instalación, Uso y Ejemplos de Código",
        "url": "https://collabnix.com/complete-ollama-guide",
        "content": "Únete a nuestro servidor de Discord..."
    }
]

Controlando el Número de Resultados

import ollama

# Obtener más resultados
response = ollama.web_search("últimas noticias de IA", max_results=10)

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

Obteniendo el Contenido Completo de una Página

¿Cuál es la diferencia entre web_search y web_fetch en la biblioteca de Python de Ollama? web_search consulta la internet y devuelve múltiples resultados de búsqueda con títulos, URLs y fragmentos. web_fetch obtiene el contenido completo de una URL específica, devolviendo el título de la página, el contenido en formato markdown y los enlaces. El contenido markdown devuelto por web_fetch es ideal para su procesamiento posterior—si necesita convertir HTML a markdown en otros contextos, consulte nuestra guía sobre convertir HTML a Markdown con Python.

from ollama import web_fetch

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

Salida:

WebFetchResponse(
    title='Ollama',
    content='[Modelos en la nube](https://ollama.com/blog/cloud-models) ahora están disponibles en Ollama\n\n**Chatea y construye con modelos abiertos**\n\n[Descarga](https://ollama.com/download) [Explora modelos](https://ollama.com/models)\n\nDisponible para macOS, Windows y 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 resultados relevantes:

from ollama import web_search, web_fetch

# Buscar información
search_results = web_search("nuevas características de Ollama 2025")

# Recuperar contenido completo del primer resultado
if search_results.results:
    first_url = search_results.results[0].url
    full_content = web_fetch(first_url)
    
    print(f"Título: {full_content.title}")
    print(f"Contenido: {full_content.content[:500]}...")
    print(f"Enlaces encontrados: {len(full_content.links)}")

Construyendo un Agente de Búsqueda

¿Cuáles son los modelos de Python que 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 requieran salidas estructuradas de estos modelos, consulte nuestra guía sobre LLMs con salida estructurada usando Ollama y Qwen3.

Primero, extraiga un modelo capaz:

ollama pull qwen3:4b

Agente de Búsqueda Simple

Aquí hay un agente de búsqueda básico que puede decidir autónomamente 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': "¿qué es el nuevo motor de Ollama"}]

while True:
    response = chat(
        model='qwen3:4b',
        messages=messages,
        tools=[web_search, web_fetch],
        think=True
    )
    
    if response.message.thinking:
        print('🧠 Pensando:', response.message.thinking[:200], '...')
    
    if response.message.content:
        print('💬 Respuesta:', response.message.content)
    
    messages.append(response.message)
    
    if response.message.tool_calls:
        print('🔧 Llamadas a herramientas:', 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('📥 Resultado:', str(result)[:200], '...')
                # Recortar resultado para ajustar a límites de contexto
                messages.append({
                    'role': 'tool', 
                    'content': str(result)[:2000 * 4], 
                    'tool_name': tool_call.function.name
                })
            else:
                messages.append({
                    'role': 'tool', 
                    'content': f'Herramienta {tool_call.function.name} no encontrada', 
                    'tool_name': tool_call.function.name
                })
    else:
        break

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

Agente de Búsqueda Avanzado con Manejo de Errores

Aquí hay 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 durante el chat: {e}"
            
            self.messages.append(response.message)
            
            # Si no hay llamadas a herramientas, tenemos una respuesta final
            if not response.message.tool_calls:
                return response.message.content or "No se generó ninguna respuesta"
            
            # Ejecutar llamadas a herramientas
            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 "Se alcanzó el número máximo de iteraciones sin una respuesta final"
    
    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'Herramienta desconocida: {func_name}'
        
        try:
            result = self.tools[func_name](**args)
            # Recortar para límites de contexto
            result_str = str(result)
            if len(result_str) > 8000:
                result_str = result_str[:8000] + "... [recortado]"
            return result_str
        except Exception as e:
            return f'Error de herramienta: {e}'

# Uso
agent = SearchAgent(model='qwen3:4b')
answer = agent.query("¿Cuáles son las últimas características en Ollama?")
print(answer)

Búsqueda Web Asincrónica

¿Puedo usar la búsqueda web de Ollama en Python con código asincrónico? Sí, la biblioteca de Python de Ollama admite operaciones asincrónicas. Use AsyncClient para operaciones de búsqueda y recuperación no bloqueantes en aplicaciones asincrónicas. Para comparaciones de rendimiento entre Python y otros lenguajes en contextos sin servidor, consulte nuestro análisis de rendimiento de AWS Lambda entre JavaScript, Python y Golang.

import asyncio
from ollama import AsyncClient

async def async_search():
    client = AsyncClient()
    
    # Realizar múltiples búsquedas concurrentemente
    tasks = [
        client.web_search("características de Ollama"),
        client.web_search("herramientas de LLM locales"),
        client.web_search("agentes de búsqueda de IA"),
    ]
    
    results = await asyncio.gather(*tasks)
    
    for i, result in enumerate(results):
        print(f"Búsqueda {i + 1}:")
        for r in result.results[:2]:
            print(f"  - {r.title}")
        print()

# Ejecutar búsqueda asincrónica
asyncio.run(async_search())

Agente de Búsqueda Asincrónico

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
        
        # Ejecutar llamadas a herramientas concurrentemente
        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))
        
        # Recopilar resultados
        for tool_name, task in tool_tasks:
            result = await task
            messages.append({
                'role': 'tool',
                'content': str(result)[:8000],
                'tool_name': tool_name
            })

# Ejecutar
answer = asyncio.run(async_research_agent("¿Qué es nuevo en Python 3.13?"))
print(answer)

Longitud de Contexto y Rendimiento

¿Qué longitud de contexto debo establecer para agentes de búsqueda en Python? Establezca la longitud de contexto a 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

# Establecer un contexto más alto para tareas intensivas de búsqueda
response = chat(
    model='qwen3:4b',
    messages=[{'role': 'user', 'content': 'Investigar los últimos desarrollos en IA'}],
    tools=[web_search],
    options={
        'num_ctx': 32768,  # 32K contexto
    }
)

Integración con el Servidor 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 y raspado web, consulte nuestro tutorial detallado sobre construcción de servidores MCP en Python.

Integración con Cline

Configure servidores MCP en las configuraciones de Cline:

Administrar 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ñada 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 su propio servidor MCP

#!/usr/bin/env python3
"""Servidor MCP simple para búsqueda web de Ollama."""

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:
    """Buscar información en la web."""
    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:
    """Recuperar el contenido completo de una página web."""
    result = web_fetch(url)
    return f"# {result.title}\n\n{result.content}"

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

Ejemplos Prácticos

Estos ejemplos demuestran aplicaciones reales de la API de búsqueda web de Ollama. Puede ampliar estos patrones para construir sistemas más complejos—por ejemplo, combinar resultados de búsqueda con generación de PDF en Python para crear informes de investigación.

Resumidor de Noticias

from ollama import chat, web_search

def summarize_news(topic: str) -> str:
    # Buscar noticias recientes
    results = web_search(f"{topic} últimas noticias", max_results=5)
    
    # Formatear resultados de búsqueda para el modelo
    news_content = "\n\n".join([
        f"**{r.title}**\n{r.content}"
        for r in results.results
    ])
    
    # Pedir al modelo que resuma
    response = chat(
        model='qwen3:4b',
        messages=[{
            'role': 'user',
            'content': f"Resuma estos artículos sobre {topic}:\n\n{news_content}"
        }]
    )
    
    return response.message.content

summary = summarize_news("inteligencia artificial")
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:
    # Buscar información relevante
    search_results = web_search(question, max_results=3)
    
    # Recuperar contenido completo de fuentes principales
    sources = []
    full_content = []
    
    for result in search_results.results[:3]:
        try:
            page = web_fetch(result.url)
            sources.append(result.url)
            full_content.append(f"Fuente: {result.url}\n{page.content[:2000]}")
        except:
            continue
    
    # Generar respuesta completa
    context = "\n\n---\n\n".join(full_content)
    
    response = chat(
        model='qwen3:4b',
        messages=[{
            'role': 'user',
            'content': f"""Basado en las siguientes fuentes, responda esta pregunta: {question}

Fuentes:
{context}

Proporcione una respuesta completa con citaciones de las fuentes."""
        }]
    )
    
    return ResearchResult(
        question=question,
        sources=sources,
        answer=response.message.content
    )

# Uso
result = research("¿Cómo funciona la nueva programación de modelos de Ollama?")
print(f"Pregunta: {result.question}")
print(f"Fuentes: {result.sources}")
print(f"Respuesta: {result.answer}")

Modelos Recomendados

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

Buenas Prácticas

  1. Recortar Resultados: Siempre recorte los resultados de la web para ajustarlos a los límites de contexto (~8000 caracteres)
  2. Manejo de Errores: Envuelva las llamadas a herramientas en try/except para fallos de red
  3. Límites de Tasa: Respete los límites de tasa de la API de Ollama para la búsqueda web
  4. Longitud de Contexto: Use ~32000 tokens para agentes de búsqueda
  5. Asincrónico para Escalabilidad: Use AsyncClient para operaciones concurrentes
  6. Pruebas: Escriba pruebas unitarias para sus agentes de búsqueda para garantizar su fiabilidad
  7. Bases de Python: Tenga una guía de referencia rápida de Python a mano para consultas rápidas sobre sintaxis y patrones comunes

Enlaces Útiles