Часть 2: Загрузка данных and Improving или "Хождение по промтам"
Цель этой публикации — показать процесс взаимодействия с ИИ при написании мобильного приложения. Обычно в таких историях публикуют исходный промт, а затем готовый результат. Здесь же хотелось показать более подробно именно сам процесс «Хождения по промтам», как по ходу выстраиваются «взаимоотношения» и происходит взаимообучение ИИ и разработчика. Думаю это будет полезно как уже работающим с ИИ для написания кода, так и тем, кто только начинает входить в этот сегодняшний main stream.
Статья написана в продолжение поста, в котором рассказывалось как с помощью Claude Sonnet 3.7 было написано небольшое мобильное приложение на SwiftUI. Это пользовательский список фильмов. И да, я знаю, что таких приложений вагон и маленькая тележка, но как любому разработчику не нравится брать что‑то навороченное и непонятное, а хочется, как всегда, сделать что‑то «простое и удобное».
Загрузка данных
После того как приложение заработало, захотелось внести туда данные. Начал делать это вручную, записывая один фильм за другим и получая известное удовольствие, когда видишь как программа работает, как удобно вносить данные, как приятно выглядит интерфейс и т. д.
Но текстовый файл, куда ранее вносил заметки о фильмах, получился очень большой. И по прикидкам вручную пришлось бы их вносить где‑то с месяц. Что, конечно же, надоест через несколько дней. И тогда появилась идея — а почему бы не использовать все тот же ИИ и для этой задачи?
Сказано — сделано. Идея была такая: из текстовой информации сделать JSON файл. Составил промт для Claude Sonnet (он обновился до v. 4), загрузил структуру модели и сам текстовый файл.
Кстати, по ходу, небольшое примечание по поводу выбора модели ИИ. Дело в том, что в недавних публикациях, здесь на Хабре, хвалили Claude Opus 4 по сравнению с Sonnet. Но когда я спросил сам ИИ, чем эти модели отличаются, он ответил, что Opus для более стратегических задач, таких, например, как анализ, проектирование и т. д., а Sonnet больше для написания конкретного кода. Даже немного попробовал их сравнить на каком‑то отдельном примере, но, возможно, задача была не очень сложная, поскольку особой разницы не заметил. Поэтому остался на Sonnet.
Первый блин, как и следовало ожидать, оказался комом. Вначале Клод бодро взялся за работу, но потом завис и уже ни на что не реагировал.
Тогда предложил ему выдавать результат частями, по 3 или по 5. Здесь, в свою очередь, случилась другая засада. Где‑то на третьей части он опять останавливался, но на этот раз выдавал сообщение, что достиг максимума по лимиту сообщения. И рядом была кнопочка Continue, которую он предлагал нажать, чтобы продолжить. Но работала она ненадёжно. Сразу после остановки вообще не реагировала, нужно было подождать какое‑то время, минуту другую. И дальше работа шла тоже не стабильно: делались копии незавершённых частей и они начинали путаться, снова всё останавливалось, и, кроме того, обрабатывалась не вся информация. Часть текста просто терялась.
Эта тема с лимитами оказалась с продолжением. В комментариях к первой части этой публикации был вопрос о длине контекста данной модели. Задаю Клоду этот вопрос, но он отвечает уклончиво, мол, depends от многих факторов.
Тогда решаю загружать текстовую информацию тоже частями. По ходу спрашиваю, сколько фильмов тебе загружать, чтобы не зависал и не терял информацию. Он отвечает 50–70. Ок, загружаю 60, но результат тот же.
Тут уже начинаю на него наезжать, типа «Почему ты зависаешь даже на том количестве фильмов, которое сам и определил?» И здесь он начинает как бы оправдываться и заодно выдаёт что‑то более конкретное. Что это зависит не от количества фильмов, а от обработки информации. Дальше уже не стал спрашивать. Скорее всего, что он как‑то там по‑своему анализирует, сопоставляет и т. д. Тем более что структура модели фильма включала в себя более 20 свойств.
В общем, урезал порцию информации до 10 фильмов. И тогда все пошло как по маслу. Он бодро взялся за работу и через несколько минут выдал результат.
Но тут возник следующий вопрос: а как приложение поднимет этот JSON файл? Не будут ли там ошибки? т. е., надо было проверить как эти данные будут выглядеть на экране.
Останавливаюсь, задаю ему промт и он выдаёт чуть ли не с сотню строк кода. Что вызывает определённый дискомфорт, поскольку уже и так много кода, которым не управляешь, а тут ещё больше.
Тогда появляется другое решение, а именно: использовать этот JSON файл как демо‑данные. Дело в том, что в приложении есть массив с несколькими записями, которые используются для отладки. т. е., при первом открытии приложения проверяется есть ли данные в памяти телефона. Если нет, то загружаются демо‑данные. Они помогают пользователю освоиться на первых порах, показывая как могут выглядеть внесённые данные. Дальше их можно или удалить, или сохранить. И при последующих открытиях приложения оно уже показывает не демо‑данные, а те, которые пользователь сохранил на диске телефона.
Отсюда, было решено использовать JSON файл именно как демо‑данные. Надо, конечно отметить, что у этого решения есть свои минусы. Самый первый, что это не best practice. И что файл с данными будет очень большим. Но поскольку приложение для себя и это делается только один раз, а потом эти огромные демо‑данные можно просто удалить, то выгода от замены ручного ввода на автоматизацию процесса перекрывает все минусы с лихвой. И самый главный плюс, что не надо никакого дополнительного кода. Нужно только положить данные в соответствующий массив, а дальше он автоматом будет показан на экране. И да, по ходу JSON файл уже превратился в Swift файл с соответствующей структурой.
Этот промт прошёл на ура и оставалось только нарезать исходный текстовый файл на куски и скармливать их ИИ для обработки. Чтобы ускорить процесс загружал по 20 файлов. Больше уже решил не испытывать судьбу.
Также сказались и особенности исходного контента. В частности, попадались группы фильмов, у которых, например, было только название, и которые все были не просмотрены. Так бывает, когда видишь где‑то на ТикТоке или в рилсах небольшой клип из фильма, он тебе понравился, хочется посмотреть весь фильм. Но в этот момент некогда, а потом забываешь. Поэтому по‑быстрому записываешь название в заметках, чтобы найти его потом в свободное время.
Заодно по ходу небольшое наблюдение о нашей нынешней реальности. При наличии современного интернета появилась привычка смотреть несколько фильмов одновременно, 3, а то и больше. Посмотришь один немного, потом другой, потом третий. Под настроение. И уже наверное мало кто помнит, что такое «Программа телепередач на завтра», о которой пел когда‑то Барыкин
В других случаях было ещё сложнее. Например, группа фильмов, которые все просмотрены, но информация о них записана бегло. В частности, некоторые фильмы были описаны структурировано, например: Название: Искатели приключений, Год: 2015 и т. д. А другие одной строкой, например: Угроза, боевик, 2023, спецназ освобождает заложников, 6.
Тогда было решено и эту задачу поручить ИИ. т. е., разобрать и сортировать информацию по полям структуры данных. С чем он, надо сказать, справился очень даже неплохо. Могу вспомнить только одну ошибку такого рода, когда он название жанра занёс в дополнительные заметки.
В итоге, путём такого вот «хождения по промтам» была обработана и структурирована информация о 347 фильмах.
Изменения и улучшения
Конечно, в процессе всей этой работы понадобилось что‑то изменить, улучшить и т. д. Это здесь, при написании статьи, для более удобного чтения, делишь текст на логические части. А там, по ходу, так или иначе получается в основном зигзагами. Попробовал сделать JSON файл, видишь, что надо проверить как он зайдет в приложение, задаешь ИИ новый промт, тестируешь и т. д.
Все изменения уже не упомнишь, но вот два были довольно интересными. Вначале захотелось в общем списке добавить три поля: Смотреть, Просмотрено и Повторный просмотр. Вначале хотел расписать промт, типа сделай горизонтальный стек и т. д., но потом решил пусть он сам думает, может предложит что‑то свое. В итоге, он предложил 2 варианта: один более визуально навороченный, с цветными плашками, а второй попроще, только текст. Попробовал оба, выбрал простой.
Во втором случае, когда нарезал текстовый файл разными кусками, то 20 фильмов, то 11, то 5, явно потребовалось как‑то контролировать количество загруженных фильмов на ходу. Запросил у него счетчик количества фильмов. Он опять выдал 2 варианта, тоже более навороченный и более простой. Здесь выбрал более навороченный. И он остался насовсем, потому как получилось удобно.
Здесь хочу отметить одну особенность промта, к которой пришел на таких вот примерах. А именно: не слишком опускаться в технические подробности и задавать способ реализации. Оно конечно, понятно, что ситуации могут быть разные, но вот в данном конкретном случае оказалось более продуктивно описать только задачу, т. е., что хочет получить пользователь, а не то как он хочет это получить.
Этот подход сработал и при общей постановке задачи. Вначале я несколько раз писал ему в стиле «сделай так», а потом, думаю, зачем тратить на это время. И стал ставить задачу в стиле «сделай это». И хотя он выдал массу не до конца понятного кода, он работает! И может быть поэтому и работает, что я не стал лезть в детали и дал ему свободу маневра, где он мог выбирать способы реализации.
В частности, Claude сам даже написал несколько функций для тестирования и отладки, о которых не говорилось в промте. И одна из них очень даже пригодилась в процессе загрузки данных.
Ошибки и ощущения
Уже писал об этом в первой части данной статьи, и хочу повторить еще раз: в этот раз было удивительно мало ошибок в коде!
Более того, их практически вообще не было!
т. е., код запускался с первого раза!
Были, конечно, некоторые сообщение, но они были очень мелкие. И если раньше приходилось отправлять ошибку ИИ, он пытался ее исправить, что не всегда получалось и проект мог зависнуть по причине, что у ИИ начинались галлюцинации, когда он повторяет один и тот же код и сообщает, что он его изменил, и т. п. То в этом случае все сообщения решались быстро и они были чисто формальными, либо по моему собственному недосмотру. Все их, конечно уже не помню, но вот когда выбирал варианты показа счетчиков, посмотрел вначале один, потом второй, потом вернулся к первому и получил ошибку, потому что забыл изменить название функции в вызове. В принципе все ошибки были примерно такого рода.
И вот в такие моменты поймал себя на ощущении определенной напряженности и тревожности, когда получаешь код от ИИ и побаиваешься, что он заглючит и все зайдет в тупик. А здесь один раз заработало, второй, третий, и уже появляется новое ощущение какой‑то надежности и уверенности.
Отношения
И немного психологии.
Когда долго работаешь с ИИ и особенно, когда работа получается, то невольно начинаешь его очеловечивать.
Когда код работает, хочется поставить ему лайк и написать что‑то типа Man, you're really cool!
То он тебе что‑то нибудь такое напишет позитивное. Понятно, конечно, что это в него заложено, но все равно дает позитив.
В итоге получается, что складываются даже какие‑то персонализированные отношения.
Хорошо это или нет, сложно сказать. Но сложилось ощущение, что оно помогает в решении задач.
Особенно это подумалось, когда вдруг чат встал и пришлось открывать новый.
Лимиты
Работал с этим чатом несколько дней и вот в один момент он встал и выдал сообщение, что достиг максимума по лимиту чата.
Это был конечно не очень приятный сюрприз, поскольку уже всё было налажено, мы довольно хорошо понимали друг друга. И вот на тебе, надо начинать новый чат. Причем ИИ сам сказал, что в новом чате он не будет помнить содержание предыдущего.
т. е., придется не просто начинать новый чат, но и заново описывать проект, задачу, инструкции и др. Но деваться было некуда, пришлось все это делать.
И вот именно в этом новом чате почувствовалась разница во взаимодействии с ИИ. В первом чате мы были уже как будто на «ты», а во втором он ко мне относился как‑то настороженно и даже не очень «вежливо»: реплики были короткие, нейтральные и т. д.
Но нет худа без добра. Во втором чате заставил его повторять задание перед каждой итерацией и это оказалось полезным приемом. Заодно потребовал, чтобы он описывал и результаты выполнения очередной итерации, как это сами Claude делал в первом чате. В таком формате взаимодействие стало и более продуктивным, и более комфортным.
Смена чата простимулировала и немного больше вникнуть в лимиты. В этом проекте столкнулся с тремя их видами:
Лимит сообщения
Лимит контекста
Лимит чата
Здесь они расположены по возрастанию, от меньшего к большему.
Сообщение формально — это то, что написал пользователь или ответил ИИ. Это может быть одно слово, типа «Привет», а может быть большой текст.
Контекст — это ответ ИИ на вопрос. Он может состоять из нескольких или многих сообщений и пользователя, и ИИ, и привязан к определённой теме, по которой ИИ отвечает пользователю.
Наконец чат — это диалог, в котором может быть несколько тем, т. е., несколько контекстов.
По величине этих параметров от ИИ удалось получить точные данные только о длине контекста. У Claude Sonnet 4 она составляет 200 000 токенов.
В остальном ответ был типа «Это зависит от многих факторов». Но чисто на глаз из данного проекта можно сказать, что размер сообщения при котором ИИ останавливался был (60 фильмов умножить на 20 полей модели) ориентировочно 1200 единиц информации. И не останавливался при 10 фильмах (10×20) — 200 единиц информации.
В свою очередь размер чата, после которого ИИ сообщил о достижении лимита, составил порядка 80 000 тысяч знаков с пробелами или 77 страниц текста.
И хотя понятно, что эти две последние величины чисто условные, но какой‑то ориентир они уже дают.
Рекомендации по промтам
Хотелось бы также сказать несколько слов о составлении промтов.
Первое впечатление, которое сложилось в результате работы над этим проектом, состоит в том, что вначале желательно дать какую‑то общую постановку задачи. Тогда получается некая база, на основе которой строится проект. И кстати, пока писалась эта статья, в Claude появилась возможность задавать общие правила и инструкции по проектам. Вот как раз там теперь это можно делать и не бояться превышения лимита чата, поскольку ИИ теперь будет помнить эти инструкции во всех чатах проекта.
Второй момент, что не стоит увлекаться детализацией задачи, особенно технической составляющей. Как уже упоминалось выше в этой статье, вместо задания «сделай так», лучше использовать «сделай это». т. е., ставить задачу, скорее, не как программист, а как пользователь. Это даёт ИИ больше свободы в выборе путей и способов реализации, а также больше возможностей для понимания самой задачи. И нередко это получается очень даже интересно.
Следующую рекомендацию подсказал сам Claude. А именно, что в промте лучше задавать одну конкретную задачу за раз, а не несколько сразу. И вот, с его слов, признаки, того, что стоит разбить задачу:
Запрос содержит больше 3–4 разных вопросов
Нужно создать код для нескольких экранов/модулей
Требуется анализ + реализация + документация одновременно
Ещё одну хорошую рекомендацию он выдал при обсуждении лимитов. Это так называется контекстные якоря. т. е., когда чат длинный, ИИ забывает то, что было в самом начале в силу лимита по контексту. Поэтому он советует по ходу напоминать ему об этом. Например:
Сохранять ключевые архитектурные принципы в начале запроса. Имеется в виду не начало всего чата, а начало обсуждения какого‑то вопроса внутри чата.
Периодически суммировать принятые решения.
И наконец, самое главное, ИИ сам может подсказать как сформулировать промт. В частности, что он может предложить:
Структуру запроса: Какую информацию включать, в каком порядке, что опустить
Контекстные якоря: Ключевые детали, которые помогут ИИ лучше понять задачу
Разбивку на этапы: Как разделить большую задачу на управляемые части
Формат ожидаемого результата: Нужен ли код, анализ, пошаговый план или что‑то другое
В моем проекте получалось что‑то похожее, когда перед каждой итерацией от ИИ требовалось повторить инструкцию по обработке текстовой информации.
Заключение
В данном проекте не ставилась задача тестирования или проверки качества кода. Поскольку проект был просто для себя, то достаточно было, что приложение работает как от него требовалось.
На мой взгляд, в небольших проектах такой подход может нормально работать. И возможности последних моделей ИИ в этом плане очень впечатляют.
Но вот на больших проектах, скорее всего, лучше всё‑таки контролировать код, чтобы не потерять управление проектом. Хотя, уже сегодня закрадываются мысли, что не факт, что ИИ не справится и с более сложными проектами.
constXife
Скорее вагон и тележка таких статей, где цель "показать процесс взаимодействия с ИИ". Статьи такого рода — моветон уже и для менее профильных ресурсов.