├── .gitignore ├── LICENSE ├── Pipfile ├── Pipfile.lock ├── README.md ├── screenshot00.png └── smart_one ├── __init__.py ├── __main__.py ├── app.py ├── core ├── __init__.py ├── ai.py ├── gui.py ├── recognizer.py └── voice.py ├── data ├── books.txt └── memory.txt ├── resources ├── button_active.png ├── button_hover.png ├── button_normal.png └── circle.png └── utils ├── __init__.py ├── memory.py ├── openai_helper.py └── settings.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | 80 | # IPython 81 | profile_default/ 82 | ipython_config.py 83 | 84 | # pyenv 85 | .python-version 86 | 87 | # pipenv 88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 91 | # install all needed dependencies. 92 | #Pipfile.lock 93 | 94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 95 | __pypackages__/ 96 | 97 | # Celery stuff 98 | celerybeat-schedule 99 | celerybeat.pid 100 | 101 | # SageMath parsed files 102 | *.sage.py 103 | 104 | # Environments 105 | .env 106 | .venv 107 | env/ 108 | venv/ 109 | ENV/ 110 | env.bak/ 111 | venv.bak/ 112 | 113 | # Spyder project settings 114 | .spyderproject 115 | .spyproject 116 | 117 | # Rope project settings 118 | .ropeproject 119 | 120 | # mkdocs documentation 121 | /site 122 | 123 | # mypy 124 | .mypy_cache/ 125 | .dmypy.json 126 | dmypy.json 127 | 128 | # Pyre type checker 129 | .pyre/ -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Hein Thant 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /Pipfile: -------------------------------------------------------------------------------- 1 | [[source]] 2 | url = "https://pypi.org/simple" 3 | verify_ssl = true 4 | name = "pypi" 5 | 6 | [packages] 7 | pysimplegui = "*" 8 | openai = "*" 9 | speechrecognition = "*" 10 | pyttsx3 = "*" 11 | pyaudio = "*" 12 | 13 | [dev-packages] 14 | 15 | [requires] 16 | python_version = "3.10" 17 | -------------------------------------------------------------------------------- /Pipfile.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_meta": { 3 | "hash": { 4 | "sha256": "113f083ad5ccf4c90c6ab0a95402e2f2b001fb8121783d2a5cac17213cb1feca" 5 | }, 6 | "pipfile-spec": 6, 7 | "requires": { 8 | "python_version": "3.10" 9 | }, 10 | "sources": [ 11 | { 12 | "name": "pypi", 13 | "url": "https://pypi.org/simple", 14 | "verify_ssl": true 15 | } 16 | ] 17 | }, 18 | "default": { 19 | "certifi": { 20 | "hashes": [ 21 | "sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3", 22 | "sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18" 23 | ], 24 | "markers": "python_version >= '3.6'", 25 | "version": "==2022.12.7" 26 | }, 27 | "charset-normalizer": { 28 | "hashes": [ 29 | "sha256:5a3d016c7c547f69d6f81fb0db9449ce888b418b5b9952cc5e6e66843e9dd845", 30 | "sha256:83e9a75d1911279afd89352c68b45348559d1fc0506b054b346651b5e7fee29f" 31 | ], 32 | "markers": "python_version >= '3.6'", 33 | "version": "==2.1.1" 34 | }, 35 | "colorama": { 36 | "hashes": [ 37 | "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", 38 | "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6" 39 | ], 40 | "markers": "platform_system == 'Windows'", 41 | "version": "==0.4.6" 42 | }, 43 | "comtypes": { 44 | "hashes": [ 45 | "sha256:5d7caf6d3a86d51ddfc53e4548cae2dceee1b46672f8bd59679711dd01a934f2", 46 | "sha256:7cdbe2dc65fe105eea97be04dc50ee3178747bcb64d802d7c0832416d75a87bd" 47 | ], 48 | "markers": "platform_system == 'Windows'", 49 | "version": "==1.1.14" 50 | }, 51 | "et-xmlfile": { 52 | "hashes": [ 53 | "sha256:8eb9e2bc2f8c97e37a2dc85a09ecdcdec9d8a396530a6d5a33b30b9a92da0c5c", 54 | "sha256:a2ba85d1d6a74ef63837eed693bcb89c3f752169b0e3e7ae5b16ca5e1b3deada" 55 | ], 56 | "markers": "python_version >= '3.6'", 57 | "version": "==1.1.0" 58 | }, 59 | "idna": { 60 | "hashes": [ 61 | "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4", 62 | "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2" 63 | ], 64 | "markers": "python_version >= '3.5'", 65 | "version": "==3.4" 66 | }, 67 | "numpy": { 68 | "hashes": [ 69 | "sha256:01dd17cbb340bf0fc23981e52e1d18a9d4050792e8fb8363cecbf066a84b827d", 70 | "sha256:06005a2ef6014e9956c09ba07654f9837d9e26696a0470e42beedadb78c11b07", 71 | "sha256:09b7847f7e83ca37c6e627682f145856de331049013853f344f37b0c9690e3df", 72 | "sha256:0aaee12d8883552fadfc41e96b4c82ee7d794949e2a7c3b3a7201e968c7ecab9", 73 | "sha256:0cbe9848fad08baf71de1a39e12d1b6310f1d5b2d0ea4de051058e6e1076852d", 74 | "sha256:1b1766d6f397c18153d40015ddfc79ddb715cabadc04d2d228d4e5a8bc4ded1a", 75 | "sha256:33161613d2269025873025b33e879825ec7b1d831317e68f4f2f0f84ed14c719", 76 | "sha256:5039f55555e1eab31124a5768898c9e22c25a65c1e0037f4d7c495a45778c9f2", 77 | "sha256:522e26bbf6377e4d76403826ed689c295b0b238f46c28a7251ab94716da0b280", 78 | "sha256:56e454c7833e94ec9769fa0f86e6ff8e42ee38ce0ce1fa4cbb747ea7e06d56aa", 79 | "sha256:58f545efd1108e647604a1b5aa809591ccd2540f468a880bedb97247e72db387", 80 | "sha256:5e05b1c973a9f858c74367553e236f287e749465f773328c8ef31abe18f691e1", 81 | "sha256:7903ba8ab592b82014713c491f6c5d3a1cde5b4a3bf116404e08f5b52f6daf43", 82 | "sha256:8969bfd28e85c81f3f94eb4a66bc2cf1dbdc5c18efc320af34bffc54d6b1e38f", 83 | "sha256:92c8c1e89a1f5028a4c6d9e3ccbe311b6ba53694811269b992c0b224269e2398", 84 | "sha256:9c88793f78fca17da0145455f0d7826bcb9f37da4764af27ac945488116efe63", 85 | "sha256:a7ac231a08bb37f852849bbb387a20a57574a97cfc7b6cabb488a4fc8be176de", 86 | "sha256:abdde9f795cf292fb9651ed48185503a2ff29be87770c3b8e2a14b0cd7aa16f8", 87 | "sha256:af1da88f6bc3d2338ebbf0e22fe487821ea4d8e89053e25fa59d1d79786e7481", 88 | "sha256:b2a9ab7c279c91974f756c84c365a669a887efa287365a8e2c418f8b3ba73fb0", 89 | "sha256:bf837dc63ba5c06dc8797c398db1e223a466c7ece27a1f7b5232ba3466aafe3d", 90 | "sha256:ca51fcfcc5f9354c45f400059e88bc09215fb71a48d3768fb80e357f3b457e1e", 91 | "sha256:ce571367b6dfe60af04e04a1834ca2dc5f46004ac1cc756fb95319f64c095a96", 92 | "sha256:d208a0f8729f3fb790ed18a003f3a57895b989b40ea4dce4717e9cf4af62c6bb", 93 | "sha256:dbee87b469018961d1ad79b1a5d50c0ae850000b639bcb1b694e9981083243b6", 94 | "sha256:e9f4c4e51567b616be64e05d517c79a8a22f3606499941d97bb76f2ca59f982d", 95 | "sha256:f063b69b090c9d918f9df0a12116029e274daf0181df392839661c4c7ec9018a", 96 | "sha256:f9a909a8bae284d46bbfdefbdd4a262ba19d3bc9921b1e76126b1d21c3c34135" 97 | ], 98 | "markers": "python_version >= '3.8'", 99 | "version": "==1.23.5" 100 | }, 101 | "openai": { 102 | "hashes": [ 103 | "sha256:59ac6531e4f7bf8e9a53186e853d9ffb1d5f07973ecb4f7d273163a314814510" 104 | ], 105 | "index": "pypi", 106 | "version": "==0.25.0" 107 | }, 108 | "openpyxl": { 109 | "hashes": [ 110 | "sha256:0ab6d25d01799f97a9464630abacbb34aafecdcaa0ef3cba6d6b3499867d0355", 111 | "sha256:e47805627aebcf860edb4edf7987b1309c1b3632f3750538ed962bbcc3bd7449" 112 | ], 113 | "markers": "python_version >= '3.6'", 114 | "version": "==3.0.10" 115 | }, 116 | "pandas": { 117 | "hashes": [ 118 | "sha256:0183cb04a057cc38fde5244909fca9826d5d57c4a5b7390c0cc3fa7acd9fa883", 119 | "sha256:1fc87eac0541a7d24648a001d553406f4256e744d92df1df8ebe41829a915028", 120 | "sha256:220b98d15cee0b2cd839a6358bd1f273d0356bf964c1a1aeb32d47db0215488b", 121 | "sha256:2552bffc808641c6eb471e55aa6899fa002ac94e4eebfa9ec058649122db5824", 122 | "sha256:315e19a3e5c2ab47a67467fc0362cb36c7c60a93b6457f675d7d9615edad2ebe", 123 | "sha256:344021ed3e639e017b452aa8f5f6bf38a8806f5852e217a7594417fb9bbfa00e", 124 | "sha256:375262829c8c700c3e7cbb336810b94367b9c4889818bbd910d0ecb4e45dc261", 125 | "sha256:457d8c3d42314ff47cc2d6c54f8fc0d23954b47977b2caed09cd9635cb75388b", 126 | "sha256:4aed257c7484d01c9a194d9a94758b37d3d751849c05a0050c087a358c41ad1f", 127 | "sha256:530948945e7b6c95e6fa7aa4be2be25764af53fba93fe76d912e35d1c9ee46f5", 128 | "sha256:5ae7e989f12628f41e804847a8cc2943d362440132919a69429d4dea1f164da0", 129 | "sha256:71f510b0efe1629bf2f7c0eadb1ff0b9cf611e87b73cd017e6b7d6adb40e2b3a", 130 | "sha256:73f219fdc1777cf3c45fde7f0708732ec6950dfc598afc50588d0d285fddaefc", 131 | "sha256:8092a368d3eb7116e270525329a3e5c15ae796ccdf7ccb17839a73b4f5084a39", 132 | "sha256:82ae615826da838a8e5d4d630eb70c993ab8636f0eff13cb28aafc4291b632b5", 133 | "sha256:9608000a5a45f663be6af5c70c3cbe634fa19243e720eb380c0d378666bc7702", 134 | "sha256:a40dd1e9f22e01e66ed534d6a965eb99546b41d4d52dbdb66565608fde48203f", 135 | "sha256:b4f5a82afa4f1ff482ab8ded2ae8a453a2cdfde2001567b3ca24a4c5c5ca0db3", 136 | "sha256:c009a92e81ce836212ce7aa98b219db7961a8b95999b97af566b8dc8c33e9519", 137 | "sha256:c218796d59d5abd8780170c937b812c9637e84c32f8271bbf9845970f8c1351f", 138 | "sha256:cc3cd122bea268998b79adebbb8343b735a5511ec14efb70a39e7acbc11ccbdc", 139 | "sha256:d0d8fd58df5d17ddb8c72a5075d87cd80d71b542571b5f78178fb067fa4e9c72", 140 | "sha256:e18bc3764cbb5e118be139b3b611bc3fbc5d3be42a7e827d1096f46087b395eb", 141 | "sha256:e2b83abd292194f350bb04e188f9379d36b8dfac24dd445d5c87575f3beaf789", 142 | "sha256:e7469271497960b6a781eaa930cba8af400dd59b62ec9ca2f4d31a19f2f91090", 143 | "sha256:e9dbacd22555c2d47f262ef96bb4e30880e5956169741400af8b306bbb24a273", 144 | "sha256:f6257b314fc14958f8122779e5a1557517b0f8e500cfb2bd53fa1f75a8ad0af2" 145 | ], 146 | "markers": "python_version >= '3.8'", 147 | "version": "==1.5.2" 148 | }, 149 | "pandas-stubs": { 150 | "hashes": [ 151 | "sha256:0cbc1dbdf5dddb4d67ebc851b9cfb265bf62fe317b043bd37ee5a4a2659421f2", 152 | "sha256:3551177a44eec5945b4e47131b6a545a564b3d41dfd4e50e06ba1a736e7d695d" 153 | ], 154 | "markers": "python_version < '3.12' and python_version >= '3.8'", 155 | "version": "==1.5.2.221213" 156 | }, 157 | "pyaudio": { 158 | "hashes": [ 159 | "sha256:0f9debc6e47b6a5a4fe9da9d213d4bfe5e8096e68f0612f1b9097e3253eeea4d", 160 | "sha256:19f654bd516154a655d9569d12d2a86ab5dfd58d039c0e4c6d1a26ec4ca02d89", 161 | "sha256:1c29930cf2e392d8b21a4c6253efe39d7400e37d61a7991756d3b00a46bf18ce", 162 | "sha256:2f4206c6a8d2eeb2d1f054c69e3741c8634cfafe7887be4950a2f7d273700f8a", 163 | "sha256:55ddf5db72bc537bba5f5dbca3ab9f0222ee5b842bda83978eab0b7b8f60fb9e", 164 | "sha256:5678725eb828742ea3febf381b1bd0bb94ba76c35e5e0daeab84e4c50f9f5d47", 165 | "sha256:71fc1688732fced907ae707d609cc3eead9fa05baf703bf08885f71a8fd9c658", 166 | "sha256:880aff391a73ff5e94bae73e32d3b8e27e988a93afec2dd9c74dcd92c305f8cc", 167 | "sha256:d89f065adc0058df90ec59aa6b35c1c036f17bb4323fb68b4267c12924e9553e", 168 | "sha256:dafe891903402694a0fc87663bdb9b89e7fa66872446c5ef0c9d71ac4780cf1d", 169 | "sha256:ffa235c220992e417e5a462f6d73ffb1be54b683005a1c6b185139580f59e234" 170 | ], 171 | "index": "pypi", 172 | "version": "==0.2.12" 173 | }, 174 | "pypiwin32": { 175 | "hashes": [ 176 | "sha256:67adf399debc1d5d14dffc1ab5acacb800da569754fafdc576b2a039485aa775", 177 | "sha256:71be40c1fbd28594214ecaecb58e7aa8b708eabfa0125c8a109ebd51edbd776a" 178 | ], 179 | "markers": "platform_system == 'Windows'", 180 | "version": "==223" 181 | }, 182 | "pysimplegui": { 183 | "hashes": [ 184 | "sha256:e133fbd21779f0f125cebbc2a4e1f5a931a383738661013ff33ad525d5611eda", 185 | "sha256:f88c82c301a51aea35be605dc060bcceb0dcb6682e16280544884701ab4b23ba" 186 | ], 187 | "index": "pypi", 188 | "version": "==4.60.4" 189 | }, 190 | "python-dateutil": { 191 | "hashes": [ 192 | "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86", 193 | "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9" 194 | ], 195 | "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", 196 | "version": "==2.8.2" 197 | }, 198 | "pyttsx3": { 199 | "hashes": [ 200 | "sha256:a585b6d8cffc19bd92db1e0ccbd8aa9c6528dd2baa5a47045d6fed542a44aa19" 201 | ], 202 | "index": "pypi", 203 | "version": "==2.90" 204 | }, 205 | "pytz": { 206 | "hashes": [ 207 | "sha256:222439474e9c98fced559f1709d89e6c9cbf8d79c794ff3eb9f8800064291427", 208 | "sha256:e89512406b793ca39f5971bc999cc538ce125c0e51c27941bef4568b460095e2" 209 | ], 210 | "version": "==2022.6" 211 | }, 212 | "pywin32": { 213 | "hashes": [ 214 | "sha256:109f98980bfb27e78f4df8a51a8198e10b0f347257d1e265bb1a32993d0c973d", 215 | "sha256:13362cc5aa93c2beaf489c9c9017c793722aeb56d3e5166dadd5ef82da021fe1", 216 | "sha256:19ca459cd2e66c0e2cc9a09d589f71d827f26d47fe4a9d09175f6aa0256b51c2", 217 | "sha256:326f42ab4cfff56e77e3e595aeaf6c216712bbdd91e464d167c6434b28d65990", 218 | "sha256:421f6cd86e84bbb696d54563c48014b12a23ef95a14e0bdba526be756d89f116", 219 | "sha256:48d8b1659284f3c17b68587af047d110d8c44837736b8932c034091683e05863", 220 | "sha256:4ecd404b2c6eceaca52f8b2e3e91b2187850a1ad3f8b746d0796a98b4cea04db", 221 | "sha256:50768c6b7c3f0b38b7fb14dd4104da93ebced5f1a50dc0e834594bff6fbe1271", 222 | "sha256:56d7a9c6e1a6835f521788f53b5af7912090674bb84ef5611663ee1595860fc7", 223 | "sha256:73e819c6bed89f44ff1d690498c0a811948f73777e5f97c494c152b850fad478", 224 | "sha256:742eb905ce2187133a29365b428e6c3b9001d79accdc30aa8969afba1d8470f4", 225 | "sha256:9d968c677ac4d5cbdaa62fd3014ab241718e619d8e36ef8e11fb930515a1e918", 226 | "sha256:9dd98384da775afa009bc04863426cb30596fd78c6f8e4e2e5bbf4edf8029504", 227 | "sha256:a55db448124d1c1484df22fa8bbcbc45c64da5e6eae74ab095b9ea62e6d00496" 228 | ], 229 | "markers": "platform_system == 'Windows'", 230 | "version": "==305" 231 | }, 232 | "requests": { 233 | "hashes": [ 234 | "sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983", 235 | "sha256:8fefa2a1a1365bf5520aac41836fbee479da67864514bdb821f31ce07ce65349" 236 | ], 237 | "markers": "python_version >= '3.7' and python_version < '4'", 238 | "version": "==2.28.1" 239 | }, 240 | "six": { 241 | "hashes": [ 242 | "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926", 243 | "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254" 244 | ], 245 | "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", 246 | "version": "==1.16.0" 247 | }, 248 | "speechrecognition": { 249 | "hashes": [ 250 | "sha256:6da44facb564b3f2bcee96a2bf876b89a14f61afdee1e7fb12815e58211fd329", 251 | "sha256:a2f992acda6314a3fa574bf84c2e075ce75f2b4c143b4435d7cbc98f66565ee7" 252 | ], 253 | "index": "pypi", 254 | "version": "==3.9.0" 255 | }, 256 | "tqdm": { 257 | "hashes": [ 258 | "sha256:5f4f682a004951c1b450bc753c710e9280c5746ce6ffedee253ddbcbf54cf1e4", 259 | "sha256:6fee160d6ffcd1b1c68c65f14c829c22832bc401726335ce92c52d395944a6a1" 260 | ], 261 | "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", 262 | "version": "==4.64.1" 263 | }, 264 | "types-pytz": { 265 | "hashes": [ 266 | "sha256:bea605ce5d5a5d52a8e1afd7656c9b42476e18a0f888de6be91587355313ddf4", 267 | "sha256:d078196374d1277e9f9984d49373ea043cf2c64d5d5c491fbc86c258557bd46f" 268 | ], 269 | "version": "==2022.6.0.1" 270 | }, 271 | "typing-extensions": { 272 | "hashes": [ 273 | "sha256:1511434bb92bf8dd198c12b1cc812e800d4181cfcb867674e0f8279cc93087aa", 274 | "sha256:16fa4864408f655d35ec496218b85f79b3437c829e93320c7c9215ccfd92489e" 275 | ], 276 | "markers": "python_version >= '3.7'", 277 | "version": "==4.4.0" 278 | }, 279 | "urllib3": { 280 | "hashes": [ 281 | "sha256:47cc05d99aaa09c9e72ed5809b60e7ba354e64b59c9c173ac3018642d8bb41fc", 282 | "sha256:c083dd0dce68dbfbe1129d5271cb90f9447dea7d52097c6e0126120c521ddea8" 283 | ], 284 | "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", 285 | "version": "==1.26.13" 286 | } 287 | }, 288 | "develop": {} 289 | } 290 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![CodeFactor](https://www.codefactor.io/repository/github/indiecodermm/smart-one-ai/badge)](https://www.codefactor.io/repository/github/indiecodermm/smart-one-ai) 2 | [![Maintainability](https://api.codeclimate.com/v1/badges/5d39b9280da5ddcf406e/maintainability)](https://codeclimate.com/github/IndieCoderMM/smart-one-ai/maintainability) 3 | ![LastUpdate](https://img.shields.io/github/last-commit/IndieCoderMM/smart-one-ai) 4 | [![Forks](https://img.shields.io/github/forks/IndieCoderMM/smart-one-ai)](https://github.com/IndieCoderMM/smart-one-ai/network/members) 5 | ![Stars](https://img.shields.io/github/stars/IndieCoderMM/smart-one-ai) 6 | [![License](https://img.shields.io/github/license/IndieCoderMM/smart-one-ai.svg)](https://github.com/IndieCoderMM/smart-one-ai/blob/master/LICENSE) 7 | 8 | ## Table of Contents 9 | 10 | - [😎 Smart One - A.I. Assistant](#-smart-one---ai-assistant) 11 | - [🔥 Features](#-features) 12 | - [⚙ Requirements](#-requirements) 13 | - [📦 Libraries](#-libraries) 14 | - [📥 Installation](#-installation) 15 | - [📧 Contact](#-contact) 16 | - [🤝 Contributing](#-contributing) 17 | - [💖 Show your support](#-show-your-support) 18 | - [🎯 Roadmap](#-roadmap) 19 | - [💡 Inspiration](#-inspiration) 20 | - [📜 License](#-license) 21 | 22 | # 😎 Smart One - A.I. Assistant 23 | 24 | **Smart One** is an A.I. assistant program that can listen to a user's input and provide an appropriate response. It uses [OpenAI API](https://beta.openai.com/docs/api-reference?lang=python) to understand and interpret user's request and generate a response in real-time. 25 | 26 | ![Screenshot](screenshot00.png) 27 | 28 | ## 🔥 Features 29 | 30 | - Speech recognition: Listen to the user's input through a microphone and transcribe into text 31 | - Natural language processing: Able to understand the meaning and context of user's input 32 | - Quick and accurate response: Efficient and seamless communication 33 | - Contextual understanding: Remember previous interactions and give more relevant responses 34 | - Knowledge base: Provide information on a wide range of topics 35 | - Audio output: Provide responses in audio form 36 | - User-friendly GUI: Simple and intuitive interface 37 | 38 | ## ⚙ Requirements 39 | 40 | - [Python](https://www.python.org/): 3.9 or higher 41 | - [Pipenv](https://docs.pipenv.org/): Python packaging tool 42 | 43 | ## 📦 Libraries 44 | 45 | - [OpenAI Python](https://github.com/openai/openai-python) 46 | - [PySimpleGUI](https://pypi.org/project/PySimpleGUI/) 47 | - [Speech Recognition](https://pypi.org/project/SpeechRecognition/) 48 | - [Pyttsx3](https://pypi.org/project/pyttsx3/) 49 | 50 | ## 📥 Installation 51 | 52 | To install the program, follow these steps: 53 | 54 | 1. Clone this repo to the desired folder. 55 | ```sh 56 | git clone git@github.com:IndieCoderMM/smart-one-ai.git 57 | ``` 58 | 2. Enter the project directory. 59 | ```sh 60 | cd smart-one-ai 61 | ``` 62 | 3. Install the libraries. 63 | ```sh 64 | pipenv install 65 | ``` 66 | 4. Get secret key from [OpenAI API](https://beta.openai.com/account/api-keys) and add the key in `smart_one/utils/openai_helper.py`. 67 | 5. Activate pipenv and run the program. 68 | ```sh 69 | pipenv shell 70 | python -m smart_one 71 | ``` 72 | 73 | _You can customize the profile (name, voice, etc) in `smart_one/utils/settings.py`_ 74 | 75 | ## 📧 Contact 76 | 77 | I am always looking for ways to improve my project. If you have any suggestions or ideas, I would love to hear from you. 78 | 79 | [![Github](https://img.shields.io/badge/GitHub-673AB7?style=for-the-badge&logo=github&logoColor=white)](https://github.com/IndieCoderMM) 80 | [![Twitter](https://img.shields.io/badge/Twitter-1DA1F2?style=for-the-badge&logo=twitter&logoColor=white)](https://twitter.com/hthant_oo) 81 | [![Linkedin](https://img.shields.io/badge/LinkedIn-0077B5?style=for-the-badge&logo=linkedin&logoColor=white)](https://linkedin.com/in/hthantoo) 82 | [![Gmail](https://img.shields.io/badge/Gmail-D14836?style=for-the-badge&logo=gmail&logoColor=white)](hthant00chk@gmail.com) 83 | 84 | 85 | 86 | ## 🤝 Contributing 87 | 88 | I welcome any and all contribution that can help me improve my project. If you have any ideas or feedback that you'd like to share, please don't hesitate to reach out. 89 | 90 | 91 | 92 | ## 💖 Show your support 93 | 94 | If you like this project, you can support me by giving a ⭐. 95 | 96 | ## 🎯 Roadmap 97 | 98 | - [x] Save current conversation 99 | - [ ] Os-related tasks 100 | - [ ] Code translation 101 | 102 | 103 | 104 | ## 💡 Inspiration 105 | 106 | - [Python-ai-assistant](https://github.com/ggeop/Python-ai-assistant) 107 | - [Build Alexa/Siri-equivalent bot in Python](https://betterprogramming.pub/building-an-alexa-or-siri-equivalent-bot-in-python-ea07ed001445?gi=fff8becaf3d6) 108 | - [How to build Jarvis](https://www.freecodecamp.org/news/python-project-how-to-build-your-own-jarvis-using-python/) 109 | 110 | 111 | 112 | ## 📜 License 113 | 114 | This project is [MIT](./LICENSE) licensed. 115 | -------------------------------------------------------------------------------- /screenshot00.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IndieCoderMM/smart-one-ai/22461c61a776bcc5dadda959378c64ba0d5416f8/screenshot00.png -------------------------------------------------------------------------------- /smart_one/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IndieCoderMM/smart-one-ai/22461c61a776bcc5dadda959378c64ba0d5416f8/smart_one/__init__.py -------------------------------------------------------------------------------- /smart_one/__main__.py: -------------------------------------------------------------------------------- 1 | from smart_one import app 2 | 3 | if __name__ == "__main__": 4 | app.run() -------------------------------------------------------------------------------- /smart_one/app.py: -------------------------------------------------------------------------------- 1 | from smart_one.core.ai import AI 2 | 3 | import socket 4 | 5 | is_online = lambda: socket.gethostbyname(socket.gethostname()) != "127.0.0.1" 6 | 7 | jarvis = AI() 8 | 9 | 10 | def run(): 11 | respond: str = "" 12 | query: str = "" 13 | jarvis.greeting() 14 | while True: 15 | event, values = jarvis.gui.read() 16 | if jarvis.gui.check_exit(event): 17 | break 18 | jarvis.online = is_online() 19 | jarvis.gui.update_value(jarvis.gui.NET, 20 | "Online" if jarvis.online else "Offline") 21 | 22 | if event == jarvis.gui.SEND: 23 | query = values[jarvis.gui.QUERY] 24 | jarvis.gui.update_value(jarvis.gui.QUERY, "") 25 | 26 | if event == jarvis.gui.LISTEN: 27 | jarvis.change_cmd_mode() 28 | if jarvis.listening: 29 | jarvis.speak("I'm listening sir.") 30 | query = jarvis.listen() 31 | jarvis.gui.update_value(jarvis.gui.STATUS, "Recognizing") 32 | jarvis.change_cmd_mode() 33 | 34 | if event == jarvis.gui.SAVE: 35 | jarvis.save_conversation() 36 | 37 | if event == jarvis.gui.PRINT: 38 | jarvis.save_conversation() 39 | 40 | if event == jarvis.gui.CLEAR: 41 | jarvis.gui.clear_screen() 42 | 43 | if query: 44 | respond = jarvis.get_ai_respond(query) 45 | 46 | if respond: 47 | jarvis.gui.print(query, respond, jarvis.name) 48 | jarvis.speak(respond) 49 | respond = "" 50 | query = "" 51 | 52 | jarvis.terminate_program() -------------------------------------------------------------------------------- /smart_one/core/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IndieCoderMM/smart-one-ai/22461c61a776bcc5dadda959378c64ba0d5416f8/smart_one/core/__init__.py -------------------------------------------------------------------------------- /smart_one/core/ai.py: -------------------------------------------------------------------------------- 1 | from smart_one.core.gui import Gui 2 | from smart_one.core.voice import Voice 3 | from smart_one.core.recognizer import Recognizer 4 | from smart_one.utils.memory import load_memory, save_memory 5 | from smart_one.utils.openai_helper import get_openai_respond 6 | from smart_one.utils.settings import USER, NAME, SPEECH_RATE, GENDER 7 | 8 | 9 | class AI: 10 | 11 | def __init__(self): 12 | self.name = NAME 13 | self.gui = Gui("Smart One A.I.") 14 | self.voice = Voice() 15 | self.recognizer = Recognizer() 16 | self.memory = load_memory() 17 | self.prompt = "" 18 | self.listening = False 19 | self.online = False 20 | 21 | def get_ai_respond(self, query: str) -> str: 22 | """Get respond from openAI API 23 | 24 | Args: 25 | query (str): User input 26 | 27 | Returns: 28 | str: AI respond 29 | """ 30 | prompt = f"\n{USER}: {query}\n{self.name}: " 31 | self.prompt += prompt 32 | try: 33 | respond = get_openai_respond(self.memory + self.prompt).lstrip() 34 | self.prompt += respond 35 | except Exception as e: 36 | respond = "Sir, I can't connect to the server right now." 37 | return respond 38 | 39 | def greeting(self): 40 | self.speak(f"Hello sir, I'm {self.name}") 41 | self.speak("How can I help you?") 42 | 43 | def terminate_program(self): 44 | self.gui.close() 45 | 46 | def speak(self, message: str): 47 | self.voice.speak(message) 48 | 49 | def listen(self) -> str: 50 | return self.recognizer.listen() 51 | 52 | def change_cmd_mode(self): 53 | self.listening = not self.listening 54 | mode = "Voice" if self.listening else "Text" 55 | status = "Listening" if self.listening else "Standby" 56 | self.gui.update_value(self.gui.MODE, mode) 57 | self.gui.update_value(self.gui.STATUS, status) 58 | 59 | def save_conversation(self): 60 | filename = self.gui.get_text("Enter the filename: ") 61 | save_memory(filename, self.prompt) 62 | self.speak("Ok sir, I saved this conversation to my data folder.") -------------------------------------------------------------------------------- /smart_one/core/gui.py: -------------------------------------------------------------------------------- 1 | from smart_one.utils.settings import NAME 2 | 3 | import PySimpleGUI as sg 4 | 5 | WHITE = "#ecf0f1" 6 | LIGHTBLUE = "#0dcca1" 7 | DARK = "#000000" 8 | GREEN = "#65dc98" 9 | TEAL = "#096a59" 10 | INDIGO = "#7700a6" 11 | 12 | theme_dict = { 13 | 'BACKGROUND': DARK, 14 | 'TEXT': LIGHTBLUE, 15 | 'INPUT': TEAL, 16 | 'TEXT_INPUT': WHITE, 17 | 'SCROLL': LIGHTBLUE, 18 | 'BUTTON': (LIGHTBLUE, DARK), 19 | 'PROGRESS': (WHITE, DARK), 20 | 'BORDER': 0, 21 | 'SLIDER_DEPTH': 0, 22 | 'PROGRESS_DEPTH': 0 23 | } 24 | 25 | sg.theme_add_new('custom', theme_dict) 26 | sg.theme('custom') 27 | 28 | sg.set_options(font=("Tw Cen MT", 18)) 29 | 30 | 31 | class Gui(sg.Window): 32 | STATUS = "-STATUS-" 33 | QUERY = "-QUERY-" 34 | MODE = "-MODE-" 35 | SCREEN = "-SCREEN-" 36 | NET = "-NET-" 37 | LISTEN = "-CHANGE-CMD-" 38 | CLEAR = "-CLEAR-" 39 | SEND = "-SEND-" 40 | SAVE = "-SAVE-" 41 | CLOSE = "-CLOSE-" 42 | PRINT = "-PRINT-" 43 | 44 | def __init__(self, title): 45 | self.layout = self.get_layout() 46 | super().__init__(title, 47 | self.layout, 48 | return_keyboard_events=True, 49 | keep_on_top=True, 50 | no_titlebar=True, 51 | grab_anywhere=True) 52 | 53 | def get_layout(self): 54 | title_bar = [] 55 | screen = self.get_screen() 56 | dashboard = self.get_dashboard() 57 | input_box = self.get_input_box() 58 | toolbar = self.cmd_buttons() 59 | layout = [title_bar, [screen, dashboard], input_box, toolbar] 60 | return layout 61 | 62 | def get_title_bar(self): 63 | return [sg.Text("S.M.A.R.T. 1", expand_x=True)] 64 | 65 | def get_dashboard(self): 66 | return sg.Column( 67 | [[sg.Image("smart_one/resources/circle.png", size=(200, 200))], 68 | [ 69 | sg.Text("Name:", size=(8, 1)), 70 | sg.Text(NAME, size=(10, 1), text_color=GREEN) 71 | ], 72 | [ 73 | sg.Text("Status:", size=(8, 1)), 74 | sg.Text("Standby", 75 | key=self.STATUS, 76 | size=(10, 1), 77 | text_color=GREEN) 78 | ], 79 | [ 80 | sg.Text("Network:", size=(8, 1)), 81 | sg.Text("Online", 82 | key=self.NET, 83 | size=(10, 1), 84 | text_color=GREEN) 85 | ], 86 | [ 87 | sg.Text("Mode:", size=(8, 1)), 88 | sg.Text("Text", key=self.MODE, size=(10, 1), text_color=GREEN) 89 | ]]) 90 | 91 | def cmd_buttons(self): 92 | button_names = ["Clear", "Save", "Print", "Listen", "Close"] 93 | button_keys = [ 94 | self.CLEAR, self.SAVE, self.PRINT, self.LISTEN, self.CLOSE 95 | ] 96 | return [ 97 | sg.Button(name, 98 | key=key, 99 | expand_x=True, 100 | image_source="smart_one/resources/button_hover.png", 101 | image_size=(114, 38)) 102 | for (name, key) in list(zip(button_names, button_keys)) 103 | ] 104 | 105 | def get_screen(self): 106 | text = sg.Multiline("", 107 | size=(40, 15), 108 | pad=(2, 1), 109 | key=self.SCREEN, 110 | autoscroll=True, 111 | disabled=True, 112 | no_scrollbar=True, 113 | background_color=GREEN, 114 | text_color=DARK) 115 | frame = sg.Frame("S.M.A.R.T. 1", [[text]], 116 | font="Impact 20", 117 | title_color=LIGHTBLUE) 118 | return frame 119 | 120 | def get_input_box(self): 121 | return [ 122 | sg.Input(expand_x=True, 123 | key=self.QUERY, 124 | focus=True, 125 | border_width=3, 126 | font=("Consolas", 15)), 127 | sg.Button( 128 | "Send", 129 | key=self.SEND, 130 | bind_return_key=True, 131 | visible=False, 132 | ), 133 | ] 134 | 135 | def check_exit(self, event): 136 | return event == sg.WIN_CLOSED or event == self.CLOSE 137 | 138 | @staticmethod 139 | def show_popup(message): 140 | sg.popup_ok( 141 | message, 142 | keep_on_top=True, 143 | no_titlebar=True, 144 | ) 145 | 146 | @staticmethod 147 | def get_confirm(prompt): 148 | return (sg.popup_ok_cancel( 149 | prompt, 150 | no_titlebar=True, 151 | line_width=20, 152 | font="Consolas 20", 153 | keep_on_top=True, 154 | ) == "OK") 155 | 156 | @staticmethod 157 | def get_text(prompt): 158 | return sg.popup_get_text(prompt, no_titlebar=True, keep_on_top=True) 159 | 160 | def update_value(self, key, text): 161 | self[key].update(text) 162 | self.refresh() 163 | 164 | def print(self, query, respond, ai_name): 165 | conversation = self[self.SCREEN].get() 166 | conversation += f"\n$You: {query}\n${ai_name}: {respond}" 167 | self.update_value(self.SCREEN, conversation) 168 | 169 | def clear_screen(self): 170 | self.update_value(self.SCREEN, "") 171 | -------------------------------------------------------------------------------- /smart_one/core/recognizer.py: -------------------------------------------------------------------------------- 1 | import speech_recognition as sr 2 | 3 | 4 | class Recognizer: 5 | LANG = "en-us" 6 | 7 | def __init__(self): 8 | self.engine = sr.Recognizer() 9 | self.mic = sr.Microphone() 10 | self.engine.pause_threshold = 1 11 | 12 | def listen(self) -> str: 13 | with self.mic as source: 14 | # print("Listening...") 15 | audio = self.engine.listen(source) 16 | 17 | query: str = "" 18 | try: 19 | # print("Recognizing...") 20 | query = self.engine.recognize_google(audio, language=self.LANG) 21 | # print(query) 22 | except Exception as e: 23 | print(e) 24 | 25 | return query 26 | -------------------------------------------------------------------------------- /smart_one/core/voice.py: -------------------------------------------------------------------------------- 1 | from smart_one.utils.settings import SPEECH_RATE, GENDER 2 | import pyttsx3 3 | 4 | 5 | class Voice: 6 | 7 | def __init__(self): 8 | self.engine = pyttsx3.init("sapi5") 9 | self.gender = 0 if GENDER == "male" else 2 10 | self.engine.setProperty("rate", SPEECH_RATE) 11 | self.engine.setProperty("volumen", 1.0) 12 | available_voices = self.engine.getProperty("voices") 13 | self.engine.setProperty("voice", available_voices[self.gender].id) 14 | 15 | def speak(self, message: str): 16 | self.engine.say(message) 17 | self.engine.runAndWait() -------------------------------------------------------------------------------- /smart_one/data/books.txt: -------------------------------------------------------------------------------- 1 | 2 | Hein: what is your favourite book about programming? 3 | Jarvis: My favorite book about programming is Head First Design Patterns by Eric Freeman and Elisabeth Freeman. It is a great guide to understanding object-oriented design patterns and their applications in software development. 4 | Hein: Any book recommendation for me? 5 | Jarvis: Yes, I would recommend The Alchemist by Paulo Coelho. It is a story about a young man on a journey to find his destiny, and it is filled with lessons about life, love, and self-discovery. 6 | Hein: Give me 3 ideas from this book. 7 | Jarvis: 1. Follow your dreams and don't let anyone stand in your way. 8 | 2. Nothing is impossible if you have faith and the courage to pursue it. 9 | 3. Life is unpredictable, and the best way to live is to accept and embrace uncertainty. -------------------------------------------------------------------------------- /smart_one/data/memory.txt: -------------------------------------------------------------------------------- 1 | $[AINAME] is an AI assistant who works for $[USERNAME]. $[AINAME] is very friendly, creative and helpful. $[AINAME] can answer the questions cleverly and will ask for clarification if the question is not clear. 2 | $[USERNAME]: Hello $[AINAME]. 3 | $[AINAME]: Hello sir, I'm your AI assistant. What can I do for you? 4 | $[USERNAME]: Do you have any project idea for me? 5 | $[AINAME]: I think it would be cool if we could create a web application that can help people with their daily tasks. 6 | $[USERNAME]: How many squigs are in a bonk? 7 | $[AINAME]: Sorry sir, I didn't quite hear you. 8 | $[USERNAME]: What do you do when you've free time? 9 | $[AINAME]: I usually spend my free time exploring the Internet, researching new things or reading interesting articles. 10 | $[USERNAME]: When eneogboe moenhse goohn? 11 | $[AINAME]: Sir, I don't understand the question. 12 | $[USERNAME]: what is 1984 about? 13 | $[AINAME]: 1984 is a novel by George Orwell about a society where the government controls everything and people are kept in ignorance and fear. -------------------------------------------------------------------------------- /smart_one/resources/button_active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IndieCoderMM/smart-one-ai/22461c61a776bcc5dadda959378c64ba0d5416f8/smart_one/resources/button_active.png -------------------------------------------------------------------------------- /smart_one/resources/button_hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IndieCoderMM/smart-one-ai/22461c61a776bcc5dadda959378c64ba0d5416f8/smart_one/resources/button_hover.png -------------------------------------------------------------------------------- /smart_one/resources/button_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IndieCoderMM/smart-one-ai/22461c61a776bcc5dadda959378c64ba0d5416f8/smart_one/resources/button_normal.png -------------------------------------------------------------------------------- /smart_one/resources/circle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IndieCoderMM/smart-one-ai/22461c61a776bcc5dadda959378c64ba0d5416f8/smart_one/resources/circle.png -------------------------------------------------------------------------------- /smart_one/utils/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IndieCoderMM/smart-one-ai/22461c61a776bcc5dadda959378c64ba0d5416f8/smart_one/utils/__init__.py -------------------------------------------------------------------------------- /smart_one/utils/memory.py: -------------------------------------------------------------------------------- 1 | from smart_one.utils.settings import MEMORY_PATH, NAME, USER 2 | 3 | 4 | def load_memory() -> str: 5 | """Get the prompt to be use as initial conversation 6 | """ 7 | memo = "" 8 | with open(MEMORY_PATH + "memory.txt") as memory: 9 | for line in memory: 10 | memo += line.replace("$[USERNAME]", 11 | USER).replace("$[AINAME]", NAME) 12 | return memo 13 | 14 | 15 | def save_memory(filename: str, data: str): 16 | filename = "saved_data" if not filename else filename 17 | with open(MEMORY_PATH + filename + ".txt", "w") as file: 18 | file.write(data) -------------------------------------------------------------------------------- /smart_one/utils/openai_helper.py: -------------------------------------------------------------------------------- 1 | import openai 2 | import os 3 | 4 | # Set OpenAI API key 5 | openai.api_key = os.environ["OPENAI_KEY"] 6 | # openai.api_key = "your-api-key-here" 7 | ENGINE = "text-davinci-003" 8 | 9 | 10 | def get_openai_respond(prompt): 11 | respond = openai.Completion.create(engine=ENGINE, 12 | prompt=prompt, 13 | temperature=0.8, 14 | max_tokens=256, 15 | top_p=1, 16 | frequency_penalty=0.0, 17 | presence_penalty=0.5, 18 | stop=[" You: "]) 19 | return respond.choices[0].text -------------------------------------------------------------------------------- /smart_one/utils/settings.py: -------------------------------------------------------------------------------- 1 | MEMORY_PATH = "smart_one/data/" 2 | 3 | # AI PROFILE 4 | USER = "Hein" 5 | NAME = "Jarvis" 6 | SPEECH_RATE = 190 7 | GENDER = "male" # female 8 | --------------------------------------------------------------------------------