Обучение программированию с нуля. Вы напишете MVP для стартапа на Python за 1 день. OpenAI API + Google API

Привет! Это бесплатный пошаговый гайд для обучения программированию на языке Python для начинающих. С помощью урока вы создадите полезное приложение -- тренажёр для изучения иностранных языков. Сами, на языке программирования Python и без «зерокодинга».

Игорь Диев
Запускаю стартапы и учу новичков программированию. Подпишитесь на мой linkedin или телеграм. Это вдохновит на новые материалы 🤗

Я часто читаю статьи на VC о том, как кто-то придумал и разработал бота на 20к участников и с платными подписками, сделал вирусное приложение, получил признание стартап-сообщества. Я решил освоить Python и вместе с вами заглянуть «под капот» подобных MVP, сделав нечто подобное своими руками.

🔥Важно: добавлено продолжение урока, обязательно прочитайте его, чтобы ваш бот работал на сервере 24/7: Как запустить ChatGPT-бота на сервере? Программирование с нуля для начинающих. Python + Telebot + демон PM2

Урок будет разбит на 10 модулей. Начиная с 4-го модуля каждый раз у вас будет получаться рабочая программа на языке программирования Python. Каждый следующий модуль будет её дополнять. Вы можете остановиться на любом из них, если почувствуете, что становится сложно.

Список модулей:

Чтобы статья была более универсальной и лаконичной, я буду скрывать самые элементарные пояснения под блок "содержание скрыто", вот такой:

Содержание скрыто
Показать

Элементарное определение.

1. Задача и план решения

Задача пришла из жизни: некоторые читают книги на английском, чтобы изучать язык, и часто встречают новые слова. Было бы здорово их куда-то вбивать, получать перевод, сохранять и на основе последних добавленных слов выдавать тест для самопроверки.

На основе формулировки задачи распишем схему взаимодействия с программой:

Схема взаимодействия с программой
  1. Просим пользователя ввести текст
  2. Принимаем текст от пользователя
  3. Переводим введенный текст на нужный нам язык
  4. Выводим результат перевода

Также нам нужно сделать несколько пунктов меню:

  1. Старт (просто стартуем, просим пользователя ввести текст)
  2. Словарь — выводим последние 10 добавленных слов
  3. Тест — просим программу сгенерировать для нас тест
  4. Помощь

2. Устанавливаем PyCharm для программирования на Python

Скачаем главный инструмент -- бесплатную (для личного использования) среду для разработки на Python. Для этого вбейте в Google или Яндекс «PyCharm последняя версия» > переходите на сайт JetBrains > выберите Windows/MAC > нажмите на Community — Скачать exe.

Почему я не даю прямую ссылку? Хочу, чтобы урок был актуальным в будущем, а прямая ссылка может измениться.

Предупреждение: PyCharm весит много (400 Мб), если вы не хотите пользоваться такой тяжелой программой, покажу в конце материала, как написать программу в среде Google Collab без установки программ, через браузер.

Также в конце материала приводятся рекомендации по программированию на Python под Mac.

После скачивания нажмите «установить», выберите папку для установки и нажмите Next, далее жмите Next на каждом шаге, пока не завершите установку.

3. Пишем первую программу на Python

Найдите в интерфейсе программы Pycharm слева вверху пункт File > New Project

Создание нового проекта в интерфейсе PyCharm

В открывшемся окне ничего не меняйте и жмите Create.

Вы увидите вот такой прекрасный код:

Удалите весь код, который выдал вам PyCharm. Замените его на строчку. приведенную ниже. Чтобы знания лучше закрепились, предлагаю перепечатать текст вручную, не делать Ctrl-C -- Ctrl-V.

print('Hi, VC!')

Вот как это должно выглядеть:

Первые строчки кода на Python
Содержание скрыто
Показать

Это очень простой код, он означает команду print (напечатай!) и информацию в скобках, которую мы хотим с помощью этой команды напечатать.

Написав данный код, найдите вот такую кнопку в виде зеленого треугольника справа вверху и нажмите на нее.

Внизу в вашей программе отобразится результат выполнения программы.

Во вкладке Run в нижней части программы должна появиться строчка, которую мы хотели напечатать.

Если все сработало, я вас поздравляю, вы написали первую программу на Python.

💪Задача для закрепления навыков:

Выведите на экран другую надпись, например, «Hello, Zuckerberg».

4. Настраиваем и программируем на Python Телеграм-бота

Теперь вам нужно создать и настроить вашего собственного бота в Telegram. Следуйте этой простой пошаговой инструкции.

Создание бота в Телеграм

Найдите в Телеграме бота под названием @BotFather. Можете нажать на ссылку ниже:

Зайдите в menu > /newbot. Введите имя для вашего бота. Введите username для вашего бота.

Username отличается от имени тем, что username — это уникальный адрес. вашего бота вида @username, и он всегда должен заканчиваться на слово bot, а имя бота — это отображаемое имя в левой колонке в Телеграм.

У вас должен произойти такой диалог:

Создание нового бота в Телеграм

Самое важное — это API Token. Я его замазал на скриншоте, чтобы показать, что это секретная информация. Никому не давайте ваш токен, не выкладывайте в публичное пространство. Токен — это как пароль, с помощью него можно получить доступ к вашему боту и изменить его.

Подключаем API Token telebot API

Теперь зайдите в PyCharm и создайте файл config. py.

Находим слева вкладку Project, в ней файл main. py. Кликаем рядом с ним правой кнопкой мыши и нажимаем New > FIle.

Создаем новый файл

Система предложит ввести имя файла, напишите config. py и нажмите Enter.

Содержание скрыто
Показать

Имя файла может быть любым, это не принципиально, но по смыслу нам подходит слово «конфиг» от слова «конфигурация», т. к. этот файл будет «настраивать», «конфигурировать» нашу программу

Создаем файл config.py для хранения токенов

Проследите, чтобы файл лежал рядом с файлом main. py, а не в какой-то другой папке. Пути до файлов в программировании очень важны. Если файл попал в другое место, перетащите его, чтобы он оказался рядом с main. py как на скриншоте ниже.

Проверяем, что config.py лежит рядом с основным файлом нашей программы

Дисклеймер: файл config в будущем мы будем хранить в другом месте, но пока это не принципиально, и для удобства прописывания путей к файлам используем корневую папку.

В файл config. py мы пишем следующую строчку.

tg_token='ваш токен, который вам дал BotFather'

Выглядеть это должно вот так:

Указываем токен в файле config.py
Содержание скрыто
Показать

В этой записи слово tg_token является названием переменной. Знак = является оператором присваивания, он говорит, что у этой переменной будет значение, которое стоит после знака =. В кавычках записывается наша строка, в данном случае — токен. Обратите внимание, в Python в основном случае не важно, какие кавычки вы ставите, одинарные или двойные.

Теперь зайдем в файл main. py. В нем мы будем импортировать модули.

Содержание скрыто
Показать

Python в чистом виде — это инструмент. Как, например, дрель. Рабочий отправляется выполнять задачу и берет с собой к дрели набор насадок: сверло по керамике, шлифовальную насадку и тд. В зависимости от задачи он будет брать с собой разные насадки. Также и в Python с помощью импорта мы добавляем в инструменты для решения конкретных задач.

В данном случае нам нужно написать Телеграм-бота, поэтому мы подключим инструмент — модуль TelegramBotAPI, который называется Telebot.

Для импорта Telebot нам нужно прописать следующую строчку в самом верху:

import telebot

Выглядеть это будет так:

Подключаем Telebot (TelegramBotAPI)

Теперь нам нужно импортировать наш файл config. py. Пишем такой код:

import config​

Далее пишем такую строчку, в ней мы подключаем конкретного бота к нашей программе. В скобках мы обращаемся к нашему файлу config. py, чтобы получить значение переменной tg_token.

bot = telebot.TeleBot(config.tg_token)
Импорт Telebot и файла Config.py, инициализация бота с токеном

Импорт модулей идет чаще всего в два шага: 1. мы подключаем их с помощью команды import… в основной программе (это мы уже сделали) и 2. мы устанавливаем файлы импортируемых модулей с помощью команды pip3 install.

Но перед тем как начнем что-то устанавливать, настроим виртуальное окружение.

Активация виртуального окружения

Сейчас пользователям Windows будет немножечко больно, я не буду подробно объяснять, что мы будем делать, просто следуйте инструкции.

1. Зайдите во вкладку Terminal в нижней части PyCharm:

Вкладка Terminal

