Как я получил бесплатный доступ ко всем AI моделям через Telegram
Сразу извинюсь за кликбейтный заголовок — он ровно настолько кликбейтный, насколько правдивый: просто у истории есть нюансы, и все они ниже.
Предыстория
Года три я вообще ничего не писал. Ни на vc.ru, ни где либо ещё. Не то что бы разлюбил — просто закрутился: развивался, работал, менял стек, менял проекты, было не до статей. Написание текстов как-то само по себе отвалилось из списка приоритетов, и я даже не заметил, как прошло три года.
А вернулся я к этому делу благодаря тому, что подсел на нейронки. Не в смысле "модно спросить у GPT рецепт борща", а в смысле реально плотно — код, тексты, тупые бытовые вопросы вместо гугла, всё туда. И вот, копаясь в старых архивах, я откопал свой древний проект — телеграм-бота на библиотеке g4f gpt4free, который позволяет дёргать нейросети через бесплатных провайдеров, без API-ключей и подписок (какого мое удивление, что она все еще .
Запустил бота на удачу — а он взял и заработал. Спустя столько лет, столько смен версий g4f, столько всего — работает. Это меня настолько воодушевило, что я решил не просто порадоваться и забыть, а реально довести проект до ума. И заодно — раз уж я снова что-то пишу руками не для работы — вспомнить, как писать статьи.Так что вот, ловите историю про то, как маленький ботик с одним промптом превратился в что-то похожее на полноценный ChatGPT-клиент прямо в Telegram (нет, но я так хочу думать).
Что вообще такое g4f
Для тех, кто не в теме: gpt4free — это опенсорсная библиотека, которая агрегирует кучу бесплатных (и не очень легальных, чего уж скрывать) способов дёрнуть разные нейросети — GPT, Claude, Gemini, DeepSeek и десятки других — без единого платного API-ключа. По сути это обёртка над кучей веб-версий и открытых эндпоинтов разных сервисов, приведённая к одному общему интерфейсу, максимально похожему на официальный OpenAI SDK.Работает это не идеально стабильно (об этом ниже будет отдельный больной абзац), но когда работает — работает бесплатно и достаточно хорошо, и это уже неплохо.
Как было раньше
Первая версия бота была максимально простой затеей на один вечер: один файл, синхронный `pyTelegramBotAPI`, устаревший вызов `g4f.ChatCompletion.create`, и вся "база данных" — это словарь в оперативной памяти `dialogs = {}`, где на каждого пользователя копилась общая история сообщений. Без персистентности (рестарт бота — прощай история), без выбора чего-либо, без вообще ничего (но это был вечерний pet-проект). Единсвенное, что там было реально прикольно - всегда в начала истории (которая не поддерживась g4f вообще, но путем експерементов было придуманно как ее сделать) пихался системный пром. Путем эксперементов трех летней давности было вявленно, что почти все модели принимают первое сообщение с определенным JSON массивом - как историю сообщений. + На тот момент только вышел BingAI - и он был бесплатным и самым шустрым и единсвенным с бесплатным GPT3 - поэтому я использовал только его. А еще он генерировал картинки, которые можно было извлекать из ответов (ну все это старые и единсвенные плюшки, страго проекта).
Что стало теперь
Я решил не мелочиться и впихнуть в бота максимум того, что вообще имеет смысл в ChatGPT-подобном клиенте:
- Неограниченное количество отдельных чатов — создавай, переименовывай, архивируй, удаляй, переключайся между ними в любой момент.
- Папки для организации чатов.
- Избранное и закреплённые чаты.
- Полноценная история сообщений с деревом веток — можно откатиться на любое сообщение в диалоге и продолжить с него как с новой ветки.
- Готовые роли-пресеты (Кодер, Учитель, Юрист, Доктор, Маркетолог, Дизайнер) с заранее прописанными системными промптами.
- Этого мне было мало и я еще сделал, настройку кастомных пресетов. - Опциональная долговременная память — бот может запоминать факты про тебя (имя, предпочтения) между чатами, если сам разрешишь. (Я это иногда использую в чатах, что бы отвечать на вопросы HR-ов про себя и мой стек).
- Потоковая генерация ответа (стриминг, как в настоящем ChatGPT — текст печатается на лету).
- Экспорт истории переписки.
- Статистика использования — сколько чатов, сообщений, токенов (хотя на сженные токены нам все равно, т.к. у нас их бесконечно много - но пусть будут для статистики)
- Это самый сырой раздел, т.к. я его писал последним и особо не тестировал.
Цель была простая: сделать максимально бесплатный и максимально жирный GPT-клиент в Telegram — чтобы можно было быстро спросить какую-нибудь тупость вместо того, чтобы открывать гугл или жечь свои лимиты. Что бы было очень просто всегда под рукой, закинуть свои вопросы туда. Собсвенно, результатом данной цели являеться ботик @GussiTradeGPTbot (пока MVP - но все же достаточно удобно)
Полный тур по интерфейсу
Раз уж бот вырос до отдельного мини-приложения внутри Telegram — расскажу, как я это всё разложил по экранам.
Главное меню
После `/start` я показываю приветствие и главное меню — четыре ряда инлайн-кнопок:
- 💬 Мои чаты / ➕ Новый чат
- ⭐ Избранное / 📂 Архив
- 🗂 Папки / 📊 Статистика
- ⚙ Настройки / ℹ Помощь
Собирается это меню одной маленькой функцией — вот она целиком, для понимания масштаба (это буквально весь код одного экрана):
Чаты
💬 Мои чаты" открывает список всех активных чатов — закреплённые сверху, дальше по дате последнего сообщения. Тап по чату открывает его карточку — превью настроек и подменю управления: настройки чата, инструменты, переименовать, закрепить, в избранное, в папку, в архив, удалить.
Вот как эта карточка чата собирается на практике:
- ⚙ Настройки чата — отдельное подменю: выбор провайдера (режим генерации), свой системный промпт для конкретно этого чата, параметры генерации (temperature, top_p, лимит токенов).
- 🛠 Инструменты чата — второе подменю: ветки диалога, применить пресет, постраничная история, экспорт, очистка/сжатие контекста.
Папки, избранное, архив
Папки — простая организация чатов по темам: создаю папку, закидываю туда чаты через "🗂 В папку" в карточке чата. Избранное и архив — те же списки чатов, только отфильтрованные по флагам "закреплён"/"в архиве".
Инструменты персонализации чата
Пресеты: шесть встроенных персон с заранее прописанными системными промптами: Кодер 🔥, Дизайнер 🎨, Учитель 📚, Юрист ⚖, Доктор 🩺, Маркетолог 📈. Применяется одной кнопкой прямо на чат — меняется системный промпт, и бот начинает отвечать в этой роли.
Да и в настройках самого чата можно посмотреть системный промт, который будет использоваться в чате и менять его на свое усмотрение самому.
Ветки: регулировка и управления ветками ответвления от данного чата. От любого сообщения можно начать новый чат, скопировав всю предыдущую историю чата, сохраняя контекст.
История: полная история данного чата, не знаю даже чем может быть полезна данная функция, но подумал что возможно будет необходима при поиске старых сообщений.
Экспорт: сделан в дополнение истории, плюс бывает, что я реально историю из своего tg бота экспортирую в полноценную модель. Так, что раздел достаточно полезный.
Долговременная память
Опциональная фича, по умолчанию выключена. Если включить в настройках — можно накидать боту фактов о себе (имя, часовой пояс, любимый язык программирования, что угодно), и он будет подмешивать их в системный промпт каждого чата. Каждый факт — это просто пара ключ/значение, добавляется прямо перепиской с ботом. (не всегда стабильная, я ее только дорабатываю)
Групповой режим
Недоделанное MVP - потом может допишу.
Разработка
История про выбор модели, которая не вышла
Отдельно расскажу про грабли, на которые я наступил и с позором откатил решение. Изначально я хотел сделать как в приличных клиентах: отдельно выбор модели (GPT-4, Claude, Gemini...) и отдельно выбор провайдера (через кого именно эта модель дёргается).
Красиво же — два независимых селектора, гибкость на максимум.И тут выяснилось неприятное: модели в g4f жёстко привязаны к провайдерам. Не любой провайдер умеет отдавать любую модель. Результат — россыпь ошибок (вот малая часть):
- ModelNotFoundError: выбранная модель не обслуживается выбранным провайдером.
- Add an api_key: провайдер внезапно требует ключ, хотя формально бесплатный.
- MissingAuthError/NoValidHarFileError: провайдер требует куки или HAR-файл из настоящего браузера, которых у серверного бота никогда не будет.
Починил я это вообще легко - выпилил выбор модели вообще. Теперь пользователь выбирает только режим/провайдера (Авто, Случайный, Умный Авто или конкретный провайдер), а какую модель использовать — решает уже сам провайдер, ему видней, что у него реально работает (раз g4f так умеет, пусть сама либа работает). Это не идеально с точки зрения "хочу именно Claude и точка", зато перестало ломаться на пустом месте.
Как это всё устроено внутри
Код проекта я целиком выкладывать не буду, но архитектуру и подход опишу максимально честно, чтобы было понятно.
Проект строго послойный:
Абстракно структура такая:
хендлеры → сервисы → репозитории → модели БД
- Хендлеры — это тонкая прослойка, которая только разбирает апдейты от Telegram и вызывает нужный сервис, сама в базу данных не лезет.
- Сервисы — вся бизнес-логика (создать чат, спросить у нейронки, применить пресет), они ничего не знают про Telegram API.
- Репозитории — чистый доступ к БД через SQLAlchemy, без бизнес-логики.
- Модели БД - понятно, отдельные классы описывающие модельки таблиц.
Стек моей балалайки: Python, pyTelegramBotAPI в асинхронном варианте (AsyncTeleBot), PostgreSQL + SQLAlchemy 2.0 (полностью асинхронный ORM) + Alembic для миграций, всё в Docker.
Как хранятся пользователи, чаты и сообщения
Начну с моделей БД — они честно передают, как устроены сущности внутри. У пользователя есть настройки один-к-одному и отдельная таблица под долговременную память:
Формальных "сессий" в привычном вебовском смысле у меня нет — есть только эта таблица `users` по `telegram_id`, и в оперативной памяти процесса живёт словарь "какой чат у какого пользователя сейчас активный" (чтобы не гонять лишний раз в базу на каждое сообщение). Вся остальная персистентность — в PostgreSQL, так что рестарт бота или деплой новой версии (что происходит часто) ничего не роняет — история и настройки остаются на месте.
Самое интересное архитектурное решение — сообщения хранятся не списком, а деревом. У каждого сообщения есть ссылка на "родителя", а у чата — указатель на текущее "активное" сообщение (хвост переписки).Это даёт бесплатную возможность ветвления: беру любое сообщение из середины диалога, продолжаю его — и это уже новая ветка, старая при этом никуда не девается, `Branch` просто хранит именованную ссылку на нужный лист. Восстановление истории от корня до нужного сообщения делается одним рекурсивным SQL-запросом, а не N запросами в цикле:
Моя обвязка над g4f
Сама библиотека g4f по духу похожа на официальный клиент OpenAI, только с дополнительным параметром `provider` — в чистом виде выглядит вот так:
А вокруг этого у меня выстроена тонкая, но важная прослойка — по сути свой маленький SDK поверх g4f, с двумя типизированными результатами:
И собственно вызов — функция `ask`, которая **никогда не кидает исключение наружу**: всегда возвращает результат с заполненным полем `error`, если что-то пошло не так. Это принципиальное решение — вызывающий код гарантированно получает хоть что-то, а не подвисает в ожидании ответа, который никогда не придёт:
Стриминговая версия `ask_stream` устроена так же честно — асинхронный генератор, который отдаёт накопленный текст по мере поступления чанков и никогда не роняет исключение выше себя.
Цепочка фолбэка провайдеров
Отдельный модуль превращает выбранный пользователем режим в упорядоченный список провайдеров, которые нужно перепробовать один за другим:
"Здоровье" провайдера — пара полей в таблице `provider_configs` (`is_healthy`, `avg_latency_ms`), которые обновляются после каждой попытки запроса. Никакой магии, обычная скользящая статистика по факту успеха/провала и затраченному времени.
А сам список провайдеров и моделей я не хардкожу руками — при каждом старте отдельный модуль обходит живой реестр g4f.Provider/g4f.models и синхронизирует его в БД.
Слой сервиса и хендлера
Сервис не знает про Telegram вообще, только принимает сессию БД и доменные объекты — вот сокращённая версия того, что происходит при обычном (не стриминговом) сообщении. Я это кстати использую стабильно в других проектах, когда мне надо сгенерировать текст или промт, для более умной нейронки я прошу нажу g4f сгенерировать мне текс/промт.
А хендлер сверху — максимально тонкий, вся его работа: получить апдейт из Telegram, дёрнуть сервис, отправить ответ обратно.
Что сейчас и что дальше
Если честно — сейчас это скорее MVP, чем финальный продукт. Работает, довольно стабильно для бесплатной штуки, но допиливать есть что: загрузка файлов, полноценный глобальный поиск по всем чатам, экспорт в красивый HTML/PDF — всё это в планах, но не горит.
Проект буду поддерживать и развивать дальше, так что если есть идеи, что добавить, или багрепорт — пишите, буду только рад обратной связи и предложениям.
Отдельно про ограничения: сервачок, на котором всё это крутится — не самый мощный, а сам g4f работает не всегда стабильно, потому что это в буквальном смысле обёртка над бесплатными лазейками в чужие сервисы — они иногда ведут себя не очень предсказуемо. Поэтому если пользуетесь ботом — рекомендую держать режим "Авто" выбора провайдера, он сам переключается между рабочими вариантами. Иногда всё равно ответ может идти дольше обычного или вылезти с ошибкой — в таком случае просто попробуйте ещё раз чуть позже. Бот будет оставаться полностью бесплатным, так что жду фидбеков и пожеланий в функциональности.
Потестить бота можно тут: @GussiTradeGPTbot