Полтора месяца назад я заметил, что отвечаю на одни и те же вопросы в чатах по кругу. Одни и те же ссылки, одни и те же объяснения, одни и те же «да, вот тут почитай». Раздражало не количество — раздражало ощущение, что я трачу голову на то, что давно уже знаю.
Тогда я решил сделать себе бота, который знает мой контекст и отвечает вместо меня там, где мне нечего добавить. Что из этого вышло — расскажу.
Почему не готовые решения
Первый порыв был предсказуемый: поискать что-то готовое. Нашёл пару ботов в магазинах — один просил подписку за 15 долларов в месяц и при этом не умел помнить контекст разговора дольше одного сообщения, второй оказался просто обёрткой над ChatGPT без каких-либо настроек. Потратил на это вечер и понял: проще сделать своё.
Технически порог входа здесь невысокий. Нужен Python, аккаунт в Telegram и API-ключ от любой языковой модели. Я взял OpenAI, но с тем же успехом можно использовать Anthropic или открытые модели через OpenRouter — интерфейс у всех похожий.
Как это собирается
Начал с регистрации бота через BotFather — это стандартный шаг, занимает три минуты. Пишешь /newbot, придумываешь имя, получаешь токен. Токен сохраняешь в переменную окружения, не в код. Я усвоил это после того, как однажды случайно запушил ключ на GitHub и полчаса его отзывал.
Дальше — библиотека python-telegram-bot. Она берёт на себя всю работу с Telegram API: получение сообщений, отправку ответов, обработку команд. Базовый скелет выглядит примерно так:
from telegram.ext import Application, MessageHandler, filters
async def handle_message(update, context):
user_text = update.message.text
reply = ask_llm(user_text)
await update.message.reply_text(reply)
app = Application.builder().token(TELEGRAM_TOKEN).build()
app.add_handler(MessageHandler(filters.TEXT, handle_message))
app.run_polling()
Функция ask_llm — это уже обращение к OpenAI или другому провайдеру. Стандартный вызов через openai.chat.completions.create с нужной моделью.
На этом этапе бот уже работает. Но это просто эхо с интеллектом — он не помнит, что ты ему говорил минуту назад.
Память — самое важное
Без памяти бот бесполезен для личного использования. Каждое сообщение для него — первое знакомство. Это ломает любой нормальный диалог.
Простейшее решение — хранить историю сообщений в словаре по chat_id. Что-то вроде:
conversation_history = {}
def ask_llm(chat_id, user_text):
if chat_id not in conversation_history:
conversation_history[chat_id] = [
{"role": "system", "content": SYSTEM_PROMPT}
]
conversation_history[chat_id].append(
{"role": "user", "content": user_text}
)
response = openai.chat.completions.create(
model="gpt-4o",
messages=conversation_history[chat_id]
)
reply = response.choices[0].message.content
conversation_history[chat_id].append(
{"role": "assistant", "content": reply}
)
return reply
Проблема — история растёт бесконечно и в какой-то момент вылетает за лимит токенов. Я решил это грубо: обрезаю историю до последних 20 сообщений, но всегда оставляю системный промпт первым. Не элегантно, но работает.
Если нужно что-то серьёзнее — можно подключить SQLite или Redis и хранить историю там. Тогда бот не теряет память при перезапуске.
Системный промпт решает всё
Вот тут я провёл больше всего времени. Технически бот был готов за вечер, но ещё неделю я переписывал системный промпт — потому что без него это был просто ChatGPT в Telegram, ничего личного.
Мой промпт описывает несколько вещей. Во-первых, контекст: чем я занимаюсь, какие темы для меня важны, какой стиль общения мне близок. Во-вторых, ограничения: что бот не должен придумывать, если не знает — лучше честно сказать. В-третьих, поведение в конкретных ситуациях — например, если спрашивают про технические инструменты, давать конкретные примеры, а не теоретические обзоры.
Несколько итераций я убил на то, что промпт был слишком длинным и расплывчатым. Потом сократил раза в три — и стало заметно лучше. Модель не теряется в инструкциях, когда их меньше.
Хорошо работает приём с примерами прямо в промпте. Не «отвечай кратко», а «вот пример хорошего ответа: ...». Разница ощутимая.
Где это живёт
Запускать бота локально — плохая идея. Закроешь ноутбук — и бот недоступен. Я поднял его на маленьком VPS за 5 долларов в месяц. Там Ubuntu, Python, и бот запущен через systemd как сервис — стартует при загрузке, перезапускается при падении.
Альтернатива — Railway или Render, там можно задеплоить за 10 минут без настройки сервера. Для старта вполне годится. Я переехал на VPS позже, когда мне захотелось больше контроля.
Важный момент: переменные окружения. Токен Telegram, ключ OpenAI — всё это живёт в .env файле и никогда не попадает в репозиторий. Звучит очевидно, но я видел достаточно утёкших ключей на GitHub, чтобы повторять это каждый раз.
Что получилось
Бот работает у меня уже полтора месяца. Использую его для нескольких вещей: быстрые вопросы по коду, когда не хочу переключаться на браузер; черновики сообщений, когда нужно сформулировать что-то аккуратно; иногда просто чтобы подумать вслух и получить структурированный ответ.
Самое неожиданное — насколько важен именно личный контекст в промпте. Тот же GPT-4 через обычный интерфейс отвечает иначе, потому что не знает, кто я и зачем спрашиваю. Бот знает — и это меняет качество ответов ощутимо.
Что не работает: бот плохо справляется с задачами, где нужна актуальная информация. Он не лезет в интернет, не знает, что было вчера. Для этого придётся добавлять инструменты — это уже следующий уровень сложности, до которого я пока не дошёл.
Если хочется попробовать — порог входа реально небольшой. День работы, и базовая версия будет готова. Дальше можно докручивать под себя сколько угодно.
