YAML Metadata Warning: empty or missing yaml metadata in repo card (https://huggingface.co/docs/hub/model-cards#model-card-metadata)

🎤 Turkish ASR + LLM Multimodal Model

Türkçe konuşmayı metne çeviren ve üzerinde LLM tabanlı işlemler yapabilen multimodal bir model.

🎯 Bu Proje Ne Yapıyor?

Bu proje klasik ASR'dan farklı bir yaklaşım kullanıyor:

Klasik ASR Bu Proje
Ses → Whisper → Metin Ses → Whisper Encoder → Audio Projector → Turkish LLM → Metin
Tek model 3 bileşen birlikte çalışır
Sadece transkript Transkript + Anlama + Analiz

Mimari

┌─────────┐     ┌─────────────────┐     ┌─────────────────┐     ┌─────────────┐
│  Ses    │ ──► │ Whisper Encoder │ ──► │ Audio Projector │ ──► │ Turkish LLM │ ──► Metin
│ (Audio) │     │   (1280 dim)    │     │  (1280 → 4096)  │     │  (4096 dim) │
└─────────┘     └─────────────────┘     └─────────────────┘     └─────────────┘
                     (Frozen)              (Eğitildi)            (LoRA + Merge)

Bileşenler

Bileşen Model Görevi Durum
Whisper Encoder openai/whisper-large-v3-turbo Sesi 1280 boyutlu vektörlere çevirir Frozen (eğitilmedi)
Audio Projector 2-layer MLP + LayerNorm Whisper çıktısını LLM formatına dönüştürür (1280d → 4096d) Eğitildi
Turkish LLM Trendyol/Trendyol-LLM-7b-chat-v1.0 Audio vektörlerinden Türkçe metin üretir LoRA fine-tuned → Merged

🚀 Kurulum & Kullanım

Gereksinimler

  • Google Colab (GPU gerekli - L4/T4/A100)
  • Python 3.10+
  • ~15GB GPU RAM

Hızlı Başlangıç

# ============================================================================
# 🎤 TURKISH ASR + LLM FULL PIPELINE
# ============================================================================

!pip install -q bitsandbytes

import torch
import torch.nn as nn
import librosa
import numpy as np
from transformers import WhisperProcessor, WhisperModel, AutoTokenizer, AutoModelForCausalLM, BitsAndBytesConfig
from huggingface_hub import hf_hub_download
from IPython.display import Audio, display
from google.colab import drive

drive.mount('/content/drive')

REPO_ID = "Cosmobillian/turkish-asr-whisper-llm"
DEVICE = "cuda"

class AudioProjector(nn.Module):
    def __init__(self):
        super().__init__()
        self.proj = nn.Sequential(
            nn.Linear(1280, 4096),
            nn.GELU(),
            nn.Linear(4096, 4096),
            nn.LayerNorm(4096)
        )
    def forward(self, x):
        return self.proj(x)

print("📥 Modeller yükleniyor...")

whisper_processor = WhisperProcessor.from_pretrained(REPO_ID, subfolder="whisper")
whisper_model = WhisperModel.from_pretrained(REPO_ID, subfolder="whisper", torch_dtype=torch.float16, device_map="auto")
whisper_model.eval()
print("✓ Whisper")

llm_tokenizer = AutoTokenizer.from_pretrained(REPO_ID, subfolder="llm")
if llm_tokenizer.pad_token is None:
    llm_tokenizer.pad_token = llm_tokenizer.eos_token

bnb_config = BitsAndBytesConfig(load_in_4bit=True, bnb_4bit_quant_type="nf4", bnb_4bit_compute_dtype=torch.float16)
llm_model = AutoModelForCausalLM.from_pretrained(REPO_ID, subfolder="llm", quantization_config=bnb_config, device_map="auto", trust_remote_code=True)
llm_model.eval()
print("✓ LLM")

projector_path = hf_hub_download(REPO_ID, "audio_projector.pt")
projector = AudioProjector()
projector.load_state_dict(torch.load(projector_path, map_location=DEVICE)['state_dict'])
projector = projector.to(DEVICE).to(torch.float16).eval()
print("✓ Projector")
print("✅ Tüm modeller hazır!")

Fonksiyonlar

1. Ses → Transkript

@torch.no_grad()
def speech_to_text(audio_path):
    """Ses dosyasını transkripte çevirir"""
    audio, sr = librosa.load(audio_path, sr=16000, mono=True)
    if np.abs(audio).max() > 0:
        audio = audio / np.abs(audio).max()
    
    inputs = whisper_processor(audio, sampling_rate=16000, return_tensors="pt")
    audio_features = inputs.input_features.to(DEVICE, dtype=torch.float16)
    
    with torch.amp.autocast('cuda', dtype=torch.float16):
        audio_embeds = whisper_model.encoder(audio_features).last_hidden_state
        projected = projector(audio_embeds)
        prompt = llm_tokenizer("Transkript:", return_tensors="pt").input_ids.to(DEVICE)
        prompt_embeds = llm_model.get_input_embeddings()(prompt)
        inputs_embeds = torch.cat([projected, prompt_embeds], dim=1)
        
        outputs = llm_model.generate(
            inputs_embeds=inputs_embeds,
            max_new_tokens=256,
            do_sample=False,
            pad_token_id=llm_tokenizer.pad_token_id,
            eos_token_id=llm_tokenizer.eos_token_id
        )
        text = llm_tokenizer.decode(outputs[0], skip_special_tokens=True)
    
    return text.split("Transkript:")[-1].strip() if "Transkript:" in text else text

# Kullanım
transcript = speech_to_text("ses.wav")
print(transcript)

2. LLM ile Metin İşleme

@torch.no_grad()
def text_to_text(prompt, max_tokens=512):
    """LLM ile metin işleme (özet, analiz, soru-cevap vb.)"""
    inputs = llm_tokenizer(prompt, return_tensors="pt").to(DEVICE)
    
    with torch.amp.autocast('cuda', dtype=torch.float16):
        outputs = llm_model.generate(
            **inputs,
            max_new_tokens=max_tokens,
            do_sample=True,
            temperature=0.7,
            top_p=0.9,
            pad_token_id=llm_tokenizer.pad_token_id,
            eos_token_id=llm_tokenizer.eos_token_id
        )
    
    response = llm_tokenizer.decode(outputs[0], skip_special_tokens=True)
    if prompt in response:
        response = response.replace(prompt, "").strip()
    return response

3. Full Pipeline (Ses → Transkript → LLM İşlem)

def full_pipeline(audio_path, task="özet"):
    """
    Tam pipeline: Ses → Transkript → LLM Analiz
    
    task seçenekleri:
    - "özet": Transkripti özetle
    - "analiz": İçerik analizi yap
    - "düzelt": Yazım hatalarını düzelt
    - "başlık": Başlık öner
    - "anahtar": Anahtar kelimeler çıkar
    - "duygu": Duygu analizi yap
    """
    
    # Adım 1: Transkript
    transcript = speech_to_text(audio_path)
    
    # Adım 2: LLM işlem
    prompts = {
        "özet": f"Aşağıdaki metni kısaca özetle:\n\n{transcript}\n\nÖzet:",
        "analiz": f"Aşağıdaki metni analiz et:\n\n{transcript}\n\nAnaliz:",
        "düzelt": f"Yazım hatalarını düzelt:\n\n{transcript}\n\nDüzeltilmiş:",
        "başlık": f"Başlık öner:\n\n{transcript}\n\nBaşlık:",
        "anahtar": f"Anahtar kelimeler:\n\n{transcript}\n\nKelimeler:",
        "duygu": f"Duygu analizi:\n\n{transcript}\n\nDuygu:"
    }
    
    prompt = prompts.get(task, f"{task}\n\nMetin: {transcript}\n\nCevap:")
    result = text_to_text(prompt)
    
    return {"transcript": transcript, "llm_output": result}

# Kullanım
result = full_pipeline("ses.wav", task="özet")
print(result["transcript"])
print(result["llm_output"])

4. Ses Hakkında Soru Sor

def ask_about_audio(audio_path, question):
    """Ses içeriği hakkında soru sor"""
    
    transcript = speech_to_text(audio_path)
    
    prompt = f"""Transkript: {transcript}

Soru: {question}

Cevap:"""
    
    return text_to_text(prompt)

# Kullanım
answer = ask_about_audio("ses.wav", "Konuşmacı ne anlatıyor?")
print(answer)

📊 Eğitim Detayları

Parametre Değer
Dataset 23,000+ Türkçe YouTube transkript
Batch Size 1 (gradient accumulation: 8)
Learning Rate 5e-5
Epochs 3
Precision BFloat16
Hardware NVIDIA L4 (22GB)
LoRA Config r=16, alpha=32, dropout=0.05
Target Modules q_proj, k_proj, v_proj, o_proj

Eğitim Süreci

  1. Whisper Encoder: Frozen (eğitilmedi)
  2. Audio Projector: Sıfırdan eğitildi (1280d → 4096d)
  3. LLM: LoRA ile fine-tune edildi, sonra base model ile merge edildi

📁 Model Dosyaları

Cosmobillian/turkish-asr-whisper-llm/
├── whisper/                 # Whisper encoder + processor
│   ├── config.json
│   ├── model.safetensors
│   ├── preprocessor_config.json
│   └── ...
├── llm/                     # Merged LLM (LoRA değil, full weights)
│   ├── config.json
│   ├── model.safetensors
│   ├── tokenizer.json
│   └── ...
├── audio_projector.pt       # Projector weights
├── config.json              # Model config
└── README.md

🔧 Teknik Detaylar

Audio Projector Mimarisi

AudioProjector(
    Linear(1280, 4096),   # Whisper dim → LLM dim
    GELU(),               # Aktivasyon
    Linear(4096, 4096),   # Ek dönüşüm
    LayerNorm(4096)       # Normalizasyon
)

Neden Bu Mimari?

  1. Whisper Encoder Only: Decoder kullanmıyoruz çünkü metin üretimini LLM yapıyor
  2. Projector: Whisper ve LLM farklı boyutlarda çalışıyor, köprü gerekli
  3. LoRA + Merge: Eğitim sırasında memory tasarrufu, inference'da hız
  4. 4-bit Quantization: 7B LLM'i consumer GPU'da çalıştırabilmek için

Benzer Projeler

⚠️ Limitasyonlar

  • Maksimum ~30 saniye ses (VRAM limiti)
  • Gürültülü ortamlarda performans düşebilir
  • Çoklu konuşmacı desteği sınırlı
  • Türkçe dışı dillerde çalışmaz

📝 Lisans

MIT License

👤 Yazar

Cosmobillian(Cengizhan BAYRAM)

🙏 Teşekkürler

Downloads last month
32
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support