File size: 5,235 Bytes
545b9ff
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
"""
Hugging Face Spaces için CEFR Classifier App
Bu dosyayı Space'inize yükleyin
"""
import gradio as gr
import torch
from transformers import AutoTokenizer, AutoModelForCausalLM
from peft import PeftModel
import os
import re

# Model yükleme (Space başlangıcında bir kez)
# NOT: Kendi model path'inizi buraya yazın (Hub'dan veya lokal)
MODEL_NAME = os.getenv("MODEL_NAME", "keremigenas/cefr-llama-3b-optimized")  # Hub'daki model adınız
BASE_MODEL = "meta-llama/Llama-3.2-3B-Instruct"

print("Model yükleniyor...")
hf_token = os.getenv("HF_TOKEN")

# Tokenizer
tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME, token=hf_token)
if tokenizer.pad_token is None:
    tokenizer.pad_token = tokenizer.eos_token

# Base model
base_model = AutoModelForCausalLM.from_pretrained(
    BASE_MODEL,
    torch_dtype=torch.bfloat16 if torch.cuda.is_available() else torch.float32,
    device_map="auto",
    token=hf_token
)

# LoRA adaptörleri
model = PeftModel.from_pretrained(base_model, MODEL_NAME)
model = model.merge_and_unload()
model.eval()
print("✓ Model yüklendi")

def create_prompt(sentence):
    """Llama modeli için prompt oluştur"""
    system_prompt = """Sen bir CEFR (Common European Framework of Reference) seviye sınıflandırıcısısın. 
Verilen Türkçe cümleyi analiz edip A1, A2, B1, B2, C1 veya C2 seviyelerinden birine sınıflandır.

CEFR Seviyeleri:
- A1: Başlangıç seviyesi, çok basit cümleler, temel kelimeler
- A2: Temel seviye, günlük konuşma, basit cümleler
- B1: Orta seviye, karmaşık cümleler, günlük konuşma
- B2: Orta-ileri seviye, akademik dil, karmaşık yapılar
- C1: İleri seviye, akıcı dil, karmaşık ifadeler
- C2: Uzman seviye, anadil seviyesine yakın, çok karmaşık yapılar

Önce analiz yap:
- Cümle yapısı
- Dilbilgisi karmaşıklığı
- Kelime seviyesi
- Metin tutarlılığı

Sonra SADECE CEFR seviyesini (A1, A2, B1, B2, C1 veya C2) döndür."""

    user_prompt = f"Cümle: {sentence}\n\nBu cümlenin CEFR seviyesi nedir?"
    prompt = f"<|begin_of_text|><|start_header_id|>system<|end_header_id|>\n\n{system_prompt}<|eot_id|><|start_header_id|>user<|end_header_id|>\n\n{user_prompt}<|eot_id|><|start_header_id|>assistant<|end_header_id|>\n\n"
    return prompt

def predict_cefr(text):
    """Metni cümlelere ayır ve her biri için CEFR seviyesi tahmin et"""
    if not text or not text.strip():
        return "Lütfen bir metin girin."
    
    # Cümleleri ayır
    sentences = re.split(r'[.!?]+', text)
    sentences = [s.strip() for s in sentences if s.strip()]
    
    if not sentences:
        return "Cümle bulunamadı."
    
    results = []
    for sentence in sentences:
        try:
            prompt = create_prompt(sentence)
            inputs = tokenizer(prompt, return_tensors="pt", truncation=True, max_length=512)
            inputs = {k: v.to(model.device) for k, v in inputs.items()}
            
            with torch.no_grad():
                outputs = model.generate(
                    **inputs,
                    max_new_tokens=10,
                    do_sample=False,
                    pad_token_id=tokenizer.eos_token_id
                )
            
            generated_text = tokenizer.decode(outputs[0], skip_special_tokens=False)
            
            # CEFR seviyesini çıkar
            valid_levels = ['A1', 'A2', 'B1', 'B2', 'C1', 'C2']
            level = "B1"  # default
            
            # Assistant response'u çıkar
            if "<|start_header_id|>assistant<|end_header_id|>" in generated_text:
                response = generated_text.split("<|start_header_id|>assistant<|end_header_id|>")[-1]
                response = response.split("<|eot_id|>")[0].strip()
            else:
                response = generated_text.split(prompt)[-1].strip() if prompt in generated_text else generated_text[-20:]
            
            # Seviyeyi bul
            for lvl in valid_levels:
                if lvl in response.upper():
                    level = lvl
                    break
            
            results.append(f"{sentence} → **{level}**")
        except Exception as e:
            results.append(f"{sentence} → Hata: {str(e)}")
    
    return "\n\n".join(results)

# Gradio interface
with gr.Blocks(title="CEFR Seviye Sınıflandırıcı") as demo:
    gr.Markdown("# 🇹🇷 CEFR Seviye Sınıflandırıcı")
    gr.Markdown("Türkçe metinlerinizi CEFR seviyelerine göre sınıflandırın.")
    
    with gr.Row():
        with gr.Column():
            text_input = gr.Textbox(
                label="Türkçe Metin",
                placeholder="Analiz etmek istediğiniz metni buraya yazın...",
                lines=5
            )
            btn = gr.Button("Analiz Et", variant="primary")
        
        with gr.Column():
            output = gr.Markdown(label="Sonuçlar")
    
    btn.click(fn=predict_cefr, inputs=text_input, outputs=output)
    
    gr.Examples(
        examples=[
            "Merhaba, benim adım Ahmet.",
            "Eğer müze gezilmezse, kültürel bilgiler eksik olabilir.",
            "Deney sonuçları geç geldiği için rapor geç hazırlandı."
        ],
        inputs=text_input
    )

demo.launch()