๐งฌ TruthDNA โ Misinformation Tracker
Inspiration
It started with a WhatsApp message.
My family group chat lit up one morning with a health claim โ something about a common food causing cancer, shared by a well-meaning relative who genuinely believed it. Within hours it had been forwarded hundreds of times across other groups. By the time I tracked down the original source and debunked it, the damage was done. Nobody reads the correction. Everyone remembers the claim.
That moment stuck with me. Misinformation doesn't spread because people are gullible โ it spreads because verification is too slow and too hard. The World Economic Forum ranked misinformation the #1 global threat in 2026, above climate change and armed conflict. As of today, $62\%$ of all online content is estimated to be false or misleading. And with AI now capable of generating convincing fake papers, deepfakes, and news articles at scale, the problem is accelerating faster than any human fact-checker can keep up.
I wanted to build something that fights misinformation the way misinformation itself spreads โ fast, autonomous, and continuously improving.
What I Learned
Building TruthDNA taught me that the hardest part of AI agent development isn't the model โ it's the context engineering.
Getting GPT-4o-mini to return a reliable verdict wasn't just about prompting. It required:
- A calibration layer that checks whether source evidence directly supports the claim before accepting the verdict
- A confidence weight system that tracks which entity types historically appear in misinformation
The weight score for each entity type is computed as:
$$w_e = \frac{N_{\text{misinfo}}(e)}{N_{\text{misinfo}}(e) + N_{\text{true}}(e)}$$
Where $w_e \in [0, 1]$ represents how misinformation-prone claims mentioning entity type $e$ tend to be. A score of $w_e > 0.7$ triggers an automatic score boost during analysis:
$$S_{\text{final}} = \min\left(100,\ S_{\text{base}} + \sum_{e \in E} \mathbb{1}[w_e > 0.7] \cdot w_e \cdot 15\right)$$
I also learned that graph databases fundamentally change how you think about knowledge. In a relational database, asking "which claims share the same entities?" requires expensive joins. In Neo4j, it's a single Cypher traversal. That architectural insight unlocked mutation detection โ the ability to see when the same actors and technologies appear across multiple coordinated false claims.
How I Built It
TruthDNA is a fully async Python pipeline with six stages, each powered by a different sponsor technology:
Pipeline Architecture
Input (text or image)
โ
[Reka Vision] โ Extracts text from screenshots and images
โ
[Pioneer GLiNER2] โ Named entity recognition (12 entity types)
โ
[Query Builder] โ Adaptive search queries weighted by learned risk scores
โ
[Tavily] โ Real-time search across 14 trusted fact-checking sources
โ
[OpenAI GPT-4o] โ Misinformation scoring (0โ100%) + verdict + reasoning
โ
[Neo4j AuraDB] โ Knowledge graph storage + relationship mapping
โ
Output: Verdict + HTML Report + Learning Update
The Self-Learning System
The learning system runs before and after every claim analysis:
Before โ
update_confidence_weights()queries all pastClaimnodes and their linkedEntitynodes, computing $w_e$ for each entity type and storing the result asWeightnodes in Neo4jBefore โ
get_improvement_suggestions()finds semantically similar past claims using sequence matching, applying a $+10\%$ score boost if a similar claim was previously verified as misinformationAfter โ
log_query_effectiveness()updatesQueryPatternnodes with success rates, tracking which search strategies reliably return verifiable sourcesAfter โ
log_learning_event()increments theanalysis_countproperty on every entity node involved in the claim
Over time, the system builds a living knowledge graph where:
(:Claim)nodes store verdicts, scores, and reasoning(:Entity)nodes accumulate analysis history(:Weight)nodes encode learned misinformation risk per entity type(:QueryPattern)nodes track which search strategies work best[:MENTIONS]relationships connect claims to entities[:CONTRADICTS]relationships link claims to debunking sources
Stack
| Component | Technology |
|---|---|
| Entity Extraction | Pioneer GLiNER2 API |
| Vision / OCR | Reka Flash |
| Real-Time Search | Tavily |
| AI Scoring | OpenAI GPT-4o-mini |
| Knowledge Graph | Neo4j AuraDB |
| Web UI | Streamlit |
| Async Runtime | Python asyncio + httpx |
Challenges
1. Async Architecture Across Mixed Sync/Async Drivers
Neo4j provides both a sync driver (GraphDatabase) and an async driver (AsyncGraphDatabase). The learning system uses the sync driver (for CPU-bound similarity calculations run in thread executors), while the graph storage layer uses the async driver. Keeping these two in sync โ pun intended โ without blocking the event loop required careful use of run_in_executor and strict separation of responsibilities.
2. Calibrating the Scorer Without Ground Truth
The biggest challenge was preventing the system from being overconfident. GPT-4o-mini would sometimes return MISINFORMATION with HIGH confidence for claims where the search results were only tangentially related. I built a calibration function that checks direct evidence overlap between the claim and search results using tokenized word intersection:
$$\text{overlap_ratio} = \frac{|\text{terms}{\text{claim}} \cap \text{terms}{\text{source}}|}{\max(|\text{terms}_{\text{claim}}|, 1)}$$
If $\text{overlap_ratio} < 0.45$ and $|\text{shared terms}| < 3$, the verdict is downgraded to UNVERIFIABLE regardless of what the model returned. This single rule dramatically improved verdict reliability.
3. Cold Start Problem
A self-learning system that starts with no data is useless for a demo. I solved this by building a seed script that pre-populates AuraDB with 12 historical claims, 18 entities, 22 relationships, and 5 query patterns โ giving the learning system enough signal to start producing meaningful weight scores and recommendations from the very first run.
4. Running Neo4j in Production
Switching from a local Neo4j instance to AuraDB mid-development broke the connection string format (neo4j:// vs neo4j+s://), the default database name, and the password validation logic. Every file that instantiated a driver had to be updated and tested. A small thing that cost significant time right before the deadline.
What's Next
- Vector embeddings for claim similarity instead of character-level sequence matching โ using Neo4j's native vector index with sentence-transformer embeddings
- Reka Vision integrated into the Streamlit UI so users can upload images and screenshots directly
- Mutation scoring โ a dedicated metric for detecting when the same false claim has been reworded and is spreading again
- Browser extension โ flag claims inline on Twitter, LinkedIn, and WhatsApp Web before you share them
Built in 4.5 hours for the Context Engineering Hackathon ยท February 2026
Log in or sign up for Devpost to join the conversation.