PokiToki: Удобный GPT-бот в телеграме

За последние месяцы только ленивый не сделал телеграм-бота, который работает с API OpenAI. Были такие статьи и на Хабре.
Написать игрушечного ChatGPT-бота можно хоть за час. А вот сделать его удобным в повседневной работе заметно сложнее. Я занимался этим последние несколько недель и хочу показать, что получилось.
Итак, pokitoki — это чат-бот на Python, который использует языковую модель ChatGPT (GPT-3.5 или GPT-4) от OpenAI. Вот некоторые его возможности:
- Работает в личных и групповых чатах.
- Отвечает на прямые вопросы, упоминания и форварды.
- Читает внешние ссылки (статьи, код, данные).
- Поддерживает шорткаты (команды для нейросети).
Личные чаты
В личном чате бот работает как ваш персональный ассистент.

Чтобы разрешить личные чаты с другими пользователями, пропишите их в настройке telegram_usernames.
По умолчанию у бота ужасная память, поэтому он не помнит предыдущие реплики. Но можно задавать уточняющие вопросы через ответную реплику (Ctrl/Cmd + ↑ на десктопе) или плюсик:
Почему так?
В большинстве случаев люди задают нейросети несвязанные вопросы. Поэтому по умолчанию каждый вопрос начинает диалог «с чистого листа».Если человек хочет продолжить диалог, то отвечает на сообщение собеседника — это стандартная для телеграма механика. Поэтому вопрос, заданный в ответ на сообщение бота, считается продолжением беседы.
Я рассматривал альтернативный вариант: по умолчанию считать вопросы одним диалогом и принудительно завершать его командой
reset. Но оказалось, что так менее удобно.
Команды:
/retry— переспрашивает последний вопрос;/help— показывает помощь;/version— показывает информацию о боте.
Группы
Чтобы бот ответил на вопрос в группе, тегните его на уже заданном вопросе или задайте прямой вопрос:
Чтобы бот отвечал всем участникам группы, пропишите ID группы в настройке telegram_chat_ids. Если настройка не задана, бот игнорирует вопросы от всех участников группы, кроме перечисленных в telegram_usernames.
Если не знаете ID группы, команда /version поможет его выяснить:
Chat information: - id: -1001405001234 - title: My Favorite Group - type: supergroup ...
Внешние ссылки
Если скормить ChatGPT ссылку, она либо начнет галлюцинировать, либо признается, что не может прочитать:
Q: What is the content of sqlime.org/employees.sql? Make no assumptions.
A: As an AI language model, I cannot access external URLs on the internet.
Чтобы решить эту проблему, бот предварительно загружает текст по ссылке и подает на вход нейросети:

Поддерживает только текстовый контент (статьи, код, данные), но не PDF, изображения или аудио.
Шорткаты
Используйте короткие команды, чтобы сэкономить время и заставить бота сделать что-то конкретное с заданным вопросом.
Например, попросите проверить и исправить текст командой !proofread:

Вот преднастроенные шорткаты:
bugfixчинит проблемы в коде.proofreadвычитывает и исправляет текст.translateпереводит текст на английский.summarizeрезюмирует длинный текст.
Можно добавлять собственные шорткаты, см. примеры в config.example.yml.
Другие полезные штуки
Удобство работы с ботом складывается из мелочей. Вот некоторые ситуации, в которых он экономит время и действия.
Форварды
Допустим, вы получили сообщение от коллеги или прочитали пост на канале, и хотите задать по нему вопрос. Просто перешлите сообщение боту и ответьте на уточняющий вопрос, который он задаст:
Ответ вложением
Бывает, что ответ нейросети не вмещается в максимальный размер сообщения, предусмотренный телеграмом. В этом случае бот не сломается и не будет спамить вас сообщениями. Вместо этого пришлет ответ вложенным markdown-файлом:

Исправленный вопрос
Чтобы перефразировать или дополнить последний вопрос, отредактируйте его (↑ на десктопе). Бот заметит это и ответит на уточненный вопрос.
Информация о боте
Команда /version показывает подробную информацию о чате, боте и настройках нейросети:
Chat information: - id: -1001405001234 - title: My Favorite Group - type: supergroup Bot information: - id: 5930739038 - name: @pokitokibot - version: 70 - usernames: 6 users - chat IDs: [] - access to messages: True AI information: - model: gpt-3.5-turbo - history depth: 3 - shortcuts: ['bugfix', 'proofread', 'summarize', 'translate']
Как установить
- Получить ключ для OpenAI API
- Получить токен для телеграм-бота от @BotFather
- Скопировать
config.example.ymlвconfig.ymlи прописать там ключи. - Запустить бота.
docker compose up --build
Исходники
Я старался писать понятный модульный код, с комментариями и тестами.

Краткое описание модулей:
botстартует бота и обрабатывает полученные от пользователя команды и сообщения. Логику ответов на вопросы делегирует модулямquestions,fetcherиai.chatgpt.questionsобрабатывает вопрос от пользователя перед тем, как задать его нейросети. Отличает обычные вопросы от уточняющих, обрабатывает упоминания в группе. Активирует шорткаты с помощью модуляshortcuts.shortcutsизвлекает шорткат из текста вопроса и заменяет его на конкретную команду нейросети.fetcherизвлекает ссылки из вопроса, подтягивает их содержимое и подставляет в текст вопроса.modelsпредоставляет обертку для истории сообщений пользователя.ai.chatgptпредоставляет обертку над API OpenAI.configзагружает настройки из файлаconfig.yml.
Исходники на гитхабе
Буду рад, если бот вам пригодится. По отзывам, он неплохо подходит как для индивидуального использования, так и для небольших сообществ (по интересам или рабочих).