2. Проверьте, есть ли у вас приписка venv в скобках рядом со строчкой вида C:\Users\…

Проверяем, есть ли приписка (venv)

3. Если приписка есть, переходите сразу к блоку «Установка Telebot». Если приписки нет, следуйте инструкции.

4. Напишите следующую строку в Терминал и нажмите Enter.

cmd.exe
Запускаем cmd.exe

5. Теперь введите следующий код.

cd venv/Scripts
Заходим в папку Scripts

6. Введите туда же в Терминал следующую строчку.

activate.bat
Активируем виртуальную среду

5. Перед строкой в Терминале должно появиться слово (venv).

Проверяем, что виртуальная среда активировалась

Если приписка не появилась, пробуем альтернативный способ.

1. Зайдите в File > Settings

Заходим в Settings

2. Откройте вкладку Tools > Terminal

Заходим в настройку Терминала

3. В пункте Shell path нажмите на треугольник, чтобы появился выпадающий список, и выберите строчку, которая заканчивается на cmd. exe.

Запускаем cmd.exe

4. Убедитесь, что установлена галочка Activate virtualvenv и указан правильный путь к вашему проекту (если вы его не меняли, он должен быть правильным).

Проверяем галочку Activate virtualvenv

5. Нажмите кнопку Apply, после этого перезапустите Pycharm (закройте и откройте его). Перед строкой пути в Терминале должно появиться слово (venv).

Содержание скрыто
Показать

Что мы сделали? Мы запустили виртуальное окружение. Зачем это надо? В программировании, как я писал выше, очень важны пути к файлам. Виртуальная среда позволяет создать как бы изолированное пространство со своим набором инструментов для каждой программы и со своими путями ко всем необходимым файлам. Я не думаю, что вам нужно сейчас глубоко погружаться в этот термин, но выполненная настройка важна для дальнейшей работы.

Установка Telebot

После того как виртуальное окружение настроено, мы можем установить модуль telebot. Пишем следующий код в Терминале и нажимаем Enter.

pip3 install telebot

На экране начнет происходить магия, и потом появится фраза со словами Successfully installed.

Установка модуля telebot

Еще несколько строчек на языке программирования Python и ваш бот оживет!

@bot.message_handler(content_types=['text']) def handle_message(message): bot.send_message(message.chat.id, text="Hi, VC!")

В этом коде мы говорим, что все сообщения, которые являются текстом, мы будем обрабатывать с помощью функции handle_message.

Содержание скрыто
Показать

Функция — это то, что идет в Python после слова def. Любая функция умеет получать на вход некоторые данные (аргументы), что-то с ними делать и выдавать результат. Приведу пример простейшей функции, чтобы вы поняли, о чем речь.

Содержание скрыто
Показать
Простейшая функция
Содержание скрыто
Показать

Обратите внимание на каждый элемент этой программы, вы без труда разберетесь, что к чему.

Содержание скрыто
Показать
  • def означает, что мы создаем функцию
  • add — это имя функции, оно может быть произвольным
  • (a, b) — это аргументы функции
  • c — это переменная, которую мы создали внутри функции
  • = и + — это математические операторы для получения результата с помощью функции
  • return передает результат выполнения функции. Он должен выполниться только один раз. Также бывают функции без return, это нормально
  • str — это приведение числа к строке
  • а print мы уже проходили, эта команда (функция, на самом деле) печатает на экран то, что передали ей в качестве аргумента
  • в последней строчке мы вызвали сразу 3 функции — str, print и нашу add
Содержание скрыто
Показать

Результат выполнения программы, естественно, вывод на экран числа 14.

Вернемся к нашему главному коду в main. py. В нем есть такая строчка

bot.send_message(message.chat.id, text="Hi, VC!")

Она означает, что мы будем посылать сообщение "Hi, VC!" в бота.

Последний штрих. Чтобы программа не прекращала работу (пока мы ее не остановим принудительно) мы должны прописать следующую строчку:

bot.polling()

Весь код будет выглядеть так:

Программируем простейший Телеграм-Бот на Python

Запустим программу (зеленый треугольник):

Запускаем выполнение скрипта в PyChar

Заходим в нашего бота, он просит нажать Start. Нажимаем. И вуаля. Вы можете нажать несколько раз, и каждый раз получите сообщение от бота. Вы можете писать любые сообщения, и бот вам всегда ответит своё Hi, VC!.

Первая версия Телеграм Бота

Если все получилось, то это невероятное, вы только начали изучать основы программирования, но уже смогли настроить виртуальное окружение для работы с программой на Python и запрограммировали собственного бота.

💪Задача для закрепления навыков:

Попробуйте вывести в бота фразу "Hello, Zuckerberg!"

5. Подключаем к Телеграм-боту на Python Google Translate API

Содержание скрыто
Показать

Перед тем как двигаться дальше, расскажу вам, что такое API. Представьте, что программы — это люди. У людей есть какие-то внутренние процессы, какой-то внутренний мир, а есть уши и рот, чтобы общаться. Так же и программы общаются друг с другом с помощью API, спрашивать друг у друга что-то и получать ответы.

Для перевода слов с одного языка на другой нам нужны Google Trans API. Воспользуемся импортом в коде основной программы, вверху.

from googletrans import Translator
Подключаем модуль Googletrans

Пишем такую строчку:

translator = Translator(service_urls=['translate.googleapis.com'])
Инициализируем translator

Теперь пропишем следующую строчку. Мы просим Googletrans перевести фразу Hi, VC на русский.

bot.send_message(message.chat.id, text=translator.translate("Hi, VC!", src="en", dest="ru").text)
Применяем функцию translate

Здесь. translate — функция, в которую передаем три аргумента — текст, язык-источник (английский) и язык назначения (русский).

Устанавливаем Googletrans API. Давайте начнем с такой очевидной команды в Терминале:

pip3 install googletrans

Если программные модули установились и мы получили сообщение «Successfully installed », запускаем программу (зеленый треугольник).

Далее заходим в бота, пишем ему какое-то сообщение. Но ответа не приходит. В чем же дело? А дело — в ошибке. Вернитесь в PyCharm. Посмотрите, что мы натворили.

Ошибка AttributeError

Я специально допустил эту ошибку, чтобы показать вам, как действовать в таких случаях. В любой момент времени какой-то модуль может установиться «криво», не туда, не так, не тот и тд. Что-то может перестать работать на той стороне, куда мы посылаем запросы.

Для решения проблем скопируем текст ошибки и воспользуемся поиском (Google или Яндекс).

Ищем как исправить ошибку при исполнении программы
Содержание скрыто
Показать

В первой ссылке видим сайт StackOverflow, это сайт, на котором одни программисты пишут о возникших ошибках, а другие делятся опытом их решения.

По первой ссылке получаем такую рекомендацию:

Пользуемся StackOveflow, чтобы найти рекомендацию по исправлению ошибки

Теперь удаляем нашу версию googletrans

pip3 uninstall googletrans

Система попросит подтвердить изменения, нажмите y и Enter.

Терминал просит подтверждения действий

Пробуем установить googletrans так, как указано в скриншоте. Пишем в Терминале:

pip install googletrans==3.1.0a0

Напомню, что все действия нужно выполнять, если в терминале вы видите префикс venv и правильный путь к вашему проекту.

Проверяем, что ваша программа выглядит вот так. И запускаем ее.

Снова запускаем программу для тестирования
Содержание скрыто
Показать

Обратите внимание, что когда программа работает, зеленый треугольник меняется на закругленную стрелочку, а справа появляется красный квадрат. Нажатие на красный квадрат останавливает программу.

Кнопка остановки исполнения программы

Возвращаемся в бот. Пишем туда что-нибудь и — о чудо! — получаем перевод. VC по версии Google Translate на русском звучит как «ВК» (венчурный капитал, наверное).

Получили первый переведенный текст.

Давайте теперь научимся переводить с английского на русский любой введенный текст и отправлять это обратно в бот. Убираем «Hi, VC» и заменяем это на выражение message. text. Получится такая конструкция:

bot.send_message(message.chat.id, text=translator.translate(message.text, src="en", dest="ru").text)

Message. text в данном случае содержит последнее сообщение, которое мы прислали в бот. Почему мы пишем message. text, а не просто message, что казалось бы, логично? Потому что в message есть не только текст, но и время отправки, и автор сообщения и тд.

Программа теперь выглядит так.

Принимаем сообщение, переводим с английского на русский и отправляем обратно в бота.

Пообщался с ботом. Узнал много нового)

