Хочу описать процесс создания приложения, которое работает с OpenAI API. Идея приложения возникла из потребности улучшить мой английский язык. Как говорится, если у вас есть молоток, то все проблемы выглядят как гвозди. Так как я программист, я решил написать Искусственный Интеллект, который будет заменять учителя английского языка.

Сценарий взаимодействия с приложением следующий: ученик задает тему урока, ИИ-учитель предоставляет список основных слов по теме. Ученик может спрашивать значение слов, которые ему не знакомы, ИИ-учитель предоставляет значения слов и примеры их использования. Затем ИИ-учитель вступает в диалог с учеником по заданной теме, ученик может отвечать на вопросы и задавать свои вопросы. ИИ-учитель также находит ошибки в ответах ученика.
Изначально я думал о создании полноценного веб-сервиса, на котором любой желающий сможет зарегистрироваться, привязать свою карту и начать обучение с ИИ-учителем. Однако в итоге, я решил начать с прототипа: консольного приложения на Rust, с которым можно будет вести диалог из терминала. Но потом я немного остыл от этой идеи, так как реализация полноценного сервиса требует открытия юридического лица, заключения договора с банком для обработки карт клиентов, аренды облака для сервера, разработки веб-версии ИИ-учителя и инвестиций в рекламную кампанию.
Я, конечно, могу выполнить все эти задачи, но создание такого сервиса будет достаточно долгим и необходимы значительные инвестиции. А сделать это на коленке и потерять свое время, и не иметь возможности составить конкуренцию с аналогичными стартапами из США, которые имеют достаточные средства на рекламу и развитие, неинтересно.
Вернемся к тонкостям реализации данного приложения. Для того чтобы получить список основных слов по теме, нужно выполнять запрос "completions" к OpenAI API. Этот запрос возвращает логическое завершение текста, который вы ему передадите, например, список основных слов по теме урока.
В итоге, методом проб и ошибок у меня получился запрос, который посылает программа, он выглядит следующим образом:
Give list of words linked with the subject "_TOPIC_". Words should comma separated. Only words.  
Где _TOPIC_ - тема урока с ИИ-учителем. Результатом работы этого запроса будет список слов, разделенных запятой, по нужной вам теме.
Далее по логике приложения необходимо было дать объяснение словам, которые не знает ученик. Получился следующий запрос:
Give answer what is "_WORD_" from the field "_TOPIC_".  
Где _WORD_ - слово, которое требует объяснения, _TOPIC_ - тема урока. В ответ вы получите 1-2 предложения, объясняющие данное слово.
Для наглядности, необходимо сгенерировать примеры использования данного слова. У меня получились следующие два запроса:
Give sentence with word "_WORD_" in field "_TOPIC_".  
Give rude sentence with word "_WORD_" in field "_TOPIC_".
На каждый из них я получил два разных предложения, в которых демонстрируется использование слова. Первое - общего характера, второе - немного с агрессией, для разнообразия, так сказать.
Далее приложение должно вступить в диалог с учащимся. Один из самых простых способов - это использовать список слов по теме урока и задать вопрос, используя его. У меня получился следующий запрос к OpenAI API:
Give _QUESTION_TYPE_. About "_TOPIC_". Use word "_WORD_". Do not use word "_TOPIC_".  
Где _QUESTION_TYPE_ - тип вопроса, который выбирается случайным образом из списка:
- Yes/No question 
- Wh-question 
- Choice question 
- Open-ended question 
- Hypothetical question 
- Leading question 
- Rhetorical question 
- Funnel question 
- Probing question 
- Clarifying question 
- Follow-up question 
- Forced-choice question 
- Matching question 
- Categorical question 
- Comparison question 
- Rude question 
- Polite question 
Что позволяет генерировать всегда разные вопросы даже при многократном прохождении урока по одной и той же теме.
При том в этом запросе я добавил в конец "Do not use word "_TOPIC_", чтобы в каждом вопросе от учителя не было слова с упоминанием темы урока, а то все предложения будут одинаковыми. И выглядит это очень не естественно.
Далее стоит задача определить, есть ли ошибки в ответе ученика. Для этого у OpenAI API есть запрос "edits". Он позволяет взять кусок текста и изменить в него. Там два параметра: исходный текст и то, что с ним надо сделать. В итоге, я, вызывая эту функцию, передавал текст ответа ученика и следующую строку:
Fix grammar and spelling.  
На выходе я получал строку с исправленным текстом. Если она не совпадала с тем что писал ученик, то я считал, что он ошибся, и выводил исправленный вариант.
В случае, когда ученик игнорирует вопрос ИИ-учителя и пишет в ответ свой вопрос, или отвечая на него, добавляет еще и свой, то я через OpenAI API "completions" генерирую ему ответ такой строкой:
Give _SENTENCE_TYPE_ answer on text: _STUDENT_QUESTION_.
Где _STUDENT_QUESTION_ - текст с вопросом учащегося, а _SENTENCE_TYPE_ - тип утвердительного предложения который выбирается случайным образом из следующего списка:
- Declarative 
- Imperative 
- Assertive 
- Optative 
- Exhortative 
- Descriptive 
- Expository 
- Complex 
- Polite 
- Rude 
Таким образом, даже на одни и те же вопросы ИИ-учитель всегда дает разный ответ, что вносит разнообразие во время общения.
Код консольной программы ИИ-учителя можно посмотреть здесь. Код библиотеки работающей с OpenAI API можно посмотреть здесь.
Ну и наконец, пример взаимодействия с этой программой, которая заменяет учителя английского языка:
Please enter a topic of the lesson:
hotel
Words of lesson:
- Lodging 
- Accommodation 
- Suite 
- Room 
- Reception 
- Concierge 
- Check-in 
- Check-out 
- Amenities 
- Restaurant 
- Bar 
- Pool 
- Spa 
- Gym 
- Valet 
- Bellhop 
Do you know all these words? Say: Yes or write unknown words comma separated:
bellhop, valet
Bellhop
A bellhop is a hotel employee who assists guests with their luggage and other needs. They are usually the first person a guest sees when they arrive at the hotel. Example 1: The bellhop carried our luggage to our room in the hotel. Example 2: "Hey bellhop, why are you so slow? Hurry up and get my bags to my room!"
Valet
Valet is a service offered by some hotels where a guest can have their car parked and retrieved by a hotel employee. Example 1: The hotel valet was very helpful in parking our car. Example 2: "If you can't do your job as a valet in this hotel, then you should find another job."
What type of establishment typically offers a variety of food and beverages for customers to enjoy?
I think it is restraunt.
I think it is restaurant. < grammar fixes
What is the process for check-in at a lodging establishment?
You need show a passport and student card. Is it correct?
You need to show a passport and student card. Is it correct? < grammar fixes
Yes, it is correct that you need to show a passport and student card in order to prove your identity and student status. Depending on the situation, you may need to provide additional documents such as a birth certificate or proof of address.
What kind of lodging would you prefer?
I prefer room with toulet and shower. If I visit hotel with wife then I prefer one big bad for two.
I prefer room with toilet and shower. If I visit hotel with wife then I prefer one big bad for two. < grammar fixes
What is the average wait time at the reception desk?
Usually it could take not more 5 minutes.
Usually it could take not more than 5 minutes. < grammar fixes
What services does a concierge provide?
You could ask a concierge call you at 7:00 am to wake you tommorow.
You could ask a concierge to call you at 7:00 am to wake you tomorrow. < grammar fixes
What kind of accommodation can you find when you travel?
When I travel I usualy take apartmant in hotel.
When I travel I usually take an apartment in a hotel. < grammar fixes
Do you have a swimming pool at your accommodation?
No We do not have swimming pool at the hotel.
No, we do not have a swimming pool at the hotel. < grammar fixes
Комментарии (28)
 - lair24.01.2023 22:26- Ну и наконец, пример взаимодействия с этой программой, которая заменяет учителя английского языка: - Пытается заменить, но не заменяет. Разбор ошибок нужен?  - igumnov Автор25.01.2023 04:49+1- Ага. Это прототип. Первая версия. Написал всего за пару вечеров.  - lair25.01.2023 04:55- Вы сам не видите, что ваш "учитель" (а) пропускает очень много языковых ошибок, и (б) вообще не проверяет текст на смысл?  - igumnov Автор25.01.2023 05:20- Я вижу. Вы тоже. Что дальше? 
 
 
 
 - lair24.01.2023 22:44- реализация полноценного сервиса требует [...] разработки веб-версии ИИ-учителя [..] Я, конечно, могу выполнить все эти задачи - Воу. Вы правда искренне считаете, что в одиночку можете сделать ИИ, который заменяет учителя иностранного языка? 
 - KValery25.01.2023 04:51- Идея для новой фичи: пользователь задаёт уровень знания языка, тему конкретную или без темы. Далее нужно сделать интеграцию чата с голосовым помощником, чтобы реализовать следующий процесс имитации разговорного диалога: пользователь говорит фразу голосовому помощнику, тот ее распознает и отправляет в gpt, gpt выдает текстовый ответ, голосовой помощник его озвучивает. - Я протестировал такое взаимодействие пока только на уровне текста и это уже супер для имитации реального диалога. При этом я заранее задал условие, чтобы на все мои ответы gpt отвечал только ОК, если ответ был написан правильно. И NO плюс верное написание, если мой ответ был написан неверно. - Если же будет добавлена функция голосовая, то это будет аналог живого устного общения, которого обычно очень не хватает при обучении языку.  - igumnov Автор25.01.2023 04:53- Годно, спасибо! Если случится чудо и бизнес ангел ворвется в мою дверь, то обязательно найму команду программистов и ученых лингвистов для реализации ваших идей. Ну или если заскучаю, может что-то сам допишу в рамках своего прототипа. 
 
 - leonidv25.01.2023 09:57- Исходя из тэга Rust и Open API в названии, я ожидал прочитать про создание сервиса на Rust. Как мне кажется, тэг Rust здесь лишний. 
 
           
 

PrinceKorwin
Спасибо за ссылки на код. Хочу себе сделать что-то подобное. В вашем коде смутило обилие . unwrap (). Это нормально? Тем более для библиотеки.
igumnov Автор
Не должна либа сваливаться в panic. Согласен с Вами. Просто хотел быстрее написать.
igumnov Автор
Убрал все unwrap
Теперь вот какая проблема, код стал тяжело читаем:
Может есть другой способ как красиво написать что бы читабельность была нормальная?
Ну и я что-то поленился заводить свои Error и просто возвращаю в случае ошибки String с текстом ошибки, наверное это не очень хорошо.
lain8dono
Для кода, написанного на скорую руку вполне. Но лучше по быстрому обернуть в thiserror.