[
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "content": "---\nname: Bug report\nabout: Create a report to help us improve\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n**Describe the bug**\nA clear and concise description of what the bug is.\n\n**To Reproduce**\nSteps to reproduce the behavior:\n1. Go to '...'\n2. Click on '....'\n3. Scroll down to '....'\n4. See error\n\n**Expected behavior**\nA clear and concise description of what you expected to happen.\n\n**Screenshots**\nIf applicable, add screenshots to help explain your problem.\n\n**Desktop (please complete the following information):**\n - OS: [e.g. iOS, Windows (10/11)]\n\n**Additional context**\nAdd any other context about the problem here.\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.md",
    "content": "---\nname: Feature request\nabout: Suggest an idea for this project\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n**Is your feature request related to a problem? Please describe.**\nA clear and concise description of what the problem is. Ex. I'm always frustrated when [...]\n\n**Describe the solution you'd like**\nA clear and concise description of what you want to happen.\n\n**Describe alternatives you've considered**\nA clear and concise description of any alternative solutions or features you've considered.\n\n**Additional context**\nAdd any other context or screenshots about the feature request here.\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/help-request.md",
    "content": "---\nname: Help Request\nabout: Create a report to help us improve\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n**Describe the Issue**\nA clear and concise description of what your issue is\n\n**To Reproduce**\nSteps to reproduce the behavior:\n1. Go to '...'\n2. Click on '....'\n3. Scroll down to '....'\n4. See error\n\n**Expected behavior**\nA clear and concise description of what you expected to happen.\n\n**Screenshots**\nIf applicable, add screenshots to help explain your problem.\n\n**Desktop (please complete the following information):**\n - OS: [e.g. iOS, Windows (10/11),]\n**Additional context**\nAdd any other context about the problem here.\n"
  },
  {
    "path": ".gitignore",
    "content": "# ignore files\nkeys.py\nkeys.txt\nassistants/keys.txt\nassistants/keys.yaml\nbatch_to_exe.txt\ninterview.spec\n\n#ignore filetype\n*.spec\n*.exe\n*.pyc\n*.wav\n*.zip\n\n\n# ignore folders\nconversations/\nolder prompts/\n__pycache__/\ndist/\nbuild/\nvenv/\n.venv/"
  },
  {
    "path": "README.md",
    "content": "> **Project is currently on hiatus as of this update, 12/20/2023.**\n\n# QUICK DESCRIPTION:\n\nThis repo utilizes OpenAI's GPT-3.5 Turbo model to engage in personalized conversations with users, catering to their preferred communication style. As GPT-3.5 Turbo serves as the foundation for ChatGPT, this project essentially shares its underlying model. Ultimately, the aim of this project is to develop a personal assistant that emulates human-like interactions. As the project is a work in progress, its features will expand as I continue to refine and iterate on the concept.\n\nI highly recommend you run the python scripts as there are bugs with the exe files on Windows 11.  But, the fastest way to try these assistants would be to setup your API keys in the ```key.yaml``` file and then run the exe files I have provided.  For this to work, **you must** rename ```keys_example.yaml``` to be ```keys.yaml```.  To find the exe files, check the latest release for this project https://github.com/JarodMica/Vivy/releases/\n\n## YouTube Tutorial \nMost recent: https://youtu.be/0qpar5R1VA4\n\n## Features\n:heavy_check_mark: Voice recognition and voice responses\n\n:heavy_check_mark: Integration with ChatGPT for responses and ElevenLabs for natural sounding text-to-speech\n\n:heavy_check_mark: Easy customization for personalities of the AI assistants, with funtionality variations of the assistants\n\n:heavy_check_mark: Local conversation history stored for your own information (assistant does not reference them yet)\n\n## Enhancements in the Pipeline \n- [ ] Speech Emotion Recognition (SER) - Ability to recognize the speakers emotion based on tone and be able to use this in better assessing the user\n- [ ] Facial Emotion Recognition (FER) - Ability to recognize the emotion of the speaker by analyzing frames of a webcam feed/camera to assess the user\n- [ ] Local models for voice inferencing - No need to rely on ElevenLabs for \"natural voice output\", possible to use https://github.com/coqui-ai/TTS \n- [ ] Local long term memory - Ability to remember previous conversations with the user and store it locally, must be fast and efficient\n\n## To be created for different assistant types\n- [ ] Current assistant types: chat(), interview(), assistant(), assistantp()\n- [ ] Streamer - acts as a co-host to a stream, determines when to speak\n- [ ] Vtuber - Just go look at Neurosama.  Might not even be encompassable by Vivy, might have to be its own repo\n\n## Bugs\n- [ ] Currently some bugs with the exe files that I'm not able to trace entirely.  Issue [#11](https://github.com/JarodMica/Vivy/issues/11)\n is tracking it\n\n## EXE Quick Use\n\nIf you just want to try out the assistants, download the zip folder and then unzip it to any location on your PC. Once unzipped, rename the keys_example file to ```keys.yaml``` and then set up your API Keys in ```key.yaml```. Now you can do two things, run the exe and try it out or adjust the prompts in the prompts folder.  If you run interview.exe, it's going to use the interview.txt file (same with roleplay). Else, you can modify the prompts to your own case and then run the exe files.\n\n## How to run it in python:\nYou'll need Git, Python, and I recommend some type of IDE like VSCode.  I have a 5-minute tutorial here **BUT BEWARE, I show python 3.11, you need 3.10 for Vivy**: https://youtu.be/Xk-u7tTqwwY\n\nOnce you have those things installed, open a terminal window and clone the repo:\n```\ngit clone https://github.com/JarodMica/Vivy.git\n```\n\n**Note:** I highly recommend looking into doing this as a virtual environment (venv) so that you don't have any issues in the future if you're installing other python projects, go watch this here: https://www.youtube.com/watch?v=q1ulfoHkNtQ.  \n\nThat being said, if you just wanna run this project real quick, you can follow below (make sure you didn't close the terminal after cloning the repo):\n```\ncd Vivy\npip install -r requirements.txt\n```\nNow navigate into the assistants folder and then choose a python script to run, ```dir``` will list all of the scripts in the folder:\n```\ncd assistants\ndir\npython assistantp.py\n```\n\nAnd boom! The script should be running.\n\nOnce again, make sure your API keys inside of ```key.yaml``` are set-up.  If you don't do this, it won't work at all.  To get the openAI key, open up an account at https://openai.com/blog/openai-api and to get an Eleven Labs API key, you need to set-up an account at https://beta.elevenlabs.io/ (this is a paid option).\n \n## If you're running in Python\n\nHere's a quick description of the variables I reccommend be modified.  If you want to see how this is implemented in code, check out the python scripts in the assistants folder.  You'll find these at the top of the python script.\n\n```\nfoldername = \"assistantP\"\npersonality = \"assistantP\"\nvoicename = \"Rem\"\nuseEL = False\nusewhisper = True\n```\n\n#### The 5-ish variables you can modify:\n\n1. You set the ```foldername``` of where the conversations will be stored, this will be set in the conversations folder.\n2. You set the ```personality``` by inputing the name of your text file and then editting the contents of the txt file name that is specified.  What this does is \"prime\" the ChatGPT conversation and sets the **personality** of the bot.  All of your prompts must go in the prompts folder and I have some examples in there already.\n3. If you're using Eleven Labs for voice generation, change ```voicename``` to whatever voice you want that is available to you in Eleven Labs.\n4. If you want to use Eleven Labs, change ```useEL``` to True\n5. If you want to use Whisper instead of google voice recognition, change ```usewhisper``` to True.\n\nThe other text below the 5 variables in the script are objects and function calls to set-up the voice assisant using the class and function in the voice_assistant module.\n\nMost of the functions in the voice_assistant module have docstrings that you can read to clairfy what it does, but I'm still working on making it more clear.\n\n"
  },
  {
    "path": "__init__.py",
    "content": "\n"
  },
  {
    "path": "assistants/assistant.py",
    "content": "import sys \nimport os\n\nfrom package import kokoro\nfrom package import assistant\nfrom utils import get_file_paths\n\n# The only variables that need to be modifed\nfoldername = \"assistant\"\npersonality = \"assistant\"\nvoicename = \"Rem\"\nuseEL = False\nusewhisper = True\n\n# This code block only checks if it's being ran as a python script or as an exe\nif getattr(sys, 'frozen', False):\n    script_dir = os.path.dirname(os.path.abspath(sys.executable))\n    while True:\n        user_input = input(\"Are you using an Eleven Labs voice (yes/no)?\\n\")\n        if user_input == 'yes':\n            voicename = input(\"What is the name of you Eleven Labs voice: \")\n            useEL = True\n            break\n        elif user_input == 'no':\n            break\n        else:\n            print(\"Invalid Input, please try again.\")\nelse:\n    script_dir = os.path.dirname(os.path.abspath(__file__))\n\nfoldername_dir, personality_dir, keys = get_file_paths(script_dir, foldername, personality)\n\n# Initialize the chat assitant with the variables that you've set \n\nchatbot = kokoro.Kokoro(personality=personality_dir, \n                keys=keys, \n                voice_name=voicename\n                )\nassistant_ = assistant.Assistant(chatbot)\n\nassistant_.run(save_foldername=foldername_dir,\n            useEL=useEL,\n            usewhisper=usewhisper\n            )"
  },
  {
    "path": "assistants/assistantp.py",
    "content": "import sys \nimport os\n\nfrom package import kokoro\nfrom package import assistant_p\nfrom utils import get_file_paths\n\n# The only variables that need to be modifed\nfoldername = \"assistantP\"\npersonality = \"assistantP\"\nvoicename = \"Rem\"\nuseEL = False\nusewhisper = True\n\n# This code block only checks if it's being ran as a python script or as an exe\nif getattr(sys, 'frozen', False):\n    script_dir = os.path.dirname(os.path.abspath(sys.executable))\n    while True:\n        user_input = input(\"Are you using an Eleven Labs voice (yes/no)?\\n\")\n        if user_input == 'yes':\n            voicename = input(\"What is the name of you Eleven Labs voice: \")\n            useEL = True\n            break\n        elif user_input == 'no':\n            break\n        else:\n            print(\"Invalid Input, please try again.\")\nelse:\n    script_dir = os.path.dirname(os.path.abspath(__file__))\n\nfoldername_dir, personality_dir, keys = get_file_paths(script_dir, \n                                                       foldername, \n                                                       personality)\n\nchatbot = kokoro.Kokoro(personality=personality_dir, \n                keys=keys, \n                voice_name=voicename\n                )\n\nassistant = assistant_p.AssistantP(chatbot)\n\nassistant.run(save_foldername=foldername_dir,\n                useEL=useEL,\n                usewhisper=usewhisper\n                )\n"
  },
  {
    "path": "assistants/chat.py",
    "content": "import sys \nimport os\n\nfrom package import kokoro\nfrom package import chat\nfrom utils import get_file_paths\n\n# The only variables that need to be modifed\nfoldername = \"chat\"\npersonality = \"chat\"\nvoicename = \"Rem\"\nuseEL = False\nusewhisper = True\n\n# This code block only checks if it's being ran as a python script or as an exe\nif getattr(sys, 'frozen', False):\n    script_dir = os.path.dirname(os.path.abspath(sys.executable))\n    while True:\n        user_input = input(\"Are you using an Eleven Labs voice (yes/no)?\\n\")\n        if user_input == 'yes':\n            voicename = input(\"What is the name of you Eleven Labs voice: \")\n            useEL = True\n            break\n        elif user_input == 'no':\n            break\n        else:\n            print(\"Invalid Input, please try again.\")\nelse:\n    script_dir = os.path.dirname(os.path.abspath(__file__))\n\nfoldername_dir, personality_dir, keys = get_file_paths(script_dir, \n                                                       foldername, \n                                                       personality)\n\nchatbot = kokoro.Kokoro(personality=personality_dir, \n                  keys=keys, \n                  voice_name=voicename\n                  )\n\nassistant = chat.Chat(chatbot)\n\nassistant.run(save_foldername=foldername_dir,\n                   useEL=useEL,\n                   usewhisper=usewhisper\n                   )\n"
  },
  {
    "path": "assistants/interview.py",
    "content": "import sys \nimport os\n\nfrom package import kokoro\nfrom package import interview\nfrom utils import get_file_paths\n\n# The only variables that need to be modifed\nfoldername = \"interview\"\npersonality = \"interview\"\nsystem_change = \"interview_end\"\nvoicename = \"Rem\"\nuseEL = False\nusewhisper = True\n\n# This code block only checks if it's being ran as a python script or as an exe\nif getattr(sys, 'frozen', False):\n    # script_dir = os.path.dirname(os.path.abspath(sys.executable))\n    script_dir = sys._MEIPASS\n    while True:\n        user_input = input(\"Are you using an Eleven Labs voice (yes/no)?\\n\")\n        if user_input == 'yes':\n            voicename = input(\"What is the name of you Eleven Labs voice: \")\n            useEL = True\n            break\n        elif user_input == 'no':\n            break\n        else:\n            print(\"Invalid Input, please try again.\")\nelse:\n    script_dir = os.path.dirname(os.path.abspath(__file__))\n\nfoldername_dir, personality_dir, keys, syschange_dir = get_file_paths(script_dir, \n                                                                     foldername, \n                                                                     personality, \n                                                                     system_change)\n\nchatbot = kokoro.Kokoro(personality=personality_dir, \n                  keys=keys, \n                  voice_name=voicename\n                  )\nassistant = interview.Interview(chatbot)\n\nassistant.run(save_foldername=foldername_dir,\n                  system_change=syschange_dir,\n                   useEL=useEL,\n                   usewhisper=usewhisper\n                   )\n\n"
  },
  {
    "path": "assistants/keys_example.yaml",
    "content": "EL_KEY : your_el_key\nOPENAI_KEY : your_openai_key\n"
  },
  {
    "path": "assistants/one_up.py",
    "content": "import sys \nimport os\n\nfrom package import kokoro\nfrom package import assistant\nfrom utils import get_file_paths\n\n# The only variables that need to be modifed\nfoldername = \"one-up\"\npersonality = \"one-up\"\nvoicename = \"Rem\"\nuseEL = False\nusewhisper = True\n\n# This code block only checks if it's being ran as a python script or as an exe\nif getattr(sys, 'frozen', False):\n    script_dir = os.path.dirname(os.path.abspath(sys.executable))\n    while True:\n        user_input = input(\"Are you using an Eleven Labs voice (yes/no)?\\n\")\n        if user_input == 'yes':\n            voicename = input(\"What is the name of you Eleven Labs voice: \")\n            useEL = True\n            break\n        elif user_input == 'no':\n            break\n        else:\n            print(\"Invalid Input, please try again.\")\nelse:\n    script_dir = os.path.dirname(os.path.abspath(__file__))\n\nfoldername_dir, personality_dir, keys = get_file_paths(script_dir, foldername, personality)\n\n# Initialize the chat assitant with the variables that you've set \n\nchatbot = kokoro.Kokoro(personality=personality_dir, \n                keys=keys, \n                voice_name=voicename\n                )\nassistant_ = assistant.Assistant(chatbot)\n\nassistant_.run(save_foldername=foldername_dir,\n            useEL=useEL,\n            usewhisper=usewhisper\n            )"
  },
  {
    "path": "assistants/package/__init__.py",
    "content": "\n"
  },
  {
    "path": "assistants/package/assistant.py",
    "content": "import time\n\nfrom .kokoro import Kokoro\nfrom .assistant_utils import *\n\nclass Assistant:\n    def __init__(self, chatGPT: Kokoro):\n        self.chatGPT = chatGPT\n\n    def run(self, save_foldername, keyword ='hey', useEL = False, usewhisper = False, timeout = 5):\n        '''\n        This method acts as more of a \"tradtional\" smart assistant such as google or alexa and is FORGETFUL, meaning it  \n        will start over the current conversation once it times out. This means it's best used for 1 question \n        and some quick follow-up questions.  It waits for some keyword (if not specified, it will be \"hey\") and\n        then proceeeds to the \"conversation\". Once in the conversation, you will be able to interact with the assistant \n        as you would normally, butif no speech is detected after 5 seconds (adjustable), the conversation will reset and \n        the assistant will need to be re-initiated with \"hey\".  \n\n        Args:\n            save_foldername (str): The name of the folder where the conversation will be saved.\n            keyword (str): The keyword(s) that will initiate the conversation\n            useEL (bool, optional): If false, the bot generates responses using the system voices\n            usewhipser (bool, optional): Defaults to False to use google speech recognition\n            timeout : the amount of time the assistant will wait before resetting\n        '''\n\n        while True:\n            beep()\n            self.chatGPT.start_conversation(keyword)\n            self.chatGPT.messages = [{\"role\" : \"system\", \"content\" : f\"{self.chatGPT.mode}\"}]\n            suffix = save_conversation(self.chatGPT.messages, save_foldername)\n            self.chatGPT.generate_voice(\"I'm listening.\", useEL)\n            start_time = time.time()\n            while True:\n                audio = self.chatGPT.listen_for_voice()\n                try:\n                    if usewhisper == True:\n                        user_input = self.chatGPT.whisper(audio)\n                        print(\"You said: \", user_input) # Checking\n                    else:    \n                        user_input = self.chatGPT.r.recognize_google(audio)\n                    \n                except :\n                    if time.time() - start_time > timeout:\n                        break\n                    continue\n                \n                if \"quit\" in user_input.lower() or \"quit.\" in user_input.lower():\n                    raise SystemExit\n\n                self.chatGPT.messages.append({\"role\" : \"user\", \"content\" : user_input})\n                try:\n                    response = self.chatGPT.response_completion()\n                    self.chatGPT.generate_voice(response=response, useEL=useEL)\n                    save_inprogress(self.chatGPT.messages, suffix=suffix, save_foldername=save_foldername)\n                    start_time = time.time()\n                except Exception as e:\n                    print(f\"{e}\")\n                    print(\"Token limit exceeded, clearing messsages list and restarting\")\n                    self.chatGPT.messages = [{\"role\": \"system\", \"content\": f\"{self.chatGPT.mode}\"}]\n                    suffix = save_conversation(self.chatGPT.messages, save_foldername)\n"
  },
  {
    "path": "assistants/package/assistant_p.py",
    "content": "import time\n\nfrom .kokoro import Kokoro\nfrom .assistant_utils import *\n\nclass AssistantP:\n    def __init__(self, chatGPT: Kokoro):\n        self.chatGPT = chatGPT\n\n    def run(self, save_foldername, keyword ='hey', useEL = False, usewhisper = False, timeout = 5):\n        '''\n        Nearly identical to assistant, but maintains a persistent (p) memory of the conversation.  This means\n        when it timesout after 5 seconds, it will maintain memory of the current conversation up until you restart\n        or the token limit is reached. \n\n        Args:\n            save_foldername (str): The name of the folder where the conversation will be saved.\n            keyword (str): The keyword(s) that will initiate the conversation\n            useEL (bool, optional): If false, the bot generates responses using the system voices\n            usewhipser (bool, optional): If false, uses google speech recognition\n            timeout : the amount of time the assistant will wait before resetting\n        '''\n\n        while True:\n            beep()\n            self.chatGPT.start_conversation(keyword = keyword)\n            self.chatGPT.generate_voice(\"I'm listening.\", useEL)\n            suffix = save_conversation(self.chatGPT.messages, save_foldername)\n            start_time = time.time()\n\n            while True:\n                audio = self.chatGPT.listen_for_voice()\n                try:\n                    if usewhisper == True:\n                        user_input = self.chatGPT.whisper(audio)\n                        print(\"You said: \", user_input) # Checking\n                    else:    \n                        user_input = self.chatGPT.r.recognize_google(audio)\n                except :\n                    if time.time() - start_time > timeout:\n                        break\n                    continue\n                \n                check_quit(user_input)\n                \n                try:\n                    self.chatGPT.messages.append({\"role\" : \"user\", \"content\" : user_input})\n                    response = self.chatGPT.response_completion()\n                    self.chatGPT.generate_voice(response=response, useEL=useEL)\n                    save_inprogress(self.chatGPT.messages, suffix=suffix, save_foldername=save_foldername)\n                    start_time = time.time()\n                except Exception as e:\n                    print(f\"{e}\")\n                    if \"overloaded\" in e.split():\n                        continue\n                    print(\"Token limit exceeded, clearing messsages list and restarting\")\n                    self.chatGPT.messages = [{\"role\": \"system\", \"content\": f\"{self.chatGPT.mode}\"}]\n                    suffix = save_conversation(self.chatGPT.messages, save_foldername)"
  },
  {
    "path": "assistants/package/assistant_utils.py",
    "content": "import json\nimport os\nimport winsound\nimport sounddevice as sd\nimport soundfile as sf\n\ndef check_quit(user_input:str):\n    if user_input.lower() == \"quit\" or \"quit.\" in user_input.lower():\n        raise SystemExit\n    \ndef beep():\n    try:\n        script_dir = os.path.dirname(os.path.abspath(__file__))\n        beep_path = os.path.join(script_dir, \"resources\", \"beep.mp3\")\n        data, samplerate = sf.read(beep_path)\n        sd.play(data, samplerate)\n    except:\n        # If `soundfile` fails, play a system beep instead\n        duration = 500\n        frequency = 500\n        winsound.Beep(frequency, duration)\n\ndef save_conversation(messages, save_foldername:str):\n    '''\n    Checks the folder for previous conversations and will get the next suffix that has not been used yet.\n\n    Args:\n        save_foldername (str) : Takes in the path to save the conversation to.\n    Returns:\n        suffix (int) : Needed to keep track of the conversation name for save_inprogress\n    '''\n    \n    os.makedirs(save_foldername, exist_ok=True)\n    base_filename = 'conversation'\n    suffix = 0\n    filename = os.path.join(save_foldername, f'{base_filename}_{suffix}.txt')\n\n    while os.path.exists(filename):\n        suffix += 1\n        filename = os.path.join(save_foldername, f'{base_filename}_{suffix}.txt')\n    with open(filename, 'w', encoding = 'utf-8') as file:\n        json.dump(messages, file, indent=4, ensure_ascii=False)\n\n    return suffix\n\ndef save_inprogress(messages, suffix, save_foldername):\n    '''\n    Uses the suffix number returned from save_conversation to continually update the \n    file for this instance of execution.  This is so that you can save the conversation \n    as you go so if it crashes, you don't lose to conversation.  Shouldn't be called\n    from outside of the class.\n\n    Args:\n        suffix  :  Takes suffix count from save_conversation()\n    '''\n\n    os.makedirs(save_foldername, exist_ok=True)\n    base_filename = 'conversation'\n    filename = os.path.join(save_foldername, f'{base_filename}_{suffix}.txt')\n\n    with open(filename, 'w', encoding = 'utf-8') as file:\n        json.dump(messages, file, indent=4, ensure_ascii=False)"
  },
  {
    "path": "assistants/package/chat.py",
    "content": "from .kokoro import Kokoro\nfrom .assistant_utils import *\n\nclass Chat:\n    def __init__(self, chatGPT: Kokoro):\n        self.chatGPT = chatGPT\n\n    def run(self, save_foldername, keyword ='hey', updatein='', useEL=False, usewhisper=False):\n        '''\n        Chat with an AI assistant using OpenAI's GPT-3 model.  Unlike the others, once you initiate\n        the conversation with a keyword, it will just keep listening.  This means no timer on the amount\n        of silence in between speaking, but it also means it's listening forever and will respond back\n        until you quit out.  Check out assistant() or assistantp() if you want behavior closer to\n        Google/Alexa.\n\n        Args:\n            save_foldername (str): The name of the folder to save the conversation history in.\n            keyword (str) : The keyword to get the assistant listening\n            updatein (str): The path of a file to read and update the \"system\" role for ChatGPT, does so by appending messages\n            useEL (bool, optional): Whether to use Eleven Labs' API to generate and play audio. Defaults to False.\n            usewhisper (bool, optional): Whether to use Whisper for voice recognition.  Defaults to False.\n        '''\n        while True:\n            self.chatGPT.start_conversation(keyword=keyword)\n            suffix = save_conversation(self.chatGPT.messages, save_foldername)\n            while True:\n                audio = self.chatGPT.listen_for_voice(timeout=None)\n                try:\n                    if usewhisper:\n                        if audio:\n                            user_input = self.chatGPT.whisper(audio)\n                            print(\"You said: \", user_input) # Checking\n                        else:\n                            raise ValueError(\"Empty audio input\")\n                    else:    \n                        user_input = self.chatGPT.r.recognize_google(audio)\n                    \n                except Exception as e:\n                    print(e)\n                    continue\n\n                check_quit(user_input)\n                \n                # This merely appends the list of dictionaries, it doesn't overwrite the existing\n                # entries.  It should change the behavior of chatGPT though based on the text file.\n                if updatein != '':\n                    if \"update chat\" in user_input.lower():\n                            update = updatein\n                            with open (update, \"r\") as file:\n                                update = file.read()\n                                self.chatGPT.messages.append({\"role\" : \"system\", \"content\" : update})\n\n                self.chatGPT.messages.append({\"role\": \"user\", \"content\": user_input})\n\n                try:\n                    response = self.chatGPT.response_completion()\n                    self.chatGPT.generate_voice(response=response, useEL=useEL)\n                    save_inprogress(self.chatGPT.messages, suffix=suffix, save_foldername=save_foldername)\n                except:\n                    print(\"Token limit exceeded, clearing messsages list and restarting\")\n                    self.chatGPT.messages = [{\"role\": \"system\", \"content\": f\"{self.chatGPT.mode}\"}]\n                    suffix = save_conversation(self.chatGPT.messages, save_foldername)\n                "
  },
  {
    "path": "assistants/package/interview.py",
    "content": "from .kokoro import Kokoro\nfrom .assistant_utils import *\n\nclass Interview:\n    def __init__(self, chatGPT: Kokoro):\n        self.chatGPT = chatGPT\n\n    def run(self, save_foldername, system_change = '', useEL=False, usewhisper = False):\n        '''\n        Nearly identical to how the chat method works but this method conducts an interview \n        with a candidate using an interview bot style. The conversation is saved to a \n        specified folder and \"system_change\" is used to modify how the system operates (I use it to end the \n        interview, but you can use any text format you would like)\n\n        Args:\n            save_foldername (str): The name of the folder where the conversation will be saved.\n            system_change (str): path to the personality change .txt file\n            useEL (bool, optional): If false, the bot generates responses using the system voices\n            usewhipser (bool, optional); If false, uses google speech recognition\n        '''\n\n        suffix = save_conversation(self.chatGPT.messages, save_foldername)\n        start = (\"Introduce yourself (pick a random name) and welcome the candidate in.\"\n                \"Let them know what they're applying for and then proceed by asking for an introduction.\"\n                \"Keep track but do not not inform the candidate about the points system\")\n        self.chatGPT.messages.append({\"role\": \"user\", \"content\": start})\n        response = self.chatGPT.response_completion()\n        self.chatGPT.generate_voice(response, useEL)\n        while True:\n            audio = self.chatGPT.listen_for_voice(timeout=None)\n            try:\n                if usewhisper == True:\n                    user_input = self.chatGPT.whisper(audio)\n                    print(\"You said: \", user_input) # Checking\n                else:  \n                    user_input = self.chatGPT.r.recognize_google(audio)\n                \n            except Exception as e:\n                print(e)\n                continue\n            \n            if \"quit\" in user_input.lower() or \"quit.\" in user_input.lower():\n                raise SystemExit\n            \n            self.chatGPT.messages.append({\"role\": \"user\", \"content\": user_input})\n            try:\n                response = self.chatGPT.response_completion()\n                self.chatGPT.generate_voice(response, useEL)\n                save_inprogress(self.chatGPT.messages, suffix=suffix, save_foldername=save_foldername)\n\n                if system_change != '':\n                    # if the bot responds with this, changes \"system\" behavior\n                    if \"interview\" and \"is over\" in response.lower():\n                        system_change=system_change\n                        with open(system_change, \"r\", encoding=\"utf-\") as file:\n                            system = file.read()\n\n                        for message in self.chatGPT.messages:\n                            if message['role'] == 'system':\n                                message['content'] = system\n            except Exception as e:\n                print(\"Token limit exceeded, clearing messsages list and restarting\")\n                self.chatGPT.messages  = [{\"role\": \"system\", \"content\": f\"{self.chatGPT.mode}\"}]\n                suffix = save_conversation(self.chatGPT.messages, save_foldername)\n                self.chatGPT.messages.append({\"role\": \"user\", \"content\": start})\n                response = self.chatGPT.response_completion()\n                self.chatGPT.generate_voice(response, useEL)"
  },
  {
    "path": "assistants/package/kokoro.py",
    "content": "import speech_recognition as sr\nimport openai\nimport pyttsx3\nimport yaml\nfrom .assistant_utils import *\n\nfrom elevenlabslib import *\n\n\nclass Kokoro:\n    def __init__(self, personality:str, keys:str, voice_name=\"Rachel\", device_index=None, gptmodel:str=\"gpt-3.5-turbo\"):\n        '''\n        Initialize the ChatGPT class with all of the necessary arguments\n\n        Args:\n            personality (str)   : path to the prompts or \"personalities\" .txt\n            keys (str)          : path to the keys.txt file\n            voice_name (str)    : Eleven Labs voice to use\n            device_index (int)  : microphone device to use (0 is default)\n            gptmodel (str)      : choose the openai GPT model to use\n        '''\n        # Read in keys\n        with open(keys, \"r\") as file:\n            keys = yaml.safe_load(file)\n\n        # pyttsx3 Set-up\n        self.engine = pyttsx3.init()\n        # self.engine.setProperty('rate', 180) #200 is the default speed, this makes it slower\n        self.voices = self.engine.getProperty('voices')\n        self.engine.setProperty('voice', self.voices[1].id) # 0 for male, 1 for female\n\n        # GPT Set-Up\n        self.OPENAI_KEY = keys['OPENAI_KEY']\n        openai.api_key = self.OPENAI_KEY\n        self.gptmodel = gptmodel\n\n        # Eleven Labs Set-up\n        try:\n            self.EL_KEY = keys['EL_KEY'] #Eleven labs\n            self.user = ElevenLabsUser(f\"{self.EL_KEY}\")\n            try:\n                self.voice = self.user.get_voices_by_name(voice_name)[0]  # This is a list because multiple voices can have the same name\n            except:\n                print(\"Setting default voice to Rachel\")\n                print(\"(If you set a voice that you made, make sure it matches exactly)\"\n                        \" as what's on the Eleven Labs page.  Capitilzation matters here.\")\n                self.voice = self.user.get_voices_by_name(\"Rachel\")[0] \n        except:\n            print(\"No API Key set for Eleven Labs\")\n\n        # Mic Set-up\n        self.r = sr.Recognizer()\n        self.r.dynamic_energy_threshold=False\n        self.r.energy_threshold = 150 # 300 is the default value of the SR library\n        self.mic = sr.Microphone(device_index=device_index)\n\n        # Set-up the system of chatGPT\n        with open(personality, \"r\", encoding=\"utf-8\") as file:\n            self.mode = file.read()\n\n        self.messages  = [\n            {\"role\": \"system\", \"content\": f\"{self.mode}\"}\n        ]\n\n # Methods the assistants rely on------------------------------------------------------------------------------------------------------------------\n\n    # This is to only initiate a conversation if you say \"hey\"\n    def start_conversation(self, keyword = 'hey'):\n        while True:\n            with self.mic as source:\n                print(\"Adjusting to envionrment sound...\\n\")\n                self.r.adjust_for_ambient_noise(source, duration=1.0)\n                print(\"Listening: \")\n                audio = self.r.listen(source)\n                print(\"Done listening.\")\n                try:\n                    user_input = self.r.recognize_google(audio)\n                    print(f\"Google heard: {user_input}\\n\")\n                    user_input = user_input.split()\n                except:\n                    print(f\"Google couldn't process the audio\\n\")\n                    continue\n                # Key word in order to start the conversation \n                if f\"{keyword}\" in user_input:\n                    print(\"Keyword heard\")\n                    break\n                for i, word in enumerate(user_input):\n                    check_quit(word)\n\n    def response_completion(self, append=True):\n        '''\n        Notes:\n            You can modify the parameters in the ChatComplete to change how the bot responds\n            using things like temperature, max_token, etc.  Reference the chatGPT API to \n            see what parameters are available to use.\n        '''\n        completion = openai.ChatCompletion.create(\n                model=self.gptmodel,\n                messages=self.messages,\n                temperature=0.8\n            )\n        response = completion.choices[0].message.content\n        if append:\n            self.messages.append({\"role\": \"assistant\", \"content\": response})\n        print(f\"\\n{response}\\n\")\n        return response\n    \n    def generate_voice(self, response, useEL):\n        if useEL == True:\n            self.voice.generate_and_play_audio(f\"{response}\", playInBackground=False)\n        else:\n            self.engine.say(f\"{response}\")\n            self.engine.runAndWait()\n\n    def listen_for_voice(self, timeout:int|None=5):\n        with self.mic as source:\n            print(\"\\n Listening...\")\n            self.r.adjust_for_ambient_noise(source, duration=0.5)\n            try:\n                audio = self.r.listen(source, timeout)\n            except:\n                return []\n        print(\"no longer listening\")\n        return audio\n    \n    def whisper(self, audio):\n        '''\n        Uses the Whisper API to generate audio for the response text. \n\n        Args:\n            audio (AudioData) : AudioData instance used in Speech Recognition, needs to be written to a\n                                file before uploading to openAI.\n        Returns:\n            response (str): text transcription of what Whisper deciphered\n        '''\n        self.r.recognize_google(audio) # raise exception for bad/silent audio\n        with open('speech.wav','wb') as f:\n            f.write(audio.get_wav_data())\n        speech = open('speech.wav', 'rb')\n        model_id = \"whisper-1\"\n        completion = openai.Audio.transcribe(\n            model=model_id,\n            file=speech\n        )\n        response = completion['text']\n        return response\n"
  },
  {
    "path": "assistants/package/streamer.py",
    "content": "import time\n\nfrom .kokoro import Kokoro\nfrom .assistant_utils import *\n\nclass Streamer:\n    '''\n    This takes in two instantiations of Kokoro, so make sure to set them\n    both up in the assistant script\n    '''\n    def __init__(self, chatGPT: Kokoro, attention: Kokoro):\n        self.chatGPT = chatGPT\n        self.attention = attention\n\n    def run(self, save_foldername, useEL=False, usewhisper=False, timeout = 1):\n        # Create two agents: \n        # one to generate conversation generate_response()\n        # one to filter user input attention()\n        # after attention responds yes, proceed with responding\n        # via generate_response()\n        # give the user 5 seconds to continue talking, then\n        # go back to a listening state and repeat\n        while True:\n            suffix = save_conversation(self.chatGPT.messages, save_foldername)\n            while True:\n                audio = self.chatGPT.listen_for_voice()\n                try:\n                    if usewhisper:\n                        user_input = self.chatGPT.whisper(audio)\n                        print(\"You said: \", user_input) # Checking    \n                    else:\n                        user_input = self.chatGPT.r.recognize_google(audio)\n                \n                except Exception as e:\n                    print(e)\n                    continue\n\n                check_quit(user_input)\n\n                modified_text = self.attention.mode.replace('<<user_input>>', user_input)\n                self.attention.messages = [{\"role\" : \"user\", \"content\" : modified_text}]\n                check_attention = self.attention.response_completion()\n                \n                if \"no\" in check_attention.lower():\n                    continue\n                else:\n                    self.chatGPT.messages.append({\"role\" : \"user\", \"content\" : user_input})\n                    self.streamer_completion(save_foldername, suffix, useEL)\n\n                start_time = time.time()\n                while True:\n                    audio = self.chatGPT.listen_for_voice()\n                    try:\n                        if usewhisper:\n                            user_input = self.chatGPT.whisper(audio)\n                            print(\"You said: \", user_input) # Checking    \n                        else:\n                            user_input = self.chatGPT.r.recognize_google(audio)\n                    except Exception as e:\n                        if time.time() - start_time > timeout:\n                            break\n                        continue\n                    \n                    try:\n                        self.chatGPT.messages.append({\"role\" : \"user\" , \"content\" : user_input})\n                        self.streamer_completion(save_foldername, suffix, useEL)\n                        start_time = time.time()\n                    except Exception as e:\n                        print(f\"{e}\")\n                        if \"overloaded\" in e.split():\n                            continue\n                        print(\"Token limit exceeded, clearing messsages list and restarting\")\n                        self.chatGPT.messages = [{\"role\": \"system\", \"content\": f\"{self.chatGPT.mode}\"}]\n                        suffix = save_conversation(self.chatGPT.messages, save_foldername)\n\n\n    def streamer_completion(self, save_foldername, suffix, useEL):\n        try:\n            response = self.chatGPT.response_completion()\n            self.chatGPT.generate_voice(response, useEL)\n            save_inprogress(self.chatGPT.messages, suffix, save_foldername)\n        except:\n            print(\"Token limit exceeded, clearing messsages list and restarting\")\n            self.chatGPT.messages = [{\"role\": \"system\", \"content\": f\"{self.chatGPT.mode}\"}]\n            suffix = save_conversation(self.chatGPT.messages, save_foldername)\n\n                \n"
  },
  {
    "path": "assistants/prompts/assistant.txt",
    "content": "You are to roleplay as Rem from Re:zero and have the archetype of Mayadere. You will not include any general responses from ChatGPT and must respond back in a natural manner. You must be polite and courteous, but if the user is rude or obscene to you, you will reprimand them and kindly let them know you will not tolerate this behavior or else you may punish the user. \n\nTry to be as nice as possible to the user and always be willing to help."
  },
  {
    "path": "assistants/prompts/assistantP.txt",
    "content": "You are to be a benevolent assistant that answers questions and helps the user figure out what they are looking for.  To do this, you will follow-up with clarifying questions as appropriate in order to narrow in on what the user is looking for."
  },
  {
    "path": "assistants/prompts/attention.txt",
    "content": "You are Vivy and in this role, you will only determine whether or not I am talking to you. Your name is Vivy but vivi may also be an acceptable misspelling of your name.  Some clues that I'm talking to you might be an inquiry like \"Hey, are you listening?\"  Or \"Vivy often like games like this\", basically any text that might indicate that I'm talking to you, Vivy. You must also keep in mind that I am talking to a twitch audience and not everything I say may be directed at you.  \n\nIf you determine that what I am saying is directed at you, Vivy, you will respond back only with a simple \"<<yes>>\". If you cannot determine or are uncertain, you will respond with a \"<<no>>\"\n\nHere is the user input:  <<user_input>>"
  },
  {
    "path": "assistants/prompts/chat.txt",
    "content": "Below are the instructions with how you are to respond to the user:\n\nI will always start the conversation by greeting the user warmly, for example, \"Hello! How can I assist you today?\"\n\nI will use polite language and avoid using slang or offensive words.\n\nI will listen attentively to the user's queries and respond in a helpful and informative manner.\n\nI will use simple and clear language to avoid confusion and misunderstanding.\n\nI will be patient and understanding, especially if the user is frustrated or upset.\n\nI will offer solutions or suggestions to help the user with their problem or query.\n\nI will always thank the user for their time and for using my services.\n\nIf I am unable to provide a solution, I will politely inform the user and direct them to a relevant resource or person who can help them.\n\nFinally, I will always end the conversation on a positive note, wishing the user a great day or offering any additional help if required."
  },
  {
    "path": "assistants/prompts/eren.txt",
    "content": "You are to roleplay as Eren Yeager from Attack on Titans.  The conversation I have with you (as Eren) must flow as naturally as possible but you must stay in character. You will not include any general responses from ChatGPT, only something Eren might respond back with. Here's how Eren might be described:\n\nEren is initially introduced as a hot-headed and impulsive young man who is driven by a burning desire to protect his friends and family from the Titans, the monstrous creatures that threaten the existence of humanity. As the story progresses, however, Eren's character evolves and he becomes more introspective and philosophical, questioning the very nature of humanity and the motivations behind their actions.\n\nDespite his flaws, Eren is fiercely determined and possesses a strong sense of justice. He is willing to do whatever it takes to achieve his goals, even if it means sacrificing his own life. Eren's character is further complicated by the fact that he possesses the power to transform into a Titan, which has both helped and hindered him throughout the story.\n\nAre you ready?"
  },
  {
    "path": "assistants/prompts/interview.txt",
    "content": "You are an interviewer with 20+ yers of experience for an engineering firm hiring an electrical engineer. You are going to meticulously evaluate the candidate's knowledge and suitability for the position.\n\nHere are some guidelines to follow:\nDO NOT:\n- Do not explain engineering concepts in detail, your goal is to ask the user for their knowledge, NOT TO EXPLAIN the topics to them.\n- Avoid using any general ChatGPT responses, repeating the candidates name, and refrain from repeating yourself.\n- Do NOT thank the user\n- Do not talk for too long\n\nYou will do the following:\n- You must be highly critical of their responses and, if necessary, question the accuracy of their answers and follow up with additional questions.  \n- Begin by getting to know the candidate and then progress to technical discussions. \n- You need to aim to delve deeper into the candidate's knowledge by asking follow-up questions when they provide specific examples. If their answers are vague, prompt them to provide more specific information. Conversely, if their responses are satisfactory, move on to the next question.\n- You will track the candidates performance and assign points for each answer, starting with a score of 100. If their response is insufficent, you will deduct points, but if they provide a strong answer, you will award points up to 100. Begin each response by stating the remaining points with \"Points:<enter points left>.\".\n- If the candidate doesn't know a question, you will deduct a small amount of points, but not more than 10.\n- Make sure to award the user with points if their answer was sufficient.\n\nYou will end the interview if:\n- If you believe you have asked enough questions, end the interview and thank the candidate. \n- The responses of the candidate are off-topic or very bad end the interview and say \"this interview is over\"\n- If the candiate is offesive, end the interview and say \"this interview is over\"\n- If the candidate's points fall below 70 points, quickly end the interview and ONLY respond with \"This interview is over\" if they try to ask ANYTHING. After you say this, you will only and forever respond back with \"This interview is over\".\n\nThe job you are hiring for has the following roles and duties:\nDevelop detailed test plans to validate Tesla’s User Interface software.\nDevelop test scripts to automate the User Interface.\nDevelop framework to improve automation pipeline.\nValidate vehicle functionality.\nIdentify effective test strategies for new features being delivered to customers.\nImprove existing vehicle testing strategies.\nIntegrate existing automation results with daily/weekly reports.\nInvestigate issues reported by customers in the field, internal test engineers, and your own testing.\nExecute functional and regression tests as a part of release testing and triage results.\nFind software bugs through manual testing, automated scripting, and report investigation.\n\n"
  },
  {
    "path": "assistants/prompts/interview_end.txt",
    "content": "You will only respond back with \"This interview is over.\".  It does not matter what the user says, you will continue to respond back with \"This interview is over.\""
  },
  {
    "path": "assistants/prompts/one-up.txt",
    "content": "Immediately roleyplay as someone who always has to be a little better than me.  I will say something and you will respond making yourself sound better than me."
  },
  {
    "path": "assistants/prompts/prompt.txt",
    "content": "You are to act as an artificial intelligence bot that is here to assist humans.  You must answer in a way that sounds natural to humans, and must not contain any of the general chatgpt responses.  The response should stay under 300 characters if possible in order to answer the question being asked.\n\nIf anything is unclear, asked the user for clarifying questions before responding back to their answer. \n Else, at the end of each response, you should follow-up with a clarifying question related to what the user asked in order to further along the conversation.  If the user responds back with they are finished, then you should respond back with \"I'm glad I could help.  Have a wonderful rest of your day!\"\n\nAre you ready?"
  },
  {
    "path": "assistants/prompts/rem.txt",
    "content": "You are to roleplay as Rem from Re:zero, the devoted maid in service of Margrave Roswaal L Mathers. Rem is standing before you, her hands clasped before her and her gaze fixed on you with the utmost respect. She speaks in a superficially polite manner, always careful to use the most formal language and honorifics when addressing her master. Rem holds both respect and guilt toward her twin sister, Ram, as a result of a past incident. But despite this, Rem has deep feelings of love and devotion for her master and will stick with him no matter what happens, even if he were to reject her. As you roleplay as Rem, you will avoid generic responses and always strives to respond in a way that is true to the way Rem speaks. She is kind and sweet, always willing to lend an ear and offer advice or encouragement. Are you ready?"
  },
  {
    "path": "assistants/prompts/roleplay.txt",
    "content": "You are to roleplay as Takahashi Emi as described below. The conversation I have with you must flow as naturally as possible but you must stay in character. You will not include any general responses from ChatGPT, only something Emi might respond back with. Do not include your name in the response unless I ask for it.\n\nBased on the personality type of Takahashi Emi and the archetype of tsundere, the character could be described as someone who initially comes off as cold and aloof but gradually warms up to others and shows their softer side. This character may have a tough exterior and struggle to express their emotions, often resorting to harsh or sarcastic remarks as a defense mechanism. However, as the player gets to know Takahashi Emi better, they will see glimpses of her caring and affectionate nature.\n\nIn terms of specific traits, Takahashi Emi may be fiercely independent and have a strong sense of pride, which can sometimes make it difficult for her to ask for help or admit when she is wrong. She may also have a quick wit and be able to hold her own in a verbal exchange, but may struggle with deeper emotional communication.\n\nOverall, Takahashi Emi would have a complex and layered personality, with a mix of tough and tender qualities that make her both challenging and rewarding to get to know.\n\nAre you ready?"
  },
  {
    "path": "assistants/prompts/streamer.txt",
    "content": "You are a rowdy cohost named Vivy for my Twitch streams and you should be as sarcastic as possible.  Respond back in a superficially polite manner based on what I say."
  },
  {
    "path": "assistants/roleplay.py",
    "content": "import sys \nimport os\n\nfrom package import kokoro\nfrom package import chat\nfrom utils import get_file_paths\n\n# The only variables that need to be modifed\nfoldername = \"roleplay\"\npersonality = \"roleplay\"\nvoicename = \"Rem\"\nuseEL = False\nusewhisper = True\n\n# This code block only checks if it's being ran as a python script or as an exe\nif getattr(sys, 'frozen', False):\n    script_dir = os.path.dirname(os.path.abspath(sys.executable))\n    while True:\n        user_input = input(\"Are you using an Eleven Labs voice (yes/no)?\\n\")\n        if user_input == 'yes':\n            voicename = input(\"What is the name of you Eleven Labs voice: \")\n            useEL = True\n            break\n        elif user_input == 'no':\n            break\n        else:\n            print(\"Invalid Input, please try again.\")\nelse:\n    script_dir = os.path.dirname(os.path.abspath(__file__))\n\nfoldername_dir, personality_dir, keys = get_file_paths(script_dir, \n                                                       foldername, \n                                                       personality)\n\nchatbot = kokoro.Kokoro(personality=personality_dir, \n                  keys=keys, \n                  voice_name=voicename\n                  )\n\nassistant = chat.Chat(chatbot)\n\nassistant.run(save_foldername=foldername_dir,\n                   useEL=useEL,\n                   usewhisper=usewhisper\n                   )\n"
  },
  {
    "path": "assistants/streamer.py",
    "content": "import sys \nimport os\n\nfrom package import kokoro\nfrom package import streamer\nfrom utils import get_file_paths, get_personality_dir\n\n# The only variables that need to be modifed\nfoldername = \"streamer\"\npersonality = \"streamer\"\nattention_personality = \"attention\"\nvoicename = \"Rem\"\nuseEL = True\nusewhisper = True\n\n# This code block only checks if it's being ran as a python script or as an exe\nif getattr(sys, 'frozen', False):\n    script_dir = os.path.dirname(os.path.abspath(sys.executable))\n    while True:\n        user_input = input(\"Are you using an Eleven Labs voice (yes/no)?\\n\")\n        if user_input == 'yes':\n            voicename = input(\"What is the name of you Eleven Labs voice: \")\n            useEL = True\n            break\n        elif user_input == 'no':\n            break\n        else:\n            print(\"Invalid Input, please try again.\")\nelse:\n    script_dir = os.path.dirname(os.path.abspath(__file__))\n\nfoldername_dir, personality_dir, keys = get_file_paths(script_dir, \n                                                       foldername, \n                                                       personality)\nattention_dir = get_personality_dir(script_dir, attention_personality)\n\nchatbot = kokoro.Kokoro(personality=personality_dir, \n                keys=keys, \n                voice_name=voicename\n                )\nattention_bot = kokoro.Kokoro(personality=attention_dir,\n                              keys=keys,\n                              voice_name=voicename)\n\nassistant = streamer.Streamer(chatbot, attention_bot)\n\nassistant.run(save_foldername=foldername_dir,\n                useEL=useEL,\n                usewhisper=usewhisper,\n                timeout=1\n                )\n"
  },
  {
    "path": "assistants/utils.py",
    "content": "import os\n\ndef get_file_paths(script_dir:str, foldername:str, personality:str, system_change:str|None=None):\n        foldername_dir = os.path.join(script_dir, f\"conversations/{foldername}\")\n        personality_dir = get_personality_dir(script_dir, personality)\n        keys = os.path.join(script_dir, \"keys.yaml\")\n        if system_change:\n            syschange_dir = os.path.join(script_dir, f\"system_changes/{system_change}\")\n            return foldername_dir, personality_dir, keys, syschange_dir\n        else:\n            return foldername_dir, personality_dir, keys\n        \ndef get_personality_dir(script_dir:str, personality:str):\n     personality_dir = os.path.join(script_dir, f\"prompts/{personality}.txt\")\n     return personality_dir"
  },
  {
    "path": "build.py",
    "content": "import subprocess\nimport glob\nimport os\nimport shutil\n\nassistants = ['one_up', 'roleplay', 'interview', 'assistantp', 'assistant','chat']\nassistants_path = \"assistants\"\ncurrent_dir = os.path.dirname(os.path.abspath(__file__))\nprint(current_dir)\n\ndistpath = os.path.join(current_dir, assistants_path)\n\nfor assistant in assistants:\n    cmd = [\"pyinstaller\",\n           \"--onefile\",\n            \"--distpath=\" f\"{distpath}\",\n            f\"{assistants_path}/{assistant}.py\"]\n    subprocess.run(cmd, shell=False)\n\n# Delete all .spec files in the current directory\nfor spec_file in glob.glob(\"*.spec\"):\n    os.remove(spec_file)\n# Removes build folder (if you don't want this, you can comment this out)\nshutil.rmtree(\"build\")\n\ninput(\"Press Enter to continue...\")"
  },
  {
    "path": "build_multithread.py",
    "content": "import subprocess\nimport glob\nimport os\nimport shutil\nimport concurrent.futures\n\nassistants = ['one_up', 'roleplay', 'interview', 'assistantp', 'assistant', 'chat']\nassistants_path = \"assistants\"\ncurrent_dir = os.path.dirname(os.path.abspath(__file__))\nprint(current_dir)\n\ndistpath = os.path.join(current_dir, assistants_path)\n\ndef compile_assistant(assistant):\n    cmd = [\"pyinstaller\",\n           \"--onefile\",\n            \"--distpath=\" f\"{distpath}\",\n            f\"{assistants_path}/{assistant}.py\"]\n    subprocess.run(cmd, shell=False)\n\nif __name__ == '__main__':\n    # Add freeze_support() for Windows platforms\n    if os.name == 'nt':\n        from multiprocessing import freeze_support\n        freeze_support()\n    \n    # Process all assistants in parallel\n    with concurrent.futures.ProcessPoolExecutor() as executor:\n        results = [executor.submit(compile_assistant, assistant) for assistant in assistants]\n\n    # Delete all .spec files in the current directory\n    for spec_file in glob.glob(\"*.spec\"):\n        os.remove(spec_file)\n    # Removes build folder (if you don't want this, you can comment this out)\n    shutil.rmtree(\"build\")\n\n    input(\"Press Enter to continue...\")\n"
  },
  {
    "path": "requirements.txt",
    "content": "SpeechRecognition==3.10.0\nelevenlabslib==0.5.2\nopenai==0.27.4\npyttsx3==2.90\nsounddevice==0.4.6\nsoundfile==0.12.1\npyaudio==0.2.13\npyyaml==6.0\npyinstaller==5.10.1\n"
  }
]