paint-brush
İki tərəfli səsli söhbətlə öz süni intellektinizi yerləşdirmək düşündüyünüzdən daha asandır!tərəfindən@herahavenai
Yeni tarix

İki tərəfli səsli söhbətlə öz süni intellektinizi yerləşdirmək düşündüyünüzdən daha asandır!

tərəfindən HeraHaven AI10m2025/01/08
Read on Terminal Reader

Çox uzun; Oxumaq

Bu bələdçi Python, Transformers, Qwen2-Audio-7B-Instruct və Bark istifadə edərək ikitərəfli səsli qarşılıqlı əlaqəni dəstəkləyən yerli LLM serverinin qurulmasında sizə yol göstərəcək.
featured image - İki tərəfli səsli söhbətlə öz süni intellektinizi yerləşdirmək düşündüyünüzdən daha asandır!
HeraHaven AI HackerNoon profile picture

LLM-lərin səs imkanları ilə inteqrasiyası fərdiləşdirilmiş müştərilərlə qarşılıqlı əlaqədə yeni imkanlar yaratmışdır.


Bu bələdçi Python, Transformers, Qwen2-Audio-7B-Instruct və Bark istifadə edərək ikitərəfli səsli qarşılıqlı əlaqəni dəstəkləyən yerli LLM serverinin qurulmasında sizə yol göstərəcək.

İlkin şərtlər

Başlamazdan əvvəl aşağıdakıları quraşdıracaqsınız:

  • Python : Versiya 3.9 və ya daha yüksək.
  • PyTorch : Modelləri işə salmaq üçün.
  • Transformers : Qwen modelinə girişi təmin edir.
  • Sürətləndirmək : Bəzi mühitlərdə tələb olunur.
  • FFmpeg & pydub : Audio emal üçün.
  • FastAPI : Veb server yaratmaq üçün.
  • Uvicorn : FastAPI-ni işə salmaq üçün ASGI server.
  • Bark : Mətn-nitq sintezi üçün.
  • Multipart & Scipy : Səsi manipulyasiya etmək üçün.


FFmpeg Linux-da apt install ffmpeg vasitəsilə quraşdırıla bilər və ya MacOS-da brew install ffmpeg .


Siz pip istifadə edərək Python asılılıqlarını quraşdıra bilərsiniz: pip install torch transformers accelerate pydub fastapi uvicorn bark python-multipart scipy

Addım 1: Ətraf mühitin qurulması

Əvvəlcə Python mühitimizi quraq və PyTorch cihazımızı seçək:


 import torch device = 'cuda' if torch.cuda.is_available() else 'cpu'


Bu kod CUDA-uyğun (Nvidia) GPU-nun mövcud olub olmadığını yoxlayır və cihazı müvafiq olaraq təyin edir.


Əgər belə bir GPU yoxdursa, PyTorch daha yavaş olan CPU-da işləyəcək.


Daha yeni Apple Silicon cihazları üçün cihaz PyTorch-u Metal üzərində işlətmək üçün mps -ə də təyin edilə bilər, lakin PyTorch Metal tətbiqi hərtərəfli deyil.

Addım 2: Modelin yüklənməsi

Açıq mənbəli LLM-lərin əksəriyyəti yalnız mətn daxiletmə və mətn çıxışını dəstəkləyir. Bununla belə, səslə səs sistemi yaratmaq istədiyimiz üçün bu, (1) nitqi LLM-ə daxil edilməzdən əvvəl mətnə çevirmək və (2) LLM çıxışını geri çevirmək üçün daha iki modeldən istifadə etməyimizi tələb edəcək. nitqinə.


Qwen Audio kimi multimodal LLM-dən istifadə etməklə biz nitq daxiletməsini mətn cavabında emal etmək üçün bir modeldən qurtula bilərik və sonra yalnız LLM çıxışını yenidən nitqə çevirən ikinci modeldən istifadə etməliyik.


Bu multimodal yanaşma təkcə emal vaxtı və (V) RAM istehlakı baxımından daha səmərəli deyil, həm də adətən daha yaxşı nəticələr verir, çünki giriş səsi heç bir sürtünmə olmadan birbaşa LLM-ə göndərilir.


Runpod və ya Vast kimi bulud GPU hostunda işləyirsinizsə, yükləmədən əvvəl export HF_HOME=/workspace/hfexport XDG_CACHE_HOME=/workspace/bark işlətməklə HuggingFace ev və Bark qovluqlarını həcm yaddaşınıza qurmaq istəyə bilərsiniz. modellər.


 from transformers import AutoProcessor, Qwen2AudioForConditionalGeneration model_name = "Qwen/Qwen2-Audio-7B-Instruct" processor = AutoProcessor.from_pretrained(model_name) model = Qwen2AudioForConditionalGeneration.from_pretrained(model_name, device_map="auto").to(device)


