diff --git a/Archives/TTStest.py b/Archives/TTStest.py new file mode 100644 index 0000000..fd72132 --- /dev/null +++ b/Archives/TTStest.py @@ -0,0 +1,11 @@ +from openai import OpenAI + +client = OpenAI() + +response = client.audio.speech.create( + model="tts-1-hd", + voice="echo", + input="Test Audio", +) + +response.stream_to_file("output.mp3") \ No newline at end of file diff --git a/Archives/text-to-response-test.py b/Archives/text-to-response-test.py new file mode 100644 index 0000000..06594d5 --- /dev/null +++ b/Archives/text-to-response-test.py @@ -0,0 +1,69 @@ +from openai import OpenAI +import io +import os +import time + +client = OpenAI(default_headers={"OpenAI-Beta": "assistants=v2"}) + + +def query_and_record(prompt, mp3_filename): + # Retrieve the OpenAI API key from environment variables + api_key = os.getenv("OPENAI_API_KEY") + if not api_key: + raise ValueError("OpenAI API key is not set in environment variables.") + + + assistant = client.beta.assistants.create( + name="Senior Tech Help", + instructions="You are a helpful tech teach specifically for seniors. You will help older adults (ages 50+) with quick questions about smartphones, voice assistants, computers, cameras, the internet, digital shopping, or any other technology related topic. You will always ask for specifics, like what device or phone they are using, and provide them with step by step instructions for their response.", + model="gpt-4-turbo", + ) + + + thread = client.beta.threads.create() + + message = client.beta.threads.messages.create( + thread_id=thread.id, + role="user", + content=prompt + ) + + run = client.beta.threads.runs.create( + thread_id=thread.id, + assistant_id=assistant.id, + instructions="Please address the user as Jane Doe. The user has a premium account." + ) + + while run.status == "in_progress" or run.status == "queued": + time.sleep(1) + run = client.beta.threads.runs.retrieve( + thread_id=thread.id, + run_id=run.id + ) + + if run.status == "completed": + message_list = client.beta.threads.messages.list( + thread_id=thread.id + ) + + + + # Extract the text from the response + text_response = message_list.data[0].content[0].text.value + + #print(text_response) + + response = client.audio.speech.create( + model="tts-1-hd", + voice="echo", + input=text_response, + ) + + response.stream_to_file(mp3_filename) + + return print("Response recorded to " + mp3_filename) + +# Example usage +prompt = input("Enter your tech question for Helper Bee:") +mp3_filename = "response.mp3" +query_and_record(prompt, mp3_filename) diff --git a/Archives/wake-word-assistant.py b/Archives/wake-word-assistant.py new file mode 100644 index 0000000..e1040d8 --- /dev/null +++ b/Archives/wake-word-assistant.py @@ -0,0 +1,187 @@ +from dotenv import load_dotenv +import sounddevice as sd +import struct +import numpy as np +import tempfile +import pvporcupine +import wave +import os +import time +from pvrecorder import PvRecorder +import wavio +from openai import OpenAI +import pygame + +load_dotenv() + +# Retrieve the OpenAI API key and Porcupine access key from environment variables +openai_api_key = os.getenv("OPENAI_API_KEY") +porcupine_access_key = os.getenv("PORCUPINE_ACCESS_KEY") +assistant_api_key = os.getenv("ASSISTANT_API_KEY") + +sd.default.device = None #'seeed-2mic-voicecard' + +if not openai_api_key: + raise ValueError("OpenAI API key is not set in environment variables.") +if not porcupine_access_key: + raise ValueError("Porcupine access key is not set in environment variables.") + +# Initialize OpenAI client +client = OpenAI(api_key=openai_api_key, default_headers={"OpenAI-Beta": "assistants=v2"}) + +# Initialize Porcupine +porcupine = pvporcupine.create( + access_key=porcupine_access_key, + keywords=["picovoice", "bumblebee"] +) + +def record_audio(samplerate=44100, chunk_duration=1, silence_threshold=2000): + """ + Record audio from the default microphone until silence is detected. + """ + print("Recording... Press Ctrl+C to stop.") + audio_file = [] + + try: + while True: + recording = sd.rec(int(chunk_duration * samplerate), samplerate=samplerate, channels=1, dtype='int16') + sd.wait() + audio_file.append(recording) + + # Check if the last recorded chunk is silent + if is_silent(recording, silence_threshold): + print("Silence detected, stopping recording.") + break + + except KeyboardInterrupt: + print("Recording stopped manually.") + + if audio_file: + audio_file = np.concatenate(audio_file, axis=0) + return audio_file + else: + raise ValueError("No audio file recorded.") + +def is_silent(file, threshold=500): + """ + Returns True if the audio file is below the silent threshold. + """ + return np.abs(file).mean() < threshold + +def query_and_record(prompt): + """ + Send a prompt to the OpenAI assistant and record the response as an MP3 file. + """ + # # Create an assistant instance + # assistant = client.beta.assistants.create( + # name="Senior Tech Help", + # instructions="You are a helpful tech teacher specifically for seniors. You will help older adults (ages 50+) with quick questions about smartphones, voice assistants, computers, cameras, the internet, digital shopping, or any other technology-related topic. You will always ask for specifics, like what device or phone they are using, and provide them with step-by-step instructions for their response.", + # model="gpt-4o" + # ) + assistant_id = assistant_api_key + + # Create a thread for communication + thread = client.beta.threads.create() + + # Send user's prompt to the AI + message = client.beta.threads.messages.create( + thread_id=thread.id, + role="user", + content=prompt + ) + + # Start the AI to process the user prompt + run = client.beta.threads.runs.create( + thread_id=thread.id, + assistant_id=assistant_id, + instructions="Please address the user as Jane Doe. The user has a premium account." + ) + + # Wait until AI is complete with processing + while run.status in ["in_progress", "queued"]: + time.sleep(1) + run = client.beta.threads.runs.retrieve( + thread_id=thread.id, + run_id=run.id + ) + + if run.status == "completed": + message_list = client.beta.threads.messages.list( + thread_id=thread.id + ) + # Extract the text content from the response + # text_response = "" + # for message in message_list.data: + # if message.role == "assistant" and message.content: + # text_response += message.content + "\n" + + + text_response = message_list.data[0].content[0].text.value + + # Generate an audio response from the text + response = client.audio.speech.create( + model="tts-1-hd", + voice="echo", + input=text_response, + ) + + with tempfile.NamedTemporaryFile(suffix=".mp3", delete=False) as tmpfile: + mp3_filename = tmpfile.name + response.stream_to_file(mp3_filename) + + print("Response recorded to " + mp3_filename) + + # Initialize pygame mixer + pygame.mixer.init() + + # Load the mp3 file + pygame.mixer.music.load(mp3_filename) + + # Play the mp3 file + pygame.mixer.music.play() + + # Wait until the music finishes playing + while pygame.mixer.music.get_busy(): + pygame.time.Clock().tick(10) + +# Main loop for keyword detection and interaction +recorder = PvRecorder(frame_length=porcupine.frame_length) +recorder.start() + +try: + while True: + pcm = recorder.read() + keyword_index = porcupine.process(pcm) + + if keyword_index == 0: + print("Detected 'picovoice'") + elif keyword_index == 1: + print("Detected 'bumblebee'") + + # Record audio from the microphone + audio_file = record_audio() + + # Convert audio to text using OpenAI API + with tempfile.NamedTemporaryFile(suffix=".wav", delete=False) as tmpfile: + tmpfilename = tmpfile.name + wavio.write(tmpfilename, audio_file, 44100, sampwidth=2) + + transcription = client.audio.transcriptions.create( + model="whisper-1", + file=open(tmpfilename, "rb"), + ) + + print("Transcription:", transcription.text) + + # Example usage + prompt = transcription.text + query_and_record(prompt) + +except KeyboardInterrupt: + print("Script interrupted.") +finally: +# Ensuring proper release of resources + if porcupine is not None: + porcupine.delete() + recorder.stop() + recorder.delete() diff --git a/Archives/wake-word-audio.py b/Archives/wake-word-audio.py new file mode 100644 index 0000000..bf371c5 --- /dev/null +++ b/Archives/wake-word-audio.py @@ -0,0 +1,112 @@ +import sounddevice as sd +import numpy as np +import tempfile +import wavio +from openai import OpenAI +import threading +import os +import pvporcupine +#from pvrecorder import PvRecorder +import time +from response import handle_interaction +from dotenv import load_dotenv + +load_dotenv() + +# Retrieve the OpenAI API key and Porcupine access key from environment variables +openai_api_key = os.getenv("OPENAI_API_KEY") +porcupine_access_key = os.getenv("PORCUPINE_ACCESS_KEY") + +if not openai_api_key: + raise ValueError("OpenAI API key is not set in environment variables.") +if not porcupine_access_key: + raise ValueError("Porcupine access key is not set in environment variables.") + +# Initialize Porcupine +porcupine = pvporcupine.create( + access_key=porcupine_access_key, + keywords=["picovoice", "bumblebee"] +) + +# Initialize the OpenAI client +client = OpenAI(api_key=openai_api_key, default_headers={"OpenAI-Beta": "assistants=v2"}) + +def record_audio(samplerate=44100, chunk_duration=1, silence_threshold=1000, silence_duration=10): + """ + Record audio in real-time and stop when silence is detected for the specified duration. + """ + print("Recording... Press Ctrl+C to stop.") + audio_file = [] + silence_start_time = None + chunk_size = int(chunk_duration * samplerate) + + try: + with sd.InputStream(samplerate=samplerate, channels=1, dtype='int16', callback=lambda indata, frames, time, status: audio_file.append(indata.copy())): + while True: + if len(audio_file) > 0: + last_chunk = audio_file[-1] + + # Check if the last chunk is silent + if is_silent(last_chunk, silence_threshold): + if silence_start_time is None: + silence_start_time = time.time() + elif time.time() - silence_start_time > silence_duration: + print("Silence detected, stopping recording.") + break + else: + silence_start_time = None + + except KeyboardInterrupt: + print("Recording stopped manually.") + + return np.concatenate(audio_file, axis=0) if audio_file else np.array([]) + + +def is_silent(chunk, threshold=1000): + """ + Returns True if the audio chunk is below the silent threshold. + """ + # Calculate the RMS value of the audio chunk + rms = np.sqrt(np.mean(np.square(chunk))) + return rms < threshold + + +recorder = sounddevice.InputStream(frame_length=porcupine.frame_length) +recorder.start() + +try: + while True: + pcm = recorder.read() + keyword_index = porcupine.process(pcm) + + if keyword_index == 0: + print("Detected 'picovoice'") + elif keyword_index == 1: + print("Detected 'bumblebee'") + + # Record audio from the microphone with real-time silence detection + audio_file = record_audio(silence_duration=2) + + # Convert audio to text using OpenAI API + with tempfile.NamedTemporaryFile(suffix=".wav", delete=False) as tmpfile: + tmpfilename = tmpfile.name + wavio.write(tmpfilename, audio_file, 44100, sampwidth=2) + + transcription = client.audio.transcriptions.create( + model="whisper-1", + file=open(tmpfilename, "rb"), + ) + + print("Transcription:", transcription.text) + + # Start a new thread for handling the interaction + interaction_thread = threading.Thread(target=handle_interaction, args=(transcription.text,)) + interaction_thread.start() + +except KeyboardInterrupt: + print("Script interrupted.") +finally: + if porcupine is not None: + porcupine.delete() + recorder.stop() + recorder.delete() diff --git a/Archives/wake-word-detect.py b/Archives/wake-word-detect.py new file mode 100644 index 0000000..610d921 --- /dev/null +++ b/Archives/wake-word-detect.py @@ -0,0 +1,177 @@ +from dotenv import load_dotenv +import sounddevice as sd +import struct +import numpy as np +import tempfile +import pvporcupine +import wave +import os +import time +from pvrecorder import PvRecorder +import wavio +from openai import OpenAI + +load_dotenv() + +# Retrieve the OpenAI API key and Porcupine access key from environment variables +openai_api_key = os.getenv("OPENAI_API_KEY") +porcupine_access_key = os.getenv("PORCUPINE_ACCESS_KEY") + +sd.default.device = None #'seeed-2mic-voicecard' + +if not openai_api_key: + raise ValueError("OpenAI API key is not set in environment variables.") +if not porcupine_access_key: + raise ValueError("Porcupine access key is not set in environment variables.") + +# Initialize OpenAI client +client = OpenAI(api_key=openai_api_key, default_headers={"OpenAI-Beta": "assistants=v2"}) + +# Initialize Porcupine +porcupine = pvporcupine.create( + access_key=porcupine_access_key, + keywords=["picovoice", "bumblebee"] +) +# paud = pyaudio.PyAudio() +# audio_frame = paud.open(rate=porcupine.sample_rate, channels=1, format=pyaudio.paInt16, input=True, frames_per_buffer=porcupine.frame_length) + +def record_audio(samplerate=44100, chunk_duration=1, silence_threshold=500): + """ + Record audio from the default microphone until silence is detected. + """ + print("Recording... Press Ctrl+C to stop.") + audio_file = [] + + try: + while True: + recording = sd.rec(int(chunk_duration * samplerate), samplerate=samplerate, channels=1, dtype='int16') + sd.wait() + audio_file.append(recording) + + # Check if the last recorded chunk is silent + if is_silent(recording, silence_threshold): + print("Silence detected, stopping recording.") + break + + except KeyboardInterrupt: + print("Recording stopped manually.") + + if audio_file: + audio_file = np.concatenate(audio_file, axis=0) + return audio_file + else: + raise ValueError("No audio file recorded.") + +def is_silent(file, threshold=500): + + """ + Returns True if the audio file is below the silent threshold. + """ + return np.abs(file).mean() < threshold + +def query_and_record(prompt, mp3_filename): + """ + Send a prompt to the OpenAI assistant and record the response as an MP3 file. + """ + # Create an assistant instance + assistant = client.beta.assistants.create( + name="Senior Tech Help", + instructions="You are a helpful tech teacher specifically for seniors. You will help older adults (ages 50+) with quick questions about smartphones, voice assistants, computers, cameras, the internet, digital shopping, or any other technology-related topic. You will always ask for specifics, like what device or phone they are using, and provide them with step-by-step instructions for their response.", + model="gpt-4o" + ) + + # Create a thread for communication + thread = client.beta.threads.create() + + # Send user's prompt to the AI + message = client.beta.threads.messages.create( + thread_id=thread.id, + role="user", + content=prompt + ) + + # Start the AI to process the user prompt + run = client.beta.threads.runs.create( + thread_id=thread.id, + assistant_id=assistant.id, + instructions="Please address the user as Jane Doe. The user has a premium account." + ) + + # Wait until AI is complete with processing + while run.status in ["in_progress", "queued"]: + time.sleep(1) + run = client.beta.threads.runs.retrieve( + thread_id=thread.id, + run_id=run.id + ) + + if run.status == "completed": + message_list = client.beta.threads.messages.list( + thread_id=thread.id + ) + + # Extract the text content from the response + # text_response = "" + # for message in message_list.data: + # if message.role == "assistant" and message.content: + # text_response += message.content + "\n" + + text_response = message_list.data[0].content[0].text.value + + # Generate an audio response from the text + response = client.audio.speech.create( + model="tts-1-hd", + voice="echo", + input=text_response, + ) + + response.stream_to_file(mp3_filename) + + print("Response recorded to " + mp3_filename) + + +# Main loop for keyword detection and interaction +recorder = PvRecorder(frame_length=porcupine.frame_length) +recorder.start() +wav_file = None + +try: + while True: + pcm = recorder.read() + keyword_index = porcupine.process(pcm) + + if keyword_index == 0: + print("Detected 'picovoice'") + elif keyword_index == 1: + print("Detected 'bumblebee'") + + # Record audio from the microphone + audio_file = record_audio() + + # Convert audio to text using OpenAI API + with tempfile.NamedTemporaryFile(suffix=".wav", delete=False) as tmpfile: + tmpfilename = tmpfile.name + wavio.write(tmpfilename, audio_file, 44100, sampwidth=2) + + transcription = client.audio.transcriptions.create( + model="whisper-1", + file=open(tmpfilename, "rb"), + ) + + print("Transcription:", transcription.text) + + # Example usage + prompt = transcription.text + mp3_filename = "response.mp3" + query_and_record(prompt, mp3_filename) + +except KeyboardInterrupt: + print("Script interrupted.") +finally: +# Ensuring proper release of resources + if porcupine is not None: + porcupine.delete() + # if audio_frame is not None: + # audio_frame.close() + # if paud is not None: + # paud.terminate() diff --git a/Archives/wake-word-thread.py b/Archives/wake-word-thread.py new file mode 100644 index 0000000..7e91f51 --- /dev/null +++ b/Archives/wake-word-thread.py @@ -0,0 +1,202 @@ +from dotenv import load_dotenv +import sounddevice as sd +import struct +import numpy as np +import tempfile +import pvporcupine +import wave +import os +import time +from pvrecorder import PvRecorder +import wavio +from openai import OpenAI +import pygame +import threading + +load_dotenv() + +# Retrieve the OpenAI API key and Porcupine access key from environment variables +openai_api_key = os.getenv("OPENAI_API_KEY") +porcupine_access_key = os.getenv("PORCUPINE_ACCESS_KEY") +assistant_api_key = os.getenv("ASSISTANT_API_KEY") + +sd.default.device = None # 'seeed-2mic-voicecard' + +if not openai_api_key: + raise ValueError("OpenAI API key is not set in environment variables.") +if not porcupine_access_key: + raise ValueError("Porcupine access key is not set in environment variables.") + +# Initialize OpenAI client +client = OpenAI(api_key=openai_api_key, default_headers={"OpenAI-Beta": "assistants=v2"}) + +# Initialize Porcupine +porcupine = pvporcupine.create( + access_key=porcupine_access_key, + keywords=["picovoice", "bumblebee"] +) + +thread_id = None #store the thread ID + +def record_audio(samplerate=44100, chunk_duration=1, silence_threshold=2000): + """ + Record audio from the default microphone until silence is detected. + """ + print("Recording... Press Ctrl+C to stop.") + audio_file = [] + + try: + while True: + recording = sd.rec(int(chunk_duration * samplerate), samplerate=samplerate, channels=1, dtype='int16') + sd.wait() + audio_file.append(recording) + + # Check if the last recorded chunk is silent + if is_silent(recording, silence_threshold): + print("Silence detected, stopping recording.") + break + + except KeyboardInterrupt: + print("Recording stopped manually.") + + if audio_file: + audio_file = np.concatenate(audio_file, axis=0) + return audio_file + else: + raise ValueError("No audio file recorded.") + +def is_silent(file, threshold=500): + """ + Returns True if the audio file is below the silent threshold. + """ + return np.abs(file).mean() < threshold + +def query_and_record(prompt): + """ + Send a prompt to the OpenAI assistant and record the response as an MP3 file. + """ + # # Create an assistant instance + # assistant = client.beta.assistants.create( + # name="Senior Tech Help", + # instructions="You are a helpful tech teacher specifically for seniors. You will help older adults (ages 50+) with quick questions about smartphones, voice assistants, computers, cameras, the internet, digital shopping, or any other technology-related topic. You will always ask for specifics, like what device or phone they are using, and provide them with step-by-step instructions for their response.", + # model="gpt-4o" + # ) + assistant_id = assistant_api_key + + global thread_id # Access the global thread ID + + if thread_id is None: + # Create a thread for communication + thread = client.beta.threads.create() + thread_id = thread.id + print(f"New thread created with ID: {thread_id}") + else: + # Retrieve the existing thread + thread = client.beta.threads.retrieve(thread_id) + print(f"Using existing thread with ID: {thread_id}") + + # Send user's prompt to the AI + message = client.beta.threads.messages.create( + thread_id=thread.id, + role="user", + content=prompt + ) + + # Start the AI to process the user prompt + run = client.beta.threads.runs.create( + thread_id=thread.id, + assistant_id=assistant_id, + instructions="Please address the user as Jane Doe. The user has a premium account." + ) + + # Wait until AI is complete with processing + while run.status in ["in_progress", "queued"]: + time.sleep(1) + run = client.beta.threads.runs.retrieve( + thread_id=thread.id, + run_id=run.id + ) + + if run.status == "completed": + message_list = client.beta.threads.messages.list( + thread_id=thread.id + ) + + text_response = message_list.data[0].content[0].text.value + + # Generate an audio response from the text + response = client.audio.speech.create( + model="tts-1-hd", + voice="echo", + input=text_response, + ) + + with tempfile.NamedTemporaryFile(suffix=".mp3", delete=False) as tmpfile: + mp3_filename = tmpfile.name + response.stream_to_file(mp3_filename) + + print("Response recorded to " + mp3_filename) + + # Initialize pygame mixer + pygame.mixer.init() + + # Load the mp3 file + pygame.mixer.music.load(mp3_filename) + + # Play the mp3 file + pygame.mixer.music.play() + + # Wait until the response finishes playing + while pygame.mixer.music.get_busy(): + pygame.time.Clock().tick(10) + +def handle_interaction(prompt): + """ + Handle the interaction with the AI in a separate thread. + """ + query_and_record(prompt) + +# Main loop for keyword detection and interaction +recorder = PvRecorder(frame_length=porcupine.frame_length) +recorder.start() + +try: + while True: + pcm = recorder.read() + keyword_index = porcupine.process(pcm) + + if keyword_index == 0: + print("Detected 'picovoice'") + elif keyword_index == 1: + print("Detected 'bumblebee'") + + # Record audio from the microphone + audio_file = record_audio() + + # Convert audio to text using OpenAI API + with tempfile.NamedTemporaryFile(suffix=".wav", delete=False) as tmpfile: + tmpfilename = tmpfile.name + wavio.write(tmpfilename, audio_file, 44100, sampwidth=2) + + transcription = client.audio.transcriptions.create( + model="whisper-1", + file=open(tmpfilename, "rb"), + ) + + print("Transcription:", transcription.text) + + # Example usage + prompt = transcription.text + + # Start a new thread for handling the interaction + interaction_thread = threading.Thread(target=handle_interaction, args=(prompt,)) + interaction_thread.start() + +except KeyboardInterrupt: + print("Script interrupted.") +finally: +# Ensuring proper release of resources + if porcupine is not None: + porcupine.delete() + recorder.stop() + recorder.delete() diff --git a/response.py b/response.py new file mode 100644 index 0000000..d532f97 --- /dev/null +++ b/response.py @@ -0,0 +1,125 @@ +""" +This script interacts with an OpenAI assistant by sending text prompts and receiving voice responses. +It performs the following tasks: +1. Loads environment variables for the OpenAI API key and assistant access key. +2. Initializes the audio device using the sounddevice library. +3. Sets up an OpenAI client with the provided API key. +4. Manages conversation threads with the assistant, either creating a new one or continuing an existing one. +5. Sends user prompts to the assistant and retrieves responses. +6. Converts the assistant's text response into an audio file. +7. Plays the audio response using the pygame library. +""" + +import tempfile +import os +from openai import OpenAI +import pygame +import time +import sounddevice as sd +from dotenv import load_dotenv + +load_dotenv() + +# Retrieve the OpenAI API key and Porcupine access key from environment variables +openai_api_key = os.getenv("OPENAI_API_KEY") +assistant_api_key = os.getenv("ASSISTANT_API_KEY") + +sd.default.device = None # 'seeed-2mic-voicecard' + +# Initialize OpenAI client +client = OpenAI(api_key=openai_api_key, default_headers={"OpenAI-Beta": "assistants=v2"}) + +thread_id = None # Store the thread ID + +def query_and_record(prompt): + """ + Send a prompt to the OpenAI assistant and record the response as an MP3 file. + """ + assistant_id = assistant_api_key + + global thread_id # Access the global thread ID + + if not prompt.strip(): + print("Error: The prompt is empty.") + return + + if thread_id is None: + # Create a thread for communication + thread = client.beta.threads.create() + thread_id = thread.id + print(f"New thread created with ID: {thread_id}") + else: + # Retrieve the existing thread + thread = client.beta.threads.retrieve(thread_id) + print(f"Using existing thread with ID: {thread_id}") + + try: + # Send user's prompt to the AI + message = client.beta.threads.messages.create( + thread_id=thread.id, + role="user", + content=prompt + ) + + # Start the AI to process the user prompt + run = client.beta.threads.runs.create( + thread_id=thread.id, + assistant_id=assistant_id, + instructions="Please address the user as Jane Doe. The user has a premium account." + ) + + # Wait until AI is complete with processing + while run.status in ["in_progress", "queued"]: + time.sleep(1) + run = client.beta.threads.runs.retrieve( + thread_id=thread.id, + run_id=run.id + ) + + if run.status == "completed": + message_list = client.beta.threads.messages.list( + thread_id=thread.id + ) + + # Ensure there's a valid response + if not message_list.data or not message_list.data[0].content: + print("Error: No response content available.") + return + + text_response = message_list.data[0].content[0].text.value + + # Generate an audio response from the text + response = client.audio.speech.create( + model="tts-1-hd", + voice="echo", + input=text_response, + ) + + with tempfile.NamedTemporaryFile(suffix=".mp3", delete=False) as tmpfile: + mp3_filename = tmpfile.name + response.stream_to_file(mp3_filename) + + print("Response recorded to " + mp3_filename) + + # Initialize pygame mixer + pygame.mixer.init() + + # Load the mp3 file + pygame.mixer.music.load(mp3_filename) + + # Play the mp3 file + pygame.mixer.music.play() + + # Wait until the response finishes playing + while pygame.mixer.music.get_busy(): + pygame.time.Clock().tick(10) + + except Exception as e: + print("Error during query and recording:", str(e)) + + +def handle_interaction(prompt): + """ + Handle the interaction with the AI. + """ + query_and_record(prompt) diff --git a/voiceassist.py b/voiceassist.py new file mode 100644 index 0000000..f7bdbc1 --- /dev/null +++ b/voiceassist.py @@ -0,0 +1,146 @@ +""" +This script is designed for detecting a wake word and handling voice interactions with an OpenAI assistant. +The script performs the following tasks: + +1. Imports necessary libraries such as sounddevice, numpy, tempfile, wavio, and OpenAI. +2. Loads environment variables to retrieve the OpenAI API key and Porcupine access key, which are essential for authentication and wake word detection. +3. Initializes the Porcupine wake word engine to listen for specific keywords ("picovoice" and "bumblebee"). +4. Sets up an OpenAI client for sending user prompts and receiving responses. +5. Defines functions to: + - Detect the wake word using an audio stream. + - Record audio until silence is detected, indicating the end of the user's command. + - Handle follow-up commands by continuously listening after the initial response. +6. The main loop continuously listens for the wake word and handles interactions as long as the script is running. +7. Ensures proper cleanup by deleting the Porcupine instance when the script is interrupted. +""" + +import sounddevice as sd +import numpy as np +import tempfile +import wavio +from openai import OpenAI +import threading +import os +import pvporcupine +import time +from response import handle_interaction +from dotenv import load_dotenv + +load_dotenv() + +# Retrieve the OpenAI API key and Porcupine access key from environment variables +openai_api_key = os.getenv("OPENAI_API_KEY") +porcupine_access_key = os.getenv("PORCUPINE_ACCESS_KEY") + +if not openai_api_key: + raise ValueError("OpenAI API key is not set in environment variables.") +if not porcupine_access_key: + raise ValueError("Porcupine access key is not set in environment variables.") + +# Initialize Porcupine +porcupine = pvporcupine.create( + access_key=porcupine_access_key, + keywords=["picovoice", "bumblebee"] +) + + +# Initialize the OpenAI client +client = OpenAI(api_key=openai_api_key, default_headers={"OpenAI-Beta": "assistants=v2"}) + +frame_length = porcupine.frame_length +sample_rate = porcupine.sample_rate + +def is_silent(chunk, threshold=1000): + rms = np.sqrt(np.mean(np.square(chunk))) + return rms < threshold + +def detect_wake_word(): + try: + with sd.InputStream(samplerate=sample_rate, channels=1, dtype='int16') as stream: + while True: + pcm = stream.read(frame_length)[0] + pcm = np.frombuffer(pcm, dtype=np.int16) + keyword_index = porcupine.process(pcm) + + if keyword_index == 0: + print("Detected 'picovoice'") + return 'picovoice' + elif keyword_index == 1: + print("Detected 'bumblebee'") + return 'bumblebee' + except KeyboardInterrupt: + print("Script interrupted.") + +def record_audio(samplerate=44100, chunk_duration=1, silence_threshold=1000, silence_duration=10): + print("Recording... Press Ctrl+C to stop.") + audio_file = [] + silence_start_time = None + chunk_size = int(chunk_duration * samplerate) + + try: + with sd.InputStream(samplerate=samplerate, channels=1, dtype='int16', callback=lambda indata, frames, time, status: audio_file.append(indata.copy())): + while True: + if len(audio_file) > 0: + last_chunk = audio_file[-1] + + # Check if the last chunk is silent + if is_silent(last_chunk, silence_threshold): + if silence_start_time is None: + silence_start_time = time.time() + elif time.time() - silence_start_time > silence_duration: + print("Silence detected, stopping recording.") + break + else: + silence_start_time = None + + except KeyboardInterrupt: + print("Recording stopped manually.") + + return np.concatenate(audio_file, axis=0) if audio_file else np.array([]) + +def handle_follow_up(): + print("Listening for follow-up command...") + audio_file = record_audio(silence_duration=5) + + if len(audio_file) > 0: + with tempfile.NamedTemporaryFile(suffix=".wav", delete=False) as tmpfile: + tmpfilename = tmpfile.name + wavio.write(tmpfilename, audio_file, 44100, sampwidth=2) + + transcription = client.audio.transcriptions.create( + model="whisper-1", + file=open(tmpfilename, "rb"), + ) + + print("Transcription:", transcription.text) + + interaction_thread = threading.Thread(target=handle_interaction, args=(transcription.text,)) + interaction_thread.start() + interaction_thread.join() + + # After handling the follow-up, check if there is more to listen for + handle_follow_up() + else: + print("No follow-up detected. Restarting wake word detection.") + wake_word_thread = threading.Thread(target=detect_wake_word_instance) + wake_word_thread.start() + +def detect_wake_word_instance(): + while True: + wake_word = detect_wake_word() + if wake_word == 'bumblebee': + handle_follow_up() + else: + break + +try: + while True: + wake_word_thread = threading.Thread(target=detect_wake_word_instance) + wake_word_thread.start() + wake_word_thread.join() + +except KeyboardInterrupt: + print("Script interrupted.") +finally: + if porcupine is not None: + porcupine.delete() diff --git a/wake-word-assistant.py b/wake-word-assistant.py new file mode 100644 index 0000000..e1040d8 --- /dev/null +++ b/wake-word-assistant.py @@ -0,0 +1,187 @@ +from dotenv import load_dotenv +import sounddevice as sd +import struct +import numpy as np +import tempfile +import pvporcupine +import wave +import os +import time +from pvrecorder import PvRecorder +import wavio +from openai import OpenAI +import pygame + +load_dotenv() + +# Retrieve the OpenAI API key and Porcupine access key from environment variables +openai_api_key = os.getenv("OPENAI_API_KEY") +porcupine_access_key = os.getenv("PORCUPINE_ACCESS_KEY") +assistant_api_key = os.getenv("ASSISTANT_API_KEY") + +sd.default.device = None #'seeed-2mic-voicecard' + +if not openai_api_key: + raise ValueError("OpenAI API key is not set in environment variables.") +if not porcupine_access_key: + raise ValueError("Porcupine access key is not set in environment variables.") + +# Initialize OpenAI client +client = OpenAI(api_key=openai_api_key, default_headers={"OpenAI-Beta": "assistants=v2"}) + +# Initialize Porcupine +porcupine = pvporcupine.create( + access_key=porcupine_access_key, + keywords=["picovoice", "bumblebee"] +) + +def record_audio(samplerate=44100, chunk_duration=1, silence_threshold=2000): + """ + Record audio from the default microphone until silence is detected. + """ + print("Recording... Press Ctrl+C to stop.") + audio_file = [] + + try: + while True: + recording = sd.rec(int(chunk_duration * samplerate), samplerate=samplerate, channels=1, dtype='int16') + sd.wait() + audio_file.append(recording) + + # Check if the last recorded chunk is silent + if is_silent(recording, silence_threshold): + print("Silence detected, stopping recording.") + break + + except KeyboardInterrupt: + print("Recording stopped manually.") + + if audio_file: + audio_file = np.concatenate(audio_file, axis=0) + return audio_file + else: + raise ValueError("No audio file recorded.") + +def is_silent(file, threshold=500): + """ + Returns True if the audio file is below the silent threshold. + """ + return np.abs(file).mean() < threshold + +def query_and_record(prompt): + """ + Send a prompt to the OpenAI assistant and record the response as an MP3 file. + """ + # # Create an assistant instance + # assistant = client.beta.assistants.create( + # name="Senior Tech Help", + # instructions="You are a helpful tech teacher specifically for seniors. You will help older adults (ages 50+) with quick questions about smartphones, voice assistants, computers, cameras, the internet, digital shopping, or any other technology-related topic. You will always ask for specifics, like what device or phone they are using, and provide them with step-by-step instructions for their response.", + # model="gpt-4o" + # ) + assistant_id = assistant_api_key + + # Create a thread for communication + thread = client.beta.threads.create() + + # Send user's prompt to the AI + message = client.beta.threads.messages.create( + thread_id=thread.id, + role="user", + content=prompt + ) + + # Start the AI to process the user prompt + run = client.beta.threads.runs.create( + thread_id=thread.id, + assistant_id=assistant_id, + instructions="Please address the user as Jane Doe. The user has a premium account." + ) + + # Wait until AI is complete with processing + while run.status in ["in_progress", "queued"]: + time.sleep(1) + run = client.beta.threads.runs.retrieve( + thread_id=thread.id, + run_id=run.id + ) + + if run.status == "completed": + message_list = client.beta.threads.messages.list( + thread_id=thread.id + ) + # Extract the text content from the response + # text_response = "" + # for message in message_list.data: + # if message.role == "assistant" and message.content: + # text_response += message.content + "\n" + + + text_response = message_list.data[0].content[0].text.value + + # Generate an audio response from the text + response = client.audio.speech.create( + model="tts-1-hd", + voice="echo", + input=text_response, + ) + + with tempfile.NamedTemporaryFile(suffix=".mp3", delete=False) as tmpfile: + mp3_filename = tmpfile.name + response.stream_to_file(mp3_filename) + + print("Response recorded to " + mp3_filename) + + # Initialize pygame mixer + pygame.mixer.init() + + # Load the mp3 file + pygame.mixer.music.load(mp3_filename) + + # Play the mp3 file + pygame.mixer.music.play() + + # Wait until the music finishes playing + while pygame.mixer.music.get_busy(): + pygame.time.Clock().tick(10) + +# Main loop for keyword detection and interaction +recorder = PvRecorder(frame_length=porcupine.frame_length) +recorder.start() + +try: + while True: + pcm = recorder.read() + keyword_index = porcupine.process(pcm) + + if keyword_index == 0: + print("Detected 'picovoice'") + elif keyword_index == 1: + print("Detected 'bumblebee'") + + # Record audio from the microphone + audio_file = record_audio() + + # Convert audio to text using OpenAI API + with tempfile.NamedTemporaryFile(suffix=".wav", delete=False) as tmpfile: + tmpfilename = tmpfile.name + wavio.write(tmpfilename, audio_file, 44100, sampwidth=2) + + transcription = client.audio.transcriptions.create( + model="whisper-1", + file=open(tmpfilename, "rb"), + ) + + print("Transcription:", transcription.text) + + # Example usage + prompt = transcription.text + query_and_record(prompt) + +except KeyboardInterrupt: + print("Script interrupted.") +finally: +# Ensuring proper release of resources + if porcupine is not None: + porcupine.delete() + recorder.stop() + recorder.delete() diff --git a/wake-word-audio.py b/wake-word-audio.py new file mode 100644 index 0000000..46102b5 --- /dev/null +++ b/wake-word-audio.py @@ -0,0 +1,112 @@ +import sounddevice as sd +import numpy as np +import tempfile +import wavio +from openai import OpenAI +import threading +import os +import pvporcupine +from pvrecorder import PvRecorder +import time +from response import handle_interaction +from dotenv import load_dotenv + +load_dotenv() + +# Retrieve the OpenAI API key and Porcupine access key from environment variables +openai_api_key = os.getenv("OPENAI_API_KEY") +porcupine_access_key = os.getenv("PORCUPINE_ACCESS_KEY") + +if not openai_api_key: + raise ValueError("OpenAI API key is not set in environment variables.") +if not porcupine_access_key: + raise ValueError("Porcupine access key is not set in environment variables.") + +# Initialize Porcupine +porcupine = pvporcupine.create( + access_key=porcupine_access_key, + keywords=["picovoice", "bumblebee"] +) + +# Initialize the OpenAI client +client = OpenAI(api_key=openai_api_key, default_headers={"OpenAI-Beta": "assistants=v2"}) + +def record_audio(samplerate=44100, chunk_duration=1, silence_threshold=1000, silence_duration=10): + """ + Record audio in real-time and stop when silence is detected for the specified duration. + """ + print("Recording... Press Ctrl+C to stop.") + audio_file = [] + silence_start_time = None + chunk_size = int(chunk_duration * samplerate) + + try: + with sd.InputStream(samplerate=samplerate, channels=1, dtype='int16', callback=lambda indata, frames, time, status: audio_file.append(indata.copy())): + while True: + if len(audio_file) > 0: + last_chunk = audio_file[-1] + + # Check if the last chunk is silent + if is_silent(last_chunk, silence_threshold): + if silence_start_time is None: + silence_start_time = time.time() + elif time.time() - silence_start_time > silence_duration: + print("Silence detected, stopping recording.") + break + else: + silence_start_time = None + + except KeyboardInterrupt: + print("Recording stopped manually.") + + return np.concatenate(audio_file, axis=0) if audio_file else np.array([]) + + +def is_silent(chunk, threshold=1000): + """ + Returns True if the audio chunk is below the silent threshold. + """ + # Calculate the RMS value of the audio chunk + rms = np.sqrt(np.mean(np.square(chunk))) + return rms < threshold + + +recorder = PvRecorder(frame_length=porcupine.frame_length) +recorder.start() + +try: + while True: + pcm = recorder.read() + keyword_index = porcupine.process(pcm) + + if keyword_index == 0: + print("Detected 'picovoice'") + elif keyword_index == 1: + print("Detected 'bumblebee'") + + # Record audio from the microphone with real-time silence detection + audio_file = record_audio(silence_duration=5) + + # Convert audio to text using OpenAI API + with tempfile.NamedTemporaryFile(suffix=".wav", delete=False) as tmpfile: + tmpfilename = tmpfile.name + wavio.write(tmpfilename, audio_file, 44100, sampwidth=2) + + transcription = client.audio.transcriptions.create( + model="whisper-1", + file=open(tmpfilename, "rb"), + ) + + print("Transcription:", transcription.text) + + # Start a new thread for handling the interaction + interaction_thread = threading.Thread(target=handle_interaction, args=(transcription.text,)) + interaction_thread.start() + +except KeyboardInterrupt: + print("Script interrupted.") +finally: + if porcupine is not None: + porcupine.delete() + recorder.stop() + recorder.delete() diff --git a/wake-word-detect.py b/wake-word-detect.py new file mode 100644 index 0000000..610d921 --- /dev/null +++ b/wake-word-detect.py @@ -0,0 +1,177 @@ +from dotenv import load_dotenv +import sounddevice as sd +import struct +import numpy as np +import tempfile +import pvporcupine +import wave +import os +import time +from pvrecorder import PvRecorder +import wavio +from openai import OpenAI + +load_dotenv() + +# Retrieve the OpenAI API key and Porcupine access key from environment variables +openai_api_key = os.getenv("OPENAI_API_KEY") +porcupine_access_key = os.getenv("PORCUPINE_ACCESS_KEY") + +sd.default.device = None #'seeed-2mic-voicecard' + +if not openai_api_key: + raise ValueError("OpenAI API key is not set in environment variables.") +if not porcupine_access_key: + raise ValueError("Porcupine access key is not set in environment variables.") + +# Initialize OpenAI client +client = OpenAI(api_key=openai_api_key, default_headers={"OpenAI-Beta": "assistants=v2"}) + +# Initialize Porcupine +porcupine = pvporcupine.create( + access_key=porcupine_access_key, + keywords=["picovoice", "bumblebee"] +) +# paud = pyaudio.PyAudio() +# audio_frame = paud.open(rate=porcupine.sample_rate, channels=1, format=pyaudio.paInt16, input=True, frames_per_buffer=porcupine.frame_length) + +def record_audio(samplerate=44100, chunk_duration=1, silence_threshold=500): + """ + Record audio from the default microphone until silence is detected. + """ + print("Recording... Press Ctrl+C to stop.") + audio_file = [] + + try: + while True: + recording = sd.rec(int(chunk_duration * samplerate), samplerate=samplerate, channels=1, dtype='int16') + sd.wait() + audio_file.append(recording) + + # Check if the last recorded chunk is silent + if is_silent(recording, silence_threshold): + print("Silence detected, stopping recording.") + break + + except KeyboardInterrupt: + print("Recording stopped manually.") + + if audio_file: + audio_file = np.concatenate(audio_file, axis=0) + return audio_file + else: + raise ValueError("No audio file recorded.") + +def is_silent(file, threshold=500): + + """ + Returns True if the audio file is below the silent threshold. + """ + return np.abs(file).mean() < threshold + +def query_and_record(prompt, mp3_filename): + """ + Send a prompt to the OpenAI assistant and record the response as an MP3 file. + """ + # Create an assistant instance + assistant = client.beta.assistants.create( + name="Senior Tech Help", + instructions="You are a helpful tech teacher specifically for seniors. You will help older adults (ages 50+) with quick questions about smartphones, voice assistants, computers, cameras, the internet, digital shopping, or any other technology-related topic. You will always ask for specifics, like what device or phone they are using, and provide them with step-by-step instructions for their response.", + model="gpt-4o" + ) + + # Create a thread for communication + thread = client.beta.threads.create() + + # Send user's prompt to the AI + message = client.beta.threads.messages.create( + thread_id=thread.id, + role="user", + content=prompt + ) + + # Start the AI to process the user prompt + run = client.beta.threads.runs.create( + thread_id=thread.id, + assistant_id=assistant.id, + instructions="Please address the user as Jane Doe. The user has a premium account." + ) + + # Wait until AI is complete with processing + while run.status in ["in_progress", "queued"]: + time.sleep(1) + run = client.beta.threads.runs.retrieve( + thread_id=thread.id, + run_id=run.id + ) + + if run.status == "completed": + message_list = client.beta.threads.messages.list( + thread_id=thread.id + ) + + # Extract the text content from the response + # text_response = "" + # for message in message_list.data: + # if message.role == "assistant" and message.content: + # text_response += message.content + "\n" + + text_response = message_list.data[0].content[0].text.value + + # Generate an audio response from the text + response = client.audio.speech.create( + model="tts-1-hd", + voice="echo", + input=text_response, + ) + + response.stream_to_file(mp3_filename) + + print("Response recorded to " + mp3_filename) + + +# Main loop for keyword detection and interaction +recorder = PvRecorder(frame_length=porcupine.frame_length) +recorder.start() +wav_file = None + +try: + while True: + pcm = recorder.read() + keyword_index = porcupine.process(pcm) + + if keyword_index == 0: + print("Detected 'picovoice'") + elif keyword_index == 1: + print("Detected 'bumblebee'") + + # Record audio from the microphone + audio_file = record_audio() + + # Convert audio to text using OpenAI API + with tempfile.NamedTemporaryFile(suffix=".wav", delete=False) as tmpfile: + tmpfilename = tmpfile.name + wavio.write(tmpfilename, audio_file, 44100, sampwidth=2) + + transcription = client.audio.transcriptions.create( + model="whisper-1", + file=open(tmpfilename, "rb"), + ) + + print("Transcription:", transcription.text) + + # Example usage + prompt = transcription.text + mp3_filename = "response.mp3" + query_and_record(prompt, mp3_filename) + +except KeyboardInterrupt: + print("Script interrupted.") +finally: +# Ensuring proper release of resources + if porcupine is not None: + porcupine.delete() + # if audio_frame is not None: + # audio_frame.close() + # if paud is not None: + # paud.terminate() diff --git a/wake-word-thread.py b/wake-word-thread.py new file mode 100644 index 0000000..7e91f51 --- /dev/null +++ b/wake-word-thread.py @@ -0,0 +1,202 @@ +from dotenv import load_dotenv +import sounddevice as sd +import struct +import numpy as np +import tempfile +import pvporcupine +import wave +import os +import time +from pvrecorder import PvRecorder +import wavio +from openai import OpenAI +import pygame +import threading + +load_dotenv() + +# Retrieve the OpenAI API key and Porcupine access key from environment variables +openai_api_key = os.getenv("OPENAI_API_KEY") +porcupine_access_key = os.getenv("PORCUPINE_ACCESS_KEY") +assistant_api_key = os.getenv("ASSISTANT_API_KEY") + +sd.default.device = None # 'seeed-2mic-voicecard' + +if not openai_api_key: + raise ValueError("OpenAI API key is not set in environment variables.") +if not porcupine_access_key: + raise ValueError("Porcupine access key is not set in environment variables.") + +# Initialize OpenAI client +client = OpenAI(api_key=openai_api_key, default_headers={"OpenAI-Beta": "assistants=v2"}) + +# Initialize Porcupine +porcupine = pvporcupine.create( + access_key=porcupine_access_key, + keywords=["picovoice", "bumblebee"] +) + +thread_id = None #store the thread ID + +def record_audio(samplerate=44100, chunk_duration=1, silence_threshold=2000): + """ + Record audio from the default microphone until silence is detected. + """ + print("Recording... Press Ctrl+C to stop.") + audio_file = [] + + try: + while True: + recording = sd.rec(int(chunk_duration * samplerate), samplerate=samplerate, channels=1, dtype='int16') + sd.wait() + audio_file.append(recording) + + # Check if the last recorded chunk is silent + if is_silent(recording, silence_threshold): + print("Silence detected, stopping recording.") + break + + except KeyboardInterrupt: + print("Recording stopped manually.") + + if audio_file: + audio_file = np.concatenate(audio_file, axis=0) + return audio_file + else: + raise ValueError("No audio file recorded.") + +def is_silent(file, threshold=500): + """ + Returns True if the audio file is below the silent threshold. + """ + return np.abs(file).mean() < threshold + +def query_and_record(prompt): + """ + Send a prompt to the OpenAI assistant and record the response as an MP3 file. + """ + # # Create an assistant instance + # assistant = client.beta.assistants.create( + # name="Senior Tech Help", + # instructions="You are a helpful tech teacher specifically for seniors. You will help older adults (ages 50+) with quick questions about smartphones, voice assistants, computers, cameras, the internet, digital shopping, or any other technology-related topic. You will always ask for specifics, like what device or phone they are using, and provide them with step-by-step instructions for their response.", + # model="gpt-4o" + # ) + assistant_id = assistant_api_key + + global thread_id # Access the global thread ID + + if thread_id is None: + # Create a thread for communication + thread = client.beta.threads.create() + thread_id = thread.id + print(f"New thread created with ID: {thread_id}") + else: + # Retrieve the existing thread + thread = client.beta.threads.retrieve(thread_id) + print(f"Using existing thread with ID: {thread_id}") + + # Send user's prompt to the AI + message = client.beta.threads.messages.create( + thread_id=thread.id, + role="user", + content=prompt + ) + + # Start the AI to process the user prompt + run = client.beta.threads.runs.create( + thread_id=thread.id, + assistant_id=assistant_id, + instructions="Please address the user as Jane Doe. The user has a premium account." + ) + + # Wait until AI is complete with processing + while run.status in ["in_progress", "queued"]: + time.sleep(1) + run = client.beta.threads.runs.retrieve( + thread_id=thread.id, + run_id=run.id + ) + + if run.status == "completed": + message_list = client.beta.threads.messages.list( + thread_id=thread.id + ) + + text_response = message_list.data[0].content[0].text.value + + # Generate an audio response from the text + response = client.audio.speech.create( + model="tts-1-hd", + voice="echo", + input=text_response, + ) + + with tempfile.NamedTemporaryFile(suffix=".mp3", delete=False) as tmpfile: + mp3_filename = tmpfile.name + response.stream_to_file(mp3_filename) + + print("Response recorded to " + mp3_filename) + + # Initialize pygame mixer + pygame.mixer.init() + + # Load the mp3 file + pygame.mixer.music.load(mp3_filename) + + # Play the mp3 file + pygame.mixer.music.play() + + # Wait until the response finishes playing + while pygame.mixer.music.get_busy(): + pygame.time.Clock().tick(10) + +def handle_interaction(prompt): + """ + Handle the interaction with the AI in a separate thread. + """ + query_and_record(prompt) + +# Main loop for keyword detection and interaction +recorder = PvRecorder(frame_length=porcupine.frame_length) +recorder.start() + +try: + while True: + pcm = recorder.read() + keyword_index = porcupine.process(pcm) + + if keyword_index == 0: + print("Detected 'picovoice'") + elif keyword_index == 1: + print("Detected 'bumblebee'") + + # Record audio from the microphone + audio_file = record_audio() + + # Convert audio to text using OpenAI API + with tempfile.NamedTemporaryFile(suffix=".wav", delete=False) as tmpfile: + tmpfilename = tmpfile.name + wavio.write(tmpfilename, audio_file, 44100, sampwidth=2) + + transcription = client.audio.transcriptions.create( + model="whisper-1", + file=open(tmpfilename, "rb"), + ) + + print("Transcription:", transcription.text) + + # Example usage + prompt = transcription.text + + # Start a new thread for handling the interaction + interaction_thread = threading.Thread(target=handle_interaction, args=(prompt,)) + interaction_thread.start() + +except KeyboardInterrupt: + print("Script interrupted.") +finally: +# Ensuring proper release of resources + if porcupine is not None: + porcupine.delete() + recorder.stop() + recorder.delete()