File size: 7,209 Bytes
98c2b46 |
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 |
# logic_analyzer.py (V2 - Adım 2.4 Düzeltmesi - Fonksiyon Adı Hatası Giderildi)
import spacy
from spacy.tokens import Doc, Span
from typing import List, Dict, Tuple
import data_models # Düz yapı importu
import nlp_utils # Embedding fonksiyonları için
import torch
import torch.nn as nn
from rich.console import Console
console = Console()
# --- Basit Kural Tabanlı Safsata İpuçları (Aynı) ---
POPULUM_INDICATORS = {
"everybody knows", "everyone knows", "everyone agrees",
"it is common sense", "most people think", "the majority believes"
}
HASTY_GENERALIZATION_KEYWORDS = {"always", "never", "all", "none", "every", "everyone", "nobody"}
def check_false_dichotomy(sent_text_lower: str) -> bool:
has_either = " either " in f" {sent_text_lower} " or sent_text_lower.startswith("either ")
has_or = " or " in f" {sent_text_lower} "
return has_either and has_or
# Kural Tabanlı Tespit Fonksiyonları (Aynı)
def detect_ad_populum(sent: Span) -> List[data_models.Finding]:
findings = []; sent_text_lower = sent.text.lower()
for indicator in POPULUM_INDICATORS:
if indicator in sent_text_lower:
findings.append(data_models.Finding(finding_type="Fallacy", description="Potential 'Appeal to Popularity' (Ad Populum / Bandwagon) detected by rule.", severity="Medium", span_start=sent.start_char, span_end=sent.end_char, details={"fallacy_type": "Ad Populum (Rule)", "trigger": indicator})); break
return findings
def detect_hasty_generalization(sent: Span) -> List[data_models.Finding]:
findings = []
for token in sent:
if token.text.lower() in HASTY_GENERALIZATION_KEYWORDS:
findings.append(data_models.Finding(finding_type="Fallacy", description="Potential 'Hasty Generalization' detected by keyword rule (needs context!).", severity="Low", span_start=sent.start_char, span_end=sent.end_char, details={"fallacy_type": "Hasty Generalization (Rule)", "trigger": token.text})); break
return findings
def detect_false_dichotomy(sent: Span) -> List[data_models.Finding]:
findings = []; sent_text_lower = sent.text.lower()
if check_false_dichotomy(sent_text_lower):
findings.append(data_models.Finding(finding_type="Fallacy", description="Potential 'False Dichotomy' (Either/Or Fallacy) detected by rule.", severity="Medium", span_start=sent.start_char, span_end=sent.end_char, details={"fallacy_type": "False Dichotomy (Rule)", "trigger": "either...or pattern"}))
return findings
# --- ML Tabanlı Safsata Tespiti (Placeholder - Fonksiyon adı düzeltildi) ---
FALLACY_CLASSES = ["Ad Hominem", "Hasty Generalization", "Appeal to Popularity", "No Fallacy"]
BERT_HIDDEN_SIZE = 768; NUM_FALLACY_CLASSES = len(FALLACY_CLASSES)
class FallacyClassifierPlaceholder(nn.Module):
def __init__(self, input_size=BERT_HIDDEN_SIZE, num_classes=NUM_FALLACY_CLASSES):
super().__init__(); self.linear = nn.Linear(input_size, num_classes)
# Bu mesajın sadece bir kere görünmesi için kontrol eklenebilir ama şimdilik kalsın
console.print("[yellow]Placeholder Fallacy Classifier initialized (UNTRAINED). Results will NOT be accurate.[/yellow]", style="dim")
def forward(self, sentence_embedding):
if sentence_embedding.dim() == 1: sentence_embedding = sentence_embedding.unsqueeze(0)
logits = self.linear(sentence_embedding); return logits
try:
placeholder_classifier = FallacyClassifierPlaceholder()
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
placeholder_classifier.to(device); placeholder_classifier.eval()
_ml_classifier_loaded = True
except Exception as e:
console.print(f"[bold red]Error initializing ML Fallacy Classifier: {e}. ML detection disabled.[/bold red]")
_ml_classifier_loaded = False
def ml_fallacy_detection_for_sentence(sentence_text: str, sent_span: Span) -> List[data_models.Finding]: # Span eklendi
"""
Tek bir cümle için BERT embedding'i alır ve EĞİTİLMEMİŞ sınıflandırıcı ile
safsata tahmini yapar (PLACEHOLDER - DOĞRU SONUÇ VERMEZ).
Span bilgisi eklendi.
"""
findings = []
if not _ml_classifier_loaded: return findings # Sınıflandırıcı yüklenemediyse boş dön
try:
# DÜZELTME: Doğru fonksiyon adını kullan: get_sentence_embedding (tekil)
sentence_embedding = nlp_utils.get_sentence_embedding(sentence_text, strategy='mean')
if sentence_embedding is None: # Embedding alınamadıysa
return findings
sentence_embedding = sentence_embedding.to(device)
with torch.no_grad(): logits = placeholder_classifier(sentence_embedding)
probabilities = torch.softmax(logits.squeeze(), dim=0)
predicted_prob, predicted_idx = torch.max(probabilities, dim=0)
predicted_class = FALLACY_CLASSES[predicted_idx.item()]
predicted_prob = predicted_prob.item()
# Sadece "No Fallacy" olmayanları ekle (güvenilmez skorla)
if predicted_class != "No Fallacy":
findings.append(data_models.Finding(
finding_type="Fallacy",
description=f"Potential '{predicted_class}' detected by ML Placeholder (Score: {predicted_prob:.2f} - UNRELIABLE).",
severity="Low",
span_start=sent_span.start_char, # Doğru span bilgisi kullanıldı
span_end=sent_span.end_char, # Doğru span bilgisi kullanıldı
details={"fallacy_type": f"{predicted_class} (ML Placeholder)", "confidence": predicted_prob}
))
except Exception as e:
console.print(f"[yellow]Warning: ML Fallacy prediction failed for sentence: {e}[/yellow]", style="dim")
return findings
# --- Geliştirilmiş Ana Analiz Fonksiyonu (Düzeltilmiş Hali) ---
def enhanced_fallacy_analyzer(doc: Doc) -> List[data_models.Finding]:
"""
Metindeki cümleleri hem basit kurallarla hem de ML Placeholder ile
analiz ederek potansiyel safsataları bulur (V2 Seviyesi).
"""
all_findings = []
console.print(" -> Running Rule-Based Fallacy Checks...", style="dim")
sentences = list(doc.sents)
for sent in sentences:
all_findings.extend(detect_ad_populum(sent))
all_findings.extend(detect_hasty_generalization(sent))
all_findings.extend(detect_false_dichotomy(sent))
if _ml_classifier_loaded: # ML sınıflandırıcı yüklendiyse çalıştır
console.print(f" -> Running ML Placeholder Fallacy Checks ({len(sentences)} sentences)...", style="dim")
for sent in sentences:
# ml_fallacy_detection_for_sentence'a artık span'ı da gönderiyoruz
all_findings.extend(ml_fallacy_detection_for_sentence(sent.text, sent))
else:
console.print(" -> Skipping ML Placeholder Fallacy Checks (Initialization failed).", style="dim")
# TODO: Bulguları birleştirme / önceliklendirme
console.print(f" -> Enhanced Fallacy Analyzer found {len(all_findings)} potential indicators (Rules + ML Placeholder).", style="dim")
return all_findings |