Шесть возможностей модели Ollama на практике
Потоковый вывод, режим размышления, структурированный вывод, визуальное понимание, векторные эмбеддинги, вызов инструментов, а также веб-поиск образуют полную картину возможностей модели Ollama.
В этой главе официальная библиотека Python используется для поочерёдной отработки каждой возможности; все примеры можно запускать напрямую.
Сначала нам нужно установить Ollama Python SDK.
Установить его можно с помощью pip:
pip install ollama
Убедитесь, что в вашей среде установлен Python 3.x, и что ваша сеть может получить доступ к локальному сервису Ollama.
Перед использованием Python SDK убедитесь, что локальный сервис Ollama запущен.
Вы можете запустить его с помощью инструмента командной строки:
ollama serve
После запуска локального сервиса Python SDK будет взаимодействовать с ним для выполнения инференса модели и других задач.
Возможность 1: Потоковый вывод
Потоковая передача заставляет ответ появляться в интерфейсе слово за словом; это основа опыта чат-приложений.
В SDK установите stream в True, затем перебирайте каждый chunk:
Пример
# Включите потоковую передачу, получайте ответы по фрагментам
stream = chat(
model='qwen3.5',
messages=[{'role': 'user', 'content': 'Представь Python Tutorial в трёх предложениях'}],
stream=True,
)
# Печатайте по фрагментам, одновременно объединяя полное содержимое
content = ''
for chunk in stream:
print(chunk.message.content, end='', flush=True)
content += chunk.message.content
# Объединённое содержимое можно использовать для сохранения истории или архивирования в хранилище
Ключевой момент: каждый потоковый чанк — это лишь "фрагмент"; вы должны сами накапливать полное содержимое на стороне клиента. При добавлении ответа этого раунда в историю диалога позже используйте объединённый полный текст.
Возможность 2: Режим размышления
Модели рассуждений сначала выводят процесс размышления, прежде чем дать ответ. В SDK это управляется параметром think, а размышления и основной текст принадлежат двум отдельным полям.
Пример
response = chat(
model='qwen3.5',
messages=[{'role': 'user', 'content': 'Что больше, 9.9 или 9.11?'}],
think=True,
stream=False,
)
# Процесс размышления и итоговый ответ принадлежат двум отдельным полям
print('Размышление:', response.message.thinking)
print('Ответ:', response.message.content)
В сценариях потоковой передачи размышления и содержимое появляются поочерёдно в чанках; используйте конечный автомат для переключения областей отображения:
Пример
stream = chat(
model='qwen3.5',
messages=[{'role': 'user', 'content': 'Сколько будет 17 умножить на 23?'}],
think=True,
stream=True,
)
in_thinking = False
for chunk in stream:
if chunk.message.thinking:
if not in_thinking:
in_thinking = True
print('[Thinking]', end='', flush=True)
print(chunk.message.thinking, end='', flush=True)
elif chunk.message.content:
if in_thinking:
in_thinking = False
print('\n'[Answer]', end='', flush=True)
print(chunk.message.content, end='', flush=True)
Рекомендация по реализации UI: отображать размышления как сворачиваемую серую область, отображать содержимое как основной текст; серия gpt-oss принимает только три уровня усилия мышления — low / medium / high — передача логического значения недопустима.
Возможность 3: Структурированный вывод
Структурированный вывод заставляет модель возвращать данные, которые строго соответствуют JSON Schema; в сочетании с валидацией Pydantic это стандартный способ для программ потреблять вывод модели.
Пример
from pydantic import BaseModel
# Определите ожидаемую структуру данных с помощью Pydantic
class Site(BaseModel):
name: str
category: str
free: bool
response = chat(
model='qwen3.5',
messages=[{'role': 'user', 'content': 'Представь руководство по Python'}],
format=Site.model_json_schema(),
)
# Возвращаемое содержимое — это строка JSON, соответствующая схеме; проверьте и разберите её напрямую
site = Site.model_validate_json(response.message.content)
print(site.name, site.category, site.free)
Этот паттерн — краеугольный камень всех приложений по извлечению данных: извлечение полей из резюме, вытаскивание ключевой информации из тикетов и извлечение информации из изображений (в сочетании с возможностями зрения) — всё это использует его.
Два совета для стабильности: установите temperature в options равным 0; также опишите значение полей в промпте, обеспечивая двойные ограничения вместе со схемой.
Возможность 4: Визуальное понимание
Мультимодальные модели (такие как qwen3.5) могут принимать изображения. SDK поддерживает передачу путей к файлам напрямую, что гораздо удобнее, чем кодирование base64 в REST API.
Пример
response = chat(
model='qwen3.5',
messages=[{
'role': 'user',
'content': 'Что это за страница на скриншоте? Перечислите основные функции.',
'images': ['screenshot.png'],
}],
)
print(response.message.content)
Сочетание визуального анализа со структурированным выводом позволяет реализовать "image-to-data":
Пример
from pydantic import BaseModel
# Определите целевую структуру для извлечения из изображения
class Receipt(BaseModel):
merchant: str
total: float
date: str
response = chat(
model='qwen3.5',
messages=[{
'role': 'user',
'content': 'Извлеките продавца, сумму и дату из этого фото чека',
'images': ['receipt.jpg'],
}],
format=Receipt.model_json_schema(),
options={'temperature': 0},
)
print(Receipt.model_validate_json(response.message.content))
Возможность 5: векторные эмбеддинги
Интерфейс embed создаёт текстовые векторы пакетно; в сочетании с косинусным сходством он может реализовать минимально жизнеспособный семантический поиск.
Пример
# Сгенерировать векторы документов пакетно
docs = [
'Python — интерпретируемый язык',
'JavaScript в основном выполняется в браузере',
'EXAMPLE предоставляет бесплатные руководства по программированию',
]
result = ollama.embed(model='embeddinggemma', input=docs)
vectors = result['embeddings']
print(len(vectors), len(vectors[0])) # 3 вектора и их размерности
# Вычислить косинусное сходство между вектором запроса и векторами документов, чтобы отсортировать и получить результаты
query = ollama.embed(model='embeddinggemma', input='Сложно ли изучать Python?')
Индексация и запросы должны использовать одну и ту же модель встраивания; иначе векторные пространства несогласованы, и результаты поиска бессмысленны. Полная реализация базы знаний рассматривается в главе проекта RAG.
Возможность 6: Вызов инструментов
Вызов инструментов учит модель «просить о помощи»: когда она определяет, что нужна внешняя информация, она возвращает tool_calls; программа выполняет соответствующие функции, и после передачи результатов обратно модель обобщает и отвечает.
Сначала рассмотрим полную последовательность цикла Agent, чтобы понять, как сообщения циркулируют между четырьмя участниками:
Python SDK позволяет передавать функции непосредственно как инструменты; сигнатура функции и docstring автоматически преобразуются в схему:
Пример
# Локальная функция инструмента: docstring становится описанием инструмента, которое видит модель
def get_weather(city: str) -> str:
"""Запросить текущую температуру указанного города
Аргументы:
city: название города
Возвращает:
Описание текущей температуры
"""
temperatures = {"Пекин": "22°C", "Шанхай": "26°C", "Нью-Йорк": "18°C"}
return temperatures.get(city, "Неизвестный город")
messages = [{'role': 'user', 'content': 'Какая сейчас температура в Нью-Йорке?'}]
# Цикл агента: повторять, пока модель больше не запрашивает инструменты
while True:
response = chat(
model='qwen3.5',
messages=messages,
tools=[get_weather],
)
# Добавить сообщение модели (включая tool_calls) в историю
messages.append(response.message)
if not response.message.tool_calls:
# Больше нет запросов к инструментам; вывести окончательный ответ
print(response.message.content)
break
# Есть запросы к инструментам: выполнить их и вернуть результаты с ролью 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,
})
Три инженерных момента: во-первых, каждый response.message должен быть добавлен обратно в messages как есть, а результаты инструментов передаются обратно с ролью tool; во-вторых, при параллельных вызовах инструментов модель может вернуть несколько tool_calls сразу — выполняйте и добавляйте их по одному; в-третьих, в реальных проектах результаты инструментов могут быть очень длинными, поэтому будьте осторожны и обрезайте их, чтобы защитить контекстное окно.
Возможность 7: Веб-поиск
Ollama официально предоставляет два веб-интерфейса, web_search и web_fetch, которые можно подключить как инструменты, чтобы модель могла отвечать на новую информацию за пределами её обучающих данных.
Пример
# Подключить веб-доступ как инструмент
available_tools = {'web_search': web_search, 'web_fetch': web_fetch}
messages = [{'role': 'user', 'content': "Какие новые функции появились у Ollama недавно?"}]
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:
# Результаты инструментов могут быть очень длинными; обрезайте, чтобы защитить контекст
result = str(func(**call.function.arguments))
messages.append({
'role': 'tool',
'tool_name': call.function.name,
'content': result[:2000],
})
Другие расширенияВеб-интерфейсы требуют создания API-ключа на ollama.com; результаты поиска легко могут достигать тысяч токенов, поэтому официальная рекомендация — устанавливать контекст на 32K или выше для таких агентных сценариев. Также есть готовая реализация MCP Server, которая может интегрироваться с такими инструментами, как Cline и Codex; подробности интеграции см. в главе об экосистеме.