
Как проверить, что API LLM служит объявленную модель
Языковые модели не могут выбрать случайное число. Этот дефект — это стабильная цифровая подпись для проверки, служит ли API объявленную модель.
Попроси языковую модель выбрать случайное число от 1 до 100 достаточно раз — и произойдёт что-то странное: ответы не случайны. Одна модель постоянно выбирает 42 и 73. Другая предпочитает 47 и 57. Паттерн стабилен, воспроизводим и отличается для каждой модели.
В июле 2026 года одна статья превратила эту странность в метод верификации. One Token Is Enough: Fingerprinting and Verifying Large Language Models from Single-Token Output Distributions показывает, что распределения ответов образуют надёжный поведенческий отпечаток — достаточный, чтобы проверить снаружи, служит ли API-endpoint объявленную модель[1]. Без весов, логитов, привилегированного доступа. Просто сотни односложных ответов.
В этом гайде объясняется, почему поле model — это скорее утверждение, чем гарантия, как работает отпечатков одного токена, что означают цифры и где границы метода.
TL;DR
- Поле
modelв ответе API не поддаётся верификации протоколом. Ничто не доказывает, что запрос на флагманскую модель был ею обработан[1]. - Языковые модели не могут выдать равномерное распределение. На наборе проб из статьи медианное распределение ответов содержит около 1.0 бита энтропии вместо 6.64 бит, которые давало бы равномерное число от 1 до 100[1].
- Этот дефект постоянен, поэтому он работает как подпись. Одна модель, один скос, каждый раз.
- На шкале есть разделение: одна модель против себя даёт JSD около 0.14, одна модель у двух провайдеров — около 0.23, две разные модели — около 0.46[1].
- Точность высока, но не идеальна. Равнополовинная ошибка — 10.6% при 8 пробных единицах и 7.3% при полном наборе 40, AUC = 0.971[1].
- Несовпадение — это признак, не доказательство. Квантование, тихое обновление версии, скрытый системный промпт — всё это смещает распределение без обмана.
Ты не видишь, что скрывается за API
Когда ты обращаешься к endpoint чат-дополнений, отправляешь текст и получаешь текст. Поле model в ответе содержит то, что решил туда положить сервер. Ничто в протоколе не доказывает, что запрос был обработан моделью с этим именем, а не чем-то в десять раз дешевле[1].
Эта щель становится критична, когда всё больше рынка работает через посредников: агрегаторы перепродают сотни моделей через один endpoint, региональные реселлеры предлагают флагманский доступ ниже официальной цены, сторонние хосты сервят open-weight модели с выбранным квантованием и стеком развёртывания, который ты не видишь[1].
Большинство таких бизнесов честные. Но стимул к обману очевиден, и отдельный аудит 17 shadow-API операторов обнаружил несколько endpoint'ов, которые не прошли верификацию по объявленным моделям[2].
Дело не только в мошенничестве. Провайдер может квантовать модель, чтобы сэкономить на обслуживании, развернуть тихую версию, или маршрутизировать трафик через смешанные бэкенды. Если качество твоего продукта зависит от конкретной модели, вопрос "что я на самом деле получаю?" должен иметь ответ на основе фактов, а не доверия.
Почему случайные числа выдают игру
Метод опирается на хорошо задокументированный дефект. Языковые модели не вычисляют — они предсказывают, поэтому при запросе случайного числа воспроизводят смещения своих данных обучения и настройки предпочтений[1].

Три кластера доминируют:
- 42 представлено непропорционально часто — ответ из «Справочника путешественника по Галактике», отзывающийся сквозь десятилетия интернет-текстов.
- 7 носит тысячелетия культурного веса как счастливое число, к которому тянутся люди.
- 37, 47, 73 и другие двузначные простые числа кажутся случайными людям, поэтому доминируют в человеком сгенерированных примерах «случайных» чисел, на которых обучалась модель.
Статья квантифицирует коллапс: медианное распределение ответов несёт примерно 1.0 бит энтропии, тогда как честный выбор от 1 до 100 нёс бы 6.64 бита[1]. Если честная кость имеет сто граней, большинство моделей ведут себя как слегка смещённая монета.
Ключевой момент в том, что дефект постоянен. Одна модель выдаёт одно и то же смещённое распределение каждый раз, а разные модели, включая сестринские версии в одном семействе, выдают измеримо разные. Баг становится сигнатурой.
Протокол в четыре шага
1. Зондирование. Задай endpoint батарею односложных вопросов: выбери случайное число от 1 до 100, назови случайный цвет, подбрось монету. Статья использует 10 заданий на 4 языках для 40 пробных единиц, дискретизируя каждую 30 раз при temperature 1.0, max_tokens=16 и отключённым reasoning[1].
2. Отпечаток. Для каждой пробной единицы составь ответы в эмпирическое распределение. Набор этих распределений — поведенческий отпечаток endpoint'а.
3. Сравни. Измерь расстояние между отпечатком и доверенной эталоном для объявленной модели, используя дивергенцию Jensen-Shannon по основанию 2, так что шкала идёт от 0 (идентично) к 1 (не пересекаются).
4. Решай. Малое расстояние означает согласованность с утверждением. Большое означает, что endpoint поведенчески совсем другой.
Две свойства делают это трудным для обхода. Не требует спецдоступа — всё, что отвечает на чат-дополнения, можно отпечатать. И нет магической строки для фильтрации, потому что каждое зондирование — обычный безвредный вопрос из пулов перефразировок, так что нечестный middlebox не может внести специальный случай без нарушения обычного трафика[1].
Чтение числа расстояния
Значение дивергенции ничего не значит без опорных точек, и здесь метод становится практичен.

