From 1f76088cd9b989ea8b4c93bac8e44eed4d6b7b8d Mon Sep 17 00:00:00 2001 From: Roderick Bishop Date: Tue, 12 Mar 2024 19:14:01 -0500 Subject: [PATCH] logging, linting changes, and some todo items --- assistant/.gitignore | 3 +- assistant/README.md | 16 +++--- assistant/assistant/__init__.py | 90 ++++++++++++++++++--------------- 3 files changed, 61 insertions(+), 48 deletions(-) diff --git a/assistant/.gitignore b/assistant/.gitignore index 94e20cb..bd37646 100644 --- a/assistant/.gitignore +++ b/assistant/.gitignore @@ -1,2 +1,3 @@ *.env -*.idea \ No newline at end of file +*.idea +*.log \ No newline at end of file diff --git a/assistant/README.md b/assistant/README.md index 334557d..385b01c 100644 --- a/assistant/README.md +++ b/assistant/README.md @@ -24,17 +24,19 @@ Tony Stark, J.A.R.V.I.S. and Robert Elo Bishop(my grandfather). ELO is meant to - Chat GPT integration or Local LLM generation; The option to choose/switch models. - Internet Search (whitelisted sources) - Wake and shut down word/phrases/intents +- Modes for verbose logging/print out -## tech stack/integrations +## Possible tech stack/modules/tools to use -Python- language -Poetry- build system -pyttsx4/Elevel labs- Text to speech -OpenAI API- interact with models -Exa- Search for AI -Slint-Desktop UI for python +- [Python](https://www.python.org/)- language +- [Poetry](https://python-poetry.org/)- build system +- [pyttsx4](https://pypi.org/project/pyttsx4/) or [Eleven labs](https://elevenlabs.io/)- Text to speech +- [OpenAI API](https://platform.openai.com/docs/overview)- interact with models +- [Exa](https://github.com/exa-labs/exa-py)- Search for AI ## Changelog +- 3.8.24: Got instruction on project organization/implementation. Separate part into epics/bodies of work. Could use JIRA or some other tool to organize and stay on track. Simplify README & develop a more clear project. + ## contributors diff --git a/assistant/assistant/__init__.py b/assistant/assistant/__init__.py index f58438e..a63fea3 100644 --- a/assistant/assistant/__init__.py +++ b/assistant/assistant/__init__.py @@ -1,13 +1,12 @@ -import threading import time - +import datetime +import os +import logging import speech_recognition as sr import pyttsx4 -import datetime from openai import OpenAI import elevenlabs from elevenlabs import play -import os from dotenv import load_dotenv from exa_py import Exa @@ -26,18 +25,29 @@ # initialize integration components exa: Exa = Exa(exaKey) +# Create and configure logger +today = datetime.datetime.now().__str__() +logging.basicConfig(filename=f"log{today}.log", + format='%(asctime)s %(message)s', + filemode='w') + +logger = logging.getLogger() -def speakAndPrint(text) -> None: - # audio = elevenlabs.generate( - # text=text, voice="Adam", model="eleven_monolingual_v1", api_key=elevenKey - # ) - # play(audio) +# todo: timer metrics on request completion time +# todo: GPT-4 + + +def speak_and_print(text) -> None: + audio = elevenlabs.generate( + text=text, voice="George", model="eleven_monolingual_v1", api_key=elevenKey + ) + play(audio) print(text) - ttsEngine.say(text=text) - ttsEngine.runAndWait() + # ttsEngine.say(text=text) + # ttsEngine.runAndWait() -def wishMe() -> None: +def wish_me() -> None: hour: int = int(datetime.datetime.now().hour) if 0 <= hour < 12: greeting = "Good Morning, Rod! How may I help you" @@ -47,12 +57,11 @@ def wishMe() -> None: else: greeting = "Good evening, Sir" - speakAndPrint(greeting) + speak_and_print(greeting) # the assistant will listen to you, go speech to text. def listen() -> str: - print(sr.Microphone.list_working_microphones()) with sr.Microphone(device_index=1) as source: print("Listening...") @@ -73,7 +82,7 @@ def listen() -> str: # submit text to LLM -def textToModel(query: str) -> None: +def text_to_model(query: str) -> None: completion = client.chat.completions.create( model="gpt-3.5-turbo", messages=[ @@ -83,7 +92,7 @@ def textToModel(query: str) -> None: ] ) reply = summarize(completion.choices[0].message.content) - speakAndPrint(reply) + speak_and_print(reply) def summarize(response: str) -> str: @@ -94,21 +103,21 @@ def summarize(response: str) -> str: return response -def listenForKeywords(query: str) -> bool: +def parse_keywords(query: str) -> bool: skipLLM = False if query == "stop": - speakAndPrint("Okay, hope I was able to help!") - exit() + speak_and_print("Okay, hope I was able to help!") + os._exit(0) elif "thanks elo that is all I needed" in query: - speakAndPrint("Okay, hope I was able to help!") - exit() + speak_and_print("Okay, hope I was able to help!") + os._exit(0) elif 'search' in query: - speakAndPrint("I can run a search query for that if you'd like") + speak_and_print("I can run a search query for you. Please confirm") if confirm(): - speakAndPrint("What would you like me to search?") + speak_and_print("What would you like me to search?") desiredSearch = listen() contents = exa.search_and_contents(desiredSearch) - speakAndPrint("I've come up with a couple of results and displayed them in your console") + speak_and_print("I've come up with a couple of results and displayed them in your console") print(contents.results) skipLLM = True @@ -119,25 +128,26 @@ def listenForKeywords(query: str) -> bool: def confirm() -> bool: confirmationQuery = listen() if confirmationQuery == "yes" or "ok" or "sure": - speakAndPrint("Confirmed") + speak_and_print("Confirmed") return True else: - speakAndPrint("alright.") + speak_and_print("alright.") return False - +#todo: calibrate function needs to also set a mic to use for the session. This way it makes it smoother. def calibrate() -> int: - speakAndPrint("Hi. Elo is booting up. Please wait.") + speak_and_print("Hi. Elo is booting up. Please wait.") print("Initializing...") - microphoneDict = sr.Microphone.list_working_microphones() - print("A list of mics! %s" % microphoneDict) - print("A list of mic values! %s" % microphoneDict.values()) - for mic in microphoneDict.values(): + microphones = sr.Microphone.list_working_microphones() + print("A list of mics! %s" % microphones) + print("A list of mic values! %s" % microphones.values()) + for mic in microphones.values(): if mic == 'Shure MV7': return 1 + logger.info(f"ELO Chose device 1{microphones.get('Shure MV7')}") else: - speakAndPrint("Please connect your iphone's mic sir.") - iphone = microphoneDict.get('Skywalker (2) Microphone') + speak_and_print("Please connect your iphone's mic sir.") + iphone = microphones.get('Skywalker (2) Microphone') time.sleep(5) return iphone @@ -145,15 +155,15 @@ def calibrate() -> int: def main() -> None: startup = calibrate() if startup == 0: - speakAndPrint("Not able to connect to audio source") - exit() - wishMe() + speak_and_print("Not able to connect to audio source") + quit(0) + wish_me while True: query = listen().lower() - if not listenForKeywords(query): - textToModel(query) + if not parse_keywords(query): + text_to_model(query) else: - break + pass if __name__ == "__main__":