ПРОГРЕС:
0%

Урок 12 AI-БОТ

Сьогодні ти запустиш справжній штучний інтелект на своєму комп'ютері — без ключів, без оплати, без хмари. Модель Gemma 2B від Google працюватиме локально через Ollama, а твій Telegram-бот на aiogram спілкуватиметься з нею. Все — на твоєму ПК.

🧰 Що потрібно мати

00

Що таке LLM і як вона працює

Теорія за 3 хвилини
теорія

LLM (Large Language Model) — це нейромережа, яка навчилась на мільярдах текстів і вміє продовжувати речення. ChatGPT, Claude, Gemini — все це LLM.

Як LLM генерує відповідь?

  1. Ти пишеш промпт (запит) — наприклад: «Що таке Linux?»
  2. Модель розбиває текст на токени (шматочки слів)
  3. Для кожного наступного токена вона рахує ймовірність — який найбільш вірогідний?
  4. Обраний токен додається до відповіді, і цикл повторюється
Промпт: "Що таке Linux?" ↓ [Токенізація] → ["Що", " таке", " Linux", "?"] ↓ [Нейромережа] → P("Linux" | ...) = 0.3, P("це" | ...) = 0.6, ... ↓ Вивід: "Linux — це операційна система..." (токен за токеном)

Хмарні vs Локальні моделі

Хмарні (ChatGPT, Claude) — великі, розумні, але потрібен інтернет + API-ключ + гроші.

Локальні (Gemma, LLaMA, Mistral) — менші, але працюють на твоєму комп'ютері безкоштовно і без інтернету.

💡 Gemma 2B — модель від Google з 2 мільярдами параметрів. Вона досить компактна (займає ~1.5 ГБ RAM), і при цьому непогано відповідає на запитання.

Що таке Ollama?

Ollama — це програма, яка завантажує і запускає LLM-моделі локально на твоєму комп'ютері. Вона надає REST API на порті 11434, з яким можна працювати через curl або requests з Python.

Архітектура нашого бота: TelegramБот (aiogram)Ollama API (:11434)Gemma 2B хмара Python на ПК localhost модель в RAM твій комп'ютер
01

Встановлюємо Ollama

Завантажуємо і ставимо на свій ПК
інсталяція

Windows

  1. Відкрий https://ollama.com/download
  2. Натисни Download for Windows
  3. Запусти завантажений OllamaSetup.exe
  4. Натисни Install → дочекайся завершення

Mac

  1. Відкрий https://ollama.com/download
  2. Натисни Download for macOS
  3. Відкрий .dmg файл і перетягни Ollama в Applications
  4. Запусти Ollama з Launchpad

Linux

curl -fsSL https://ollama.com/install.sh | sh

Перевірка: чи працює?

Відкрий командний рядок (Windows: Win+Rcmd → Enter) і виконай:

ollama --version

Маєш побачити щось на кшталт:

ollama version is 0.6.x
💡 На Windows Ollama працює як фоновий процес — ти побачиш іконку лами в системному треї (біля годинника). Якщо іконки нема — запусти Ollama з меню Пуск.
⚠️ Якщо ollama --version видає помилку — перезавантаж комп'ютер після встановлення.
02

Завантажуємо модель Gemma

Перше завантаження — ~815 МБ
модель

Ollama сама завантажить модель з інтернету. Потрібно зробити це один раз — далі модель зберігається на диску.

У командному рядку виконай:

ollama pull gemma3:1b

Побачиш прогрес завантаження:

pulling manifest
pulling 7cd4618c1faf... 100% ▕████████████████▏ 815 MB
pulling ...
success
⚠️ Завантаження ~815 МБ — залежно від швидкості інтернету може зайняти 2-10 хвилин. Будь терплячим!

Перевірка: які моделі є?

ollama list
NAME         ID              SIZE      MODIFIED
gemma3:1b    8648f39daa8f    815 MB    Just now

Тест: поговоримо з AI в терміналі!

ollama run gemma3:1b

Відкриється чат прямо в терміналі. Напиши щось:

>>> Що таке Python?
Python — це високорівнева мова програмування...

Щоб вийти — напиши /bye або натисни Ctrl+D.