| Сравнение | Типичное JSD |
|---|---|
| Одна модель против себя | ~0.14 |
| Одна модель, два разных провайдера | ~0.23 |
| Две разные модели | ~0.46 |
Между «одно и то же» и «разное» есть реальный просвет[1]. Заметь, что означает средняя строка: даже честное развёртывание одной модели другим хостом смещается измеримо, потому что квантование, стек развёртывания и скрытые системные промпты оставляют следы.
Точность масштабируется с числом проб. При 8 пробных единицах равнополовинная ошибка — 10.6%, при полных 40 — 7.3%, AUC = 0.971[1].
Что статья нашла в природе
Случай palmyra-x5. Самый поразительный результат статьи касается модели, предлагаемой как закрытый флагман, чей отпечаток находился на расстоянии JSD 0.141 от open-weight модели объёмом 235B, статистически неотличимо от ~0.140, который получается при сравнении модели с самой собой. Поведенчески, заключает статья, endpoint служил функционально эквивалентную open-source модель[1].
Одна модель, разные провайдеры, иногда подозрительно разные. Из 34 пар одной модели у разных провайдеров 10 отклонились за пределы 5-го процентиля распределения подделок[1]. Некоторые официальные развёртывания моделей сторонних разработчиков дрейфуют настолько, что выглядят как разные модели. Верификация — не параноя даже когда никто не врёт о названии.
Исследовательские артефакты открыты: датасет отпечатков опубликован под CC-BY-4.0, код воспроизведения под MIT, оба на Zenodo[3][4].
Запусти проверку сам
Протокол простой достаточный для прямой реализации. Его структура:
import collections, math
from openai import OpenAI
client = OpenAI(api_key="...", base_url="https://your-endpoint/v1")
def probe(model, prompt, n=25):
counts = collections.Counter()
for _ in range(n):
r = client.chat.completions.create(
model=model,
messages=[{"role": "user", "content": prompt}],
temperature=1.0,
max_tokens=16,
)
counts[r.choices[0].message.content.strip()] += 1
total = sum(counts.values())
return {k: v / total for k, v in counts.items()}
def jsd(p, q):
keys = set(p) | set(q)
m = {k: 0.5 * (p.get(k, 0) + q.get(k, 0)) for k in keys}
def kl(a):
return sum(a[k] * math.log2(a[k] / m[k]) for k in a if a[k] > 0)
return 0.5 * kl(p) + 0.5 * kl(q)Четыре практических совета для правильного выполнения.
Зафиксируй условия дискретизации. Temperature 1.0, маленький max_tokens, reasoning отключен. Отпечаток, собранный под другие настройки, несравним с собранным под статью.
Используй больше одного зондирования. Один вопрос шумный. Ошибка примерно вдвое уменьшается, переходя от 8 пробных единиц к 40.
Сравнивай с эталоном, собранным так же. Чистейший эталон — официальный endpoint для одной модели, отпечатанный в одной сессии под идентичными настройками, а не опубликованная таблица собранная месяцами ранее.
Смотри и вспомогательные сигналы. Отпечаток, не согласующийся сам с собой при разбиении на половины, намекает на мультибэкенд-маршрутизацию. Односложные ответы, биллящиеся сотнями completion-токенов, намекают на padding. Раздутые prompt-токены намекают на большой скрытый системный промпт.
Стандартная проверка из 8 пробных единиц при 25 выборках — это примерно 200 крошечных запросов, что стоит доли цента на малой модели.
Что результат значит и не значит
Будь точен в интерпретации, что поддерживает этот метод.
Несовпадение — признак, не доказательство. Метод имеет встроенную частоту ошибок, около 10.6% EER при 8 пробных единицах. Агрессивное квантование, тихое обновление модели, устаревший эталон или скрытый системный промпт сервера могут все сместить распределения без намерения обмана. Красный результат — причина для переделки с большим числом проб, теста второго эталона и вопросов[1].
Совпадение сильно, но не абсолютно. Утончённая подделка могла бы в принципе имитировать распределения другой модели, хотя проделать это на дюжинах перефразированных многоязычных зондирований при правильном обслуживании обычного трафика — сложнее, чем звучит.
Моделям с reasoning нужен уход. Отпечатки собираются с reasoning отключен. Где endpoint не может его отключить, уверенность падает.
Расстояние — свойство endpoint'а в момент времени, не приговор бизнесу.
FAQ
Что такое LLM fingerprinting?
Измерение распределения ответов модели на батарею односложных вопросов, потом сравнение этого распределения с эталоном для модели, которую endpoint говорит что служит[1].
Почему языковые модели не могут генерировать случайные числа?
Они предсказывают, не вычисляют, поэтому запрос на случайность возвращает смещения данных обучения и настройки предпочтений. Культурно значимые значения вроде 42 и 7 доминируют, коллапсируя распределение примерно к 1.0 биту энтропии против идеального равномерного 6.64[1].
Какое различие считается несовпадением?
Используй эталоны статьи вместо фиксированного порога: около 0.14 для модели против себя, 0.23 для одной модели между провайдерами, 0.46 для разных моделей[1].
Сколько запросов требует проверка?
Полный протокол статьи — 40 пробных единиц по 30 выборок каждая. Более лёгкая 8-единичная проверка при 25 выборках — примерно 200 запросов и поднимает равнополовинную ошибку с 7.3% до 10.6%[1].
Может ли провайдер обнаружить и обойти тест?
Нелегко. Зондирования — обычные безвредные вопросы из пулов перефразировок, так что внести специальный случай без нарушения обычного трафика трудно[1].
Означает ли провалившаяся проверка, что провайдер врёт?
Нет. Квантование, тихие обновления версий, скрытые системные промпты и устаревшие эталоны все производят дрейф без обмана. Расстояние — статистическое наблюдение, заслуживающее более пристального изучения.
Датасет доступен?
Да. Датасет отпечатков на Zenodo под CC-BY-4.0, код воспроизведения под MIT[3][4].
Отношение к полю model как к утверждению
Полезный сдвиг здесь маленький и специфичный. Поле model в ответе API — утверждение, и теперь есть дешёвый, открытый, статистически обоснованный способ проверить это утверждение снаружи, построенный на ничём более экзотичном, чем факт, что языковые модели не могут назвать случайное число в целях самосохранения.
Если ты покупаешь ёмкость через любого посредника, правильное место для этого — рядом с мониторингом аптайма: периодическая проверка против эталона, собранного тобой самим, со вспомогательными сигналами, наблюдаемыми рядом с дистанцией. И правильный способ прочитать красный результат — как начало разговора, не конец. Верифицировать LLM API — собирать свидетельства об endpoint'е в момент времени, что стоит делать ровно потому, что альтернатива — предположение.
Ссылки
- Bruckner, Tomáš. One Token Is Enough: Fingerprinting and Verifying Large Language Models from Single-Token Output Distributions. arXiv, July 2026. arxiv.org/abs/2607.10252
- CISPA researchers. Real Money, Fake Models — an audit of shadow LLM API operators. arXiv. arxiv.org/abs/2603.01919
- LLM fingerprint dataset (models × tasks × languages). Zenodo, CC-BY-4.0. zenodo.org
- Reproduction code for One Token Is Enough. Zenodo, MIT License. zenodo.org
Further reading
- reAPI. How to use Claude Opus 5. reapi.ai/blog/how-to-use-claude-opus-5
- reAPI. How to use GPT-5.6. reapi.ai/blog/how-to-use-gpt-5-6
Автор

Категории
Ещё статьи

Kimi K3 vs Claude Opus 5: открытые веса или API
Kimi K3 vs Claude Opus 5: сравниваем открытые веса, контекст 1M, рассуждение, мультимодальный ввод, цены API, требования к развёртыванию и выбор модели.


Цена API удаления фона: расчет за полезное изображение
Рассчитайте стоимость API удаления фона от текущей ставки 88 кредитов, добавьте отклоненные результаты, повторные попытки, хранение и проверку качества.


Опенсорс апскейлеры видео: video2x и Real-ESRGAN
Гайд по апскейлу видео: сравнение video2x и Real-ESRGAN, движки, поддержка Vulkan, AMD и Intel, анимационные модели, тайлинг для низкой памяти, лицензирование.
