paint-brush
अपना खुद का वॉयस असिस्टेंट कैसे बनाएं और इसे व्हिस्पर + ओलामा + बार्क का उपयोग करके स्थानीय रूप से कैसे चलाएंद्वारा@vndee
1,741 रीडिंग
1,741 रीडिंग

अपना खुद का वॉयस असिस्टेंट कैसे बनाएं और इसे व्हिस्पर + ओलामा + बार्क का उपयोग करके स्थानीय रूप से कैसे चलाएं

द्वारा Duy Huynh13m2024/04/02
Read on Terminal Reader

बहुत लंबा; पढ़ने के लिए

आवाज-आधारित इंटरैक्शन: उपयोगकर्ता अपने आवाज इनपुट को रिकॉर्ड करना शुरू और बंद कर सकते हैं, और सहायक उत्पन्न ऑडियो को वापस चलाकर प्रतिक्रिया देता है। संवादी संदर्भ: सहायक अधिक सुसंगत और प्रासंगिक प्रतिक्रियाओं को सक्षम करते हुए, बातचीत के संदर्भ को बनाए रखता है। लामा-2 भाषा मॉडल का उपयोग सहायक को संक्षिप्त और केंद्रित प्रतिक्रियाएँ प्रदान करने की अनुमति देता है।
featured image - अपना खुद का वॉयस असिस्टेंट कैसे बनाएं और इसे व्हिस्पर + ओलामा + बार्क का उपयोग करके स्थानीय रूप से कैसे चलाएं
Duy Huynh HackerNoon profile picture

अपना खुद का आरएजी कैसे बनाएं और इसे स्थानीय स्तर पर कैसे चलाएं, इस बारे में मेरी नवीनतम पोस्ट के बाद, आज, हम न केवल बड़े भाषा मॉडल की बातचीत क्षमताओं को लागू करके बल्कि सुनने और बोलने की क्षमताओं को भी जोड़कर इसे एक कदम आगे ले जा रहे हैं। विचार सीधा है: हम प्रतिष्ठित आयरन मैन फिल्मों से जार्विस या फ्राइडे की याद दिलाते हुए एक वॉयस असिस्टेंट बनाने जा रहे हैं, जो आपके कंप्यूटर पर ऑफ़लाइन काम कर सकता है।


चूंकि यह एक परिचयात्मक ट्यूटोरियल है, मैं इसे पायथन में लागू करूंगा और शुरुआती लोगों के लिए इसे काफी सरल रखूंगा। अंत में, मैं एप्लिकेशन को स्केल करने के तरीके पर कुछ मार्गदर्शन प्रदान करूंगा।

टेकस्टैक

सबसे पहले, आपको एक वर्चुअल पायथन वातावरण स्थापित करना चाहिए। इसके लिए आपके पास कई विकल्प हैं, जिनमें पाइनेव, वर्चुअलएन्व, कविता और अन्य शामिल हैं जो समान उद्देश्य को पूरा करते हैं। व्यक्तिगत रूप से, मैं अपनी व्यक्तिगत प्राथमिकताओं के कारण इस ट्यूटोरियल के लिए कविता का उपयोग करूँगा। यहां कई महत्वपूर्ण लाइब्रेरी हैं जिन्हें आपको इंस्टॉल करना होगा:


  • रिच : देखने में आकर्षक कंसोल आउटपुट के लिए।
  • ओपनाई-व्हिस्पर : वाक्-से-पाठ रूपांतरण के लिए एक मजबूत उपकरण।
  • सुनो-बार्क : टेक्स्ट-टू-स्पीच संश्लेषण के लिए एक अत्याधुनिक लाइब्रेरी, जो उच्च गुणवत्ता वाला ऑडियो आउटपुट सुनिश्चित करती है।
  • लैंगचैन : बड़े भाषा मॉडल (एलएलएम) के साथ इंटरफेस करने के लिए एक सीधी लाइब्रेरी।
  • साउंडडिवाइस , प्यूडियो और स्पीच रिकग्निशन : ऑडियो रिकॉर्डिंग और प्लेबैक के लिए आवश्यक।