Наш бот переводит слова

Поздравляю! Вы подключили API Google Translate, не испугались первой ошибки и нашли, как ее решить.

💪Задача для закрепления навыков:

Попробуйте перевести слова с английского на немецкий. Найдите в коде двухбуквенные обозначения языков (ru, en) и замените ru на код Германии. Найдите его сами в поисковике, введя «двухбуквенные обозначения стран».

6. Реализуем функцию «словарь» на Python для сохранения слов и команду в Телеграм-боте для вывода слов

Работаем с файлами с помощью Python

В этой программе нам нужно будет работать с несколькими файлами. Python позволяет создавать файлы с различными расширениями, считывать содержимое и записывать в них информацию.

Вот таким выражением мы будем записывать введенное пользователем слово в файл.

with open("vocabulary.txt", "a") as file: file.write(message.text+"\n")

Вызывать эту команду мы будем изнутри функции, в которой получаем от пользователя текст.

Функция обработки входящего сообщения от Телеграм-бота
Содержание скрыто
Показать

Что мы тут сделали: команда open открывает файл, в скобках название файла и префикс «a«, что означает, что каждое новое слово мы будем добавлять в файл, а не, например, переписывать его полностью. С помощью команды write мы пишем информацию в файл (message. text — это слово, которое мы получили из бота и »\n» — это выражение для переноса строки в файле. Если ее не добавить, все слова в файле будут идти в одну строку, а этого нам не нужно.

Запускаем программу (зеленый треугольник).

Заходим в бота и пишем ему несколько английских слов.

Переводим слова, который - по нашей задумке - записываются в словарь

Заходим в папку с нашим проектом. Она лежит по адресу наподобие C:\Users\______\PycharmProjects\pythonProject1. В ней рядом с файлами main. py и config. py должен появиться файл vocabulary. txt.

Находим файл, который мы создали в Python

Откройте файл, вы увидите, что в нем сохранены наши слова.

Проверяем, что слова сохраняются в словарь

Настраиваем команду (/command) в Телеграм-боте и выводим с 10 последних слов из файла

Чтобы настроить команду /vocabulary нам нужно будет снова вернуться к @BotFather в Телеграме. Заодно настроим команды /start и /help.

Жмем menu > mybots

Заходим в mybots

Из предложенного списка выбираем вашего бота и жмет Edit bot.

Редактируем бота

Выбираем Edit Commands

Задаем команды

Бот предложит ввести команды. Делаем так, как указано на картинке — команды пишем по-английски с маленькой буквы, далее пишем дефис, далее пишем понятный для пользователя текст команды.

Указываем команды для Телеграм-Бота

Теперь создадим обработчик события «Нажали на кнопку /vocabulary». Для этого в Telebot API есть специальная функция.

@bot.message_handler(commands=['vocabulary'])

Далее создаем функцию show_vocabulary

def show_vocabulary(message):

Внутри этой функции открываем файл на чтение (вместо режима «a» ставим режим «r»):

with open("vocabulary.txt", "r") as file:

Далее нам нужно считать файл в список строк, взять последние 10 элементов и вывести их на экран в порядке, обратном порядку добавления.

@bot.message_handler(commands=['vocabulary']) def show_vocabulary(message): with open("vocabulary.txt", "r") as file: lines = file.readlines()[-10:] for line in reversed(lines): bot.send_message(message.chat.id, text=line)
Содержание скрыто
Показать
  1. lines = file. readlines() [-10:] означает, что в список lines мы сохраняем последние 10 строк (выражение [-10:]), полученных с помощью функции readlines() (чтение файла целиком) из файла file. Чем список отличается от строки? Тем, что список — это набор элементов (в данном случае строк), каждый из которых имеет свой порядковый номер, по которому элемент можно найти.
  2. for line in reversed(lines): — пробегаем по всем элементам списка lines (по каждой line)
  3. bot. send_message(message. chat. id, text=line — такую конструкцию мы уже встречали. Выводим в каждом отдельном сообщении одну строку.

Итак, у вас должен получиться такой код.

Этот скрипт умеет принимать слова, переводить их, возвращать в бота и обрабатывать команду /vocabulary

Давайте проверим, как он выполняется. Для этого напишем боту 12 слов и выполним команду /vocabulary. По идее, он должен вывести последние 10 слов.

Проверяем команду /vocabulary

Я вас поздравляю, вы научились работать с файлами в Python и создавать команды в Телеграм-боте.

💪Задачи для закрепления навыков:

  • Попробуйте вывести последние 5 слов
  • Попробуйте сделать это в том порядке, в котором вы их добавляли (старое добавленное выводим первым).

7. Самое интересное! Подключаем и используем OpenAI API (Chat GPT)

Эта часть, как мне кажется, самая крутая, потому что мы будем работать с мощной технологией, которая превратит наш простенький Телеграм-бот в MVP стартапа на базе ChatGPT. Я конечно, отчасти иронизирую, но в каждой шутке есть доля правды.

Сейчас мы уже полностью готовы к ее использованию: мы знаем, что такое API, знаем, как импортировать и устанавливать модули, знаем, как пользоваться токенами.

Перед тем как приступим к программированию сделаем три действия: зарегистрируемся (или авторизуемся) в OpenAI, сделаем промпт-дизайн и подключим с помощью токена наш аккаунт в OpenAI.

Регистрация в OpenAI

  1. Если вы в РФ, то доступ к OpenAI может быть ограничен. Воспользуйтесь инструкциями из этой статьи
  2. Если вы не в РФ, вбивайте в поиск «open ai api», переходите на сайт OpenAI, ищите там надпись Sign UP и регистрируетесь любым удобным способом, например, с помощью Google-аккаунта.

Промпт-дизайн в ChatGPT

Промпт — это наша инструкция, которую мы посылаем нейросети в надежде, что она сгенерирует нам классный ответ.

Перед тем как подключить OpenAI API к Телеграм-боту через Python, нам нужно через веб-интерфейс потренироваться создавать идеальный запрос для генерации нужного результата.

Я бы хотел отправлять нейросети английское слово, а в ответ получать тест вида «выберите верный перевод». Также нужно попросить нейросеть указать правильный ответ.

Заходим в chat. openai. com (эта ссылка, я думаю. меняться не будет). Создаем новый чат. Пишем в нем буквально следующее:

Сочини тест для изучения английского слова с четырьмя вариантами ответов​ к слову Deteriorate

Результат получается интересным:

Но есть проблема: нейросеть выдает сразу несколько тестов и формулирует вопрос на английском. Лучший способ получить от нее идеальный результат — показать ей пример или шаблон. Создадим новый чат и переформулируем запрос:

Придумай одно задание на русском языке для изучения следующего английского слова: deteriorate. Пример задания: Как перевести слово "frog"? Варианты ответов: 1: Лось 2: Лягушка (правильный ответ) 3: Краб 4: Медведь

Вот что нейросеть для нас сочинила, получилось замечательно.

К программе мы будет подключать немного более простую, чем ChatGPT, версию от OpenAI, она называется Da Vinci 003. Давайте убедимся, что она так же блестяще справится с задачей. Для этого ищем в поиске playground openai, заходим на сайт open ai и ищем раздел Playground.

Сначала выберите справа нейросеть da vinci 003, другие настройки не меняйте.

Теперь введите запрос и нажмите Submit. Результат получается отличный.

Подобный ответ нам прилетит, если мы отправим запрос из программы к нейросети. Нам нужно будет автоматически вычленить из него варианты ответов (это будут последние 4 строки ответа) и отрезать словосочетание «правильный ответ» вместе со скобками.

Чтобы получить код для генерации подобных ответов, достаточно нажать на кнопку View code в правой части интерфейса Playground.

И еще важный нюанс, мы должны взять не весь диалог с нейросетью, а только часть до слова «deteriorate». Само слово мы будем подставлять из программы. Мы получаем код:

Скопируйте его целиком, вот так:

import os import openai openai.api_key = os.getenv("OPENAI_API_KEY") response = openai.Completion.create( model="text-davinci-003", prompt="Придумай одно задание на русском языке для изучения следующего английского слова: deteriorate. \n\nПример задания:\nКак перевести слово \"frog\"?\nВарианты ответов:\n1: Лось\n2: Лягушка (правильный ответ)\n3: Краб\n4: Медведь\n\nЗадание:\nКак перевести слово ", temperature=0.7, max_tokens=256, top_p=1, frequency_penalty=0, presence_penalty=0 )

И вставьте в вашу программу вот в эти места.

По умолчанию Open AI предлагает добавить свой токен с помощью «переменных окружения« операционной системы, и для этого импортирует «os». Но мы выбрали другой способ работы с токенами, поэтому убираем »import os», прописываем путь к токену openai. api_key и вставляем обращение к файлу confg. py.

openai.api_key = config.openai_token

Теперь идем в Open AI за токеном. Ссылку вы можете получить в окошке View code, которое мы открывали ранее, вот тут:

Либо на странице API keys, которая находится примерно вот здесь:

Копируете ваш API key (токен) и вставляете его в config. py.

Прописываем токены в config.py

Я снова замазал токены на скриншоте, чтобы продемонстрировать, что они секретные. Причем токен OpenAI еще более секретный, чем токен Telegot API. OpenAI списывает деньги за использование сервиса. Сначала виртуальные (их вам хватит на эксперименты), а затем реальные, если вы оформите подписку. Злоумышленник гипотетически может повлиять не только на вашу программу, но и на содержимое кошелька.

Давайте добавим внизу функцию print, чтобы проверить, что нейросеть выдает нам ответ.

print(response['choices'][0]['text'])

Здесь response — это ответ от нейросети. Мы пишем [«choices'][0]['text»], потому что выводим не весь ответ, а только текст ответа. Помимо текста там содержится еще много информации, она нам для работы программы не нужна.

У вас должен получиться такой код:

Жмем зеленый треугольник для запуска программы, и через несколько секунд получаем очередное чудо — нейросеть от Open AI ответила в нашу программу на Python.

Если вы допрограммировали до этого места, поздравляю, это очень круто. Вы научились работать с нейросетью через код на Python.

💪Задача для закрепления навыков:

Измените формулировку запроса к нейросети и посмотрите, какой будет ответ.

8. Программируем кнопки в Телеграм-боте с ответами теста, проверяем ответы пользователей

Создаем функцию создания теста

Сейчас мы создадим функцию, которая умеет на вход получить слово, а на выходе вернуть тест от Open AI.

Для этого перед блоком программы, который начинается с response, добавим такую строчку:

def make_test(word):
Содержание скрыто
Показать

Эта строчка означает, что мы создаем функцию с названием make_test и аргументом word.

Строчку после prompt = мы изменим, добавив вместо слова «deteriorate» (это то слово, которые мы вставляли для примера) нашу переменную word. Вот так это будет выглядеть. Обратите внимание, что в Python мы можем переносить строки. Тут я это сделал для удобочитаемости.

prompt="Придумай одно задание на русском языке для изучения следующего английского слова: "+word+". " "\n\nПример задания:\nКак перевести слово \"frog\"?\nВарианты ответов:" "\n1: Лось\n2: Лягушка (правильный ответ)\n3: Краб\n4: Медведь\n\nЗадание:\nКак перевести слово \""+ word+"?",

Возвращаем ответ с помощью return.

return("Как перевести слово <b>"+word+"</b>?"+(response['choices'][0]['text']))

Обратите внимание, мы добавляем в ответ слово word (наше искомое слово) , а также сам вопрос «как перевести слово..», т. к. нейросеть не присылает эту часть теста.

Также мы добавляем выражение <b></b>, которое делает текст жирным, если в bot. send_message мы пропишем параметр parse_mode=«html». Когда выведем текст, вы увидите, что искомое слово станет жирным.

Вызывать эту функцию мы будем из нашей функции, которая обрабатывает текст. Давайте сразу в ответ на введенное слово будем отправлять тест прямо в бота. Это временное решение, мы просто хотим убедиться, что тест генерируется.

bot.send_message(message.chat.id, text=make_test(message.text), parse_mode="html")

Вся программа уже не помещается в один скриншот, поэтому пролистайте галерею:

Запускаем программу. Вы знаете как это делать. Вот результат:

Все работает неплохо.

Простите, но на этом месте я задумался, правильно ли писать «варианты ответов» или «варианты ответа». Грамота. ру подсказывает, что правильно писать «выберите правильный ответ». Так и поступим.

Каждая мелочь может влиять на эмоции пользователя от общения с программой

Теперь все выглядит отлично, близится финал.

Результат генерации теста

Разбираем ответ Open AI на отдельные элементы

Ответ от нейросети мы получаем в виде единого текстового сообщения. Нам нужно разделить его на несколько строк, чтобы работать с каждым ответом отдельно.

В Python очень удобно работать с текстами (строками и символами). Есть замечательная функция split, которая поможет нам, ориентируясь на перенос строки (символ "\n"), разделить сообщение от нейросети на строки.

#разбиваем ответ на отдельные строки test = make_test(message.text).split("\n")
Содержание скрыто
Показать

Наша программа становится большой, и я решил отмечать специальными комментариями разные фрагменты кода, чтобы не запутаться. Комментарий начинается со знака решетки. В принципе, комментарии считаются моветоном, из кода должно быть понятно все без пояснений, но для учебной программы это может быть полезно.

Test должен быть списком строк. Выведем его на экран с помощью функции print, чтобы это проверить.

Разделяем ответ нейросети на отдельные строки. Проверяем результат

Теперь попробуем отдельно вычленить ответы. Для этого мы уберем print(test) и вместо него напишем следующий код.

#получаем варианты ответов for i in range (2,6): if (test[i].endswith(" (правильный ответ)")): print (test[i][:-19]) else: print(test[i])
Содержание скрыто
Показать

Объясню, что мы делаем. for i in range (2,6): — пробегаем циклом for с помощью i по диапазону от 2 до 6. Почему от 2 до 6 — потому что нам нужны ответы, они располагаются со второй по шестую строчку.

Содержание скрыто
Показать

Далее мы используем выражение if else, вы раньше с ним не сталкивались. Это условный оператор, это как бы стрелочник, который позволяет пустить вагон кода по разным путям в зависимости от условий. После if мы пишем условие «нет ли на конце слова «правильный ответ'?" и если есть — выводим ответ, отрезав от него последние 19 символов (словосочетание «правильный ответ»). В ином случае (else) выводим вариант ответа целиком.

Содержание скрыто
Показать

Знаю, это было сложно. Но посмотрев на результат выполнения кода, вы поймете, что мы сделали.

Давайте от вариантов ответа отрежем также цифру с точкой и пробелом

Для этого запишем вот такой код.

if (test[i].endswith(" (правильный ответ)")): print (test[i][3:-19]) else: print(test[i][3:])
Содержание скрыто
Показать

Вот эти выражения рядом со словом test — это очень интересные и полезные штуки. Давайте расшифруем выражение test[i][3:-19]. test — это отдельные строки из ответа Open AI, [i] означает, что нам нужна строчка из test с номером i. А выражение [3:-19] означает, что мы хотим отрезать 3 символа в начале (цифру, точку и пробел) и 19 от конца строки (фразу "(правильный ответ)").

Погодите, но как же мы теперь узнаем, какой ответ правильный? А давайте сохраним его в другой файл, который назовем «current_answer».

Сохраняем правильный ответ в файл

При открытии файла будем пользоваться режимом «w», а не «a», потому что мы хотим каждый раз »перетирать» значения в файле, а не дополнять, ведь текущий правильный ответ только один.

Пишем

with open ("current_answer.txt", "w") as file: file.write(test[i][3:-19])

Этот код мы вставляем под условие if (test[i]. endswith(" (правильный ответ)")): , то есть, мы пишем в файл данный ответ только тогда, когда это правильный ответ.

Запускаем программу. Вводим в телеграм-бота нашего енота.

Для проверки программы мы должны отправить запрос в виде слова

Заходим в папку с файлами проекта. Находим там новый файл current_answer.

Открываем его и видим там енота.

Файл  с правильным ответом

Выводим варианты ответов в виде кнопок KeyboardButton в Телеграм-боте

Теперь мы выведем варианты ответов в виде кнопок. Для создания кнопок в Телеграм боте нам нужно сделать разметку и расположить в ней элементы. Делается это такой строчкой.

markup = types.ReplyKeyboardMarkup(resize_keyboard=True, one_time_keyboard=True, row_width=2)

Добавляем types через import в верхней части кода:

from telebot import types

В данном случае нам не нужно дополнительно устанавливать модули, только подключить с помощью import.

Удаляем из кода временные сообщения, которые мы посылали в бот для проверки, я имею в виду вот эту строку bot. send_message(message. chat. id, text=make_test(message. text), parse_mode=«html»). А также убираем все print, которые также использовали для тестирования.

Теперь мы изменяем содержимое test, удаляя оттуда все лишние элементы Для этого элементу списка test и порядковым номером i мы присваиваем то же значение, только без лишних символов (цифр, пробелов и тд):

for i in range (2,6): if (test[i].endswith(" (правильный ответ)")): #убираем лишние символы из теста test[i] = test[i][3:-19] with open ("current_answer.txt", "w") as file: file.write(test[i][3:-19]) else: # убираем лишние символы из теста test[i] = test[i][3:]

Добавляем в кнопки (KeyboardButton) текст и передаем их в разметку (markup). Обратите внимание, что порядковые номера элементов test начинаются с цифры 2, потому что нулевой и первый элемент — это две вводные фразы теста, а далее идут как раз наши четыре варианта ответов.

#создаем кнопки с вариантами ответов и добавляем в разметку btn1 = types.KeyboardButton(test[2]) btn2 = types.KeyboardButton(test[3]) btn3 = types.KeyboardButton(test[4]) btn4 = types.KeyboardButton(test[5]) markup.add(btn1, btn2, btn3, btn4)

Приведу также более продвинутый способ выведения кнопок для более опытных читателей.

Добавляем пустой список кнопок.

btnlist = []

Внутри ветвей условного оператора добавляем кнопки к списку btnlist:

btnlist.append(types.KeyboardButton(test[i][3:-19])) и btnlist.append(types.KeyboardButton(test[i][3:]))

Передаем список кнопок в наш markup (разметку), добавляя вначале значок * (на данном этапе не важно, что она делает, просто добавьте ее):

markup.add(*btnlist)

Выбрав любой из способов заполнения кнопок, вы их в любом случае в итоге передаете в markup. Теперь можем вывести этот markup.

bot.send_message(message.chat.id, text=test[0]+"\n"+test[1], parse_mode="html", reply_markup=markup)

Приведу коды для первого и второго способа генерации кнопок в виде галереи. В чем их отличие? Первый визуально более наглядный, но позволяет работать только с 4-мя кнопками. Второй выглядит сложно, но более гибок. Для данного урока вполне подойдет первый способ.

Посмотрим, что получается:

Сгенерированный нейросетью тест

Проверяем, правильный ли ответ, и мотивируем пользователя

Итак, что у нас есть на данном этапе и что осталось сделать?

  1. Мы умеем генерировать тест (правда, делаем это каждый раз, когда пользователь вводит текст). Нужно создать функцию обработки команды /test и переместить генерацию теста туда.
  2. Мы умеем генерировать тест из последнего введенного слова. Нужно создать функцию, которая подбирает случайные слова в словаре.
  3. Мы умеем сохранять текущий верный ответ теста в файл. Нужно научиться сравнивать этот ответ с тем, что вводит пользователь.
  4. Мы умеем обрабатывать любые сообщения и переводить их. Но есть проблема — когда пользователь будет нажимать на кнопку ответа, в чат будет прилетать его вариант ответа в виде текста. Нужно научиться отделить ответы на тест и запросы на перевод и обрабатывать их по-разному.

Функция случайного выбора слова из словаря.

# функция random_word возвращает случайное слово из файла def random_word(file): # получаем из файла случайное слово with open(file, "r") as file: lines = file.readlines() top10 = lines[-10:] word = random.choice(top10)[:-1] if len(top10) > 0 else 'Raccoon' return word
Содержание скрыто
Показать

Выражение [-10:] берет последние 10 элементов списка строк файла. random.choice позволяет нам вернуть случайную строку (слово). [:-1] — отрезаем от слова перенос строки (\n).

Выражение if esle здесь записано новым способом, более лаконичным.

Функция обработки команды /test

В нее мы переносим весь код, связанный с обработкой ответа от нейросети, разделения его на варианты ответа и тд.

@bot.message_handler(commands=['test']) def show_test(message): #вызываем функцию random_word word = random_word("vocabulary.txt") # генерируем тест и разбиваем ответ от нейросети на отдельные строки test = make_test(word).split("\n") markup = types.ReplyKeyboardMarkup(resize_keyboard=True, one_time_keyboard=True, row_width=2) # получаем варианты ответов for i in range(2, 6): if (test[i].endswith(" (правильный ответ)")): # убираем лишние символы из варианта ответов и сохраняем ответ test[i] = test[i][3:-19] with open("current_answer.txt", "w") as file: file.write(test[i]) else: # убираем лишние символы из теста test[i] = test[i][3:] # создаем кнопки с вариантами ответов и добавляем в разметку btn1 = types.KeyboardButton(test[2]) btn2 = types.KeyboardButton(test[3]) btn3 = types.KeyboardButton(test[4]) btn4 = types.KeyboardButton(test[5]) markup.add(btn1, btn2, btn3, btn4) bot.send_message(message.chat.id, text=test[0] + "\n" + test[1], parse_mode="html", reply_markup=markup)

В функцию random_word мы передаем файл словаря в таком виде word = random_word(«vocabulary. txt»).

Давайте проверим вывод. Сначала я удалю все строки из файла vocabulary. txt, должен вернуться Racoon.

Теперь я добавлю несколько слов и проверю, что выдается случайный результат.

Разделяем состояния бота: тест отдельно, ввод и перевод — отдельно

Внутри функции обработки текста по сути нам нужно реализовать следующую логику:

  • Если файл current_answer — пустой, то мы не находимся в состоянии решения теста, мы должны переводить введенный текст.
  • Если файл current_answer — непустой, мы сейчас находимся в состоянии решения теста, мы должны проверить, совпадает ли введенный пользователем текст с содержимым файла current_answer. Если совпадает, пишем, что пользователь — молодец. Если не совпадает, пишем, что пользователь — не молодец.
  • После выполнения всех этих действий, мы должны очистить файл current_answer, т. к. мы уже не в состоянии теста.

Давайте теперь реализуем условный оператор if-elif-else в функции обработки текста.

Сначала мы сохраняем содержимое файла current_answer в переменную word.

with open("current_answer.txt", "r") as file: word = file.readlines()

Теперь проверяем, есть ли что-то в файле current_answer. Если нет, переводим текст и записываем результат в словарь.

if word == []: bot.send_message(message.chat.id, text=translator.translate(message.text, src="en", dest="ru").text) with open("vocabulary.txt", "a") as v_file: v_file.write(message.text + "\n")

Для проверки используем выражение if word == [] (или еще лучше if not word) то есть, проверяем, что слово не равно пустому списку.

Если у нас в файле «правильный ответ» есть слово и оно равно слову. которое ввел пользователь, то мы поздравляем его с правильным ответом.

elif word[0] == message.text: bot.send_message(message.chat.id, text=random.choice("🥳🎉👯🎊👍🦝🤩🥂🎂🕺")) bot.send_message(message.chat.id, text="Это верный ответ!") bot.send_message(message.chat.id, text="Вы можете продолжить проходить /test, либо переведите новое слово ", reply_markup=hidemarkup)

В ином случае (если введенное слово не совпадает с «правильным ответом») пишем, что угадано неверно.

else: bot.send_message(message.chat.id, text="😕") bot.send_message(message.chat.id, text="Увы, это не "+message.text+", а "+word[0]) bot.send_message(message.chat.id, text="Вы можете пройти еще один /test или переведите новое слово", reply_markup=hidemarkup)

Обратите внимание, при ответах мы передаем новый markup (hidemarkup), который убирает все кнопки (варианты ответов). Кнопки нам в данный момент не нужны.

Чтобы такой markup, прячущий кнопки, создать, вызываем следующий код непосредственно перед началом оператора if-else:

hidemarkup = types.ReplyKeyboardRemove()

Еще интересный момент — для поздравления пользователя мы используем функцию random, которая выбирает случайный веселый смайлик из списка. Приятная неожиданность никогда не помешает.

bot.send_message(message.chat.id, text=random.choice("🥳🎉👯🎊👍🦝🤩🥂🎂🕺"))

Также обратите внимание, что при вводе текста мы добавляем проверку на количество введенных слов, считая количество пробелов. Бот пока не сможет работать с идиомами и выражениями, и вернет ошибку, если пользователь введет больше двух слов.

if message.text.find(" ") > 0: bot.send_message(message.chat.id, text="Простите, мы на данный момент принимаем только отдельные слова")

В этом модуле вы вывели динамические кнопки в Телеграм-боте, написали собственный тест, а также научились управлять логикой программы.

💪Задача для закрепления навыков:

Сделайте несколько вариантов негативных ответов, используя функцию random.choice.

9. Тестируем программу и исправляем ошибки

Проверим, как все работает. Очистим словарь, и заполним числами от 1 до 10.

Несколько раз сгенерируем тест. Программа должна возвращать случайное число в качестве задания и генерировать случайные поздравительные смайлы.

В принципе, все работает неплохо, но есть нюанс. В процессе работы с программой я очень редко, но ловил неверный перевод слов. Вот пара вопиющих случаев:

Почему так происходит? При генерации ответов нейросеть, в зависимости от переданных в нее параметров temperature, top-p, frequency penalty и presense penalty, может быть более и менее "креативной", быть склонной выдавать одинаковые ответы или стараться не делать повторов. Возможно, она решила заменять правильные ответы неправильными для разнообразия. Вот разбор параметров нейросети.

Меняю параметры, меняю промпт, прописываю также текстом, что мне не нужны повторы слова, не нужны синонимы и тд:

Меняем вызов нейросети в коде.

Проверяем, работает лучше, но иногда все равно бывают сбои. Идея генерировать весь ответ через Open AI была наглядной и заманчивой, но плохой. Придется переделать эту функцию, общаться с нейросетью на английском (для надежности), а верный ответ сохранять в файл сразу, не получая его от нейросети, а перевод всех слов делать непосредственно перед выводом через Google.

Промпт:

Улучшенный prompt

Вместо Raccoon нужно будет вставить наше искомое слово. Получится так:

prompt="I'm composing a word test. I give you the word. You give me 3 options of wrong answers." "\nExample:\nI: Frog\nYou: \nElephant\nDog\nCat\nI:" + word + " \nYou:\n",

Код функции обработки теста становится более логичным.

# обрабатываем команду /test @bot.message_handler(commands=['test']) def show_test(message): # вызываем функцию random_word word = random_word("vocabulary.txt") # генерируем тест и разбиваем ответ от нейросети на отдельные строки test = make_test(word).split("\n") # добавляем в список наше искомое test.append(word) # добавляем в файл верный ответ, переведенный на русский with open("current_answer.txt", "w") as file: file.write(translator.translate(word, src="en", dest="ru").text) # перемешиваем ответы shuffle(test) for i in range(0, 4): test[i] = translator.translate(test[i], src="en", dest="ru").text markup = types.ReplyKeyboardMarkup(resize_keyboard=True, one_time_keyboard=True, row_width=2) # создаем кнопки с вариантами ответов и добавляем в разметку btn1 = types.KeyboardButton(test[0]) btn2 = types.KeyboardButton(test[1]) btn3 = types.KeyboardButton(test[2]) btn4 = types.KeyboardButton(test[3]) markup.add(btn1, btn2, btn3, btn4) bot.send_message(message.chat.id, text="Как перевести слово <b>" + word + "</b>?\nВыберите правильный ответ:", parse_mode="html", reply_markup=markup)
Содержание скрыто
Показать

Что тут делаем:

Содержание скрыто
Показать
  1. С помощью append добавляем верный вариант ответа в конец списка test.
  2. С помощью функции shuffle (модуль с которой нужно подключить через from random import shuffle) мы «перемешиваем» варианты ответов.
  3. Английские слова мы заменяем на русские с помощью translate.
  4. Переносим в эту функцию фразы «Как перевести слово…» и «Выберите правильный вариант ответа».

Проверил, все работает отлично. Одна проблема — некоторые слова начинаются с маленькой буквы. Чтобы исправить применяем функцию title.

test.append(word.title())

Также для устранения повторов я установил presence_penalty=1 при запросе к нейросети. Насколько я понимаю, при такой настройке нейросеть будет максимально стараться исключить повторы.

Нашел еще одну проблему в коде при тестировании — если вы впервые запускаете программу и у вас еще нет файла current_answer, программа вылетит с ошибкой. Мы пытаемся прочитать файл, которого нет. Решается выражением try-except, которое служит для обработки ошибок.

@bot.message_handler(content_types=['text']) def handle_message(message): try: with open("current_answer.txt", "r") as file: word = file.readlines() except FileNotFoundError: c_file = open("current_answer.txt", "w") c_file.close() with open("current_answer.txt", "r") as file: word = file.readlines()

Try - попробуем открыть файл - ecept - если файла не существует, создадим файл и попробуем его открыть.

В этом модуле мы научились тестировать итоговую программу и исправлять неверные решения.

💪Задача для закрепления навыков:

Потестируйте программу самостоятельно. Не щадите ее, отправляйте тексты на неправильных языках, пишите несуществующие слова, несколько раз подряд прокликивайте кнопки. Уверен, вы найдете еще ошибки.

10. Делаем фирменный стиль, настраиваем команды /start и /help. И — урок окончен.

Мы же деаем MVP для стартапа, а не просто программу, не так ли? А что в стартапе еще важнее, чем программа? Конечно, фирменный стиль.

Т. к. енот уже стал частью программы, я решил именно его использовать в качестве маскота. Не путать с Vik Enot.

Чтобы получить некого умного енота, забиваю в бесплатную нейросеть (в бота, о котором писал выше) запросы типа мультяшный енот ученый, енот лингвист, енот математик, и получаю что-то вот такое. Но зато бесплатно.

Выбираю енота-математика. Немного фотошоплю с помощью бесплатной Figma и добавляю в команду /start.

Команда "Старт"

Заполняем также функцию для команды /help. Тестирую вывод:

Привожу код для /start и /help. Обратите внимание, что мы используем parse_mode=«html», чтобы иметь возможность добавлять теги (жирное) и (подчеркнутое) для форматирования текста.

# обрабатываем команду /start @bot.message_handler(commands=['start']) def show_start(message): bot.send_photo(message.chat.id, photo=open("Raccoon1.png", 'rb'), caption="") bot.send_message(message.chat.id, text="<u>Привет! Я бот, который помогает изучать новые английские слова и лучше их запомнить.</u>\n\n" "Напишите английское слово и отправьте его мне", parse_mode="html") bot.send_message(message.chat.id, text="👇")
# обрабатываем команду /help @bot.message_handler(commands=['help']) def show_start(message): bot.send_photo(message.chat.id, photo=open("Raccoon2.png", 'rb'), caption="") bot.send_message(message.chat.id, text="<b>Как пользоваться ботом</b>\n\n" "💡 Когда вы читаете книгу на " "английском языке и встречаете <b>новое слово</b>, отправьте его мне, " "я его переведу и запишу в словарик.\n\n" "💡 Вы можете <b>посмотреть последние добавленные слова</b> с помощью команды " "/vocabulary \n\n" "💡 Вы также можете получить <b>индивидуальный тест</b> для лучшего запоминания" "последних добавленных слов. Для этого выберите команду /test\n\n" "Если вы хотите снова меня увидеть, напишите /start\n\n", parse_mode="html")

Для отправки картинок используется команда send_photo, также вам нужно положить файлы (в данном случае Raccoon.png и Raccoon2.png, но вы можете использовать любые) в папку проекта.

Добавляем в бота аватар и описание, также через @botfather.

Пишем /mybots > выбираем нашего бота > Edit Bot > Edit Botpic.

Меняю имя бота и заполняю описания с помощью /mybots > выбираем нашего бота > Edit Bot > Edit Name / Edit About.

Вышло вот так. По-моему, неплохо.

Дополнительный функция

На этом месте я подумал, что наша программа простовата для искусственного интеллекта OpenAI. Но программирование тем и привлекательно, что дает неограниченные возможности для созидания. Мы уже подключили нейросеть и можем решать любые языковые задачи, которые придут нам на ум.

Тратим 2 минуты и дописываем команду /compose, которая берет три последних слова из словаря и сочиняет из них предложение. Почему бы не показать новые слова в контексте использования?

Вот такая функция (копируемый код будет ниже).

Вот такой результат.

Скринкаст использования программы.

Еще я попробовал поставить нашу нейросеть в тупик, прислав несколько несочетаемых слов (цемент, жимолость и одалживать). Справилась она неплохо.

Приведу полный код нашей программы.

Для того чтобы сделать наш итоговый код более красивым, выделяем текст кода и выполняем команду Ctrl + Alt + L. Эта команда убирает лишние отступы, выравнивает строчки. Привожу полный код программы.

Чать 1.

import telebot import config from googletrans import Translator import openai from telebot import types import random from random import shuffle # подключаем токены bot = telebot.TeleBot(config.tg_token) openai.api_key = config.openai_token translator = Translator(service_urls=['translate.googleapis.com']) # возвращаем варианты ответов от нейросети def make_test(word): response = openai.Completion.create( model="text-davinci-003", prompt="I'm composing a word test. I give you the word. You give me 3 options of wrong answers." " No repeating answers." "\nExample:\nI: Frog\nYou: \nElephant\nDog\nCat\nI:" + word + " \nYou:\n", temperature=0.7, max_tokens=256, top_p=1, frequency_penalty=0, presence_penalty=1 ) return response['choices'][0]['text'] # функция random_word возвращает случайное слово из файла def random_word(file): # получаем из файла случайное слово with open(file, "r") as file: lines = file.readlines() top10 = lines[-10:] word = random.choice(top10)[:-1] if len(top10) > 0 else 'Raccoon' return word # обрабатываем команду /start @bot.message_handler(commands=['start']) def show_start(message): bot.send_photo(message.chat.id, photo=open("Raccoon1.png", 'rb'), caption="") bot.send_message(message.chat.id, text="<u>Привет! Я бот, который помогает изучать новые " "английские слова и лучше их запомнить.</u>\n\n" "Напишите английское слово и отправьте его мне", parse_mode="html") bot.send_message(message.chat.id, text="👇") # обрабатываем команду /help @bot.message_handler(commands=['help']) def show_start(message): bot.send_photo(message.chat.id, photo=open("Raccoon2.png", 'rb'), caption="") bot.send_message(message.chat.id, text="<b>Как пользоваться ботом</b>\n\n" "💡 Когда вы читаете книгу на " "английском языке и встречаете <b>новое слово</b>, отправьте его мне, " "я его переведу и запишу в словарик.\n\n" "💡 Вы можете <b>посмотреть последние добавленные слова</b> с помощью команды " "/vocabulary \n\n" "💡 С помощью команды /compose вы можете" " сгенерировать <b>примеры использования</b> новых слов \n\n" "💡 Вы также можете получить <b>индивидуальный тест</b> для лучшего запоминания " "последних добавленных слов. Для этого выберите команду /test\n\n" "Если вы хотите снова меня увидеть, напишите /start\n\n", parse_mode="html")

Часть 2.

# обрабатываем команду /compose @bot.message_handler(commands=['compose']) def show_start(message): with open("vocabulary.txt", "r") as file: words = file.readlines() n = len(words) word1 = words[n - 1] word2 = words[n - 2] word3 = words[n - 3] response = openai.Completion.create( model="text-davinci-003", prompt="Compose a sentence using " "words" + word1 + ", " + word2 + ", " + word3 + "return each of these words in <b></b> tag", temperature=0.7, max_tokens=256, top_p=1, frequency_penalty=0, presence_penalty=1 ) bot.send_message(message.chat.id, text=response['choices'][0]['text'], parse_mode="html") # обрабатываем команду /test @bot.message_handler(commands=['test']) def show_test(message): # вызываем функцию random_word word = random_word("vocabulary.txt") # генерируем тест и разбиваем ответ от нейросети на отдельные строки test = make_test(word.title()).split("\n") # добавляем в список наше искомое test.append(word.title()) # добавляем в файл верный ответ, переведенный на русский with open("current_answer.txt", "w") as file: file.write(translator.translate(word, src="en", dest="ru").text.title()) # перемешиваем ответы shuffle(test) for i in range(0, 4): test[i] = translator.translate(test[i], src="en", dest="ru").text markup = types.ReplyKeyboardMarkup(resize_keyboard=True, one_time_keyboard=True, row_width=2) # создаем кнопки с вариантами ответов и добавляем в разметку btn1 = types.KeyboardButton(test[0].title()) btn2 = types.KeyboardButton(test[1].title()) btn3 = types.KeyboardButton(test[2].title()) btn4 = types.KeyboardButton(test[3].title()) markup.add(btn1, btn2, btn3, btn4) bot.send_message(message.chat.id, text="Как перевести слово <b>" + word.title() + "</b>?\nВыберите правильный ответ:", parse_mode="html", reply_markup=markup) # обрабатываем команду /vocabulary @bot.message_handler(commands=['vocabulary']) def show_vocabulary(message): with open("vocabulary.txt", "r") as file: lines = file.readlines()[-10:] for line in reversed(lines): bot.send_message(message.chat.id, text=line) # обрабатываем текстовое сообщение от пользователя @bot.message_handler(content_types=['text']) def handle_message(message): try: with open("current_answer.txt", "r") as file: word = file.readlines() except FileNotFoundError: c_file = open("current_answer.txt", "w") c_file.close() with open("current_answer.txt", "r") as file: word = file.readlines() hidemarkup = types.ReplyKeyboardRemove() if not word: if message.text.find(" ") > 0: bot.send_message(message.chat.id, text="Простите, мы на данный момент принимаем только отдельные слова") else: bot.send_message(message.chat.id, text=translator.translate(message.text, src="en", dest="ru").text, reply_markup=hidemarkup) with open("vocabulary.txt", "a") as v_file: v_file.write(message.text.title() + "\n") elif word[0] == message.text: bot.send_message(message.chat.id, text=random.choice("🥳🎉👯🎊👍🦝🤩🥂🎂🕺")) bot.send_message(message.chat.id, text="Это верный ответ!") bot.send_message(message.chat.id, text="Вы можете продолжить проходить /test, либо переведите новое слово ", reply_markup=hidemarkup) else: bot.send_message(message.chat.id, text="😕") bot.send_message(message.chat.id, text="Увы, это не " + message.text + ", а " + word[0]) bot.send_message(message.chat.id, text="Вы можете пройти еще один /test или переведите новое слово", reply_markup=hidemarkup) with open("current_answer.txt", "w") as file: file.write("") bot.polling()

Как выполнить урок на Mac.

Загружаем PyCharm, версию Community для Mac.

Устанавливаем XCode for mac. На самом деле, нужен не весь Xcode, а только Xcode Command Line Tool. Его можно найти по вот этому адресу. Введите в поиск «Xcode» и найдите версию для вашей версии Mac ОС.

Создайте новый проект в PyCharm, venv должно активироваться само.

Все прочие шаги урока не отличаются для Win и Mac.

Как весь урок пройти вообще без установки программ, непосредственно в браузере.

Это очень легкий способ. В нем есть минусы, но для данной задачи вполне подойдет.

Заходим в Google Collab (это среда разработки, которая может работать в браузере). Для этого пишем в поиске google collab

Вставляем наш итоговый код в правой части интерфейса.

Загружаем файлы в левой части интерфейса.

Модули тут устанавливаются вот такой записью.

Запускаем, все работает. Так как мы здесь разместили наш файл config, бот будет работать по той же ссылке с тем же аккаунтом Open AI.

Наша программа еще далека от совершенства. Опишу дальнейшие улучшения. Если вы хотите узнать, как это все делать, пожалуйста, поставьте лайк статье. Если она наберет 50 лайков, то я сделаю второй, более продвинутый урок.

  1. Запуск программы на сервере на Linux (сейчас вы можете запустить ее только на своем компьютере, это неудобно).
  2. Запуск сервиса, который позволяет программе работать 24/7 и перезапускает ее в случае краша.
  3. Подключение базы данных, чтобы для каждого пользователя хранить его словарь и его правильный ответ.
  4. Можно также сделать настраиваемым для каждого пользователя количество последних слов для теста (не 10, а 20, например).
  5. Отправка теста по таймеру (например, 3 раза в день).
  6. Реализуем еще несколько вариантов теста (например, будем тренировать spelling — правильное написание, выдавая отдельные буквы).
  7. Функция выбора языков для разных пользователей.
  8. Генерация аудио из текста и озвучивание переведенного слова, чтобы пользователь запоминал еще и произношение новых слов.
  9. Прием на вход голосовых сообщений от пользователя.
  10. Возможно. даже обработка идиом или word chunks
  11. Обработка всех возможных ошибок и сценариев использования

Напишите в комментариях, получилось ли у вас выполнить задачу? Какие возникли трудности? Что бы вы хотели разобрать в следующих уроках (например, сайты, приложения)?

0
81 комментарий
Написать комментарий...
badResistor

Лол скилл фактори и прочие напряглись. Везде ооп лесом, только тут бесплатно)
хорошо сделано!

Ответить
Развернуть ветку
Игорь Диев
Автор

Спасибо!
ООП это не для новичков и не за 'один день', но есть идея сделать материал по нему. Очень наглядную задачу, где будет видно, в чем его удобство и красота

Ответить
Развернуть ветку
11 комментариев
Иван Лисовец

не переживайте, пока есть мамонты скилл фактори и прочим нечего переживать

Ответить
Развернуть ветку
1 комментарий
Дмитрий Перепёлкин

Мне кажется это статья для хабра, тут, всё же, аудитория немного не та.
Но, поддерживаю @badResistor лучше в как можно большем количестве ресурсов давать бесплатные уроки, чтобы люди перестали уже кормить в конец охуевшие skillbox, skillfactory и т.п.

Ответить
Развернуть ветку
badResistor

Не, такого легкого подхода надо больше и везде. Прога в 21ом веке это как уметь читать в 20ом

Ответить
Развернуть ветку
5 комментариев
Еvgeniy Gutsal

Монументальная работа!

Ответить
Развернуть ветку
Игорь Диев
Автор

Мне самому пошагового гайда не хватало, когда начал изучать чат-боты или OpenAI. Решил сделать "как для себя"

Ответить
Развернуть ветку
2 комментария
Продюсер душнила

По моему, это самое понятное и интересное обучение программированию, которое я, как гуманитарий, когда либо видел! Автору спасибо! Хочется еще подобных кейсов увидеть.

Ответить
Развернуть ветку
Игорь Диев
Автор

А это самый приятный комментарий, спасибо!

Мне как раз хотелось более или менее популярно показать, чем именно занимаются программисты. На самом деле, профессиональное программирование - это очень сложная дисциплина, но какую-то базовую программу, на мой взгляд. может написать почти любой человек без особого опыта

Ответить
Развернуть ветку
3 комментария
Игорь Диев
Автор

Привет! Вторую статью допилил, надеюсь, будет интересно https://vc.ru/u/8087-igor-diev/653624-vyzval-demona-zapustiv-chatgpt-na-servere

Ответить
Развернуть ветку
1 комментарий
Дмитрий Беговатов

Спасибо за ваш труд, мне как раз было интересно как сделать бота на питоне с интеграцией GPT и как его запустить на отдельном сервере. Надеюсь, наберется 50 лайков.

P.S. Сколько времени на верстку этого всего ушло я даже не спрашиваю, догадываюсь, что много!

Ответить
Развернуть ветку
Дмитрий Перепёлкин
Сколько времени на верстку этого всего ушло я даже не спрашиваю, догадываюсь, что много!

Вангую, что целый день

Ответить
Развернуть ветку
Игорь Диев
Автор

Первые строчки материала я написал, если честно, 13-го марта ))

