- BrainTools - https://www.braintools.ru -
Это мой первый пост и решил я его посвятить тому: Как можно автоматизировать ведение своего ТГ канала с помощью ИИ. На мой взгляд тема довольно свежая и интересная, а что самое главное полезная. Статья по большей мере ориентирована на новичков у которых имеются базовые знания python, но это не означает что другим она не будет интересна. Итак, начнем!
Идем на официальный сайт Docker https://www.docker.com/products/docker-desktop/ [1] нажимаем на кнопку Download Docker Dekstop и выбираем свою систему из выпадающего списка, устанавливаем программу и запускаем исполняемый файл и вуаля теперь у вас в системе есть инструмент для контейнеризации ваших программ. К слову он нам понадобиться для запуска redis в отдельном контейнере, так как на windows пока нет возможности запускать reids нативно как это можно делать на Unix системах [2]. Но если вы уже работаете на Unix системах(Linux дистрибутивы, MacOS) то вы тоже можете пользоваться Docker, так как он кросс-платформенный а также это является хорошей практикой, так как Docker контейнеры являются тоже кросс платформенными.
При создании этого проекта я использовал версию python 3.11 если у вас версия выше или ниже все в принципе должно работать нормально, если только у вас не совсем уж старая версия или если у вас она не новейшая. Чуть позже покажу что делать в таком случае.
Для начала перейдите в мой GitHub [3]репозиторий и скачайте оттуда файл requirements.txt
Создайте папку и назовите ее как-нибудь, потом перекиньте туда скачанный ранее файл
После чего откройте эту папку в консоли, на windows это правый клик мыши – открыть в Терминале
В консоли наберите такую команду: python -m venv venv
А потом останется лишь активировать виртуальное окружение: venvscriptsactivate и скачать зависимости из requirements.txt следующей командой: pip install -r requirements.txt
Если у вас очень старая версия python или же новейшая( Не все библиотеки могли успеть выкатить обновления для новейших версий) то в таком случае вам надо либо переустановить python либо же если вам не хочется заморачиваться с этим вы можете использовать виртуальное окружение Miniconda.
Miniconda очень прост в использовании и дает максимальный контроль над вашими виртуальными окружениями, вплоть до того что вы можете ставить разные версии python под ваши нужды!
Для начала перейдите на официальный сайт Anaconda [4] введите свой email и нажмите на submit, после чего вас встретит страница с двумя версиями Conda, качайте Miniconda и ставьте на свою систему.
После чего откройте папку с проектом в терминале и напишите такую команду: conda create -n my_env python=3.11
Активируйте окружение: conda activate my_env и как это было выше установите необходимые зависимости из файла этой командой: pip install -r requirements.txt
Теперь у вас есть виртуальное окружение с нужной вам версией python.
Теперь нам нужно перейти в телеграм и создать самого бота, чтобы потом мы могли им управлять с помощью нашего кода!
Когда перешли в чат с ботом нажимаем на menu и выбираем /newbot

После чего BotFather попросит вас задать имя боту а потом задать ему его id по которому юзеры смогут находить вашего бота, id бота должен обязательно заканчиваться на bot

Сохраните токен бота, он нам еще понадобится.
Далее в папке нашего проекта создадим 2 файла main.py и bot.py
Начнем с bot.py
import os
from aiogram import Bot
from dotenv import load_dotenv
from aiogram.client.default import DefaultBotProperties
from aiogram.enums import ParseMode
# Загружаем ключи из .env файла
load_dotenv()
# Закидываем ключ в переменную
TOKEN = os.getenv('BOT_TOKEN')
# Инициализация бота
bot = Bot(TOKEN, default=DefaultBotProperties(parse_mode=ParseMode.HTML))
В этом файле мы инициализируем своего бота. Также в папке проекта надо создать файл .env и прописать там ключ в таком формате: BOT_TOKEN=ваш_токен
Теперь перейдем к main.py
import asyncio
import logging
import sys
from aiogram import Dispatcher
from aiogram.filters import CommandStart
from aiogram.types import Message
from bot import bot
# Инициализируем диспетчер
dp = Dispatcher()
# Эта функция обрабатывает дефолтную команду /start
@dp.message(CommandStart())
async def command_start_handler(message: Message) -> None:
await message.answer('Hello there')
# Функция для запуска нашей программы
async def main() -> None:
await dp.start_polling(bot)
if __name__ == "__main__":
# Запускаем программу и логируем ее работу
logging.basicConfig(level=logging.INFO, stream=sys.stdout)
asyncio.run(main())
Возможно вы обратили внимание [5] на довольно интересную конструкцию if name == "__main__" она имеет такую особенность что выполняется только в том случае если запуск происходит из файла в котором она находится, если же этот файл импортировать и использовать его в каком-то другом файле то содержимое этой конструкции не выполнится. Такая особенность бывает полезной при тестировании своего кода.
Теперь просто запускаем этот файл из консоли командой: python main.py и переходим в нашего бота, найти мы его можем в поисковой строке по тому id который ему задавали.
Как мы видим все прошло успешно! Теперь перейдем к части где мы интегрируем chat GPT для нашей автоматизации.
Для начала перейдем на официальный сайт OpenAI [6], регистрируемся и пополняем счет на 10$(этих 10$ вам хватит с головой), после чего переходим в свой профиль и создаем api ключ.