💡 Ти щойно запустив AI на своєму комп'ютері! Він працює без інтернету (після завантаження моделі), без реєстрації, без оплати.
03

Ollama API: спілкуємось через HTTP

REST API на localhost:11434
API

Окрім чату в терміналі, Ollama надає HTTP API — це спосіб відправляти запити програмно (з Python, з бота, з будь-якої програми).

Тест через curl (або браузер)

Відкрий у браузері: http://localhost:11434 — маєш побачити текст "Ollama is running".

Тепер відправимо запит до моделі. У командному рядку:

# Windows (cmd):
curl -s http://localhost:11434/api/generate -d "{\"model\":\"gemma3:1b\",\"prompt\":\"Скажи привіт!\",\"stream\":false}"

Отримаєш JSON-відповідь з полем "response":

{"model":"gemma3:1b","response":"Привіт! 👋 Як справи?","done":true,...}

Тест через Python

Створи файл test_llm.py (у будь-якій папці, наприклад на Робочому столі):

import requests

URL = "http://localhost:11434/api/generate"

data = {
    "model": "gemma3:1b",
    "prompt": "Розкажи коротко: що таке Python?",
    "stream": False
}

print("⏳ Питаю модель...")
resp = requests.post(URL, json=data)
result = resp.json()

print("🤖 Відповідь:")
print(result["response"])

Запусти:

python test_llm.py
⏳ Питаю модель...
🤖 Відповідь:
Python — це мова програмування високого рівня...
💡 requests.post(URL, json=data) — відправляє POST-запит з JSON-тілом. Це те саме, що curl, але зручніше. Метод .json() автоматично парсить відповідь у словник Python.
⚠️ Якщо бачиш ModuleNotFoundError: No module named 'requests' — встанови: pip install requests
04

Створюємо Telegram-бота

BotFather + токен
telegram

Тепер створимо Telegram-бота, через якого будемо спілкуватись з Gemma.

Крок за кроком

  1. Відкрий Telegram і знайди @BotFather
  2. Напиши /newbot
  3. Введи назву бота (наприклад: Petro AI Bot)
  4. Введи username — має закінчуватись на bot (наприклад: petro_ai_2026_bot)
  5. BotFather дасть тобі токен — рядок виду 7123456789:AAH...
⚠️ Токен — це пароль бота! Не публікуй його в чатах, не комітай в git, не показуй на скріншотах. Хто має токен — той керує ботом.

Збережи токен — він потрібен на наступному кроці.

05

Встановлюємо бібліотеки

pip install aiogram requests
pip

Нам потрібні дві бібліотеки:

  • aiogram — сучасна бібліотека для Telegram Bot API (async)
  • requests — бібліотека для HTTP-запитів (до Ollama)

У командному рядку:

pip install aiogram requests

Перевір:

python -c "import aiogram; print(aiogram.__version__)"
# має вивести 3.x.x
💡 Чому aiogram, а не python-telegram-bot? aiogram використовує async/await — він не блокує бота, поки чекає відповідь від Ollama. Це важливо, бо генерація тексту може тривати 5-20 секунд.
06

Пишемо бота: Telegram + Gemma

Головний код проєкту
код

Створи файл ai_bot.py (наприклад, у папці на Робочому столі). Вставь весь код нижче. Читай коментарі!

import asyncio
import requests
from aiogram import Bot, Dispatcher, F
from aiogram.types import Message

# ═══════════════════════════════════════════════
# НАЛАШТУВАННЯ — заміни TOKEN на свій!
# ═══════════════════════════════════════════════
TOKEN = "СЮДИ_ВСТАВ_СВІЙ_ТОКЕН"       # від BotFather
OLLAMA_URL = "http://localhost:11434/api/generate"
MODEL = "gemma3:1b"

# Створюємо бота і диспетчер
bot = Bot(token=TOKEN)
dp = Dispatcher()

# ═══════════════════════════════════════════════
# Функція: запит до Ollama
# ═══════════════════════════════════════════════
def ask_gemma(prompt: str) -> str:
    """Відправляє промпт до Gemma і повертає відповідь."""
    data = {
        "model": MODEL,
        "prompt": prompt,
        "stream": False
    }
    try:
        resp = requests.post(OLLAMA_URL, json=data, timeout=120)
        result = resp.json()
        return result.get("response", "(модель не відповіла)")
    except Exception as e:
        return f"❌ Помилка: {e}"

