Spaces:
Running
Running
Upload app.py
Browse files
app.py
CHANGED
|
@@ -8,7 +8,7 @@ import re
|
|
| 8 |
import os
|
| 9 |
import numpy as np
|
| 10 |
|
| 11 |
-
GOOGLE_API_KEY = "
|
| 12 |
SEARCH_ENGINE_ID = "f34f8a4816771488b"
|
| 13 |
GEMINI_API_KEY = "AIzaSyAHPzJ_VjTX3gZLBV28d3sq97SdER2qfkc"
|
| 14 |
MODEL_PATH = "./vietnamese_fake_news_model"
|
|
@@ -137,8 +137,36 @@ def process_search_results(items):
|
|
| 137 |
return search_results
|
| 138 |
|
| 139 |
def google_search_fallback(news_text):
|
| 140 |
-
print("Google Search is unavailable
|
| 141 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 142 |
|
| 143 |
|
| 144 |
|
|
@@ -344,29 +372,42 @@ def analyze_with_gemini(news_text, search_results, distilbert_prediction, distil
|
|
| 344 |
else:
|
| 345 |
search_summary = "Không tìm thấy kết quả tìm kiếm Google cho tin tức này. Điều này có thể do API bị giới hạn hoặc tin tức quá mới/chưa được đăng tải."
|
| 346 |
|
| 347 |
-
#
|
| 348 |
-
distilbert_analysis = ""
|
| 349 |
-
if distilbert_prediction:
|
| 350 |
-
distilbert_analysis = f"Phân tích DistilBERT: Dự đoán '{distilbert_prediction}' với độ tin cậy {distilbert_confidence:.3f}"
|
| 351 |
-
else:
|
| 352 |
-
distilbert_analysis = "DistilBERT: Không thể phân tích"
|
| 353 |
|
| 354 |
prompt = f"""
|
| 355 |
-
Hãy phân tích tin tức sau và đánh giá độ tin cậy của
|
| 356 |
|
| 357 |
"{news_text}"
|
| 358 |
|
| 359 |
{search_summary}
|
| 360 |
|
| 361 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 362 |
|
| 363 |
-
|
| 364 |
|
| 365 |
-
1.
|
| 366 |
-
2. Tại sao bạn nghĩ vậy? (Giải thích ngắn gọn, dễ hiểu)
|
| 367 |
-
3. Người đọc nên làm gì? (Lời khuyên đơn giản)
|
| 368 |
|
| 369 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 370 |
"""
|
| 371 |
|
| 372 |
print("Calling Gemini API...")
|
|
@@ -375,12 +416,12 @@ Tránh dùng thuật ngữ kỹ thuật, hãy viết như đang nói chuyện v
|
|
| 375 |
if search_results:
|
| 376 |
print(f"DEBUG - First search result title: {search_results[0].get('title', 'No title')}")
|
| 377 |
|
| 378 |
-
# Use
|
| 379 |
generation_config = genai.types.GenerationConfig(
|
| 380 |
-
temperature=0.
|
| 381 |
-
top_p=0.
|
| 382 |
-
top_k=
|
| 383 |
-
max_output_tokens=
|
| 384 |
)
|
| 385 |
response = model.generate_content(prompt, generation_config=generation_config)
|
| 386 |
print("Gemini API response received successfully")
|
|
@@ -392,20 +433,59 @@ Tránh dùng thuật ngữ kỹ thuật, hãy viết như đang nói chuyện v
|
|
| 392 |
|
| 393 |
# If we hit the API limit, provide a basic analysis
|
| 394 |
if "429" in str(e) or "quota" in str(e).lower():
|
| 395 |
-
print("Gemini API quota exceeded, providing fallback analysis...")
|
| 396 |
-
|
| 397 |
-
|
| 398 |
-
|
| 399 |
-
|
| 400 |
-
|
| 401 |
-
|
| 402 |
-
|
| 403 |
-
|
| 404 |
-
|
| 405 |
-
|
| 406 |
-
|
| 407 |
-
|
| 408 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 409 |
return fallback_analysis
|
| 410 |
|
| 411 |
# For other errors, see what models are available
|
|
@@ -634,9 +714,11 @@ def analyze_news(news_text):
|
|
| 634 |
</div>
|
| 635 |
|
| 636 |
### 🧠 **Phân tích thông minh**
|
| 637 |
-
<div style="background: #f8f9fa; padding:
|
|
|
|
| 638 |
{gemini_analysis}
|
| 639 |
</div>
|
|
|
|
| 640 |
|
| 641 |
### 📊 **KẾT LUẬN CUỐI CÙNG**
|
| 642 |
<div style="background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%); color: white; padding: 15px; border-radius: 8px; margin: 20px 0;">
|
|
|
|
| 8 |
import os
|
| 9 |
import numpy as np
|
| 10 |
|
| 11 |
+
GOOGLE_API_KEY = "AIzaSyASwqVh3ELFVKH-W3WuHtmjg3XgtwjJQKg"
|
| 12 |
SEARCH_ENGINE_ID = "f34f8a4816771488b"
|
| 13 |
GEMINI_API_KEY = "AIzaSyAHPzJ_VjTX3gZLBV28d3sq97SdER2qfkc"
|
| 14 |
MODEL_PATH = "./vietnamese_fake_news_model"
|
|
|
|
| 137 |
return search_results
|
| 138 |
|
| 139 |
def google_search_fallback(news_text):
|
| 140 |
+
print("Google Search is unavailable - using enhanced content analysis")
|
| 141 |
+
# Enhanced content analysis without external search
|
| 142 |
+
fake_indicators = ['giả', 'sai', 'không đúng', 'bịa đặt', 'lừa đảo', 'fake news', 'tin đồn', 'nghi vấn']
|
| 143 |
+
real_indicators = ['chính thức', 'xác nhận', 'chính xác', 'đúng', 'verified', 'chính phủ', 'bộ y tế', 'cơ quan']
|
| 144 |
+
|
| 145 |
+
text_lower = news_text.lower()
|
| 146 |
+
fake_count = sum(1 for word in fake_indicators if word in text_lower)
|
| 147 |
+
real_count = sum(1 for word in real_indicators if word in text_lower)
|
| 148 |
+
|
| 149 |
+
# Create more detailed analysis
|
| 150 |
+
analysis_details = []
|
| 151 |
+
if fake_count > real_count:
|
| 152 |
+
analysis_details.append("Nhiều từ khóa nghi ngờ được sử dụng")
|
| 153 |
+
elif real_count > fake_count:
|
| 154 |
+
analysis_details.append("Có từ khóa xác thực từ nguồn chính thức")
|
| 155 |
+
|
| 156 |
+
# Check for other patterns
|
| 157 |
+
if len(news_text) < 100:
|
| 158 |
+
analysis_details.append("Tin tức quá ngắn, thiếu thông tin chi tiết")
|
| 159 |
+
if '!' in news_text or '!!!' in news_text:
|
| 160 |
+
analysis_details.append("Sử dụng dấu chấm than thái quá")
|
| 161 |
+
|
| 162 |
+
snippet = f"Phân tích nội dung: {fake_count} từ nghi ngờ, {real_count} từ xác thực. "
|
| 163 |
+
snippet += "; ".join(analysis_details) if analysis_details else "Không phát hiện dấu hiệu đặc biệt"
|
| 164 |
+
|
| 165 |
+
return [{
|
| 166 |
+
'title': 'Phân tích nội dung chi tiết (không có tìm kiếm Google)',
|
| 167 |
+
'snippet': snippet,
|
| 168 |
+
'link': 'content-analysis-only'
|
| 169 |
+
}]
|
| 170 |
|
| 171 |
|
| 172 |
|
|
|
|
| 372 |
else:
|
| 373 |
search_summary = "Không tìm thấy kết quả tìm kiếm Google cho tin tức này. Điều này có thể do API bị giới hạn hoặc tin tức quá mới/chưa được đăng tải."
|
| 374 |
|
| 375 |
+
# Note: We're not including DistilBERT results to keep Gemini analysis independent
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 376 |
|
| 377 |
prompt = f"""
|
| 378 |
+
Bạn là một chuyên gia phân tích tin tức chuyên nghiệp. Hãy phân tích chi tiết tin tức sau và đánh giá độ tin cậy của nó:
|
| 379 |
|
| 380 |
"{news_text}"
|
| 381 |
|
| 382 |
{search_summary}
|
| 383 |
|
| 384 |
+
Hãy thực hiện phân tích toàn diện theo các tiêu chí sau:
|
| 385 |
+
|
| 386 |
+
1. **Phân tích nội dung**: Kiểm tra tính logic, mâu thuẫn, ngôn ngữ cảm xúc thái quá
|
| 387 |
+
2. **Phân tích nguồn tin**: Đánh giá uy tín và độ tin cậy của nguồn
|
| 388 |
+
3. **Phân tích ngữ cảnh**: So sánh với thông tin có sẵn và kiến thức thực tế
|
| 389 |
+
4. **Phân tích ngôn ngữ**: Tìm dấu hiệu của tin giả như từ ngữ gây sốc, cảm xúc
|
| 390 |
+
5. **Phân tích thời gian**: Kiểm tra tính hợp lý về mặt thời gian
|
| 391 |
|
| 392 |
+
Trả lời theo định dạng sau (chỉ bằng tiếng Việt, viết chi tiết và chuyên nghiệp):
|
| 393 |
|
| 394 |
+
**1. KẾT LUẬN:** [THẬT/GIẢ/KHÔNG XÁC ĐỊNH]
|
|
|
|
|
|
|
| 395 |
|
| 396 |
+
**2. PHÂN TÍCH CHI TIẾT:**
|
| 397 |
+
- **Nội dung:** [Phân tích chi tiết về nội dung tin tức]
|
| 398 |
+
- **Nguồn tin:** [Đánh giá về nguồn và độ tin cậy]
|
| 399 |
+
- **Ngữ cảnh:** [So sánh với thông tin có sẵn]
|
| 400 |
+
- **Ngôn ngữ:** [Phân tích cách sử dụng từ ngữ]
|
| 401 |
+
- **Thời gian:** [Kiểm tra tính hợp lý về mặt thời gian]
|
| 402 |
+
|
| 403 |
+
**3. CÁC DẤU HIỆU CẢNH BÁO:** [Liệt kê các dấu hiệu đáng ngờ nếu có]
|
| 404 |
+
|
| 405 |
+
**4. KHUYẾN NGHỊ CHO NGƯỜI ĐỌC:**
|
| 406 |
+
- [Hướng dẫn cụ thể để kiểm chứng thông tin]
|
| 407 |
+
- [Các nguồn tin đáng tin cậy để tham khảo]
|
| 408 |
+
- [Cách phân biệt tin thật và tin giả]
|
| 409 |
+
|
| 410 |
+
Viết chi tiết, chuyên nghiệp và hữu ích cho người đọc.
|
| 411 |
"""
|
| 412 |
|
| 413 |
print("Calling Gemini API...")
|
|
|
|
| 416 |
if search_results:
|
| 417 |
print(f"DEBUG - First search result title: {search_results[0].get('title', 'No title')}")
|
| 418 |
|
| 419 |
+
# Use settings optimized for detailed analysis
|
| 420 |
generation_config = genai.types.GenerationConfig(
|
| 421 |
+
temperature=0.3, # Slightly higher for more creative analysis
|
| 422 |
+
top_p=0.9, # Allow more diverse vocabulary
|
| 423 |
+
top_k=40, # More vocabulary choices for detailed writing
|
| 424 |
+
max_output_tokens=2000 # Allow much longer responses
|
| 425 |
)
|
| 426 |
response = model.generate_content(prompt, generation_config=generation_config)
|
| 427 |
print("Gemini API response received successfully")
|
|
|
|
| 433 |
|
| 434 |
# If we hit the API limit, provide a basic analysis
|
| 435 |
if "429" in str(e) or "quota" in str(e).lower():
|
| 436 |
+
print("Gemini API quota exceeded, providing enhanced fallback analysis...")
|
| 437 |
+
|
| 438 |
+
# Enhanced analysis based on content patterns
|
| 439 |
+
fake_patterns = ['giả', 'sai', 'không đúng', 'bịa đặt', 'lừa đảo', 'fake news', 'tin đồn']
|
| 440 |
+
real_patterns = ['chính thức', 'xác nhận', 'chính xác', 'đúng', 'verified', 'chính phủ', 'bộ y tế']
|
| 441 |
+
|
| 442 |
+
news_lower = news_text.lower()
|
| 443 |
+
fake_score = sum(1 for pattern in fake_patterns if pattern in news_lower)
|
| 444 |
+
real_score = sum(1 for pattern in real_patterns if pattern in news_lower)
|
| 445 |
+
|
| 446 |
+
# Adjust prediction based on patterns
|
| 447 |
+
if fake_score > real_score and distilbert_prediction == 'FAKE':
|
| 448 |
+
confidence_boost = "Cao (có từ khóa nghi ngờ)"
|
| 449 |
+
elif real_score > fake_score and distilbert_prediction == 'REAL':
|
| 450 |
+
confidence_boost = "Cao (có từ khóa xác thực)"
|
| 451 |
+
else:
|
| 452 |
+
confidence_boost = "Trung bình"
|
| 453 |
+
|
| 454 |
+
# Create detailed fallback analysis
|
| 455 |
+
conclusion = 'THẬT' if distilbert_prediction == 'REAL' else 'GIẢ' if distilbert_prediction == 'FAKE' else 'KHÔNG XÁC ĐỊNH'
|
| 456 |
+
|
| 457 |
+
# Enhanced analysis based on content patterns
|
| 458 |
+
suspicious_patterns = []
|
| 459 |
+
if fake_score > 0:
|
| 460 |
+
suspicious_patterns.append(f"Tìm thấy {fake_score} từ khóa nghi ngờ")
|
| 461 |
+
if real_score > 0:
|
| 462 |
+
suspicious_patterns.append(f"Tìm thấy {real_score} từ khóa xác thực")
|
| 463 |
+
|
| 464 |
+
warning_signs = []
|
| 465 |
+
if 'cảnh báo' in news_lower or 'nguy hiểm' in news_lower:
|
| 466 |
+
warning_signs.append("Sử dụng từ ngữ gây sợ hãi")
|
| 467 |
+
if 'ngay lập tức' in news_lower or 'khẩn cấp' in news_lower:
|
| 468 |
+
warning_signs.append("Tạo cảm giác cấp bách không cần thiết")
|
| 469 |
+
if len(news_text) < 100:
|
| 470 |
+
warning_signs.append("Tin tức quá ngắn, thiếu thông tin chi tiết")
|
| 471 |
+
|
| 472 |
+
fallback_analysis = f"""**1. KẾT LUẬN:** {conclusion}
|
| 473 |
+
|
| 474 |
+
**2. PHÂN TÍCH CHI TIẾT:**
|
| 475 |
+
- **Nội dung:** {'Tin tức có vẻ hợp lý' if distilbert_prediction == 'REAL' else 'Tin tức có nhiều dấu hiệu đáng ngờ' if distilbert_prediction == 'FAKE' else 'Nội dung không rõ ràng'}
|
| 476 |
+
- **Nguồn tin:** Google Search không khả dụng (hết quota) - không thể kiểm tra nguồn
|
| 477 |
+
- **Ngữ cảnh:** Phân tích từ khóa: {confidence_boost}
|
| 478 |
+
- **Ngôn ngữ:** {'Ngôn ngữ trung tính' if fake_score == real_score else 'Có dấu hiệu cảm xúc thái quá' if fake_score > real_score else 'Ngôn ngữ khách quan'}
|
| 479 |
+
- **Thời gian:** Không thể xác minh do thiếu thông tin bổ sung
|
| 480 |
+
|
| 481 |
+
**3. CÁC DẤU HIỆU CẢNH BÁO:**
|
| 482 |
+
{chr(10).join([f"- {sign}" for sign in warning_signs]) if warning_signs else "- Không phát hiện dấu hiệu cảnh báo rõ ràng"}
|
| 483 |
+
|
| 484 |
+
**4. KHUYẾN NGHỊ CHO NGƯỜI ĐỌC:**
|
| 485 |
+
- **Kiểm tra nguồn:** Tìm kiếm thông tin tương tự trên các trang báo uy tín như VnExpress, Tuổi Trẻ, Thanh Niên
|
| 486 |
+
- **Xác minh thời gian:** Kiểm tra xem tin tức có được đăng tải đồng thời trên nhiều nguồn không
|
| 487 |
+
- **Đánh giá ngôn ngữ:** Tránh chia sẻ tin tức có ngôn ngữ cảm xúc thái quá hoặc tạo cảm giác cấp bách
|
| 488 |
+
- **Lưu ý:** Do hệ thống API tạm thời không khả dụng, kết quả phân tích có thể không hoàn toàn chính xác"""
|
| 489 |
return fallback_analysis
|
| 490 |
|
| 491 |
# For other errors, see what models are available
|
|
|
|
| 714 |
</div>
|
| 715 |
|
| 716 |
### 🧠 **Phân tích thông minh**
|
| 717 |
+
<div style="background: #f8f9fa; padding: 20px; border-radius: 10px; border-left: 4px solid #ffc107; margin: 15px 0; font-family: 'Segoe UI', Arial, sans-serif; line-height: 1.6;">
|
| 718 |
+
<div style="white-space: pre-line; color: #333;">
|
| 719 |
{gemini_analysis}
|
| 720 |
</div>
|
| 721 |
+
</div>
|
| 722 |
|
| 723 |
### 📊 **KẾT LUẬN CUỐI CÙNG**
|
| 724 |
<div style="background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%); color: white; padding: 15px; border-radius: 8px; margin: 20px 0;">
|