Hesablama tələblərimizi azaltmaq üçün burada Qwen Audio model seriyasının kiçik 7B variantından istifadə etməyi seçdik. Bununla belə, siz bu məqaləni oxuduğunuz zaman Qwen daha güclü və daha böyük audio modelləri buraxmış ola bilər. Ən son modelindən istifadə etdiyinizi iki dəfə yoxlamaq üçün HuggingFace-də bütün Qwen modellərinə baxa bilərsiniz.


İstehsal mühiti üçün daha yüksək ötürmə qabiliyyəti üçün vLLM kimi sürətli nəticə çıxarma mühərrikindən istifadə etmək istəyə bilərsiniz.

Addım 3: Bark modelinin yüklənməsi

Bark bir çox dilləri və səs effektlərini dəstəkləyən ən müasir açıq mənbəli mətndən nitqə AI modelidir.


 from bark import SAMPLE_RATE, generate_audio, preload_models preload_models()


Barkdan başqa, siz digər açıq mənbəli və ya mülkiyyətli mətndən nitqə modellərdən də istifadə edə bilərsiniz. Nəzərə alın ki, mülkiyyətli olanlar daha performanslı ola bilsələr də, daha yüksək qiymətə gəlirlər. TTS arenası müasir müqayisə aparır .


Hər iki Qwen Audio 7B və Bark yaddaşa yükləndikdə, təxmini (V) RAM istifadəsi 24 GB-dır, ona görə də aparatınızın bunu dəstəklədiyinə əmin olun. Əks halda, yaddaşa qənaət etmək üçün Qwen modelinin kvantlaşdırılmış versiyasından istifadə edə bilərsiniz .

Addım 4: FastAPI Serverinin qurulması

Daxil olan audio və ya mətn daxiletmələrini idarə etmək və audio cavabları qaytarmaq üçün iki marşrutu olan FastAPI server yaradacağıq.


 from fastapi import FastAPI, UploadFile, Form from fastapi.responses import StreamingResponse import uvicorn app = FastAPI() @app.post("/voice") async def voice_interaction(file: UploadFile): # TODO return @app.post("/text") async def text_interaction(text: str = Form(...)): # TODO return if __name__ == "__main__":  uvicorn.run(app, host="0.0.0.0", port=8000)


Bu server /voice/text son nöqtəsində POST sorğuları vasitəsilə audio faylları qəbul edir.

Addım 5: Audio Girişi emal edin

Daxil olan audionu emal etmək və onu Qwen modeli üçün hazırlamaq üçün ffmpeg-dən istifadə edəcəyik.


 from pydub import AudioSegment from io import BytesIO import numpy as np def audiosegment_to_float32_array(audio_segment: AudioSegment, target_rate: int = 16000) -> np.ndarray: audio_segment = audio_segment.set_frame_rate(target_rate).set_channels(1) samples = np.array(audio_segment.get_array_of_samples(), dtype=np.int16) samples = samples.astype(np.float32) / 32768.0 return samples def load_audio_as_array(audio_bytes: bytes) -> np.ndarray: audio_segment = AudioSegment.from_file(BytesIO(audio_bytes)) float_array = audiosegment_to_float32_array(audio_segment, target_rate=16000) return float_array

Addım 6: Qwen ilə Mətn Cavabının Yaradılması

İşlənmiş audio ilə biz Qwen modelindən istifadə edərək mətn cavabı yarada bilərik. Bu, həm mətn, həm də audio daxiletmələri idarə etməli olacaq.


Önprosessor daxiletməmizi modelin söhbət şablonuna çevirəcək (Qwen işində ChatML).


 def generate_response(conversation): text = processor.apply_chat_template(conversation, add_generation_prompt=True, tokenize=False) audios = [] for message in conversation: if isinstance(message["content"], list): for ele in message["content"]: if ele["type"] == "audio": audio_array = load_audio_as_array(ele["audio_url"]) audios.append(audio_array) if audios: inputs = processor( text=text, audios=audios, return_tensors="pt", padding=True ).to(device) else: inputs = processor( text=text, return_tensors="pt", padding=True ).to(device) generate_ids = model.generate(**inputs, max_length=256) generate_ids = generate_ids[:, inputs.input_ids.size(1):] response = processor.batch_decode( generate_ids, skip_special_tokens=True, clean_up_tokenization_spaces=False )[0] return response


model.generate funksiyasındakı temperatur kimi nəsil parametrləri ilə oynamaqdan çekinmeyin.

Addım 7: Bark ilə mətni nitqə çevirmək

Nəhayət, yaradılan mətn cavabını yenidən nitqə çevirəcəyik.


 from scipy.io.wavfile import write as write_wav def text_to_speech(text): audio_array = generate_audio(text) output_buffer = BytesIO() write_wav(output_buffer, SAMPLE_RATE, audio_array) output_buffer.seek(0) return output_buffer

Addım 8: API-lərdə hər şeyin inteqrasiyası

