Привет, Хабр! На фоне популярности decision‑моделей мне захотелось познакомиться с их механизмом работы. Объектом исследования я выбрал модель Clef от Cloudflare просто потому, что она больше всего на слуху.
Статья носит познавательный характер и будет интересна тем, кто, как и я, захочет разобраться в работе модели. Фрагменты кода и конфигурации взяты из репозитория авторов.
номер токена в позиции (input_ids[t])
Запрос состоит из state (о чём решаем) и questions (что нужно решить). Пример от Cloudflare:
- создаются автоматически: true, false
- ключи criteria, отсортированные по алфавиту
- индексы списка criteria: «0», «1», …
Для team получается отсортированный по ID список:
Этап 1. encode_record: запрос становится текстом
encode_record склеивает все поля JSON в один промпт и попутно запоминает, где в нём лежит каждый вопрос и каждая опция.
Шаг 1. question_options превращает criteria в список пар (раздел 2).
Шаг 2. Каждая пара заворачивается в маленький словарь:
Шаг 3. Словарь превращается в строку функцией render:
Фиксированный порядок ключей и отсутствие пробелов нужны, чтобы одна и та же опция всегда давала одни и те же токены.
Промпт целиком ([префикс], [state] и т.д. добавлены для наглядности):
После токенизации алгоритм запоминает позиции в промпте вопросов и опций:
Каждый кусок токенизируется отдельно для того, чтобы не происходило склеивание (если токенизировать весь промпт целиком, BPE может склеить конец «OPTION 1: » с началом JSON в один токен).
После этого происходит сдвиг всей схемы на длину префикса и state:
пар чисел, сгруппированы по вопросам
На этом этапе происходит расчёт по всем слоям без головы и применение LayerNorm к последнему выходному слою:
last_hidden_state — по вектору на каждый токен каждой записи батча.
После этапа 2 есть таблица. Номер строки совпадает с номером токена в input_ids. Этап A вырезает из этой таблицы нужные строки (спаны, которые были выделены ранее).
те же позиции, но через input_ids в таблице lm_head
Вектор вопроса
Пусть question_span team = (5, 8), то есть строки 5, 6, 7:
Каждая координата — среднее трёх чисел в столбце: например, (0.2+0.8-0.1)/3=0.3.
Контекстный вектор опции. Пусть option_span billing = (9, 11), то есть строки 9 и 10:
Лексический вектор опции. Позиции те же (9, 11), но строки берутся не из . Сначала по спану читаются номера токенов, потом по этим номерам берутся строки lm_head (номера условные):
Разница между ctx и lex: строка 9 в — это слово «billing», прочитанное Qwen после тикета, и она меняется от запроса к запросу. Строка — слово «billing» само по себе, и она всегда одна и та же.
g и memory. g — просто последняя строка таблицы. memory — все строки, каждая умноженная на . Спаны тут не нужны.
по вектору на вопрос, в порядке вопросов
Прежде чем переходить к следующему этапу распишу какие проекции мы имеем:
- вопроса, которому принадлежит опция
Evidence routing
— этап, в котором каждая опция сама ищет в тексте подтверждения для себя. Это два одинаковых по устройству слоя EvidenceRoutingLayer, каждый со своими весами.
Каждая опция обрабатывается независимо и на выходе получаем распределение «важности» токена всего запроса к конкретной опции.
- что Qwen понял об опции после прочтения тикета;
- что значат слова опции сами по себе;
- к какому вопросу опция относится. Опция ищет в тексте «что-то про себя в контексте этого вопроса».
Опции всех вопросов склеиваются в одну матрицу. Это же представление попадает на вход второго EvidenceRoutingLayer.
Сборка запросов и вызов слоёв в JointSchemaHead.forward
режется обратно на группы вопросов (обогащённые).
Этап C1. Сборка поля для каждого вопроса
На этом этапе для каждого вопроса собирается один вектор — поле. Поле дальше пойдёт в joint‑слои, и в конце с ним будут сравниваться опции.
- — Softmax. Распределение опций каждого вопроса.
- — получаем вектор, который представляет собой общую картину по всем опциям для каждого вопроса.
- — глобальная добавка. Все поля «знают», о чём весь тикет.
- — эмбеддинг типа. Таблица из трёх обучаемых строк: noul, choice, score. Поле знает, как будут читаться его опции.
На этом этапе вопросы впервые узнают друг о друге. Поля обмениваются информацией и ещё раз сверяются с текстом.
TransformerDecoderLayer
— базовый слой декодеров в архитектуре Transformer.
- Self‑attention: вопросы смотрят друг на друга
Запросы, ключи и значения берутся из одних и тех же полей (16 голов по 64), матрица внимания каждой головы имеет размер:
Строка — кто смотрит, столбец — на кого. Каждое поле смотрит на все три, включая себя.
- Cross‑attention: поля читают текст
Смысл: после подблока 1 поле уже знает, что думают другие вопросы, и перечитывает текст с этим знанием. Например, поле severity, получив от urgent сигнал «срочно», может внимательнее посмотреть на «every customer».
Объявление скорера и масштабов в _init_:
Логит собирается из двух независимых частей:
- prior работает только с , в пространстве Qwen (5120);
- joint работает только с и в пространстве головы (1024).
— смысл вопроса плюс смысл всего запроса.
Лексический вектор — словарный смысл слов опции без контекста.
- — обучаемый коэффициент масштабирования
2c. MLP (residual_scorer в коде) по признакам пары. Для каждой пары собирается вектор длиной 4096:
Применение Softmax в рамках вопроса:
В этой статье я постарался осветить процесс работы модели принятия решений Clef. Если вы заметили неточность в излагаемом материале — буду рад услышать ваше объяснение и критику для более глубокого понимания работы!
Claude за полчаса разгадал загадку АНБ, которой больше 25 лет
Четверть века вокруг одного из главных стандартов современной криптографии держалась почти детективная интрига. В 2000 году американский институт стандартов NIST утвердил набор эллиптических кривых от P‑192 до P‑521 — сегодня на P‑256 держатся подписи сертификатов сайтов, токены входа и защищённые чипы телефонов. Параметры этих кривых выведены из начальных значений (seed), которые Агентство национальной безопасности США передало в стандарт без всяких объяснений. 16 октября 2026 года команда Anthropic сообщила, что её внутренняя исследовательская модель Claude меньше чем за полчаса нашла происхождение этих чисел, а криптограф Филиппо Вальсорда, объявивший за разгадку награду, подтвердил правильность решения.
Как я выгружал 1,8 TB с Яндекс Диска после аварии в дата‑центрах
Anthropic забанила мой Claude и отдала в экспорте только телефон. Теперь мне отвечает Grok в парике.





