· · ·
|
Misinformation doesn't spread because people are careless. It spreads because verification is expensive and confidence is cheap. Checking a claim properly means finding independent sources, cross-referencing them, weighing their credibility, and reasoning about what they actually support — work that takes minutes a reader doesn't have, against a claim that took seconds to write. The asymmetry is structural, not incidental. Every system that doesn't correct for it will keep losing to the same dynamic. |
Most "AI fact-checkers" collapse the entire verification problem into a single number — a confidence score, a true/false label — generated by a model reasoning over its own parametric memory. This fails in two specific, avoidable ways:
| Failure Mode | Consequence |
|---|---|
| The model answers from what it was trained on, not from current, checkable sources | Confident answers about claims the model has no real evidence for |
| The output is a verdict with no visible reasoning chain | The user has no way to audit *why* the system concluded what it did — trust is demanded, not earned |
A credibility score without a reasoning trace is not meaningfully different from a stranger's opinion. VERITAS is built on the premise that the reasoning path — which claims were extracted, which evidence was retrieved, how each piece of evidence was weighted — is not an optional add-on. It is the product.
This is also why VERITAS deliberately does not rely on an LLM to generate its verdicts. An LLM asked "is this true" answers from its training distribution — a static, dated, unaudited source. VERITAS instead retrieves live, external evidence for every claim and scores credibility against that retrieved evidence — so a conclusion is only ever as strong as the sources backing it, and those sources are always visible.
VERITAS is an Explainable Intelligence Platform — it takes unstructured text, extracts the claims within it, retrieves independent evidence for each claim, scores credibility against that evidence, and returns a fully traceable reasoning chain, not a verdict handed down from a black box.
|
Extract
|
Retrieve
|
Score
|
Explain
|
flowchart TB
subgraph Client["Client Layer"]
UI["React Frontend<br/>Submission · Report · Evidence Trace"]
end
subgraph Backend["Application Layer"]
FL["Flask<br/>Auth · Submission · Orchestration"]
FA["FastAPI Microservice<br/>NLP Pipeline · Evidence Retrieval · Scoring"]
end
subgraph Intelligence["Intelligence Pipeline"]
NLP["spaCy + Transformers<br/>Claim + Entity Extraction"]
ML["scikit-learn<br/>Credibility Scoring Models"]
EV["Google Custom Search / News API<br/>Live Evidence Retrieval"]
end
UI -->|"REST"| FL
FL -->|"internal call"| FA
FA --> NLP
NLP --> EV
EV --> ML
ML --> FA
FA -->|"scored, explainable report"| FL
FL -->|"JSON"| UI
style ML fill:#0B1D33,stroke:#D4AF37,color:#fff
style EV fill:#10B981,stroke:#0A0A0A,color:#111
flowchart LR
A["Raw Text Input"] --> B["Claim Extraction<br/>spaCy + Transformers"]
B --> C["Entity Recognition"]
C --> D["Evidence Retrieval<br/>Google Search / News API"]
D --> E["Credibility Scoring<br/>scikit-learn"]
E --> F["Bias Detection"]
F --> G["Explainability Engine"]
G --> H["Report Generator"]
style B fill:#0B1D33,stroke:#D4AF37,color:#fff
style E fill:#10B981,stroke:#0A0A0A,color:#111
style G fill:#D4AF37,stroke:#0A0A0A,color:#111
|
Problem: Not every sentence in a document is a checkable factual claim — opinions, questions, and hedged statements aren't. Verifying all of them wastes evidence-retrieval budget on things that were never falsifiable to begin with. Solution: A spaCy-based syntactic pass isolates candidate factual assertions; a transformer-based classifier then filters for claims that are specific and checkable, discarding opinion and speculative language before anything reaches the evidence layer. |
Note Engineering decision: extraction is deliberately a two-stage filter (syntactic candidate generation, then classification) rather than a single model call — cheaper syntactic filtering runs first so the more expensive transformer pass only sees plausible candidates. |
Named entities within each extracted claim — people, organizations, dates, locations, figures — are tagged so evidence retrieval can be scoped precisely. A claim about "unemployment in Q3 2025" and a claim about "unemployment" in general should not be verified against the same evidence set; entity tagging is what makes that distinction possible.
|
Retrieves live, independent evidence for each extracted claim via the Google Custom Search / News API — not from a static or pre-indexed corpus, and not from a model's training data. Each claim is issued as a targeted query, and returned sources are collected alongside their publication metadata for downstream credibility weighting. Why this matters: a verification system whose evidence base doesn't update is making the same category of error it's meant to catch — asserting something as current when it may no longer be true. |
flowchart TD
A["Extracted Claim"] --> B["Query Formulation"]
B --> C["Google Custom Search / News API"]
C --> D["Source Collection<br/>+ Publication Metadata"]
D --> E["Passed to Credibility Scoring"]
style C fill:#10B981,stroke:#0A0A0A,color:#111
|
Retrieved evidence is not treated as uniformly trustworthy. A scikit-learn-based scoring model weighs each source against features including source diversity, agreement across independent sources, and publication recency — and produces a credibility score for the claim as a function of its evidence, not as an isolated model judgment.
Tip
A claim supported by three independent, agreeing sources is scored differently than one supported by three re-publications of a single original source — the scoring model is designed to detect and discount the latter.
|
This is the subsystem that makes VERITAS a research-grade platform rather than another opaque classifier. For every credibility score produced, the Explainability Engine reconstructs and exposes the full reasoning path: which claim was extracted, which entities anchored it, which sources were retrieved, how each source was weighted, and how those weights combined into the final score. Research value: because every stage of the pipeline persists its intermediate output, the reasoning trace is not reconstructed after the fact from logs — it is a first-class artifact generated alongside the score itself. |
Evidence sources are also screened for editorial lean and framing bias, so a credibility score isn't inadvertently built on a set of sources that all share the same blind spot. Bias signal is surfaced in the report as context for interpreting the evidence — not used to silently discard sources, since a biased source can still contain accurate factual content.
Synthesizes claim, evidence, credibility score, and bias signal into a single structured report — the reasoning trace made legible, not just logged. This is the artifact a user actually reads: not a bare score, but the evidence chain that produced it.
▲ Placeholder — record a walkthrough of a real claim submission → evidence trace → report and replace this GIF.
|
React, structured around a submission-to-report flow: text/claim input, a live pipeline-status view during processing, and a report surface that renders the evidence trace as a navigable structure rather than a wall of text. |
Flask owns submission handling and orchestration; the NLP/ML pipeline and evidence retrieval are isolated in a FastAPI microservice, so the compute-heavy transformer inference and external API calls (Google Search/News) can be scaled and rate-limited independently of the core application. |
| Layer | Technology | Purpose |
|---|---|---|
| Frontend | React | Claim submission, live pipeline status, evidence-trace report view |
| Application Backend | Flask | Submission handling, auth, orchestration |
| Intelligence Microservice | FastAPI | NLP pipeline, evidence retrieval, scoring — isolated for independent scaling |
| NLP | spaCy, Hugging Face Transformers | Claim extraction, entity recognition |
| Credibility Modeling | scikit-learn | Evidence-weighted credibility scoring — no LLM in the scoring path |
| External Evidence | Google Custom Search / News API | Live, independent evidence retrieval per claim |
| Hosting | Vercel | Production deployment |
Note
VERITAS deliberately does not use an LLM for claim scoring or verdict generation — credibility is a function of retrieved evidence and a scikit-learn scoring model, not a language model's parametric judgment. This is a core design choice, not a limitation: see §II–§IV.
veritas/
├── client/ # React frontend
│ └── src/
│ ├── components/ # Submission form, pipeline status, report view
│ ├── pages/
│ └── services/ # API client layer
├── server/
│ ├── flask_app/ # Auth, submission endpoints, orchestration
│ └── intelligence_service/ # FastAPI microservice
│ ├── extraction/ # spaCy + Transformers claim/entity extraction
│ ├── evidence/ # Google Search/News API integration
│ ├── scoring/ # scikit-learn credibility models
│ ├── explainability/ # Reasoning trace assembly
│ └── main.py
├── requirements.txt
└── package.json
Note
Placeholder — confirm this matches your actual repo layout before publishing; adjust to your real package structure.
- Google Search/News API keys held server-side only — never exposed to the React client
- Claim submissions should be rate-limited to prevent evidence-API quota exhaustion from abuse
- Model artifacts (scikit-learn scoring models) versioned separately from application code
Warning
Placeholder — confirm actual data retention policy for submitted text and generated reports before publishing.
| Concern | Approach |
|---|---|
| Transformer inference latency | Isolated FastAPI microservice, independently scalable from the Flask request path |
| External API rate limits | Evidence retrieval results cached per claim signature to avoid redundant Google Search/News calls |
| Pipeline throughput | Two-stage claim extraction (cheap syntactic filter before expensive transformer pass, §VIII) keeps per-document cost proportional to actual claim density |
- Claim Extraction (spaCy + Transformers)
- Evidence Engine (live Google Search / News API)
- Credibility Scoring (scikit-learn)
- Explainability Engine + Report Generator
- Multi-language claim extraction
- Source-credibility reputation tracking over time
- Batch/document-level verification (beyond single-claim submission)
- Fork the repository and create a feature branch (
feat/your-feature) - If touching the scoring model, document the features it consumes and retrain/validate before submitting
- Any new pipeline stage must persist intermediate output for the Explainability Engine — see §XII
- Open a PR describing the reasoning-quality impact, not just the code diff
Bhagavan — @thenameisbhagavan
Distributed under the MIT License. See LICENSE for details.
