fraunhofer commited on
Commit
7604960
·
1 Parent(s): 3ef82e6

SPACE PYTHON CODES

Browse files
Dockerfile ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Python 3.9 tabanlı bir Linux kuruyoruz
2
+ FROM python:3.9
3
+
4
+ # Çalışma klasörünü ayarla
5
+ WORKDIR /code
6
+
7
+ # Ses işleme için gerekli olan FFmpeg'i kur (Linux paket yöneticisiyle)
8
+ RUN apt-get update && apt-get install -y ffmpeg
9
+
10
+ # Kütüphane listesini kopyala ve kur
11
+ COPY ./requirements.txt /code/requirements.txt
12
+ RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
13
+
14
+ # Kullanıcı yetkilerini ayarla (Hugging Face güvenlik kuralı)
15
+ RUN useradd -m -u 1000 user
16
+ USER user
17
+ ENV HOME=/home/user \
18
+ PATH=/home/user/.local/bin:$PATH
19
+
20
+ # Kodları sunucuya kopyala
21
+ WORKDIR $HOME/app
22
+ COPY --chown=user . $HOME/app
23
+
24
+ # Modeli önceden indir (Deploy süresini hızlandırır)
25
+ RUN python3 -c "import whisper; whisper.load_model('base')"
26
+
27
+ # Uygulamayı başlat (Port 7860 olmak ZORUNDA)
28
+ CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "7860"]
__pycache__/main.cpython-313.pyc ADDED
Binary file (5.34 kB). View file
 
__pycache__/phonology_engine.cpython-313.pyc ADDED
Binary file (2.58 kB). View file
 
