Repository navigation
Releases: JMS1717/ming-voice
Release list
v1.6.0: native Linux (AMD and NVIDIA), Jarvis mode, smarter Home Assistant
Ming Voice now runs natively on Linux, on AMD and NVIDIA GPUs, with a one-line install. This release also adds Jarvis mode, much better Home Assistant control, steadier built-in voices, and a move to PyTorch 2.11.
Linux
Open a terminal and paste:
curl -fsSL https://raw.githubusercontent.com/JMS1717/ming-voice/main/install.sh | bash- Distros: Arch, CachyOS, EndeavourOS, Manjaro, Ubuntu, Debian, Pop!_OS, Mint, Fedora, Nobara and openSUSE. Others work too if they have git and curl.
- AMD needs no ROCm install. PyTorch's ROCm 7.2 build carries its own libraries, so the standard
amdgpudriver that comes with your kernel is enough. Supported cards are the RX 6800 and newer, the RX 7000 and 9000 series, and Radeon PRO. - NVIDIA needs only your distro's driver; PyTorch brings CUDA 12.8.
- What the installer does:
- Installs what's missing (git, curl, openssl, PortAudio) with your package manager.
- Picks the right GPU. When there's also an integrated GPU, it uses the big one.
- Sets up cards PyTorch doesn't list as their closest supported sibling.
- Adds you to the
rendergroup. - Puts Ming Voice in your app menu.
- Running it again skips the finished steps.
- The
ming-voicecommand starts the server in the background, waits for the model, and opens the app. You can also:--always-on: wake word, no browser--phone: use it from your phone--autostart: start at login--stop,--status,--logs
Tested in fresh CachyOS, Arch, Ubuntu 24.04, Debian 13, Fedora and openSUSE Tumbleweed installs, plus CUDA on a real NVIDIA card.
PyTorch 2.11 and ROCm 7.2
- Every platform moves from PyTorch 2.8 to 2.11:
- ROCm 7.2 on Linux
- AMD's ROCm 7.2.4 build in WSL
- CUDA 12.8 on NVIDIA
- On Windows, re-run the installer (or
bash setup_env.sh) to upgrade. Speed and output match the old version.
Jarvis mode
- Pick Jarvis (robot butler) under Settings → Persona. You get a dry-witted British butler with its own designed voice and the wake word "Jarvis".
- Even its tool confirmations are in character.
- The voice is an original design, not a copy of anyone's.
Home Assistant
- Media: pause, skip, volume and "what's playing?" for speakers and TVs.
- Lights: colours, warm white and "dimmer".
- Car: climate, temperature and defrost.
- Follow-ups work: "now turn it off", "and the living room too".
- Rooms: "turn off the lights" means the lights in the room the device is in.
- Two commands at once: "turn off the desk lamp and lock the car".
- For later: "turn off the lights in 20 minutes", "start the vacuum at 9 am".
- Music Assistant: "play some jazz on the kitchen speaker".
- Heads-ups when a lock or garage door is left open at night, or the vacuum gets stuck or finishes.
- Clear commands go straight to Home Assistant, and your own words are used, not the model's rewording.
Also new
- Ending the conversation: say "that's all, bye" and it ends the conversation, or goes back to sleep in wake-word mode.
- Steadier built-in voices: voice anchors keep them consistent from reply to reply, and numbers from 21 to 99 are said as words.
- Windows installer: one step with
install.ps1/Install.cmd, including experimental NVIDIA support. - Tests:
dev/test_ha_model.pychecks the model's Home Assistant calls.
v1.5.0: lists, memory, and a voice that reads numbers right
Ming Voice now keeps shopping and to-do lists, remembers things you tell it, picks up the conversation after a restart, and reads numbers, money and units aloud the way you'd say them.
Lists
- New
liststool. Try "add milk, eggs and bread to my shopping list", "what's on my to-do list?", "I bought the eggs" or "clear my shopping list". - It handles shopping, to-do, or any list you name. "Groceries" means the shopping list.
- Duplicates and plurals are handled: "egg" removes "eggs".
- Lists are kept in
.lists.jsonon the server.
Memory
- New
memorytool. Say "remember that I parked on level 3", and days later ask "where did I park?". Say "forget where I parked" to remove it. - Up to 40 facts are kept in
.memory.jsonand given to the model in every conversation.
Replies that claim an action are made true
- Sometimes the model says it changed a list or forgot something without calling the tool, for example "The eggs are off your list".
- That call is now made for it, so what it said actually happened.
- If the call doesn't succeed (say the item wasn't on the list), the reply tells you so.
Survives restarts
- The conversation is saved in
.conversation.jsonafter every turn. - A server that restarts within 30 minutes carries on where it left off. Set the window with
MING_RESUME_S. - New chat clears it.
Speaks numbers and symbols properly
These are rewritten into words before they're spoken:
- "240 × 37" and "3x"
- "-5°C"
- score and year ranges ("24-17", "2025–2026")
- money ("$1,299.99", "$5.5 million", "£3.50")
- speeds ("12 km/h", "5 mph")
- "12:00 PM"
- simple fractions, "&", and hyphenated words such as "Wi-Fi"
Each rule was checked by speaking it and transcribing it back.
Better routing
- Requests to research or compare what's best this year now reliably use web search.
Tests
dev/test_speech_text.py: offline checks of the spoken-text rewriting.dev/test_tools.py: now covers lists and memory, offline.
v1.4.0 — smarter tool use, listenable answers, self-restarting server
Ming Voice now answers more of what you ask itself, uses tools only when they help, keeps answers short enough to listen to, and restarts by itself after a crash.
Better answers, fewer needless tool calls
- The assistant knows its name. The persona is now "Ming". Before, "Hey Ming" in your question sometimes made it look "Ming" up: in Hermes, in Jellyfin, or on the clock.
- The time and date need no tool. Each reply starts from a private note of the local date and time, so "what time is it?" and "what's today's date?" are answered at once.
get_current_timeis for other time zones. - Jellyfin is only used when you talk about watching or listening. It only starts playback when you say to (play, watch, put on, listen, ...). "Tell me a joke" no longer plays a show with "joke" in its title.
- Replies that forget the tools are caught. Sometimes the model says it can't look things up ("I don't have access to real-time data..."). Now the start of such a reply is held back before it is spoken, and the turn becomes a web search (or a weather lookup) instead.
- Answers you can listen to.
- An answer from search or weather results ends after a few sentences.
- Any other answer ends after about 30 seconds of speech, unless you asked for something long: a story, a recipe, steps, "in detail", and so on.
- A reply that reaches the length limit now finishes its sentence instead of stopping mid-word.
Hermes only when you ask for it
ask_hermesnow runs only when you say "Hermes" ("ask Hermes to ..."). This is checked against what you actually said.MING_HERMES_AUTO=1brings back the old behaviour: Ming hands Hermes anything its own tools can't do.
Timers
- Repeating alarms. A timer that goes off is said again every minute, twice more, until you say something or press stop. Set the repeats with
MING_ALARM_REPEATS(0for once only) and the interval withMING_ALARM_REPEAT_S. - Wording fixes. "Your timer for 10 minutes is done" replaces "Your 10 minutes timer is done". A reminder written as "time to stretch" is no longer said as "Time to time to stretch".
Reliability
- Self-restarting server.
run.shrestarts the server 10 s after a crash whenMING_SUPERVISE=1. The always-on launcher sets this.- A GPU error that leaves the device unusable now exits the server, so it comes back on a fresh one.
- A second copy started by mistake exits with a clear message instead of looping.
- Weather lookups retry once when the weather service is slow or failing, and remember place lookups, which saves a round trip.
Always-on client
- Check your microphones:
python windows\ming_client.py --test-micslists every input device with its level and flags silent ones. Use it to pickinput_devicefor.client.json. - Silent-mic warning: the client log now names the microphone and speakers in use. It also warns when the mic has picked up nothing for 10 minutes, for example when it is muted or the wrong device is selected.
Tests
dev/test_routing.pyspeaks 17 everyday questions and checks which tools are used for each. General knowledge must use no tool, the time and date must come from the note, and research must use web search.
v1.3.0 — always on: desk client, announcements, confirmations
Ming Voice now works as an always-on home assistant: no browser tab, announcements from Home Assistant, and a spoken check before risky actions.
Always on, without a browser
windows\ming_client.pyis a background client that uses the PC's own microphone and speakers, in wake-word mode ("Hey Ming, ..."). Timer alarms and announcements play through the speakers too.- Start it: run
windows\Ming Voice (always on).cmd. It starts the server minimized, plus phone access and the client. - Start at sign-in:
windows\install_autostart.ps1now sets up this always-on version. Use-Browserfor the previous behaviour (open the app in the browser). - Speakers vs. headset: on speakers the mic is muted while Ming talks, so it never answers itself. With a headset, set
"barge_in": trueto be able to talk over it. - Sharing with the phone: opening the app on your phone takes over; the PC client takes the conversation back by itself 15 s after the phone app is closed.
- Settings go in
.client.json(not committed): wake word, voice, location, and mic/speaker devices. - Needs: Python for Windows with
pip install sounddevice websockets numpy.
Announcements
- From Home Assistant: Ming listens on Home Assistant's event bus. An automation with an
eventaction (ming_announce,message: Someone is at the front door.) makes it say that. No integration,configuration.yamlchange or HA restart is needed. - From anything else: send
POST /api/announcewith{"message": "The washer is done."}. - How they're said: each one waits for a quiet moment and plays a short chime first. Announcements that can't be said within
ttl(5 minutes by default) are dropped.
Confirmation for risky actions
- Unlocking, opening a garage door or gate, and disarming an alarm get a question first: "Just to be sure: do you want me to unlock the front door?"
- The action only happens on a yes in your next turn, within a minute. Exactly what you were asked about is what runs.
- A yes in the same reply that asked doesn't count, and neither does a yes to a different device.
- Questions ("is the garage open?") and locking/closing aren't asked about.
MING_CONFIRM_RISKY=0turns this off.
Context
- When the context fills up, it's rebuilt from the conversation as text between turns, while nobody is talking (about 0.5 s). Before, this happened at the start of your next reply and delayed it. The first two exchanges and the most recent ones are kept.
- Long prompts are processed in 512-token chunks, which bounds their GPU memory.
- Context size: 8k stays the default on 24 GB cards and 16k is used from 32 GB;
MING_MAX_CTXoverrides it. A bigger context doesn't slow short conversations, but on a 24 GB card 16k leaves the GPU libraries too little working memory next to the voice model.
Fixes
- The Windows launcher's "is it already running?" check timed out because PowerShell 5 tries IPv6 for
localhostfirst. When that happened it tried to start a second server.
Ming Voice 1.2: wake word, timers, Brave Search
This release is a step toward an always-on assistant: a wake word, native timers and reminders, and better web search.
Wake word
- New Wake word turn-taking mode (Settings). It listens all the time but only answers speech that starts with its name, e.g. "Hey Ming, turn off the lamp". You can also say just "Hey Ming", wait for the chime, then talk.
- Follow-up window: for 8 s after each reply you can keep talking without the wake word.
- No training, no extra model: the name is checked by Ming's own speech recognition on the first 1.6 s of each utterance, while you're still talking. Answers start as fast as in hands-free mode. Any name works; set it in Settings.
- Timer alarms and Hermes results are announced whether it's asleep or awake.
Timers and reminders
- A native
timertool: "set a timer for 10 minutes", "remind me to call mom at 5 pm", "how long is left?", "cancel the pasta timer". - Understands durations ("an hour and a half", "90 seconds") and clock times ("5:30 pm", "tomorrow at 9", "Friday at noon").
- When one goes off, the page chimes and says it, e.g. "Time to call mom.".
- Timers are saved to disk, so they survive a restart. One that went off while the server was down is announced late rather than lost.
Web search
- Optional Brave Search (
.brave_keyorMING_BRAVE_KEY; there's a free tier) for fresher, more reliable web results. DuckDuckGo stays the fallback, and news questions still use DuckDuckGo News, which ranks headlines better. - Answers after a tool call are now kept to one or two spoken sentences: no bulleted lists, no "want me to dig deeper?".
Other
windows/install_autostart.ps1starts Ming Voice when you sign in to Windows. It only affects your account; run it with-Removeto undo.- New
dev/test_wake.py, plus timer checks indev/test_tools.py.
Ming Voice 1.1: tools, Home Assistant, Jellyfin, Hermes
The assistant can now use tools while it talks, and the model decides when to call them. General questions and small talk still get an instant answer with no tool call.
New
- Web search (DuckDuckGo, no key) for news, prices, scores and recent events. The reply shows what was searched and the sources.
- Weather (Open-Meteo, no key): current conditions and a 3-day forecast. Set "Your location" in Settings to use it as the default.
- Calculator and clock for exact arithmetic and the current date and time.
- Home Assistant control through HA's own Assist API. Device names, aliases and areas work just as they do in HA, and only entities exposed to voice assistants can be touched.
- Jellyfin: search the library, play (a series continues at the next unwatched episode), pause, resume, stop, skip, and ask "what's playing?" on any open Jellyfin player.
- Hermes Agent delegation: "ask Hermes to …" hands bigger jobs to a Hermes Agent running in the background. The answer is spoken when it's ready, even if the conversation has moved on.
- Tools that change something (Home Assistant, Jellyfin, Hermes) never run from a speculative reply. They wait until your turn has really ended.
- A cached system prompt, so the first reply after a reconnect starts quickly.
Fixes
- Memory no longer grows during long sessions (
MALLOC_ARENA_MAX=2). - Phone links opened from another app no longer land on the access-denied page, and that page now has a box to enter the key.
Setup
Each integration is optional and is turned on by adding a git-ignored file next to server.py: .ha_token / .ha_url, .jellyfin.json, .hermes.json. The README's Tools section shows the format for each.
Tested with dev/test_tools.py (tool choice, answers, delegation) and dev/test_api.py (14/14).
Ming Voice 1.0
First release of Ming Voice: a fully local, low-latency speech-to-speech voice assistant built on Ming-3.0-audio-tiny, running on AMD Radeon GPUs (ROCm 7.2 in WSL2). No audio leaves the machine.
Highlights
- ~0.23 s from the end of your speech to the first audio (median, RX 7900 XTX), measured from the last audible sound of the question
- Smart turn detection (Smart Turn v3) with speculative replies generated during your pause, plus resume after a pause: if you carry on talking right after it starts answering, the answer is withdrawn and everything is answered as one turn
- Barge-in that works on a speakerphone: the server recognises its own voice coming back through the mic and stops only for yours (stops ~0.23 s after you start talking)
- Use it from your phone over HTTPS on your home network: QR code, access key, installable web app, conversation restored after reconnects
- OpenAI-compatible API:
/v1/audio/speech,/v1/audio/transcriptions,/v1/chat/completions(audio in and out),/v1/models - 7 built-in voices plus voice cloning from a 5–15 s sample; English and Chinese
- 16 GB cards supported via int8 MoE experts (auto below 23 GB VRAM, ~12.5 GB total)
Performance (RX 7900 XTX, 24 GB)
| End of speech → first audio | ~0.23 s median |
| Thinker decode | ~115 tokens/s |
| Talker | ~0.3× real time |
| Startup | ~30 s |
| VRAM | ~20.5 GB bf16 · ~12.5 GB int8 experts |
Since the first commit
- Speed: fused Triton RMSNorm/MoE router, grouped MoE prefill kernels, graph-captured prefill, energy-based pause timing and earlier speculation took end-of-speech-to-audio from ~0.56 s to ~0.23 s
- Echo guard locks onto the echo delay before trusting a match (fixes a rare swallowed barge-in)
- Server memory no longer grows per conversation (glibc arenas capped in
run.sh); ~0.6 GB less RAM without idle compile workers - Phone fixes: login links opened from other apps, message bar position, updates picked up on reload
Install
See the README: Windows 11 + WSL2 Ubuntu 24.04, an AMD GPU with 16 GB+ VRAM, ~30 GB disk.