БэкендData и ИИPython

Как подключить Ollama к Python: локальный чат-бот без платного API

Подключаем Ollama к Python, запускаем локальную модель, добавляем потоковый вывод и историю сообщений, а затем проверяем ошибки соединения и длину контекста.

Кодик

Автор

7 мин чтения

Ollama запускает модель локально, а официальная библиотека ollama даёт Python привычную функцию chat без платного API-ключа. Мы соберём терминальный чат с потоковым ответом, короткой историей и понятной диагностикой. Запросы пойдут в локальный сервис Ollama, а модель можно заменить одной переменной.

Локальный чат удобен для обучения и текста, который не нужно отправлять стороннему API. Но модель занимает память, первый запуск может быть медленным, а качество зависит от размера. Начните с компактного тега, проверьте ollama run и только затем добавляйте Python. Так проще отделить установку, модель и свой код.

1Запускаем модель

Ollama хранит локальный тег и обслуживает запросы на компьютере.

2Подключаем Python

Библиотека ollama передаёт messages локальному сервису.

3Сохраняем диалог

Список ролей даёт модели контекст нескольких последних реплик.

Из каких частей состоит локальный чат

Ollama состоит из локального сервиса и моделей, загруженных отдельными тегами. Команда ollama pull получает файлы модели, ollama list показывает доступные теги, а ollama ps показывает, что сейчас загружено в память. Python-пакет является клиентом: он не содержит веса модели и не запускает магию внутри одного процесса. Функция chat отправляет список messages сервису Ollama. При stream=True ответ приходит небольшими частями, поэтому пользователь видит текст сразу, а программа параллельно собирает полную строку для истории.

СлойКоманда или объектКак проверить
Программа Ollamaollama --versionКоманда находится в PATH
Локальная модельollama pull gemma3:1bТег виден в ollama list
Сервисollama run gemma3:1bМодель отвечает в терминале
Python-клиентuv add ollamaИмпорт проходит без ошибки
Историяlist[dict] с ролямиВторой ответ помнит первый вопрос

Не начинайте диагностику с переустановки Python. Сначала добейтесь ответа через ollama run. Если он есть, сервис и модель работают, а искать ошибку нужно в имени тега, окружении проекта или структуре messages.

Путь локального ответа
Python является клиентом локального сервиса. Полный ответ возвращается в историю

Выбирайте локальный тег осознанно. В примере gemma3:1b выбран как компактная стартовая модель. Проверьте карточку модели и доступную память. Тег с cloud в названии или внешний endpoint меняет предположение о локальной обработке, поэтому не подменяйте его незаметно.

Пишем Python-цикл с потоковым ответом

Установите Ollama с официального сайта, выполните ollama pull gemma3:1b и проверьте ollama run gemma3:1b. Затем создайте проект: uv init local-chat и uv add ollama. Код ниже читает имя модели из переменной OLLAMA_MODEL, поэтому её можно заменить без правки файла. Команды /clear и /exit управляют историей. После каждого ответа в messages остаётся максимум шесть пар, чтобы учебный чат не разрастался бесконечно.

import os

from ollama import ResponseError, chat

MODEL = os.getenv("OLLAMA_MODEL", "gemma3:1b")
MAX_MESSAGES = 12

messages = [{
    "role": "system",
    "content": "Ты учебный помощник. Отвечай кратко и показывай один пример.",
}]

print(f"Локальный чат: {MODEL}")
print("Команды: /clear, /exit")

while True:
    prompt = input("\nВы: ").strip()
    if not prompt:
        continue
    if prompt == "/exit":
        break
    if prompt == "/clear":
        messages = messages[:1]
        print("История очищена")
        continue

    messages.append({"role": "user", "content": prompt})
    chunks: list[str] = []
    print("Бот: ", end="", flush=True)

    try:
        stream = chat(model=MODEL, messages=messages, stream=True)
        for part in stream:
            text = part.message.content or ""
            print(text, end="", flush=True)
            chunks.append(text)
        print()
    except ConnectionError:
        print("\nOllama не отвечает. Запустите приложение или сервис.")
        messages.pop()
        continue
    except ResponseError as error:
        print(f"\nОшибка Ollama: {error}")
        messages.pop()
        continue

    answer = "".join(chunks)
    messages.append({"role": "assistant", "content": answer})
    messages = messages[:1] + messages[-MAX_MESSAGES:]
Что должно произойти после запуска
  • Текст появляется частями, а не после ожидания всего ответа.
  • Второй вопрос может ссылаться на предыдущую реплику благодаря messages.
  • Команда /clear удаляет диалог, но сохраняет системную инструкцию.
  • Если сервис не запущен или тег модели неверен, чат показывает понятное сообщение.

Поток и обычный ответ
Смысл одинаков, ощущение разное. В истории оба режима дают одно сообщение assistant

Как messages превращается в продолжение разговора

Каждое сообщение имеет роль. system задаёт постоянную инструкцию, user хранит вопросы, assistant хранит полные ответы. Ollama читает весь переданный список при каждом новом запросе. Потоковые chunks нужны только для интерфейса: в историю добавляется одна склеенная строка, иначе диалог превратится в сотни мелких сообщений. Ограничение MAX_MESSAGES оставляет системное сообщение и последние реплики. Это простая стратегия окна, а не долгосрочная память. После /clear модель ничего не знает о предыдущем диалоге, потому что список был очищен.

