lightmate commited on
Commit
a535254
Β·
verified Β·
1 Parent(s): 1ec7e77

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +96 -68
app.py CHANGED
@@ -3,28 +3,30 @@ from newspaper import Article
3
  from modules.online_search import search_online
4
  from modules.validation import calculate_truthfulness_score
5
  from modules.knowledge_graph import search_kg
6
- from modules.generate_explanation import generate_explanation # Import the explanation generator
7
  from dotenv import load_dotenv
8
  import os
9
  from concurrent.futures import ThreadPoolExecutor
 
10
 
11
- # Load environment variables from .env file
12
  load_dotenv()
13
 
14
- # Constants
 
 
 
 
15
  KG_INDEX_PATH = "KG/news_category_index.faiss"
16
  KG_DATASET_PATH = "KG/News_Category_Dataset_v3.json"
17
  SEARCH_API_KEY = os.getenv("SEARCH_API_KEY")
18
  SEARCH_BASE_URL = os.getenv("SEARCH_BASE_URL")
19
  SEARCH_MODEL = os.getenv("SEARCH_MODEL")
20
 
21
- # Initialize ThreadPoolExecutor
22
- executor = ThreadPoolExecutor(max_workers=3) # Increased workers to accommodate explanation task
23
 
24
- # Function to process input and evaluate truthfulness
25
  def evaluate_news(news_input):
26
- # Display loading message
27
- yield "**Processing... Please wait while we analyze the information.** ⏳"
28
 
29
  # Handle URL input
30
  if news_input.startswith("http"):
@@ -37,94 +39,120 @@ def evaluate_news(news_input):
37
  yield f"**Error processing the URL:** {str(e)}"
38
  return
39
  else:
40
- # Direct text input
41
  news_text = news_input
42
 
43
  try:
44
- # Run both search functions concurrently using ThreadPoolExecutor
45
  future_kg = executor.submit(search_kg, news_text, KG_INDEX_PATH, KG_DATASET_PATH)
46
  future_online = executor.submit(search_online, news_text, SEARCH_API_KEY, SEARCH_BASE_URL, SEARCH_MODEL)
47
 
48
- # Wait for the results of both tasks
49
  kg_content = future_kg.result()
50
  online_search_results = future_online.result()
51
 
52
- # Combine context from KG and online search
 
 
 
 
53
  context = online_search_results['message_content'] + '\n' + kg_content + '\n' + 'Device set to use cpu'
54
- # print(context) # Debug log
55
 
56
- # Calculate truth score
57
  truth_score = calculate_truthfulness_score(info=news_text, context=context)
 
58
 
59
- # Determine truthfulness status and recommendation
60
  if truth_score > 0.7:
61
- status = "likely true"
62
- recommendation = "You can reasonably trust this information, but further verification is always recommended for critical decisions."
63
  elif truth_score > 0.4:
64
- status = "uncertain"
65
- recommendation = "This information might be partially true, but additional investigation is required before accepting it as fact."
66
  else:
67
- status = "unlikely to be true"
68
- recommendation = "It is recommended to verify this information through multiple reliable sources before trusting it."
 
 
 
 
 
 
69
 
70
- # Display initial result with score
71
- result = f"**News**: \"{news_text[:300]}...\"\n\n"
72
- result += f"**Truthfulness Score**: {truth_score:.2f} (**{status.capitalize()}**)\n\n"
73
- result += f"**Analysis**: {recommendation}\n\n"
74
- yield result # Immediately display score and recommendation
75
 
76
  # Generate explanation asynchronously
77
  future_explanation = executor.submit(generate_explanation, news_text, context, truth_score)
 
78
 
79
- # Add explanation and sources once available
80
- explanation = future_explanation.result() # Wait for explanation result
81
  if explanation:
82
- result += f"**Explanation**: {explanation}\n\n" # Append explanation
83
 
84
- # Add sources from the online search results (top 5 sources)
85
- sources = online_search_results.get('sources', [])
86
- if sources:
87
- result += "\n**Sources**:\n"
88
- # Ensure we only show up to 5 sources
89
- for i, source in enumerate(sources[:5]):
90
- result += f"{i + 1}. {source}\n"
91
- result += "\n*Please make sure to do your own research for more confirmation and to cross-check the information.*"
92
 
