diff --git a/src/sayvai_tools/tools/TTS/__init__.py b/src/sayvai_tools/tools/TTS/__init__.py new file mode 100644 index 0000000..6c41695 --- /dev/null +++ b/src/sayvai_tools/tools/TTS/__init__.py @@ -0,0 +1,3 @@ +from sayvai_tools.tools.TTS.tool import VoiceOutputRun + +__all__ = ["VoiceOutputRun"] diff --git a/src/sayvai_tools/tools/audio/streaming.py b/src/sayvai_tools/tools/TTS/tool.py similarity index 81% rename from src/sayvai_tools/tools/audio/streaming.py rename to src/sayvai_tools/tools/TTS/tool.py index a84e856..fff44e3 100644 --- a/src/sayvai_tools/tools/audio/streaming.py +++ b/src/sayvai_tools/tools/TTS/tool.py @@ -1,8 +1,6 @@ """base tool for IO""" -from typing import Callable from elevenlabs import play -from langchain.pydantic_v1 import Field from sayvai_tools.utils.voice.tts import ElevenlabsAudioStreaming @@ -27,14 +25,13 @@ def _run( ): """Use the Human input tool.""" # input_func: Callable = Field(default_factory=lambda: input) - tts = ElevenlabsAudioStreaming() - inputbytes = tts.audio_streaming( + tts = ElevenlabsAudioStreaming(self.api_key) + input_bytes = tts.audio_streaming( query, model="eleven_multilingual_v1", voice="Adam", audio_streaming=True, stability=0.5, similarity=0.5, - api_key=self.api_key, ) - play(inputbytes) + play(input_bytes) diff --git a/src/sayvai_tools/tools/audio/__init__.py b/src/sayvai_tools/tools/audio/__init__.py deleted file mode 100644 index acf3460..0000000 --- a/src/sayvai_tools/tools/audio/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from sayvai_tools.tools.audio.streaming import VoiceOutputRun - -__all__ = ["VoiceOutputRun"] diff --git a/src/sayvai_tools/tools/calendar/calendar/tool.py b/src/sayvai_tools/tools/calendar/calendar/tool.py index 02a5e8f..f04966e 100644 --- a/src/sayvai_tools/tools/calendar/calendar/tool.py +++ b/src/sayvai_tools/tools/calendar/calendar/tool.py @@ -12,7 +12,7 @@ def __init__(self, scope: str, email: str, summary: str): self.cal = GCalendar(scope=self.scope, email=self.email, summary=self.summary) def _run(self, date: str): - return self.cal.book_slots(date) + return self.cal.book_slots(input_str=date) async def _arun(self, date: str): raise NotImplementedError("Calendar async not implemented") diff --git a/src/sayvai_tools/tools/calendar/tool.py b/src/sayvai_tools/tools/calendar/tool.py deleted file mode 100644 index 1dd811f..0000000 --- a/src/sayvai_tools/tools/calendar/tool.py +++ /dev/null @@ -1,16 +0,0 @@ -from sayvai_tools.utils.google.gcalendar import GCalendar - - -class Calendar: - name = "calendar" - description = "You can ask calendar tool to create an event for you." - - def __init__(self, scope: str): - self.scope = scope - self.cal = GCalendar(self.scope) - - def _run(self, date: str): - return self.cal.book_slots(date) - - async def _arun(self, date: str): - raise NotImplementedError("Calendar async not implemented") diff --git a/src/sayvai_tools/tools/retrive_details/__init__.py b/src/sayvai_tools/tools/retrive_details/__init__.py new file mode 100644 index 0000000..30c371c --- /dev/null +++ b/src/sayvai_tools/tools/retrive_details/__init__.py @@ -0,0 +1,5 @@ +from sayvai_tools.tools.retrive_details.retrive_email.tool import RetrieveEmail +from sayvai_tools.tools.retrive_details.retrive_phone.tool import RetrievePhone + +__all__ = ["RetrieveEmail", + "RetrievePhone"] diff --git a/src/sayvai_tools/tools/retrive_details/retrive_email/__init__.py b/src/sayvai_tools/tools/retrive_details/retrive_email/__init__.py new file mode 100644 index 0000000..4ad48ae --- /dev/null +++ b/src/sayvai_tools/tools/retrive_details/retrive_email/__init__.py @@ -0,0 +1 @@ +__all__ = ["RetrieveEmail"] diff --git a/src/sayvai_tools/tools/retrive_email/tool.py b/src/sayvai_tools/tools/retrive_details/retrive_email/tool.py similarity index 100% rename from src/sayvai_tools/tools/retrive_email/tool.py rename to src/sayvai_tools/tools/retrive_details/retrive_email/tool.py diff --git a/src/sayvai_tools/tools/retrive_details/retrive_phone/__init__.py b/src/sayvai_tools/tools/retrive_details/retrive_phone/__init__.py new file mode 100644 index 0000000..0caf36b --- /dev/null +++ b/src/sayvai_tools/tools/retrive_details/retrive_phone/__init__.py @@ -0,0 +1 @@ +__all__ = ["RetrievePhone"] diff --git a/src/sayvai_tools/tools/retrive_phone/tool.py b/src/sayvai_tools/tools/retrive_details/retrive_phone/tool.py similarity index 100% rename from src/sayvai_tools/tools/retrive_phone/tool.py rename to src/sayvai_tools/tools/retrive_details/retrive_phone/tool.py diff --git a/src/sayvai_tools/tools/retrive_email/__init__.py b/src/sayvai_tools/tools/retrive_email/__init__.py deleted file mode 100644 index a145c6c..0000000 --- a/src/sayvai_tools/tools/retrive_email/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from sayvai_tools.tools.retrive_email.tool import RetrieveEmail - -__all__ = ["RetrieveEmail"] diff --git a/src/sayvai_tools/tools/retrive_phone/__init__.py b/src/sayvai_tools/tools/retrive_phone/__init__.py deleted file mode 100644 index 800c69e..0000000 --- a/src/sayvai_tools/tools/retrive_phone/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from sayvai_tools.tools.retrive_phone.tool import RetrievePhone - -__all__ = ["RetrievePhone"] diff --git a/src/sayvai_tools/utils/google/drive/__init__.py b/src/sayvai_tools/utils/google/drive/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/sayvai_tools/utils/drive/drivetool.py b/src/sayvai_tools/utils/google/drive/drivetool.py similarity index 100% rename from src/sayvai_tools/utils/drive/drivetool.py rename to src/sayvai_tools/utils/google/drive/drivetool.py diff --git a/src/sayvai_tools/utils/drive/service.py b/src/sayvai_tools/utils/google/drive/service.py similarity index 100% rename from src/sayvai_tools/utils/drive/service.py rename to src/sayvai_tools/utils/google/drive/service.py diff --git a/src/sayvai_tools/utils/google/gcalendar.py b/src/sayvai_tools/utils/google/gcalendar.py index 50a8a16..e0adac3 100644 --- a/src/sayvai_tools/utils/google/gcalendar.py +++ b/src/sayvai_tools/utils/google/gcalendar.py @@ -167,7 +167,7 @@ def check_is_slot_available(start_time, end_time, booked_slots): def book_slots( self, - date, + input_str: str, MINIMUM_TIME_SLOT: int = 15, MAXIMUM_TIME_SLOT: int = 60, OPEN_TIME: int = 9, @@ -183,13 +183,13 @@ def book_slots( :param MAXIMUM_TIME_SLOT: :param OPEN_TIME: :param MINIMUM_TIME_SLOT: - :param date: + :param input_str: :return: appointment event creation """ startt = time.time() # splits the input string into start time, end time and email - input_pairs = date.split("/") + input_pairs = input_str.split("/") start_time = self.parse_date(input_pairs[0]) end_time = self.parse_date(input_pairs[1]) phone = input_pairs[2] diff --git a/src/sayvai_tools/utils/voice/recording.py b/src/sayvai_tools/utils/voice/recording.py index c242389..817a36f 100644 --- a/src/sayvai_tools/utils/voice/recording.py +++ b/src/sayvai_tools/utils/voice/recording.py @@ -5,7 +5,7 @@ from pydub import AudioSegment from pydub.silence import split_on_silence -# Constants for audio input +# Constants for TTS input FORMAT = pyaudio.paInt16 CHANNELS = 1 RATE = 44100 @@ -17,11 +17,11 @@ def record(): def match_target_amplitude(aChunk, target_dBFS): - """Normalize given audio chunk""" + """Normalize given TTS chunk""" change_in_dBFS = target_dBFS - aChunk.dBFS return aChunk.apply_gain(change_in_dBFS) - # Open a stream to capture audio from the microphone + # Open a stream to capture TTS from the microphone stream = audio.open( format=FORMAT, channels=CHANNELS, @@ -31,29 +31,29 @@ def match_target_amplitude(aChunk, target_dBFS): frames_per_buffer=CHUNK_SIZE, ) - # Create a list to store audio chunks + # Create a list to store TTS chunks audio_chunks = [] # Recording flag recording = False - # Record audio until interrupted + # Record TTS until interrupted try: j = 0 while True: data = stream.read(CHUNK_SIZE) audio_data = np.frombuffer(data, dtype=np.int16) - # Check if audio data is silence + # Check if TTS data is silence is_silence = np.max(audio_data) < 350 # print(np.max(audio_data)) if recording: if is_silence: - # End of an audio chunk + # End of an TTS chunk recording = False if len(audio_chunks) > 0: - # Process the recorded audio chunk + # Process the recorded TTS chunk song = AudioSegment( data=b"".join(audio_chunks), sample_width=2, @@ -75,7 +75,7 @@ def match_target_amplitude(aChunk, target_dBFS): # Normalize the entire chunk normalized_chunk = match_target_amplitude(audio_chunk, -20.0) - # Export the audio chunk with a new bitrate + # Export the TTS chunk with a new bitrate mp3_buffer = io.BytesIO() normalized_chunk.export( mp3_buffer, format="mp3", bitrate="192k" @@ -85,16 +85,16 @@ def match_target_amplitude(aChunk, target_dBFS): mp3_buffer.close() return mp3_bytes - # Clear the audio chunks list + # Clear the TTS chunks list audio_chunks.clear() break else: - # Continue recording audio data + # Continue recording TTS data audio_chunks.append(data) else: - # Start recording when non-silent audio is detected + # Start recording when non-silent TTS is detected if not is_silence: recording = True audio_chunks.append(data) diff --git a/src/sayvai_tools/utils/voice/stt.py b/src/sayvai_tools/utils/voice/stt.py index e41688b..315a6ee 100644 --- a/src/sayvai_tools/utils/voice/stt.py +++ b/src/sayvai_tools/utils/voice/stt.py @@ -198,7 +198,7 @@ def select_microphone_distance(self): ) def select_media_type(self): - if self.original_media_type == "audio": + if self.original_media_type == "TTS": return speech.RecognitionMetadata.OriginalMediaType.AUDIO elif self.original_media_type == "video": return speech.RecognitionMetadata.OriginalMediaType.VIDEO diff --git a/src/sayvai_tools/utils/voice/tts.py b/src/sayvai_tools/utils/voice/tts.py index 1042caa..479f02b 100644 --- a/src/sayvai_tools/utils/voice/tts.py +++ b/src/sayvai_tools/utils/voice/tts.py @@ -54,7 +54,7 @@ def audio_streaming( ): api_key = self.api_key """ - passes the text to elevenlabs api to play the audio + passes the text to elevenlabs api to play the TTS """ if not isinstance(audio_streaming, bool): @@ -76,7 +76,7 @@ def audio_streaming( api_key=api_key, ) # audio_stream is a generator with byte values that cannot be saved directly using save function - # so we add all the byte values in generator to a single variable and save the audio + # so we add all the byte values in generator to a single variable and save the TTS byte_values = bytearray() for byte_chunk in audio_stream: byte_values += byte_chunk @@ -84,15 +84,15 @@ def audio_streaming( # Convert the accumulated byte values to a bytes object final_byte_data = bytes(byte_values) return final_byte_data - # save(final_byte_data, "E:/Text-to-speech/src/audio buffer/audio.wav") + # save(final_byte_data, "E:/Text-to-speech/src/TTS buffer/TTS.wav") # play(final_byte_data) # if Audio streaming is False else: audio = generate(text=text, voice=voice, model=model, api_key=api_key) return audio - # save(audio, "E:/Text-to-speech/src/audio buffer/audio.wav") - # play(audio) + # save(TTS, "E:/Text-to-speech/src/TTS buffer/TTS.wav") + # play(TTS) @staticmethod def avail_voices(): diff --git a/tests/calendar/conftest.py b/tests/calendar/conftest.py new file mode 100644 index 0000000..948dc71 --- /dev/null +++ b/tests/calendar/conftest.py @@ -0,0 +1,42 @@ +import pytest + + +@pytest.fixture +def correct_parameters(): + return { + "scope": "https://www.googleapis.com/auth/calendar", + "email": "info@sayvai.io", + "summary": "sample test calendar", + "date": "2023, 10, 4, 16, 00/2023, 10, 4, 16, 59/9629076714/SriDhanush", + } + + +@pytest.fixture +def incorrect_parameters(): + return { + "scope": "https://www.googleapis.com/auth/calendar", + "email": "info@sayvai.io", + "summary": "sample test calendar", + "date": "2023, 10, 4, 16, 00/2023, 10, 4, 16, 59/SriDhanush", + } + + +@pytest.fixture +def past_date(): + return { + "scope": "https://www.googleapis.com/auth/calendar", + "email": "info@sayvai.io", + "summary": "sample test calendar", + "date": "2023, 10, 4, 16, 00/2023, 10, 4, 16, 59/9629076714/SriDhanush", + } + + +@pytest.fixture +def past_time(): + return { + "scope": "https://www.googleapis.com/auth/calendar", + "email": "info@sayvai.io", + "summary": "sample test calendar", + "date": "2023, 12, 4, 16, 00/2023, 12, 4, 13, 59/9629076714/SriDhanush", + } + diff --git a/tests/calendar/test_calendar.py b/tests/calendar/test_calendar.py new file mode 100644 index 0000000..14bce03 --- /dev/null +++ b/tests/calendar/test_calendar.py @@ -0,0 +1,40 @@ +import pytest +from typing import Tuple, List, Dict, Any, Text, Optional +from sayvai_tools.tools.calendar.calendar import Calendar + + +def test_positive(correct_parameters: Dict[str, Any]): + scope = correct_parameters["scope"] + email = correct_parameters["email"] + summary = correct_parameters["summary"] + date = correct_parameters["date"] + cal = Calendar(scope=scope, email=email, summary=summary) + assert cal._run(date) + + +def test_incorrect(incorrect_parameters: Dict[str, Any]): + scope = incorrect_parameters["scope"] + email = incorrect_parameters["email"] + summary = incorrect_parameters["summary"] + date = incorrect_parameters["date"] + cal = Calendar(scope=scope, email=email, summary=summary) + with pytest.raises(Exception): + cal._run(date) + + +def test_past_date(past_date: Dict[str, Any]): + scope = past_date["scope"] + email = past_date["email"] + summary = past_date["summary"] + date = past_date["date"] + cal = Calendar(scope=scope, email=email, summary=summary) + assert cal._run(date) == "The provided date and time are in the past." + + +def test_time(past_time: Dict[str, Any]): + scope = past_time["scope"] + email = past_time["email"] + summary = past_time["summary"] + date = past_time["date"] + cal = Calendar(scope=scope, email=email, summary=summary) + assert cal._run(date) == "End time should be greater than start time."