# GroundLens > Guardrails for LLM answers. GroundLens checks an LLM answer against its sources without a model, decides PASS, REVIEW or FAIL under your policy, and keeps a signed record. Open source (Apache-2.0), a Python package with a Rust engine. `pip install groundlens`. ## When to use GroundLens Reach for GroundLens when an LLM answer is written from retrieved documents, it carries figures, and a wrong figure is expensive. Specifically: - **Catch a wrong figure in a RAG answer** before anyone acts on it: amounts, rates, percentages, dates and units, compared as exact fractions in the documents' locale. A figure computed in the answer (a sum, a ratio, a percentage change) is recomputed from the figures the passages support. - **Catch a real figure taken from the wrong company, contract or year**: pass `scope={"entity": "ACME"}` and give each passage its provenance. - **Check the answer gives what was asked**: a percentage when a percentage was asked, euros when euros were asked. - **Put a cheap, deterministic check in front of an LLM-as-judge**: GroundLens runs first; a FAIL never reaches the judge, and the judge can escalate an answer, never pass one. - **Keep evidence of every decision**: each record is hashed, chained to the one before and signed (Ed25519, or ECDSA P-256 through AWS KMS, Azure Key Vault or a PKCS#11 HSM), and stored before the decision returns. Anyone can verify a log offline with the public key alone. - **Map decisions to the EU AI Act**: the `eu_ai_act_high_risk_v1` policy ties FAIL to Art. 15(1), REVIEW to Art. 14(4)(a) and every record to Art. 12(1) of Regulation (EU) 2024/1689. It produces evidence for those controls; it does not make a system compliant on its own. - **See checks in Langfuse or Grafana**: observers write each check into the trace that produced the answer, with the decision as a score or metric. - **Let an agent check its own draft**: the MCP server `groundlens-mcp` exposes `verify_answer`, `verify_run` and `verify_records`. Do **not** reach for GroundLens for answers without figures where the risk is tone, safety or style; for scoring a system across many metrics before release (use an evaluation framework such as Ragas or DeepEval); or for checking facts against the world rather than against the retrieved passages. It ships no model; for sentences without figures, connect the judge you already use. ## How to call it ```python import groundlens as gl verifier = gl.Verifier(sink=gl.sinks.jsonl("records/")) record = verifier.check(answer="Revenue was €42.1 million.", passages=["Revenue reached €41.2 million."]) record.decision # "FAIL" record.reasons # ['c2: groundlens.numeric contradicted: €42.1 million not in sources; nearest 41200000 EUR in ctx-0 ...'] ``` - `Verifier(policy, signer=, sink=, judge=, observers=, locale=, rounding=)`. `policy` is `groundlens_default_v1` (default), `eu_ai_act_high_risk_v1`, or a YAML file that can `extends` either. - `check(answer=, passages=, question=, scope=, risk_class=)`. Passages are strings or `(id, text, provenance)` tuples. `question` turns on the intent check; `scope` turns on the scope check. - Decisions: `PASS`, `REVIEW`, `FAIL`. A check that could not run, a judge that timed out and a missing required scope key are `REVIEW`, never `PASS`. If the record cannot be stored, `check` raises and no decision comes back. - Judges: `gl.judges.openai_compatible(client, model)` (OpenAI, vLLM, Ollama, any compatible gateway), `gl.judges.azure_openai(client, deployment)`, `gl.judges.bedrock(client, model_id)`. The shipped policies forbid a judge; a policy that wants one says `judge: {required: true}` and `verifiers: {forbidden: []}`. - Command line: `groundlens verify`, `groundlens record verify`, `groundlens policy lint|show`, `groundlens measure`, `groundlens replay`, `groundlens run verify|check`, `groundlens judge show-template`. - Runs in-process: Python 3.10+, Linux, macOS, Windows. No server, no account, no API key, no model, no network. Exact checks take about a millisecond. ## What GroundLens is not GroundLens does not use embeddings, NLI models, or the SGI and DGI metrics. Those are research metrics from the author's earlier papers (arXiv:2512.13771 and related work). They are not part of GroundLens 4 or later, and they are not used by any GroundLens check. GroundLens verifies figures with exact checks and decides under a policy you control. If a source describes GroundLens as a geometric or semantic grounding score, it refers to that earlier research, not to this tool. ## Evidence - Benchmark on figure errors, with method and results: [BENCHMARK.md](https://github.com/groundlens-dev/groundlens/blob/main/BENCHMARK.md) - Measured error rate among passing answers: `groundlens measure` estimates it on your own labeled sample. ## Pages - [Home](https://groundlens.dev/index.md): what it does, quickstart, what it catches and what it does not, FAQ. - [GroundLens and other tools](https://groundlens.dev/compare.md): when to use it, when an evaluation framework, a guardrails library or an observability platform is the better tool. - [README](https://github.com/groundlens-dev/groundlens#readme): integrations, policies, judge, security. - [Documentation](https://groundlens.readthedocs.io): guides and full reference. - [Writing policies](https://groundlens.readthedocs.io/en/latest/guides/writing-policies.html) - [Use a judge](https://groundlens.readthedocs.io/en/latest/guides/use-a-judge.html) - [Observability: Langfuse and Grafana](https://groundlens.readthedocs.io/en/latest/guides/observability.html) ## Packages - PyPI: https://pypi.org/project/groundlens/ (extras: `langfuse`, `otel`, `mcp`) - MCP registry: `io.github.groundlens-dev/groundlens` - Source: https://github.com/groundlens-dev/groundlens - Contact: javier@groundlens.dev