CoolFace
Apppublic

Danielchris145/TruthCheck-AI

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
app.py297 linesDownload Raw Back to root
1# app.py2import os3from flask import Flask, render_template, request, jsonify4from functools import lru_cache5import hashlib6import sqlite37import datetime8import json9 10from models.claim_extractor import ClaimExtractor11from models.keyword_extractor import KeywordExtractor12from models.evidence_retriever import EvidenceRetriever13from models.nli_classifier import NLIClassifier14from utils.similarity import calculate_similarity15from utils.config import Config16 17 18# Initialize models globally19claim_extractor = ClaimExtractor()20keyword_extractor = KeywordExtractor()21evidence_retriever = EvidenceRetriever()22nli_classifier = NLIClassifier()23 24 25class TruthCheckSystem:26    def __init__(self):27        self.claim_extractor = claim_extractor28        self.keyword_extractor = keyword_extractor29        self.evidence_retriever = evidence_retriever30        self.nli_classifier = nli_classifier31        self.cache = {}32        33    def _get_cache_key(self, text):34        """Generate cache key for claim"""35        return hashlib.md5(text.encode()).hexdigest()36    37    def verify_claim(self, text):38        """39        Enhanced fact verification with multi-evidence aggregation40        and consensus mechanism (similar to FactCheck system)41        """42        try:43            # Check cache44            cache_key = self._get_cache_key(text)45            if cache_key in self.cache:46                print("Returning cached result")47                return self.cache[cache_key]48            49            # Step 1: Extract claims50            claims = self.claim_extractor.extract_claims(text)51            if not claims:52                result = ("Low Confidence", 0.3, "No valid claims found. Please provide a clear factual statement.")53                self.cache[cache_key] = result54                return result55            56            claim = claims[0]57            58            # Step 2: Extract keywords59            keywords = self.keyword_extractor.extract_keywords(claim)60            61            # Step 3: Retrieve evidence from multiple sources62            evidence_items = self.evidence_retriever.get_evidence(keywords)63            64            if not evidence_items:65                result = ("Low Confidence", 0.3, "Not enough reliable evidence found.")66                self.cache[cache_key] = result67                return result68            69            # Step 4: Filter by semantic similarity70            relevant_evidence = []71            for item in evidence_items:72                similarity = calculate_similarity(claim, item['content'])73                if similarity > Config.SIMILARITY_THRESHOLD:74                    item['similarity_score'] = similarity75                    relevant_evidence.append(item)76            77            if not relevant_evidence:78                result = ("Low Confidence", 0.4, "No semantically relevant evidence found.")79                self.cache[cache_key] = result80                return result81            82            # Step 5: Sort by combined score (credibility + similarity)83            for item in relevant_evidence:84                item['combined_score'] = (85                    item.get('credibility_score', 0.5) * 0.6 +86                    item.get('similarity_score', 0.5) * 0.487                )88            89            relevant_evidence.sort(key=lambda x: x['combined_score'], reverse=True)90            91            # Step 6: Multi-Evidence NLI with Consensus Mechanism92            # Use top 4 evidence sources (as per FactCheck research)93            top_evidence = relevant_evidence[:4]94            95            nli_results = []96            for evidence_item in top_evidence:97                nli_result = self.nli_classifier.classify(claim, evidence_item['content'])98                nli_results.append({99                    'nli': nli_result,100                    'credibility': evidence_item.get('credibility_score', 0.5),101                    'similarity': evidence_item.get('similarity_score', 0.5),102                    'source': evidence_item.get('source', 'Unknown'),103                    'url': evidence_item.get('url', '')104                })105            106            # Step 7: Weighted Consensus Voting107            entailment_score = 0108            contradiction_score = 0109            neutral_score = 0110            111            total_weight = 0112            for result in nli_results:113                # Weight by credibility and confidence114                weight = result['credibility'] * result['nli']['confidence']115                total_weight += weight116                117                if result['nli']['label'] == 'ENTAILMENT':118                    entailment_score += weight119                elif result['nli']['label'] == 'CONTRADICTION':120                    contradiction_score += weight121                else:122                    neutral_score += weight123            124            # Normalize scores125            if total_weight > 0:126                entailment_score /= total_weight127                contradiction_score /= total_weight128                neutral_score /= total_weight129            130            # Step 8: Determine final label with consensus threshold131            consensus_threshold = 0.6  # Require 60% agreement132            133            max_score = max(entailment_score, contradiction_score, neutral_score)134            135            if max_score == entailment_score and entailment_score >= consensus_threshold:136                label = "True"137                final_confidence = entailment_score138            elif max_score == contradiction_score and contradiction_score >= consensus_threshold:139                label = "False"140                final_confidence = contradiction_score141            else:142                label = "Low Confidence"143                final_confidence = max(entailment_score, contradiction_score, neutral_score)144            145            # Step 9: Prepare evidence summary146            evidence_summary = self._format_evidence_summary(nli_results, top_evidence)147            148            result = (label, final_confidence, evidence_summary)149            150            # Cache result151            self.cache[cache_key] = result152            153            return result154            155        except Exception as e:156            print(f"Error during claim verification: {e}")157            import traceback158            traceback.print_exc()159            return ("Error", 0.0, f"An internal error occurred: {str(e)}")160    161    def _format_evidence_summary(self, nli_results, evidence_items):162        """Format evidence summary with sources and verdicts"""163        summary_parts = []164        165        summary_parts.append(f"**Analyzed {len(nli_results)} sources:**\n")166        167        for i, (nli_res, evidence) in enumerate(zip(nli_results, evidence_items), 1):168            source = nli_res['source']169            verdict = nli_res['nli']['label']170            confidence = nli_res['nli']['confidence']171            credibility = nli_res['credibility']172            url = nli_res['url']173            174            # Get snippet175            content = evidence.get('content', '')[:300]176            177            summary_parts.append(178                f"\n**Source {i}: {source}**\n"179                f"Verdict: {verdict} (Confidence: {confidence:.2%})\n"180                f"Credibility Score: {credibility:.2f}\n"181                f"Excerpt: {content}...\n"182                f"URL: {url}\n"183            )184        185        return "\n".join(summary_parts)186 187 188# Initialize system189truthcheck_system_instance = TruthCheckSystem()190 191 192DB_PATH = os.path.join(os.getcwd(), 'history.db')193 194def init_db():195    """Initialize SQLite database"""196    conn = sqlite3.connect(DB_PATH)197    c = conn.cursor()198    c.execute('''199        CREATE TABLE IF NOT EXISTS verifications (200            id INTEGER PRIMARY KEY AUTOINCREMENT,201            claim TEXT NOT NULL,202            label TEXT NOT NULL,203            confidence REAL,204            date TIMESTAMP DEFAULT CURRENT_TIMESTAMP205        )206    ''')207    conn.commit()208    conn.close()209 210init_db()211 212 213def create_app():214    app = Flask(__name__, static_folder='static', template_folder='templates')215    app.config['SECRET_KEY'] = os.environ.get('SECRET_KEY', Config.SECRET_KEY)216    app.config['DEBUG'] = Config.DEBUG217    218    @app.route('/')219    def index():220        return render_template('index.html')221 222    @app.route('/how-it-works')223    def how_it_works():224        return render_template('how_it_works.html')225 226    @app.route('/api-docs')227    def api_docs():228        return render_template('api.html')229    230    @app.route('/dashboard')231    def dashboard():232        return render_template('dashboard.html')233 234    @app.route('/api/history')235    def get_history():236        try:237            conn = sqlite3.connect(DB_PATH)238            conn.row_factory = sqlite3.Row239            c = conn.cursor()240            c.execute('SELECT * FROM verifications ORDER BY date DESC LIMIT 50')241            rows = c.fetchall()242            conn.close()243            244            history = []245            for row in rows:246                history.append({247                    'id': row['id'],248                    'claim': row['claim'],249                    'label': row['label'],250                    'confidence': row['confidence'],251                    'date': row['date']252                })253            return jsonify(history)254        except Exception as e:255            return jsonify({'error': str(e)}), 500256 257    @app.route('/api/verify', methods=['POST'])258    def verify_claim_api():259        try:260            data = request.get_json()261            claim_text = data.get('claim', '')262            263            if not claim_text:264                return jsonify({'error': 'No claim provided'}), 400265            266            label, confidence, evidence = truthcheck_system_instance.verify_claim(claim_text)267            268            # Save to DB269            try:270                conn = sqlite3.connect(DB_PATH)271                c = conn.cursor()272                c.execute('INSERT INTO verifications (claim, label, confidence) VALUES (?, ?, ?)',273                          (claim_text, label, float(confidence)))274                conn.commit()275                conn.close()276            except Exception as e:277                print(f"DB Error: {e}")278            279            result = {280                'label': label,281                'confidence': round(confidence, 3),282                'evidence': evidence,283                'claim': claim_text284            }285            286            return jsonify(result)287            288        except Exception as e:289            print(f"API error: {e}")290            return jsonify({'error': f'Server error: {str(e)}'}), 500291    292    @app.route('/health')293    def health_check():294        return jsonify({'status': 'healthy', 'message': 'TruthCheck is running.'})295    296    return app297