निर्भरताओं की विस्तृत सूची के लिए, यहां लिंक देखें।


यहां सबसे महत्वपूर्ण घटक लार्ज लैंग्वेज मॉडल (एलएलएम) बैकएंड है, जिसके लिए हम ओलामा का उपयोग करेंगे। एलएलएम को ऑफ़लाइन चलाने और परोसने के लिए ओलामा को एक लोकप्रिय उपकरण के रूप में व्यापक रूप से मान्यता प्राप्त है। यदि ओलामा आपके लिए नया है, तो मैं ऑफ़लाइन आरएजी पर मेरे पिछले लेख को देखने की सलाह देता हूं: "अपना खुद का आरएजी बनाएं और इसे स्थानीय रूप से चलाएं: लैंगचैन + ओलामा + स्ट्रीमलिट।" मूल रूप से, आपको बस ओलामा एप्लिकेशन डाउनलोड करना होगा, अपना पसंदीदा मॉडल निकालना होगा और उसे चलाना होगा।

वास्तुकला

ठीक है, अगर सब कुछ सेट हो गया है, तो अगले चरण पर आगे बढ़ें। नीचे हमारे एप्लिकेशन का समग्र आर्किटेक्चर है, जिसमें मूल रूप से 3 मुख्य घटक शामिल हैं:


  • वाक् पहचान : ओपनएआई के व्हिस्पर का उपयोग करके, हम बोली जाने वाली भाषा को पाठ में परिवर्तित करते हैं। विविध डेटासेट पर व्हिस्पर का प्रशिक्षण विभिन्न भाषाओं और बोलियों में इसकी दक्षता सुनिश्चित करता है।


  • संवादी श्रृंखला : संवादात्मक क्षमताओं के लिए, हम लामा-2 मॉडल के लिए लैंगचैन इंटरफ़ेस का उपयोग करेंगे, जिसे ओलामा का उपयोग करके परोसा जाता है। यह सेटअप एक सहज और आकर्षक बातचीत प्रवाह का वादा करता है।


  • वाक् सिंथेसाइज़र : पाठ को वाक् में बदलना बार्क के माध्यम से प्राप्त किया जाता है, जो सुनो एआई का एक अत्याधुनिक मॉडल है, जो अपने जीवंत वाक् उत्पादन के लिए प्रसिद्ध है।


वर्कफ़्लो सीधा है: भाषण रिकॉर्ड करें, पाठ को ट्रांसक्राइब करें, एलएलएम का उपयोग करके प्रतिक्रिया उत्पन्न करें, और बार्क का उपयोग करके प्रतिक्रिया को मुखर करें।

व्हिस्पर, ओलामा और बार्क के साथ वॉयस असिस्टेंट के लिए अनुक्रम आरेख।

कार्यान्वयन

