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: : Versiya 3.9 və ya daha yüksək. Python : Modelləri işə salmaq üçün. PyTorch : Qwen modelinə girişi təmin edir. Transformers : Bəzi mühitlərdə tələb olunur. Sürətləndirmək : Audio emal üçün. FFmpeg & pydub : Veb server yaratmaq üçün. FastAPI : FastAPI-ni işə salmaq üçün ASGI server. Uvicorn : Mətn-nitq sintezi üçün. Bark : Səsi manipulyasiya etmək üçün. Multipart & Scipy FFmpeg Linux-da vasitəsilə quraşdırıla bilər və ya MacOS-da . apt install ffmpeg 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 -ə də təyin edilə bilər, lakin PyTorch Metal tətbiqi hərtərəfli deyil. mps 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. və ya kimi bulud GPU hostunda işləyirsinizsə, yükləmədən əvvəl və işlətməklə HuggingFace ev və Bark qovluqlarını həcm yaddaşınıza qurmaq istəyə bilərsiniz. modellər. Runpod Vast export HF_HOME=/workspace/hf export XDG_CACHE_HOME=/workspace/bark 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 bilərsiniz. HuggingFace-də bütün Qwen modellərinə baxa İstehsal mühiti üçün daha yüksək ötürmə qabiliyyəti üçün kimi sürətli nəticə çıxarma mühərrikindən istifadə etmək istəyə bilərsiniz. vLLM 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 və son nöqtəsində POST sorğuları vasitəsilə audio faylları qəbul edir. /voice /text 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 funksiyasındakı temperatur kimi nəsil parametrləri ilə oynamaqdan çekinmeyin. model.generate 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 istifadə edə bilərik: curl # 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: Çatbotlar (məsələn, , ); Character AI NSFW AI Chat Telefon agentləri (məsələn, , ) Synthflow Bland Müştəri Dəstəyi Avtomatlaşdırılması (məsələn, , ) Zendesk Forethought Hüquq köməkçiləri ( , ) Harvey AI Leya AI 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)