කටහඬ හැකියාවන් සමඟ LLMs ඒකාබද්ධ කිරීම පුද්ගලාරෝපිත පාරිභෝගික අන්තර්ක්රියා වල නව අවස්ථා නිර්මාණය කර ඇත.
මෙම මාර්ගෝපදේශය Python, Transformers, Qwen2-Audio-7B-Instruct, සහ Bark භාවිතා කරමින් ද්වි-මාර්ග හඬ අන්තර්ක්රියා සඳහා සහාය දක්වන දේශීය LLM සේවාදායකයක් පිහිටුවීම හරහා ඔබව ගෙන යනු ඇත.
අපි ආරම්භ කිරීමට පෙර, ඔබ පහත ස්ථාපනය කර ඇත:
FFmpeg ලිනක්ස් හි apt install ffmpeg
හරහා හෝ MacOS මත brew install ffmpeg
ස්ථාපනය කළ හැක.
ඔබට pip භාවිතයෙන් පයිතන් පරායත්තතා ස්ථාපනය කළ හැක: pip install torch transformers accelerate pydub fastapi uvicorn bark python-multipart scipy
පළමුව, අපි අපගේ Python පරිසරය සකසා අපගේ PyTorch උපාංගය තෝරා ගනිමු:
import torch device = 'cuda' if torch.cuda.is_available() else 'cpu'
මෙම කේතය CUDA-අනුකූල (Nvidia) GPU තිබේ දැයි පරීක්ෂා කර ඒ අනුව උපාංගය සකසයි.
එවැනි GPU නොමැති නම්, PyTorch ඒ වෙනුවට වඩා මන්දගාමී CPU මත ධාවනය වේ.
නව Apple Silicon උපාංග සඳහා, Metal මත PyTorch ධාවනය කිරීමට උපාංගය
mps
ලෙසද සැකසිය හැක, නමුත් PyTorch Metal ක්රියාත්මක කිරීම විස්තීර්ණ නොවේ.
බොහෝ විවෘත මූලාශ්ර LLMs සහාය දක්වන්නේ පෙළ ආදානය සහ පෙළ ප්රතිදානය පමණි. කෙසේ වෙතත්, අපට වොයිස්-ඉන්-වොයිස්-අවුට් පද්ධතියක් නිර්මාණය කිරීමට අවශ්ය බැවින්, (1) එය අපගේ එල්එල්එම් වෙත පෝෂණය කිරීමට පෙර කථනය පෙළ බවට පරිවර්තනය කිරීමට සහ (2) එල්එල්එම් ප්රතිදානය නැවත පරිවර්තනය කිරීමට අපට තවත් ආකෘති දෙකක් භාවිතා කිරීමට අවශ්ය වනු ඇත. කතාවට.
Qwen Audio වැනි බහුමාධ්ය LLM භාවිතා කිරීමෙන්, අපට කථන ආදානය පෙළ ප්රතිචාරයක් ලෙස සැකසීමට එක් ආකෘතියකින් ගැලවිය හැකි අතර, පසුව LLM ප්රතිදානය නැවත කථනය බවට පරිවර්තනය කිරීමට දෙවන ආකෘතියක් භාවිතා කළ යුතුය.
මෙම බහුමාධ්ය ප්රවේශය සැකසුම් කාලය සහ (V)RAM පරිභෝජනය සම්බන්ධයෙන් වඩා කාර්යක්ෂම වනවා පමණක් නොව, ආදාන ශ්රව්ය ඝර්ෂණයකින් තොරව LLM වෙත කෙලින්ම යවන බැවින් සාමාන්යයෙන් වඩා හොඳ ප්රතිඵල ලබා දෙයි.
ඔබ Runpod හෝ Vast වැනි ක්ලවුඩ් GPU සත්කාරකයක් මත ධාවනය කරන්නේ නම්, බාගත කිරීමට පෙර
export HF_HOME=/workspace/hf
සහexport XDG_CACHE_HOME=/workspace/bark
ධාවනය කිරීමෙන් HuggingFace මුල් පිටුව සහ පොත්ත නාමාවලි ඔබේ පරිමාව ගබඩා කිරීමට සැකසීමට අවශ්ය වනු ඇත. ආකෘති.
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)
අපගේ ගණනය කිරීමේ අවශ්යතා අඩු කිරීම සඳහා අපි මෙහි Qwen Audio මාදිලි මාලාවේ කුඩා 7B ප්රභේදය භාවිතා කිරීමට තෝරා ගත්තෙමු. කෙසේ වෙතත්, ඔබ මෙම ලිපිය කියවන කාලය වන විට Qwen වඩා ශක්තිමත් සහ විශාල ශ්රව්ය මාදිලි නිකුත් කර ඇත. ඔබ ඔවුන්ගේ නවතම මාදිලිය භාවිතා කරන්නේදැයි දෙවරක් පරීක්ෂා කිරීමට ඔබට HuggingFace හි සියලුම Qwen මාදිලි නැරඹිය හැක.
නිෂ්පාදන පරිසරයක් සඳහා, ඔබට වැඩි ප්රතිදානයක් සඳහා vLLM වැනි වේගවත් අනුමාන එන්ජිමක් භාවිතා කිරීමට අවශ්ය විය හැක.
Bark යනු බහු භාෂා මෙන්ම ශබ්ද ප්රයෝග සඳහා සහය දක්වන අති නවීන විවෘත-මූලාශ්ර පෙළ- සිට-කථන AI ආකෘතියකි.
from bark import SAMPLE_RATE, generate_audio, preload_models preload_models()
පොත්තට අමතරව, ඔබට වෙනත් විවෘත මූලාශ්ර හෝ හිමිකාර පෙළ සිට කථන ආකෘති ද භාවිතා කළ හැක. හිමිකාර ඒවා වඩාත් කාර්ය සාධනය විය හැකි අතර, ඒවා ඉතා ඉහළ පිරිවැයක් දරන බව මතක තබා ගන්න. TTS ක්ෂේත්රය යාවත්කාලීන සංසන්දනයක් තබා ගනී .
Qwen Audio 7B සහ Bark යන දෙකම මතකයට පටවා ඇති අතර, ආසන්න (V)RAM භාවිතය 24GB වේ, එබැවින් ඔබේ දෘඪාංග මෙයට සහය දක්වන බවට වග බලා ගන්න. එසේ නොමැතිනම්, ඔබට මතකය සුරැකීමට Qwen ආකෘතියේ ප්රමාණාත්මක අනුවාදයක් භාවිතා කළ හැක .
අපි එන ශ්රව්ය හෝ පෙළ ආදාන හැසිරවීමට සහ ශ්රව්ය ප්රතිචාර ලබා දීමට මාර්ග දෙකක් සහිත FastAPI සේවාදායකයක් සාදන්නෙමු.
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)
මෙම සේවාදායකය POST ඉල්ලීම් හරහා ශ්රව්ය ගොනු /voice
සහ /text
අන්ත ලක්ෂ්යයේදී පිළිගනී.
අපි එන ශ්රව්ය සැකසීමට සහ එය Qwen ආකෘතිය සඳහා සූදානම් කිරීමට ffmpeg භාවිතා කරන්නෙමු.
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
සැකසූ ශ්රව්ය සමඟ, අපට Qwen ආකෘතිය භාවිතයෙන් පෙළ ප්රතිචාරයක් ජනනය කළ හැක. මෙයට පෙළ සහ ශ්රව්ය ආදාන දෙකම හැසිරවීමට අවශ්ය වනු ඇත.
පූර්ව සකසනය අපගේ ආදානය ආකෘතියේ කතාබස් අච්චුවට පරිවර්තනය කරයි (Qwen නඩුවේ 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
ශ්රිතයේ උෂ්ණත්වය වැනි උත්පාදන පරාමිතීන් සමඟ සෙල්ලම් කිරීමට නිදහස් වන්න.
අවසාන වශයෙන්, අපි උත්පාදනය කරන ලද පෙළ ප්රතිචාරය නැවත කථනයට පරිවර්තනය කරන්නෙමු.
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
ශ්රව්ය හෝ පෙළ ආදානය සැකසීමට, ප්රතිචාරයක් උත්පාදනය කිරීමට සහ සංස්ලේෂණය කළ කථාව 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")
සහායක ප්රතිචාර කෙරෙහි වැඩි පාලනයක් ලබා ගැනීමට ඔබට සංවාදවලට පද්ධති පණිවිඩයක් එක් කිරීමට ද තෝරා ගත හැකිය.
අපගේ සේවාදායකය පිං කිරීමට අපට පහත පරිදි 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"
මෙම පියවර අනුගමනය කිරීමෙන්, ඔබ අති නවීන මාදිලි භාවිතයෙන් ද්වි-මාර්ග හඬ අන්තර්ක්රියා කළ හැකි සරල දේශීය සේවාදායකයක් පිහිටුවා ඇත. මෙම සැකසුම වඩාත් සංකීර්ණ හඬ-සක්රීය යෙදුම් තැනීම සඳහා පදනමක් ලෙස සේවය කළ හැක.
ඔබ AI බලයෙන් ක්රියාත්මක වන භාෂා ආකෘතිවලින් මුදල් ඉපැයීමේ ක්රම ගවේෂණය කරන්නේ නම්, මෙම විභව යෙදුම් සලකා බලන්න:
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)