Мне надоело переключаться между вкладками. ChatGPT в браузере, заметки в одном приложении, напоминалки в другом — и всё это параллельно с Telegram, где и так живёт половина рабочего общения. В какой-то момент я решил: пусть ассистент будет там, где я уже нахожусь.
Это разбор того, как я поднял собственного Telegram-бота с GPT-4 внутри. Без магии, без "три клика и готово" — но и без написания тысяч строк кода. Расскажу что работает, где я споткнулся, и почему готовые решения меня не устроили.
Почему не взял готовое
Готовых ботов с ИИ в Telegram — десятки. @ChatGPT_karfly_bot, @GPT4Telegrambot и ещё куча с похожими названиями. Я пробовал несколько. Работают, отвечают, иногда даже быстро.
Проблема у всех одна: мои запросы, мои контексты и мои данные уходят через чужой сервер. Кому принадлежит этот сервер, что с ним происходит — непонятно. Для бытовых вопросов это, может, и нормально. Для рабочих — нет.
Плюс никакой кастомизации. Хочу чтобы бот знал мой стиль, помнил контекст между сессиями, умел работать с моими заметками — в готовых решениях этого нет, или это платно и всё равно через чужую инфраструктуру.
Что нужно для старта
Список короткий. OpenAI API ключ — регистрируешься на platform.openai.com, пополняешь баланс на 5-10 долларов для начала, этого хватит надолго. Telegram Bot Token — создаётся через @BotFather за две минуты, он же даст имя боту. Python 3.10+ на любой машине или VPS. Из библиотек нужны python-telegram-bot и openai — обе ставятся через pip.
Я запускал сначала локально на MacBook, потом переехал на дешёвый VPS за 3 евро в месяц, чтобы бот работал постоянно, а не только когда у меня открыт ноутбук.
Базовый бот: от нуля до первого ответа
Вот минимальный рабочий код, с которого я начал:
import os
from telegram import Update
from telegram.ext import ApplicationBuilder, MessageHandler, filters, ContextTypes
from openai import OpenAI
client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])
async def handle_message(update: Update, context: ContextTypes.DEFAULT_TYPE):
user_text = update.message.text
response = client.chat.completions.create(
model="gpt-4o",
messages=[
{"role": "system", "content": "Ты — личный ассистент. Отвечаешь коротко и по делу."},
{"role": "user", "content": user_text}
]
)
await update.message.reply_text(response.choices[0].message.content)
app = ApplicationBuilder().token(os.environ["TELEGRAM_BOT_TOKEN"]).build()
app.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, handle_message))
app.run_polling()
Это работает. Но у него нет памяти — каждый запрос изолирован. Спросишь "а что я говорил раньше?" — бот не знает. Именно здесь я потратил час, пытаясь понять почему бот "тупит", пока не дошло что я вообще не передаю историю диалога.
Добавляем память
Фикс простой — храним историю в словаре, где ключ это chat_id:
conversation_history = {}
async def handle_message(update: Update, context: ContextTypes.DEFAULT_TYPE):
chat_id = update.effective_chat.id
user_text = update.message.text
if chat_id not in conversation_history:
conversation_history[chat_id] = [
{"role": "system", "content": "Ты — личный ассистент Зеро. Помнишь контекст разговора, отвечаешь коротко."}
]
conversation_history[chat_id].append({"role": "user", "content": user_text})
response = client.chat.completions.create(
model="gpt-4o",
messages=conversation_history[chat_id]
)
assistant_reply = response.choices[0].message.content
conversation_history[chat_id].append({"role": "assistant", "content": assistant_reply})
await update.message.reply_text(assistant_reply)
Нюанс: история живёт в памяти процесса. Перезапустил бота — всё сбросилось. Для серьёзного использования надо писать историю в файл или базу данных. Я использую простой JSON-файл — не идеально, но для личного бота хватает.
Дело в том, что длинная история — это дорогой запрос. Я ограничил историю последними 20 сообщениями: этого достаточно для связного диалога, и токены не улетают в космос.
Системный промпт — это половина результата
Вот где я реально почувствовал разницу. Первые дни бот отвечал как обычный ChatGPT — вежливо, развёрнуто, с "конечно!" в начале каждой фразы. Меня это раздражало.
Потратил вечер на настройку системного промпта. Вот что работает у меня:
Ты — личный ассистент. Работаешь только со мной.
Отвечай коротко — если можно одним предложением, так и делай.
Не объясняй что ты сейчас сделаешь — просто делай.
Если задача требует списка — делай список. Если нет — не делай.
Когда не знаешь — говори прямо, не выдумывай.
Обращайся ко мне на "ты".
После этого бот стал ощутимо другим. Меньше воды, больше конкретики. GPT очень послушно следует инструкциям, если они чёткие — никакой магии, просто это работает.
Полезные команды, которые я добавил
Чистый диалог — это хорошо, но несколько команд реально упрощают жизнь.
/new сбрасывает историю и начинает чистый разговор. Без этого бот иногда путается, когда переходишь к совсем другой теме.
/remind — простая обёртка, которая форматирует напоминание и отправляет его обратно через N минут через job_queue в python-telegram-bot. Работает локально, без внешних сервисов.
/summarize — скидываешь длинный текст с этой командой, бот делает краткое резюме. Пользуюсь регулярно для статей.
Команды добавляются через CommandHandler — стандартный механизм библиотеки, документация у python-telegram-bot подробная.
Где запускать
Локально на ноутбуке — работает, пока ноутбук включён. Для постоянной работы нужен сервер.
Я взял самый дешёвый VPS у Hetzner — CX11, около 4 евро в месяц. Ubuntu, Python, systemd-сервис для автозапуска — и бот работает круглосуточно. Systemd-конфиг для этого простейший, гуглится за минуту по запросу "systemd python bot service".
На практике есть альтернатива — Railway или Render, там есть бесплатные тиры. Я пробовал Railway: работает, но free tier засыпает если бот неактивен. Для постоянного использования лучше платный VPS.
Что получилось в итоге
Бот живёт у меня уже четыре месяца. Трачу на OpenAI API в среднем 2-3 доллара в месяц — это при довольно активном использовании с GPT-4o. Переключишься на gpt-4o-mini для простых запросов — будет ещё дешевле.
Главное что я получил: контекст не теряется между устройствами, данные не уходят через чужой сервис, и я могу дорабатывать бота под свои задачи. На прошлой неделе добавил команду которая анализирует мои черновики — заняло 20 минут.
Один вечер от нуля до работающего бота. Дальше просто добавляешь то, что нужно именно тебе.