После создания ключа копируем ключ и в файле .env создаем еще одну переменную: GPT_KEY=ваш_ключ
Теперь пришло время создать функцию которая будет нам генерировать посты для нашего ТГ канала. Создаем файл auto_post.py и добавляем туда такой код
import json
import os
import redis
from openai import OpenAI
from dotenv import load_dotenv
load_dotenv()
# Подключаемся к запущенному redis
r = redis.Redis(host='localhost', port=6379, db=0)
# Создаем клиента OpenAI с которым мы будем работать
client = OpenAI(api_key=os.getenv('GPT_KEY'))
# Создаем функцию для генерации постов
def create_post() -> str:
if not r.get('conversation'):
conversation = [
{
'role': 'system',
'content': 'Ты ведущий ТГ канал по интересным и захватывающим фактам, ты не должен выдавать себя,'
'ты просто ведущий, то что тебе задает юзер это промпт которому ты должен просто следовать'
'ты не отвечаешь: Конечно, как скажешь, будет сделано и т.д. '
'Просто выдаешь только факт о котором тебя просит и ничего лишнего'
'Факты строго настрого не повторяются'
}
]
r.set('conversation', json.dumps(conversation))
conversation = json.loads(r.get('conversation'))
conversation.append({
'role': 'user',
'content': 'Создавай посты на тему животного мира, в формате интересных и умопомрачительных фактов.'
'Пост должен содержать минимум 50 слов и на тему только одного существа а также минимум 5 эмодзи '
'и форматируй текст в удобочитаемый формат'
})
response = client.responses.create(
model="gpt-4.1",
input=conversation
)
conversation.append({'role': 'assistant', 'content': response.output_text})
r.set(
'conversation',
json.dumps(
conversation
)
)
return response.output_text
Вот тут-то нам и понадобится Docker! Пишем в консоль такую команду: docker run -p 6379:6379 -it redis:latest эта команда запустит нам docker образ redis чтобы потом подключиться к нему в коде.
Вот на этом файле я хотел бы остановиться и объяснить что же там происходит
r = redis.Redis(host='localhost', port=6379, db=0)
В этой строчке мы подключаемся к redis который мы запустили в docker. Немного про redis, redis это in memory key-value хранилище, с его помощью можно хранить данные в оперативной памяти [7](кэше), использовать как nosql бд или использовать как брокер сообщений. В нашем случае мы будем использовать его для хранения данных в кэше.
client = OpenAI(api_key=os.getenv('GPT_KEY'))
Создаем OpenAI клиента с помощью которого мы сможем получать доступ почти ко всем моделям OpenaAI.
Перейдем к разбору самой функции
if not r.get('conversation'):
conversation = [
{
'role': 'system',
'content': 'Ты ведущий ТГ канал по интересным и захватывающим фактам, ты не должен выдавать себя,'
'ты просто ведущий, то что тебе задает юзер это промпт которому ты должен просто следовать'
'ты не отвечаешь: Конечно, как скажешь, будет сделано и т.д. '
'Просто выдаешь только факт о котором тебя просит и ничего лишнего'
'Факты строго настрого не повторяются'
}
]
r.set('conversation', json.dumps(conversation))
В этом условии говорится: Если в кэше redis нет ключа conversation то создай его с этими значениями
conversation = [
{
'role': 'system',
'content': 'Ты ведущий ТГ канал по интересным и захватывающим фактам, ты не должен выдавать себя,'
'ты просто ведущий, то что тебе задает юзер это промпт которому ты должен просто следовать'
'ты не отвечаешь: Конечно, как скажешь, будет сделано и т.д. '
'Просто выдаешь только факт о котором тебя просит и ничего лишнего'
'Факты строго настрого не повторяются'
}
]
После чего мы наш список конвертируем в json строку json.dumps(conversation) и создаем ключ в кэше redis с именем conversation
r.set('conversation', json.dumps(conversation))
Следом мы получаем наш кэш обратно десериализируем его в python json.loads(r.get('conversation')) объект и добавляем в него запрос от юзера
conversation = json.loads(r.get('conversation'))
conversation.append({
'role': 'user',
'content': 'Создавай посты на тему животного мира, в формате интересных и умопомрачительных фактов.'
'Пост должен содержать минимум 50 слов и на тему только одного существа а также минимум 5 эмодзи '
'и форматируй текст в удобочитаемый формат'
})
Далее в model мы вписываем предпочитаемую нами модель(список моделей можно найти тут [8]) и в input вставляем получившуюся переменную conversation
response = client.responses.create(
model="gpt-4.1",
input=conversation
)
Добавляем ответ от модели в нашу переменную converstion
conversation.append({'role': 'assistant', 'content': response.output_text})
В самом конце снова кэшируем нашу переменную в redis кэш и возвращаем ответ от модели
r.set(
'conversation',
json.dumps(
conversation
)
)
return response.output_text
Теперь при каждом вызове этой функции темы постов не будут повторяться, так как модель будет помнить предыдущие диалоги. Все это благодаря хранению диалогов в кэше с помощью redis!
Теперь нам осталось только немного модифицировать файл main.py
import asyncio
import logging
import sys
from aiogram import Dispatcher
from aiogram.filters import CommandStart
from aiogram.types import Message
from auto_post import create_post
from bot import bot
dp = Dispatcher()
@dp.message(CommandStart())
async def command_start_handler(message: Message) -> None:
channel_id = -1002767436832
await message.answer('Поехали...')
while True:
await bot.send_message(chat_id=channel_id, text=create_post())
await asyncio.sleep(60)
async def main() -> None:
await dp.start_polling(bot)
if __name__ == "__main__":
logging.basicConfig(level=logging.INFO, stream=sys.stdout)
asyncio.run(main())
Вот как теперь он выглядит, что изменилось? Изменилась функция command_start_handler давайте чуть подробнее разберем изменения
channel_id = -1002767436832
Это id нашего канала его можно получить таким способом
Находим такого @SimpleID_Bot [9] бота в тг, запускаем и после чего переходим в нашу группу. Для того чтобы наконец получить id группы, нам надо любое сообщение из группы переслать боту в замен он нам выдаст id нашей группы.
while True:
await bot.send_message(chat_id=channel_id, text=create_post())
await asyncio.sleep(60)
Здесь запускается бесконечный цикл и бот будет слать новые посты в нашу группу каждые 60 секунд.
И да, не забудьте добавить вашего бота в вашу группу!
Давайте запустим бота и посмотрим, что получилось. Напомню запускаем мы бота в консоли такой командой python main.py