Ответить
Развернуть ветку
Игорь Диев
Автор
Ответить
Развернуть ветку
1 комментарий
Андрей Байкалов

"Хобби-программист" – а что, хорошо звучит...

Ответить
Развернуть ветку
Игорь Диев
Автор

Это не в том смысле, что я работал программистом, а потом меня уволили и я стал хобби-программистом )) Это в том смысле, что я никогда не работал программистом, да и не планирую

Ответить
Развернуть ветку
Аккаунт удален

Комментарий недоступен

Ответить
Развернуть ветку
Игорь Диев
Автор

У меня монитор при ярком освещении плохо отображает темную тему, поэтому часто сам светлой темой пользуюсь. Для урока выбрал темную, потому что, насколько я понимаю, для большинства так удобнее

Ответить
Развернуть ветку
1 комментарий
Vlad

Сделайте игру. Пишу cat. Чатгпт подкидывает 3 предложения со словом cat. Вижу там слово "fire" получаю и перевод и еще 3 предложения где это слово используется, и так можно погружаться дальше в бесконечность

Ответить
Развернуть ветку
Александр Петров

Очень👍🏻
Вспомнил, лет двадцать назад была прога, которая генерировала трёхэтажные матерные ругательства

Ответить
Развернуть ветку
Ildarik

