Spaces:
Sleeping
Sleeping
File size: 3,843 Bytes
c7651c2 d0b84c0 c7651c2 d0b84c0 c7651c2 d0b84c0 c7651c2 d0b84c0 c7651c2 d0b84c0 c7651c2 d0b84c0 c7651c2 d0b84c0 c7651c2 d0b84c0 c7651c2 d0b84c0 c7651c2 d0b84c0 c7651c2 d0b84c0 c7651c2 d0b84c0 c7651c2 d0b84c0 c7651c2 d0b84c0 c7651c2 d0b84c0 c7651c2 d0b84c0 c7651c2 d0b84c0 c7651c2 d0b84c0 c7651c2 d0b84c0 c7651c2 d8e48b4 d0b84c0 c7651c2 1f1d56e d8e48b4 1f1d56e d8e48b4 d0b84c0 |
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 |
import asyncio
import os
import numpy as np
import torch
import gradio as gr
from fastapi import FastAPI
from fastrtc import AsyncStreamHandler, Stream, wait_for_item
from transformers import pipeline, AutoTokenizer
# 1. Hardware & Modell-Initialisierung
device = "cuda" if torch.cuda.is_available() else "cpu"
# Wir nutzen 4-bit Quantisierung falls CUDA verfügbar ist, um Latenz zu sparen
model_kwargs = {"torch_dtype": torch.float16, "load_in_4bit": True} if device == "cuda" else {}
# STT: Whisper-tiny für minimale Latenz
stt_pipe = pipeline("automatic-speech-recognition", model="openai/whisper-tiny", device=device)
# LLM: Phi-3-mini (Instruction-tuned)
llm_model = "microsoft/Phi-3-mini-4k-instruct"
tokenizer = AutoTokenizer.from_pretrained(llm_model)
llm_pipe = pipeline("text-generation", model=llm_model, tokenizer=tokenizer, device=device, model_kwargs=model_kwargs)
# TTS: MMS-TTS für Deutsch
tts_pipe = pipeline("text-to-speech", model="facebook/mms-tts-deu", device=device)
class OpenSourceHandler(AsyncStreamHandler):
def __init__(self, expected_layout="mono", output_sample_rate=24000):
super().__init__(expected_layout, output_sample_rate, input_sample_rate=16000)
self.output_queue = asyncio.Queue()
async def receive(self, frame: tuple[int, np.ndarray]) -> None:
rate, array = frame
# Zugriff auf die Gradio-Zusatzeingaben (z.B. Sprache oder System-Prompt)
# latest_args[0] ist der erste zusätzliche Input nach dem Audio
# Hier beispielhaft für zukünftige Erweiterungen:
# system_msg = self.latest_args[0] if self.latest_args else "Du bist ein Assistent."
# 1. STT: Audio -> Text (Whisper erwartet Float32)
audio_fp32 = array.astype(np.float32) / 32768.0
text_result = stt_pipe({"sampling_rate": rate, "raw": audio_fp32})["text"]
# Rausch-Filter: Nur antworten, wenn wirklich Text erkannt wurde
if len(text_result.strip()) > 3:
# 2. LLM: Antwort generieren
# return_full_text=False verhindert, dass der Prompt mit ausgegeben wird
prompt = f"<|user|>\n{text_result}<|end|>\n<|assistant|>"
outputs = llm_pipe(prompt, max_new_tokens=64, do_sample=True, return_full_text=False)
answer = outputs[0]["generated_text"].strip()
# 3. TTS: Text -> Audio
# MMS-TTS gibt ein Dict zurück: {'audio': ndarray, 'sampling_rate': int}
audio_out = tts_pipe(answer)
audio_data = audio_out["audio"] # Das ist bereits ein numpy array
# Resampling / Konvertierung zu Int16 für den Stream
audio_int16 = (audio_data * 32767).astype(np.int16)
# Wir nutzen await für die Queue, um sauberes Async-Verhalten zu garantieren
await self.output_queue.put((self.output_sample_rate, audio_int16))
async def emit(self) -> tuple[int, np.ndarray] | None:
return await wait_for_item(self.output_queue)
def copy(self) -> "OpenSourceHandler":
return OpenSourceHandler(output_sample_rate=self.output_sample_rate)
# 2. FastAPI & Stream Setup
app = FastAPI() # Hier definieren wir die App!
stream = Stream(
modality="audio",
mode="send-receive",
handler=OpenSourceHandler(),
additional_inputs=[
gr.Textbox(label="System Message", value="Du bist ein hilfreicher KI-Assistent."),
],
)
# ... (Handler und Stream Definitionen bleiben gleich)
# Wir nutzen stream.ui, was ein normales gradio.Blocks Objekt ist
app = gr.mount_gradio_app(FastAPI(), stream.ui, path="/")
if __name__ == "__main__":
import uvicorn
import os
port = int(os.getenv("PORT", 7860))
# Wir starten die 'app' (FastAPI), die nun das Gradio UI auf "/" enthält
uvicorn.run(app, host="0.0.0.0", port=port) |