Кодинговые AI ассистенты
Fill-in-the-Middle: как модель дописывает код в середине файла
Клоуз-тест (cloze-test) -- это упражнение, в котором некоторая часть текста скрывается (маскируется), и участнику необходимо заполнить эти пробелы учитывая лексику и контекст. Слово cloze произошло от closure из Гештальдпсихологии, а сам тест предложил Вилсон Тэйлор в далеком 1953 году [1]. В 2018 году похожий тест применили для обучения языковой модели BERT [2]. Если классически LLM обучается предсказывать следующий токен для некоторой входящей последовательности
token1, token2, token3, ... -> predict_next_tokenто в "cloze" подходе авторы статьи заставили BERT модель предсказывать замаскированные токены получая на вход контекст слева и справа, которые обычно называют PREFIX и SUFFIX
Подобный метод обучения моделей называют Fill-in-the-Middle (FIM). Эту идею можно применить и к тексту, содержащему код. Обычно при FIM подходе во время обучения добавляют специальные токены, которые обозначают PREFIX, SUFFIX, MIDDLE (замаскированный код). На картинках эти токены обозначены |PREFIX| , |SUFFIX| и |MIDDLE| соответственно
Тут |END_OF_TEXT| так же является специальным токеном, который обозначает конец генерации. Его можно воспринимать как один из стоп-сигналов: если модель сгенерировала его, клиент прекращает генерацию и возвращает ответ (без этого токена). На практике часто добавляют и другие стоп-условия. В итоге, так как LLM просто продолжает входящую последовательность, отправляя на вход |PREFIX|{prefix}|SUFFIX|{suffix}|MIDDLE| мы ожидаем получить {masked_code}|END_OF_TEXT|
Рассмотрим небольшой пример: пусть в некотором файле card.py мы замаскировали код Card("Q", "Hearts") и хотим, чтобы LLM его предсказала. Во время обучения модель учится предсказывать продолжение PREFIX так, чтобы после логично следовал SUFFIX. Она заметит в префиксе созданный датакласс Card, а в суффиксе -- объект card действительно имеет тип Card, т.к. идет обращение к его полю card.rank. Составим промт для LLM по принципу, описанному выше
В нашем примере мы получим какой-то такой ответ
Обычно модели содержать и другие специальные токены, которые позволяют предоставлять модели дополнительный контекст: содержание других файлов, содержание pull request, репорты из github/gitlab issues, и т.д.
Единого нэйминга для таких спец. токенов нет. В этой книге мы будем использовать обобщенный вид |{TOKEN_NAME}|, не привязываясь к конкретной модели. Вот небольшая таблица с примерами таких токенов для популярных кодинговых моделей
Токен |FILE_SEP|, как легко догадаться, служит для разграничения кода из разных файлов. Как показано в таблице -- не все модели во время обучения явно имеют спец. токен для этого. Например, модель Codestral multifile собирает несколько секций вида
+++++ path/to/file.ts
{content}
+++++ path/to/current.ts
{prefix}и после объединяет их в финальный шаблон вида
[SUFFIX]{suffix}[PREFIX]{all_files_plus_current_prefix}Другими словами, все кодовые сниппеты добавляются к префиксу основного файла. Подробнее о том, как FIM используется при обучении кодовых моделей, можно прочитать в работах [3]-[7].
Тут важно отметить, что предсказывать замаскированный код можно не только с помощью FIM обученной модели, но и с помощью обычной instruct LLM по типу GPT. Но обычно так не делают. FIM-модель обучена ровно на такую задачу, когда instrcut-модель использует другой интерфейс: ей дают человеческую инструкцию, а она отвечает как ассистент. Примером может служить следующий промпт
You are a HOLE FILLER...
...
<QUERY>
{prefix}{{FILL_HERE}}{suffix}
</QUERY>
TASK: Fill the {{FILL_HERE}} hole.
Answer only with the CORRECT completion...
<COMPLETION>Ожидается, что instruct-модель допишет только содержимое completion, а роль |END_OF_TEXT| тут будет выполнять сгенерированный LLM текст </COMPLETION>
You are a HOLE FILLER...
...
<QUERY>
{prefix}{{FILL_HERE}}{suffix}
</QUERY>
TASK: Fill the {{FILL_HERE}} hole.
Answer only with the CORRECT completion...
<COMPLETION>
↓
LLM
↓
SOME_FILL</COMPLETION>Источники
- Cloze Procedure: A New Tool for Measuring Readability - Wilson L. Taylor, 1953. Работа, в которой был предложен cloze-тест.
- BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding - Jacob Devlin et al., 2018. Описание masked language modeling — задачи восстановления скрытых токенов, использованной при обучении BERT.
- Efficient Training of Language Models to Fill in the Middle — OpenAI, 2022. Исследование FIM-обучения и способов преобразования исходных последовательностей в пары из префикса и суффикса.
- Qwen2.5-Coder Technical Report — Qwen Team, 2024. Технический отчет о семействе Qwen2.5-Coder, включая обучение моделей решению задач дополнения кода.
- StarCoder 2 and The Stack v2: The Next Generation — BigCode, 2024. Описание моделей StarCoder2, обучающего корпуса The Stack v2 и используемого подхода к FIM-обучению.
- Seed-Coder: Let the Code Model Curate Data for Itself — ByteDance Seed, 2025. Технический отчет о подготовке данных и обучении семейства кодовых моделей Seed-Coder.
- DeepSeek-Coder-V2: Breaking the Barrier of Closed-Source Models in Code Intelligence — DeepSeek AI, 2024. Описание архитектуры, обучения и возможностей DeepSeek-Coder-V2.