Большое спасибо за проделанную работу 👍 очень интересно и доступно

Ответить
Развернуть ветку
Murat Oshroev

Респект!)

Ответить
Развернуть ветку
stark

Вы пишите на библиотеке pyTelegrambotapi судя по транскрипшену, но предлагаете установить что то левое…
If elif лучше заменить на match/case
Команды можно импортировать прямо из кода, типы все равно импортировали.

По этой библиотеке примерно миллиард примеров и документаций, лучше бы показали aiogram

Ответить
Развернуть ветку
stark

Ну и вот это
if word == []:
Никогда не отработает

Ответить
Развернуть ветку
4 комментария
Дмитрий Перепёлкин
If elif лучше заменить на match/case

Не все любят case. И чем лучше? AFAIK python также будет по case идти как по elif, кроме синтаксиса никакого прироста, но могу ошибаться.

лучше бы показали aiogram

На SO полно вопросов ответов )

Ответить
Развернуть ветку
1 комментарий
Игорь Диев
Автор

По телеграму - согласен, много. Возможно, еще придумаю урок по aiogram. Про модули - я хотел показать, как ставить через терминал, т.к. в следующем уроке будем выкладывать на сервер, там же все равно придется модули ставить командами. Про telebot - спасибо, я думал это синонимы с pyTelegramBotAPI

