Ny fampidirana ny LLM miaraka amin'ny fahaizan'ny feo dia namorona fahafahana vaovao amin'ny fifandraisan'ny mpanjifa manokana.
Ity toro-lalana ity dia hitarika anao amin'ny fametrahana mpizara LLM eo an-toerana izay manohana fifandraisana feo roa amin'ny alàlan'ny Python, Transformers, Qwen2-Audio-7B-Instruct, ary Bark.
Alohan'ny hanombohantsika dia apetrakao ireto manaraka ireto:
Ny FFmpeg dia azo apetraka amin'ny alàlan'ny apt install ffmpeg
amin'ny Linux na brew install ffmpeg
amin'ny MacOS.
Azonao atao ny mametraka ny fiankinan-doha Python amin'ny fampiasana pip: pip install torch transformers accelerate pydub fastapi uvicorn bark python-multipart scipy
Voalohany, andao hanangana ny tontolo Python ary hisafidy ny fitaovana PyTorch:
import torch device = 'cuda' if torch.cuda.is_available() else 'cpu'
Ity kaody ity dia manamarina raha misy GPU mifanaraka amin'ny CUDA (Nvidia) ary mametraka ny fitaovana mifanaraka amin'izany.
Raha tsy misy GPU toy izany, ny PyTorch dia handeha amin'ny CPU izay miadana kokoa.
Ho an'ny fitaovana Apple Silicon vaovao, ny fitaovana dia azo apetraka amin'ny
mps
mba hampandehanana ny PyTorch amin'ny Metal, saingy tsy feno ny fampiharana PyTorch Metal.
Ny ankamaroan'ny LLM open source dia tsy manohana afa-tsy fampidirana lahatsoratra sy famoahana lahatsoratra. Na izany aza, satria te-hamorona rafitra feo-in-voice-out isika, dia mitaky modely roa hafa izany mba (1) hamadika ny lahateny ho lahatsoratra alohan'ny hampidirana azy ao amin'ny LLM-ntsika ary (2) hamadika ny vokatra LLM miverina. amin'ny kabary.
Amin'ny fampiasana LLM multimodal toa an'i Qwen Audio, afaka miala amin'ny maodely iray isika mba handrafetana ny fidiran'ny lahateny ho valin'ny lahatsoratra, ary avy eo dia tsy maintsy mampiasa modely faharoa ihany no mamadika ny famoahana LLM ho kabary.
Ity fomba fiasa multimodal ity dia tsy vitan'ny hoe mahomby kokoa amin'ny fotoana fanodinana sy ny fanjifana (V) RAM, fa matetika koa dia manome vokatra tsara kokoa satria alefa mivantana any amin'ny LLM ny feo fampidirana tsy misy korontana.
Raha mihazakazaka amin'ny mpampiantrano rahona GPU toa an'i Runpod na Vast ianao, dia te-hametraka ny lahatahiry HuggingFace home & Bark amin'ny fitahirizana boky ianao amin'ny alàlan'ny fampandehanana
export HF_HOME=/workspace/hf
&export XDG_CACHE_HOME=/workspace/bark
alohan'ny hisintonana azy. ireo modely.
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)
Nisafidy ny hampiasa ny variana kely 7B amin'ny andiany modely Qwen Audio izahay eto mba hampihenana ny fepetra takian'ny kajy. Na izany aza, Qwen dia mety namoaka modely feo matanjaka kokoa sy lehibe kokoa amin'ny fotoana mamaky ity lahatsoratra ity. Azonao atao ny mijery ny maodely Qwen rehetra ao amin'ny HuggingFace hanamarina indroa fa mampiasa ny maodely farany ianao.
Ho an'ny tontolo famokarana, azonao atao ny mampiasa motera famintinana haingana toy ny vLLM mba hahazoana vokatra avo kokoa.
Bark dia maodely AI text-to-speech miaraka amin'ny loharanom-baovao misokatra manara-penitra izay manohana fiteny maro ary koa ny vokatry ny feo.
from bark import SAMPLE_RATE, generate_audio, preload_models preload_models()
Ankoatra ny Bark, azonao atao koa ny mampiasa modely amin'ny lahatsoratra-to-kabary hafa loharano misokatra. Ataovy ao an-tsaina fa na dia mety ho mahomby kokoa aza ny fananana, dia lafo kokoa ny vidiny. Ny kianja TTS dia mitazona fampitahana vaovao .
Miaraka amin'ny Qwen Audio 7B & Bark voatahiry ao anaty fitadidiana, ny fampiasana RAM (V) eo ho eo dia 24GB, koa ataovy azo antoka fa manohana izany ny fitaovanao. Raha tsy izany dia azonao atao ny mampiasa dikan-dikan-dikan-dikan-dikan-dikan-dikan-dikan-dikan-dikan-dikan-dikan-dikan-dikan-dikan-dikan-dikan-dikan-dikan-dikan-dikan-dikan-dikan-dikan-dikan-dikan-dikan-dikan-dikan-dikan-dikan-dikan-dikan-dikan-dikan-dikan-dikan-dikan-dikan-dikan-dikan-dikan-dikan-dikan-dikan-dikan- dikan-dikan-dikan-dikan-dikan-dikan-dikan?
Hamorona mpizara FastAPI izahay miaraka amin'ny lalana roa hifehezana ny fampidiran-peo na lahatsoratra ho avy ary hamerina valiny amin'ny feo.
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)
Ity mpizara ity dia manaiky rakitra audio amin'ny alàlan'ny fangatahana POST eo amin'ny teboka farany /voice
& /text
.
Hampiasa ffmpeg izahay handaminana ny feo ho avy ary hanomana izany ho an'ny modely Qwen.
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
Miaraka amin'ny feo voahodina, afaka mamorona valinteny amin'ny alàlan'ny modely Qwen isika. Mila mitantana ny fampidirana lahatsoratra sy feo izany.
Ny preprocessor dia hamadika ny fampidiranay ho modely amin'ny chat modely (ChatML amin'ny raharaha Qwen).
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
Aza misalasala milalao miaraka amin'ny masontsivana taranaka toy ny mari-pana ao amin'ny
model.generate
function.
Farany, havadiky ho kabary ny valin-teny novokarina.
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
Havaozy ny teboka farany mba hanodinana ny fampidiran-peo na lahatsoratra, mamorona valiny ary mamerina ny lahateny natambatra ho rakitra WAV.
@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")
Azonao atao ihany koa ny misafidy ny hampiditra hafatra rafitra amin'ny resaka mba hahazoana fifehezana bebe kokoa amin'ny valinteny mpanampy.
Azontsika atao ny mampiasa curl
hanesorana ny servery toy izao manaraka izao:
# 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"
Amin'ny fanarahana ireo dingana ireo dia nanangana mpizara tsotra eo an-toerana ianao afaka mifandray amin'ny feo roa mampiasa maodely manara-penitra. Ity fananganana ity dia azo ampiasaina ho fototry ny fananganana rindranasa be pitsiny kokoa noho ny feo.
Raha mikaroka fomba hahazoana vola amin'ny maodely fiteny mampiasa AI ianao dia diniho ireto fampiharana mety ireto:
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)