File size: 8,445 Bytes
5334f44
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1a29176
5334f44
 
 
 
 
 
 
 
 
 
 
 
 
 
56c88e0
5334f44
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4a992f2
5334f44
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4a992f2
 
5334f44
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4a992f2
 
 
 
 
 
 
 
 
 
 
 
 
 
5334f44
 
4a992f2
 
 
 
 
 
 
 
 
 
 
 
5334f44
 
 
 
 
 
 
 
 
 
 
 
 
 
7be7c68
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
220
221
222
223
224
225
226
227
228
import torch
import wikipedia
from transformers import pipeline
import gradio as gr

# --- 1. İlk Tarama Modeli (Hızlı NER) ---
# XLM-Roberta çok dillidir ve standart olarak PER, LOC, ORG, MISC etiketleri üretir.
print("1. Standart NER Modeli yükleniyor...")
ner_pipe = pipeline("ner", model="xlm-roberta-large-finetuned-conll03-english", aggregation_strategy="simple")

# --- 2. Akıl Yürütme Modeli (LLM - RAG Karar Verici) ---
print("2. LLM (Karar Verici) yükleniyor...")
model_id = "Qwen/Qwen2.5-1.5B-Instruct" # Türkçe yeteneği iyi ve hızlı

llm_model_kwargs = {}
if torch.cuda.is_available():
    llm_model_kwargs["torch_dtype"] = torch.bfloat16
    llm_device_map = "auto"
    print("CUDA desteği bulundu, model GPU üzerinde bfloat16 ile yüklenecek.")
else:
    print("CUDA desteği bulunamadı, model CPU üzerinde float32 ile yüklenecek.")
    llm_device_map = "cpu" # Explicitly set to CPU for clarity and robustness

gen_pipe = pipeline(
    "text-generation",
    model=model_id,
    model_kwargs=llm_model_kwargs,
    device_map=llm_device_map
)
print("\\n Modeller Hazır!")

# --- Wikipedia Fonksiyonu ---
wikipedia.set_lang("tr")
def get_wiki_summary(term):
    try:
        results = wikipedia.search(term)
        if not results: return None
        return wikipedia.summary(results[0], sentences=3)
    except:
        return None