कार्यान्वयन की शुरुआत बार्क पर आधारित TextToSpeechService तैयार करने से होती है, जिसमें टेक्स्ट से भाषण को संश्लेषित करने और लंबे टेक्स्ट इनपुट को निर्बाध रूप से संभालने के तरीकों को शामिल किया जाता है:

 import nltk import torch import warnings import numpy as np from transformers import AutoProcessor, BarkModel warnings.filterwarnings( "ignore", message="torch.nn.utils.weight_norm is deprecated in favor of torch.nn.utils.parametrizations.weight_norm.", ) class TextToSpeechService: def __init__(self, device: str = "cuda" if torch.cuda.is_available() else "cpu"): """ Initializes the TextToSpeechService class. Args: device (str, optional): The device to be used for the model, either "cuda" if a GPU is available or "cpu". Defaults to "cuda" if available, otherwise "cpu". """ self.device = device self.processor = AutoProcessor.from_pretrained("suno/bark-small") self.model = BarkModel.from_pretrained("suno/bark-small") self.model.to(self.device) def synthesize(self, text: str, voice_preset: str = "v2/en_speaker_1"): """ Synthesizes audio from the given text using the specified voice preset. Args: text (str): The input text to be synthesized. voice_preset (str, optional): The voice preset to be used for the synthesis. Defaults to "v2/en_speaker_1". Returns: tuple: A tuple containing the sample rate and the generated audio array. """ inputs = self.processor(text, voice_preset=voice_preset, return_tensors="pt") inputs = {k: v.to(self.device) for k, v in inputs.items()} with torch.no_grad(): audio_array = self.model.generate(**inputs, pad_token_id=10000) audio_array = audio_array.cpu().numpy().squeeze() sample_rate = self.model.generation_config.sample_rate return sample_rate, audio_array def long_form_synthesize(self, text: str, voice_preset: str = "v2/en_speaker_1"): """ Synthesizes audio from the given long-form text using the specified voice preset. Args: text (str): The input text to be synthesized. voice_preset (str, optional): The voice preset to be used for the synthesis. Defaults to "v2/en_speaker_1". Returns: tuple: A tuple containing the sample rate and the generated audio array. """ pieces = [] sentences = nltk.sent_tokenize(text) silence = np.zeros(int(0.25 * self.model.generation_config.sample_rate)) for sent in sentences: sample_rate, audio_array = self.synthesize(sent, voice_preset) pieces += [audio_array, silence.copy()] return self.model.generation_config.sample_rate, np.concatenate(pieces)
  • आरंभीकरण ( __init__ ) : वर्ग एक वैकल्पिक device पैरामीटर लेता है, जो मॉडल के लिए उपयोग किए जाने वाले डिवाइस को निर्दिष्ट करता है (या तो यदि GPU उपलब्ध है तो cuda , या cpu )। यह बार्क मॉडल और संबंधित प्रोसेसर को suno/bark-small पूर्व-प्रशिक्षित मॉडल से लोड करता है। आप मॉडल लोडर के लिए suno/bark निर्दिष्ट करके बड़े संस्करण का भी उपयोग कर सकते हैं।


  • संश्लेषण ( synthesize ) : यह विधि एक text इनपुट और एक voice_preset पैरामीटर लेती है, जो संश्लेषण के लिए उपयोग की जाने वाली आवाज को निर्दिष्ट करती है। आप यहां अन्य voice_preset मान देख सकते हैं। यह इनपुट टेक्स्ट और वॉयस प्रीसेट तैयार करने के लिए processor का उपयोग करता है, और फिर model.generate() विधि का उपयोग करके ऑडियो ऐरे उत्पन्न करता है। उत्पन्न ऑडियो सरणी को NumPy सरणी में परिवर्तित कर दिया जाता है और नमूना दर ऑडियो सरणी के साथ वापस कर दी जाती है।


  • लॉन्ग-फॉर्म सिंथेसाइज़ ( long_form_synthesize ) : इस विधि का उपयोग लंबे टेक्स्ट इनपुट को संश्लेषित करने के लिए किया जाता है। यह पहले nltk.sent_tokenize फ़ंक्शन का उपयोग करके इनपुट टेक्स्ट को वाक्यों में टोकनाइज़ करता है। प्रत्येक वाक्य के लिए, यह ऑडियो सरणी उत्पन्न करने के लिए synthesize विधि को कॉल करता है। इसके बाद यह प्रत्येक वाक्य के बीच एक संक्षिप्त मौन (0.25 सेकंड) जोड़कर, उत्पन्न ऑडियो सरणियों को जोड़ता है।


अब जबकि हमारे पास TextToSpeechService सेटअप है, हमें बड़े भाषा मॉडल (एलएलएम) सेवा के लिए ओलामा सर्वर तैयार करने की आवश्यकता है। ऐसा करने के लिए, आपको इन चरणों का पालन करना होगा:


  • नवीनतम लामा-2 मॉडल खींचें : ओलामा भंडार से नवीनतम लामा-2 मॉडल डाउनलोड करने के लिए निम्नलिखित कमांड चलाएँ: ollama pull llama2


  • ओलामा सर्वर शुरू करें : यदि सर्वर अभी तक शुरू नहीं हुआ है, तो इसे शुरू करने के लिए निम्नलिखित कमांड निष्पादित करें: ollama serve


