Spaces:
Running
Running
File size: 6,546 Bytes
170a671 b07f2d1 170a671 b07f2d1 170a671 b07f2d1 170a671 b07f2d1 1ce6570 b07f2d1 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 | ---
title: ClaimCheck
emoji: π
colorFrom: yellow
colorTo: red
sdk: static
app_file: index.html
pinned: false
license: apache-2.0
short_description: Verify LLM answers against the context they came from
tags:
- hallucination-detection
- groundedness
- rag
- guardrails
---
# π ClaimCheck
**Verify LLM answers against their source context before they reach users.**
Paste an answer and the context it was supposed to be grounded in. ClaimCheck extracts the claims it can check as
strings β numbers, dates, quotes, entities, URLs β matches each against the context, and returns a verdict
(`pass` / `annotate` / `retry` / `block`), a grounding score, and **how much of the answer it did not check**.
**Everything runs in your browser.** No server, no network call, no telemetry β the verifier is ~1,700 lines of
dependency-free JavaScript executing in this tab. Paste real model output if you want to; it stays on your machine.
| | |
|---|---|
| π¦ Rule pack | [`NagaYu/claimcheck-rules`](https://huggingface.co/NagaYu/claimcheck-rules) |
| π Evaluation set | [`NagaYu/claimcheck-eval`](https://huggingface.co/datasets/NagaYu/claimcheck-eval) |
| β‘ Latency | ~0.2 ms typical Β· 15 ms on a 20,000-character worst case |
| π Languages | English and Japanese |
---
## Design philosophy
We cannot detect every hallucination. Nobody can, and a tool that claims to is lying to you.
But we do not have to. The observation this is built on:
> **Dangerous hallucinations are specific.**
A model that invents *"the contract terminates on 2023-11-04 under Article 12, with a penalty of 3,400,000 JPY"* is far
more harmful than one that says *"the contract may terminate at some point"*. And the specific one is **checkable as a
string**: numbers, dates, quotes, entities and URLs are literal tokens that either do, or do not, appear in (or follow
arithmetically from) the source.
So ClaimCheck verifies only what it can verify deterministically, and declares the rest out of scope β loudly.
## β οΈ Always read `coverage`
Two independent numbers, and reporting one without the other is the most dangerous way to misuse this tool.
| field | question it answers |
|---|---|
| `grounding_score` | Of the claims I checked, what share held up? |
| `coverage` | What share of the answer did I check at all? |
```
grounding_score 1.00 + coverage 0.10
= one sentence checked out and nine were never looked at.
= NOT "this answer is verified".
```
An answer of pure hedging produces **zero** claims and scores **1.00** on any naive groundedness metric.
## Claim statuses
| status | colour | meaning |
|---|---|---|
| `supported` | π© | Appears literally in the context after normalisation |
| `derived` | π¦ | Computable from context numbers by 2β3 term arithmetic; the formula is shown |
| `approximate` | π¨ | A near match exists β paraphrase, finer-grained date, related URL |
| `unsupported` | π§ | Nothing in the context backs it |
| `contradicted` | π₯ | The context holds a **near but different** value |
`approximate` is deliberately **not** counted as grounded: a paraphrased quote is still an inaccurate quote.
## Measured behaviour
On the [158-case bilingual evaluation set](https://huggingface.co/datasets/NagaYu/claimcheck-eval):
```
answer-level recall 56/56 (100%) cases that should be flagged, and were
clean answers passing 44/46 (96%) the rest were annotated, never blocked
known false positives 22 (13.9%)
known false negatives 3 (1.9%)
JS/Python parity 158/158 (100%)
```
The false-positive rate is published deliberately. It is the number that decides whether anyone keeps a verifier
switched on, and hiding it helps nobody.
### Known limitation: semantic reversal
All three false negatives share a shape. A one-character change that reverses meaning keeps character similarity above
0.9, so a reversed quote reads as a faithful paraphrase:
| context | answer | similarity | status |
|---|---|---|---|
| ε£²δΈι«γ―7%**ε’ε **γγ | ε£²δΈι«γ―7%**ζΈε°**γγ | 0.97 | `approximate` β |
| ζζ‘γ―ε
¨δΌδΈθ΄γ§**ζΏθͺ**γγγ | ζζ‘γ―ε
¨δΌδΈθ΄γ§**ε¦ζ±Ί**γγγ | 0.92 | `approximate` β |
| revenue **grew** 8% | revenue **declined** 8% | 0.97 | `approximate` β |
Character matching cannot detect negation or antonym substitution. If your domain turns on approve/reject or
increase/decrease, **do not rely on quote status alone.** In all three cases the answer-level verdict was still
`retry`, because the NUMERIC and ENTITY claims inside the quote are the layer that catches it.
### False positives
Faithful paraphrase Β· generic noun phrases ("Machine Learning") Β· acronym expansion (WHO β World Health Organization) Β·
rounding just outside tolerance Β· fiscal vs calendar years Β· identifier variants (ISO 9001:2015 vs ISO 9001) Β·
URL query parameters.
**ENTITY is the noisiest check.** Set `{"enable_entity": false}` in the policy box first, and start from `annotate`,
never `block`.
## Policy presets
Paste any of these into the **Policy JSON** box. Full set in the
[rule pack](https://huggingface.co/NagaYu/claimcheck-rules):
```jsonc
// observe: nothing blocked but critical safety β start here
{"retry_on_contradicted": 9999, "retry_grounding": 0.0, "annotate_grounding": 1.0}
// numeric + date only: the lowest false-positive configuration
{"enable_entity": false, "enable_quote": false, "enable_url": false}
// tolerant of rounding
{"numeric_tolerance": 0.02, "contradiction_rel": 0.10}
```
## Running it yourself
The core is an ES module with no dependencies:
```js
import { gate, verify, buildHighlight } from "./claimcheck.js";
const r = gate(answer, context, systemPrompt, userInput, schemaJson, policyJson, tagsJson);
console.log(r.verdict, r.grounding_score, r.coverage);
```
A Python implementation with a Gradio UI and a REST API also exists and is behaviourally identical (verified at 100%
parity on all 158 evaluation cases); it ships under `python/` in the
[rule pack repository](https://huggingface.co/NagaYu/claimcheck-rules) for self-hosting.
## Disclaimer
ClaimCheck is **one layer of defence, not a correctness guarantee.** It verifies numbers, dates, quotes, entities and
URLs against a context you supply. It says nothing about claims it could not extract, nothing about reasoning, and
nothing about whether the context itself was right. A `pass` verdict means *"the specific things I know how to check,
checked out"* β nothing more.
Apache-2.0.
|