Главная / Статьи

Ограниченные промпты: как не позволить ИИ-ассистентам создавать параллельные стеки

Почему нечеткие запросы на функции заставляют помощников по программированию добавлять дублирующиеся библиотеки и обертки, и как ограниченный запрос с указанием путей, инвариантов и жестких ограничений решает эту проблему.

Издатель: REACTAPP.TOP6 мин чтения1323 слов

Источники: AI Doesn’t Need Better Prompts. It Needs Boundaries.

Если попросить помощника по программированию «создать страницу настроек пользователя», обычно получится что-то, что компилируется, отображается и выглядит готовым к использованию. Однако при более внимательном рассмотрении оказывается, что у такого кода свой хранилище состояния, собственные функции для получения данных и библиотека валидации, которой никогда не использовалось в вашем репозитории. Ничего не ломается, и именно поэтому проблема ускользает от проверки. В этой статье объясняется, почему нечеткие запросы приводят к подобным результатам, почему добавление прилагательных не помогает, как составлять четкие запросы, а также приводится перечень проверок, позволяющий сохранять генерируемый код в рамках существующей архитектуры.

Почему нечеткие запросы приводят к скрытым ошибкам

Представьте команду, работающую над приложением для администрирования клиентов, созданным с использованием React и TypeScript. В кодбазе уже имеются примитивы форм, общий клиент API и хук для уведомлений. Кто-то просит ассистента создать страницу настроек в одном коротком предложении. Результат включает в себя вкладки, формы, сообщения-тосты, элементы загрузки и небольшой хранилище состояния. Однако на самом деле эти изменения несовместимы с текущей кодбазой:

  • Состояние форм управляется библиотекой, которая не используется в проекте.
  • Рядом с общим клиентом API появляются новые обертки для запросов fetch.
  • Сообщения-тосты генерируются непосредственно в коде, а не с помощью хука уведомлений проекта.
  • Шаблоны валидации игнорируют структуры, уже определенные в папке types/.
  • «Хранилище настроек» на стороне клиента содержит три поля, которые на самом деле должны храниться на сервере.
  • Элементы загрузки не соответствуют остальной части панели управления.

Ничто из этого не вызывает ошибок, и всё может выдержать краткий анализ, если только кто-то не откроет файл package.json. В этом и заключается опасность: нечеткие запросы приводят к мягким сбоям. Они вводят дополнительный способ выполнения задачи, которую команда уже решила, и каждый будущий сотрудник вынужден работать с обоими вариантами. Ассистент хорошо справляется с кодом, который он может увидеть; именно файлы, которые он никогда не открывал, определяют, действительно ли та или иная функция подходит для вашего приложения.

Почему более длинный запрос — не решение

Обычный совет — быть более конкретным. Естественной следующей попыткой является запрос к «отшлифованной, готовой к использованию» странице настроек с «чистым интерфейсом, хорошим TypeScript и надежной обработкой ошибок».

Это создаёт ту же параллельную архитектуру, только с большей уверенностью. Слова описывают вкус, а вкус позволяет модели полностью свободно создавать структуру. То, чего не хватало, — это не красноречие. Это были границы: чёткие указания на то, что модель может использовать, чего ей нельзя добавлять и что считается завершённым.

Написание ограниченной версии

Приведённый ниже ограниченный запрос требует тех же функций, но написан как описание задачи. В нём указываются конкретные компоненты, hook, клиент API и файл схемы для повторного использования, перечисляются действия при нажатии на вкладку и отправке, определяются тесты, а в конце приводятся чёткие запреты.

Build a user settings page in React and TypeScript.
Use ONLY these existing pieces:
- `src/components/FormField.tsx`
- `src/components/Button.tsx`
- `src/hooks/useNotify.ts`
- `src/api/client.ts` (no new fetch wrappers)
- validation schemas from `src/types/userSettings.ts`
Behavior:
- Tabs: Profile, Notifications, Security
- Preserve unsaved edits when switching tabs
- Show server field errors beside the matching inputs
- Disable submit while in flight
- Ignore duplicate submits
Tests:
- loading, success, server error, duplicate click
- empty required fields
Do NOT:
- add a state-management library
- add a toast library
- create a new API client
- invent types that duplicate `src/types/userSettings.ts`

