LLM понимание кода через LSP: модель получает типы и связи вместо сырого текста
Языковые модели генерируют код строка за строкой, но без понимания структуры проекта они не видят, какой тип у переменной, какие методы доступны у импортированного сервиса и где объявлен нужный класс, а Language Server Protocol (стандарт связи между редактором и языковым анализатором) уже хранит все эти связи.

LSP-контекст превращает автодополнение из текстовой угадайки в осмысленный вывод: модель получает не похожие строки, а точные определения типов, сигнатуры методов и граф зависимостей проекта, поэтому качество подсказок растёт без дообучения (обучения модели на ваших примерах под узкую задачу).
Идея проста: IDE уже знает, что returnService это объект с методами submit, cancel, getById и update. Проблема в том, что большинство систем автодополнения на базе LLM (большой языковой модели) до сих пор ищут контекст через текстовое сходство, например через алгоритм BM25. Совпадение слов не равно связи между частями программы. Источник, на который опирается этот материал, показывает, как подключить языковой сервер к конвейеру автодополнения и передать модели структурированные факты вместо сырого текста.
Что понадобится
- Редактор с поддержкой LSP: VS Code, IntelliJ IDEA (через PSI, внутреннюю систему семантического анализа кода), Eclipse, Vim/Neovim с LSP-клиентом или любой другой, поддерживающий протокол
- Языковой сервер для вашего стека: TypeScript Language Server, gopls для Go, rust-analyzer для Rust и так далее
- Доступ к LLM с поддержкой FIM (Fill-in-the-Middle, режим дописывания кода в середине файла): подойдут модели, работающие через API, в том числе доступные на Yandex Cloud
- Базовое понимание JSON-RPC: протокол прост, запрос содержит поля
method,paramsиid, ответ возвращает тот жеidи либоresult, либоerror - Время: настройка занимает от одного до трёх часов, если языковой сервер уже установлен
Как устроена сессия между редактором и языковым сервером?
Прежде чем строить конвейер, полезно увидеть, что происходит «под капотом». Протокол LSP стандартизирует обмен между LSP-клиентом (встроен в редактор) и языковым сервером (отдельный процесс, который разбирает код).
27 июня 2016 года Microsoft, Red Hat и Codenvy публично объявили о совместной работе над LSP. VS Code уже использовал JSON-протокол для общения с языковыми серверами, Codenvy добавляла поддержку в Eclipse Che, а Red Hat работала над отдельным Java-сервером. Спецификацию открыли, чтобы один сервер подключался к разным редакторам.
Сессия выглядит так:
- initialize: клиент и сервер обмениваются возможностями, редактор узнаёт, какие языковые функции поддерживает сервер
- didOpen / didChange: редактор передаёт серверу актуальную копию файла, включая несохранённые изменения
- textDocument/definition, textDocument/hover, textDocument/references: клиент спрашивает, сервер отвечает адресом определения, типом, списком использований
Сам протокол не понимает TypeScript, Go или Rust. Он задаёт формат сообщений, а точность ответов зависит от конкретного языкового сервера.
Пошаговая инструкция
- Определите точку курсора и соберите импорты
Система автодополнения фиксирует позицию курсора в файле. В примере из источника курсор стоит на строке 8 внутри функции createReturn, после набранных букв ret.
- Отправьте
textDocument/definitionдля каждого импорта
Для импорта returnService запрос выглядит так:
json
{
"method": "textDocument/definition",
"params": {
"textDocument": { "uri": "file:///project/returns.ts" },
"position": { "line": 0, "character": 12 }
}
}
Языковой сервер вернёт не исходный код, а адрес: URI файла и диапазон строк, где объявлен returnService. LSP-клиент читает этот файл и извлекает определение.
- Запросите тип переменной через
textDocument/hover
Для переменной request с типом ReturnRequest сервер вернёт сигнатуру интерфейса: поля orderId, reason и их типы. Модель получит точную структуру, а не угадает её по совпадению имён.
- Соберите доступные методы через
textDocument/completion
Если пользователь написал returnService., сервер вернёт допустимые элементы: cancel, getById, submit, update. Но в нашем случае мы не останавливаемся на списке методов: LLM предскажет намерение и сгенерирует целое выражение, используя сигнатуры этих методов как контекст.
- Сформируйте промпт (запрос к модели) с LSP-контекстом
Вместо того чтобы вставлять в промпт «похожие файлы», добавьте конкретные блоки:
- определение returnService с его методами и аргументами
- интерфейс ReturnRequest с полями
- интерфейс ReturnReason, если он доступен через цепочку определений
- Передайте собранный контекст в LLM в режиме FIM
Модель получает префикс (код до курсора), суффикс (код после курсора) и LSP-контекст как дополнительный блок. Результат: подсказка опирается на реальные типы и сигнатуры, а не на текстовое сходство.
Ввод. Курсор стоит после ret внутри функции createReturn. Без LSP-контекста модель видит только текст файла и результаты BM25-поиска, то есть файлы, где встречаются слова ReturnRequest и returnService.
С LSP-контекстом. Система отправила textDocument/definition для returnService и получила файл с объявлением сервиса, где видны методы submit(command), cancel(id), getById(id), update(id, data). Затем через textDocument/hover извлекла тип аргумента command у метода submit.
Результат. Модель сгенерировала:
return returnService.submit({
orderId: request.orderId,
reason: request.reason
});
Подсказка точно соответствует сигнатуре метода и полям интерфейса, потому что модель видела определение, а не догадывалась по совпадению слов.
Путать текстовое совпадение с семантической связью. BM25 находит файлы, где встречается слово returnService, но не отвечает на вопрос, какой тип у этой переменной и какие методы ей доступны. Если ограничиться только текстовым поиском, LLM-понимание кода остаётся поверхностным.
Забывать про несохранённые изменения. LSP работает с виртуальной копией файла, которую передаёт didChange. Если ваш конвейер читает файл с диска, а не из LSP-сессии, контекст может устареть на несколько правок.
Считать, что LSP и textDocument/completion достаточно. Встроенное автодополнение сервера отвечает на вопрос «какие символы допустимы здесь», а LLM решает более общую задачу: предсказать намерение и сгенерировать выражение. LSP даёт факты, модель строит из них ответ.
Игнорировать платформенные различия. В IntelliJ IDEA данные часто приходят не через LSP, а через PSI (Program Structure Interface, внутренняя модель кода JetBrains). Метод доступа другой, но принцип тот же: получить определение, тип и связи.
Что делать с этим прямо сейчас?
Разработчику на 1С или в Yandex Cloud. LSP-серверы существуют для десятков языков. Если вы работаете в VS Code с подключением к облачной среде, проверьте, поддерживает ли ваш языковой сервер методы definition, hover и references. Эти три метода покрывают базовый набор для построения контекста.
Автору технического контента на Дзене. LLM-понимание кода через LSP это конкретная тема для серии постов с практическими примерами. Покажите разницу между подсказкой «без контекста» и «с LSP-контекстом» на скриншотах, такой формат собирает сохранения.
Тимлиду или предпринимателю. Если ваша команда использует внутреннее автодополнение, добавление LSP-контекста не требует дообучения модели и не увеличивает расходы на инференс (вычисление ответа модели). Вы улучшаете вход, а не меняете модель.
По моим наблюдениям, большинство открытых проектов автодополнения до сих пор ограничиваются текстовым поиском по репозиторию. LSP-контекст даёт модели то, чего у неё нет по определению: граф связей конкретного проекта, актуальный на момент нажатия клавиши. Это не замена дообучения и не магия: если языковой сервер для вашего стека слаб (а для некоторых языков он действительно сырой), качество контекста будет соответствующим. Но для TypeScript, Go, Rust, Java, Python серверы зрелые, и выигрыш ощутим без единого дополнительного запроса к модели.
Связка LSP и LLM не требует замены модели или редактора. Она требует одного архитектурного решения: спрашивать у IDE то, что IDE уже знает, и передавать ответ в промпт. Кто сделает это первым в своём рабочем процессе, получит подсказки, которые читают структуру проекта, а не гадают по словам.
Попробуйте генератор промптов dzen.guru
Соберите системный промпт для кодового ассистента с учётом LSP-контекста за пять минут
Попробовать
Основатель dzen.guru. Эксперт по монетизации и продвижению на Дзен. Автор курса «Старт на Дзен 2026».
Читайте также

Meta запустила Pocket: создание игр без кода через промпты прямо в соцсети
Meta второго июня открыла для всех пользователей в США приложение Pocket, которое позволяет создавать небольшие интерактивные игры текстовыми промптами…

Skala 1.1 ускоряет DFT вычисления: точность дорогих методов за цену полулокального функционала
Microsoft Research обновила Skala до версии 1.1 и начала встраивать этот нейросетевой функционал в пять крупных пакетов вычислительной химии, включая CP2K,…

ChatGPT получил доступ к Apple Messages: бот читает и отправляет сообщения за вас
ChatGPT теперь работает внутри Apple Messages: OpenAI выпустила плагин, который читает, сортирует и отправляет сообщения от имени пользователя, но просит не…
Комментарии