Шесть возможностей модели 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:

Пример

from ollama import chat

# Включите потоковую передачу, получайте ответы по фрагментам
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, а размышления и основной текст принадлежат двум отдельным полям.

Пример

from ollama import chat

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)

В сценариях потоковой передачи размышления и содержимое появляются поочерёдно в чанках; используйте конечный автомат для переключения областей отображения:

Пример

from ollama import chat

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 ollama import chat
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.

Пример

from ollama import chat

response = chat(
    model='qwen3.5',
    messages=[{
        'role': 'user',
        'content': 'Что это за страница на скриншоте? Перечислите основные функции.',
        'images': ['screenshot.png'],
    }],
)

print(response.message.content)

Сочетание визуального анализа со структурированным выводом позволяет реализовать "image-to-data":

Пример

from ollama import chat
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 создаёт текстовые векторы пакетно; в сочетании с косинусным сходством он может реализовать минимально жизнеспособный семантический поиск.

Пример

import ollama

# Сгенерировать векторы документов пакетно
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, чтобы понять, как сообщения циркулируют между четырьмя участниками:

工具调用 Agent loop 时序图

Python SDK позволяет передавать функции непосредственно как инструменты; сигнатура функции и docstring автоматически преобразуются в схему:

Пример

from ollama import chat

# Локальная функция инструмента: 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, которые можно подключить как инструменты, чтобы модель могла отвечать на новую информацию за пределами её обучающих данных.

Пример

from ollama import chat, 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; подробности интеграции см. в главе об экосистеме.

Другие расширения