# --- LLM ile Etiket Rafine Etme Fonksiyonu ---
def refine_label_with_llm(entity_text, wiki_context, custom_label_definitions):
    labels_str = ", ".join(custom_label_definitions.keys())
    label_definitions_str = " ".join(
        [f"- {k}: {v}" for k, v in custom_label_definitions.items()]
    )

    few_shot_examples = """
ÖRNEK 1 (NORP İÇİN):
VARLIK: Türk
BAĞLAM: Türkler, Türkiye Cumhuriyeti'nde yaşayan ve Türkçe konuşan büyük bir etnik gruptur. (NORP tanımı ile eşleşir.)
SONUÇ: NORP

ÖRNEK 2 (MOVIE İÇİN):
VARLIK: Yüzüklerin Efendisi
BAĞLAM: Peter Jackson tarafından yönetilmiş, 2001-2003 yılları arasında yayınlanan üç fantastik macera filminden oluşan seridir. (MOVIE tanımı ile eşleşir.)
SONUÇ: MOVIE

ÖRNEK 3 (AWARD İÇİN):
VARLIK: Altın Ayı
BAĞLAM: Berlin Uluslararası Film Festivali'nde en iyi film için verilen en yüksek ödüldür. (AWARD tanımı ile eşleşir.)
SONUÇ: AWARD

ÖRNEK 4 (SOFTWARE İÇİN):
VARLIK: Photoshop
BAĞLAM: Adobe tarafından geliştirilen, fotoğraf ve resim düzenleme programı. (SOFTWARE tanımı ile eşleşir.)
SONUÇ: SOFTWARE

ÖRNEK 5 (BOOK İÇİN):
VARLIK: Sefiller
BAĞLAM: Victor Hugo tarafından yazılmış, 1862'de yayınlanmış tarihi bir romandır. (BOOK tanımı ile eşleşir.)
SONUÇ: BOOK

ÖRNEK 6 (PRODUCT İÇİN):
VARLIK: iPhone 15 Pro
BAĞLAM: Apple tarafından üretilen ve 2023 yılında piyasaya sürülen akıllı telefon modelidir. (PRODUCT tanımı ile eşleşir.)
SONUÇ: PRODUCT

ÖRNEK 7 (AWARD İÇİN - Film Festivali Ödülü):
VARLIK: Altın Palmiye
BAĞLAM: Cannes Film Festivali'nin en prestijli ödülü olup, festivalin en iyi filmine verilir. (AWARD tanımı ile eşleşir.)
SONUÇ: AWARD

ÖRNEK 8 (AWARD İÇİN - Film Festivali Ödülü):
VARLIK: Altın Portakal Ödülü
BAĞLAM: Türkiye'nin en eski ve prestijli film festivali ödüllerinden biridir. (AWARD tanımı ile eşleşir.)
SONUÇ: AWARD
    """

    prompt = f"""
Sen uzman bir veri sınıflandırma sistemisin.
Görevin, aşağıdaki BAĞLAM'ı okumak ve ETİKET TANIMLARI'ndan hangisinin varlığa en uygun olduğunu belirlemektir.

Aşağıdaki adımları izle:
1. BAĞLAM'ı analiz et.
2. ETİKET TANIMLARI ile karşılaştır.
3. BULDUĞUN EŞLEŞMEYİ VE SEÇİMİ TEK SATIRDA ÇIKTI FORMATINA UYGUN OLARAK VER.

{few_shot_examples}

---

ETİKET TANIMLARI:
{label_definitions_str}

---

GÖREV VARLIĞI:
VARLIK: {entity_text}
BAĞLAM (Wikipedia): {wiki_context}

ÇIKTI FORMATI:
Gerekçe: [Tanımlarla eşleşen anahtar kelime veya tanım]
Cevap: [SEÇİLEN ETİKET]

Gerekçe:
    """

    messages = [{"role": "user", "content": prompt}]
    outputs = gen_pipe(messages, max_new_tokens=100, do_sample=False, temperature=0.1)
    full_output = outputs[0]["generated_text"][-1]["content"].strip()

    final_label = "MISC"
    try:
        cevap_satiri = [line for line in full_output.split('
') if 'Cevap:' in line][-1]
        raw_label = cevap_satiri.split('Cevap:')[-1].strip().upper()

        valid_labels = list(custom_label_definitions.keys()) + ["UNKNOWN"]
        if raw_label in valid_labels:
            final_label = raw_label

    except IndexError:
        print(f"❌ Uyarı: LLM çıktı formatını bozdu. Ham çıktı: {full_output[:50]}...")
        final_label = "MISC"

    return final_label

# --- NER Pipeline Fonksiyonu ---
def advanced_ner_pipeline(text, target_labels):
    initial_results = ner_pipe(text)
    final_results = []

    for entity in initial_results:
        word = entity['word']
        label = entity['entity_group']

        result_obj = {
            "entity": word,
            "initial_label": label,
            "final_label": label,
            "source": "Model"
        }

        if label == "MISC":
            standardized_word = word.title()
            wiki_context = get_wiki_summary(standardized_word)

            if wiki_context:
                new_label = refine_label_with_llm(standardized_word, wiki_context, target_labels)
                result_obj["final_label"] = new_label
                result_obj["source"] = "RAG+LLM"
            
        final_results.append(result_obj)

    return final_results

# --- Özel Etiket Tanımları ---
custom_label_definitions = {
    "SOFTWARE": "Bilgisayar programları, mobil uygulamalar, yapay zeka sistemleri veya işletim sistemleri gibi dijital araçlar.",
    "AWARD": "Bir başarı, katkı veya üstünlük karşılığında verilen ödül, madalya veya nişan. (Örnek: Nobel, Oscar, Altın Küre, Film Festivali Ödülü)",
    "BOOK": "Yazılı veya basılı bir eser, yayınlanmış bir roman, ders kitabı veya ansiklopedi.",
    "MOVIE": "Sinema filmi, uzun metrajlı veya kısa film gibi görsel-işitsel yapıt.",
    "PRODUCT": "Ticari olarak satılan somut bir eşya, model veya cihaz. (Örnek: Araba modeli, telefon serisi, elektrikli süpürge)",
    "NORP": "Milliyetler, dini veya politik gruplar. (Örnek: Türk,fransız, fra. Hristiyan, Sosyalist Parti)"
}


# --- Gradio Arayüzü Fonksiyonu ---
def process_ner_request(text):
    results = advanced_ner_pipeline(text, custom_label_definitions)

    # Sonuçları daha okunaklı bir formatta string olarak döndür
    formatted_output = """<table style='width:100%; border-collapse: collapse;'>
"""
    formatted_output += "  <tr style='background-color: #f2f2f2; border: 1px solid #ddd;'>
"
    formatted_output += "    <th style='padding: 8px; text-align: left; border: 1px solid #ddd;'>VARLIK</th>
"
    formatted_output += "    <th style='padding: 8px; text-align: left; border: 1px solid #ddd;'>İLK ETİKET</th>
"
    formatted_output += "    <th style='padding: 8px; text-align: left; border: 1px solid #ddd;'>RAG SONRASI</th>
"
    formatted_output += "    <th style='padding: 8px; text-align: left; border: 1px solid #ddd;'>KAYNAK</th>
"
    formatted_output += "  </tr>
"

    for item in results:
        formatted_output += "  <tr style='border: 1px solid #ddd;'>
"
        formatted_output += f"    <td style='padding: 8px; text-align: left; border: 1px solid #ddd;'>{item['entity']}</td>
"
        formatted_output += f"    <td style='padding: 8px; text-align: left; border: 1px solid #ddd;'>{item['initial_label']}</td>
"
        formatted_output += f"    <td style='padding: 8px; text-align: left; border: 1px solid #ddd;'>{item['final_label']}</td>
"
        formatted_output += f"    <td style='padding: 8px; text-align: left; border: 1px solid #ddd;'>{item['source']}</td>
"
        formatted_output += "  </tr>
"
    formatted_output += "</table>"
    return formatted_output

# --- Gradio Arayüzünü Tanımla ---
iface = gr.Interface(
    fn=process_ner_request,
    inputs=gr.Textbox(lines=5, placeholder="Metin giriniz..."),
    outputs=gr.HTML(label="NER Sonuçları"),
    title="Gelişmiş Named Entity Recognition (NER) Uygulaması",
    description="Metindeki varlıkları tanır ve MISC etiketlerini Wikipedia ve LLM kullanarak zenginleştirir."
)

# --- Gradio Uygulamasını Başlat ---
if __name__ == "__main__":
    iface.launch(share=True)