[
  {
    "path": ".gitignore",
    "content": "# Byte-compiled / optimized / DLL files\n__pycache__/\n*.py[cod]\n*$py.class\n\n# C extensions\n*.so\n\n# Distribution / packaging\n.Python\nbuild/\ndevelop-eggs/\ndist/\ndownloads/\neggs/\n.eggs/\nlib/\nlib64/\nparts/\nsdist/\nvar/\nwheels/\npip-wheel-metadata/\nshare/python-wheels/\n*.egg-info/\n.installed.cfg\n*.egg\nMANIFEST\n\n# PyInstaller\n#  Usually these files are written by a python script from a template\n#  before PyInstaller builds the exe, so as to inject date/other infos into it.\n*.manifest\n*.spec\n\n# Installer logs\npip-log.txt\npip-delete-this-directory.txt\n\n# Unit test / coverage reports\nhtmlcov/\n.tox/\n.nox/\n.coverage\n.coverage.*\n.cache\nnosetests.xml\ncoverage.xml\n*.cover\n*.py,cover\n.hypothesis/\n.pytest_cache/\n\n# Translations\n*.mo\n*.pot\n\n# Django stuff:\n*.log\nlocal_settings.py\ndb.sqlite3\ndb.sqlite3-journal\n\n# Flask stuff:\ninstance/\n.webassets-cache\n\n# Scrapy stuff:\n.scrapy\n\n# Sphinx documentation\ndocs/_build/\n\n# PyBuilder\ntarget/\n\n# Jupyter Notebook\n.ipynb_checkpoints\n\n# IPython\nprofile_default/\nipython_config.py\n\n# pyenv\n.python-version\n\n# pipenv\n#   According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.\n#   However, in case of collaboration, if having platform-specific dependencies or dependencies\n#   having no cross-platform support, pipenv may install dependencies that don't work, or not\n#   install all needed dependencies.\n#Pipfile.lock\n\n# PEP 582; used by e.g. github.com/David-OConnor/pyflow\n__pypackages__/\n\n# Celery stuff\ncelerybeat-schedule\ncelerybeat.pid\n\n# SageMath parsed files\n*.sage.py\n\n# Environments\n.env\n.venv\nenv/\nvenv/\nENV/\nenv.bak/\nvenv.bak/\n\n# Spyder project settings\n.spyderproject\n.spyproject\n\n# Rope project settings\n.ropeproject\n\n# mkdocs documentation\n/site\n\n# mypy\n.mypy_cache/\n.dmypy.json\ndmypy.json\n\n# Pyre type checker\n.pyre/\n"
  },
  {
    "path": "BUILD.md",
    "content": "Build package and publish to pypi:\n```bash\nrm -rf dist/*\npython3 -m build\npython3 -m twine upload  dist/*\n```\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2023 Yunfeng Wang\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# talkGPT4All\nA voice chatbot based on GPT4All and talkGPT.\n\n[Video demo](https://www.zhihu.com/zvideo/1625779747656515584).\n\nPlease check more details in this [blog post (in Chinese)](https://zhuanlan.zhihu.com/p/632592897).\n\nIf you are looking for the older version of talkGPT4All, please checkout to [dev/v1.0.0](https://github.com/vra/talkGPT4All/tree/dev/v1.0.0) branch.\n\n## Installation\n\n### Install using pip (Recommend)\ntalkgpt4all is on PyPI, you can install it using simple one command:\n```bash\npip install talkgpt4all\n```\n### Install from source code\nClone the code:\n```bash\ngit clone https://github.com/vra/talkGPT4All.git <ROOT>\n```\n\nInstall the dependencies and talkGPT4All in a python virtual environment:\n```bash\ncd <ROOT>\npython -m venv talkgpt4all\nsource talkgpt4all/bin/activate\npip install -U pip\npip install -r requirements.txt\n```\n\n## Extra dependencies for Linux users\nWe use [pyttsx3](https://github.com/nateshmbhat/pyttsx3) to convert text to voice. Please note that on Linux ，You need to install dependencies:\n```bash\nsudo apt update && sudo apt install -y espeak ffmpeg libespeak1\n```\n\n## Usage\nOpen a terminal and type `talkgpt4all` to begin:\n```bash\ntalkgpt4all\n```\n\n### Use different LLMs\nYou can choose different LLMs  using `--gpt-model-type <type>`, all available choices:\n```python\n{\n\"ggml-gpt4all-j-v1.3-groovy\"\n\"ggml-gpt4all-j-v1.2-jazzy\"\n\"ggml-gpt4all-j-v1.1-breezy\"\n\"ggml-gpt4all-j\"\n\"ggml-gpt4all-l13b-snoozy\"\n\"ggml-vicuna-7b-1.1-q4_2\"\n\"ggml-vicuna-13b-1.1-q4_2\"\n\"ggml-wizardLM-7B.q4_2\"\n}\n```\n\n### Use different Whisper models\nYou can choose whisper model type using `--whisper-model-type <type>`, all available choices:\n```python\n{\n\"tiny.en\"\n\"tiny\"\n\"base.en\"\n\"base\"\n\"small.en\"\n\"small\"\n\"medium.en\"\n\"medium\"\n\"large-v1\"\n\"large-v2\"\n\"large\"\n}\n```\n\n### Tune voice rate\nYou can tune the voice rate using `--voice-rate <rate>`, default rate is 165. the larger the speak faster.\n\ne.g.,\n```bash\ntalkgpt4all --whisper-model-type large --voice-rate 150\n```\n\n## RoadMap\n+ [x] Add source building for llama.cpp, with more flexible interface.\n+ [x] More LLMs\n+ [x] Add support for contextual information during chating.\n+ [ ] Test code on Linux，Mac Intel and WSL2.\n+ [ ] Add support for Chinese input and output.\n+ [ ] Add Documents and Changelog\n\ncontributions are welcomed!\n"
  },
  {
    "path": "pyproject.toml",
    "content": "[build-system]\nrequires = [\"hatchling\"]\nbuild-backend = \"hatchling.build\"\n\n[project]\nname = \"talkgpt4all\"\nversion = \"2.1.1\"\nauthors = [\n  { name=\"Yunfeng Wang\", email=\"wyf.brz@gmail.com\" },\n]\ndescription = \"A voice chatbot based on GPT4All and OpenAI Whisper, running on your PC locally\"\nreadme = \"README.md\"\nrequires-python = \">=3.7\"\nclassifiers = [\n    \"Programming Language :: Python :: 3\",\n    \"License :: OSI Approved :: MIT License\",\n    \"Operating System :: OS Independent\",\n]\ndependencies = [\n\"gpt4all\",\n\"openai-whisper\",\n\"playsound\",\n\"SpeechRecognition\",\n\"TTS\",\n]\n\n[project.scripts]\ntalkgpt4all = \"talkgpt4all.__init__:main\"\n\n[project.urls]\n\"Homepage\" = \"https://github.com/vra/talkGPT4All\"\n\"Bug Tracker\" = \"https://github.com/vra/talkGPT4All/issues\"\n"
  },
  {
    "path": "requirements.txt",
    "content": "gpt4all\nopenai-whisper\nplaysound\nSpeechRecognition\nTTS\n"
  },
  {
    "path": "src/talkgpt4all/__init__.py",
    "content": "import argparse\n\nfrom .chat import GPT4AllChatBot\n\n\ndef main():\n    parser = argparse.ArgumentParser()\n    parser.add_argument(\n        \"--gpt-model-name\",\n        type=str,\n        default=\"ggml-gpt4all-j-v1.3-groovy\",\n        help=\"\"\"GPT4All model name, All available names:\n            [\n            ggml-gpt4all-j-v1.3-groovy\n            ggml-gpt4all-j-v1.2-jazzy\n            ggml-gpt4all-j-v1.1-breezy\n            ggml-gpt4all-j\n            ggml-gpt4all-l13b-snoozy\n            ggml-vicuna-7b-1.1-q4_2\n            ggml-vicuna-13b-1.1-q4_2\n            ggml-wizardLM-7B.q4_2\n            ggml-stable-vicuna-13B.q4_2\n            ]\n            \"\"\",\n    )\n    parser.add_argument(\n        \"--whisper-model-type\",\n        type=str,\n        default=\"base\",\n        help=\"whisper model type, default is base\",\n    )\n    parser.add_argument(\n        \"--voice-rate\",\n        type=int,\n        default=165,\n        help=\"voice rate, default is 165, the larger the speak faster\",\n    )\n    args = parser.parse_args()\n\n    chat_bot = GPT4AllChatBot(\n        args.gpt_model_name, args.whisper_model_type, args.voice_rate\n    )\n    while True:\n        chat_bot.run()\n"
  },
  {
    "path": "src/talkgpt4all/chat.py",
    "content": "import argparse\nimport os\nimport subprocess\nimport tempfile\n\nfrom gpt4all import GPT4All\nfrom playsound import playsound\nimport speech_recognition as sr\nfrom TTS.api import TTS\n\n\nclass GlowTTS:\n    def __init__(self):\n        self.tts = TTS(model_name=\"tts_models/en/ljspeech/glow-tts\", progress_bar=False)\n\n    def process(self, text, audio_save_path):\n        return self.tts.tts_to_file(text=text, file_path=audio_save_path)\n\n\nclass GPT4AllChatBot:\n    \"\"\"Voice chat bot based on Whisper and GPT4All\"\"\"\n\n    def __init__(self, gpt_model_name, whisper_model_type, tts_rate=165):\n        print(f\"==> GPT4All model: {gpt_model_name}, Whisper model: {whisper_model_type}\")\n        self.gpt_model = GPT4All(gpt_model_name, allow_download=True)\n\n        self.whisper_model_type = whisper_model_type\n\n        self.voice_recognizer = sr.Recognizer()\n        self.mic = sr.Microphone()\n\n        self.tts_engine = GlowTTS()\n\n    def run(self):\n        \"\"\"Run the listen-think-response loop\"\"\"\n        input_words = self._voice_to_text()\n        answer = self.run_gpt(input_words)\n        self._text_to_voice(answer)\n\n    def _voice_to_text(self):\n        \"\"\"Listen voice and convert voice to text using OpenAI Whisper\"\"\"\n        print(\"Listening...\")\n        with self.mic as source:\n            self.voice_recognizer.adjust_for_ambient_noise(source)\n            audio = self.voice_recognizer.listen(source)\n            transcript = self.voice_recognizer.recognize_whisper(\n                audio, self.whisper_model_type\n            )\n            return transcript\n\n    def run_gpt(self, question):\n        \"\"\"Run GPT4All model with input_data as input\"\"\"\n\n        with self.gpt_model.chat_session():\n            answer = self.gpt_model.generate(prompt=question)\n        print(\"==> answer:\", answer)\n        return answer\n\n    def _text_to_voice(self, answer):\n        \"\"\"Convert text to voice using TTS tools\"\"\"\n        tmp_file = tempfile.NamedTemporaryFile(\n            prefix=\"talkgpt4all-\", suffix=\".wav\", delete=False\n        )\n        tmp_dir = os.path.dirname(tmp_file.name)\n        try:\n            try:\n                audio = self.tts_engine.process(answer, tmp_file.name)\n            except RuntimeError:\n                print(\n                    \"Errors occur when converting anwser to audio. please try another question.\"\n                )\n                return\n\n            playsound(tmp_file.name)\n        finally:\n            tmp_file.close()\n            os.remove(tmp_file.name)\n\n\nif __name__ == \"__main__\":\n    parser = argparse.ArgumentParser()\n    parser.add_argument(\n        \"-m\",\n        \"--gpt-model-name\",\n        type=str,\n        default=\"mistral-7b-openorca.Q4_0.gguf\",\n        help=\"\"\"GPT4All model name, All available names:\n            [\n            mistral-7b-openorca.Q4_0.gguf\n            mistral-7b-instruct-v0.1.Q4_0.gguf\n            gpt4all-falcon-q4_0.gguf\n            orca-2-7b.Q4_0.gguf\n            orca-2-13b.Q4_0.gguf\n            wizardlm-13b-v1.2.Q4_0.gguf\n            nous-hermes-llama2-13b.Q4_0.gguf\n            gpt4all-13b-snoozy-q4_0.gguf\n            mpt-7b-chat-merges-q4_0.gguf\n            orca-mini-3b-gguf2-q4_0.gguf\n            replit-code-v1_5-3b-q4_0.gguf\n            starcoder-q4_0.gguf\n            rift-coder-v0-7b-q4_0.gguf\n            all-MiniLM-L6-v2-f16.gguf\n            em_german_mistral_v01.Q4_0.gguf\n            ]\n            \"\"\",\n    )\n    parser.add_argument(\n        \"-w\",\n        \"--whisper-model-type\",\n        type=str,\n        default=\"base\",\n        help=\"whisper model type, default is base\",\n    )\n    parser.add_argument(\n        \"--voice-rate\",\n        type=int,\n        default=165,\n        help=\"voice rate, default is 165, the larger the speak faster\",\n    )\n    args = parser.parse_args()\n\n    chat_bot = GPT4AllChatBot(\n        args.gpt_model_name, args.whisper_model_type, args.voice_rate\n    )\n    while True:\n        chat_bot.run()\n"
  },
  {
    "path": "tests/example_test.py",
    "content": ""
  }
]