एक बार जब आप इन चरणों को पूरा कर लेंगे, तो आपका एप्लिकेशन उपयोगकर्ता इनपुट पर प्रतिक्रियाएं उत्पन्न करने के लिए ओलामा सर्वर और लामा-2 मॉडल का उपयोग करने में सक्षम होगा।


इसके बाद, हम मुख्य एप्लिकेशन लॉजिक की ओर बढ़ेंगे। सबसे पहले, हमें निम्नलिखित घटकों को आरंभ करने की आवश्यकता है:

  • रिच कंसोल : हम टर्मिनल के भीतर उपयोगकर्ता के लिए एक बेहतर इंटरैक्टिव कंसोल बनाने के लिए रिच लाइब्रेरी का उपयोग करेंगे।


  • व्हिस्पर स्पीच-टू-टेक्स्ट : हम एक व्हिस्पर स्पीच रिकग्निशन मॉडल शुरू करेंगे जो ओपनएआई द्वारा विकसित एक अत्याधुनिक ओपन-सोर्स स्पीच रिकग्निशन सिस्टम है। हम उपयोगकर्ता इनपुट को ट्रांसक्रिप्ट करने के लिए बेस इंग्लिश मॉडल ( base.en ) का उपयोग करेंगे।


  • बार्क टेक्स्ट-टू-स्पीच : हम एक बार्क टेक्स्ट-टू-स्पीच सिंथेसाइज़र इंस्टेंस शुरू करेंगे, जिसे ऊपर लागू किया गया था।


  • वार्तालाप श्रृंखला : हम लैंगचैन लाइब्रेरी से अंतर्निहित ConversationalChain उपयोग करेंगे जो वार्तालाप प्रवाह को प्रबंधित करने के लिए एक टेम्पलेट प्रदान करता है। हम इसे ओलामा बैकएंड के साथ लामा-2 भाषा मॉडल का उपयोग करने के लिए कॉन्फ़िगर करेंगे।
 import time import threading import numpy as np import whisper import sounddevice as sd from queue import Queue from rich.console import Console from langchain.memory import ConversationBufferMemory from langchain.chains import ConversationChain from langchain.prompts import PromptTemplate from langchain_community.llms import Ollama from tts import TextToSpeechService console = Console() stt = whisper.load_model("base.en") tts = TextToSpeechService() template = """ You are a helpful and friendly AI assistant. You are polite, respectful, and aim to provide concise responses of less than 20 words. The conversation transcript is as follows: {history} And here is the user's follow-up: {input} Your response: """ PROMPT = PromptTemplate(input_variables=["history", "input"], template=template) chain = ConversationChain( prompt=PROMPT, verbose=False, memory=ConversationBufferMemory(ai_prefix="Assistant:"), llm=Ollama(), )