Ответить
Развернуть ветку
Vlad

Где ссылка на бота?
(Нашел)

Ответить
Развернуть ветку
Vlad

Но лучше разместить в конце поста по традиции !

Ответить
Развернуть ветку
2 комментария
Vlad

Чет не пашет, где там обещенная игра в кошки, с 4мя ответами?

Ответить
Развернуть ветку
Игорь Диев
Автор

Введите слова в словарь, нажмите /test
Если ничего не выдает, то Open AI может висеть )

Ответить
Развернуть ветку
2 комментария
Vlad
Ответить
Развернуть ветку
Игорь Диев
Автор

Ну по задумке это программа для тех, кто учит английский, читая книги на английском :) Типа такая целевая аудитория

Ответить
Развернуть ветку
Игорь Диев
Автор

Но поверьте, любой, кто решит написать по уроку данную программу, может научить ее принимать русские слова

Ответить
Развернуть ветку
Vlad

Тогда нужно второй вариант для тех кто учит английский - придумываю предложение "какая вкусная селедка", понимаю что я не знаю слово "селедка" вбиваю и получаю ответ

Ответить
Развернуть ветку
Игорь Диев
Автор

Да, хорошая идея. А вы видели приложение Drops? Там как раз для начинающих, очень крутое

Ответить
Развернуть ветку
Vlad

