VoiceToWrite / app.py
Seicas's picture
Update app.py
02eb251 verified
raw
history blame
8.77 kB
import os
import tempfile
import json
import time
import gradio as gr
import spacy
from preprocessing import clean_audio
from asr import transcribe_file
from diarization import diarize_segments
from privacy import MedicalPrivacyProcessor
from config import settings
# HuggingFace token'ını ayarla
HF_TOKEN = os.getenv("HF_TOKEN", "")
if not HF_TOKEN:
print("Warning: HF_TOKEN not set!")
def load_spacy_model():
"""SpaCy modelini yükle veya indir"""
try:
# Önce mevcut modelleri kontrol et
available_models = spacy.util.get_installed_models()
if "tr_core_news_md" in available_models:
print("Türkçe SpaCy modeli bulundu, yükleniyor...")
return spacy.load("tr_core_news_md")
elif "tr_core_news_sm" in available_models:
print("Küçük Türkçe SpaCy modeli bulundu, yükleniyor...")
return spacy.load("tr_core_news_sm")
else:
print("Türkçe SpaCy modeli bulunamadı, indiriliyor...")
os.system("python -m spacy download tr_core_news_md")
return spacy.load("tr_core_news_md")
except Exception as e:
print(f"SpaCy model yükleme hatası: {str(e)}")
print("Boş Türkçe model oluşturuluyor...")
return spacy.blank("tr")
# SpaCy modelini yükle
nlp = load_spacy_model()
# Yardım metni
usage_tips = """
## Kullanım İpuçları
1. **Dosya formatı**: WAV formatında ses dosyaları en iyi sonuçları verir.
2. **Ses kalitesi**: Gürültüsüz ortamlarda kaydedilen sesler daha iyi sonuç verir.
3. **Konuşmacı ayrımı**: Konuşmacı sayısı arttıkça tanıma doğruluğu düşebilir.
4. **Hata durumlarında**: Sistem hata verirse, ses dosyasının formatını ve boyutunu kontrol edin.
## Pediatrik Uzmanlar İçin
Sistem, çocuk hastalıkları, aşılar, ilaçlar ve muayene terimleri içeren
geniş bir tıbbi terim sözlüğü kullanır. Bu sayede pediatri vizitelerindeki
terminolojinin doğru transkribe edilmesini sağlar.
"""
# CSS stilleri
css = """
.container {padding: 20px; border-radius: 10px; box-shadow: 0 4px 8px rgba(0,0,0,0.1);}
.result-text {margin-top: 10px; padding: 15px; background: #f8f9fa; border-radius: 5px; white-space: pre-wrap;}
.speaker {font-weight: bold; color: #1a5fb4;}
.timestamp {color: #666; font-size: 0.9em;}
.success {color: green; font-weight: bold;}
.error {color: red; font-weight: bold;}
.footer {margin-top: 50px; text-align: center; color: #666; font-size: 0.9em;}
.tips {background: #e7f5ff; padding: 15px; border-radius: 5px; margin-top: 20px;}
"""
async def process_audio(audio_file, diarize=True, enhance=True, anonymize=True, progress=gr.Progress()):
try:
if audio_file is None:
return {"error": "Lütfen bir ses dosyası yükleyin."}, None
progress(0, desc="Ses dosyası hazırlanıyor...")
# Ses dosyasını temizle
if enhance:
progress(0.1, desc="Ses iyileştiriliyor...")
audio_file = clean_audio(audio_file)
# Transkripsiyon yap
progress(0.3, desc="Ses metne dönüştürülüyor...")
result = transcribe_file(
audio_file,
language="tr",
model_name=settings.ASR_MODEL
)
# Konuşmacı ayrımı
if diarize:
progress(0.6, desc="Konuşmacılar ayrıştırılıyor...")
diarization_result = diarize_segments(result["segments"])
result["diarization"] = diarization_result
# Kişisel verileri anonimleştir
if anonymize:
progress(0.8, desc="Kişisel veriler anonimleştiriliyor...")
privacy_processor = MedicalPrivacyProcessor()
result["text"] = privacy_processor.anonymize_text(result["text"])
result["anonymized"] = True
# Sonucu formatla
progress(0.9, desc="Sonuçlar hazırlanıyor...")
formatted_text = ""
if diarize and "diarization" in result:
for segment in result["diarization"]:
speaker = segment["speaker"]
text = segment["text"]
start = segment["start"]
end = segment["end"]
formatted_text += f"[{speaker}] ({start:.1f}s - {end:.1f}s): {text}\n\n"
else:
formatted_text = result["text"]
if result.get("anonymized"):
formatted_text += "\n🔒 Kişisel veriler anonimleştirildi."
progress(1.0, desc="Tamamlandı!")
return result, formatted_text
except Exception as e:
print(f"Error in process_audio: {str(e)}")
return {"error": f"İşlem sırasında hata: {str(e)}"}, None
# Ana arayüz
with gr.Blocks(theme=gr.themes.Soft(primary_hue="indigo", secondary_hue="blue"), css=css) as demo:
gr.HTML(f"""
<div style="text-align: center; max-height: 150px; margin-bottom: 30px">
<h1>Türkçe Pediatrik Konuşma Tanıma Sistemi</h1>
<p>Çocuk doktorları için geliştirilmiş, pediatri alanına özel tıbbi terminoloji tanıma özellikli transkripsiyon sistemi</p>
</div>
""")
with gr.Row():
with gr.Column(scale=1):
audio_input = gr.Audio(
label="Ses Dosyası Yükleyin veya Kaydedin",
type="filepath",
elem_classes="container"
)
with gr.Group():
with gr.Row():
diarize = gr.Checkbox(value=True, label="Konuşmacı Ayrımı")
enhance = gr.Checkbox(value=True, label="Ses İyileştirme")
with gr.Row():
anonymize = gr.Checkbox(value=True, label="Kişisel Verileri Anonimleştir")
clear_btn = gr.Button("Temizle", variant="secondary")
process_btn = gr.Button("Transkribe Et", variant="primary")
gr.HTML('<div class="tips"><b>💡 İpucu:</b> En iyi sonuçlar için gürültüsüz ortamlarda kayıt yapın.</div>')
with gr.Column(scale=2, elem_classes="container"):
with gr.Tabs():
with gr.TabItem("Konuşma Metni"):
result_text = gr.Markdown(label="Transkripsiyon Sonucu", elem_classes="result-text")
with gr.TabItem("JSON Sonucu"):
json_output = gr.JSON(label="API Yanıtı")
with gr.TabItem("Kullanım Kılavuzu"):
gr.Markdown(usage_tips)
status = gr.Markdown("Sistem hazır.")
# Uyarı mesajı
gr.HTML("""
<div style="background-color: #fff3cd; color: #856404; padding: 15px; margin: 15px 0; border-radius: 5px; border: 1px solid #ffeeba;">
<h3>⚠️ Önemli Gizlilik Uyarısı</h3>
<p>
Bu demo uygulaması <strong>yalnızca eğitim amaçlıdır</strong> ve gerçek hasta verilerinin işlenmesi için tasarlanmamıştır.
Lütfen hasta bilgisi içeren ses kayıtlarını yüklemeyin. Sistemde paylaşılan ses kayıtları üçüncü şahıslar tarafından erişilebilir
ve gizlilik/güvenlik garantisi yoktur.
</p>
<p>
Bu aracı kullanarak, yüklediğiniz verilerin <a href="https://huggingface.co/terms-of-service" target="_blank">Hugging Face Kullanım Koşulları</a>'na
uygun olduğunu kabul etmiş olursunuz.
</p>
</div>
""")
# İzin onayı
with gr.Group():
privacy_agreement = gr.Checkbox(label="Gizlilik koşullarını okudum ve kabul ediyorum", value=False)
# Onay olmadan işlem yapılmasını engelle
def check_agreement(agreement, *args):
if not agreement:
return {"error": "Devam etmek için gizlilik koşullarını kabul etmelisiniz."}, "Lütfen gizlilik koşullarını kabul edin."
return process_audio(*args)
process_btn.click(
fn=check_agreement,
inputs=[privacy_agreement, audio_input, diarize, enhance, anonymize],
outputs=[json_output, result_text]
)
clear_btn.click(
lambda: (None, None, "Sistem hazır."),
outputs=[audio_input, result_text, status]
)
gr.HTML("""
<div class="footer">
<p>© 2023 Türkçe Pediatrik Konuşma Tanıma Sistemi | Çocuk doktorları için geliştirilmiştir.</p>
</div>
""")
# Hugging Face Spaces için gerekli
if __name__ == "__main__":
demo.queue().launch(server_name="0.0.0.0", server_port=7860, share=False)