Tiny Jarvis
Hardware- 13 Devlogs
- 14 Total hours
Voice-activated local AI agent sitting on your desk running on a Raspberry pi 5, custom HAT with OLED screen and vintage control interface.
Voice-activated local AI agent sitting on your desk running on a Raspberry pi 5, custom HAT with OLED screen and vintage control interface.
cooking_helper.py in a cooking/ folderrecipes.csv
csv.DictReader object to access the info and organize it into a list, very useful.main.py so that when the user’s prompt starts with “Cooking”, it takes a random recipe from the csv file (using the random.randint(a, b) function) and returns a formatted sentence with all the info for cooking that recipe.JOURNAL.md
python main.py and somwhow got three errors in a row.trys and except Exception as e everywhere to prevent this.ssd1106 not being a real OLED screen part namegpiozero missing the rpi-lgpio library, which needs system-wide packages swig and liblgpio-dev so yh dependency hell.install.sh with these changes, now works perfectly.rpi-imager
user-data, cloud-init-ouput.log, etc… realized the Imager wasn’t writing the information in those files but others, booting it up into HDMI, checking the logs, managing to bypass username but not keyboard layout, etc… I EVEN TRIED LEGACY VERSIONS OF THE OS AND CREATING A wpa_supplicant.conf.rpi-imager version (even though I had updated it) and turns out my laptop just couldn’t get the latest version : it was 1.8.0, not 2.1.0 (the latest one).install.sh which is basically fire since you just runchmod +x install.sh
./install.sh
and the whole system-wide-packages-and-dependencies are all installed in the right order, easily.
llama.cpp
ai.py with this new feature, there are more settings than Ollama for optimizing performance for CPU-only (4 cores) which is great, however I had to download a .gguf from Hugging Face and accidentally ended up being given access to a repository for the model?! so i can now propose changes to that repo, for some reason…TypeError in main.py
JOURNAL.md, where I soldered and tested the prototype PCBs I ordered from JLCPCBAssistantDisplay class to better manage the OLED threads - way cleaner nowsentence_buffer() in ai.py and get_lastest_recordings() in listener.py, now the only function in main.py is main(). Clean!faster-whisper model by setting cpu_threads to 4 and beam_size to 1, even if we’ll lose a tiny bit in quality. Still a good tradeoffglob detected the file while it was being written to and passed it on to faster-whisper, then it would be corrupted and be mashed garbage. So I read some documentation about the queue module and used that, it’s way better and easier in the end.ollama’s ChatResponse class allows, when creating an instance of it, to write stream = True.sentence_buffer() that seperates them into a list of words, that are then given to Piper TTS in speaker.py
pyaudio to stream the Piper TTS output into the speakers! it’s actually just a Python wrapper for a C library called portaudio, so I ran into a LOT of dependency issues, but that’s a battle for another day.main.py into other files for better managementthreading, and realized it wasn’t that difficult to implement in my project.oled("thinking_animation.gif") it ran sequentially, so the whole script had to wait for the animation to finish, which obviously can’t happen.threading.Event() which enabled me to manage the “workers” way better (sorry, i’m getting used to the vocabulary)main.py for better explainability.Note: sadly it will be difficult to use threads in the rest of the code, since the process is, at its core, sequential.
Faster-whisperneeds audio to proceed, the ollama AI chatbot needs a prompt to continue, etc…
How to install section, there are tons of different commands to run to ensure it works first tryOLED.py: it now supports gifs, which is great because of Piskel which can turn simple animations into gifs.thinking_animation.gif and button_pressed.gif)listener.py for future debugging.One of the biggest issues with this project so far: the difficulty to test it! I don’t have all the required materials yet. I might use the
pytestmodule? we’ll see
Tiny_Jarvis/
├── .venv/
├── piper_voices/
├── recordings/ # New
├── assets/ # New
├── ai.py
├── listener.py # New
├── main.py
├── OLED.py
├── speaker.py
├── transcriber.py # New
├── README.md
└── requirements.txt
assets/ folder for the OLED screen visualsrecordings/ folder for the audio captured by the mic when the user is speakinglistener.py: actively listens for a button press; when pressed, records audio through the usb mic until the button is released, then that audio is sent to transcriber.py
transcriber.py: takes that audio and passes it as input into faster-whisper to “translate” into text !main.py: there is still a lot to be done if we are talking speed/efficiency, but the core pipeline is done.faster-whisper, then that text is given as prompt to the AI chatbot (like Qwen3-0.6B. The response is then turned into a voice using Piper TTS and outputted through the speaker!Possible future implementation of the threading module to make it faster, even though I have no idea how it works.
.venv/ so that all necessary python modules and packages are cleanly installed together.requirements.txt, where I put all the python modules I import in the project so that people can reuse it.piper_voices/ directory and downloaded a medium voice via python -m piper.download_voices en_US-lessac-medium
Tiny_Jarvis/
├── ai.py # the AI chatbot
├── main.py # the main script
├── OLED.py # The visuals!
└── speaker.py # the audio
main.py later on.README.md. It’s empty for now, will fill it in later.