NLong commited on
Commit
59dfe15
·
verified ·
1 Parent(s): 6c48551

Upload app.py

Browse files
Files changed (1) hide show
  1. app.py +219 -52
app.py CHANGED
@@ -393,20 +393,24 @@ Trả lời theo định dạng sau (chỉ bằng tiếng Việt, viết chi ti
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
 
@@ -471,6 +475,121 @@ Viết chi tiết, chuyên nghiệp và hữu ích cho người đọc.
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
@@ -500,67 +619,115 @@ Viết chi tiết, chuyên nghiệp và hữu ích cho người đọc.
500
  return f"Lỗi phân tích Gemini: {e}"
501
 
502
  def calculate_combined_confidence(distilbert_prediction, distilbert_confidence, source_credibility, popularity_score, gemini_analysis, source_support=0.5):
503
- """Calculate combined confidence from all three tools"""
 
 
 
 
 
504
 
505
- # Base confidence from DistilBERT
506
  if distilbert_prediction == "REAL":
507
- base_confidence = distilbert_confidence
508
  else:
509
- base_confidence = 1 - distilbert_confidence
510
 
511
- # Adjust based on source credibility (stronger adjustments)
512
- if source_credibility > 0.7:
513
- credibility_adjustment = 0.2 # Increased from 0.1
514
- elif source_credibility > 0.4:
515
- credibility_adjustment = 0.05 # Small positive adjustment
516
- else:
517
- credibility_adjustment = -0.1
518
 
519
- # Adjust based on popularity
520
- if popularity_score > 0.7:
521
- popularity_adjustment = 0.1 # Increased from 0.05
522
- elif popularity_score > 0.4:
523
- popularity_adjustment = 0.0
524
  else:
525
- popularity_adjustment = -0.05
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
526
 
527
- # Adjust based on source support (whether sources support or contradict the news)
528
- if source_support > 0.7:
529
- support_adjustment = 0.15 # Sources strongly support
530
- elif source_support > 0.4:
531
- support_adjustment = 0.0 # Sources are neutral
 
532
  else:
533
- support_adjustment = -0.15 # Sources contradict
534
 
535
- # Adjust based on Gemini analysis (stronger adjustments)
536
- gemini_lower = gemini_analysis.lower()
537
- if "độ tin cậy cao" in gemini_lower or "tin cậy cao" in gemini_lower or "cao" in gemini_lower:
538
- gemini_adjustment = 0.2 # Increased from 0.1
539
- elif "độ tin cậy thấp" in gemini_lower or "tin cậy thấp" in gemini_lower or "thấp" in gemini_lower:
540
- gemini_adjustment = -0.2 # Increased from -0.1
 
541
  else:
542
- gemini_adjustment = 0.0
543
-
544
- # Special case: If DistilBERT confidence is very low but sources and Gemini agree it's real
545
- if (distilbert_confidence < 0.6 and
546
- source_credibility > 0.6 and
547
- ("cao" in gemini_lower or "chính xác" in gemini_lower or "đáng tin cậy" in gemini_lower) and
548
- not ("thấp" in gemini_lower or "giả" in gemini_lower or "fake" in gemini_lower)):
549
- # Override with higher confidence ONLY if Gemini says it's real
550
- base_confidence = 0.8
551
- print("Overriding low DistilBERT confidence due to strong source and Gemini agreement for REAL")
552
-
553
- # Special case: If DistilBERT and Gemini both say FAKE, respect that
554
- elif (distilbert_prediction == "FAKE" and
555
- ("thấp" in gemini_lower or "giả" in gemini_lower or "fake" in gemini_lower)):
556
- # Override with low confidence for FAKE
557
- base_confidence = 0.2
558
- print("Overriding confidence due to DistilBERT and Gemini agreement for FAKE")
559
-
560
- # Calculate final confidence
561
- final_confidence = base_confidence + credibility_adjustment + popularity_adjustment + gemini_adjustment + support_adjustment
562
  final_confidence = max(0.05, min(0.95, final_confidence))
563
 
 
 
 
 
 
 
564
  return final_confidence
565
 
566
  def analyze_news(news_text):
 
393
 
394
  **1. KẾT LUẬN:** [THẬT/GIẢ/KHÔNG XÁC ĐỊNH]
395
 
396
+ **2. ĐỘ TIN CẬY:** [X%/Y%] (Trong đó X% là độ tin cậy tin THẬT, Y% là độ tin cậy tin GIẢ, X+Y=100%)
397
+
398
+ **3. PHÂN TÍCH CHI TIẾT:**
399
  - **Nội dung:** [Phân tích chi tiết về nội dung tin tức]
400
  - **Nguồn tin:** [Đánh giá về nguồn và độ tin cậy]
401
  - **Ngữ cảnh:** [So sánh với thông tin có sẵn]
402
  - **Ngôn ngữ:** [Phân tích cách sử dụng từ ngữ]
403
  - **Thời gian:** [Kiểm tra tính hợp lý về mặt thời gian]
404
 
405
+ **4. CÁC DẤU HIỆU CẢNH BÁO:** [Liệt kê các dấu hiệu đáng ngờ nếu có]
406
 
407
+ **5. KHUYẾN NGHỊ CHO NGƯỜI ĐỌC:**
408
  - [Hướng dẫn cụ thể để kiểm chứng thông tin]
409
  - [Các nguồn tin đáng tin cậy để tham khảo]
410
  - [Cách phân biệt tin thật và tin giả]
411
 
412
+ QUAN TRỌNG: Trong phần "ĐỘ TIN CẬY", hãy cung cấp tỷ lệ phần trăm chính xác dựa trên phân tích của bạn. Ví dụ: "95%/5%" nghĩa là 95% tin tức này là THẬT, 5% là GIẢ.
413
+
414
  Viết chi tiết, chuyên nghiệp và hữu ích cho người đọc.
415
  """
416
 
 
475
 
476
  fallback_analysis = f"""**1. KẾT LUẬN:** {conclusion}
477
 
478
+ **2. ĐỘ TIN CẬY:** {'5%/95%' if conclusion == 'GIẢ' else '95%/5%' if conclusion == 'THẬT' else '50%/50%'}
479
+
480
+ **3. PHÂN TÍCH CHI TIẾT:**
481
+ - **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'}
482
+ - **Nguồn tin:** Google Search không khả dụng (hết quota) - không thể kiểm tra nguồn
483
+ - **Ngữ cảnh:** Phân tích từ khóa: {confidence_boost}
484
+ - **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'}
485
+ - **Thời gian:** Không thể xác minh do thiếu thông tin bổ sung
486
+
487
+ **4. CÁC DẤU HIỆU CẢNH BÁO:**
488
+ {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"}
489
+
490
+ **5. KHUYẾN NGHỊ CHO NGƯỜI ĐỌC:**
491
+ - **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
492
+ - **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
493
+ - **Đá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
494
+ - **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"""
495
+ return fallback_analysis
496
+
497
+ # For other errors, see what models are available
498
+ try:
499
+ models = genai.list_models()
500
+ print("Available models:")
501
+ for model in models:
502
+ if 'gemini' in model.name.lower():
503
+ print(f" - {model.name}")
504
+ except Exception as list_error:
505
+ print(f"Could not list models: {list_error}")
506
+ return f"Lỗi phân tích Gemini: {e}"
507
+
508
+ def extract_gemini_percentage(gemini_analysis):
509
+ """Extract percentage confidence from Gemini analysis"""
510
+ try:
511
+ gemini_lower = gemini_analysis.lower()
512
+
513
+ # Look for the confidence percentage pattern
514
+ import re
515
+
516
+ # Pattern to match "X%/Y%" format
517
+ percentage_pattern = r'độ tin cậy.*?(\d+)%/(\d+)%'
518
+ match = re.search(percentage_pattern, gemini_lower)
519
+
520
+ if match:
521
+ real_percent = int(match.group(1))
522
+ fake_percent = int(match.group(2))
523
+
524
+ # Normalize to ensure they add up to 100
525
+ total = real_percent + fake_percent
526
+ if total > 0:
527
+ real_percent = real_percent / total
528
+ fake_percent = fake_percent / total
529
+ else:
530
+ real_percent = 0.5
531
+ fake_percent = 0.5
532
+
533
+ print(f"Extracted Gemini percentages: {real_percent:.1%} real, {fake_percent:.1%} fake")
534
+ return real_percent, fake_percent
535
+
536
+ # Fallback: try to find individual percentages
537
+ real_match = re.search(r'(\d+)%.*?thật', gemini_lower)
538
+ fake_match = re.search(r'(\d+)%.*?giả', gemini_lower)
539
+
540
+ if real_match and fake_match:
541
+ real_percent = int(real_match.group(1)) / 100
542
+ fake_percent = int(fake_match.group(1)) / 100
543
+ print(f"Extracted Gemini percentages (fallback): {real_percent:.1%} real, {fake_percent:.1%} fake")
544
+ return real_percent, fake_percent
545
+
546
+ print("Could not extract Gemini percentages, using conclusion analysis")
547
+ return None, None
548
+
549
+ except Exception as e:
550
+ print(f"Error extracting Gemini percentages: {e}")
551
+ return None, None
552
+
553
+ # If we hit the API limit, provide a basic analysis
554
+ if "429" in str(e) or "quota" in str(e).lower():
555
+ print("Gemini API quota exceeded, providing enhanced fallback analysis...")
556
+
557
+ # Enhanced analysis based on content patterns
558
+ fake_patterns = ['giả', 'sai', 'không đúng', 'bịa đặt', 'lừa đảo', 'fake news', 'tin đồn']
559
+ real_patterns = ['chính thức', 'xác nhận', 'chính xác', 'đúng', 'verified', 'chính phủ', 'bộ y tế']
560
+
561
+ news_lower = news_text.lower()
562
+ fake_score = sum(1 for pattern in fake_patterns if pattern in news_lower)
563
+ real_score = sum(1 for pattern in real_patterns if pattern in news_lower)
564
+
565
+ # Adjust prediction based on patterns
566
+ if fake_score > real_score and distilbert_prediction == 'FAKE':
567
+ confidence_boost = "Cao (có từ khóa nghi ngờ)"
568
+ elif real_score > fake_score and distilbert_prediction == 'REAL':
569
+ confidence_boost = "Cao (có từ khóa xác thực)"
570
+ else:
571
+ confidence_boost = "Trung bình"
572
+
573
+ # Create detailed fallback analysis
574
+ conclusion = 'THẬT' if distilbert_prediction == 'REAL' else 'GIẢ' if distilbert_prediction == 'FAKE' else 'KHÔNG XÁC ĐỊNH'
575
+
576
+ # Enhanced analysis based on content patterns
577
+ suspicious_patterns = []
578
+ if fake_score > 0:
579
+ suspicious_patterns.append(f"Tìm thấy {fake_score} từ khóa nghi ngờ")
580
+ if real_score > 0:
581
+ suspicious_patterns.append(f"Tìm thấy {real_score} từ khóa xác thực")
582
+
583
+ warning_signs = []
584
+ if 'cảnh báo' in news_lower or 'nguy hiểm' in news_lower:
585
+ warning_signs.append("Sử dụng từ ngữ gây sợ hãi")
586
+ if 'ngay lập tức' in news_lower or 'khẩn cấp' in news_lower:
587
+ warning_signs.append("Tạo cảm giác cấp bách không cần thiết")
588
+ if len(news_text) < 100:
589
+ warning_signs.append("Tin tức quá ngắn, thiếu thông tin chi tiết")
590
+
591
+ fallback_analysis = f"""**1. KẾT LUẬN:** {conclusion}
592
+
593
  **2. PHÂN TÍCH CHI TIẾT:**
594
  - **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'}
595
  - **Nguồn tin:** Google Search không khả dụng (hết quota) - không thể kiểm tra nguồn
 
619
  return f"Lỗi phân tích Gemini: {e}"
620
 
621
  def calculate_combined_confidence(distilbert_prediction, distilbert_confidence, source_credibility, popularity_score, gemini_analysis, source_support=0.5):
622
+ """Calculate combined confidence using weighted approach:
623
+ - DistilBERT: 30% weight
624
+ - Gemini AI: 30% weight
625
+ - Google Search (source credibility + support): 20% weight
626
+ - Other factors: 20% weight
627
+ """
628
 
629
+ # 1. DISTILBERT SCORE (30% weight)
630
  if distilbert_prediction == "REAL":
631
+ distilbert_score = distilbert_confidence
632
  else:
633
+ distilbert_score = 1 - distilbert_confidence
634
 
635
+ print(f"DistilBERT Score: {distilbert_score:.3f} (30% weight)")
636
+
637
+ # 2. GEMINI AI SCORE (30% weight)
638
+ gemini_lower = gemini_analysis.lower()
639
+
640
+ # Try to extract percentage from Gemini analysis first
641
+ gemini_real_percent, gemini_fake_percent = extract_gemini_percentage(gemini_analysis)
642
 
643
+ if gemini_real_percent is not None and gemini_fake_percent is not None:
644
+ # Use the extracted percentage directly
645
+ gemini_score = gemini_real_percent
646
+ print(f"Gemini Score (from percentage): {gemini_score:.3f} (30% weight) - {gemini_real_percent:.1%} real, {gemini_fake_percent:.1%} fake")
 
647
  else:
648
+ # Fallback to conclusion analysis
649
+ conclusion_score = 0.5 # Default neutral
650
+ if "**kết luận:** giả" in gemini_lower or "kết luận:** fake" in gemini_lower or "kết luận:** giả" in gemini_lower:
651
+ conclusion_score = 0.1 # Very low for FAKE
652
+ print("Gemini Conclusion: FAKE")
653
+ elif "**kết luận:** thật" in gemini_lower or "kết luận:** real" in gemini_lower or "kết luận:** thật" in gemini_lower:
654
+ conclusion_score = 0.9 # Very high for REAL
655
+ print("Gemini Conclusion: REAL")
656
+ elif "giả" in gemini_lower and "kết luận" in gemini_lower:
657
+ # Check if "giả" appears near "kết luận"
658
+ conclusion_start = gemini_lower.find("kết luận")
659
+ if conclusion_start != -1:
660
+ conclusion_section = gemini_lower[conclusion_start:conclusion_start + 50]
661
+ if "giả" in conclusion_section:
662
+ conclusion_score = 0.1
663
+ print("Gemini Conclusion: FAKE (detected in conclusion section)")
664
+ elif "thật" in conclusion_section:
665
+ conclusion_score = 0.9
666
+ print("Gemini Conclusion: REAL (detected in conclusion section)")
667
+
668
+ # Additional analysis indicators
669
+ fake_indicators = ["giả", "fake", "vô lý", "phi thực tế", "absurd", "preposterous", "impossible",
670
+ "không thể xảy ra", "không có căn cứ", "tin giả"]
671
+ real_indicators = ["thật", "real", "chính xác", "đúng", "xác nhận", "verified", "đáng tin cậy"]
672
+
673
+ fake_count = sum(1 for indicator in fake_indicators if indicator in gemini_lower)
674
+ real_count = sum(1 for indicator in real_indicators if indicator in gemini_lower)
675
+
676
+ # Adjust based on analysis indicators (but conclusion takes priority)
677
+ if fake_count > real_count:
678
+ analysis_adjustment = -0.2
679
+ print(f"Gemini Analysis: {fake_count} fake indicators vs {real_count} real indicators")
680
+ elif real_count > fake_count:
681
+ analysis_adjustment = 0.2
682
+ print(f"Gemini Analysis: {real_count} real indicators vs {fake_count} fake indicators")
683
+ else:
684
+ analysis_adjustment = 0.0
685
+
686
+ gemini_score = max(0.1, min(0.9, conclusion_score + analysis_adjustment))
687
+ print(f"Gemini Score (from conclusion): {gemini_score:.3f} (30% weight)")
688
+
689
+ # 3. GOOGLE SEARCH SCORE (20% weight - source credibility + support)
690
+ # Source credibility component (10%)
691
+ credibility_component = source_credibility * 0.5 # Convert to 0-0.5 scale
692
+
693
+ # Source support component (10%)
694
+ support_component = source_support * 0.5 # Convert to 0-0.5 scale
695
 
696
+ google_search_score = credibility_component + support_component + 0.5 # Add base 0.5 for neutral
697
+
698
+ # If Gemini strongly says FAKE, reduce Google Search score
699
+ if gemini_score < 0.3: # Gemini says FAKE (low score)
700
+ google_search_score = min(google_search_score, 0.4) # Cap at 0.4 when Gemini says fake
701
+ print(f"Google Search Score: {google_search_score:.3f} (20% weight) - Credibility: {source_credibility:.2f}, Support: {source_support:.2f} - CAPPED due to Gemini FAKE")
702
  else:
703
+ print(f"Google Search Score: {google_search_score:.3f} (20% weight) - Credibility: {source_credibility:.2f}, Support: {source_support:.2f}")
704
 
705
+ # 4. OTHER FACTORS (20% weight - popularity, etc.)
706
+ other_factors_score = popularity_score * 0.4 + 0.6 # Convert popularity to 0.6-1.0 scale
707
+
708
+ # If Gemini strongly says FAKE, reduce Other Factors score
709
+ if gemini_score < 0.3: # Gemini says FAKE (low score)
710
+ other_factors_score = min(other_factors_score, 0.5) # Cap at 0.5 when Gemini says fake
711
+ print(f"Other Factors Score: {other_factors_score:.3f} (20% weight) - Popularity: {popularity_score:.2f} - CAPPED due to Gemini FAKE")
712
  else:
713
+ print(f"Other Factors Score: {other_factors_score:.3f} (20% weight) - Popularity: {popularity_score:.2f}")
714
+
715
+ # 5. COMBINE WITH WEIGHTS
716
+ final_confidence = (
717
+ distilbert_score * 0.30 + # DistilBERT: 30%
718
+ gemini_score * 0.30 + # Gemini AI: 30%
719
+ google_search_score * 0.20 + # Google Search: 20%
720
+ other_factors_score * 0.20 # Other factors: 20%
721
+ )
722
+
 
 
 
 
 
 
 
 
 
 
723
  final_confidence = max(0.05, min(0.95, final_confidence))
724
 
725
+ print(f"Final Weighted Confidence: {final_confidence:.3f}")
726
+ print(f" - DistilBERT (30%): {distilbert_score:.3f} × 0.30 = {distilbert_score * 0.30:.3f}")
727
+ print(f" - Gemini (30%): {gemini_score:.3f} × 0.30 = {gemini_score * 0.30:.3f}")
728
+ print(f" - Google Search (20%): {google_search_score:.3f} × 0.20 = {google_search_score * 0.20:.3f}")
729
+ print(f" - Other Factors (20%): {other_factors_score:.3f} × 0.20 = {other_factors_score * 0.20:.3f}")
730
+
731
  return final_confidence
732
 
733
  def analyze_news(news_text):