Part 1: Your first check¶
In this part you install groundlens and run a single check against a source document. By the end you will be able to read a result and say, in plain language, what it means.
Install¶
That is the whole install. No API key, no GPU, no configuration.
The scenario¶
You asked a model a question and gave it a document to answer from. You have three strings: the question, the source you provided, and the answer the model returned. You want to know one thing: did the answer actually use the source, or did it drift back to the question and improvise?
That question, "did the answer engage its source", is what the Semantic Grounding Index (SGI) measures.
Run it¶
Create a file called check.py:
from groundlens import compute_sgi
question = "What does the water damage policy cover?"
source = (
"Coverage includes burst pipes and sudden appliance failure up to "
"$50,000. Flood damage requires a separate NFIP policy. "
"Deductible is $1,500 per occurrence."
)
answer = (
"The policy covers burst pipes and sudden appliance failure up to "
"$50,000 per occurrence, with a $1,500 deductible."
)
result = compute_sgi(question=question, context=source, response=answer)
print(f"score: {result.value:.3f}")
print(f"flagged: {result.flagged}")
print(f"to source: {result.ctx_dist:.3f}")
print(f"to question:{result.q_dist:.3f}")
Run it:
The first run downloads the embedding model. After that it is instant. You will see a score comfortably above 1.0 and flagged: False. The answer sits closer to the source than to the question, which is what a grounded answer does.
Read the result¶
compute_sgi returns an SGIResult. The fields you will use most:
valueis the raw score:distance(answer, question) / distance(answer, source). Above 1.0 means the answer moved toward the source.flaggedis the library's own call on whether this needs a human. It isTruewhen the score falls into the review or risk band.ctx_distandq_distare the two distances the ratio is built from, exposed so you can see the geometry, not just the verdict.
The thresholds behind flagged:
| SGI value | Meaning |
|---|---|
| above 1.20 | Strong engagement with the source. Pass. |
| 0.95 to 1.20 | Partial. Some source influence, not decisive. Review. |
| below 0.95 | Weak. The answer may have ignored the source. Flag. |
Turn the number into words¶
The raw score is for pipelines. For something a person can act on, pass the result to check():
from groundlens import compute_sgi, check
result = compute_sgi(question=question, context=source, response=answer)
verdict = check(result)
print(verdict.render())
check() returns a Check with a plain label ("Supported by the document"), a one-line message, a level (ok, review, or risk), and two fields you will rely on in Part 3: escalate and handoff. render() prints all of it, including the handoff line.
This check() function is the single source of truth for wording across the whole project. The README, the MCP servers, and the hosted API all render from it, so what you read here is exactly what your users will read.
What you have¶
You ran a deterministic grounding check and read it two ways: as a number for code, and as a sentence for a person. Run it again. The score is identical, every time, on any machine. That determinism is the property the whole design rests on.
There is a question you should be asking: what happens when the answer is drawn from the source but a fact inside it is wrong? That is Part 2, and it is the most important part of this tutorial.