93
- yield result # Update UI with explanation and sources
94
 
95
  except Exception as e:
96
- yield f"**Error occurred while processing the input:** {str(e)}"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
97
 
98
 
99
  # Gradio Interface
100
- with gr.Blocks() as demo:
101
- gr.Markdown("# πŸ“° EchoTruth: Verify News Authenticity in Real-Time")
102
-
103
- gr.Markdown("""
104
- **How to use:**
105
- 1. Enter a news article or URL in the box below.
106
- 2. Click on **Check Truthfulness**.
107
- 3. Receive a **truthfulness score** along with **explanations and sources** to help you assess the authenticity of the content.
108
- """)
109
-
110
- with gr.Row():
111
- input_box = gr.Textbox(
112
- placeholder="Enter news text or URL here... (e.g., https://example.com)",
113
- label="Input News or URL",
114
- lines=5
115
- )
116
-
117
- submit_btn = gr.Button("Check Truthfulness")
118
-
119
- output_box = gr.Markdown()
120
-
121
- submit_btn.click(
122
- fn=evaluate_news,
123
- inputs=[input_box],
124
- outputs=[output_box]
125
- )
 
 
 
126
 
127
  gr.Markdown("### **About EchoTruth**")
128
- gr.Markdown("EchoTruth uses AI to help users verify news authenticity in real-time. We recommend checking multiple sources before making decisions based on news.")
129
-
130
- demo.launch()
 
3
  from modules.online_search import search_online
4
  from modules.validation import calculate_truthfulness_score
5
  from modules.knowledge_graph import search_kg
6
+ from modules.generate_explanation import generate_explanation
7
  from dotenv import load_dotenv
8
  import os
9
  from concurrent.futures import ThreadPoolExecutor
10
+ from modules.record import DatabaseComponent # Import DatabaseComponent
11
 
12
+ # Load environment variables
13
  load_dotenv()
14
 
15
+ # Initialize database and executor
16
+ db = DatabaseComponent()
17
+ executor = ThreadPoolExecutor(max_workers=3)
18
+
19
+ # Constants for file paths and API keys
20
  KG_INDEX_PATH = "KG/news_category_index.faiss"
21
  KG_DATASET_PATH = "KG/News_Category_Dataset_v3.json"
22
  SEARCH_API_KEY = os.getenv("SEARCH_API_KEY")
23
  SEARCH_BASE_URL = os.getenv("SEARCH_BASE_URL")
24
  SEARCH_MODEL = os.getenv("SEARCH_MODEL")
25
 
 
 
26
 
27
+ # Function to process and verify news
28
  def evaluate_news(news_input):
29
+ yield "**Processing... Please wait.** ⏳"
 
30
 
31
  # Handle URL input
32
  if news_input.startswith("http"):
 
39
  yield f"**Error processing the URL:** {str(e)}"
40
  return
41
  else:
 
42
  news_text = news_input
43
 
44
  try:
45
+ # Run search tasks concurrently
46
  future_kg = executor.submit(search_kg, news_text, KG_INDEX_PATH, KG_DATASET_PATH)
47
  future_online = executor.submit(search_online, news_text, SEARCH_API_KEY, SEARCH_BASE_URL, SEARCH_MODEL)
48
 
49
+ # Wait for results
50
  kg_content = future_kg.result()
51
  online_search_results = future_online.result()
52
 
53
+ # Extract citations from the search results
54
+ citations = online_search_results.get("citations", []) # List of sources
55
+ first_citation = citations[0] if citations else "N/A" # Store first citation in DB
56
+
57
+ # Combine context
58
  context = online_search_results['message_content'] + '\n' + kg_content + '\n' + 'Device set to use cpu'
 
59
 
60
+ # Compute truth score
61
  truth_score = calculate_truthfulness_score(info=news_text, context=context)
62
+ truth_percentage = truth_score * 100 # Convert to percentage
63
 
64
+ # Determine truth status
65
  if truth_score > 0.7:
66
+ status = f"**{truth_percentage:.0f}% chances to be true** - This news is likely true."
 
67
  elif truth_score > 0.4:
68
+ status = f"**{truth_percentage:.0f}% chances to be true** - This news is uncertain. Please verify further."
 
69
  else:
