File size: 6,578 Bytes
1190b8e a535254 1190b8e 5db8377 a535254 1190b8e a535254 1190b8e b90e46a a535254 5db8377 1190b8e 5db8377 a535254 1190b8e 3b47028 a535254 1190b8e a535254 5db8377 1190b8e a535254 5db8377 1190b8e a535254 6133cad 1190b8e a535254 1190b8e a535254 1190b8e a535254 1190b8e a535254 1190b8e a535254 1190b8e a535254 b90e46a a535254 1190b8e a535254 6133cad a535254 6133cad a535254 6133cad a535254 6133cad a535254 1190b8e a535254 b90e46a a535254 1190b8e a535254 186a3cb a535254 6133cad a535254 b90e46a |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 |
import gradio as gr
from newspaper import Article
from modules.online_search import search_online
from modules.validation import calculate_truthfulness_score
from modules.knowledge_graph import search_kg
from modules.generate_explanation import generate_explanation
from dotenv import load_dotenv
import os
from concurrent.futures import ThreadPoolExecutor
from modules.record import DatabaseComponent # Import DatabaseComponent
# Load environment variables
load_dotenv()
# Initialize database (handle connection failures)
db = None
try:
db = DatabaseComponent()
except Exception as e:
print(f"[ERROR] Database connection failed: {str(e)}")
# Initialize thread executor
executor = ThreadPoolExecutor(max_workers=3)
# Constants for file paths and API keys
KG_INDEX_PATH = "KG/news_category_index.faiss"
KG_DATASET_PATH = "KG/News_Category_Dataset_v3.json"
SEARCH_API_KEY = os.getenv("SEARCH_API_KEY")
SEARCH_BASE_URL = os.getenv("SEARCH_BASE_URL")
SEARCH_MODEL = os.getenv("SEARCH_MODEL")
# Function to process and verify news
def evaluate_news(news_input):
if not news_input.strip():
yield "**β οΈ Warning:** Input cannot be empty. Please enter news text or a URL."
return
yield "**Processing... Please wait.** β³"
# Handle URL input
if news_input.startswith("http"):
try:
article = Article(news_input)
article.download()
article.parse()
news_text = article.title + ". " + article.text
except Exception as e:
yield f"**Error processing the URL:** {str(e)}"
return
else:
news_text = news_input
try:
# Run search tasks concurrently
future_kg = executor.submit(search_kg, news_text, KG_INDEX_PATH, KG_DATASET_PATH)
future_online = executor.submit(search_online, news_text, SEARCH_API_KEY, SEARCH_BASE_URL, SEARCH_MODEL)
# Wait for results
kg_content = future_kg.result()
online_search_results = future_online.result()
# Extract citations from the search results
citations = online_search_results.get("citations", []) # List of sources
first_citation = citations[0] if citations else "N/A" # Store first citation in DB
# Combine context
context = online_search_results['message_content'] + '\n' + kg_content + '\n' + 'Device set to use cpu'
# Compute truth score
truth_score = calculate_truthfulness_score(info=news_text, context=context)
truth_percentage = truth_score * 100 # Convert to percentage
# Determine truth status
if truth_score > 0.7:
status = f"**{truth_percentage:.0f}% chances to be true** - This news is likely true."
elif truth_score > 0.4:
status = f"**{truth_percentage:.0f}% chances to be true** - This news is uncertain. Please verify further."
else:
status = f"**{truth_percentage:.0f}% chances to be true** - This news is unlikely to be true. Proceed with caution."
# Save result in database if connection is available
if db is not None:
db.save_news_verification(news_text[:100], truth_score, first_citation)
# Initial result
result = f"**News:** \"{news_text[:300]}...\"\n\n"
result += f"**Truthfulness Score:** {truth_score:.2f} ({status})\n\n"
yield result # Display initial results
# Generate explanation asynchronously
future_explanation = executor.submit(generate_explanation, news_text, context, truth_score)
explanation = future_explanation.result()
if explanation:
result += f"**Explanation:** {explanation}\n\n"
# Display sources
if citations:
result += "\n**Sources & References:**\n"
for i, source in enumerate(citations[:5]): # Show up to 5 sources
result += f"{i + 1}. [{source}]({source})\n"
yield result # Final output with sources
except Exception as e:
yield f"**Error:** {str(e)}"
# Function to fetch dashboard data
def fetch_dashboard_data():
if db is None:
return "**β οΈ Database unavailable. Recent verification records cannot be displayed.**"
total_news = db.get_total_news_count()
last_10_news = db.get_last_10_news()
# Generate table-style layout for recent verifications
dashboard_info = f"**Total News Verified:** {total_news}\n\n"
if last_10_news:
table = "| # | News Title | Score (%) | Date Verified | Citation |\n"
table += "|---|------------|-----------|--------------|----------|\n"
for i, news in enumerate(last_10_news, start=1):
truth_percentage = news['score'] * 100 # Convert to percentage
citation = f"[Source]({news['citation']})" if news['citation'] != "N/A" else "N/A"
table += f"| {i} | {news['title'][:50]}... | {truth_percentage:.0f}% | {news['timestamp']} | {citation} |\n"
dashboard_info += table
else:
dashboard_info += "_No records found._"
return dashboard_info
# Gradio Interface
with gr.Blocks(css="""
.gradio-container { font-family: 'Georgia', serif; font-size: 16px; }
h1, h2, h3 { font-family: 'Times New Roman', serif; }
table { width: 100%; border-collapse: collapse; }
th, td { padding: 10px; border: 1px solid #ddd; text-align: left; }
""") as demo:
with gr.Tabs() as tabs:
with gr.Tab("π Verify News"):
gr.Markdown("# π° EchoTruth: News Verification")
gr.Markdown("""
**How it Works:**
- Enter a news article **or** a URL.
- Click **Check Truthfulness**.
- Get a **truth score**, an explanation, and references.
""")
input_box = gr.Textbox(placeholder="Paste news text or URL...", label="News Input", lines=5)
submit_btn = gr.Button("Check Truthfulness")
output_box = gr.Markdown()
submit_btn.click(fn=evaluate_news, inputs=[input_box], outputs=[output_box])
with gr.Tab("π Dashboard") as dashboard_tab:
gr.Markdown("# π Verification Dashboard")
dashboard_output = gr.Markdown("_Click 'Refresh Data' to load latest records._")
refresh_btn = gr.Button("π Refresh Data")
refresh_btn.click(fn=fetch_dashboard_data, inputs=[], outputs=[dashboard_output])
gr.Markdown("### **About EchoTruth**")
gr.Markdown("EchoTruth uses AI to help users verify news authenticity in real-time.")
demo.launch() |