# ═══════════════════════════════════════════════
# Команда /start
# ═══════════════════════════════════════════════
@dp.message(F.text == "/start")
async def cmd_start(msg: Message):
    await msg.answer(
        "🤖 Привіт! Я AI-бот з моделлю Gemma.\n"
        "Напиши мені будь-що — і я відповім!\n\n"
        "Модель працює локально на комп'ютері — "
        "без хмари, без оплати, без реєстрації."
    )

# ═══════════════════════════════════════════════
# Обробник текстових повідомлень
# ═══════════════════════════════════════════════
@dp.message(F.text)
async def handle_message(msg: Message):
    # Показуємо "друкує..." поки модель думає
    wait_msg = await msg.answer("⏳ Думаю...")

    # Запускаємо ask_gemma в окремому потоці,
    # щоб не блокувати бота
    loop = asyncio.get_event_loop()
    response = await loop.run_in_executor(
        None, ask_gemma, msg.text
    )

    # Обрізаємо до 4000 символів (ліміт Telegram)
    if len(response) > 4000:
        response = response[:4000] + "..."

    # Видаляємо "⏳ Думаю..." і відправляємо відповідь
    await wait_msg.delete()
    await msg.answer(response)

# ═══════════════════════════════════════════════
# Запуск
# ═══════════════════════════════════════════════
async def main():
    print("🚀 Бот запущено! Ctrl+C для зупинки.")
    await dp.start_polling(bot)

if __name__ == "__main__":
    asyncio.run(main())
⚠️ Не забудь замінити СЮДИ_ВСТАВ_СВІЙ_ТОКЕН на справжній токен від BotFather!

Розбір ключових моментів

  • ask_gemma() — звичайна функція, яка робить HTTP POST-запит до Ollama API
  • run_in_executor(None, ...) — запускає синхронну функцію в окремому потоці, щоб бот не «зависав» на 10 секунд
  • F.text — фільтр aiogram: обробляємо тільки текстові повідомлення
  • timeout=120 — чекаємо відповідь до 2 хвилин (на слабких ПК модель може думати довше)
  • wait_msg.delete() — видаляємо повідомлення «Думаю...» після отримання відповіді
07

Запускаємо і тестуємо!

Твій перший AI-бот
тест

Важливо: переконайся, що Ollama запущена (іконка в треї). Потім запусти бота:

# Перейди в папку з файлом і запусти:
python ai_bot.py

Маєш побачити:

🚀 Бот запущено! Ctrl+C для зупинки.

Тестуємо в Telegram

  1. Знайди свого бота в Telegram за username
  2. Натисни Start або напиши /start
  3. Напиши: Що таке Python?
  4. Зачекай 5-20 секунд — бот відповість!

Спробуй різне:

  • Напиши вірш про програмування
  • Поясни як працює інтернет
  • Що таке рекурсія? Поясни простими словами
  • Напиши код на Python для калькулятора
💡 Швидкість відповіді залежить від твого комп'ютера. На ПК з 8 ГБ RAM — 10-20 секунд. З 16 ГБ — 5-10 секунд. Якщо є відеокарта NVIDIA — ще швидше!
⚠️ Типові помилки:
Connection refused — Ollama не запущена. Запусти її з меню Пуск.
Unauthorized — неправильний токен. Перевір, що скопіював повністю.
Timeout — модель думає занадто довго. Спробуй коротший промпт.

Зупини бота: Ctrl+C в терміналі.

★1

Бонус: системний промпт

Даємо моделі «характер»
бонус

Зараз модель — «загальна». Можна дати їй роль — і вона поводитиметься відповідно.

Додай константу SYSTEM і зміни функцію ask_gemma():

# Системний промпт — «інструкція» для моделі
SYSTEM = "Ти — дружній асистент-програміст. Відповідай українською, коротко і зрозуміло. Якщо питають код — давай приклади з коментарями."

def ask_gemma(prompt: str) -> str:
    data = {
        "model": MODEL,
        "prompt": prompt,
        "system": SYSTEM,      # ← додали!
        "stream": False
    }
    # ... решта коду така сама

