apak commited on
Commit
4a0642c
·
verified ·
1 Parent(s): 277caac

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +45 -49
app.py CHANGED
@@ -1,40 +1,23 @@
1
- import torch
2
  import wikipedia
3
  import gradio as gr
4
  from transformers import pipeline, AutoTokenizer, AutoModelForCausalLM
5
  from rapidfuzz import process, fuzz
6
  import re
 
 
7
 
8
  # -------------------------------
9
- # 1. MODELLER VE KÜRESEL AYARLAR
10
  # -------------------------------
 
11
 
12
- # Türkçe için daha iyi bir NER modeli (multilingual ve Türkçe performansı yüksek)
13
- NER_MODEL = "savasy/bert-base-turkish-ner-cased" # Alternatif: "dbmdz/bert-large-cased-finetuned-conll03-german" multilingual
14
  ner_pipe = pipeline(
15
  "ner",
16
  model=NER_MODEL,
17
  aggregation_strategy="simple",
18
- device=0 if torch.cuda.is_available() else -1
19
  )
20
 
21
- # LLM (Qwen2.5 1.5B - hafif ve hızlı)
22
- MODEL_ID = "Qwen/Qwen2.5-1.5B-Instruct"
23
- tokenizer = AutoTokenizer.from_pretrained(MODEL_ID, trust_remote_code=True)
24
-
25
- try:
26
- llm_model = AutoModelForCausalLM.from_pretrained(
27
- MODEL_ID,
28
- torch_dtype=torch.bfloat16 if torch.cuda.is_available() else torch.float32,
29
- device_map="auto",
30
- trust_remote_code=True
31
- )
32
- LLM_AVAILABLE = True
33
- except Exception as e:
34
- print(f"LLM yüklenemedi: {e}")
35
- llm_model = None
36
- LLM_AVAILABLE = False
37
-
38
  # Wikipedia Türkçe
39
  wikipedia.set_lang("tr")
40
 
