Сьогодні ти запустиш справжній штучний інтелект на своєму комп'ютері — без ключів, без оплати, без хмари.
Модель Gemma 2B від Google працюватиме локально через Ollama, а твій
Telegram-бот на aiogram спілкуватиметься з нею. Все — на твоєму ПК.
Ollama (локальний AI)aiogram 3 (async бот)requests (HTTP з Python)LLM (Large Language Model) — це нейромережа, яка навчилась на мільярдах текстів і вміє продовжувати речення. ChatGPT, Claude, Gemini — все це LLM.
Хмарні (ChatGPT, Claude) — великі, розумні, але потрібен інтернет + API-ключ + гроші.
Локальні (Gemma, LLaMA, Mistral) — менші, але працюють на твоєму комп'ютері безкоштовно і без інтернету.
Ollama — це програма, яка завантажує і запускає LLM-моделі локально на твоєму комп'ютері. Вона надає REST API на порті 11434, з яким можна працювати через curl або requests з Python.
https://ollama.com/downloadOllamaSetup.exehttps://ollama.com/download.dmg файл і перетягни Ollama в Applicationscurl -fsSL https://ollama.com/install.sh | sh
Відкрий командний рядок (Windows: Win+R → cmd → Enter) і виконай:
ollama --version
Маєш побачити щось на кшталт:
ollama version is 0.6.x
ollama --version видає помилку — перезавантаж комп'ютер після встановлення.Ollama сама завантажить модель з інтернету. Потрібно зробити це один раз — далі модель зберігається на диску.
У командному рядку виконай:
ollama pull gemma3:1b
Побачиш прогрес завантаження:
pulling manifest
pulling 7cd4618c1faf... 100% ▕████████████████▏ 815 MB
pulling ...
success
ollama list
NAME ID SIZE MODIFIED
gemma3:1b 8648f39daa8f 815 MB Just now
ollama run gemma3:1b
Відкриється чат прямо в терміналі. Напиши щось:
>>> Що таке Python?
Python — це високорівнева мова програмування...
Щоб вийти — напиши /bye або натисни Ctrl+D.
Окрім чату в терміналі, Ollama надає HTTP API — це спосіб відправляти запити програмно (з Python, з бота, з будь-якої програми).
Відкрий у браузері: 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,...}
Створи файл 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Тепер створимо Telegram-бота, через якого будемо спілкуватись з Gemma.
@BotFather/newbotPetro AI Bot)bot (наприклад: petro_ai_2026_bot)7123456789:AAH...Збережи токен — він потрібен на наступному кроці.
Нам потрібні дві бібліотеки:
aiogram — сучасна бібліотека для Telegram Bot API (async)requests — бібліотека для HTTP-запитів (до Ollama)У командному рядку:
pip install aiogram requests
Перевір:
python -c "import aiogram; print(aiogram.__version__)"
# має вивести 3.x.x
async/await — він не блокує бота, поки чекає відповідь від Ollama. Це важливо, бо генерація тексту може тривати 5-20 секунд.Створи файл 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 APIrun_in_executor(None, ...) — запускає синхронну функцію в окремому потоці, щоб бот не «зависав» на 10 секундF.text — фільтр aiogram: обробляємо тільки текстові повідомленняtimeout=120 — чекаємо відповідь до 2 хвилин (на слабких ПК модель може думати довше)wait_msg.delete() — видаляємо повідомлення «Думаю...» після отримання відповідіВажливо: переконайся, що Ollama запущена (іконка в треї). Потім запусти бота:
# Перейди в папку з файлом і запусти:
python ai_bot.py
Маєш побачити:
🚀 Бот запущено! Ctrl+C для зупинки.
/startЩо таке Python?Спробуй різне:
Напиши вірш про програмуванняПоясни як працює інтернетЩо таке рекурсія? Поясни простими словамиНапиши код на Python для калькулятораConnection refused — Ollama не запущена. Запусти її з меню Пуск.Unauthorized — неправильний токен. Перевір, що скопіював повністю.Timeout — модель думає занадто довго. Спробуй коротший промпт.Зупини бота: Ctrl+C в терміналі.
Зараз модель — «загальна». Можна дати їй роль — і вона поводитиметься відповідно.
Додай константу SYSTEM і зміни функцію ask_gemma():
# Системний промпт — «інструкція» для моделі SYSTEM = "Ти — дружній асистент-програміст. Відповідай українською, коротко і зрозуміло. Якщо питають код — давай приклади з коментарями." def ask_gemma(prompt: str) -> str: data = { "model": MODEL, "prompt": prompt, "system": SYSTEM, # ← додали! "stream": False } # ... решта коду така сама
Перезапусти бота і спробуй — модель тепер відповідає «в ролі».
Зараз кожне повідомлення — окремий запит. Модель не пам'ятає, що ти питав раніше. Виправимо!
Додай на початку файлу (після імпортів):
# Словник: історія розмови для кожного користувача 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] = ""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 запитань. Спочатку дай свою відповідь — потім розгорни.
11434. URL: http://localhost:11434/api/generate.localhost — ззовні до неї не достукатись (це правильно для безпеки).
run_in_executor в обробнику повідомлень?ask_gemma() — синхронна функція, яка блокує виконання на 5-20 секунд.run_in_executor запускає її в окремому потоці, щоб головний async-цикл бота не зависав і міг приймати інші повідомлення.
"stream": false у запиті до Ollama?"stream": true — Ollama надсилатиме по одному токену, що корисно для стрімінгу, але складніше парсити.