Это скорее записка об архитектуре, которую должна соблюдать модель, чем более удачный запрос. По сравнению с однострочным вариантом он передаёт семь аспектов, которые ранее оставались на усмотрение:

  1. Какие существующие компоненты использовать.
  • Место, где находится источник правды для проверки.
  • Правила взаимодействия, такие как сохранение несохранённых изменений между вкладками.
  • Место, где должны отображаться ошибки.
  • Поведение при одновременных операциях: состояние в процессе выполнения и дублирование отправок.
  • Тесты, определяющие, что означает «готово».
  • Жёсткие ограничения на добавление новых зависимостей.
  • При соблюдении этих ограничений получаемый результат становится довольно однообразным. Используются те же FormField, та же функция useNotify, те же компоненты api/client. Вкладки сохраняют своё необработанное состояние без необходимости в новом хранилище, а дублирование отправок обрабатывается с помощью отключённой кнопки и теста, а не комментария «обработать позже». В существующих кодовых базах уже есть соответствующие шаблоны; задача подсказки — показать их настолько чётко, чтобы модель не смогла их пропустить.

    Это также объясняет, почему опытные разработчики чаще достигают лучших результатов с помощью ассистентов. Их преимущество не в формулировках, а в знании заранее того, какие детали имеют значение. Важно передать архитектуру, а не просто украсить запрос.

    Быстрый тест на ограниченность

    Если ваш запрос будет иметь смысл, если его вставить в любой репозиторий в мире, он ещё не является ограниченным. Хороший запрос должен быть немного бесполезным вне вашей собственной структуры проекта, поскольку в нем упоминаются ваши пути, типы и конвенции.

    Проверочный список для повторного использования

    Размещение шаблона над каждым запросом на функционал помогает сделать применение определённого стиля привычкой. Шаблон ниже группирует вопросы по категориям: контекст, неизменяемые свойства, поведение, ограничения и критерии завершения работы. Секция с неизменяемыми свойствами чаще всего игнорируется: принятие решения о том, будут ли данные храниться на сервере, в URL или в локальном состоянии интерфейса, позволяет избежать проблемы «хранение трёх полей» ещё на этапе планирования.

    CONTEXT
    - Stack: React + TypeScript
    - Relevant paths: ...
    - Patterns to copy: ...
    
    INVARIANTS
    - Where does data live (server / URL / local UI state)?
    - What must survive refresh?
    - What is the source of truth for types/validation?
    
    BEHAVIOR
    - Happy path
    - Empty / invalid input
    - Server errors (field-level + form-level)
    - Slow network / double submit
    - Permission failure
    
    CONSTRAINTS
    - Do not add: ...
    - Do not invent parallel: API client / store / toast / form lib
    - Prefer editing: [files]
    
    DONE
    - Tests for: ...
    - Manual checks: ...
    

    Используйте шаблон в качестве критерия готовности. Если вы не можете заполнить разделы с ограничениями и соответствующими путями, вы ещё не готовы к генерации кода — вы всё ещё находитесь на этапе проектирования. Генерация кода при незавершённом проектировании именно та ситуация, при которой появляется вторая архитектура. Стабильные части этого списка могут храниться в файле инструкций проекта; ознакомьтесь с нашим руководством по созданию эффективного файла CLAUDE.md.

    Что ещё требует проверки человеком

    Ограниченные промпты устраняют большую часть шума, но они не заменяют собой человеческий осмотр. При анализе различий всё равно проверяйте:

    • Новый пакет, который никто не одобрил.
    • Другой способ вызова API.
    • Типы данных, отклоняющиеся от определений сервера.
    • Состояние на стороне клиента для данных, которыми должен управлять сервер.
    • Тесты, не проверяющие сценарии, отличные от тех, которые предполагал модель.

    Написание промпта — это простая часть; понимание того, какие ограничения важны в данном кодовом базисе, — это сложная часть, и эти знания находятся у команды.

    Самое маленькое изменение, которое можно внести сегодня

    Если полный список проверок кажется слишком обременительным, добавьте в свой следующий запрос на разработку всего три пункта: какие пути использовать, какие библиотеки не добавлять и что считается «готовым», включая хотя бы один сценарий сбоя.

    Use only: [paths]
    Do not add: [libs]
    Done when: [2–3 behaviors + one failure path]
    

    • Нечеткие запросы редко приводят к сбоям; они создают дублирующуюся инфраструктуру, которая кажется готовой, но впоследствии стоит вам денег.
    • Больше прилагательных меняет тон вывода, но не его структуру. Ограничения изменяют структуру.
    • Четко сформулированный запрос определяет имена файлов для повторного использования, источник данных и типов, поведение в крайних случаях, тесты и зависимости, которые запрещено использовать.
    • Когда модель придумывает что-то вне установленных рамок, считайте это отсутствием границы: исправьте запрос и сгенерируйте результат заново, вместо того чтобы дорабатывать формулировки.