70
+ status = f"**{truth_percentage:.0f}% chances to be true** - This news is unlikely to be true. Proceed with caution."
71
+
72
+ # Save result in database
73
+ db.save_news_verification(news_text[:100], truth_score, first_citation)
74
+
75
+ # Initial result
76
+ result = f"**News:** \"{news_text[:300]}...\"\n\n"
77
+ result += f"**Truthfulness Score:** {truth_score:.2f} ({status})\n\n"
78
 
79
+ yield result # Display initial results
 
 
 
 
80
 
81
  # Generate explanation asynchronously
82
  future_explanation = executor.submit(generate_explanation, news_text, context, truth_score)
83
+ explanation = future_explanation.result()
84
 
 
 
85
  if explanation:
86
+ result += f"**Explanation:** {explanation}\n\n"
87
 
88
+ # Display sources
89
+ if citations:
90
+ result += "\n**Sources & References:**\n"
91
+ for i, source in enumerate(citations[:5]): # Show up to 5 sources
92
+ result += f"{i + 1}. [{source}]({source})\n"
 
 
 
93
 
94
+ yield result # Final output with sources
95
 
96
  except Exception as e:
97
+ yield f"**Error:** {str(e)}"
98
+
99
+
100
+ # Function to fetch dashboard data
101
+ def fetch_dashboard_data():
102
+ total_news = db.get_total_news_count()
103
+ last_10_news = db.get_last_10_news()
104
+
105
+ # Generate table-style layout for recent verifications
106
+ dashboard_info = f"**Total News Verified:** {total_news}\n\n"
107
+
108
+ if last_10_news:
109
+ table = "| # | News Title | Score (%) | Date Verified | Citation |\n"
110
+ table += "|---|------------|-----------|--------------|----------|\n"
111
+
112
+ for i, news in enumerate(last_10_news, start=1):
113
+ truth_percentage = news['score'] * 100 # Convert to percentage
114
+ citation = f"[Source]({news['citation']})" if news['citation'] != "N/A" else "N/A"
115
+ table += f"| {i} | {news['title'][:50]}... | {truth_percentage:.0f}% | {news['timestamp']} | {citation} |\n"
116
+
117
+ dashboard_info += table
118
+ else:
119
+ dashboard_info += "_No records found._"
120
+
121
+ return dashboard_info
122
 
123
 
124
  # Gradio Interface
125
+ with gr.Blocks(css="""
126
+ .gradio-container { font-family: 'Georgia', serif; font-size: 16px; }
127
+ h1, h2, h3 { font-family: 'Times New Roman', serif; }
128
+ table { width: 100%; border-collapse: collapse; }
129
+ th, td { padding: 10px; border: 1px solid #ddd; text-align: left; }
130
+ """) as demo:
131
+ with gr.Tabs() as tabs:
132
+ with gr.Tab("πŸ” Verify News"):
133
+ gr.Markdown("# πŸ“° EchoTruth: News Verification")
134
+ gr.Markdown("""
135
+ **How it Works:**
136
+ - Enter a news article **or** a URL.
137
+ - Click **Check Truthfulness**.
138
+ - Get a **truth score**, an explanation, and references.
139
+ """)
140
+
141
+ input_box = gr.Textbox(placeholder="Paste news text or URL...", label="News Input", lines=5)
142
+ submit_btn = gr.Button("Check Truthfulness")
143
+ output_box = gr.Markdown()
144
+ submit_btn.click(fn=evaluate_news, inputs=[input_box], outputs=[output_box])
145
+
146
+ with gr.Tab("πŸ“Š Dashboard") as dashboard_tab:
147
+ gr.Markdown("# πŸ“Š Verification Dashboard")
148
+ dashboard_output = gr.Markdown()
149
+ refresh_btn = gr.Button("πŸ”„ Refresh Data")
150
+ refresh_btn.click(fn=fetch_dashboard_data, inputs=[], outputs=[dashboard_output])
151
+
152
+ # Automatically refresh dashboard when the tab is opened
153
+ tabs.select(fn=fetch_dashboard_data, inputs=[], outputs=[dashboard_output])
154
 
155
  gr.Markdown("### **About EchoTruth**")
156
+ gr.Markdown("EchoTruth uses AI to help users verify news authenticity in real-time.")
157
+
158
+ demo.launch()