Такой вопрос. Какая цель статьи? Продажа курсов по обучению? Просто не помню что бы вот так кто-то делал на vc, тут вроде не хабр , но идея прикольная

Ответить
Развернуть ветку
Игорь Диев
Автор

Цели конкретной нет. Давно хотел что-то обучающее для неподготовленной аудитории сделать. Сначала хотел на YouTube в виде видео сделать урок, но потом решил в виде текста на vc

Ответить
Развернуть ветку
evilUnion

На Хабре разнесут качество кода. Вообще можно было сразу на django делать, чтобы была админ панель и сохранение в БД.
Ну и за чат надо будет платить, api там денег стоит

Ответить
Развернуть ветку
Игорь Диев
Автор

Про платность чата писал вот тут: OpenAI списывает деньги за использование сервиса. Сначала виртуальные (их вам хватит на эксперименты), а затем реальные, если вы оформите подписку.

Про качество кода: что-то упрощал специально для наглядности. Где-то может быть ламерство. Можете уточнить. как вы предложили бы улучшить? Я могу внести правки во второй статье

Ответить
Развернуть ветку
Александр Лапин

А круто получилось, пили ещё!

Ответить
Развернуть ветку
Игорь Диев
Автор

Спасибо! Пилю)

Ответить
Развернуть ветку
Игорь Диев
Автор
Ответить
Развернуть ветку
Кирюша Блиновский

красота!

Ответить
Развернуть ветку
Василий Дейков

Сыну 8 лет. На данный момент на 5 пункте. Делал все по Вашей инструкции, все получилось. Мальчишка загорелся хочет дойти до конца. Как все сделает, поделюсь его результатами)

Ответить
Развернуть ветку
Игорь Диев
Автор

Ого!! Я очень рад! Это дает +1000 к мотивации писать подобные статьи.

Моему сыну тоже 8, но он больше по визуальной части - собирает целые миры в Unity. Наверное, им скоро можно будет открывать игровую студию )

Ответить
Развернуть ветку
Игорь Диев
Автор

Но и 4-й пункт для 8 лет - уже очень круто

Ответить
Развернуть ветку
Vladimir Kazankov

круто. надо попробовать

Ответить
Развернуть ветку
78 комментариев
Раскрывать всегда