अब, आइए आवश्यक कार्यों को परिभाषित करें:

  • record_audio : यह फ़ंक्शन sounddevice.RawInputStream का उपयोग करके उपयोगकर्ता के माइक्रोफ़ोन से ऑडियो डेटा कैप्चर करने के लिए एक अलग थ्रेड में चलता है। जब भी नया ऑडियो डेटा उपलब्ध होता है तो कॉलबैक फ़ंक्शन को कॉल किया जाता है, और यह आगे की प्रक्रिया के लिए डेटा को data_queue में डाल देता है।


  • transcribe : यह फ़ंक्शन data_queue से ऑडियो डेटा को टेक्स्ट में ट्रांसक्राइब करने के लिए व्हिस्पर इंस्टेंस का उपयोग करता है।


  • get_llm_response : यह फ़ंक्शन वर्तमान वार्तालाप संदर्भ को Llama-2 भाषा मॉडल (लैंगचैन ConversationalChain के माध्यम से) में फीड करता है और उत्पन्न टेक्स्ट प्रतिक्रिया को पुनः प्राप्त करता है।


  • play_audio : यह फ़ंक्शन बार्क टेक्स्ट-टू-स्पीच इंजन द्वारा उत्पन्न ऑडियो तरंग को लेता है और इसे ध्वनि प्लेबैक लाइब्रेरी (उदाहरण के लिए, sounddevice ) का उपयोग करके उपयोगकर्ता को वापस चलाता है।
 def record_audio(stop_event, data_queue): """ Captures audio data from the user's microphone and adds it to a queue for further processing. Args: stop_event (threading.Event): An event that, when set, signals the function to stop recording. data_queue (queue.Queue): A queue to which the recorded audio data will be added. Returns: None """ def callback(indata, frames, time, status): if status: console.print(status) data_queue.put(bytes(indata)) with sd.RawInputStream( samplerate=16000, dtype="int16", channels=1, callback=callback ): while not stop_event.is_set(): time.sleep(0.1) def transcribe(audio_np: np.ndarray) -> str: """ Transcribes the given audio data using the Whisper speech recognition model. Args: audio_np (numpy.ndarray): The audio data to be transcribed. Returns: str: The transcribed text. """ result = stt.transcribe(audio_np, fp16=False) # Set fp16=True if using a GPU text = result["text"].strip() return text def get_llm_response(text: str) -> str: """ Generates a response to the given text using the Llama-2 language model. Args: text (str): The input text to be processed. Returns: str: The generated response. """ response = chain.predict(input=text) if response.startswith("Assistant:"): response = response[len("Assistant:") :].strip() return response def play_audio(sample_rate, audio_array): """ Plays the given audio data using the sounddevice library. Args: sample_rate (int): The sample rate of the audio data. audio_array (numpy.ndarray): The audio data to be played. Returns: None """ sd.play(audio_array, sample_rate) sd.wait()

फिर, हम मुख्य एप्लिकेशन लूप को परिभाषित करते हैं। मुख्य एप्लिकेशन लूप उपयोगकर्ता को संवादात्मक इंटरैक्शन के माध्यम से निम्नानुसार मार्गदर्शन करता है:


  1. उपयोगकर्ता को अपना इनपुट रिकॉर्ड करना शुरू करने के लिए Enter दबाने के लिए कहा जाता है।


  2. एक बार जब उपयोगकर्ता एंटर दबाता है, तो उपयोगकर्ता के ऑडियो इनपुट को कैप्चर करने के लिए record_audio फ़ंक्शन को एक अलग थ्रेड में कॉल किया जाता है।


  3. जब उपयोगकर्ता रिकॉर्डिंग रोकने के लिए फिर से एंटर दबाता है, तो transcribe फ़ंक्शन का उपयोग करके ऑडियो डेटा ट्रांसक्राइब किया जाता है।


  4. फिर लिखित पाठ को get_llm_response फ़ंक्शन में भेज दिया जाता है, जो Llama-2 भाषा मॉडल का उपयोग करके प्रतिक्रिया उत्पन्न करता है।


  5. उत्पन्न प्रतिक्रिया कंसोल पर मुद्रित होती है और play_audio फ़ंक्शन का उपयोग करके उपयोगकर्ता को वापस चलायी जाती है।

 if __name__ == "__main__": console.print("[cyan]Assistant started! Press Ctrl+C to exit.") try: while True: console.input( "Press Enter to start recording, then press Enter again to stop." ) data_queue = Queue() # type: ignore[var-annotated] stop_event = threading.Event() recording_thread = threading.Thread( target=record_audio, args=(stop_event, data_queue), ) recording_thread.start() input() stop_event.set() recording_thread.join() audio_data = b"".join(list(data_queue.queue)) audio_np = ( np.frombuffer(audio_data, dtype=np.int16).astype(np.float32) / 32768.0 ) if audio_np.size > 0: with console.status("Transcribing...", spinner="earth"): text = transcribe(audio_np) console.print(f"[yellow]You: {text}") with console.status("Generating response...", spinner="earth"): response = get_llm_response(text) sample_rate, audio_array = tts.long_form_synthesize(response) console.print(f"[cyan]Assistant: {response}") play_audio(sample_rate, audio_array) else: console.print( "[red]No audio recorded. Please ensure your microphone is working." ) except KeyboardInterrupt: console.print("\n[red]Exiting...") console.print("[blue]Session ended.")