@@ -52,27 +35,39 @@ CUSTOM_LABELS = {
52
  # -------------------------------
53
  # 2. YARDIMCI FONKSİYONLAR
54
  # -------------------------------
55
-
56
  def get_best_wiki_summary(entity):
57
  """Wikipedia'dan en uygun özeti getirir (fuzzy matching ile)"""
58
  try:
59
  candidates = wikipedia.search(entity, results=5)
60
  if not candidates:
61
  return None
62
- # En iyi eşleşeni seç
63
  best_title, score = process.extractOne(entity, candidates)
64
- if score < 60: # Eşleşme düşükse vazgeç
65
  return None
66
  return wikipedia.summary(best_title, sentences=2, auto_suggest=False)
67
  except:
68
  return None
69
 
70
- def batch_llm_refine(entities_data):
71
- """Birden fazla varlığı tek prompt'ta analiz eder (batch processing)"""
72
- if not LLM_AVAILABLE or not entities_data:
73
- return {e["entity"]: ("MISC", "LLM kullanılamıyor") for e in entities_data}
74
 
75
- device = next(llm_model.parameters()).device
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
76
 
77
  # Prompt hazırlığı
78
  label_rules = ""
@@ -89,28 +84,24 @@ GÖREV {i}:
89
  """
90
 
91
  prompt = f"""Sen bir NER uzmanısın. Aşağıdaki varlıkları sırayla analiz et ve her biri için sadece etiketi ver.
92
-
93
  ETİKET KURALLARI:
94
  {label_rules}
95
-
96
  FEW-SHOT ÖRNEK:
97
  VARLIK: Inception | CÜMLE: Inception filmini izledim | WIKI: Christopher Nolan filmi → MOVIE
98
  VARLIK: 1984 | CÜMLE: Orwell'in kitabı 1984 | WIKI: Roman → BOOK
99
  VARLIK: iPhone | CÜMLE: Yeni iPhone aldım | WIKI: Apple telefonu → PRODUCT
100
-
101
  Şimdi görevler:
102
  {tasks}
103
-
104
  ÇIKTI FORMATI (her satır bir görev):
105
  GÖREV X: [ETIKET]
106
  """
107
 
108
  messages = [{"role": "user", "content": prompt}]
109
  text = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
110
- inputs = tokenizer([text], return_tensors="pt").to(device)
111
 
112
  with torch.no_grad():
113
- generated = llm_model.generate(
114
  inputs.input_ids,
115
  max_new_tokens=512,
116
  temperature=0.1,
@@ -125,22 +116,26 @@ GÖREV X: [ETIKET]
125
  pattern = rf"GÖREV {i}:\s*([A-Z_]+)"
126
  match = re.search(pattern, response)
127
  label = match.group(1) if match and match.group(1) in CUSTOM_LABELS else "MISC"
128
- results[item["entity"]] = (label, response) # Tüm analiz metni ortak
 
 
 
 
 
129
  return results
130
 
 
131
  # -------------------------------
132
- # 3. ANA İŞLEM
133
  # -------------------------------
134
-
135
  def process_ner(text):
136
  logs = ["🚀 Analiz başlatıldı..."]
137
  yield "<br>".join(logs), []
138
 
139
- # NER ile varlıkları çıkar
140
  raw_entities = ner_pipe(text)
141
  misc_entities = []
142
-
143
  results = []
 
144
  for ent in raw_entities:
145
  word = ent['word'].strip()
146
  label = ent['entity_group']
@@ -148,27 +143,28 @@ def process_ner(text):
148
  if label in ["PER", "ORG", "LOC"]:
149
  results.append({"Varlık": word, "İlk": label, "Nihai": label, "Kaynak": "NER Model"})
150
  logs.append(f"✅ <b>{word}</b> → {label} (doğrudan)")
151
- else: # MISC veya bilinmeyen
152
  wiki = get_best_wiki_summary(word)
153
  if wiki:
154
  logs.append(f"🌐 <b>{word}</b> için Wiki bulundu")
155
  else:
156
  logs.append(f"⚠️ <b>{word}</b> için Wiki bulunamadı")
157
  results.append({"Varlık": word, "İlk": "MISC", "Nihai": "MISC", "Kaynak": "Fallback"})
 
158
  misc_entities.append({"entity": word, "sentence": text, "wiki": wiki})
159
 
160
  yield "<br>".join(logs), [[r["Varlık"], r["İlk"], f"<b>{r['Nihai']}</b>", r["Kaynak"]] for r in results]
161
 
162
- # Batch LLM rafinasyonu
163
- if misc_entities and LLM_AVAILABLE:
164
- logs.append("🧠 LLM ile toplu analiz yapılıyor...")
165
  yield "<br>".join(logs), [[r["Varlık"], r["İlk"], f"<b>{r['Nihai']}</b>", r["Kaynak"]] for r in results]
166
 
167
  refined = batch_llm_refine(misc_entities)
 
168
  for item in misc_entities:
169
  entity = item["entity"]
170
  new_label, _ = refined.get(entity, ("MISC", ""))
171
- # Sonuçları güncelle
172
  for r in results:
173
  if r["Varlık"] == entity:
174
  r["Nihai"] = new_label
@@ -177,13 +173,13 @@ def process_ner(text):
177
  logs.append("✨ Analiz tamamlandı!")
178
  yield "<br>".join(logs), [[r["Varlık"], r["İlk"], f"<b>{r['Nihai']}</b>", r["Kaynak"]] for r in results]
179
 
 
180
  # -------------------------------
181
- # 4. GRADIO ARAYÜZ
182
  # -------------------------------
183
-
184
  with gr.Blocks(title="RAG-NER Türkçe", theme=gr.themes.Soft()) as demo:
185
  gr.Markdown("# 🇹🇷 RAG-NER: Gelişmiş Türkçe Varlık Tanılama")
186
- gr.Markdown("Standart NER + Wikipedia + Yerel LLM ile yüksek doğruluklu özel varlık tanıma")
187
 
188
  with gr.Tab("Analiz"):
189
  txt_input = gr.Textbox(
 
 
1
  import wikipedia
2
  import gradio as gr
3
  from transformers import pipeline, AutoTokenizer, AutoModelForCausalLM
4
  from rapidfuzz import process, fuzz
5
  import re
6
+ import torch
7
+ import spaces # <<< ZeroGPU için zorunlu
8
 
9
  # -------------------------------
10
+ # 1. NER MODELİ (CPU'da çalışacak - global)
11
  # -------------------------------
12
+ NER_MODEL = "savasy/bert-base-turkish-ner-cased"
13
 
 
 
14
  ner_pipe = pipeline(
15
  "ner",
16
  model=NER_MODEL,
17
  aggregation_strategy="simple",
18
+ device=-1 # Zorla CPU (ZeroGPU startup'ta GPU yok)
19
  )
20
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
  # Wikipedia Türkçe
22
  wikipedia.set_lang("tr")
23
 
 
35
  # -------------------------------
36
  # 2. YARDIMCI FONKSİYONLAR
37
  # -------------------------------
 
38
  def get_best_wiki_summary(entity):
39
  """Wikipedia'dan en uygun özeti getirir (fuzzy matching ile)"""
40
  try:
41
  candidates = wikipedia.search(entity, results=5)
42
  if not candidates:
43
  return None
 
44
  best_title, score = process.extractOne(entity, candidates)
45
+ if score < 60:
46
  return None
47
  return wikipedia.summary(best_title, sentences=2, auto_suggest=False)
48
  except:
49
  return None
50
 
 
 
 
 
51
 
52
+ # -------------------------------
53
+ # 3. LLM RAFİNASYON (GPU'da çalışacak - decorator ile)
54
+ # -------------------------------
55
+ @spaces.GPU(duration=120) # Gerekirse süreyi artır (max ~300 saniye)
56
+ def batch_llm_refine(entities_data):
57
+ """Birden fazla varlığı tek prompt'ta analiz eder (LLM sadece burada GPU'da yüklenir)"""
58
+ if not entities_data:
59
+ return {e["entity"]: ("MISC", "Boş veri") for e in entities_data}
60
+
61
+ # Modeli sadece burada yükle (GPU mevcut)
62
+ MODEL_ID = "Qwen/Qwen2.5-1.5B-Instruct"
63
+ tokenizer = AutoTokenizer.from_pretrained(MODEL_ID, trust_remote_code=True)
64
+ model = AutoModelForCausalLM.from_pretrained(
65
+ MODEL_ID,
66
+ torch_dtype=torch.bfloat16,
67
+ device_map=None, # Manuel taşıyacağız
68
+ trust_remote_code=True
69
+ )
70
+ model.to("cuda") # ZeroGPU'da burada GPU tahsis edilmiş olur
71
 
72
  # Prompt hazırlığı
73
  label_rules = ""
 
84
  """
85
 
86
  prompt = f"""Sen bir NER uzmanısın. Aşağıdaki varlıkları sırayla analiz et ve her biri için sadece etiketi ver.
 
87
  ETİKET KURALLARI:
88
  {label_rules}
 
89
  FEW-SHOT ÖRNEK:
90
  VARLIK: Inception | CÜMLE: Inception filmini izledim | WIKI: Christopher Nolan filmi → MOVIE
91
  VARLIK: 1984 | CÜMLE: Orwell'in kitabı 1984 | WIKI: Roman → BOOK
92
  VARLIK: iPhone | CÜMLE: Yeni iPhone aldım | WIKI: Apple telefonu → PRODUCT
 
93
  Şimdi görevler:
94
  {tasks}
 
95
  ÇIKTI FORMATI (her satır bir görev):
96
  GÖREV X: [ETIKET]
97
  """
98
 
99
  messages = [{"role": "user", "content": prompt}]
100
  text = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
101
+ inputs = tokenizer([text], return_tensors="pt").to("cuda")
102
 
103
  with torch.no_grad():
104
+ generated = model.generate(
105
  inputs.input_ids,
106
  max_new_tokens=512,
107
  temperature=0.1,
 
116
  pattern = rf"GÖREV {i}:\s*([A-Z_]+)"
117
  match = re.search(pattern, response)
118
  label = match.group(1) if match and match.group(1) in CUSTOM_LABELS else "MISC"
119
+ results[item["entity"]] = (label, response)
120
+
121
+ # Belleği temizle
122
+ del model, tokenizer, inputs, generated
123
+ torch.cuda.empty_cache()
124
+
125
  return results
126
 
127
+
128
  # -------------------------------
129
+ # 4. ANA İŞLEM (CPU + GPU karışık)
130
  # -------------------------------
 
131
  def process_ner(text):
132
  logs = ["🚀 Analiz başlatıldı..."]
133
  yield "<br>".join(logs), []
134
 
 
135
  raw_entities = ner_pipe(text)
136
  misc_entities = []
 
137
  results = []
138
+
139
  for ent in raw_entities:
140
  word = ent['word'].strip()
141
  label = ent['entity_group']
 
143
  if label in ["PER", "ORG", "LOC"]:
144
  results.append({"Varlık": word, "İlk": label, "Nihai": label, "Kaynak": "NER Model"})
145
  logs.append(f"✅ <b>{word}</b> → {label} (doğrudan)")
146
+ else:
147
  wiki = get_best_wiki_summary(word)
148
  if wiki:
149
  logs.append(f"🌐 <b>{word}</b> için Wiki bulundu")
150
  else:
151
  logs.append(f"⚠️ <b>{word}</b> için Wiki bulunamadı")
152
  results.append({"Varlık": word, "İlk": "MISC", "Nihai": "MISC", "Kaynak": "Fallback"})
153
+
154
  misc_entities.append({"entity": word, "sentence": text, "wiki": wiki})
155
 
156
  yield "<br>".join(logs), [[r["Varlık"], r["İlk"], f"<b>{r['Nihai']}</b>", r["Kaynak"]] for r in results]
157
 
158
+ # LLM rafinasyonu (GPU çağrısı)
159
+ if misc_entities:
160
+ logs.append("🧠 LLM ile toplu analiz yapılıyor (GPU aktif)...")
161
  yield "<br>".join(logs), [[r["Varlık"], r["İlk"], f"<b>{r['Nihai']}</b>", r["Kaynak"]] for r in results]
162
 
163
  refined = batch_llm_refine(misc_entities)
164
+
165
  for item in misc_entities:
166
  entity = item["entity"]
167
  new_label, _ = refined.get(entity, ("MISC", ""))
 
168
  for r in results:
169
  if r["Varlık"] == entity:
170
  r["Nihai"] = new_label
 
173
  logs.append("✨ Analiz tamamlandı!")
174
  yield "<br>".join(logs), [[r["Varlık"], r["İlk"], f"<b>{r['Nihai']}</b>", r["Kaynak"]] for r in results]
175
 
176
+
177
  # -------------------------------
178
+ # 5. GRADIO ARAYÜZ
179
  # -------------------------------
 
180
  with gr.Blocks(title="RAG-NER Türkçe", theme=gr.themes.Soft()) as demo:
181
  gr.Markdown("# 🇹🇷 RAG-NER: Gelişmiş Türkçe Varlık Tanılama")
182
+ gr.Markdown("Standart NER + Wikipedia + Qwen2.5 LLM (ZeroGPU) ile özel varlık tanıma")
183
 
184
  with gr.Tab("Analiz"):
185
  txt_input = gr.Textbox(