ওপেনএআই যখন ChatGPT-এর জন্য উন্নত ভয়েস মোড প্রকাশ করতে করছে, আমি কীভাবে আমাদের LLM ভয়েস অ্যাপ্লিকেশন তৈরি করেছি এবং এটিকে একটি ইন্টারেক্টিভ বুথে সংহত করেছি তা শেয়ার করতে চাই। দেরি জঙ্গলে AI এর সাথে কথা বলুন ফেব্রুয়ারির শেষে, বালি বিখ্যাত বার্নিং ম্যান-এর নীতি অনুসারে সাজানো উৎসবের আয়োজন করেছিল। এর ঐতিহ্য অনুযায়ী, অংশগ্রহণকারীরা তাদের নিজস্ব ইনস্টলেশন এবং শিল্প বস্তু তৈরি করে। ল্যাম্পু এর আমার বন্ধুরা এবং আমি, ক্যাথলিক স্বীকারোক্তির ধারণা এবং বর্তমান LLM-এর ক্ষমতার দ্বারা অনুপ্রাণিত হয়ে, আমাদের নিজস্ব AI স্বীকারোক্তিমূলক নির্মাণের ধারণা নিয়ে এসেছি, যেখানে যে কেউ কৃত্রিম বুদ্ধিমত্তার সাথে কথা বলতে পারে। ক্যাম্প 19:19- শুরুতে আমরা কীভাবে এটি কল্পনা করেছি তা এখানে: যখন ব্যবহারকারী একটি বুথে প্রবেশ করে, আমরা নির্ধারণ করি যে আমাদের একটি নতুন অধিবেশন শুরু করতে হবে। ব্যবহারকারী একটি প্রশ্ন জিজ্ঞাসা করে, এবং AI শোনে এবং উত্তর দেয়। আমরা একটি বিশ্বস্ত এবং ব্যক্তিগত পরিবেশ তৈরি করতে চেয়েছিলাম যেখানে প্রত্যেকে তাদের চিন্তাভাবনা এবং অভিজ্ঞতা নিয়ে খোলামেলা আলোচনা করতে পারে। যখন ব্যবহারকারী রুম ছেড়ে যায়, সিস্টেমটি সেশন শেষ করে এবং কথোপকথনের সমস্ত বিবরণ ভুলে যায়। সমস্ত ডায়ালগ ব্যক্তিগত রাখার জন্য এটি প্রয়োজনীয়। ধারণার প্রমাণ ধারণাটি পরীক্ষা করতে এবং LLM-এর জন্য একটি প্রম্পট দিয়ে পরীক্ষা শুরু করতে, আমি এক সন্ধ্যায় একটি নিষ্প্রভ বাস্তবায়ন তৈরি করেছি: একটি মাইক্রোফোন শুনুন। মডেল ব্যবহার করে ব্যবহারকারীর বক্তৃতা শনাক্ত করুন। স্পিচ-টু-টেক্সট (STT) এর মাধ্যমে একটি প্রতিক্রিয়া তৈরি করুন। LLM মডেল ব্যবহার করে একটি ভয়েস প্রতিক্রিয়া সংশ্লেষিত করুন। টেক্সট-টু-স্পীচ (TTS) ব্যবহারকারীর প্রতিক্রিয়া প্লে ব্যাক করুন। এই ডেমোটি বাস্তবায়ন করতে, আমি সম্পূর্ণরূপে OpenAI থেকে ক্লাউড মডেলের উপর নির্ভর করেছি: , , এবং । চমৎকার লাইব্রেরি এর জন্য ধন্যবাদ, আমি কোডের মাত্র কয়েক ডজন লাইনে ডেমো তৈরি করেছি। হুইস্পার GPT-4 TTS speech_recognition- import os import asyncio from dotenv import load_dotenv from io import BytesIO from openai import AsyncOpenAI from soundfile import SoundFile import sounddevice as sd import speech_recognition as sr load_dotenv() aiclient = AsyncOpenAI( api_key=os.environ.get("OPENAI_API_KEY") ) SYSTEM_PROMPT = """ You are helpfull assistant. """ async def listen_mic(recognizer: sr.Recognizer, microphone: sr.Microphone): audio_data = recognizer.listen(microphone) wav_data = BytesIO(audio_data.get_wav_data()) wav_data.name = "SpeechRecognition_audio.wav" return wav_data async def say(text: str): res = await aiclient.audio.speech.create( model="tts-1", voice="alloy", response_format="opus", input=text ) buffer = BytesIO() for chunk in res.iter_bytes(chunk_size=4096): buffer.write(chunk) buffer.seek(0) with SoundFile(buffer, 'r') as sound_file: data = sound_file.read(dtype='int16') sd.play(data, sound_file.samplerate) sd.wait() async def respond(text: str, history): history.append({"role": "user", "content": text}) completion = await aiclient.chat.completions.create( model="gpt-4", temperature=0.5, messages=history, ) response = completion.choices[0].message.content await say(response) history.append({"role": "assistant", "content": response}) async def main() -> None: m = sr.Microphone() r = sr.Recognizer() messages = [{"role": "system", "content": SYSTEM_PROMPT}] with m as source: r.adjust_for_ambient_noise(source) while True: wav_data = await listen_mic(r, source) transcript = await aiclient.audio.transcriptions.create( model="whisper-1", temperature=0.5, file=wav_data, response_format="verbose_json", ) if transcript.text == '' or transcript.text is None: continue await respond(transcript.text, messages) if __name__ == '__main__': asyncio.run(main()) আমাদের যে সমস্যাগুলি সমাধান করতে হয়েছিল তা এই ডেমোর প্রথম পরীক্ষার পরে স্পষ্ট হয়ে ওঠে: . একটি নির্বোধ বাস্তবায়নে, ব্যবহারকারীর প্রশ্ন এবং উত্তরের মধ্যে বিলম্ব 7-8 সেকেন্ড বা তার বেশি। এটি ভাল নয়, তবে স্পষ্টতই, প্রতিক্রিয়া সময় অপ্টিমাইজ করার অনেক উপায় রয়েছে। প্রতিক্রিয়া বিলম্ব । আমরা আবিষ্কার করেছি যে কোলাহলপূর্ণ পরিবেশে, ব্যবহারকারী কখন স্বয়ংক্রিয়ভাবে কথা বলা শুরু করেছেন এবং শেষ করেছেন তা সনাক্ত করতে আমরা মাইক্রোফোনের উপর নির্ভর করতে পারি না। একটি বাক্যাংশের শুরু এবং শেষ ( ) সনাক্ত করা একটি অ-তুচ্ছ কাজ। এটিকে একটি সঙ্গীত উত্সবের কোলাহলপূর্ণ পরিবেশের সাথে সংযুক্ত করুন এবং এটি স্পষ্ট যে একটি ধারণাগতভাবে ভিন্ন পদ্ধতির প্রয়োজন। পরিবেষ্টিত গোলমাল শেষবিন্দু . আমরা ব্যবহারকারীকে এআই বাধা দেওয়ার ক্ষমতা দিতে চেয়েছিলাম। এটি অর্জন করতে, আমাদের মাইক্রোফোন চালু রাখতে হবে। কিন্তু এই ক্ষেত্রে, আমাদের ব্যবহারকারীর ভয়েসকে শুধুমাত্র ব্যাকগ্রাউন্ডের শব্দ থেকে নয় বরং AI এর ভয়েস থেকেও আলাদা করতে হবে। লাইভ কথোপকথন অনুকরণ প্রতিক্রিয়া বিলম্বের কারণে, আমাদের কাছে মাঝে মাঝে মনে হয়েছিল যে সিস্টেমটি হিমায়িত হয়ে গেছে। আমরা বুঝতে পেরেছি যে কতক্ষণ প্রতিক্রিয়া প্রক্রিয়া করা হবে তা ব্যবহারকারীকে জানাতে হবে প্রতিক্রিয়া আমাদের কাছে এই সমস্যাগুলি কীভাবে সমাধান করা যায় তার একটি পছন্দ ছিল: একটি উপযুক্ত প্রকৌশল বা পণ্য সমাধান খোঁজার মাধ্যমে। বুথের ইউএক্সের মাধ্যমে চিন্তা করা আমরা কোড করার আগে, ব্যবহারকারী বুথের সাথে কীভাবে ইন্টারঅ্যাক্ট করবে তা আমাদের সিদ্ধান্ত নিতে হয়েছিল: অতীতের ডায়লগ ইতিহাস পুনরায় সেট করতে বুথে একজন নতুন ব্যবহারকারীকে কীভাবে সনাক্ত করা যায় তা আমাদের সিদ্ধান্ত নেওয়া উচিত। ব্যবহারকারীর বক্তৃতার শুরু এবং শেষ কীভাবে চিনবেন এবং তারা AI বাধা দিতে চাইলে কী করবেন। এআই থেকে দেরি হলে প্রতিক্রিয়া কীভাবে কার্যকর করা যায়। বুথে একজন নতুন ব্যবহারকারীকে শনাক্ত করতে, আমরা বেশ কয়েকটি বিকল্প বিবেচনা করেছি: দরজা খোলার সেন্সর, মেঝে ওজন সেন্সর, দূরত্ব সেন্সর, এবং একটি ক্যামেরা + YOLO মডেল। পিছনের পিছনের দূরত্ব সেন্সরটি আমাদের কাছে সবচেয়ে নির্ভরযোগ্য বলে মনে হয়েছিল, কারণ এটি দুর্ঘটনাজনিত ট্রিগারগুলিকে বাদ দেয়, যেমন যখন দরজাটি যথেষ্ট শক্তভাবে বন্ধ থাকে না এবং ওজন সেন্সরের বিপরীতে জটিল ইনস্টলেশনের প্রয়োজন হয় না। একটি ডায়ালগের শুরু এবং শেষ সনাক্ত করার চ্যালেঞ্জ এড়াতে, আমরা মাইক্রোফোন নিয়ন্ত্রণ করতে একটি বড় লাল বোতাম যুক্ত করার সিদ্ধান্ত নিয়েছি। এই সমাধানটি ব্যবহারকারীকে যেকোন মুহুর্তে AI বাধা দেওয়ার অনুমতি দেয়। একটি অনুরোধ প্রক্রিয়াকরণে প্রতিক্রিয়া বাস্তবায়ন সম্পর্কে আমাদের অনেক ভিন্ন ধারণা ছিল। আমরা একটি স্ক্রীন সহ একটি বিকল্পের সিদ্ধান্ত নিয়েছি যা দেখায় যে সিস্টেমটি কী করছে: মাইক্রোফোন শোনা, একটি প্রশ্ন প্রক্রিয়া করা বা উত্তর দেওয়া। আমরা একটি পুরানো ল্যান্ডলাইন ফোনের সাথে একটি বরং স্মার্ট বিকল্প বিবেচনা করেছি। ব্যবহারকারী ফোন তুললে সেশন শুরু হবে, এবং সিস্টেমটি ব্যবহারকারীর কথা শুনবে যতক্ষণ না সে হ্যাং করে। যাইহোক, আমরা সিদ্ধান্ত নিয়েছি যে ব্যবহারকারী ফোন থেকে একটি ভয়েসের পরিবর্তে বুথ দ্বারা "উত্তর" দিলে এটি আরও খাঁটি। শেষ পর্যন্ত, চূড়ান্ত ব্যবহারকারী প্রবাহ এই মত বেরিয়ে এসেছে: একজন ব্যবহারকারী একটি বুথে হাঁটছেন। একটি দূরত্ব সেন্সর তার পিছনে ট্রিগার, এবং আমরা তাকে অভিবাদন. ব্যবহারকারী একটি ডায়ালগ শুরু করতে একটি লাল বোতাম টিপে৷ বোতাম টিপলে আমরা মাইক্রোফোন শুনি। যখন ব্যবহারকারী বোতামটি প্রকাশ করে, আমরা অনুরোধটি প্রক্রিয়া করা শুরু করি এবং এটি স্ক্রিনে নির্দেশ করি। AI উত্তর দেওয়ার সময় ব্যবহারকারী যদি একটি নতুন প্রশ্ন জিজ্ঞাসা করতে চান, তাহলে তারা আবার বোতাম টিপতে পারেন এবং AI অবিলম্বে উত্তর দেওয়া বন্ধ করে দেবে। যখন ব্যবহারকারী বুথ ছেড়ে যায়, তখন দূরত্ব সেন্সর আবার ট্রিগার করে, এবং আমরা ডায়ালগ ইতিহাস সাফ করি। স্থাপত্য দূরত্ব সেন্সর এবং লাল বোতামের অবস্থা পর্যবেক্ষণ করে। এটি HTTP API-এর মাধ্যমে আমাদের ব্যাকএন্ডে সমস্ত পরিবর্তন পাঠায়, যা সিস্টেমকে নির্ধারণ করতে দেয় যে ব্যবহারকারী বুথে প্রবেশ করেছে বা ছেড়ে গেছে এবং মাইক্রোফোন শোনা সক্রিয় করা বা প্রতিক্রিয়া তৈরি করা শুরু করা প্রয়োজন কিনা। Arduino হল একটি ব্রাউজারে খোলা একটি ওয়েব পৃষ্ঠা যা ব্যাকএন্ড থেকে ক্রমাগত সিস্টেমের বর্তমান অবস্থা গ্রহণ করে এবং ব্যবহারকারীর কাছে প্রদর্শন করে। ওয়েব UI মাইক্রোফোন নিয়ন্ত্রণ করে, সমস্ত প্রয়োজনীয় AI মডেলের সাথে ইন্টারঅ্যাক্ট করে এবং LLM প্রতিক্রিয়াগুলিকে ভয়েস করে। এতে অ্যাপের মূল যুক্তি রয়েছে। ব্যাকএন্ড হার্ডওয়্যার কিভাবে Arduino এর জন্য একটি স্কেচ কোড করতে হয়, দূরত্ব সেন্সর এবং বোতামটি সঠিকভাবে সংযুক্ত করুন এবং বুথে এটি একত্রিত করুন একটি পৃথক নিবন্ধের জন্য একটি বিষয়। প্রযুক্তিগত বিবরণে না গিয়ে আমরা কী পেয়েছি তা সংক্ষেপে পর্যালোচনা করি। আমরা একটি Arduino ব্যবহার করেছি, আরও স্পষ্টভাবে, একটি বিল্ট-ইন Wi-Fi মডিউল সহ মডেল । মাইক্রোকন্ট্রোলারটি ল্যাপটপের মতো একই Wi-Fi নেটওয়ার্কের সাথে সংযুক্ত ছিল, যা ব্যাকএন্ডে চলছিল। ESP32 আমরা যে হার্ডওয়্যার ব্যবহার করেছি তার সম্পূর্ণ তালিকা: - আমরা এটি আমাদের বন্ধুদের কাছ থেকে ধার করেছি :) স্কাইপ বুথ - $29 ESP32 - $5 বড় লাল বোতাম - $10 প্রক্সিমিটি সেন্সর ওল্ড ম্যাকবুক এয়ার - আমাদের একটি ছিল। ব্যাকএন্ড পাইপলাইনের প্রধান উপাদান হল স্পিচ-টু-টেক্সট (এসটিটি), এলএলএম এবং টেক্সট-টু-স্পিচ (টিটিএস)। প্রতিটি কাজের জন্য, অনেকগুলি বিভিন্ন মডেল স্থানীয়ভাবে এবং ক্লাউডের মাধ্যমে উপলব্ধ। যেহেতু আমাদের হাতে একটি শক্তিশালী GPU নেই, তাই আমরা মডেলগুলির ক্লাউড-ভিত্তিক সংস্করণগুলি বেছে নেওয়ার সিদ্ধান্ত নিয়েছি। এই পদ্ধতির দুর্বলতা হল একটি ভাল ইন্টারনেট সংযোগের প্রয়োজন। তা সত্ত্বেও, সমস্ত অপ্টিমাইজেশনের পর মিথস্ক্রিয়া গতি গ্রহণযোগ্য ছিল, এমনকি উৎসবে আমাদের মোবাইল ইন্টারনেটের সাথেও। এখন, আসুন পাইপলাইনের প্রতিটি উপাদান ঘনিষ্ঠভাবে দেখুন। কন্ঠ সনান্তকরণ অনেক আধুনিক ডিভাইস দীর্ঘদিন ধরে স্পিচ রিকগনিশনকে সমর্থন করেছে। উদাহরণস্বরূপ, iOS এবং macOS এর জন্য উপলব্ধ এবং ব্রাউজারগুলির জন্য। Apple Speech API ওয়েব স্পিচ API দুর্ভাগ্যবশত, তারা বা মানের দিক থেকে খুবই নিকৃষ্ট এবং স্বয়ংক্রিয়ভাবে ভাষা সনাক্ত করতে পারে না। হুইস্পার ডিপগ্রামের প্রক্রিয়াকরণের সময় কমাতে, ব্যবহারকারীর কথা বলার সাথে সাথে রিয়েল-টাইমে বক্তৃতা চিনতে সর্বোত্তম বিকল্প। সেগুলি কীভাবে বাস্তবায়ন করা যায় তার উদাহরণ সহ এখানে কিছু প্রকল্প রয়েছে: , whisper_streaming whisper.cpp আমাদের ল্যাপটপের সাথে, এই পদ্ধতি ব্যবহার করে বক্তৃতা স্বীকৃতির গতি বাস্তব সময়ের থেকে অনেক দূরে পরিণত হয়েছে। বেশ কিছু পরীক্ষার পর, আমরা OpenAI থেকে ক্লাউড-ভিত্তিক হুইস্পার মডেলের সিদ্ধান্ত নিয়েছি। এলএলএম এবং প্রম্পট ইঞ্জিনিয়ারিং আগের ধাপের স্পিচ টু টেক্সট মডেলের ফলাফল হল ডায়ালগ ইতিহাস সহ আমরা এলএলএম-এ যে পাঠ্য পাঠাই। একটি LLM নির্বাচন করার সময়, আমরা GPT-3.5 এর সাথে তুলনা করি। GPT-4 এবং Claude. দেখা গেল যে মূল ফ্যাক্টরটি এর কনফিগারেশনের মতো নির্দিষ্ট মডেলটি এত বেশি ছিল না। শেষ পর্যন্ত, আমরা GPT-4-এ বসতি স্থাপন করেছি, যার উত্তর আমরা অন্যদের চেয়ে বেশি পছন্দ করেছি। এলএলএম মডেলের জন্য প্রম্পটের কাস্টমাইজেশন একটি পৃথক শিল্প ফর্ম হয়ে উঠেছে। আপনার প্রয়োজন অনুসারে কীভাবে আপনার মডেল টিউন করবেন সে সম্পর্কে ইন্টারনেটে অনেক গাইড রয়েছে: OpenAI প্রম্পট ইঞ্জিনিয়ারিং গাইড নৃতাত্ত্বিক প্রম্পট ইঞ্জিনিয়ারিং প্রম্পট ইঞ্জিনিয়ারিং গাইড মডেলটিকে আকর্ষক, সংক্ষিপ্তভাবে এবং হাস্যকরভাবে প্রতিক্রিয়া জানাতে আমাদের প্রম্পট এবং সেটিংসের সাথে ব্যাপকভাবে পরীক্ষা করতে হয়েছিল। তাপমাত্রা টেক্সট-টু-স্পিচ আমরা টেক্সট-টু-স্পিচ মডেল ব্যবহার করে এলএলএম থেকে প্রাপ্ত প্রতিক্রিয়ার কথা বলি এবং ব্যবহারকারীর কাছে তা ফিরিয়ে দেই। এই পদক্ষেপটি আমাদের ডেমোতে বিলম্বের প্রাথমিক উত্স ছিল। এলএলএমগুলি সাড়া দিতে বেশ দীর্ঘ সময় নেয়। যাইহোক, তারা স্ট্রিমিং মোডে প্রতিক্রিয়া তৈরি করতে সমর্থন করে - টোকেন দ্বারা টোকেন। LLM-এর সম্পূর্ণ প্রতিক্রিয়ার জন্য অপেক্ষা না করেই আমরা এই বৈশিষ্ট্যটি ব্যবহার করে অপেক্ষার সময়কে অপ্টিমাইজ করার জন্য পৃথক বাক্যাংশগুলি উচ্চারণ করতে পারি। এলএলএম-এ একটি প্রশ্ন করুন। আমরা টোকেন দ্বারা বাফার টোকেনে প্রতিক্রিয়া জমা করি যতক্ষণ না আমাদের একটি সম্পূর্ণ বাক্য থাকে। প্যারামিটারটি তাৎপর্যপূর্ণ কারণ এটি কণ্ঠস্বর এবং প্রাথমিক বিলম্বের সময় উভয়কেই প্রভাবিত করে। ন্যূনতম দৈর্ঘ্যের ন্যূনতম দৈর্ঘ্যের উৎপন্ন বাক্য টিটিএস মডেলে পাঠান এবং ফলাফলটি ব্যবহারকারীর কাছে চালান। এই ধাপে, প্লেব্যাক অর্ডারে কোন রেসের শর্ত নেই তা নিশ্চিত করা প্রয়োজন। এলএলএম প্রতিক্রিয়া শেষ না হওয়া পর্যন্ত পূর্ববর্তী পদক্ষেপটি পুনরাবৃত্তি করুন LLM থেকে প্রতিক্রিয়ার অবশিষ্ট অংশগুলি প্রক্রিয়াকরণে বিলম্ব লুকানোর জন্য ব্যবহারকারী প্রাথমিক খণ্ডটি শোনার সময় আমরা সময় ব্যবহার করি। এই পদ্ধতির জন্য ধন্যবাদ, প্রতিক্রিয়া বিলম্ব শুধুমাত্র শুরুতে ঘটে এবং ~3 সেকেন্ড। async generateResponse(history) { const completion = await this.ai.completion(history); const chunks = new DialogChunks(); for await (const chunk of completion) { const delta = chunk.choices[0]?.delta?.content; if (delta) { chunks.push(delta); if (chunks.hasCompleteSentence()) { const sentence = chunks.popSentence(); this.voice.ttsAndPlay(sentence); } } } const sentence = chunks.popSentence(); if (sentence) { this.voice.say(sentence); } return chunks.text; } চূড়ান্ত স্পর্শ এমনকি আমাদের সমস্ত অপ্টিমাইজেশন সহ, একটি 3-4 সেকেন্ড বিলম্ব এখনও তাৎপর্যপূর্ণ। প্রতিক্রিয়া হ্যাং হয়ে গেছে এমন অনুভূতি থেকে ব্যবহারকারীকে বাঁচাতে আমরা প্রতিক্রিয়া সহ UI এর যত্ন নেওয়ার সিদ্ধান্ত নিয়েছি। আমরা বেশ কয়েকটি পন্থা দেখেছি: । আমাদের পাঁচটি অবস্থা প্রদর্শন করতে হবে: নিষ্ক্রিয়, অপেক্ষা করা, শোনা, চিন্তা করা এবং কথা বলা। কিন্তু LED এর সাহায্যে বোঝা সহজ ছিল এমন একটি উপায়ে কীভাবে এটি করা যায় তা আমরা বের করতে পারিনি। LED সূচক , যেমন "আমাকে ভাবতে দাও," "হুম" ইত্যাদি, বাস্তব জীবনের বক্তৃতা অনুকরণ করে। আমরা এই বিকল্পটি প্রত্যাখ্যান করেছি কারণ ফিলারগুলি প্রায়শই মডেলের প্রতিক্রিয়াগুলির স্বরের সাথে মেলে না৷ ভরাট শব্দ বুথে রাখুন। এবং অ্যানিমেশন সহ বিভিন্ন রাজ্য প্রদর্শন করুন। একটি পর্দা আমরা একটি সাধারণ ওয়েব পৃষ্ঠার সাথে শেষ বিকল্পে স্থির হয়েছি যা ব্যাকএন্ড পোল করে এবং বর্তমান অবস্থা অনুযায়ী অ্যানিমেশন দেখায়। ফলাফলগুলো আমাদের AI স্বীকারোক্তি রুম চার দিন ধরে চলেছিল এবং শত শত অংশগ্রহণকারীদের আকৃষ্ট করেছিল। আমরা ওপেনএআই এপিআই-এ প্রায় $50 খরচ করেছি। বিনিময়ে, আমরা যথেষ্ট ইতিবাচক প্রতিক্রিয়া এবং মূল্যবান ইমপ্রেশন পেয়েছি। এই ছোট পরীক্ষাটি দেখিয়েছে যে সীমিত সংস্থান এবং চ্যালেঞ্জিং বাহ্যিক অবস্থার মধ্যেও একটি এলএলএম-এ একটি স্বজ্ঞাত এবং দক্ষ ভয়েস ইন্টারফেস যুক্ত করা সম্ভব। যাইহোক, ব্যাকএন্ড উত্সগুলি GitHub-এ উপলব্ধ