Audio və ya mətn daxiletməsini emal etmək, cavab yaratmaq və sintez edilmiş nitqi WAV faylı kimi qaytarmaq üçün son nöqtələri yeniləyin.


 @app.post("/voice") async def voice_interaction(file: UploadFile): audio_bytes = await file.read() conversation = [ { "role": "user", "content": [ { "type": "audio", "audio_url": audio_bytes } ] } ] response_text = generate_response(conversation) audio_output = text_to_speech(response_text) return StreamingResponse(audio_output, media_type="audio/wav") @app.post("/text") async def text_interaction(text: str = Form(...)): conversation = [ {"role": "user", "content": [{"type": "text", "text": text}]} ] response_text = generate_response(conversation) audio_output = text_to_speech(response_text) return StreamingResponse(audio_output, media_type="audio/wav")

Siz köməkçinin cavablarına daha çox nəzarət etmək üçün söhbətlərə sistem mesajı əlavə etməyi də seçə bilərsiniz.

Addım 9: Hər şeyi yoxlayın

Serverimizi aşağıdakı kimi ping etmək üçün curl istifadə edə bilərik:


 # Audio input curl -X POST http://localhost:8000/voice --output output.wav -F "[email protected]" # Text input curl -X POST http://localhost:8000/text --output output.wav -H "Content-Type: application/x-www-form-urlencoded" -d "text=Hey"

Nəticə

Bu addımları yerinə yetirməklə siz ən müasir modellərdən istifadə edərək ikitərəfli səsli qarşılıqlı əlaqə qura bilən sadə yerli server qurmuşsunuz. Bu quraşdırma daha mürəkkəb səslə işləyən proqramların qurulması üçün əsas ola bilər.

Tətbiqlər

Süni intellektlə işləyən dil modellərindən pul qazanmağın yollarını araşdırırsınızsa, bu potensial tətbiqləri nəzərdən keçirin:

Tam kod

 import torch from fastapi import FastAPI, UploadFile, Form from fastapi.responses import StreamingResponse import uvicorn from transformers import AutoProcessor, Qwen2AudioForConditionalGeneration from bark import SAMPLE_RATE, generate_audio, preload_models from scipy.io.wavfile import write as write_wav from pydub import AudioSegment from io import BytesIO import numpy as np device = 'cuda' if torch.cuda.is_available() else 'cpu' model_name = "Qwen/Qwen2-Audio-7B-Instruct" processor = AutoProcessor.from_pretrained(model_name) model = Qwen2AudioForConditionalGeneration.from_pretrained(model_name, device_map="auto").to(device) preload_models() app = FastAPI() def audiosegment_to_float32_array(audio_segment: AudioSegment, target_rate: int = 16000) -> np.ndarray: audio_segment = audio_segment.set_frame_rate(target_rate).set_channels(1) samples = np.array(audio_segment.get_array_of_samples(), dtype=np.int16) samples = samples.astype(np.float32) / 32768.0 return samples def load_audio_as_array(audio_bytes: bytes) -> np.ndarray: audio_segment = AudioSegment.from_file(BytesIO(audio_bytes)) float_array = audiosegment_to_float32_array(audio_segment, target_rate=16000) return float_array def generate_response(conversation): text = processor.apply_chat_template(conversation, add_generation_prompt=True, tokenize=False) audios = [] for message in conversation: if isinstance(message["content"], list): for ele in message["content"]: if ele["type"] == "audio": audio_array = load_audio_as_array(ele["audio_url"]) audios.append(audio_array) if audios: inputs = processor( text=text, audios=audios, return_tensors="pt", padding=True ).to(device) else: inputs = processor( text=text, return_tensors="pt", padding=True ).to(device) generate_ids = model.generate(**inputs, max_length=256) generate_ids = generate_ids[:, inputs.input_ids.size(1):] response = processor.batch_decode( generate_ids, skip_special_tokens=True, clean_up_tokenization_spaces=False )[0] return response def text_to_speech(text): audio_array = generate_audio(text) output_buffer = BytesIO() write_wav(output_buffer, SAMPLE_RATE, audio_array) output_buffer.seek(0) return output_buffer @app.post("/voice") async def voice_interaction(file: UploadFile): audio_bytes = await file.read() conversation = [ { "role": "user", "content": [ { "type": "audio", "audio_url": audio_bytes } ] } ] response_text = generate_response(conversation) audio_output = text_to_speech(response_text) return StreamingResponse(audio_output, media_type="audio/wav") @app.post("/text") async def text_interaction(text: str = Form(...)): conversation = [ {"role": "user", "content": [{"type": "text", "text": text}]} ] response_text = generate_response(conversation) audio_output = text_to_speech(response_text) return StreamingResponse(audio_output, media_type="audio/wav") if __name__ == "__main__": uvicorn.run(app, host="0.0.0.0", port=8000)