И если Брейн не гений, то Пинки туп как пень
В детских мультиках и комедиях есть такая пара архетипичных героев: мегазлодей, который строит коварные планы, и его туповатый помощник, который не может сделать то, что от него попросят: например, Брейн и Пинки или Гарри и Марв.
Как правило, злодей не гнушается вломить своему помощнику по рылу или хотя бы просто наорать на него. Именно так строилось общение в нашей команде: я мечтал написать бота с шахматными дебютами, а ChatGPT упорно меня обманывал, раз за разом описывая вариант Найдорфа со вторым ходом черных Nf6.
В этом посте я расскажу о том, что это за бот, о технологическом стэке, который я выбрал и о проблемах, которые я встретил по дороге.
Ах да, плоттвист: в этих историях гений тоже всегда оказывается тупым. Так что если вы всегда ощущали себя так себе программистом, но всё ещё хотите кодить, читайте этот пост ради вдохновения.
Содержание
Посмотрите на содержание, чтобы понять, что вы хотите читать, а что нет. Оно написано, исходя из предположения, что вы не любопытны — если это ложное предположение, просто читайте все подряд.
Что это вообще за проект? — расскажу, зачем этот бот нужен. Читайте, если вы шахматист.
Как проект делался? — расскажу о том, с какой болью я столкнулся и распишу задачи каждого дня. Читайте, если вы, как и я, программист уровня "любитель", и вам нужно понять, что вы не один сидите с мыслью "не понимаю, что такое". Квинтессенция была в третьем дне (первые два дна были не такими сложными).
Что дальше? — расскажу о том, что планирую дальше. Читайте, если любите развивать продукты и можете сказать, что я прав или не прав.
Сегодня мы многое поняли — расскажу о том, какие выводы я для себя сделал. Читайте все, это самое главное в посте.
Что это вообще за проект?
Что бот делает?
Это бот, который разыгрывает с вами только дебюты. Логика - примерно как в карточках Anki: если вы зазубрите какую-то последовательность, то дальше сможете ее применять.
Порядок действий очень простой:
- Вы выбираете, каким дебютам хотите научиться
- Внутри этих дебютов есть разновидности - по кнопке "сыграем" бот выбирает одну из вариаций дебютов из вашей коллекции.
- Если вы разыграли дебют правильно, бот рассказывает вам его основные идеи.
Таким образом, я решаю проблему, которая возникает у меня как у шахматиста: иногда противники пытаются уйти в дебют, который я не очень хорошо знаю. Если я буду знать хотя бы какие-то вариации в этом дебюте — я смогу дотянуть до миттельшпиля. Ну а описание основных идей — это чтобы понимать, как выкарабкиваться после разыгранного дебюта.
Почему меня не устраивает игра с движками?
У движков есть две особенности:
- Я не знаю, как заставить их разыгрывать дебюты по моему выбору
- Я не знаю, как получить от них описание идей дебюта.
В общем, мне не нужна умная машина, которая будет думать. Мне нужен простой инструмент, который заставит меня зубрить вещи.
Кому может быть полезно?
Я думаю, что в основном это будет полезно шахматистам между 1600 и 2200 на ческоме:
- До 1600 вы, скорее, получите выгоду от фокусировки на одном-двух дебютах за каждую сторону; другие дебюты можно играть, исходя из базовых принципов, потому что ваши соперники все равно не знают дебюты глубоко.
- После 2200 вы уже примерно на уровне КМС, и к этому моменту вам стоит уже и так знать всё то, чему этот бот собирается людей учить.
А ещё этот бот вряд ли может быть единственным способом учить дебюты. Так же, как вы не можете изучить язык, зазубрив слова и даже выражения, вы не можете выучить дебют, заучив ходы и базовую идею. Все равно нужно читать более полное описание, изучать партии — но как заученные выражения в определенный момент оказываются нужны в речи, так и заученные последовательности ходов смогут подвести вас к знакомой позиции.
Как проект делался
День 1. Выбор технологического стэка и создание прототипа
Помните, я говорил, что гений с планами по захвату мира оказывается тупым? Так вот, я в целом периодически пописываю что-то на питоне, но раз за разом мне не удавалось запустить на нем нормального бота. Я путался, не понимая код в туториалах, и решил зайти с козырей — писать бота по официальному туториалу. В целом, он сам по себе написан не для новичков, но для одного из языков там были куски кода, которые почти что работали. Так я и выбрал себе Java 17 и писал это всё добро в InteliJ Idea. Ещё было слово Maven, если кому-то о чем-то это говорит.
Сначала я сделал бот как в уроке - он умел менять состояние и в одном состоянии повторять сообщение пользователя, а в другом - повторять его, но капсом. Я понял логику того, как бот читает текст, и задумался над тем, какие сообщения должен уметь принимать мой бот. На ум пришли две вещи:
- Выбор дебюта по названию
- Отправка хода.
Я примерно представлял, что мне нужно где-то хранить словарь дебютов, который бы имел в себе три сущности:
- Название дебюта
- Его определяющие ходы
- Его короткое описание
Я подумал, что незачем мне хранить это все в сторонних файлах и можно закинуть описания и ходы, которые нагенерит чатгпт. Ох, как же я ошибался!
В общем, после десятка попыток заставить чатгпт описывать дебюты так, как я хочу (если что, в шахматах ход - это 2 полухода, то есть машина раз за разом присылала мне половину работы), я смирился с тем, что что-то мне придётся переделывать, а для прототипа и так сойдет.
Также в описанной версии не предполагалось ничего Fancy, никакого удобного юикса, поэтому первая успешная сессия с ботом выглядела вот так:
Потом я добавил случайный выбор цвета и жизнь стала веселее.
Кстати, перед первой успешной сессией была пара забавных ошибок в моей логике, поэтому были ещё и 2 неуспешные сессии.
Первая:
И вторая:
Но тем не менее, пару багов я пофиксил и фактически бот решил первую задачу, которая на него возлагалась: я уже мог бы им пользоваться, чтобы учить дебюты самостоятельно.
Но тут взыграло тщеславие. Вы знаете, сколько людей играет в шахматы по всему миру? Я тоже не знаю, но думаю, что больше двадцати. Что если все они будут пользоваться моим ботом?
Чтобы это стало возможным, мне предстояло решить глобальные задачи:
- Сделать бот более fancy в управлении - ладно, я готов писать Sicilian Scheveningen, а также Nxd4 с правильным регистром, но на этом моменте отваливается 95% пользователей.
- Дать боту возможность работать не на моем компьютере
- Дать боту возможность работать с разными пользователями. Ну то есть так, как положено боту.
Из этого появились задачи на следующие дни:
- научиться коммитить в гит — впервые в жизни я почувствовал, что мне нужна система контроля версий. Поскольку бота в текущем виде уже можно было использовать, я не хотел его потерять в попытке сделать его публичным.
- поменять механизм наполнения дебютов, оно должно считываться из таблицы, а ещё оно должно хранить варианты некорректных ходов — лучше дать пользователю 4 кнопки с реалистичными опциями, чем просить от него ввести текст с ходом
- создать класс пользователя, в котором будет храниться значение текущего разговора для него лично - иначе бот будет получать смешаную информацию и станет бесполезным
- создать кнопки — это про юикс
- захостить — то, на чём я всегда обсирался с питоном
С гитом я разобрался вечером, а потом пошёл пить вино и спать.
День 2. Я орал, меня бесили.
Переделываю базу дебютов
Собственно говоря, я перешёл к выполнению задачек 2 и 3 из прошлого списка.
Начало дня выдалось сложноватым — я орал. Орал вслух около компьютера, а также матерился на ChatGPT. Ну а что вы хотели, я второй день в жизни на джаве программирую.
Дело было так: изнутри одного класса (Player) я объявлял инстанс другого класса (OpeningManager). Для этого инстанса мне нужно было использовать метод "набери дебютов", который, как следует из его названия, набирает дебюты из цсвшки.
Я никак не мог понять, почему заботливый IntelliJ подсказывает мне всё на одном шаге, но ничего не говорит на следующем:
private OpeningManager openingManager = new OpeningManager();
/*
вот тут IntelliJ пишет за меня примерно всё, для меня процесс нажатия кнопок выглядел буквально так: private Op tab tab = new tab;
*/
openingManager.readFromCSV("pathtomyfile");
/*
а вот тут IntelliJ начинала игнорировать существование моего инстанса и вообще говорила, что не знает, о чем это я
*/
С этим вопросом я обратился к чату джпт и раза 3 перепроверил всё, что он пишет. В один момент я отчаялся и попытался закомпилировать это с учетом красной линии, и отправил джпт ошибку:
java: <identifier> expected
На что мудрая машина сразу же отвечает: "Экий ты сударь простофиля, так ты засунь это внутрь конструктора, и всё пучком будет, вот так оно работает".
Я не знаю, есть ли смысл оскорблять ботов, и на всякий случай я перед ним потом извинился, но в моменте я чувствовал себя максимально по-Брейновски, поэтому написал так:
После этого пошло как-то полегче, и я посчитал, что задача минимум на день закрыта — теперь я могу фигачить разделение пользователей.
Разрешаем пользователям иметь некоммунистическую переписку с ботом
В целом с пользователями логика стала понятна сразу:
- То, что я раньше хранил в классе Bot, переходит в класс Player, а сам бот просто становится точкой входа сообщений. Он смотрит на айдишку, находит соответствующего игрока, и отправляет ему сообщение в зависимости от значения внутренних параметров этого игрока.
И здесь всё прошло довольно гладко: по сути я перебросил код из одного класса в другой, попутно поменяв некоторые моменты:
- Во-первых, я изменил класс, из которого берётся информация о дебютах, поэтому где-то пришлось обновить методы (но логика осталась прежней)
- Во-вторых, появилась новая логика — бот должен рандомно выбирать дебют из числа выбранных пользователем. Это было нелегко, и я уверен, что у меня есть раз 10 в коде моменты перехода из массива в список и обратно, которых более опытный программист мог бы избежать. К сожалению, мне было посрать.
- В-третьих, мне хотелось, чтобы класс Player отдавал всё сообщение единым текстом. Так что там, где я вчера, не думая, отправлял сообщения пользователю и продолжал что-то делать, сегодня пришлось совокуплять куски текста друг с другом.
Тем не менее, довольно быстро логика была прописана:
- Если мы получаем команду, ведем себя так
- Если активна эта команда, ведем себя так, а если та - эдак
В общем, создал искусственный интеллект, как и положено.
Запустил код в нынешнем виде (на этот момент старая и новая версия существуют параллельно, и старая нигде не ссылается на новую). Увидел, что всё работает по-старому и, помолясь, закоммитил изменения. Предстояли удаления кусков кода.
Чтобы быть ещё увереннее, попробовал что-то сбранчить. Впервые в жизни. И обнаружил, что оба созданных файла (OpeningsManager и Player) куда-то просрались. Вместе с ними просрался и я.
Если честно, при всей красоте IntelliJ мне кажется очень неинтуитивным её интерфейс. Примерно на все мне приходится гуглить, а потом ещё переспрашивать у чата джпт. В общем, спустя где-то 10-15 минут поисков я понял, что я всё же мастер над гитом и смог вернуться к своей хорошей версией. Предстояли удаления кусков кода.
Удаление кусков кода
Оно прошло на удивление гладко. В целом где-то за полчаса или типа того я настроил коннект между классами Bot и Player и код успешно скомпилировался. Наконец-то, моя первая переписка с новой версией бота.
Ну вы понели.
Пришлось дебажить примерно построчно. И примерно в каждой пятой строчке я находил ошибку в логике.
Сначала игроки не искались по памяти бота. Оказалось, что если список игроков — это null, то утверждение ids.contains не имеет смысла. Спасибо, что предупредил, ChatGPT!
Потом оказалось, что если список — null, то в него и вставить ничего нельзя. Спасибо, что предупредил, ChatGPT! И что повторно предупредил, когда минуту назад я спрашивал тебя про предыдущую строчку кода!
Потом в какой-то момент оказалось, что я ищу слово "correct", а в цсвшке только "Correct". Но это оказалось последней ошибкой, и вот гордый я играю со своим ботом по-новому:
Следующее, что я начал проверять — возможность параллельной игры. Моя жена под моим чутким руководством запускает бота, который со мной прошел половину дебюта, и пытается получить дебют для себя.
И тут что-то идёт не так:
Всё бы хорошо, но у меня нигде нет 13 first half-moves. Более того, почему-то бот сразу же отдал описание. У меня закралось подозрение, что переменные всё же перемешались между двумя пользователями, и количество ходов суммировалось с количеством ходов, а ответ сохранил кусок прошлого ответа.
Нет, дело было не в этом.
Просто если вы используете CSV с разделителем в виде запятой, избегайте запятых в тексте.
Кнопочки
Ну что же, бот структурно на этом моменте мне нравится, остаётся прикрутить кнопки, потому что ожидать, что пользователь корректно введёт шахматную нотацию без подсказок, я не хочу.
В целом всё получилось довольно быстро: я добавил класс Button Manager, у которого были сценарии на разные случаи жизни. Класс Button Manager делал работу, которую Player передавал Bot'у. Большую часть задачи я сделал за минут 20-30, добавив кнопки, куда хотел, кроме двух сценариев:
- Если кнопок быть не должно: впоследствии я убил на это час времени, но так и не справился. Отдельно передавал привет тому, кто придумал, что очистка клавиатурного лэйаута должна передаваться отдельным от самого лэайаута параметром.
- Кнопки, которыми пользователь может выбирать дебюты для изучения. О них — в следующем разделе.
Ой да ну его в жопу
Мне хотелось, чтобы выбор дебюта совершался примерно как совершается выбор страны в боте Оскара для Тайного Санты:
Но время подходило к двум часам ночи, и я решил, что это будет в скоупе будущих улучшений. Вместо этого я просто решил, что дефолтному пользователю подойдёт учить все дебюты, а недефолтный выполнит несложную инструкцию, в которой сам перечислит дебюты через запятую. Оставалось только показывать пользователю все дебюты, которые есть в базе.
И тут, кстати, случилось небольшое чудо.
Я в очередной раз стал формулировать запрос для чатджпт: вот, мол, у меня есть список дебютов, у них есть такой метод, мне нужно получить уникальный список. И ещё до того, как я сформулировал свой запрос, я понял, что я знаю, как его решить, и это было очень вдохновляющим опытом — на второй день кодинга, где я в основном "повторял за ботом" на неизвестном ранее языке, я понял, как можно решить задачу. Было круто!
На следующий день предстояло запустить бота не со своего компутера.
День 3. В лесах Амазонии.
Сначала я определился с хостингом: из-за того, что я постоянно путаюсь в интерфейсах гугла, я выбрал Амазон. Когда-то я уже регистрировал там аккаунт, о чём он мне сообщал, но зайти в него Амазон мне не разрешал. Полагаю, причина может быть в этом:
А может быть, просто в моей технической неграмотности.
В любом случае, новая почта + венгерский телефон + Револют решили вопросик.
Я запустил виртуальную машину на Amazon Linux и по инструкциям от Chat GPT справился практически со всем, включая установку джавы на эту машину. А затем начались проблемы —мой jar-файл не перекидывался на сервер, говоря, что у меня недостаточно прав.
Я вновь и вновь допытывался до чата, рассказывая ему о проблеме, и раз за разом чувствовал себя всё беспомощнее. Я уже дошёл до того, что дал вообще всем полные права (chmod 777), но сам я всё ещё не мог закинуть долбаный файл!
Вообще, честно говоря, ssh показалась мне очень странной херней от разработчиков для разработчиков. Неужели я один такой буратино, который не умеет делать всё в командной строке и ему бы графический интерфейс, где можно просто с папки на папку перекинуть?
Я позволил себе отдохнуть до вечера, и тут случилась Anna ex machina.
Моя жена, видя мои мучения и то, как я ору, предложила свою помощь. Первые пару часов у нее тоже возникали проблемы, пока она не попробовала подключиться к серверу через WinSCP. Вот там как раз был графический интерфейс и не было никаких проблем. В итоге jar-файл был на сервере и произошёл первый запуск. И всё получилось!
Нет.
На самом деле произошло вот это:
Между тем, суббота подошла к концу, а в воскресенье я решил последовать примеру Иисуса и оттянуться, не работая. Четвёртый день пришёлся на понедельник.
День 4. Заработало
В целом, ошибка с размещением файла хоть меня и удивила (я ожидал, что файл из ресурсов будет подтянут в jar), но не обескуражила. С новыми силами я пошёл к своему тупому помощнику и спустя минут 20-30 понял, что файл нужно искать не через указание на его путь, а через поиск в ресурсах.
Я по-новому указал на файл, пересобрал jar, мы закинули его на сервер, запустили, и - вуаля! - бот заработал! На этот раз по-настоящему.
Что дальше?
Во-первых, есть ряд программистских задач.
- Всё же сделать кнопочки для выбора дебюта.
- Формат шахматных картинок весит немного, и я уверен, что есть библиотеки, способные его генерировать. В нынешнем виде бот не умеет показывать картинки и "играть" приходится в уме. Это нормально для дебюта, потому что по сути нужно запомнить последовательность ходов, но хочется, чтобы те, кто запоминает её не текстом, а положением фигур на доске, тоже могли пользоваться ботом.
- До сих пор у бота было 2 пользователя, и хранить их информацию в оперативной памяти — ок. При этом хочется всё же научить бота периодически свою память чистить, а про пользователя не забывать.
Во-вторых, есть задача по наполнению базы дебютов. ChatGPT оказался для этой задачи слишком тупым, и у меня есть опасение, что придется наполнять её руками. Кстати, если бы бот был вам полезен и вы готовы предоставить свои руки, можете мне написать, и я скажу, как тут можно накраудсорсить. А если у вас есть идея, как получить список формата "дебют + описание" автоматизированно — это вообще было бы клево.
Наконец, в-третьих, мне бы хотелось, чтобы моим ботом попробовали пользоваться люди. Так что вот я написал этот пост и прямо сейчас сяду добавить в базу штук 20-30 дебютных вариаций, чтобы он был хоть чуточку полезным уже сейчас.
Сегодня мы многое поняли
Итак, за 4 дня работы с использованием тупого помощника и настоящего ангела-хранителя я справился с тем, чтобы у меня появился первый работающий бот.
Что я понял в процессе?
- ChatGPT в целом классно помогает сделать что-то новое. Отличие от гугла + StackOverFlow в том, что в любом моменте, где что-то непонятно, можно сказать ему: "Я не понял" — и инструкции будут даны более детально. Ещё можно лениться и просить его написать код, у меня так сделана примерно половина моего бота.
- Я очень эмоциональный человек и я обнаружил ещё одну скрытую возможность ChatGPT. Аня сказала, что я на удивление мало орал. Знаете почему?
А вот поэтому:
Чат давал мне возможность проораться. А вот почему мне это надо, я узнаю в четверг, на сессии с терапевткой.
3. Если моё главное опасение — что я что-то не смогу захостить, то в первую очередь надо проверять, могу ли я это захостить, а не писать два дня на джаве, а потом проверять.
4. Джава прикольная.
5. Я очень не люблю, когда инструменты делаются от программистов для программистов. Хочу, чтобы были инструменты от программистов для непрограммистов.
Всем пис, наслаждайтесь жижей!
CHIDOOR UTRIURD
Ouetoitbin Hmter
Должны быть десятки-сотен готовых баз дебютов в машиночитаемых форматах. Наверняка в том числе на github, и наверняка google/chatgpt должны про них знать. А перевести из одного формата в другой — дело техники.
Не удивлюсь, если есть даже какие-то стандартные форматы, чтобы можно было в бота новые дебюты загружать.
Классный пост, посмеялся!
Я тоже своего первого бота написал с помощью чатгпт и это тоже шахматный бот :D Только у меня он выплевывает новую задачку из топа личесс каждый день (если ты заходил в наш шахматный чатик, то видел поди, что он весь чат
засралзаполнил задачками).Насчет генерации картинок: есть библиотека chess которая по стандартной позиции генерит картинку (вот тут я это делаю). Это прям сильно помогло бы, все же без картинки сложно представлять, что там с позицией.
Если говорить о том, чтобы вывести этот проект на серьёзный уровень, где он будет приносить пользу, то у меня всегда была одна проблема с шахматными инди-проектами. Это объём. Вот на чесскоме в каждом варианте есть куча разветвлений, начиная с самых первых ходов
И проблема в том, что они все реально играются! Да, реже, но к первым 3-5 линиям всегда надо быть готовым, потому что это нифига не экзотика. А в этих 3-5 линиях внутри на каждом ходу есть еще своих 3-5 линий, причем, как за белых, так и за черных
И когда ты пишешь, что проект с базовым набором дебютов будет полезен вплоть до рейтинга 2200 на чесскоме, ты сильно преувеличиваешь. Чтобы дотуда добраться, надо уже изучить все свои варианты гораздо глубже. Я так говорю, потому что сам играю как раз примерно на этом уровне
Вот популярный челябинский вариант, и то место, откуда я начну анализировать. Всё что до этого - я уже знаю наизусть. И я не гений! Все мои соперники тоже это знают наизусть, потому что это популярный вариант
Поэтому, моё имхо, тут надо глобально выбрать: это проект для новичков, где можно обучиться базовым дебютам и самым популярным линиям хода до 10, либо это проект для всех, но тогда нужно добавлять возможность набирать и сохранять свои варианты для повторения по типу того же anki. В то, что один человек может объять необъятное и скопировать базу вариантов чесскома я не верю, поэтому даже не предлагаю
Как-то так, сори, что надушнил, просто буквально недавно уже натыкался на новый красивый проект для изучения дебютов, где бесплатная версия заканчивалась 10-м ходом :D А в моих личных записях меньше 15-го вариантов в принципе нет, а зачастую больше
А бот уже совсем все? Я то бы с интересом попробовал