|
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 |
|
|
|
|
|
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) |
|
|
|
|
|
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) |
|
|
|
|
|
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) |
|
|
|
|
|
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) |
|
|
|
|
|
combined = self.layer_norm2(torch.cat([attn_out, mean_emb], dim=1)) |
|
fused = self.context_fusion(combined) |
|
return self.sentiment_classifier(fused) |
|
|
|
|
|
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 = AutoTokenizer.from_pretrained("dbbiyte/histurk-BERTurk-sentiment") |
|
|
|
|
|
model = HistTurkSentiment() |
|
|
|
|
|
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""" |
|
|
|
|
|
if not text or not text.strip(): |
|
return "❌ Lütfen analiz edilecek bir metin girin!" |
|
|
|
try: |
|
|
|
load_model() |
|
|
|
|
|
inputs = tokenizer( |
|
text, |
|
return_tensors="pt", |
|
truncation=True, |
|
padding=True, |
|
max_length=256, |
|
return_token_type_ids=False |
|
) |
|
|
|
|
|
with torch.no_grad(): |
|
logits = model(**inputs) |
|
probs = F.softmax(logits, dim=-1) |
|
pred_idx = probs.argmax().item() |
|
confidence = probs[0][pred_idx].item() |
|
|
|
|
|
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)}" |
|
|
|
|
|
def create_interface(): |
|
|
|
|
|
css = """ |
|
.gradio-container { |
|
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; |
|
} |
|
.prose h2 { |
|
color: #2563eb; |
|
border-bottom: 2px solid #3b82f6; |
|
padding-bottom: 5px; |
|
} |
|
""" |
|
|
|
|
|
examples = [ |
|
|
|
["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."] |
|
|
|
] |
|
|
|
|
|
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 |
|
|
|
|
|
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 |
|
) |