Deterministic correction for AI-generated numbers in the browser, in your backend, in your terminal.
Live Demo Β β’Β Docs Β β’Β Paper Β β’Β Model Β β’Β Discussions
Ecosystem Β· Extension Β· SDK Β· Benchmark Β· Features Β· Architecture Β· Pipeline Β· Core Components Β· Quick Start Β· Results Β· Research Β· Contributing
| π Deterministic | π§Ύ Auditable | π± Open Source |
|---|---|---|
| Rule-based correction, not another model guess | Every correction logged β rule, input, output | Apache 2.0, actively developed, open to contributors |
FinVerify isn't a single backend anymore it's a monorepo of interoperable components that all share the same verification core (the DVL). Start here, then go deeper via each component's own README.
| Component | What it does |
|---|---|
| π§© finverify-extension | Chrome extension providing inline financial verification inside AI chat UIs |
| π₯ finverify-terminal | Backend services β REST API, WebSocket server β plus the terminal UI and market dashboard |
| π¦ finverify-sdk | Official Python SDK (pip install finverify-sdk) for integrating FinVerify into your own applications |
| π finverify-bench | Benchmark suite and evaluation harness for deterministic financial verification |
| π¬ research | Papers, notebooks, experiments, and reproducibility assets |
New here? Jump to Quick Start to run any of these locally, or Repository Structure for the full layout.
LLMs answering financial questions are often directionally right and numerically wrong β a decimal point misplaced, a percentage reported as a raw fraction, a sign flipped. In a regulated or capital-allocation context, that's not a rounding error. It's a liability.
Most fixes reach for more prompting. FinVerify reaches for a rule engine instead: the Deterministic Verification Layer (DVL). Scale, sign, and magnitude errors are mechanically distinct from reasoning errors β they need a rule, not another model call.
Underneath the DVL sits a Numeric Canonicalizer that parses raw numeric tokens into an unambiguous, Decimal-based representation before any correction rule runs, and a Constraint Engine that checks whether multiple claims are consistent with each other (e.g. does GrossProfit actually equal Revenue β COGS) using a dependency graph and dimensional analysis, not just single-number correction.
| Traditional AI Workflow | FinVerify |
|---|---|
| Trust the output | Verify the output |
| Probabilistic | Deterministic |
| Hidden reasoning | Auditable corrections |
| Fix errors with better prompts | Fix errors with rules |
| Black box | Transparent, logged, reproducible |
Built for
| π οΈ Developers | Shipping AI products that surface financial numbers and need an auditable correction layer |
| π¬ Researchers | Studying numerical hallucination, who need a reproducible, ground-truth-free method |
| π Analysts | Using AI chat assistants for financial analysis who want a deterministic second check |
Actively maintained Β Β·Β Apache 2.0 Β Β·Β Discussions enabled Β Β·Β Extension in active development
TypeScript React Next.js Python FastAPI Mistral-7B (QLoRA) HuggingFace Playwright GitHub Actions
FinVerify's flagship surface. It verifies numbers in AI chat output inline, without leaving the page.
| Capability | Description |
|---|---|
| Inline verification | Numerical claims in a chat response run through the DVL as you read |
| Trust badges | Each verified number gets a HIGH / MEDIUM / LOW badge from the Trust Engine |
| Verification report | Expand a badge to see the correction rule, the original value, and the corrected value |
| Provider Adapters | New chat surfaces can be added without touching the DVL |
A HIGH / MEDIUM / LOW badge rendered next to an AI chat answer.
Expanded badge showing the correction rule, original value, and corrected value.
Built as a monorepo workspace (@finverify/core shared package) with separate build targets: content and background scripts as IIFE bundles, popup as an ES module. Playwright end-to-end tests against local chat-UI fixtures are in progress, alongside the existing unit test suite.
The official Python client for FinVerify β for developers who want DVL verification inside their own applications, without going through the extension or terminal UI.
pip install finverify-sdk| Capability | Description |
|---|---|
| Sync + async clients | FinVerify and AsyncFinVerify, identical public surface |
| Offline deterministic verification | verify_local() runs the DVL correction rules in-process, no network call |
| Batch verification | Verify multiple claims in one call |
| Typed models | Dataclass response models, full type hints, py.typed marker |
| Automatic retries | Exponential backoff with jitter on 429/5xx, honoring Retry-After |
See finverify-sdk/README.md for the full API and finverify-sdk/CHANGELOG.md for release notes.
finverify-bench is the evaluation side of FinVerify: a benchmark suite and harness for measuring deterministic financial verification, independent of any single model.
- Reproducible evaluation harness for FinQA-derived and synthetic samples
- Ground-truth-blind DVL scoring β corrections never see the answer key
- Documented benchmark methodology in
BENCHMARK_DESIGN.md
See finverify-bench/README.md to run the harness yourself.
| Category | Highlights |
|---|---|
| Verification | DVL β deterministic scale, sign, and magnitude correction Β· Numeric Canonicalizer β Decimal-based numeric token parsing shared by DVL and the parser Β· Constraint Engine β dependency-graph + dimensional-analysis consistency checks across multiple claims Β· Batch Verification API β one shared constraint pass across a batch of claims Β· Trust Engine β delta-based confidence scoring |
| Browser Extension | Inline trust badges and verification reports Β· Provider Adapter architecture Β· Monorepo workspace |
| Backend | FastAPI REST + WebSocket API Β· Live market data verified through the DVL Β· SEC EDGAR & earnings-transcript ingestion Β· RAG pipeline (Pinecone + fallback) |
| Research | FinVerifyBench β synthetic diagnostic benchmark Β· Reproducible FinQA evaluation harness Β· Published ablation study |
| Developer Experience | Standalone SDK (pip install finverify-sdk) Β· Terminal UI Β· CI pipelines for backend and SDK |
| Open Source | Apache 2.0 Β· CONTRIBUTING guide, Code of Conduct, Security policy Β· Issues triaged by label |
End-to-end
flowchart TD
A[Browser: AI chat page] --> B[Provider Adapter]
B --> C[DVL]
C --> D[Backend: FastAPI]
D --> E[Trust Engine]
E --> F["UI (extension badge / terminal / dashboard)"]
Backend detail β single-claim pipeline
flowchart TD
A[User Query] --> B{Query Classifier}
B -->|advisory| C[LLM Only] --> D[Unverified Response]
B -->|numerical| E["LLM Inference (Mistral-7B + QLoRA)"]
E --> F["Numeric Canonicalizer: token β Decimal + unit"]
F --> G["DVL Pipeline: scale β sign β magnitude + audit log"]
G --> H["Trust Engine (delta-based)"]
H --> I[Verified Output + correction log]
Multi-claim pipeline β Constraint Engine
flowchart TD
A["Batch of claims (POST /v1/verify/batch)"] --> B["verify() per claim (DVL)"]
B --> C["Formula Parser + concepts.yaml"]
C --> D["Constraint Graph (dependency order, cycle detection)"]
D --> E["Dimensional Analysis (Currency / % / Ratio / PerShare / β¦)"]
E --> F["Constraint Verifier (tolerance-based comparison)"]
F --> G["BatchVerifyResponse: per-claim results + shared violations"]
Why it matters β every surface (extension, terminal, API) calls the same DVL for single-claim correction. The Constraint Engine adds a second, independent check across claims: does
GrossProfitactually equalRevenue β COGS, not just "is this one number formatted correctly."
TODO (unverified in-repo): the backend currently contains two constraint-checking code paths β
backend/fcg/constraint_engine.py(older) andbackend/core/financial/constraints/(newer, described above). Both have live test suites. This README describes the newerconstraints/module since it's the one wired intoverify_batch(); the relationship between the two, and whetherfcg/is being deprecated, isn't documented in the repo and should be clarified rather than assumed.
This diagram intentionally omits ingestion and RAG subsystems β see Repository Structure for those.
The full flow a claim goes through, end to end:
- Input β a claim arrives either from LLM output (extension, terminal query) or as a direct API call (
/verify,/v1/verify/batch). - Claim Extraction β the numeric assertion and its associated concept (e.g. "gross margin") are pulled out of the surrounding text.
- Numeric Canonicalization β the raw numeric token is parsed into a structured, unambiguous form (Decimal value + unit), rejecting ambiguous input rather than guessing.
- DVL β scale, sign, and magnitude correction rules run against the canonicalized value, with every correction logged.
- Constraint Verification (multi-claim only) β if two or more related claims are present, they're checked against each other via the dependency graph and dimensional analysis, producing
ViolationorINDETERMINATEresults rather than silently passing. - Trust Engine β a delta-based confidence score is computed from how much correction was needed.
- Output β a
VerificationResult(orBatchVerifyResponsefor batches) containing the corrected value, the trust score, and the full audit trail.
Numeric Canonicalizer (backend/numeric/canonicalizer.py) β the single source of truth for turning a raw numeric token into a Decimal value with an explicit unit. Deliberately refuses to guess on ambiguous input (e.g. locale-ambiguous grouping, unclear scale words) rather than silently picking an interpretation. Lives outside core/ specifically to avoid a circular import with app.dvl.
Constraint Engine (backend/core/financial/constraints/) β a formula parser, a dependency graph (Kahn's algorithm, explicit cycle reporting), and a tolerance-based verifier that together check whether multiple financial claims are mutually consistent, independent of whether any single claim's number is "correct" in isolation.
Formula Engine β the sole evaluator of parsed equations; the constraint parser deliberately only parses (produces an intermediate representation) and never evaluates, keeping evaluation logic in one place.
Trust Engine β computes a delta-based HIGH / MEDIUM / LOW confidence score from how much a claim's raw value had to be corrected.
Transcript Ingestion (backend/ingestion/transcripts.py) β extracts and verifies numerical claims from earnings-call transcripts.
Financial Constraint Graph β see the TODO above: this term currently refers ambiguously to either backend/fcg/constraint_engine.py (older) or the dependency graph inside backend/core/financial/constraints/graph.py (newer). Not yet resolved in-repo.
|
Runs the FastAPI verification service. git clone https://github.com/aadityat23/finverify-llm.git
cd finverify-llm/finverify-terminal/backend
python -m venv venv
source venv/bin/activate
pip install -r requirements.txt
cp .env.example .env # fill in HF_TOKEN
uvicorn app.main:app --reload --port 8000 |
Runs the terminal and market dashboard UI. cd finverify-llm/finverify-terminal/frontend
npm install
cp .env.local.example .env.local
npm run dev # http://localhost:3000 |
|
Installs the standalone Python SDK for local, offline verification. pip install finverify-sdkFor local development against this repo instead: cd finverify-llm/finverify-sdk
pip install -e ".[dev]"See |
Builds the browser extension for inline verification. cd finverify-llm/finverify-extension
npm install
npm run buildLoad it via |
Verify the backend is running:
curl http://localhost:8000/health
curl -X POST http://localhost:8000/verify \
-H "Content-Type: application/json" \
-d '{"question": "What was the profit margin?", "raw_number": 0.1240}'
curl http://localhost:8000/market/quotes?symbols=AAPL,TSLAScreenshots are an open contribution β see Contributing.
FinQA dev set, n=873, 95% bootstrap CI:
| Configuration | Accuracy | 95% CI | Ξ |
|---|---|---|---|
| Baseline (no context) | 1.00% | [0.4, 1.9] | β |
| +Document Context | 24.00% | [21.2, 26.9] | +23.0pp |
| +DVL v1 | 32.00% | [29.0, 35.1] | +8.0pp |
| +QLoRA Fine-tuning | 38.50% | [35.4, 41.7] | +6.5pp |
| +DVL v2 (final) | 42.61% | [39.5, 45.7] | +4.1pp |
Negative results: CoT prompting β9.0pp, CoT fine-tuning β12.0pp, cross-doc RAG β7.5pp.
At 42.61%, this is 5.4pp behind GPT-3.5 (no CoT, 48.0%) β using a model 25x smaller, no proprietary compute, and fully deterministic, auditable output.
The DVL only fires on formatting-level errors, not reasoning errors β see the error taxonomy below.
| Error type | Count | % |
|---|---|---|
| Reasoning (close, <50% rel.) | 210 | 39.0% |
| Reasoning (far, >50% rel.) | 184 | 34.1% |
| Magnitude | 66 | 12.2% |
| Order-of-magnitude | 62 | 11.4% |
| Sign | 9 | 1.6% |
| Scale | 4 | 0.8% |
73.1% of remaining failures are reasoning errors, not correctable by the DVL. 0% are formatting or extraction failures after fine-tuning.
finverify-llm/
βββ README.md # this file
βββ docs/ # cross-component documentation, images
βββ artifacts/ # build artifacts, exported reports
βββ finverify-extension/ # Chrome Extension (monorepo)
β βββ packages/
β β βββ core/ # @finverify/core β shared verification client
β βββ content/ # content script (IIFE build)
β βββ background/ # background script (IIFE build)
β βββ popup/ # popup UI (ESM build)
βββ finverify-terminal/ # backend services + terminal/dashboard UI
β βββ backend/
β β βββ app/
β β β βββ main.py # FastAPI app and route definitions
β β β βββ dvl.py # Deterministic Verification Layer
β β β βββ router.py # numerical vs advisory query classifier
β β β βββ parser.py # numeric extraction from LLM text
β β β βββ market.py # yfinance wrapper, DVL-verified metrics
β β β βββ models.py # request/response schemas
β β βββ numeric/ # Numeric Canonicalizer (Decimal-based token parsing)
β β βββ core/
β β β βββ engine.py # verify(), verify_batch()
β β β βββ math_engine/ # DVL rule engine
β β β βββ financial/
β β β βββ constraints/ # Formula Parser, Constraint Graph, Dimensional Analysis, Verifier
β β βββ fcg/ # TODO: older constraint-checking module β see note above on
β β β # its relationship to core/financial/constraints/, unresolved in-repo
β β βββ ingestion/ # SEC EDGAR and earnings-transcript ingestion
β β βββ rag/ # retrieval pipeline (Pinecone + fallback search)
β β βββ evals/ # cross-model evaluation harness
β βββ frontend/
β βββ app/ # Next.js pages: terminal, market, metrics
β βββ components/ # TrustScore, DVLReport, VerificationLog, etc.
β βββ lib/ # API client, offline DVL fallback, history
βββ finverify-sdk/ # standalone `pip install finverify-sdk` package
β βββ finverify/ # SDK source β sync/async clients, typed models
βββ finverify-bench/ # benchmark suite and evaluation harness
β βββ BENCHMARK_DESIGN.md # methodology and construction notes
β βββ DVL_mapping/ # ground-truth-blind DVL evaluation mapping
βββ research/ # papers, notebooks, experiments, reproducibility assets
Component reference (click to expand)
| Component | Path | Purpose |
|---|---|---|
| Chrome Extension core | finverify-extension/packages/core |
Shared verification client used across content/background/popup |
| DVL engine | backend/app/dvl.py |
Scale/sign/magnitude correction with audit logging |
| Numeric Canonicalizer | backend/numeric/canonicalizer.py |
Decimal-based numeric token parsing shared by DVL and the parser |
| Constraint Engine | backend/core/financial/constraints/ |
Formula parsing, dependency graph, dimensional analysis, tolerance-based multi-claim verification |
| Batch Verification | backend/core/engine.py (verify_batch) Β· POST /v1/verify/batch |
One shared constraint pass across a batch of claims |
| Query classifier | backend/app/router.py |
Routes numerical vs advisory queries |
| Market layer | backend/app/market.py |
Live yfinance data, DVL-verified financial metrics |
backend/fcg/constraint_engine.py |
Older multi-number accounting-identity checker; TODO β relationship to the newer Constraint Engine above is not documented in-repo | |
| SEC EDGAR ingestion | backend/ingestion/sec_edgar.py |
XBRL/fallback ingestion of 10-K/10-Q fundamentals |
| Earnings transcript verification | backend/ingestion/transcripts.py |
Regex extraction and DVL verification of earnings-call claims |
| RAG pipeline | backend/rag/pipeline.py |
Pinecone vector + keyword-overlap fallback retrieval |
| WebSocket server | backend/app/main.py |
Real-time market data push (5s interval) |
| Terminal UI | frontend/app/page.tsx |
Terminal-style query interface, three-panel layout |
| Market mode | frontend/app/market/page.tsx |
Live watchlist, verified metric cards, sparklines |
| Metrics dashboard | frontend/app/metrics/page.tsx |
Paper results, ablation study, error taxonomy |
| Python SDK | finverify-sdk/finverify/ |
Sync/async client, typed models, verify_local() offline mode |
| Benchmark suite | finverify-bench/ |
FinVerifyBench dataset, DVL evaluation mapping, design docs |
Test suite size:
finverify-terminal/backend/tests/currently defines 224 test functions across 19 files (largest:test_constraint_engine.pywith 37,test_numeric_canonicalizer.pywith 23). This count was taken directly from the test files, not from a CI run β TODO: confirm the actual passing count from a realpytestrun in CI, since the backend's heavier dependencies (torch, transformers) weren't installed for this audit.
| Method | Path | Description |
|---|---|---|
| POST | /query |
LLM inference + DVL verification |
| POST | /verify |
DVL-only verification, no LLM call |
| GET | /health |
Health check |
| GET | /market/quotes?symbols=AAPL,TSLA |
Live stock quotes |
| GET | /market/indices |
S&P 500, NASDAQ, VIX |
| GET | /market/verified-metrics?symbol=AAPL&metric=profit_margin |
DVL-verified metric |
| GET | /market/all-metrics?symbol=AAPL |
All five metrics for a symbol |
| POST, GET | /v1/fcg/* |
FCG endpoints: verify, normalize, list constraints |
| POST, GET | /v1/rag/* |
RAG endpoints: query, stats, seed |
| GET, POST, DELETE | /v1/history/* |
User query-history persistence |
| WS | /ws/market |
Real-time market data stream |
/v1/fundamentals/{ticker}, /v1/earnings/{ticker}, and /v1/ingest/* are also exposed, for on-demand SEC and transcript ingestion. Endpoint-by-endpoint documentation is an open contribution β see Contributing.
| Paper | Modular Verification Outperforms Chain-of-Thought Reasoning in Small Financial LLMs: A Systematic Ablation Study on Numerical Hallucination Reduction |
| Submitted to | FinNLP @ EMNLP 2026 / IEEE Access |
| Author | Aaditya Thokal, Universal College of Engineering, Mumbai β aaditya.thokal24@gmail.com |
| Model | aadi2026/finverify-lora β Mistral-7B + QLoRA, trained on 2,000 FinQA examples |
| Dataset | FinQA dev set (n=873); FinVerifyBench isolates formatting-level errors from reasoning errors |
Tracked through GitHub Milestones β here's where things stand, and where help is most useful.
|
Core Infrastructure
|
Verification Engine
|
|
Browser Extension
|
Developer Experience & Research
|
β
Completed π§ In progress π Planned
FinVerify is a young project with a lot of open surface area β there's a meaningful way to contribute regardless of your background.
Start with CONTRIBUTING.md for setup and workflow, and CODE_OF_CONDUCT.md for community guidelines.
| Label | Good for |
|---|---|
good first issue |
Self-contained, no deep internals required |
help wanted |
Open tasks looking for a contributor |
research |
Benchmark design, ablations, evaluation methodology |
backend |
FastAPI, DVL, ingestion, RAG |
frontend |
Next.js terminal and dashboard |
extension |
Chrome Extension, Provider Adapters, Playwright E2E |
documentation |
Endpoint docs, guides, screenshots |
First open-source contribution?
good first issueis the place to start.
| π Website | Live Demo |
| π¬ Discussions | GitHub Discussions β design questions, feedback, "is this worth doing" conversations |
| π Issues | GitHub Issues β bugs and tracked work |
| π Contributing guide | CONTRIBUTING.md |
| π₯ Contributors | CONTRIBUTORS.md |
FinVerify was created and is maintained by Aaditya Thokal, University of Mumbai/ IITM.
Apache License 2.0 β see LICENSE.
If FinVerify is useful to you, consider starring the repository. β


