Комментарии 8
Проблема с AI/LLM, на мой взгляд, всего одна - люди, т.е. их попытки внедрить новое/модное/молодёжное везде, где можно (и не нужно). Даже в те места, где обычные линейные, но хорошо прописанные алгоритмы работают и без того отлично - быстро и дёшево.
Можем поручить PHD решать квадратные уравнения? Можем! Так давайте поручим..
Увы, но это проблема не только AI/LLM, а, в принципе, всего, что "на хайпе" и беда, как мне кажется, не в том, что это пихают всюду, где нужно и не нужно, а в том, что хайп проходит, а впихнутое остаётся. Посмотрите только на количество k8s-кластеров, которые были развёрнуты на хайпе (и продолжают разворачиваться), но так и живут, потому что теперь выпилить дороже, чем было "запилить" и сейчас поддерживать.
Будущее у AI/LLM, несомнено, богатое, но если нужно две-три пары варежек в год, то пусть их лучше вяжет бабушка - не нужно покупать ткацкий станок.
С IDE есть отдельная специфическая проблема — разработчики привыкли, что все алгоритмы в IDE работают идеально точно. Ну или, привыкли к мечте, что оно так должно быть. Дополнение строки должно сказать нечто, что мы бы и сами написали (а не гениальные идеи Claude о том, как нужно переделать всё приложение, чтобы стало намного лучше). Refactor -> Rename должен переименовать все места и вхождения, включая стыки разных языков и фреймворков. Возможно, это мечта, и так никогда не происходило в реальности — extract method по JS-лапше или C++ с дефайнами, шаблонами и UB может сработать, а может не сработать, have a nice debug bitch. Но легенда такова, что так должно происходить в идеальном мире. И тут есть две стороны вопроса: с одной стороны, чтобы произвольный рефакторинг действительно сработал сразу на всех языках и стыках, одним простым алгоритмом дело не обойдется, тут нужно подключать нейронку. Но нейронка может сгенерировать мусор. С другой стороны, можно закрыть глаза, включить Don't Look Up, и сделать вид, что те моменты, когда Rename не работает — как бы и не происходили. Хорошо не жили, нечего и начинать. Кажется, что оба варианта — это жесткие галлюцинации, и нужно выработать какой-то более другой, прагматичный подход к вопросу. По крайней мере в языках, где даже человеку бывает с трудом что-либо понятно, нейронка может помочь минимизировать урон от неправильных дополнений и рефакторингов, и дать идею — а что здесь вообще было возможно написать.
а почему нельзя парсингом делать ренеймы, неро-алгоритм быстрее работает?
там как раз классно получается, придётся организовать рабочее пространство проекта(манифест файлов), и внутри этого проекта искать слово или словосочетание (внутри проекта 10 языков например) поидее это обычный поисковик просто ограничен проектом(файлами) тоесть просто список найденного и сразу всё менять неохото поэтому проходимся по найденному по 1 и по кнопке даём выбор пользователю применить ренейм
и какойнить логер запилить по изменениям
Про последовательную замену. Зачастую ты делаешь рефакторинг, и у тебя меняется код в десяти тысячах мест. Причем, есть и более сложные рефакторинги, чем rename - например change signature. Часть магии в том, что ты одним нажатием кнопки делаешь работу, которую вручную делал бы неделю. Но да, для пользователя проходить и глазами проверять каждое изменение - не вариант, этих изменений слишком много. Пользователю надо доверять тому, что автоматика ничего не сломает. Особенно если у тебя в проекте нет никаких автотестов, и результат что ничего не посыпалось - можно будет проверить только ручным тестированием.
Делать ринеймы парсингом безусловно можно, надо "всего лишь" правильно распарсить увиденное. Для чего-то это просто (например, Clojure), для чего-то нужно написать нереально сложный компилятор (C++), у чего-то понять структуру вообще невозможно в общем случае (JS с реактами и эвалами). Но распарсить сам язык недостаточно, нужно распарсить ещё и все фреймворки и способы их использования. Например, в Java критичная для ринейма информация может лежать в метаинформации в аннотации, а в PHP так и вообще в комментариях. Насколько критичная? Ну например, структура данных в файлах или в базе данных. Если не заренеймить ненужное (или наоборот - не заренеймить нужное), то у тебя перестанут на проде читаться файлы настроек или перестанут сохраняться файлы в БД, или придется накатывать миграции на БД - и молись чтобы эти миграции не накатывались автоматически по результатам анализа кода (фреймворк Hibernate вполне так может делать). Заметь, что данные о той же структуре БД могут находиться не только даже в строках с полным полным соответствием, а даже где-то внутри названия методов в произвольном месте (стандартный для Java фреймворк SpringData по названию функции findByLastname() автоматически генерит соответствующий SQL запрос в базу). Кроме фреймворков есть и просто какие-то обращения самого пользователя: он может склеить две строковые переменные и потом рефлексией взять у класса поле с таким названием. И хорошо если название есть в непосредственном коде, а не в сгенерировано во время компиляции, или ещё хуже - в рантайме приложения по каким-другим полям, косвенно. С точки зрения компилятора языка все эти вещи никак не связанные, и спросить у LSP-сервера ты это не сможешь. А ведь именно за эту магию люди и используют IDE - если бы ее не было, проще было бы использовать любой другой продвинутый текстовый редактор.
В теории, нейросеть может упростить тебе такие штуки тем, что тебе как разработчику тулинга, больше не нужно писать поиск релевантных символов или даже может, весь рефакторинг тоже не надо писать. Можно прийти к нейросети и сказать: о Великий Вычислитель, взгляни на своего недостойного раба из мяса и костей, и помоги ему заренеймить вот этот кусок текста в координатах 10:20! И на выход нейронка отвечает тебе, в идеале, ченжсет для применения изменений. Тебе больше не нужно писать сложнейшие парсеры и трансляторы коллективом из тысяч умнейших людей, и ежедневно обновлять всю эту машинерию при появлении малейших изменений в языке и фреймворках. Для пользователя это означает гораздо более дешёвые инструменты, которые всегда знают о самых свежих изменениях в языке и фреймворках, и даже учитывают все извращения которые он сам написал в своем коде (например, магия поверх рефлексии и интроспекции).
Собственно, с переходом к AI-first разработке все так и делают, но у этого подхода сейчас много проблем. Например, есть проблема в размере контекстного окна - даже у Gemini с их 1-2 миллионами токенов, внутри большого контекста есть скользящее активное окно, и вне его инструкции забываются (можно напомнить нейронке посмотреть назад и вспомнить что-то конкретное, но для этого надо отдельно индексировать - что именно надо вспоминать). Или например, нейронки сейчас все ещё довольно тупые. Чтобы посмотреть на тупость на какой-то красивой иллюстрации, попробуй поиграть в шахматы с ChatGPT. Она будет ходить невозможными ходами, рубить свои фигуры, доставать фигуры из воздуха и наоборот - игнорировать существующие. То же самое будет и с последовательностью рефакторингов. И с любой другой системой достаточно сложных правил, действующих строго во времени.
С переходом на AI-first приходится привыкать к тому, что любые достаточно невинные действия могут ломать сразу весь код. И чтобы починить его назад приходится после первого модифицирующего запроса делать ещё несколько запросов "пожалуйста, почини этот код", прогонять тесты (если они есть), и - о ужас - даже смотреть диффы изменений. Если это был рефакторинг на десять тысяч строк, тебе обычно не очень хочется смотреть глазами в дифф. И это то, что реально стало неприятным и неудобным при переходе к AI-разработке. Получив огромные магические преимущества в одном месте, мы получили в другом месте пробитие размером во все днище.
Ошибка скорее всего методическая имхо.
ИИ смотрят на кучу кода окном огромных размеров. И сейчас соревнуются в его размерах, что в массе своей совершенно зря и тупик. Если человек сделает то же самое, то ему плохо будет не то что на миллионе токенов, а намного раньше.
В Idea да и в Vscode есть же поддержка AST, нужно заполнить окно не чем попало, а именно поддеревом от операторов до артефактов. Если это делать не только на генерации но и на файнтюнинге (!), качество просто обязано прогрессировать. Просто? Да. Делают? Нет. Но это настолько на поверхности, что скорее всего не за горами. Производителям IDE тут наверное будет больше пространства для исследований, чем остальным (видео, аудио, обычные тексты), потому что код на статически типизируемых языках с AST идеально согласуется уже по своей природе.
В общем мусор на входе, мусор на выходе - то что сейчас имеем. И основная проблема не число видеокарт, а банально выборка. Точнее методика ее подготовки. Но дотюнить до производственного качества точно можно грамотным наполнением окна. Это уже довольно очевидно даже на генерации. Если сделать то же на тюнинге качественный рост гарантирован.
Да. Делают? Нет.
Как раз начинают делать Cursor использует tree-sitter чтобы чего-то гранулярно парсить. У нас в GigaIDE Cloud это тоже уже в бэклоге.
Вот про что я хотел поспорить, так про "статически типизируемых языках с AST".
Например, Java таковым языком не является, потому что во-первых никто не пишет на голой Java — пишут на Java+Spring+куча-других-фреймворков, да и в самой Java миллион рефлекшена. Половина логики лежит в анноациях, XML-ках и конвенциях классов/методов. Это одна из причин, почему мир еще не перешел на штуки типа GraalVM Native Image - не каждый проект можно скомпилировать статически, и более того — совершенно не каждый программист хочет писать на Java статически.
У C# так вообще работают LINQ expressions, за которыми может стоять примерно любой обработчик, и это прям часть языка. (Имхо, это как раз то, чем C# на самом деле лучше, чем Java. Без этой фичи у Java все коллекции выглядят как уродство).
Остальной топ языков: JS/TS, Java/Scala/C#, Python, Ruby, PHP, Lua — у них точно та же особенность. Более подробно можно что-то сказать про C/C++, Go, Rust, Swift. Но C/C++ - это легаси, а Go/Rust/Swift — это все еще считаные проценты от общего использования.
Возможно, вопрос натурально в том, заменят процесс кодирования окончательно, или нет. Станет ли он таким же автоматизированным, как сейчас происходит с трансляцией языков высокого уровня в ассемблер и машкоды.
Если люди более не будут кодировать, НИКАКИЕ из этих языков не нужны и не подходят сами по себе в качестве intermediate language. Нужен язык, который специально сдизайнен для нейросетей и только для них. В котором будут починены проблемы типа "сколько r в слове strawberry", в котором не будут экономить на длине синтаксиса и идентификаторов, и тому подобное.
А если кодирование всё ещё будут делать люди, то наоборот — нейронки совершили прорыв в том, что на "слабосвязанных" языках можно кодировать не менее эффективно, чем на Java/C#/C++. Раньше у тебя была постоянная проблема в том, что в JavaScript-подобных языках с первого взгляда ничего не понятно точно. Что-то понятно, но чтобы быть уверенным — нет. И всякие рефакторинги в IDE из-за этого работали как говно, рефакторить всё равно надо. Теперь же тебе на них гораздо проще программировать потому, что тебе и не нужно ничего до конца понимать. Ты можешь относиться к коду как к чему-то вероятностному и мимолетному, как к промежуточному представлению, некому IR стоящему между спецификацией и исполнением. Да, ты все ещё его пишешь, но можно больше не относиться к этому слишком серьезно. По сути, ты можешь теперь генерировать на JavaScript (даже без TS) раз в 10 больше кода, чем делал это раньше, за то же самое время. Лучше он от этого не станет, но вот что писать можно быстрее в разы — это совершенно точно.
Эта гонка за размер окна и скорость генерации токенов — это просто решение боли живых людей. Которая очень, очень сильно болит. Ну нет у человека в голове такого размера окна. Нельзя с такой скоростью писать буковки на JavaScript. Нейронка дает тебе все эти возможности. Поэтому люди платили и будут платить за окно и скорость генерации. Это как плата за таблетки от которых зависит твоя жизнь — сколько бы ни попросили, как бы (не)качественно они ни работали, всё равно будут покупать, потому что оно утоляет боль.
В PHPStorm в подсказках от ИИ больше всего раздражают его галлюцинации. Самый частый случай: в текущем контесте есть переменная с длинным названием, я начинаю писать вызов функции, в которую передаётся эта переменная, и отравленное искуственным "интеллектом" автодополнение предлагает не только правильно дописанное название функции и поставленную переменную, но и кучу мусора в виде дополнительных аргументов. При этом:
функция заведомо принимает только один аргумент,
домысленные аргументы даже не существуют в текущем контексте; зачастую это ключи массива - сам массив в контексте есть, а ключей таких в нём нет и никогда не было ( "но могли бы быть!" - пищит безумный ИИ).
В итоге от предложенного автодополнения приходится отказываться, и писать всё ручками. Подразнили морковкой и спрятали...
У нас в VSCode это отлично решается тем, что у тебя есть два автодополнения - базовое и AI inline completion (серый текст-призрак). Призраки настраиваются через назначение шортката экшену editor.action.inlineSuggest.trigger. Это группа шорткатов, в т.ч. там можно сделать отдельный шорткат на переключение к следующей подсказке. Например, можно назначить призрака на ctrl+H, а обычное дополнение останется на ctrl+space и tab. Если у тебя в качестве основного плагина Continue, можно его еще по-разному донастроить, чтобы было удобно (то ли туториал написать...)
Возможно, в Идее разрабам достаточно просто подсвечивать ИИ-дополнения другим цветом, или поставить рядом с ними красивую иконку с мерцающими звездочками. Такое решение сделает больно слабовидящим (скрин-ридеру придется постоянно говорить "эй ай" перед каждым элементом в списке), но полностью зрячим это достаточно мощный индикатор. Ну и раздельные шорткаты утащить из VSCode, конечно. Возможно, в IDE от JetBrains уже так и есть, но с тех пор как я переключился на разработку плагинов для VSCode (в частности, на работе днем я делаю GigaIDE Cloud), попробовать всю эту красоту времени нет.
Mellum. Быстрая, миниатюрная модель для дополнения кода в редакторе