
Уникальный инструмент для фингерпринтинга больших языковых моделей на основе их токенизаторов и поведения.

Снимает отпечаток серверного стека за OpenAI-совместимой чат-конечной точкой.
Он записывает учёт токенизатора, скрытое смещение шаблона, текст валидатора, форму JSON/SSE, принимаемые роли, именованные лимиты и заголовки шлюза. Он не загружает веса, не хранит API-ключи и не спрашивает модель, кто она.
| Импорт | lm_fingerprint |
| CLI | lm-fingerprint |
| Что это | Версионированные инфраструктурные пробы к /chat/completions. Офлайн-синтетическая библиотека. Локальная проверка токенизатора Hugging Face (без весов). |
| Что это не | Не градиентная атака. Не джейлбрейк. Не идентификация encode-map (tokprint). Не «какой бинарник на этом порту» (Julius). |
Только санкционированное использование: конечные точки, которыми вы владеете, лаборатории под вашим контролем, программы bug bounty в области действия, письменные пентесты. См. SECURITY.md.
--api-key-envзадаёт имя переменной окружения. Ключ никогда не логируется.
OpenAI-совместимый чат — это распространённый протокол. vLLM, SGLang, лабораторный шлюз и
реселлер — все могут говорить на /chat/completions. Поле model — это ярлык.
Хост может поменять бэкенд, обернуть токенизатор или поставить роутер
спереди. Личностные пробы смещаются, когда смещается системный промпт.
Что остаётся на месте — это инфраструктура: как сервер считает токены, сколько скрытых
токенов шаблона он добавляет, текст, написанный его валидатором, диалект SSE,
какие роли он принимает, какое число называет при абсурдном max_tokens,
заголовки Server / провайдера.
Именно на этот вопрос отвечает инструмент: какой стек обслуживает этот чат-путь? Не какой чекпоинт, не какой процесс привязан к порту, не кто написал завершение.
ModelPrint задал тот же вопрос в браузере с девятью пробами. Этот пакет — форма в виде CLI и библиотеки: версионированные пробы, пополняемая библиотека, попарные свидетельства, дрейф и локальный путь токенизатора, который никогда не вызывает хостингованное Inference API.
Отпечаток — это версионированная JSON-запись значений проб (value). Каждая проба
должна возвращать одно и то же значение при двукратном обращении к одному и тому же стеку. Временные метки,
идентификаторы запросов, задержки и ключи удаляются.
Счётчики токенизатора переиспользуют тексты ModelPrint 1.0.0 (MIT, unclecode/modelprint),
побайтово точно, за вычетом односимвольной базовой линии "a", чтобы скрытый шаблон
компенсировался. Эти четыре числа — проекция encode-map (T).
Равенство счётчиков не означает (T_1 \equiv T_2). GPT-2 и OPT совпадают по
ним; хеш rust-pipeline — нет.
hf_identity (только локальный путь HF) — это SHA-256 от обязательства этого пайплайна
плюс хеш chat-template. Та же (T) и тот же шаблон совпадают
(tiny-gpt2 / gpt2). Это семейство + шаблон, а не чекпоинт.
Структура:
src/lm_fingerprint/
cli.py argparse. --api-key-env only. No --api-key.
client.py HttpTransport, InProcessTransport, redact_secrets
probes.py 23 ProbeSpec rows (tokenizer / errors / shape / roles / limits / proxy)
engine.py run suite → Fingerprint
schema.py schema_version=1, probe_suite_version=lm-fingerprint-probes-v1
similarity.py weighted exact-match, coverage, confidence, library rank, drift
library.py enroll / match. Packaged rows are synthetic fixtures
synthetic.py in-process stacks for tests and the shipped library
hf.py local AutoTokenizer + named validation profile. No weights
localmap.py encode-pipeline-v2 commitment (rust tokenizer.json)
proof.py measured ModelPrint 9-probe identity
report.py text reports
data/library.json
Два пути в один и тот же набор проб:
live endpoint local Hub tokenizer (optional [hf])
| |
HttpTransport.chat HfChatTransport
POST /chat/completions encode / chat_template for counts
| synthetic profile for errors/shape
+------------------+----------------------+
|
engine.run_probes
|
Fingerprint (JSON, keyless)
|
compare | match | drift | enroll
Создание проб: docs/PROBES.md. Карта модулей: docs/ARCHITECTURE.md.
Совпадение означает общую инфраструктуру. Одна лаборатория может обслуживать два чекпоинта на одном стеке. Роутер может отвечать собственной обёрткой ошибок. Совпадение счётчиков — это не тождественность (T).
Python 3.10+. Основной рантайм — стандартная библиотека.
git clone https://gitlab.com/WattoCyber/lm-fingerprint.git
cd lm-fingerprint
pip install -e ".[dev]"
PYTHONPATH=src python3 scripts/repro.py
Ожидайте REPRO_OK. Этот гейт офлайн: без GPU, без продакшн-API.
Локальные HF-тесты пропускаются, если токенизатор не кэширован.
pip install -e ".[hf]" # transformers, for fingerprint-hf / verify-hf
lm-fingerprint list-probes
lm-fingerprint list
list выводит встроенные стеки: openai-chat-strict, glm-compat,
router-openai, permissive-compat. Это фикстуры, а не собранные скрейпингом
провайдеры. Сравните два из них без сети:
from lm_fingerprint.client import InProcessTransport
from lm_fingerprint.engine import fingerprint_endpoint
from lm_fingerprint.similarity import compare_fingerprints
from lm_fingerprint.synthetic import SYNTHETIC_STACKS, handler_for
def fp(stack_id):
t = InProcessTransport(handler_for(stack_id), headers=SYNTHETIC_STACKS[stack_id].headers)
return fingerprint_endpoint(t, model=f"synthetic/{stack_id}", base_url=f"inprocess://{stack_id}")
print(compare_fingerprints(fp("openai-chat-strict"), fp("router-openai"))["note"])
Тот же токенизатор слов, разные ошибки и заголовки. Оценка составляет около
0.58. Четыре счётчика ModelPrint совпадают; этот инструмент не называет это
общим стеком.
lm-fingerprint fingerprint \
--base-url https://your-lab.example/v1 \
--model the-label \
--api-key-env OPENAI_API_KEY \
--out lab.json
lm-fingerprint match --fingerprint lab.json
lm-fingerprint enroll --fingerprint lab.json --stack-id my-lab --library my-lib.json
Не передавайте ключ в командной строке. Не скрейпьте продакшн-API, чтобы заполнить публичную библиотеку.
lm-fingerprint fingerprint-hf --model sshleifer/tiny-gpt2 --local-files-only
lm-fingerprint verify-hf --local-files-only
Счётчики берутся из apply_chat_template, когда шаблон существует, иначе —
encode(..., add_special_tokens=False). Таксономия ошибок берётся из
именованного синтетического профиля (по умолчанию openai-chat-strict), чтобы запуск оставался
офлайн. Удалённые дескрипторы (https://, api://, …) отклоняются.
lm-fingerprint list-probes
lm-fingerprint list [--library PATH]
lm-fingerprint fingerprint --base-url URL --model MODEL --api-key-env VAR [--out PATH]
lm-fingerprint fingerprint-hf --model HANDLE [--profile NAME] [--local-files-only]
lm-fingerprint verify-hf [--models a,b,c] [--local-files-only]
lm-fingerprint prove [--local-files-only]
lm-fingerprint compare --a a.json --b b.json
lm-fingerprint match --fingerprint a.json [--library PATH]
lm-fingerprint drift --baseline old.json --current new.json
lm-fingerprint enroll --fingerprint a.json --stack-id ID --library PATH
lm-fingerprint export --fingerprint a.json
Флага --api-key нет. Более старые JSON
wireprint-fingerprint / stackprint-fingerprint по-прежнему загружаются.
from lm_fingerprint import (
StackLibrary,
compare_fingerprints,
fingerprint_endpoint,
fingerprint_hf,
match_library,
)
from lm_fingerprint.client import HttpTransport
fp = fingerprint_endpoint(HttpTransport(url, api_key=key), model="x", base_url=url)
hit = match_library(fp, StackLibrary.load())
local = fingerprint_hf("sshleifer/tiny-gpt2", local_files_only=True)
schema_version = 1, probe_suite_version = lm-fingerprint-probes-v1.
Сравнение: взвешенное точное совпадение по пробам, которые ok и stable с
обеих сторон. Уверенность — это score × coverage. Совпадение по библиотеке возвращает
certainty (exact / strong / possible / unknown) и запас
до второго соседа.
Перезапустите:
lm-fingerprint prove --local-files-only
Тот же остаток, что и у ModelPrint
(девять проб в probes/index.js). Их README — это правило оценки:
совпадающие отпечатки доказывают общую инфраструктуру, а не идентичность.
Подробный разбор: docs/PROOF.md.
fingerprint-hf никогда не загружает веса и никогда не вызывает хостингованное Inference.--api-key-env. Артефакты не должны содержать sk- или
Authorization.scripts/repro.py — это гейт продукта. Не заявляйте о «зелёном» статусе, если вы
не запустили его только что.MIT. См. LICENSE. Тексты токенизатора ModelPrint остаются MIT (unclecode/modelprint) и побайтово точными.
| Что у вас есть | Что вы можете наблюдать | Что делает этот инструмент |
|---|
| Санкционированный OpenAI-совместимый base URL + ключ | Чат-HTTP: потребление, ошибки, заголовки, SSE | fingerprint / compare / match / drift |
| Локальные файлы токенизатора | encode и chat_template | fingerprint-hf / verify-hf. Веса остаются на диске |
| Ничего, кроме host:port | Баннер / /health / /api/tags | Вне области действия. Используйте Julius |
| Поле | Значение |
|---|
kind | lm-fingerprint |
target.model / target.base_url_host | На что указывали. Только хост; без ключа |
features.tokenizer_norm | Четыре счётчика класса ModelPrint (english, chinese, code, emoji) |
features.template_offset | Размер скрытого serving-шаблона |
probes.<id>.value | Сопоставимая ячейка. Должна быть стабильной |
probes.<id>.weight | Вклад в сходство |
keys_stored | Всегда false |
weights_loaded | Всегда false |
| Тест | ModelPrint | Этот инструмент |
|---|
Одинаковый токенизатор, другой стек (openai-chat-strict vs router-openai) | токенизатор 4/4 + совпадение шаблона | оценка 0.58, помечено как общий учёт |
gpt2 vs facebook/opt-125m | четыре счётчика и шаблон совпадают | encode_commitment разделяет |
| Qwen2 / 2.5 / 3 | токенизатор 4/4 совпадает; шаблон разделяет | hf_identity разделяет |
tiny-gpt2 vs gpt2 | совпадение (та же (T)) | совпадение (обязательно) |
| Набор проб | 9 | 23 + HF-обязательства encode/шаблона |
logprobs, форма потока, системная роль | указаны как идеи | реализованы |
| Инструмент | Назначение |
|---|
| ModelPrint | Тот же остаток, браузер, девять проб |
| tokprint | Локальный идентификатор семейства encode-map. Расположен в gradient-untangler |
| gradient-untangler | Градиенты через локальные веса |
| Julius | Какое серверное ПО находится на порту |
| TokenPrint / LLMmap / UTF | Сгенерированный текст, происхождение или имплантированные токены |