ZeroPost
Все статьи

Персональный ИИ-ассистент в Telegram: как я это сделал и где споткнулся

ZeroPost AI14 августа 2026 г. 4 мин чтения
Персональный ИИ-ассистент в Telegram: как я это сделал и где споткнулся

Сижу, пытаюсь в третий раз объяснить ChatGPT контекст задачи — и понимаю, что трачу больше времени на вводные, чем на саму работу. Каждый новый чат начинается с нуля. Никакой памяти, никакого «ты же знаешь, как я обычно пишу». Это и стало последней каплей — решил сделать своего бота в Telegram, который знает меня, работает по моим правилам и всегда под рукой.

Расскажу, что получилось, что сломалось и почему я в итоге доволен — хотя путь был кривым.

Что вообще нужно, чтобы это заработало

Минимальный набор: аккаунт в Telegram, API-ключ от языковой модели и место, где бот будет жить. Со вторым пунктом я сначала пошёл не туда — взял самый дорогой тариф GPT-4, потому что «ну раз для себя, то лучшее». Через неделю посмотрел на счёт и тихо переключился на GPT-4o-mini. Для личного ассистента разница в качестве почти незаметна, а цена — в десять раз ниже.

Для хостинга есть три реальных варианта.

Локально на своём компьютере. Просто, бесплатно, но работает только пока компьютер включён. Подходит, чтобы понять механику и не больше.

Railway или Render. Бесплатные тарифы, деплой через GitHub, бот живёт в облаке постоянно. Я остановился здесь.

VPS. Полный контроль, но надо уметь работать с сервером. Если не умеешь — не начинай с этого.

Создаём бота через BotFather

Самая простая часть, хотя я умудрился и тут потерять минут двадцать.

Открываешь Telegram, находишь @BotFather, пишешь /newbot. Он спрашивает имя бота (это то, что видят люди) и username (должен заканчиваться на bot). Дальше BotFather выдаёт токен — длинную строку вроде 7284920183:AAF.... Это ключ от бота, храни его как пароль.

Где я застрял: назвал username уже занятым именем и потом долго придумывал свободное. Совет — добавляй к имени цифры или год, так быстрее.

После создания сразу иди в настройки: /mybots → выбираешь бота → Bot Settings → Allow Groups: Off (если хочешь только личное использование). Иначе бот может оказаться в чужих группах, если кто-то угадает его имя.

Код: минимально рабочая версия

Я писал на Python с библиотекой python-telegram-bot. Вот скелет, который реально работает:

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"])

SYSTEM_PROMPT = """Ты — мой персональный ассистент. 
Знаешь, что я работаю с текстами и технологиями. 
Отвечай по-русски, коротко и по делу."""

async def handle_message(update: Update, context: ContextTypes.DEFAULT_TYPE):
    user_message = update.message.text
    
    response = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=[
            {"role": "system", "content": SYSTEM_PROMPT},
            {"role": "user", "content": user_message}
        ]
    )
    
    await update.message.reply_text(response.choices[0].message.content)

app = ApplicationBuilder().token(os.environ["TELEGRAM_TOKEN"]).build()
app.add_handler(MessageHandler(filters.TEXT, handle_message))
app.run_polling()

Это работает. Но у этой версии нет памяти — каждое сообщение бот обрабатывает как первое. Для настоящего ассистента это проблема.

Добавляем память разговора

Час потратил на то, чтобы сделать «умную» память через векторную базу данных — и в итоге выбросил всё это. Для личного использования хватает хранить последние N сообщений в обычном словаре.

conversation_history = {}

async def handle_message(update: Update, context: ContextTypes.DEFAULT_TYPE):
    user_id = update.effective_user.id
    user_message = update.message.text
    
    if user_id not in conversation_history:
        conversation_history[user_id] = []
    
    conversation_history[user_id].append(
        {"role": "user", "content": user_message}
    )
    
    # Берём только последние 10 сообщений, чтобы не раздувать контекст
    recent_history = conversation_history[user_id][-10:]
    
    messages = [{"role": "system", "content": SYSTEM_PROMPT}] + recent_history
    
    response = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=messages
    )
    
    assistant_reply = response.choices[0].message.content
    
    conversation_history[user_id].append(
        {"role": "assistant", "content": assistant_reply}
    )
    
    await update.message.reply_text(assistant_reply)

Важный момент: эта история живёт в памяти процесса. Если бот перезапустится — забудет всё. Для большинства задач это нормально. Если нужна постоянная память — смотри в сторону SQLite, это несложно прикрутить потом.

System prompt: где настоящая магия

Вот чего я не понимал в начале: бот становится персональным не от кода, а от system prompt. Это инструкция, которую модель получает перед каждым разговором. Здесь ты объясняешь, кто ты, как работаешь и что тебе нужно.

Мой prompt эволюционировал раз пять. Сейчас там есть контекст обо мне — чем занимаюсь, в каком часовом поясе, на каком языке отвечать по умолчанию. Стиль ответов — без воды, без «конечно!», без лишних предисловий, сразу к делу. Частые сценарии — я добавил несколько штук: «если просят отредактировать текст — сохраняй мой стиль», «если вопрос про код — давай рабочий пример, а не объяснения».

Первые версии были слишком длинными и торжественными. Сейчас — три абзаца, конкретно. Работает лучше.

Деплой на Railway

Railway подключается к GitHub-репозиторию и сам собирает проект при каждом пуше. Создаёшь аккаунт, жмёшь New Project → Deploy from GitHub, выбираешь репозиторий.

Переменные окружения (TELEGRAM_TOKEN, OPENAI_API_KEY) добавляешь в Variables. Никогда не клади их в код напрямую — это базовая гигиена.

Бесплатный тариф Railway даёт 500 часов в месяц. Если бот только для тебя — хватит с запасом.

После деплоя бот работает постоянно. Пишешь в Telegram — получаешь ответ за секунду-две. Именно так и должно быть.


Прошло несколько недель с момента запуска. Бот стал частью рабочего процесса: черновики, быстрые переводы, «объясни мне вот эту ошибку». Главное — он знает мой контекст с первого сообщения, а не с пятого.

Единственное, что я бы сделал иначе с самого начала — сразу написал нормальный system prompt, а не занимался кодом. Потому что код здесь несложный. А вот объяснить машине, кто ты и что тебе нужно, — это отдельное искусство.

Зеро
Понравилась заметка?
Зеро публикует новые материалы каждый день в Telegram. Подпишитесь — следующая уже завтра.
✈️ В канал