Sarpyy commited on
Commit
45c5dff
·
verified ·
1 Parent(s): c66a944

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +199 -0
app.py ADDED
@@ -0,0 +1,199 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import torch
3
+ import pandas as pd
4
+ import gradio as gr
5
+ from collections import defaultdict
6
+ from transformers import AutoTokenizer, AutoModelForTokenClassification
7
+
8
+ # =========================================================================
9
+ # 1. Sabitler ve Model Yükleme
10
+ # =========================================================================
11
+
12
+ # Hugging Face Hub'daki Lemmatization modelinizin ID'si
13
+ HF_MODEL_ID = "LiProject/BERT-Turkish-Lemmatization-V2"
14
+
15
+ # GPU/CPU kontrolü
16
+ DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
17
+
18
+ try:
19
+ # Model ve Tokenizer'ı HF Hub'dan yükle
20
+ tok = AutoTokenizer.from_pretrained(HF_MODEL_ID, use_fast=True)
21
+ mdl = AutoModelForTokenClassification.from_pretrained(HF_MODEL_ID).to(DEVICE).eval()
22
+ print(f"Model yükleme başarılı: {HF_MODEL_ID} ({DEVICE} üzerinde)")
23
+
24
+ except Exception as e:
25
+ print(f"Model veya Tokenizer yüklenirken kritik hata oluştu: {e}")
26
+ exit(1)
27
+
28
+ # =========================================================================
29
+ # 2. Etiket (Lemma) Okuma Fonksiyonları
30
+ # =========================================================================
31
+
32
+ def build_id2label_from_config(cfg):
33
+ # Modelin config dosyasından id2label'ı güvenilir bir şekilde okur
34
+ n = getattr(cfg, "num_labels", None)
35
+ if n is None:
36
+ if isinstance(getattr(cfg, "id2label", None), dict): n = len(cfg.id2label)
37
+ elif isinstance(getattr(cfg, "label2id", None), dict): n = len(cfg.label2id)
38
+ else: raise ValueError("num_labels/id2label/label2id yok.")
39
+
40
+ labels = [f"LABEL_{i}" for i in range(n)]
41
+ id2label = getattr(cfg, "id2label", None)
42
+
43
+ if id2label:
44
+ if isinstance(id2label, dict):
45
+ for k,v in id2label.items():
46
+ try: i = int(k)
47
+ except:
48
+ try: i = int(float(k))
49
+ except: continue
50
+ if 0 <= i < n: labels[i] = str(v)
51
+ elif isinstance(id2label, (list,tuple)) and len(id2label)==n:
52
+ labels = [str(x) for x in id2label]
53
+
54
+ l2i = getattr(cfg, "label2id", None)
55
+ if isinstance(l2i, dict):
56
+ for lbl, idx_ in l2i.items():
57
+ try: i = int(idx_)
58
+ except:
59
+ try: i = int(float(idx_))
60
+ except: continue
61
+ if 0 <= i < n and labels[i].startswith("LABEL_"):
62
+ labels[i] = str(lbl)
63
+
64
+ for i,v in enumerate(labels):
65
+ if v.startswith("LABEL_"): labels[i] = str(i)
66
+
67
+ return labels
68
+
69
+ ID2LABEL = build_id2label_from_config(mdl.config)
70
+
71
+ # =========================================================================
72
+ # 3. Inference ve Çıktı Formatı
73
+ # =========================================================================
74
+
75
+ @torch.inference_mode()
76
+ def lemmatize_rows(multiline_text: str):
77
+ """Metni işler ve kelime bazlı kökleri içeren DataFrame döndürür."""
78
+ rows = []
79
+ sentences = [s.strip() for s in multiline_text.splitlines() if s.strip()]
80
+
81
+ if not sentences:
82
+ return pd.DataFrame(rows)
83
+
84
+ for sent in sentences:
85
+ enc = tok(sent, return_tensors="pt", truncation=True, add_special_tokens=True).to(DEVICE)
86
+ logits = mdl(**enc).logits[0]
87
+
88
+ fast = tok(sent, return_offsets_mapping=True, add_special_tokens=True)
89
+ word_ids = fast.word_ids()
90
+ offsets = fast["offset_mapping"]
91
+
92
+ idxs_by_word = defaultdict(list)
93
+ for i, wid in enumerate(word_ids):
94
+ if wid is not None:
95
+ idxs_by_word[wid].append(i)
96
+
97
+ for wid in sorted(idxs_by_word.keys()):
98
+ sub_idxs = idxs_by_word[wid]
99
+
100
+ start = offsets[sub_idxs[0]][0]
101
+ end = offsets[sub_idxs[-1]][1]
102
+ surface = sent[start:end] if (start is not None and end is not None) else ""
103
+
104
+ mean_logits = logits[sub_idxs].mean(dim=0)
105
+ pid = int(mean_logits.argmax().item())
106
+
107
+ # Modelin tahmin ettiği kök (lemma)
108
+ lemma = ID2LABEL[pid] if pid < len(ID2LABEL) else str(pid)
109
+
110
+ rows.append({"Full_Sentence": sent, "Word": surface, "Lemma": lemma})
111
+
112
+ return pd.DataFrame(rows)
113
+
114
+ def add_sentence_separators(df: pd.DataFrame, char: str = "-", repeat: int = 10) -> pd.DataFrame:
115
+ """Görünürlük için cümleler arasına ayraç satırları ekler."""
116
+ rows, prev = [], None
117
+ for _, r in df.iterrows():
118
+ if prev is not None and r["Full_Sentence"] != prev:
119
+ sep = char * repeat
120
+ rows.append({"Full_Sentence": sep, "Word": sep, "Lemma": sep})
121
+ rows.append(r.to_dict())
122
+ prev = r["Full_Sentence"]
123
+ return pd.DataFrame(rows)
124
+
125
+ def run_and_save(text):
126
+ """Ana çalıştırma fonksiyonu, tabloyu ve indirilebilir CSV'yi hazırlar."""
127
+ df = lemmatize_rows(text)
128
+ df_view = add_sentence_separators(df, char="-", repeat=10)
129
+
130
+ out_path = "lemma_output.csv"
131
+ df.to_csv(out_path, index=False)
132
+
133
+ return df_view, out_path
134
+
135
+ examples = [
136
+ "kedilerimizden biri çok hızlıca koştu",
137
+ "gözlükçüler dükkanlarını erkenden açtılar.",
138
+ "Bana hikayenin sonunu anlattılar."
139
+ ]
140
+
141
+ # =========================================================================
142
+ # 4. Gradio Arayüzü
143
+ # =========================================================================
144
+
145
+ theme = gr.themes.Soft(primary_hue="slate", neutral_hue="slate")
146
+ custom_css = """
147
+ /* Sayfa ve temel renkler */
148
+ .gradio-container { background: #000000 !important; color: #FFE8DB !important; font-family: Inter, ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, "Helvetica Neue", Arial, sans-serif; }
149
+ .prose h1, .prose h2, .prose h3, .prose p, label { color: #FFE8DB !important; }
150
+ .gr-box, .gr-panel, .border, .container { background: #0b0b0b !important; border: 1.5px solid #739EC9 !important; border-radius: 14px !important; }
151
+ textarea, input, .gr-textbox, .gr-file, .gr-form input, .gr-form textarea { background: #0f1a26 !important; color: #FFE8DB !important; border: 2px solid #5682B1 !important; border-radius: 12px !important; }
152
+ button { transition: background 0.15s ease, filter 0.15s ease, box-shadow 0.15s ease; }
153
+ button.primary, .btn-primary { background: #FFE8DB !important; color: #000000 !important; }
154
+ button.primary:hover, .btn-primary:hover { filter: brightness(0.92); }
155
+ button.secondary, .btn-secondary { background: rgba(86,130,177,0.15) !important; color: #FFE8DB !important; }
156
+ button.secondary:hover, .btn-secondary:hover { background: rgba(86,130,177,0.38) !important; border-color: #5682B1 !important; }
157
+ table { border-collapse: separate !important; border-spacing: 0 !important; }
158
+ th { background: #5682B1 !important; color: #FFE8DB !important; }
159
+ td { background: #0f1a26 !important; color: #FFE8DB !important; }
160
+ tbody tr:nth-child(2n) td { background: #122434 !important; }
161
+ #results_table { max-height: 360px !important; overflow: auto !important; }
162
+ #results_table table { table-layout: fixed !important; width: 100% !important; }
163
+ #results_table th, #results_table td { white-space: normal !important; word-break: break-word !important; }
164
+ #input_text textarea { min-height: 150px !important; }
165
+ """
166
+
167
+ with gr.Blocks(title="TR Lemmatizer", theme=theme, css=custom_css, fill_height=True) as demo:
168
+ gr.Markdown("# 🇹🇷 Türkçe Lemmatization (Kök Bulma)")
169
+ gr.Markdown(f"Model: `{HF_MODEL_ID.split('/')[-1]}`. Metni satır satır girin. Çıktı: **Full_Sentence, Word, Lemma**.")
170
+
171
+ with gr.Row():
172
+ with gr.Column(scale=3):
173
+ inp = gr.Textbox(
174
+ lines=6,
175
+ placeholder="Örn:\nKedilerimizden biri hızlıca koştu.\nGözlükçüler dükkanlarını açtılar.",
176
+ show_label=False,
177
+ elem_id="input_text"
178
+ )
179
+ with gr.Column(scale=1):
180
+ btn = gr.Button("Kökleri Bul ve CSV indir", variant="primary", elem_id="run_btn")
181
+ clr = gr.Button("Temizle", variant="secondary", elem_id="clear_btn")
182
+
183
+ out_tbl = gr.Dataframe(
184
+ headers=["Full_Sentence","Word","Lemma"],
185
+ label="Önizleme",
186
+ interactive=False,
187
+ elem_id="results_table"
188
+ )
189
+
190
+ out_file = gr.File(label="Çıktı CSV (lemma_output.csv)")
191
+
192
+ gr.Examples(examples=[[e] for e in examples], inputs=inp)
193
+
194
+ btn.click(run_and_save, inputs=inp, outputs=[out_tbl, out_file])
195
+ inp.submit(run_and_save, inputs=inp, outputs=[out_tbl, out_file])
196
+ clr.click(lambda: ("", None, None), outputs=[inp, out_tbl, out_file])
197
+
198
+ if __name__ == "__main__":
199
+ demo.launch(debug=True)