main.py ADDED
@@ -0,0 +1,135 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import FastAPI, UploadFile, File, Form, HTTPException
2
+ from faster_whisper import WhisperModel
3
+ from phonology_engine import FonolojikVaryasyonMotoru
4
+ import difflib
5
+ import os
6
+ import shutil
7
+ import uuid
8
+
9
+ app = FastAPI(title="MnemAI Ses Analiz API")
10
+
11
+ # --- MODEL AYARLARI ---
12
+ # Hugging Face CPU'su için 'int8' en iyisidir.
13
+ MODEL_SIZE = "large-v2"
14
+ DEVICE = "cpu"
15
+ COMPUTE_TYPE = "int8"
16
+
17
+ print("⏳ Whisper modeli ve Varyasyon Motoru yükleniyor...")
18
+ # Modeli global olarak bir kez yüklüyoruz
19
+ model = WhisperModel(MODEL_SIZE, device=DEVICE, compute_type=COMPUTE_TYPE)
20
+ motor = FonolojikVaryasyonMotoru()
21
+ print("✅ Sistem hazır!")
22
+
23
+ def kelime_analizi_yap(hedef: str, gelen: str):
24
+ """
25
+ Hedef kelime ile gelen kelimeyi karşılaştırır ve hataları raporlar.
26
+ """
27
+ hedef = hedef.lower().replace("İ", "i").strip()
28
+ gelen = gelen.lower().replace("İ", "i").strip()
29
+
30
+ # 1. Tam Eşleşme
31
+ if hedef == gelen:
32
+ return {
33
+ "durum": "basarili",
34
+ "skor": 100,
35
+ "mesaj": "Harika! Tamamen doğru söyledin.",
36
+ "hatalar": []
37
+ }
38
+
39
+ # 2. Hata Analizi (Difflib)
40
+ matcher = difflib.SequenceMatcher(None, hedef, gelen)
41
+ hatalar = []
42
+
43
+ # Opcodes: 'replace', 'delete', 'insert', 'equal'
44
+ for tag, i1, i2, j1, j2 in matcher.get_opcodes():
45
+ if tag == 'replace':
46
+ beklenen = hedef[i1:i2]
47
+ soylenen = gelen[j1:j2]
48
+ hatalar.append(f"'{beklenen.upper()}' yerine '{soylenen.upper()}' dedin.")
49
+ elif tag == 'delete':
50
+ beklenen = hedef[i1:i2]
51
+ hatalar.append(f"'{beklenen.upper()}' sesini yuttun.")
52
+ elif tag == 'insert':
53
+ fazla = gelen[j1:j2]
54
+ hatalar.append(f"Fazladan '{fazla.upper()}' sesi çıkardın.")
55
+
56
+ skor = int(matcher.ratio() * 100)
57
+
58
+ return {
59
+ "durum": "hatali",
60
+ "skor": skor,
61
+ "mesaj": "Bazı sesleri düzeltmemiz gerekiyor.",
62
+ "hatalar": hatalar,
63
+ "detayli_fark": {
64
+ "beklenen": hedef,
65
+ "algilanan": gelen
66
+ }
67
+ }
68
+
69
+ @app.post("/analiz")
70
+ async def ses_analiz(
71
+ file: UploadFile = File(...),
72
+ hedef_kelime: str = Form(...)
73
+ ):
74
+ """
75
+ Endpoint: Ses dosyasını ve hedeflenen kelimeyi alır, analiz sonucunu döner.
76
+ """
77
+
78
+ # 1. Dosyayı Geçici Kaydet
79
+ if not file.filename.lower().endswith(('.wav', '.mp3', '.m4a', '.ogg')):
80
+ raise HTTPException(status_code=400, detail="Geçersiz dosya formatı.")
81
+
82
+ temp_filename = f"temp_{uuid.uuid4()}.wav"
83
+
84
+ try:
85
+ with open(temp_filename, "wb") as buffer:
86
+ shutil.copyfileobj(file.file, buffer)
87
+
88
+ # 2. Fonolojik Prompt Üret (Whisper'ı yönlendirmek için)
89
+ prompt_metni = motor.varyasyonlari_uret(hedef_kelime)
90
+
91
+ # 3. Whisper Transkripsiyon
92
+ # initial_prompt: Whisper'a bu kelimenin varyasyonlu olabileceğini söylüyoruz.
93
+ segments, _ = model.transcribe(
94
+ temp_filename,
95
+ language="tr",
96
+ initial_prompt=f"Bu çocuk şu kelimeleri söyleyebilir: {prompt_metni}",
97
+
98
+ # --- YENİ EKLENEN AYARLAR ---
99
+ beam_size=5, # Daha fazla olasılığı değerlendir
100
+ vad_filter=False, # Sessizlik filtresini KAPAT (Çok önemli)
101
+ word_timestamps=False, # Tek kelime için gereksiz, hız kazandırır
102
+
103
+ # Whisper'ın "Emin değilim" deyip susmasını engellemek için filtreleri kapatıyoruz:
104
+ no_speech_threshold=0.95, # Sessizlik eşiğini yükselt
105
+ log_prob_threshold=None, # Düşük olasılıklı tahminleri de kabul et (Silme)
106
+ compression_ratio_threshold=None, # Tekrar eden bozuk sesleri de al
107
+ temperature=0 # Yaratıcılığı kapat, en net duyduğunu ver
108
+ )
109
+
110
+ # Generator'dan metni al
111
+ algilanan_metin = " ".join([s.text for s in segments]).strip()
112
+
113
+ # Noktalama temizliği
114
+ algilanan_metin = algilanan_metin.replace(".", "").replace("?", "").replace("!", "")
115
+
116
+ # 4. Karşılaştırma ve Raporlama
117
+ sonuc = kelime_analizi_yap(hedef_kelime, algilanan_metin)
118
+
119
+ return {
120
+ "hedef_kelime": hedef_kelime,
121
+ "algilanan_metin": algilanan_metin,
122
+ "analiz_sonucu": sonuc
123
+ }
124
+
125
+ except Exception as e:
126
+ return {"hata": str(e)}
127
+
128
+ finally:
129
+ # Geçici dosyayı temizle
130
+ if os.path.exists(temp_filename):
131
+ os.remove(temp_filename)
132
+
133
+ @app.get("/")
134
+ def root():
135
+ return {"durum": "MnemAI Sunucusu Calisiyor"}
phonology_engine.py ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import itertools
2
+
3
+ class FonolojikVaryasyonMotoru:
4
+ def __init__(self):
5
+ # TÜRKÇE FONOLOJİK BOZUKLUK KURALLARI
6
+ self.kurallar = {
7
+ # R Bozuklukları (Rhotacism)
8
+ 'r': ['r', 'y', 'ğ', 'l', ''],
9
+ # Önleştirme (Fronting) K->T, G->D
10
+ 'k': ['k', 't'],
11
+ 'g': ['g', 'd'],
12
+ # Durdurma (Stopping) S->T, F->P vb.
13
+ 's': ['s', 't', ''],
14
+ 'z': ['z', 'd'],
15
+ 'f': ['f', 'p'],
16
+ 'v': ['v', 'b'],
17
+ # Seda Değişimleri & Diğerleri
18
+ 'b': ['b', 'p'],
19
+ 'd': ['d', 't'],
20
+ 'c': ['c', 'ç', 't'],
21
+ 'ç': ['ç', 't', 'ş'],
22
+ 'j': ['j', 'd', 'z'],
23
+ 'ş': ['ş', 's', 't', 'ç'],
24
+ 'l': ['l', 'y', ''],
25
+ 'ğ': ['ğ', 'y', ''],
26
+ 'h': ['h', '']
27
+ }
28
+
29
+ def varyasyonlari_uret(self, hedef_kelime, max_limit=150):
30
+ """
31
+ Hedef kelimenin olası yanlış telaffuz varyasyonlarını üretir.
32
+ Whisper'a 'Initial Prompt' olarak vermek için kullanılır.
33
+ """
34
+ kelime = hedef_kelime.lower().strip()
35
+ harf_opsiyonlari = []
36
+
37
+ for harf in kelime:
38
+ secenekler = self.kurallar.get(harf, [harf])
39
+ if harf not in secenekler:
40
+ secenekler.insert(0, harf)
41
+ harf_opsiyonlari.append(secenekler)
42
+
43
+ tum_kombinasyonlar = list(itertools.product(*harf_opsiyonlari))
44
+
45
+ sonuc_listesi = set()
46
+ for kombinasyon in tum_kombinasyonlar:
47
+ varyasyon = "".join(kombinasyon)
48
+ if len(varyasyon) > 1:
49
+ sonuc_listesi.add(varyasyon)
50
+
51
+ sonuc_listesi.add(kelime)
52
+ final_liste = sorted(list(sonuc_listesi))
53
+
54
+ # Whisper prompt limiti için kesme işlemi
55
+ if len(final_liste) > max_limit:
56
+ final_liste = final_liste[:max_limit]
57
+
58
+ prompt_string = " ".join(final_liste)
59
+ return prompt_string
requirements.txt ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ fastapi
2
+ uvicorn
3
+ python-multipart
4
+ faster-whisper
5
+ numpy