Основы Эффективного Использования LLM В Разработке
Я постоянно ищу способы, как успевать больше за меньшее количество времени, и c восходом AI это наконец-то начало давать ощутимые плоды по части разработки; однако многие разработчики не видят (либо не хотят видеть) те возможности, которые открываются перед нами, и продолжают работать по старинке, невольно становясь кандидатами, которые могут и не выдержать конкуренции.

Ввиду того, что я все таки менеджер разработки, у меня много взаимодействия с разными разработчиками со всего мира, и я вижу их очень разное отношение к AI. В целом, готов его разделить на следующие категории:
- Вдохновлены и активно используют AI в работе (до 20%);
- Проявляют интерес, пробуют, но используют AI на 20% (около 60%);
- Скептики, которые либо попробовали и это не оправдало их ожиданий, либо даже не пробовали (около 20%). Цифры довольно субъективны и скорее отражают мой личный опыт, нежели являются репрезентативными по всей индустрии.
Есть исследования, которые показывают, что уровень проникновения AI в разработку - порядка 60%, что может и правда. Но пока эта цифра скорее отражает количество разработчиков использующих ChatGPT, Perplexity и подобные AI-powered сервисы без глубокого применения на практике. На деле, LLM в основном используются очень поверхностно, хотя потенциал там огромный.
Про мой опыт
За последний год я попробовал разные редакторы и плагины для IDE powered by AI, но на данный момент остановился на Cursor AI, Github Copilot и JetBrains Junie как основных продуктах, которые применяю каждый день в разработке.
Я основательно не изучал ничего дополнительно, не читал как устроены LLM в деталях, но за счет переключения между разными инструментами, я начал замечать определенные паттерны, и в конечном счете пришел к определенным выводам, которые позволяют гораздо эффективнее использовать силу LLM’ок в инди-разработке (не вижу причин, почему это не будет работать в компании, но об этом в следующих постах).
Выводы могут быть неточными с точки зрения Data Science (буду рад услышать фидбек), однако в упрощенном виде оно так и работает. Надеюсь это будет полезно широкому кругу разработчиков, и в целом станет более понятно, как модели работают, почему глючат и что с этим можно сделать.
На что жалуются разработчики
В этой части я хочу разобрать несколько основных проблем, которые озвучивают разработчики, и объяснить, почему эти проблемы возникают.
Я буду разбирать только базовые принципы и ограничения, которые никуда не денутся в ближайшем будущем. А пока мы наблюдаем, как появляются различные способы обхода этих ограничений и используем это в своей работе.
Проблема №1: LLM галлюцинирует
Мне понравилась фраза - “LLM галлюцинирует в 100% случаев, но в 80% модель права”. Любая мне известная LLM всегда стремится вам предоставить ответ, пусть даже и неверный. Фундаментально это сложно решить. Однако, стоит понимать, что есть разные причины галлюцинаций, и по отдельности их решить можно. В этом параграфе я разберу одну из таких причин.
Начну с теории. У каждой модели есть ограниченное context window - это объем текста, который LLM может одновременно учитывать или “помнить” при генерации ответа. Размер context window считают в токенах, но все усложняет то, что токен - величина не постоянная. Для упрощения считают, что один токен (для английского языка) это 4 символа. То есть грубо говоря 100 токенов вмещает 75 английских слов.
Примеры размеров context window для разных моделей:
- gpt-3 - 2,048 токенов (1,500 английских слов)
- gpt-4o - 128,000 токенов (~96,000 английских слов)
- gpt-4.1 - 1,000,000 (~750,000 английских слов).
Посчитать, сколько в вашем тексте токенов можно по ссылке https://platform.openai.com/tokenizer. Важная ремарка - размер контекста не определяет напрямую на сколько “умная” модель. Но способность держать больше контекста точно идет моделям на пользу.
Когда вы переписываетесь с ChatGPT, в рамках каждого диалога у вас есть этот самый лимит. Если лимит превышен - модели начинают забывать (вытеснять) факты из диалога и галлюцинировать.
Создатели популярных моделей используют один способ для обхода этого ограничения. Чтобы не передавать весь диалог вместе с каждым новым сообщением к модели, они создают краткую выжимку с основными фактами после каждого полученного нового сообщения, и используют эту выжимку как контекст вместо передачи всего диалога. Это позволяет вам вести диалог дольше, но некоторые факты все же теряются. Выжимки создаются теми же моделями, у которых те же ограничения. На ранних этапах зарождения LLM такой хак позволял увеличивать длину диалога. С ростом размера context window этот хак продолжает использоваться, но уже для оптимизации потребления вычислительных ресурсов (чем больше размер контекста, тем больше ресурсов требуется для обработки и генерации ответа).
Когда речь идет про разработку - принцип тот же. Однако я подозреваю, что Cursor и другие редакторы не создают выжимку из кода который вы шарите с ними, чтобы точность ответа была выше. И, как следствие, у вас быстрее заполняется контекстное окно.
Проблема №2: LLM использует устаревшую информацию
Каждая модель обучена на разных сетах данных, которые могут не включать в себя какие-то специфичные данные, такие как информация о последних версиях вашего любимого фреймворка. Да и в целом, могут и вовсе не знать о его существовании. Для не особо популярных технологий меньше информации в интернете, а следовательно и количество данных для обучения содержит меньше информации, что так же приводит к галлюцинациям, так как модели всегда стремятся дать какой-то ответ.
Модели широкого спектра очень популярны (GPT, Claude, Gemini и т.д.), но также набирают популярность и модели узкого спектра, натренированные на специализированных сетах данных. Например, модели конкретно для программирования (OpenAI Codex), или медицинские модели. Ввиду того, что обучаются такие модели на релевантном материале, их результаты работы - ощутимо лучше. Однако так же, как и в случае с общими моделями, их знания ограничиваются данными, включенными в обучение.
Представьте, что вас отправили на необитаемый остров на 20 лет. Мир уже шагнул вперед, а ваши знания застыли на определенной точке. С моделями так же. Их периодически требуется переобучать/дообучать на новых данных, чтобы они были релевантными.
Также важно упомянуть, что модели не имеют доступа к интернету, однако все основные игроки на рынке AI внедрили возможность поиска в интернете и использования результатов поиска в рамках вашего диалога. Это позволяет получать доступ к свежей информации, даже несмотря на то, что модель была обучена на старых данных. Как наверняка это реализовано - сказать сложно, но один из способов этой реализации - это разработка агента на базе MCP протокола. В детали вдаваться тут не буду, но замечу, что проще всего думать, что MCP - это протокол, по которому модели могут взаимодействовать с внешними сервисами, понимать список их функций и выполнять их.
Проблема №3: Каждый раз приходится объяснять все по новой
Модель сама по себе не имеет памяти. Она не может записывать то, что вы в нее отправляете. Однако все крупные игроки внедрили эмуляцию “памяти” в свои официальные клиенты. Например, ChatGPT, по ходу ваших диалогов своими моделями определяет “факты” о вас, которые имеет смысл сохранить. А потом использует эти факты как часть контекста для ваших чатов. Это и создает иллюзию того, что модель кое-что знает о вас. Также, память можно реализовать с помощью упомянутого ранее MCP или RAG.
Так что, если при разработке вы устали повторять одно и тоже, придется найти механизм эмуляции “памяти” для модели. И такой способ есть, об этом будет ниже.
Как решать эти проблемы в Cursor AI
Описанные проблемы и способы обхода могут казаться очевидными и я уверен, что многие уже знакомы с ними так или иначе. Но с учетом того, что я регулярно объясняю одно и то же разным людям, есть пустота, которую хочется заполнить.
Давайте на примере Cursor AI разберемся, как можно решать перечисленные выше проблемы конкретно для разработки.
1. Ограничение Context Window
Любые ресурсы ограничены. И так же стоит относится к LLM, здесь нет никакой магии.
Вот несколько практик, которые помогут вам сталкиваться с галлюцинированием реже из-за размера Context Window:
Создавайте новые диалоги как можно чаще
Старайтесь следовать принципу: 1 проблема/задача/вопрос = 1 диалог. Когда диалог получается большим - просите создать выжимку для нового диалога и копируйте ее в новый диалог. Также вспомните ситуацию, когда во время разговора вы резко меняли тему и ваш собеседник отвечал что-то не по теме. С моделями такое тоже случается, когда вы смешиваете вопросы, поэтому стоит создавать новый диалог для обсуждения чего-то не связанного с предыдущей темой.
Передавайте в диалог только необходимый контекст
Вы можете выбрать весь проект в качестве контекста и получить хороший результат. И такое возможно, но в основном только для маленьких проектов. Для средних и больших, увы, придется выбирать контекст вручную.
Переключайтесь на модель с бОльшим context window
Иногда требуется загрузить больше контекста, и в этом случае вы можете попробовать переключиться на модель с большим размером context window. Но для этого придется познакомиться с теми моделями, которые представлены в Cursor и изучить их характеристики. Тут вы можете познакомится с описанием моделей от OpenAI.
Ограничьте индексацию проекта
У Cursor есть механизм .cursorignore
. Он позволяет Cursor’у игнорировать и не индексировать определенные части вашего проекта. Тем самым сужая scope проекта и увеличивая скорость при поиске. Это актуально для монорепозиториев и больших проектов. Подробнее тут.
2. Доступ к актуальной информации
Досадно, когда ты уже используешь React 19, а Cursor подсказывает только по 18 версии, так как модель была обучена на данных, когда 19 версии еще не было.
Разработчики Cursor предлагают несколько способов, как решить эту проблему.
Используйте тег @docs
При использовании тега @docs <url>
и предоставления ему ссылки на актуальную документацию, Cursor запустит индексацию страниц, и по завершении будет помогать вам уже с полным пониманием новых фишек фреймворка.
Точно так же решается проблема с внутренней документацией. Строго говоря, вы можете скормить и swagger документацию от вашей внутренней апишки.
Используйте тег @web
Для поиска другой информации в сети, не покидая вашей IDE, воспользуйтесь тегом @web запрос
. Казалось бы ничего особенного, загуглить можно и без этого, но тут можно работать с этой информацией в рамках того же чата. Так могут подтягиваться решения со StackOverflow, например.
Используйте MCP
Cursor позволяет подключить любые MCP, которые потом будут использоваться в ваших чатах при необходимости. Один из примеров - MCP context7 который как раз помогает получать актуальную документацию.
3. Учим Cursor запоминать
Что может быть интереснее, чем каждый раз объяснять Cursor, как у вас организованы файлы и методы? Или как создать новый API в вашем проекте? Или стоит ли использовать внешние библиотеки, либо ограничиваться стандартной библиотекой? Или может как устроена межсервисная архитектура и в чем основная цель проекта?
Ссылаемся на старые чаты
Cursor недавно добавил возможность ссылаться на ваши старые чаты. Это можно использовать в формате “сделай так же, как и в том чате”, либо как продолжение связанной задачи.
Ссылаемся на файлы
Неочевидно, но тоже можно использовать в формате “проанализируй этот файл/папку и сделай так же”.
Cursor Rules
У Cursor и других IDE уже есть ответ по части организации памяти - cursor rules.
Это файл (либо набор файлов в случае Cursor), которые передаются автоматически (или вручную) в рамках вашего контекста. Таким образом, при наличии документации в формате cursor rules
, вам не придется больше повторять себя, а Cursor будет ориентироваться на ваши существующие стандарты.
Да, это по факту документация, и да, ее нужно писать. Cursor, как и junior разработчик нуждается в объяснениях и руководстве. Хотя некоторые агенты (например JetBrains Junie) делают успехи в анализе существующего кода, пытаясь сделать так же. Такой подход хоть и удобен, но не всегда эффективен, особенно, когда работаешь со старым кодом.
Хорошие новости в том, что всегда можно попросить Cursor сгенерировать и сохранить правила на основе вашего чата (прям так и спросить). А буквально несколько дней назад они реализовали команду /Generate Cursor Rules
, которая именно это и делает. Да, результат придется поревьювить и, возможно, попросить пару раз внести правки, но это значительно сокращает трудозатраты на описание.
И как приятное дополнение - новички в вашей команде смогут читать ваши cursor rules
как документацию и стандарты.
В заключении
В заключении, предлагаю вам подумать и ответить на следующие вопросы:
- Сколько токенов в этой статье?
- Как потенциально себя будет вести Cursor при работе с файлом на 10 тысяч строк?
- Что требуется сделать, чтобы эффективно провести рефакторинг с помощью Cursor?
- Как заставить Cursor запускать линтеры или сборку в конце каждого чата и исправлять ошибки автоматически?
Эффективное использование вполне возможно при понимании, какие ограничения есть у LLM.