Перезапусти бота і спробуй — модель тепер відповідає «в ролі».

💡 Ідеї для промптів:
«Ти — пірат, який відповідає піратським сленгом»
«Ти — вчитель фізики для 5 класу»
«Ти — саркастичний робот з майбутнього»
«Ти — кухар, який все пояснює через аналогії з їжею»
★2

Бонус: пам'ять діалогу

Модель запам'ятовує контекст розмови
бонус

Зараз кожне повідомлення — окремий запит. Модель не пам'ятає, що ти питав раніше. Виправимо!

Додай на початку файлу (після імпортів):

# Словник: історія розмови для кожного користувача
chat_history = {}   # {user_id: "текст діалогу"}
MAX_HISTORY = 2000  # максимум символів (щоб не перевантажити модель)

Зміни обробник повідомлень:

@dp.message(F.text)
async def handle_message(msg: Message):
    user_id = msg.from_user.id
    wait_msg = await msg.answer("⏳ Думаю...")

    # Отримуємо або створюємо історію
    history = chat_history.get(user_id, "")

    # Додаємо нове повідомлення
    history += f"\nКористувач: {msg.text}"

    # Обрізаємо якщо занадто довга
    if len(history) > MAX_HISTORY:
        history = history[-MAX_HISTORY:]

    # Формуємо промпт з контекстом
    full_prompt = history + "\nАсистент:"

    loop = asyncio.get_event_loop()
    response = await loop.run_in_executor(
        None, ask_gemma, full_prompt
    )

    # Зберігаємо відповідь в історію
    history += f"\nАсистент: {response}"
    chat_history[user_id] = history

    if len(response) > 4000:
        response = response[:4000] + "..."

    await wait_msg.delete()
    await msg.answer(response)

Тепер бот пам'ятає контекст! Спробуй:

Ти: Мене звати Петро
Бот: Привіт, Петро! ...
Ти: Як мене звати?
Бот: Тебе звати Петро! ✓
💡 Додаткове завдання: додай команду /clear, яка очищує історію: chat_history[user_id] = ""
★3

Бонус: спробуй інші моделі

Ollama підтримує десятки моделей
бонус

Gemma 2B — не єдина модель. Спробуй інші (якщо вистачає RAM):

# Маленька і швидка (потрібно ~2 ГБ RAM)
ollama pull qwen2.5:1.5b

# Розумніша, але повільніша (потрібно ~5 ГБ RAM)
ollama pull gemma3:4b

# Кодер — спеціалізована на написанні коду
ollama pull qwen2.5-coder:1.5b

Щоб переключити модель у боті — просто зміни константу:

MODEL = "qwen2.5:1.5b"    # або будь-яку іншу

Повний каталог моделей: https://ollama.com/library

💡 Кожна модель має свої сильні сторони: одні краще пишуть код, інші — краще відповідають українською, треті — краще в математиці. Експериментуй!

🎯 Самоперевірка

5 запитань. Спочатку дай свою відповідь — потім розгорни.

1. Чим локальна LLM відрізняється від ChatGPT?
Локальна LLM працює на твоєму комп'ютері — безкоштовно, без інтернету (після завантаження), без API-ключа. Але менша і повільніша.
ChatGPT працює на серверах OpenAI — потрібен інтернет, акаунт, часто оплата. Зате модель набагато більша і швидша.
2. На якому порті працює Ollama API?
Порт 11434. URL: http://localhost:11434/api/generate.
Ollama слухає на localhost — ззовні до неї не достукатись (це правильно для безпеки).
3. Навіщо run_in_executor в обробнику повідомлень?
ask_gemma()синхронна функція, яка блокує виконання на 5-20 секунд.
run_in_executor запускає її в окремому потоці, щоб головний async-цикл бота не зависав і міг приймати інші повідомлення.
4. Що робить "stream": false у запиті до Ollama?
Каже Ollama повернути всю відповідь одразу одним JSON-об'єктом.
Якщо "stream": true — Ollama надсилатиме по одному токену, що корисно для стрімінгу, але складніше парсити.
5. Чому відповідь обрізається до 4000 символів?
Telegram має ліміт 4096 символів на повідомлення.
Якщо спробувати відправити більше — API поверне помилку. Тому обрізаємо з запасом до 4000.