На фоне популярности decision‑моделей полезно разобрать их внутреннюю логику на конкретном примере. В этой статье описывается архитектурный обзор модели Clef от Cloudflare: как запрос превращается в токены, какие промежуточные представления формируются и как модель сравнивает опции для вынесения решения.
Формат запроса и токенизация
Запрос в Clef состоит из полей state (о чём решается) и questions (что нужно решить). Для вопросов формируется отсортированный по ключам список criteria с индексами «0», «1» и т. п. Перед подачей в языковую модель все поля JSON конкатенируются в единый промпт с фиксированным порядком ключей и без лишних пробелов — это обеспечивает детерминированную токенизацию одинаковых опций.
При токенизации модель запоминает позиции (спаны) для каждого вопроса и для каждой опции внутри промпта. Каждый фрагмент токенизируется отдельно, чтобы избежать нежелательной агрегации токен‑байтов, возникающей при совместной BPE‑токенизации всего промпта сразу. После токенизации происходит смещение позиций на длину префикса и state.
Этап 1 — encode_record и сохранение спанов
Функция encode_record собирает поля запроса в строку и фиксирует, где именно находятся вопросы и опции. На выходе получается промпт и набор спанов — интервалов токенов для каждого логического элемента (вопрос, опция).
Этап 2 — прогон через языковую модель
Промпт прогоняется через все слои модели без головы предсказаний, применяется LayerNorm к последнему выходному слою. Получается last_hidden_state — вектор для каждого токена. По таблице токенов затем вырезаются нужные строки по заранее сохранённым спанам.
Представления: вопрос, контекст опции и лексический вектор
- Вектор вопроса получается как усреднение векторов токенов, попадающих в span вопроса.
- Контекстный вектор опции формируется как усреднение векторов токенов опции из last_hidden_state; этот вектор отражает, как модель понимает опцию в контексте конкретного запроса.
- Лексический вектор опции — представление опции «самой по себе»; он берётся из другой проекции (например, из lm_head) и не зависит от контекста запроса.
- g — вектор последней строки таблицы; memory — матрица всех строк с масштабированием, используемая для дальнейших операций внимания.
Evidence routing
Evidence routing — этап, в котором каждая опция независимо «ищет» в тексте подтверждения для себя. Реализовано два слоя EvidenceRoutingLayer с отдельными весами. Для каждой опции вычисляется распределение важности по токенам всего запроса: модель определяет, какие части текста релевантны для конкретной опции, учитывая три фактора — как модель поняла опцию в контексте тикета, что означает опция сама по себе (лексика) и к какому вопросу опция относится.
На выходе опции всех вопросов объединяются в одну матрицу, которая затем подаётся на второй слой evidence routing для уточнения внимания.
Сборка и обогащение полей вопросов (JointSchemaHead)
После evidence routing представления режут обратно по вопросам. Для каждого вопроса собирается одно «поле» — вектор, агрегирующий информацию по всем его опциям. На этом этапе применяются несколько механизмов:
- Softmax по опциям в рамках вопроса — распределение вероятностей;
- агрегация по опциям для получения общего представления по вопросу;
- глобальная добавка: поля обмениваются информацией, чтобы учитывать общую ситуацию тикета;
- эмбеддинг типа поля: обучаемая таблица несколькими строками, которая подсказывает, как будут читаться опции (например, noul, choice, score).
После этой стадии вопросы начинают «знать» друг о друге: поля обмениваются информацией и заново сверяются с текстом, что позволяет учитывать межвопросные зависимости при принятии решения.
TransformerDecoderLayer в joint‑слоях
Для обмена информацией между полями применяются блоки, схожие с Transformer decoder layer:
- Self‑attention: поля смотрят друг на друга (multi‑head attention), каждая голова имеет свои Q/K/V. Это позволяет полям учитывать мнения других полей при формировании собственного представления.
- Cross‑attention: поля читают текст (memory), перечитывая контекст с учётом полученной межполной информации.
Идея в том, что поле, получив сигнал от другого вопроса (например, «срочно»), может внимательнее просмотреть релевантные фрагменты текста.
Сборка скорера и расчёт логитов
Итоговый логит для пары (вопрос, опция) собирается из двух независимых частей:
- prior — часть, работающая в пространстве больших контекстных эмбеддингов (пространство Qwen), основанная на представлении вопроса и опции без взаимодействия в joint‑голове;
- joint — часть, работающая в пространстве головы (меньшая размерность), использующая межполные представления и итоговую совместную обработку.
Кроме того, в расчёте участвует лексический вектор опции (словесный смысл опции без контекста) и обучаемые коэффициенты масштабирования. Для каждой пары формируется большой признак‑вектор (в реализуемом коде это MLP residual_scorer), который затем преобразуется в скалярный логит. Внутри каждого вопроса по полученным логитам делается Softmax для получения финального распределения по опциям.
Итог
Clef использует комбинированный подход: близкую к языковой модели токенизацию и контекстные эмбеддинги, специализированные слои evidence routing для поиска релевантных доказательств в тексте, обмен информацией между вопросами через joint‑слои и итоговый скоринг пар «вопрос–опция», объединяющий prior‑ и joint‑компоненты. Такая архитектура позволяет учитывать как локальный смысл опций, так и глобальную структуру запроса при принятии решения.
Если вы заметили неточность в изложении или хотите уточнить отдельные этапы — пишите объяснение или уточняющие вопросы для более глубокого разбора.