परिणाम

एक बार जब सब कुछ एक साथ रख दिया जाए, तो हम एप्लिकेशन चला सकते हैं जैसा कि ऊपर दिए गए वीडियो में दिखाया गया है। एप्लिकेशन मेरे मैकबुक पर काफी धीमी गति से चलता है क्योंकि बार्क मॉडल बड़ा है, यहां तक कि इसके छोटे संस्करण में भी। इसलिए, मैंने वीडियो की गति थोड़ी तेज़ कर दी है। CUDA-सक्षम कंप्यूटर वाले लोगों के लिए, यह तेज़ चल सकता है। यहां हमारे एप्लिकेशन की मुख्य विशेषताएं हैं:


  • आवाज-आधारित इंटरैक्शन : उपयोगकर्ता अपने आवाज इनपुट को रिकॉर्ड करना शुरू और बंद कर सकते हैं, और सहायक उत्पन्न ऑडियो को वापस चलाकर प्रतिक्रिया देता है।


  • संवादी संदर्भ: सहायक अधिक सुसंगत और प्रासंगिक प्रतिक्रियाओं को सक्षम करते हुए, बातचीत के संदर्भ को बनाए रखता है। लामा-2 भाषा मॉडल का उपयोग सहायक को संक्षिप्त और केंद्रित प्रतिक्रियाएँ प्रदान करने की अनुमति देता है।


इस एप्लिकेशन को उत्पादन-तैयार स्थिति तक बढ़ाने का लक्ष्य रखने वालों के लिए, निम्नलिखित संवर्द्धन की अनुशंसा की जाती है:

  • प्रदर्शन अनुकूलन : व्हिस्पर.सीपीपी, लामा.सीपीपी और बार्क.सीपीपी जैसे मॉडलों के अनुकूलित संस्करणों को शामिल करें, जो विशेष रूप से निचले स्तर के कंप्यूटरों पर प्रदर्शन को बढ़ावा देने के लिए डिज़ाइन किए गए हैं।


  • अनुकूलन योग्य बॉट संकेत : एक ऐसी प्रणाली लागू करें जो उपयोगकर्ताओं को बॉट के व्यक्तित्व और संकेत को अनुकूलित करने की अनुमति देती है, जिससे विभिन्न प्रकार के सहायकों (जैसे, व्यक्तिगत, पेशेवर, या डोमेन-विशिष्ट) के निर्माण को सक्षम किया जा सके।


  • ग्राफिकल यूजर इंटरफेस (जीयूआई) : समग्र उपयोगकर्ता अनुभव को बढ़ाने के लिए एक उपयोगकर्ता-अनुकूल जीयूआई विकसित करें, जिससे एप्लिकेशन अधिक सुलभ और दृश्यमान रूप से आकर्षक हो।


  • मल्टीमॉडल क्षमताएं : मल्टीमॉडल इंटरैक्शन का समर्थन करने के लिए एप्लिकेशन का विस्तार करें, जैसे ध्वनि-आधारित प्रतिक्रियाओं के अलावा छवियों, आरेखों या अन्य दृश्य सामग्री को उत्पन्न करने और प्रदर्शित करने की क्षमता।


अंत में, हमने अपना सरल वॉयस असिस्टेंट एप्लिकेशन पूरा कर लिया है, पूरा कोड यहां पाया जा सकता है: https://github.com/vndee/local-talking-llm । वाक् पहचान, भाषा मॉडलिंग और पाठ-से-वाक् प्रौद्योगिकियों का यह संयोजन दर्शाता है कि हम कैसे कुछ ऐसा बना सकते हैं जो कठिन लगता है लेकिन वास्तव में आपके कंप्यूटर पर चल सकता है। आइए कोडिंग का आनंद लें, और मेरे ब्लॉग की सदस्यता लेना न भूलें ताकि आप एआई और प्रोग्रामिंग के नवीनतम लेखों से न चूकें।


यहाँ भी प्रकाशित किया गया