Update app.py
Browse files
app.py
CHANGED
|
@@ -4,8 +4,9 @@ import re
|
|
| 4 |
from sentence_transformers import SentenceTransformer
|
| 5 |
from threading import Lock
|
| 6 |
import os
|
|
|
|
| 7 |
|
| 8 |
-
# Flask uygulamasını başlat
|
| 9 |
app = Flask(__name__)
|
| 10 |
|
| 11 |
# Model yükleme işlemini sadece bir kez yapmak için global değişkenler
|
|
@@ -17,6 +18,9 @@ embedding_model = None
|
|
| 17 |
# Metin ön işleme fonksiyonu
|
| 18 |
def metin_temizle(metin):
|
| 19 |
"""Metni küçük harfe dönüştürür, noktalama işaretlerini ve sayıları kaldırır."""
|
|
|
|
|
|
|
|
|
|
| 20 |
metin = metin.lower()
|
| 21 |
metin = re.sub(r'[^\w\s]', '', metin)
|
| 22 |
metin = re.sub(r'\d+', '', metin)
|
|
@@ -24,57 +28,87 @@ def metin_temizle(metin):
|
|
| 24 |
|
| 25 |
# Modeli yükleme fonksiyonu (Sadece bir kez çalışacak)
|
| 26 |
def load_models():
|
|
|
|
| 27 |
global classifier, embedding_model, MODEL_LOADED
|
| 28 |
-
|
|
|
|
| 29 |
with MODEL_LOCK:
|
| 30 |
if MODEL_LOADED:
|
| 31 |
return
|
|
|
|
| 32 |
print("Modeller ilk kez yükleniyor...")
|
| 33 |
try:
|
| 34 |
-
#
|
| 35 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 36 |
print("SVC modeli başarıyla yüklendi.")
|
| 37 |
-
|
| 38 |
-
#
|
| 39 |
-
raise FileNotFoundError("siniflandirma_modeli.pkl dosyası bulunamadı.")
|
| 40 |
-
try:
|
| 41 |
-
# 2. Gömme modelini doğrudan internetten indir (Distiluse modeli)
|
| 42 |
embedding_model = SentenceTransformer('distiluse-base-multilingual-cased-v2')
|
| 43 |
print("Sentence-Transformer modeli başarıyla indirildi/yüklendi.")
|
|
|
|
|
|
|
|
|
|
| 44 |
except Exception as e:
|
| 45 |
-
print(f"HATA:
|
| 46 |
-
|
| 47 |
-
|
| 48 |
-
|
|
|
|
| 49 |
|
| 50 |
-
# API
|
| 51 |
-
@app.route('/', methods=['POST']) # <-- Yeni eklendi: Kök adresi (/) dinler
|
| 52 |
@app.route('/kategorize-et', methods=['POST'])
|
| 53 |
def kategorize_et_api():
|
| 54 |
"""Gelen HTTP isteğini işler, makale başlığını kategorize eder ve sonucu JSON olarak döndürür."""
|
| 55 |
-
|
| 56 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 57 |
# Gelen JSON verisini al
|
| 58 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 59 |
if not data or 'baslik' not in data:
|
| 60 |
-
#
|
| 61 |
-
return jsonify({"hata": "Makale başlığı (baslik) JSON gövdesinde
|
| 62 |
-
|
| 63 |
makale_basligi = data.get('baslik', '')
|
| 64 |
-
temizlenmis_baslik = metin_temizle(makale_basligi)
|
| 65 |
|
| 66 |
-
|
| 67 |
-
|
| 68 |
-
|
| 69 |
-
|
| 70 |
-
|
| 71 |
-
|
| 72 |
-
|
| 73 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 74 |
|
| 75 |
-
#
|
| 76 |
-
# ancak dosyamızı daha standart tutmak için bırakabiliriz.
|
| 77 |
if __name__ == '__main__':
|
| 78 |
-
# Hugging Face'de port otomatik olarak verilir. Lokal test için 7860 kullanıyoruz
|
| 79 |
port = int(os.environ.get('PORT', 7860))
|
| 80 |
-
app.run(host='0.0.0.0', port=port)
|
|
|
|
| 4 |
from sentence_transformers import SentenceTransformer
|
| 5 |
from threading import Lock
|
| 6 |
import os
|
| 7 |
+
import sys # Hata ayıklama için eklendi
|
| 8 |
|
| 9 |
+
# Flask uygulamasını başlat
|
| 10 |
app = Flask(__name__)
|
| 11 |
|
| 12 |
# Model yükleme işlemini sadece bir kez yapmak için global değişkenler
|
|
|
|
| 18 |
# Metin ön işleme fonksiyonu
|
| 19 |
def metin_temizle(metin):
|
| 20 |
"""Metni küçük harfe dönüştürür, noktalama işaretlerini ve sayıları kaldırır."""
|
| 21 |
+
if not isinstance(metin, str):
|
| 22 |
+
# Eğer metin değilse boş string döndür
|
| 23 |
+
return ""
|
| 24 |
metin = metin.lower()
|
| 25 |
metin = re.sub(r'[^\w\s]', '', metin)
|
| 26 |
metin = re.sub(r'\d+', '', metin)
|
|
|
|
| 28 |
|
| 29 |
# Modeli yükleme fonksiyonu (Sadece bir kez çalışacak)
|
| 30 |
def load_models():
|
| 31 |
+
"""Modelleri ilk çalıştırmada yükler ve kilit mekanizması kullanır."""
|
| 32 |
global classifier, embedding_model, MODEL_LOADED
|
| 33 |
+
|
| 34 |
+
# Kilit mekanizması: Aynı anda birden fazla isteğin modeli yüklemesini engeller
|
| 35 |
with MODEL_LOCK:
|
| 36 |
if MODEL_LOADED:
|
| 37 |
return
|
| 38 |
+
|
| 39 |
print("Modeller ilk kez yükleniyor...")
|
| 40 |
try:
|
| 41 |
+
# Hugging Face Spaces'te dosyanın nerede olduğuna dikkat edin
|
| 42 |
+
# Kök dizinde olduğunu varsayıyoruz.
|
| 43 |
+
classifier_path = 'siniflandirma_modeli.pkl'
|
| 44 |
+
if not os.path.exists(classifier_path):
|
| 45 |
+
print(f"HATA: '{classifier_path}' bulunamadı. Lütfen Spaces dosya yapısını kontrol edin.", file=sys.stderr)
|
| 46 |
+
# Uygulama yüklemesini durdurmak için exception fırlatmak en sağlıklısı
|
| 47 |
+
raise FileNotFoundError(f"Model dosyası '{classifier_path}' bulunamadı.")
|
| 48 |
+
|
| 49 |
+
classifier = joblib.load(classifier_path)
|
| 50 |
print("SVC modeli başarıyla yüklendi.")
|
| 51 |
+
|
| 52 |
+
# Gömme modelini yükle
|
|
|
|
|
|
|
|
|
|
| 53 |
embedding_model = SentenceTransformer('distiluse-base-multilingual-cased-v2')
|
| 54 |
print("Sentence-Transformer modeli başarıyla indirildi/yüklendi.")
|
| 55 |
+
|
| 56 |
+
MODEL_LOADED = True
|
| 57 |
+
print("Model yükleme tamamlandı. API hazır.")
|
| 58 |
except Exception as e:
|
| 59 |
+
print(f"KRİTİK HATA: Model yüklenirken bir sorun oluştu: {e}", file=sys.stderr)
|
| 60 |
+
# Yükleme başarısız olursa, bir sonraki isteğin tekrar denemesi için MODEL_LOADED=False kalır.
|
| 61 |
+
# Ancak Spaces'te genellikle uygulama bu aşamada çöker ve yeniden başlatılır.
|
| 62 |
+
raise e
|
| 63 |
+
|
| 64 |
|
| 65 |
+
# API uç noktası: '/kategorize-et'
|
|
|
|
| 66 |
@app.route('/kategorize-et', methods=['POST'])
|
| 67 |
def kategorize_et_api():
|
| 68 |
"""Gelen HTTP isteğini işler, makale başlığını kategorize eder ve sonucu JSON olarak döndürür."""
|
| 69 |
+
try:
|
| 70 |
+
# Modelleri yükle (Zaten yüklüyse hızlıca geçer)
|
| 71 |
+
load_models()
|
| 72 |
+
except Exception as e:
|
| 73 |
+
# Model yükleme hatası oluşursa, kullanıcıya bir hata mesajı döndür
|
| 74 |
+
return jsonify({"hata": f"Model yükleme/başlatma hatası: {e}"}), 503 # Service Unavailable
|
| 75 |
+
|
| 76 |
# Gelen JSON verisini al
|
| 77 |
+
try:
|
| 78 |
+
data = request.get_json(force=True, silent=False)
|
| 79 |
+
except Exception as e:
|
| 80 |
+
# JSON ayrıştırma hatası
|
| 81 |
+
return jsonify({"hata": f"JSON formatı hatalı. Lütfen geçerli bir JSON gövdesi gönderin. Detay: {e}"}), 400
|
| 82 |
+
|
| 83 |
if not data or 'baslik' not in data:
|
| 84 |
+
# 'baslik' anahtarı yoksa
|
| 85 |
+
return jsonify({"hata": "Makale başlığı (anahtar: 'baslik') JSON gövdesinde bulunamadı veya JSON boş."}), 400
|
| 86 |
+
|
| 87 |
makale_basligi = data.get('baslik', '')
|
|
|
|
| 88 |
|
| 89 |
+
if not makale_basligi or not isinstance(makale_basligi, str):
|
| 90 |
+
# Başlık boşsa veya string formatında değilse
|
| 91 |
+
return jsonify({"hata": "Makale başlığı (baslik) boş olamaz ve metin formatında olmalıdır."}), 400
|
| 92 |
+
|
| 93 |
+
try:
|
| 94 |
+
temizlenmis_baslik = metin_temizle(makale_basligi)
|
| 95 |
+
|
| 96 |
+
# Başlığı vektöre dönüştür
|
| 97 |
+
tahmin_vektoru = embedding_model.encode([temizlenmis_baslik])
|
| 98 |
+
|
| 99 |
+
# Sınıflandırma modelini kullanarak kategoriyi tahmin et
|
| 100 |
+
tahmin_sonucu = classifier.predict(tahmin_vektoru)[0]
|
| 101 |
+
|
| 102 |
+
# Sonucu JSON formatında döndür
|
| 103 |
+
return jsonify({"kategori": tahmin_sonucu}), 200
|
| 104 |
+
|
| 105 |
+
except Exception as e:
|
| 106 |
+
# Tahmin sırasında oluşan diğer hatalar
|
| 107 |
+
print(f"TAHMİN SIRASINDA HATA: {e}", file=sys.stderr)
|
| 108 |
+
return jsonify({"hata": f"Tahmin işlemi sırasında beklenmeyen bir hata oluştu: {e}"}), 500
|
| 109 |
+
|
| 110 |
|
| 111 |
+
# Hugging Face'de bu satır genellikle gerekmez, ancak lokal test için faydalıdır.
|
|
|
|
| 112 |
if __name__ == '__main__':
|
|
|
|
| 113 |
port = int(os.environ.get('PORT', 7860))
|
| 114 |
+
app.run(host='0.0.0.0', port=port)
|