ИИ в технической работе: где помогает, а где нельзя доверять
ИИ в технической работе: где помогает, а где нельзя доверять
Вообще я микроразработчик, со мной можно связаться как угодно, я открыт ко всему
Сторонний мой проект: Zapret2UI.
Так, ну тут будут статьи для вайба, большие тех статьи уже окончены, поэтому я буду здесь разбирать чуть другие темы без особого углубления и ссылаться на свой опыт часто.
Кидаешь модели чужой конфиг на семьдесят строк, просишь разобрать по полям - получаешь толковый разбор, лучше половины гайдов. Просишь на следующем сообщении собрать такой же конфиг с нуля - получаешь красивый рабочий на вид файл, в котором два поля вырезали из проекта пару лет назад.
Одна и та же модель, один и тот же предмет, соседние сообщения. Результат в первом случае отличный, во втором вредный.
Разница не в сложности задачи и не в везении. Она проходит по одной-единственной линии, и если её увидеть, то дальше становится понятно вообще всё: и где этой штуке можно доверять почти без оглядки, и где нельзя доверять ни единой строчке.
Про то, почему модель врёт и как формулировать запросы, чтобы попадало, у меня есть отдельная статья(Не вышла на момент написания). Тут только прикладная часть, для технической работы.
Содержание
- Один вопрос, который решает всё
- Где помогает по-настоящему
- Где нельзя доверять
- Поля, которых больше нет
- Как лезть в исходники, если вы не программист
- Ссылки на документацию
- Код: где хорош и где ломается
- Команды, которые нельзя запускать не глядя
- Рабочий протокол
- Частые ошибки
- Короткий итог
ВАЖНАЯ РЕМАРКА, Я ЗДЕСЬ БУДУ В ПРИМЕР БРАТЬ ЧТО-ТО КОНКРЕТНОЕ(Конфиги, статьи свои, проекты, etc.). Они выступают как пример, это будь-то вайбкод проекты и т.д - Неважно, я разбираю сам факт работы
Один вопрос, который решает всё
Перед тем как поверить ответу, спросите себя: был ли у модели перед глазами текст, с которым она работала?
Всё, что дальше, вытекает отсюда.
Текст есть. Вы дали лог, конфиг, кусок кода, сообщение об ошибке, вывод команды. Задача сводится к работе с этим материалом: найти в нём аномалию, объяснить, что тут написано, переформулировать, сопоставить одно с другим. Это ровно то, для чего такие модели и хороши. Материал перед ними, выдумывать нечего, и надёжность тут высокая.
Текста нет. Вы просите сгенерировать конфиг, назвать флаг, вспомнить значение по умолчанию, сказать, какая версия актуальная. Теперь всё идёт из памяти о прочитанном, а память эта устроена как «что чаще встречалось в текстах», а не как справочник. Ответ будет правдоподобным по форме и каким угодно по содержанию.
Аналогия, которая мне кажется точной. Представьте человека, который прочитал гигантскую гору технической литературы, но читал невнимательно и давно, а конспектов не вёл. Дайте ему документ - разберёт блестяще, он умный и опытный. Спросите по памяти точное имя параметра - назовёт уверенно и, скорее всего, то, которое чаще попадалось, а не то, которое актуально сейчас.
Вот и вся граница. Дальше просто разложу по ней конкретные задачи.
Где помогает по-настоящему
Тут я буду сильно хвалить, потому что заслуженно: на этих задачах инструмент реально экономит часы работы, которые можно и не тратить, если верно использовать.
Простыня логов. Четыре тысячи строк, где-то в них момент, когда всё пошло не так. Скормить целиком и спросить «где начинается аномалия и что ей предшествовало» - это работает отлично, потому что весь материал перед глазами и надо просто внимательно смотреть. Человек на четырёхтысячной строке уже плывёт, машина нет.
Незнакомая команда с гроздью флагов. Видите в чужой инструкции mtr -rwzbc 200 и понятия не имеете, что это. Расшифровка каждой буквы - секундное дело, и ошибиться тут почти негде, флаги стабильны десятилетиями. Заодно можно спросить, что будет, если убрать один из них.
Разбор чужого конфига. Что за поле, за что отвечает, что будет, если поменять. С одной оговоркой, которую разберу ниже: разобрать написанное и сказать, актуально ли оно, - разные задачи. Первое надёжно, второе нет.
Регулярки, jq, awk, sed. Мой личный фаворит. Написать регулярку под конкретный формат, объяснить чужую, преобразовать JSON хитрым запросом. Причём тут есть встроенная защита от вранья: результат проверяется мгновенно, прогнали на тестовых данных и сразу видно, работает или нет. Ошибка ничего не стоит.
Заготовки. Скелет systemd-юнита, каркас docker-compose.yml, болванка скрипта с обработкой аргументов. Не финальный вариант, а стартовая точка, чтобы не писать рутину с нуля. Проверять всё равно надо, но набирать руками уже не надо.
Сообщение об ошибке. Кинули текст ошибки, получили объяснение, что она означает и куда копать. Особенно ценно, когда ошибка от незнакомого софта и гуглится плохо.
«Что я забыл». Описываете, что настроили, и просите перечислить типичные упущения. Тут модель хороша именно потому, что напоминает известное, а не изобретает новое: типовые грабли описаны тысячу раз, и в данных их много.
Объяснить своё же другими словами. Написали технический кусок, просите переложить для человека, который не в теме. Материал перед глазами, творчество минимальное, попадание высокое. Лучше всего работает с документациями, прекрасный пример моя дока-сайт для моего проекта
Поставьте звезду на гитхабе пж
Общее у всех восьми пунктов ровно одно: либо текст дан, либо ответ проверяется за секунды. Держите этот признак в голове, он и есть критерий.
Где нельзя доверять
Теперь обратная половина, и тут я буду занудствовать, т.к для меня это важно.
Конфиг с нуля под конкретную версию. Главный пункт, ему отдельный раздел ниже.
Значения по умолчанию. «Какой дефолт у этого параметра» - вопрос, на который ответ будет уверенным и часто неверным. Дефолты меняют между релизами тихо, в чейнджлоге одной строкой, и в текстах остаётся старое значение, про враньё отдельная статья.
Версии и что в них появилось. Всё про «сейчас»: какая версия актуальна, что в ней нового, что вырезали, что рекомендуют. Это ровно та область, где данные модели устарели по определению, т.к их память(!) ограничена конкретной датой, но лезть в интернет и проверять она может, выдавайте источники и сверяйте всё сами.
Числа и пороги. Сколько памяти нужно, какой размер буфера ставить, при каком проценте потерь начинаются проблемы. Число выглядит как факт, читается как факт, а взяться может из воздуха. Я к любой конкретной цифре от модели отношусь как к гипотезе, пока не увижу источник, либо не будет личного опыта.
Ссылки. Отдельный раздел ниже, потому что случай показательный.
Всё необратимое. Команды, которые удаляют, перезаписывают, форматируют, меняют правила файрвола. Не потому что модель злая, а потому что цена ошибки несимметричная: правильная команда экономит минуту, неправильная стоит вечера/дня/недели работы.
Безопасность. Настройки прав, авторизации, шифрования. Тут особенно неприятно, что неверная конфигурация обычно работает. Сервис поднялся, всё зелёное, а доступ открыт всему интернету. Обратной связи нет вообще, вы узнаете об ошибке от кого-то другого и сильно позже, и чаще всего не от доброго лица.
Поля, которых больше нет
Вот это, на мой взгляд, самая недооценённая проблема во всей теме, и объяснить её механику важнее, чем перечислить симптомы.
Модель выдаёт то, что чаще встречалось в текстах. А теперь подумайте, чего в интернете больше: статей про поле, которое существует три года, или про поле, которое существовало восемь лет и было вырезано год назад?
Массовость в данных всегда побеждает актуальность. У устаревшего было больше времени, чтобы про него написали. Причём чем удачнее была старая штука, тем больше про неё текстов и тем увереннее модель будет её предлагать после отмены.
Живой пример, который я разбирал по исходникам, когда писал статью про транспорты(Ещё не вышла на момент написания). Возьмём Xray-core, популярную штуку с активной разработкой:
| Что предложит модель | Что на самом деле |
|---|---|
"network": "tcp" | переименован в raw, старое имя пока принимается ради совместимости |
"network": "splithttp" | переименован в xhttp |
"network": "h2" или "quic" | вырезаны из транспортов совсем |
"security": "xtls" | вырезан |
"network": "ws" | работает, но помечен устаревшим, ядро пишет предупреждение в лог при старте |
Обратите внимание на разницу между строками, она принципиальная. Первые две - переименования, старое имя ещё работает, вы даже не заметите проблемы. Третья и четвёртая - конфиг просто не запустится, и это, как ни странно, лучший исход: ошибка громкая и сразу. А вот пятая самая вредная: всё работает, ничего не падает, предупреждение уходит в лог, куда вы не смотрите, и вы годами живёте на устаревшем транспорте, не подозревая об этом, и проблема вскроется только при обновлении.
Отсюда правило: сгенерированный конфиг проверяется не на «работает ли», а на «актуально ли». Запустилось - это ещё ничего не значит.
И проверять надо не по документации. Документация отстаёт от кода, иногда сильно: поле уже переименовали, а на сайте висит старый пример. Смотреть надо в исходники, в то место, где разбирается конфиг. Звучит страшно, на деле нет, и следующий раздел целиком про то, как это делается без знания языка программирования.
Как лезть в исходники, если вы не программист
Совет «сверяйся с исходниками» звучит как отговорка для тех, кто и так умеет. Поэтому объясню приём целиком, он проще, чем кажется, и знать язык программирования для него не надо.
Идея вот в чём. Имена полей конфига должны где-то в программе превращаться в действия. И почти всегда это происходит в одном месте, где имена перечислены подряд обычными строками в кавычках. То есть вам не надо читать код, вам надо найти список и посмотреть глазами.
Порядок такой.
Шаг первый: найти папку с разбором конфига. В репозитории проекта ищите каталог с названием вроде conf, config, settings, parser. У Xray это infra/conf.
Шаг второй: найти файл по смыслу. Имена там обычно говорящие: transport_internet.go, tls.go, router.go. Нужен тот, что отвечает за интересующий раздел конфига.
Шаг третий: выдернуть список имён. Можно открыть в браузере и поискать по странице, а можно одной командой:
curl -sL https://raw.githubusercontent.com/XTLS/Xray-core/main/infra/conf/transport_internet.go \
| grep -n 'case "'
Вывод получается такой (я его укоротил):
18: case "raw", "tcp":
20: case "xhttp", "splithttp":
24: case "grpc":
27: case "ws", "websocket":
33: case "h2", "h3", "http":
35: case "quic":
87: case "tls":
99: case "reality":
113: case "xtls":
Всё. Команда выдаёт полный перечень имён, которые программа вообще понимает, прямо из той версии, что лежит в репозитории сегодня. Никакой документации, никаких блогов.
Шаг четвёртый, главный: посмотреть, что стоит рядом с именем. Тут три исхода, и различаются они на глаз даже без знания языка:
- Рядом слово
returnи какое-то значение - имя рабочее. - Рядом что-то со словом
RemovedилиError- имя вырезано, конфиг с ним не запустится. - Рядом что-то со словом
DeprecatedилиWarning- имя ещё работает, но помечено устаревшим, и в лог уедет предупреждение.
Проверим на нашем примере, посмотрев уже с окружением:
case "h2", "h3", "http":
return "", errors.PrintRemovedFeatureError("HTTP transport ...", "XHTTP stream-one H2 & H3")
case "ws", "websocket":
errors.PrintNonRemovalDeprecatedFeatureWarning("WebSocket transport (with ALPN http/1.1, etc.)", "XHTTP H2 & H3")
return "websocket", nil
Читается без всякого Go: первое удалено и вдобавок сразу написано, чем заменять. Второе живо, но с предупреждением, и опять же указана замена. Разработчики, что приятно, сами пишут в коде, куда переезжать.
Приём занимает две минуты и закрывает целый класс проблем. Я им пользуюсь постоянно: сначала спрашиваю модель, потом иду в этот список и сверяю. Ловит и устаревшие поля, и выдуманные, и переименованные.
Работает это, понятно, не везде: нужен открытый исходный код и более-менее вменяемая структура проекта. Но у сетевого софта и всего опенсорсного, чем обычно и мучаются, оно есть.
Ссылки на документацию
Маленький раздел про частный случай, но случай слишком показательный, чтобы его пропустить.
Модель прекрасно знает, как устроены адреса на знакомых сайтах: домен, структура путей, стиль именования страниц. И совершенно не знает, какие конкретные страницы там существуют. В итоге получается адрес, который выглядит настоящим до последнего символа, а открывается 404-й.
Свежий пример из своей же практики, буквально при написании соседней статьи. Понадобилось сослаться на разбор от OpenAI про подхалимство в GPT-4o. Ссылка получилась вида openai.com/index/sycophancy-in-version-gpt-4o/. Домен верный, раздел /index/ верный, стиль именования верный, тема верная. Не существует. Настоящий адрес - openai.com/index/sycophancy-in-gpt-4o/, без одного слова в середине.
Одно лишнее слово, и ссылка мёртвая. При этом на глаз она неотличима от рабочей, а если её не кликнуть, то так и уедет в текст, и читатель упрётся в ошибку. При этом кстати важно заметить, что сам текст из этой статьи может быть абсолютно верным, просто сломалась ссылка по пути до источников.
Правило поэтому короткое и без исключений: любая ссылка от модели проверяется кликом. Всегда. Пять секунд, и самая дешёвая проверка из всех, что вообще бывают. Грех не пользоваться.
Код: где хорош и где ломается
Тема большая, но границу можно провести по тому же признаку.
Работает хорошо:
- Типовое и много раз написанное: разбор аргументов, чтение конфига, обход директории, обработка ошибок.
- Объяснить чужой код. Материал перед глазами, задача сводится к чтению.
- Найти баг в куске, который вы показали. Особенно опечатки, перепутанные переменные, забытые проверки на пустоту.
- Написать тесты к показанной функции. Скучная работа, и делается добросовестно.
- Перевести с языка на язык небольшой кусок(Большие проекты вообще работают криво, и часто написаны на костылях, которые на других языках работают ещё хуже даже чем оригинал).
Ломается ровно там же, где и везде: как только приходится доставать из памяти вместо того, чтобы читать с экрана. Только последствия тут вылезают наружу позже. Свежие библиотеки и API - ровно та же история, что с конфигами: сигнатуру поменяли, а в данных осталась старая. Всё, что требует держать в голове состояние большой системы, тоже мимо: модель видит фрагмент, а не проект, и последствия правки за пределами этого фрагмента не отследит. Пограничные случаи пишутся как повезёт, основной путь будет аккуратным, а пустой ввод, обрыв соединения посередине и одновременный доступ - уже лотерея. Ну и производительность: код выйдет корректным и при этом спокойно сделает запрос к базе внутри цикла.
И ещё одно, про что забывают чаще всего: код, который компилируется, и код, который делает то, что нужно, - разные вещи. Компилятор проверяет синтаксис, а не ваш замысел. Сгенерированный код часто проходит все формальные проверки и тихо делает не то. Это тот же самый эффект, что и с конфигом на устаревшем транспорте: отсутствие ошибки не равно правильности.
Если коротко суть. То, что он работает, не означает, что он работает так, как вы хотели, может вообще выполнять другие задачи.
Команды, которые нельзя запускать не глядя
Практическая часть, где ошибка стоит дороже всего.
Базовое правило одно и простое: сначала прочитать, потом запустить. Не «скопировал и вставил», а «прочитал, понял каждую часть, потом вставил». Если в команде есть кусок, который вы не понимаете, - вы не выполняете команду, вы играете в лотерею.
Что должно останавливать сразу:
rm -rfс любым путём, особенно с переменной внутри. Незакрытая или пустая переменная превращает путь в корень.dd- опечатка вof=пишет поверх не того диска, и восстанавливать будет нечего.- Одиночный
>вместо>>- молча стирает файл, в который вы собирались дописать. mkfsв любом виде.chmod -Rиchown -Rот корня или от домашней директории.iptables -Fиufw --force reset- классика с потерей доступа. Правила сбросились вместе с тем, которое разрешало ваш SSH, и всё, приехали, идите в консоль хостера.- Любой
curl ... | sh. Вы выполняете то, чего не читали, причём с правами, которые дали.
Как страховаться, от самого простого к основательному:
Сухой прогон, где он есть. rsync -n, apt --dry-run, git clean -n. Покажет, что произойдёт, ничего не сделав.
Подставить echo. Универсальный приём, когда сухого прогона нет: превратите команду в её печать. Увидите список того, что собирались натворить, и иногда он удивляет.
Сначала на копии. Тестовая машина или хотя бы копия файла рядом. Отдельная виртуалка под опыты стоит копейки и снимает целый класс проблем: там не жалко.
Держать открытой вторую сессию. Перед тем как трогать сеть или файрвол, откройте второе SSH-подключение и не закрывайте. Отрезали себе доступ первой сессией - чините второй. Приём древний, спасал многих, кстати включая меня в начале пути.
Рабочий протокол
Свёл всё в короткий список, которым пользуюсь сам.
- Спросите себя, был ли текст перед глазами. Дали лог или конфиг - доверия много. Ответ из памяти - доверия ноль до проверки.
- Ссылки кликать всегда. Пять секунд, ловит целый класс вранья.
- Числа, версии, имена полей и дефолты сверять с исходниками. Не с документацией: она отстаёт. Не с блогами: они переписывают друг у друга.
- Команды читать до запуска, а необратимые прогонять всухую.
- «Запустилось» не равно «правильно». Проверяйте на актуальность, а не только на работоспособность.
- На свежих темах доверие ниже. Чем новее технология, тем меньше её в данных.
- Просите указать, где вы неправы, вместо подтверждения своей правоты. Про это подробно в соседней статьей про враньё ИИ(Ещё не вышла на момент написания).
- Не тащите в прод с первого раза. Никогда, даже когда очень уверены.
Восьмой пункт хочется пропустить чаще всего, и обходится это дороже, чем все остальные семь вместе.
Частые ошибки
- Ставить генерацию и разбор на одну полку. Разобрать показанный конфиг и сочинить новый - задачи разной надёжности, хотя выглядят одинаково.
- Проверять конфиг только запуском. Переименованное поле запустится как ни в чём не бывало, и вы так и не узнаете, что сидите на устаревшем.
- Не открывать ссылки. Самое дешёвое из всех возможных действий и самое часто пропускаемое.
- Верить дефолтам и версиям. Это данные с датой протухания, а у модели нет способа узнать, что поменялось после её обучения.
- Копировать команды не читая. Особенно из ответа, где половина строки вам незнакома.
- Проверять по документации вместо исходников. Документация описывает намерение, код описывает поведение, и они расходятся.
- Спорить с моделью до победы. Дожать её до согласия можно всегда, и это ничего не доказывает.
- Считать отсутствие ошибок подтверждением. Неправильная конфигурация прав обычно поднимается без единого возражения.
Короткий итог
- Граница проходит по одному вопросу: был ли у модели текст перед глазами. Работа с данным материалом надёжна, генерация по памяти нет.
- Логи, чужие конфиги, незнакомые команды, регулярки, заготовки, сообщения об ошибках - тут инструмент экономит часы и почти не врёт.
- Конфиги с нуля, дефолты, версии, числа, ссылки, необратимые команды - тут доверия нет до проверки.
- Массовость в данных побеждает актуальность. Про вырезанное поле в интернете написано больше, чем про его замену, просто потому что у него было больше времени.
- Хуже всего не падение, а тихая работа на устаревшем. Переименованное поле запустится, предупреждение уйдёт в лог, и вы годами не узнаете.
- Проверять надо по исходникам, а не по документации и тем более не по блогам.
- Ссылки кликать всегда - самое дешёвое действие с самой высокой отдачей.
- Читать команды до запуска, необратимые гонять всухую, вторую SSH-сессию держать открытой.
В целом отношение у меня к этому такое: инструмент хороший ровно настолько, насколько вы готовы его перепроверять. Тому, кто проверяет, он экономит часы. Тому, кто не проверяет, он экономит часы сейчас и отнимает вечера потом. Разница целиком на вашей стороне, не на его.
Вообще я микроразработчик, со мной можно связаться как угодно, я открыт ко всему
Сторонний мой проект: Zapret2UI.
Источники
- XTLS/Xray-core - репозиторий проекта
- transport_internet.go - тут разбираются имена полей network и security
- Why Language Models Hallucinate - Kalai, Nachum, Vempala, Zhang, сентябрь 2025
- Towards Understanding Sycophancy in Language Models - Sharma и др., Anthropic, ICLR 2024
- rsync - про флаг сухого прогона