Роль или режимНазначениеТипичная ошибка
systemПравила помощникаДобавляется заново после каждого ответа
userТекущий вопросНе удаляется после сбоя запроса
assistantПолный ответВ историю кладут каждый chunk отдельно
stream=TrueПоказывает ответ постепенноChunks печатают, но не склеивают
MAX_MESSAGESОграничивает рост контекстаСлучайно удаляет system

На скорость влияют размер модели, RAM или VRAM, история и длина ответа. Сравнивайте одинаковый промпт после прогрева и смотрите ollama ps. Если система использует диск, выберите меньшую модель или сократите контекст. ConnectionError указывает на сервис, ResponseError на модель или запрос, ошибка импорта на Python-окружение.

Проверьте путь данных. Если проект должен оставаться локальным, используйте локальный host по умолчанию, локальный тег модели и не подключайте внешние инструменты без необходимости. Не помещайте секреты в промпт только потому, что базовый пример работает на вашем компьютере.

Проверяем скорость, память и ошибки соединения

Запустите чат и задайте вопрос про список Python. Следом напишите «покажи ещё один пример» и убедитесь, что модель понимает ссылку. Выполните /clear и повторите второй вопрос: теперь контекста быть не должно. Остановите сервис Ollama и проверьте сообщение ConnectionError. Затем задайте OLLAMA_MODEL на отсутствующий тег и посмотрите ResponseError. Наконец, верните рабочую модель, задайте пять пар вопросов и выведите len(messages), чтобы увидеть работу ограничения истории.

Проверка своими руками
  1. Проверьте модель сначала через ollama run gemma3:1b.
  2. Запустите Python-чат и задайте два связанных вопроса.
  3. Очистите историю и убедитесь, что ссылка на старый вопрос потерялась.
  4. Остановите Ollama и получите контролируемое сообщение о соединении.
  5. Укажите неверный тег модели и отделите ResponseError от ConnectionError.
  6. Смените MAX_MESSAGES на 4 и проследите длину списка после нескольких ответов.
Готово, если выполняются все пункты
  • Модель отвечает через Python без API-ключа.
  • Поток собирается в один assistant message.
  • История ограничена и очищается командой.
  • Ошибки сервиса и модели различаются в выводе.

Диагностика локального чата
Каждый сбой проверяется на своём слое. Не переустанавливайте всё сразу

Превращаем демо в аккуратный локальный инструмент

Чат можно перенести в Streamlit, добавить выбор модели или сохранить JSON. Улучшайте по одному. Для документов показывайте фрагменты контекста, для tools журналируйте имя и аргументы. Не храните общую messages для нескольких пользователей, каждому нужна сессия. Локальная модель тоже ошибается, поэтому факты, команды и код проверяйте.

Как изучить тему в Кодике

В Кодике начните с цикла while, списков и словарей Python. Затем научитесь ловить конкретные исключения и читать переменные окружения. Только после этого подключайте Ollama. Тогда messages будет обычным списком словарей, streaming станет циклом for, а управление командами окажется знакомым набором if.

ШагЧто изучитьМини-проект
1while, input и командыЭхо-чат с /clear и /exit
2Списки и словариХранить роли и тексты без модели
3ИсключенияРазличать два вида сбоя
4Итераторы и потокСклеить chunks в строку
5Ollama PythonПолучить связанный диалог

В тренажёре Кодика сначала реализуйте команды и обрезку истории на фиктивных строках. Затем замените генератор ответов одним вызовом chat. Такой порядок отделяет Python-логику от требований модели и сильно упрощает отладку.

Python запускают до проверки ollama run

Сначала отделите установку сервиса и модели от собственного кода.

В messages добавляют каждый chunk

Печатайте части сразу, но храните один собранный assistant answer.

История растёт без границы

Оставляйте системное сообщение и ограниченное число последних реплик.

Любая ошибка скрывается общим except

Различайте недоступный сервис, ошибку модели и проблему окружения Python.

Сверьтесь с первичным источником. Команды, API и ограничения примера проверяйте по официальной библиотеке Ollama Python. Если интерфейс или версия изменились, первичная документация важнее скриншота из старой инструкции.

Что получится в итоге

Готовый результат: Как подключить Ollama к Python: локальный чат-бот без платного API
Терминальный чат показывает ответ по мере генерации, помнит несколько последних реплик и остаётся управляемым при сбое сервиса или смене модели.

Короткие ответы
Нужен ли платный API-ключ для локального Ollama?

Нет, если используется локальный сервис и локально загруженный тег модели.

Почему chunks нужно склеивать?

Поток удобен для показа, но история должна содержать один полный ответ ассистента.

Является ли messages постоянной памятью?

Нет. Это контекст конкретного запуска. После очистки или завершения программы список исчезает, если вы его отдельно не сохранили.

Как понять, что проект действительно работает?

Проверьте основной сценарий, ошибочный ввод, повторный запуск и один граничный случай. Затем объясните вслух, где появляются данные, кто принимает решение и где хранится состояние.

Можно ли начать с готового кода из статьи?

Да. После первого запуска измените один параметр, добавьте одну проверку и повторите проект без подсказки. Так пример превращается в собственный навык.

Сделайте локальную модель частью понятной Python-программы

Циклы, списки и исключения закрепите в курсе Python. Установку и выбор модели сверяйте со статьями про запуск Ollama и про выбор модели по памяти.

Когда терминальный цикл станет понятным, соберите интерфейс из статьи про Streamlit-приложение. В Кодике сначала воспроизведите работу messages на обычных строках, затем подключите модель.