Práctica de las seis capacidades principales de los modelos de Ollama
La salida en streaming, el modo de razonamiento, la salida estructurada, la comprensión visual, la incrustación de vectores, la llamada de herramientas y la búsqueda en línea conforman el panorama completo de las capacidades de los modelos de Ollama.
Este capítulo practica una por una cada capacidad con la biblioteca oficial de Python; todos los ejemplos se pueden ejecutar directamente.
Primero, necesitamos instalar el SDK de Python de Ollama.
Puedes instalarlo con pip:
pip install ollama
Asegúrate de que Python 3.x esté instalado en tu entorno y de que el entorno de red pueda acceder al servicio local de Ollama.
Antes de usar el SDK de Python, asegúrate de que el servicio local de Ollama esté iniciado.
Puedes iniciarlo con la herramienta de línea de comandos:
ollama serve
Una vez iniciado el servicio local, el SDK de Python se comunicará con él para ejecutar tareas como la inferencia de modelos.
Capacidad 1: Salida en streaming
El streaming hace que la respuesta aparezca palabra por palabra en la interfaz; es la base de la experiencia de las aplicaciones de chat.
En el SDK, establece stream en True y luego itera procesando cada fragmento de datos:
Ejemplo
# Activa el streaming y recibe las respuestas por fragmentos
stream = chat(
model='qwen3.5',
messages=[{'role': 'user', 'content': 'Presenta EJEMPLO, el tutorial para novatos, en tres frases'}],
stream=True,
)
# Imprime por fragmentos y concatena el contenido completo
content = ''
for chunk in stream:
print(chunk.message.content, end='', flush=True)
content += chunk.message.content
# El content concatenado se puede usar para guardar el historial y archivarlo
Punto clave: cada fragmento del streaming es solo un "fragmento"; debes acumular el contenido completo en el cliente. Cuando luego quieras incluir esta respuesta en el historial de la conversación, se usa el texto completo concatenado.
Capacidad 2: Modo de razonamiento
El modelo de razonamiento primero genera un proceso de pensamiento y luego da la respuesta. En el SDK se controla mediante el parámetro think; el pensamiento y el texto de la respuesta están en dos campos separados.
Ejemplo
response = chat(
model='qwen3.5',
messages=[{'role': 'user', 'content': '¿Cuál es mayor, 9.9 o 9.11?'}],
think=True,
stream=False,
)
# El proceso de pensamiento y la respuesta final están en campos separados
print('Pensamiento:', response.message.thinking)
print('Respuesta:', response.message.content)
En el escenario de streaming, thinking y content aparecen alternándose en los fragmentos de datos; usa una máquina de estados para alternar las áreas de renderizado:
Ejemplo
stream = chat(
model='qwen3.5',
messages=[{'role': 'user', 'content': '¿Cuánto es 17 por 23?'}],
think=True,
stream=True,
)
in_thinking = False
for chunk in stream:
if chunk.message.thinking:
if not in_thinking:
in_thinking = True
print('【Pensando...】', end='', flush=True)
print(chunk.message.thinking, end='', flush=True)
elif chunk.message.content:
if in_thinking:
in_thinking = False
print('\n'【Respuesta】', end='', flush=True)
print(chunk.message.content, end='', flush=True)
Sugerencia de implementación de UI: renderiza thinking como un área gris plegable y content como el cuerpo del texto; la serie gpt-oss solo acepta tres niveles de intensidad de razonamiento: low / medium / high; pasar un valor booleano no tiene efecto.
Capacidad 3: Salida estructurada
La salida estructurada permite que el modelo devuelva datos que cumplen estrictamente con un JSON Schema; junto con la validación de Pydantic, es la forma estándar de que los programas consuman la salida del modelo.
Ejemplo
from pydantic import BaseModel
# Define la estructura de datos esperada con Pydantic
class Site(BaseModel):
name: str
category: str
free: bool
response = chat(
model='qwen3.5',
messages=[{'role': 'user', 'content': 'Presenta EJEMPLO, el tutorial para novatos'}],
format=Site.model_json_schema(),
)
# El contenido devuelto es una cadena JSON que cumple el schema; valídala y pársela directamente
site = Site.model_validate_json(response.message.content)
print(site.name, site.category, site.free)
Este patrón es la piedra angular de todas las aplicaciones de extracción de datos: extraer campos de currículos, extraer elementos de tickets, extraer información de imágenes (combinado con la capacidad visual); todas lo usan.
Dos trucos de estabilidad: establece temperature en 0 en options; describe también el significado de los campos en el prompt, creando una doble restricción con el schema.
Capacidad 4: Comprensión visual
Los modelos multimodales (como qwen3.5) pueden recibir imágenes; el SDK admite pasar directamente la ruta del archivo, mucho más conveniente que la codificación base64 de la API REST.
Ejemplo
response = chat(
model='qwen3.5',
messages=[{
'role': 'user',
'content': '¿Qué página es esta captura de pantalla? Enumera las funciones principales.',
'images': ['screenshot.png'],
}],
)
print(response.message.content)
La combinación de la visión y la salida estructurada permite hacer "conversión de imágenes en datos":
Ejemplo
from pydantic import BaseModel
# Define la estructura objetivo que se extraerá de la imagen
class Receipt(BaseModel):
merchant: str
total: float
date: str
response = chat(
model='qwen3.5',
messages=[{
'role': 'user',
'content': 'Extrae el comercio, el monto y la fecha de esta foto de recibo',
'images': ['receipt.jpg'],
}],
format=Receipt.model_json_schema(),
options={'temperature': 0},
)
print(Receipt.model_validate_json(response.message.content))
Capacidad 5: Incrustación de vectores
La interfaz embed genera vectores de texto por lotes; junto con la similitud coseno, se puede implementar una búsqueda semántica mínimamente viable.
Ejemplo
# Genera vectores de documentos por lotes
docs = [
'Python es un lenguaje interpretado',
'JavaScript se ejecuta principalmente en el navegador',
'EJEMPLO ofrece tutoriales de programación gratuitos',
]
result = ollama.embed(model='embeddinggemma', input=docs)
vectors = result['embeddings']
print(len(vectors), len(vectors[0])) # 3 vectores y sus dimensiones
# Calcula la similitud coseno entre el vector de consulta y los vectores de los documentos para ordenar y recuperar
query = ollama.embed(model='embeddinggemma', input='¿Es difícil aprender Python?')
La indexación y la consulta deben usar el mismo modelo de incrustación; de lo contrario, el espacio vectorial no es consistente y los resultados de la búsqueda no tienen sentido. La práctica completa de la base de conocimiento se desarrolla en el capítulo del proyecto RAG.
Capacidad 6: Llamada de herramientas
La llamada de herramientas hace que el modelo aprenda a "pedir ayuda": cuando determina que necesita información externa, devuelve tool_calls; el programa ejecuta la función real y, después de devolver el resultado, el modelo resume y responde.
Primero observa la secuencia completa del bucle del agente (Agent loop) para entender el flujo de mensajes entre las cuatro partes:
El SDK de Python permite pasar funciones directamente como herramientas; la firma de la función y el docstring se analizan automáticamente como schema:
Ejemplo
# Función de herramienta local: el docstring se convertirá en la descripción de la herramienta que ve el modelo
def get_weather(city: str) -> str:
"""Consulta la temperatura actual de la ciudad especificada
Args:
city: nombre de la ciudad
Returns:
Descripción de la temperatura actual
"""
temperatures = {"Beijing": "22°C", "Shanghái": "26°C", "Nueva York": "18°C"}
return temperatures.get(city, "Ciudad desconocida")
messages = [{'role': 'user', 'content': '¿Cuántos grados hace ahora en Nueva York?'}]
# Bucle del agente: repite hasta que el modelo no solicite más herramientas
while True:
response = chat(
model='qwen3.5',
messages=messages,
tools=[get_weather],
)
# Añade los mensajes del modelo (incluidos tool_calls) al historial
messages.append(response.message)
if not response.message.tool_calls:
# Cuando no hay más solicitudes de herramientas, muestra la respuesta final
print(response.message.content)
break
# Si hay solicitudes de herramientas: ejecútalas y devuelve los resultados con el rol tool
for call in response.message.tool_calls:
result = get_weather(**call.function.arguments)
messages.append({
'role': 'tool',
'tool_name': call.function.name,
'content': result,
})
Tres puntos clave de ingeniería: primero, cada response.message debe añadirse tal cual a messages, y los resultados de las herramientas se devuelven con el rol tool; segundo, en las llamadas paralelas de herramientas, el modelo puede devolver varios tool_calls a la vez; debes ejecutarlos y añadirlos uno a uno; tercero, en proyectos reales, los resultados de las herramientas pueden ser muy largos; presta atención a truncarlos para proteger la ventana de contexto.
Capacidad 7: Búsqueda en línea
Ollama ofrece oficialmente dos interfaces en línea, web_search y web_fetch, que se pueden montar como herramientas para el modelo, permitiéndole responder con información nueva más allá de sus datos de entrenamiento.
Ejemplo
# Monta la capacidad de búsqueda en línea como herramienta
available_tools = {'web_search': web_search, 'web_fetch': web_fetch}
messages = [{'role': 'user', 'content': "¿Qué novedades tiene Ollama recientemente?"}]
while True:
response = chat(
model='qwen3.5',
messages=messages,
tools=[web_search, web_fetch],
think=True,
)
messages.append(response.message)
if not response.message.tool_calls:
print(response.message.content)
break
for call in response.message.tool_calls:
func = available_tools.get(call.function.name)
if func:
# Los resultados de las herramientas pueden ser muy largos; trúncalos para proteger el contexto
result = str(func(**call.function.arguments))
messages.append({
'role': 'tool',
'tool_name': call.function.name,
'content': result[:2000],
})
Otras extensionesLas interfaces en línea requieren crear una API Key en ollama.com; los resultados de búsqueda suelen tener miles de tokens, y la recomendación oficial para este tipo de escenarios de agente es abrir el contexto a más de 32K. También tiene una implementación MCP Server lista para usar, que se puede integrar con herramientas como Cline y Codex; los detalles de integración están en el capítulo de ecosistema.