
Ferramenta única para fingerprinting de Grandes Modelos de Linguagem com base em seus tokenizadores e comportamento.

Cria a impressão digital da stack de serviço por trás de um endpoint de chat compatível com OpenAI.
Ela registra a contabilidade do tokenizer, o deslocamento oculto do template, o texto de validação, o formato JSON/SSE, a aceitação de papéis, os limites nomeados e os cabeçalhos de gateway. Não carrega pesos, não armazena chaves de API e não pergunta ao modelo quem ele é.
| Importação | lm_fingerprint |
| CLI | lm-fingerprint |
| O que é | Sondas de infraestrutura versionadas contra /chat/completions. Biblioteca sintética offline. Verificação local de tokenizer Hugging Face (sem pesos). |
| O que não é | Não é um ataque de gradiente. Não é um jailbreak. Não é identidade de mapa de codificação (tokprint). Não é “qual binário está nesta porta” (Julius). |
Uso autorizado apenas: endpoints que você possui, laboratórios que você controla, programas de bug bounty no escopo, testes de penetração com autorização por escrito. Consulte SECURITY.md.
--api-key-envnomeia uma variável de ambiente. A chave nunca é registrada em log.
Chat compatível com OpenAI é um protocolo comum. vLLM, SGLang, um gateway de laboratório e um
revendedor podem todos falar /chat/completions. O campo model é um rótulo.
O host pode trocar o backend, envolver o tokenizer ou colocar um roteador na
frente. Sondas de personalidade mudam quando o prompt do sistema muda.
O que permanece é o encanamento: como o servidor conta tokens, quantos tokens
ocultos de template ele adiciona, o texto que seu validador escreveu, o dialeto SSE,
quais papéis ele aceita, o número que ele informa quando max_tokens é absurdo,
os cabeçalhos Server / do provedor.
Essa é a pergunta que esta ferramenta responde: qual stack está lidando com este caminho de chat? Não qual checkpoint, não qual processo está vinculado à porta, não quem escreveu uma conclusão.
ModelPrint fez a mesma pergunta em um navegador com nove sondas. Este pacote é a forma CLI e biblioteca: sondas versionadas, biblioteca registrável, evidência pareada, derivação e um caminho de tokenizer local que nunca chama uma Inference API hospedada.
Um fingerprint é um registro JSON versionado dos values das sondas. Cada sonda
deve retornar o mesmo valor quando a mesma stack é atingida duas vezes. Carimbos de tempo,
ids de requisição, latência e chaves são removidos.
As contagens do tokenizer reutilizam os textos do ModelPrint 1.0.0 (MIT, unclecode/modelprint),
byte-exato, menos uma linha de base de um caractere "a" para que um template
oculto seja cancelado. Esses quatro números são uma projeção do mapa de codificação (T).
Contagens iguais não significam (T_1 \equiv T_2). GPT-2 e OPT colidem neles;
o hash do pipeline rust não colide.
hf_identity (apenas no caminho HF local) é SHA-256 do compromisso desse pipeline
mais o hash do chat-template. Mesmo (T) e o mesmo template correspondem
(tiny-gpt2 / gpt2). Isso é família + template, não um checkpoint.
Layout:
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
Dois caminhos para a mesma suíte de sondas:
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
Criação de sondas: docs/PROBES.md. Mapa de módulos: docs/ARCHITECTURE.md.
Uma correspondência é infraestrutura compartilhada. Um laboratório pode servir dois checkpoints em uma única stack. Um roteador pode responder com seu próprio invólucro de erro. A concordância de contagens não é identidade de (T).
Python 3.10+. O runtime principal é a biblioteca padrão.
git clone https://gitlab.com/WattoCyber/lm-fingerprint.git
cd lm-fingerprint
pip install -e ".[dev]"
PYTHONPATH=src python3 scripts/repro.py
Espere REPRO_OK. Esse gate é offline: sem GPU, sem APIs de produção.
Os testes HF locais são pulados se o tokenizer não estiver em cache.
pip install -e ".[hf]" # transformers, for fingerprint-hf / verify-hf
lm-fingerprint list-probes
lm-fingerprint list
list imprime as stacks empacotadas: openai-chat-strict, glm-compat,
router-openai, permissive-compat. Elas são fixtures, não provedores
obtidos via scraping. Compare duas delas sem rede:
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"])
Mesmo tokenizer de palavras, erros e cabeçalhos diferentes. A pontuação fica em torno de
0.58. As quatro contagens do ModelPrint correspondem; esta ferramenta não considera isso uma
stack compartilhada.
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
Não passe a chave na linha de comando. Não faça scraping de APIs de produção para preencher uma biblioteca pública.
lm-fingerprint fingerprint-hf --model sshleifer/tiny-gpt2 --local-files-only
lm-fingerprint verify-hf --local-files-only
As contagens vêm de apply_chat_template quando existe um template, caso contrário
de encode(..., add_special_tokens=False). A taxonomia de erros vem de um
perfil sintético nomeado (padrão openai-chat-strict) para que a execução permaneça
offline. Handles remotos (https://, api://, …) são rejeitados.
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
Não existe a flag --api-key. JSONs mais antigos de wireprint-fingerprint /
stackprint-fingerprint ainda são carregados.
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.
Comparação: correspondência exata ponderada nas sondas que estão ok e stable em
ambos os lados. A confiança é score × coverage. A correspondência na biblioteca relata
certainty (exact / strong / possible / unknown) e a margem
para o segundo vizinho.
Execute novamente:
lm-fingerprint prove --local-files-only
Mesmos vestígios do ModelPrint
(nove sondas em probes/index.js). O README deles é a regra de pontuação:
fingerprints correspondentes provam infraestrutura compartilhada, não identidade.
Relatório: docs/PROOF.md.
fingerprint-hf nunca carrega pesos e nunca chama inferência hospedada.--api-key-env. Os artefatos não devem conter sk- ou
Authorization.scripts/repro.py é o gate do produto. Não afirme que está verde a menos que você
acabou de executá-lo.MIT. Consulte LICENSE. Os textos do tokenizer do ModelPrint permanecem MIT (unclecode/modelprint) e byte-exatos.
| Você possui | O que você pode observar | O que esta ferramenta faz |
|---|
| Uma URL base OpenAI-compat autorizada + chave | Chat HTTP: uso, erros, cabeçalhos, SSE | fingerprint / compare / match / drift |
| Arquivos de tokenizer locais | encode e chat_template | fingerprint-hf / verify-hf. Os pesos permanecem no disco |
| Nada além de um host:porta | Banner / /health / /api/tags | Fora do escopo. Use Julius |
| Campo | Significado |
|---|
kind | lm-fingerprint |
target.model / target.base_url_host | O que foi apontado. Apenas host; sem chave |
features.tokenizer_norm | Quatro contagens da classe ModelPrint (inglês, chinês, código, emoji) |
features.template_offset | Tamanho oculto do template de serviço |
probes.<id>.value | Célula comparável. Deve ser estável |
probes.<id>.weight | Contribuição para a similaridade |
keys_stored | Sempre false |
weights_loaded | Sempre false |
| Teste | ModelPrint | Esta ferramenta |
|---|
Mesmo tokenizer, stack diferente (openai-chat-strict vs router-openai) | tokenizer 4/4 + correspondência de template | score 0.58, rotulado como contabilidade compartilhada |
gpt2 vs facebook/opt-125m | quatro contagens e template colidem | encode_commitment separa |
| Qwen2 / 2.5 / 3 | tokenizer 4/4 colide; template separa | hf_identity separa |
tiny-gpt2 vs gpt2 | corresponde (mesmo (T)) | corresponde (obrigatório) |
| Conjunto de sondas | 9 | 23 + compromissos de encode/template HF |
logprobs, formato do stream, papel de sistema | listados como ideias | implementados |
| Ferramenta | Objeto |
|---|
| ModelPrint | Mesmos vestígios, navegador, nove sondas |
| tokprint | ID de família do mapa de encode local. Vive em gradient-untangler |
| gradient-untangler | Gradientes através de pesos locais |
| Julius | Qual software de servidor está em uma porta |
| TokenPrint / LLMmap / UTF | Texto gerado, linhagem ou tokens implantados |