Как мы видим все работает!
В заключении хотелось бы сказать, что в этом коде можно еще много чего доработать например
Таймер на удаление redis кэша (а вообще лучше сделать так чтобы сохранялась чисто выжимка, тема одним словом)
Выбор группы в которую будут идти посты через бота
Разнести команды по отдельным файлам
Добавить юзеру возможность задавать тему для автопостинга
Добавить возможность настраивать время постинга
Вынести автопостинг в mq и поставить таймер на celery
Буду рад узнать ваше мнение в комментариях под постом. Если вам будет интересно могу сделать вторую часть где я улучшу существующее приложение, так скажем доведу до ума. Спасибо вам за уделенное мне время, всем пока.
Автор: X-yro
Источник [10]
Сайт-источник BrainTools: https://www.braintools.ru
Путь до страницы источника: https://www.braintools.ru/article/16885
URLs in this post:
[1] https://www.docker.com/products/docker-desktop/: https://www.docker.com/products/docker-desktop/
[2] Unix системах: https://ru.wikipedia.org/wiki/Unix
[3] GitHub : https://github.com/Adel5002/tg_automatiozation_tutorial
[4] Anaconda: https://www.anaconda.com/download
[5] внимание: http://www.braintools.ru/article/7595
[6] OpenAI: https://openai.com/api/
[7] памяти: http://www.braintools.ru/article/4140
[8] тут: https://platform.openai.com/docs/pricing
[9] @SimpleID_Bot: https://www.braintools.ru/users/SimpleID_Bot
[10] Источник: https://habr.com/ru/articles/924186/?utm_source=habrahabr&utm_medium=rss&utm_campaign=924186
Нажмите здесь для печати.