feat: initial release of llm-fingerprint-detector
TypeScript library + CLI implementing single-token behavioral fingerprinting of LLMs behind OpenAI-compatible APIs, per 'One Token Is Enough' (Bruckner, arXiv:2607.10252). - Zero runtime dependencies (Node >= 18.17 built-in fetch) - fingerprint / compare / verify API + llm-fingerprint CLI - Jensen-Shannon divergence over per-cell answer distributions - Reasoning-model aware (auto-disables hidden thinking channels) - Bundled sample references for 11 popular models (CC-BY-4.0, derived from the paper's public Zenodo dataset) - Unit + integration tests via node --test Co-authored-by: Cursor <[email protected]>
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
import assert from 'node:assert/strict'
|
||||
import { test } from 'node:test'
|
||||
|
||||
import {
|
||||
JSD_MATCH_THRESHOLD,
|
||||
JSD_MISMATCH_THRESHOLD,
|
||||
MIN_COMPARABLE_CELLS,
|
||||
} from '../dist/constants.js'
|
||||
import { buildComparisonResult, decideVerdict } from '../dist/verdict.js'
|
||||
|
||||
test('verdict thresholds: match / uncertain / mismatch bands', () => {
|
||||
const cells = MIN_COMPARABLE_CELLS
|
||||
assert.equal(decideVerdict(0.0, cells), 'match')
|
||||
assert.equal(decideVerdict(JSD_MATCH_THRESHOLD, cells), 'match')
|
||||
assert.equal(decideVerdict(JSD_MATCH_THRESHOLD + 1e-9, cells), 'uncertain')
|
||||
assert.equal(decideVerdict(JSD_MISMATCH_THRESHOLD, cells), 'uncertain')
|
||||
assert.equal(decideVerdict(JSD_MISMATCH_THRESHOLD + 1e-9, cells), 'mismatch')
|
||||
assert.equal(decideVerdict(0.9, cells), 'mismatch')
|
||||
})
|
||||
|
||||
test('verdict: too few comparable cells → insufficient', () => {
|
||||
assert.equal(decideVerdict(0.1, MIN_COMPARABLE_CELLS - 1), 'insufficient')
|
||||
assert.equal(decideVerdict(null, 10), 'insufficient')
|
||||
})
|
||||
|
||||
test('buildComparisonResult carries thresholds, baselines and per-cell details', () => {
|
||||
const entries = [
|
||||
{ cellId: 'random-number-1-100:en', jsd: 0.5, validA: 25, validB: 30 },
|
||||
{ cellId: 'random-color:en', jsd: 0.1, validA: 25, validB: 30 },
|
||||
{ cellId: 'coin-flip:en', jsd: 0.2, validA: 25, validB: 30 },
|
||||
{ cellId: 'random-animal:en', jsd: 0.2, validA: 25, validB: 30 },
|
||||
]
|
||||
const result = buildComparisonResult(entries, 0.25, false)
|
||||
assert.equal(result.verdict, 'match')
|
||||
assert.equal(result.comparableCellCount, 4)
|
||||
assert.equal(result.cells.length, 4)
|
||||
assert.equal(result.protocolMismatch, false)
|
||||
assert.equal(result.thresholds.match, JSD_MATCH_THRESHOLD)
|
||||
assert.equal(result.baselines.differentModel, 0.463)
|
||||
})
|
||||
Reference in New Issue
Block a user