File size: 7,681 Bytes
3aae6cf
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
dc6cbb4
 
3aae6cf
 
 
 
 
 
 
dc6cbb4
3aae6cf
 
 
 
 
 
d98d2a2
3aae6cf
dc6cbb4
3aae6cf
d98d2a2
 
 
 
3aae6cf
d98d2a2
dc6cbb4
 
d98d2a2
 
 
3aae6cf
d98d2a2
 
 
 
 
3aae6cf
 
 
d98d2a2
3aae6cf
 
 
 
 
 
 
 
 
 
 
 
 
 
dc6cbb4
3aae6cf
 
 
 
 
 
 
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
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
import gradio as gr
import torch
import torch.nn as nn
import torch.nn.functional as F
from transformers import AutoTokenizer, AutoModel
from huggingface_hub import hf_hub_download

# Model sınıfını tanımla
class HistTurkSentiment(nn.Module):
    def __init__(self):
        super().__init__()
        self.bert = AutoModel.from_pretrained('dbmdz/bert-base-turkish-cased', add_pooling_layer=False)
        hidden_size = self.bert.config.hidden_size
        
        self.multihead_attn = nn.MultiheadAttention(hidden_size, 8, dropout=0.1)
        self.layer_norm1 = nn.LayerNorm(hidden_size)
        self.layer_norm2 = nn.LayerNorm(hidden_size * 2)
        
        self.context_fusion = nn.Sequential(
            nn.Linear(hidden_size * 2, hidden_size), 
            nn.LayerNorm(hidden_size), 
            nn.GELU(),
            nn.Dropout(0.1), 
            nn.Linear(hidden_size, hidden_size), 
            nn.LayerNorm(hidden_size)
        )
        
        self.sentiment_classifier = nn.Sequential(
            nn.Linear(hidden_size, hidden_size // 2), 
            nn.LayerNorm(hidden_size // 2), 
            nn.GELU(), 
            nn.Dropout(0.1), 
            nn.Linear(hidden_size // 2, 3)
        )
    
    def forward(self, input_ids, attention_mask):
        outputs = self.bert(input_ids=input_ids, attention_mask=attention_mask, output_hidden_states=True)
        
        # Layer ensemble
        layers = torch.stack(outputs.hidden_states[-4:])
        weights = torch.tensor([0.1, 0.2, 0.3, 0.4], device=input_ids.device).view(4, 1, 1, 1)
        final_output = (layers * weights).sum(dim=0)
        
        # Embeddings
        cls_emb = F.normalize(final_output[:, 0, :], p=2, dim=1)
        mask = attention_mask.unsqueeze(-1).float()
        mean_emb = F.normalize((final_output * mask).sum(dim=1) / mask.sum(dim=1).clamp(min=1e-9), p=2, dim=1)
        
        # Attention
        q, k, v = cls_emb.unsqueeze(0), final_output.transpose(0, 1), final_output.transpose(0, 1)
        attn_out = self.multihead_attn(q, k, v)[0].squeeze(0)
        attn_out = self.layer_norm1(attn_out + cls_emb)
        
        # Fusion
        combined = self.layer_norm2(torch.cat([attn_out, mean_emb], dim=1))
        fused = self.context_fusion(combined)
        return self.sentiment_classifier(fused)

# Global değişkenler
tokenizer = None
model = None

def load_model():
    """Model ve tokenizer'ı yükle (bir kez)"""
    global tokenizer, model
    
    if model is None:
        print("Model yükleniyor...")
        
        # Tokenizer yükle
        tokenizer = AutoTokenizer.from_pretrained("dbbiyte/histurk-BERTurk-sentiment")
        
        # Model oluştur
        model = HistTurkSentiment()
        
        # Weights indir ve yükle
        weights_path = hf_hub_download("dbbiyte/histurk-BERTurk-sentiment", "pytorch_model.bin")
        model.load_state_dict(torch.load(weights_path, map_location='cpu'))
        model.eval()
        
        print("Model başarıyla yüklendi!")

def predict_sentiment(text):
    """Ana tahmin fonksiyonu"""
    
    # Boş metin kontrolü
    if not text or not text.strip():
        return "❌ Lütfen analiz edilecek bir metin girin!"
    
    try:
        # Model yükle (ilk kez çağırıldığında)
        load_model()
        
        # Tokenize et
        inputs = tokenizer(
            text, 
            return_tensors="pt", 
            truncation=True, 
            padding=True,
            max_length=256, 
            return_token_type_ids=False
        )
        
        # Tahmin yap
        with torch.no_grad():
            logits = model(**inputs)
            probs = F.softmax(logits, dim=-1)
            pred_idx = probs.argmax().item()
            confidence = probs[0][pred_idx].item()
        
        # Sonuçları formatla
        labels = ["Negatif", "Nötr", "Pozitif"]
        icons = ["😞", "😐", "😊"]
        
        result_text = f"""
## 🎯 Analiz Sonucu

### {icons[pred_idx]} **{labels[pred_idx]}** Sentiment

**Güven Skoru:** %{confidence*100:.1f}

---

### 📊 Detaylı Skorlar:
- **Negatif:** %{probs[0][0].item()*100:.1f}
- **Nötr:** %{probs[0][1].item()*100:.1f}  
- **Pozitif:** %{probs[0][2].item()*100:.1f}
        """
        
        return result_text
        
    except Exception as e:
        return f"❌ **Hata oluştu:** {str(e)}"

# Gradio arayüzü
def create_interface():
    
    # CSS stilleri
    css = """
    .gradio-container {
        font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
    }
    .prose h2 {
        color: #2563eb;
        border-bottom: 2px solid #3b82f6;
        padding-bottom: 5px;
    }
    """
    
    # Örnek metinler - 20. yüzyıl başı Türkçesi ve modern karışımı
    examples = [
        # 20. yüzyıl başı Türkçesi örnekleri
        ["Bu müessif ahval-i hazıra karşısında kalbimin hüzn ü melali had ü hesaba gelmeyub, devlet-i aliyyenin bu derece inhitat ve tedennisi beni gayet müteessir ve mahzun eylemiştir."],
        ["Pek mübarek ve mes'ud bir gün idi. Cennet-mekan Padişahımızın cülus-ı hümayunları münasebetiyle bütün tebaası kemâl-i sürur ve şadmanlık içinde bulunuyordu."],
        ["Bu kitab-ı mufîdin mütalaasından istifade-i azîme hâsıl olmuş ve ilm ü marifetimde tezayüd vuku bulmuştur. Müellif-i muhteremi hakkında duâ-yı hayr ile yâd eylerim."],
        ["Böyle bir hâdise-i elîmenin vukuu beni pek müteessir etmiş ve kalb-i âcizanemde derin bir teessür bırakmıştır. Allah her müslümânı böyle belâlardan muhafaza buyursun."],
        ["İş bu mes'ele-i mühimme hakkında düşündükçe efkâr-ı âcizanem daha ziyade karışmakta ve ne suretle hal edilebileceğini tayin edemez bir hale gelmekteyim."]
        
    ]
    
    # Arayüz oluştur
    interface = gr.Interface(
        fn=predict_sentiment,
        inputs=gr.Textbox(
            label="📝 Analiz Edilecek Metin",
            placeholder="Duygu analizini yapmak istediğiniz Türkçe metni buraya yazın...",
            lines=4,
            max_lines=10
        ),
        outputs=gr.Markdown(
            label="🎯 Analiz Sonucu"
        ),
        title="🤖 histurk-BERTurk-Sentiment Modeli Demosudur",
        description="""
        Bu uygulama, **Tarihi Türkçe-Osmanlıca metinler** için özel olarak geliştirilmiş BERT tabanlı bir sentiment analizi modeli kullanır.
        
        ### 🕰️ Tarihi Metin Desteği:
        • 20. yüzyıl başı Osmanlı Türkçesi  
        • Geçiş dönemi metinleri  
        • Modern Türkçe metinler
        
        ### 📚 Örnek Kullanım Alanları:
        • Tarihi belgeler ve mektuplar 
        • Hatıratlar, biyografiler 
        • Gazete arşivleri (1900-1950)  
        • Edebi eserler  
        • Sosyal medya ve modern metinler
        
        ### 🎯 Özellikler:
        • Tarihi dil yapılarını anlayabilir  
        • Osmanlıca kelime ve tamlamaları tanır  
        • Gerçek zamanlı analiz  
        • Detaylı güven skorları
        
        **Model:** `dbbiyte/histurk-BERTurk-sentiment`
        """,
        
        examples=examples,
        cache_examples=False,
        theme=gr.themes.Soft(
            primary_hue="blue",
            secondary_hue="gray"
        ),
        css=css,
        allow_flagging="never"
    )
    
    return interface

# Uygulamayı başlat
if __name__ == "__main__":
    print("🚀 HistTürk Duygu Analizi başlatılıyor...")
    
    interface = create_interface()
    interface.launch(
        share=False,
        server_name="0.0.0.0",
        server_port=7860
    )