Instructions to use neuphonic/neutts-air with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- llama-cpp-python
How to use neuphonic/neutts-air with llama-cpp-python:
# !pip install llama-cpp-python from llama_cpp import Llama llm = Llama.from_pretrained( repo_id="neuphonic/neutts-air", filename="neutss-air-BF16.gguf", )
llm.create_chat_completion( messages = "\"The answer to the universe is 42\"" )
- Notebooks
- Google Colab
- Kaggle
- Local Apps
- llama.cpp
How to use neuphonic/neutts-air with llama.cpp:
Install from brew
brew install llama.cpp # Start a local OpenAI-compatible server with a web UI: llama-server -hf neuphonic/neutts-air:BF16 # Run inference directly in the terminal: llama-cli -hf neuphonic/neutts-air:BF16
Install from WinGet (Windows)
winget install llama.cpp # Start a local OpenAI-compatible server with a web UI: llama-server -hf neuphonic/neutts-air:BF16 # Run inference directly in the terminal: llama-cli -hf neuphonic/neutts-air:BF16
Use pre-built binary
# Download pre-built binary from: # https://github.com/ggerganov/llama.cpp/releases # Start a local OpenAI-compatible server with a web UI: ./llama-server -hf neuphonic/neutts-air:BF16 # Run inference directly in the terminal: ./llama-cli -hf neuphonic/neutts-air:BF16
Build from source code
git clone https://github.com/ggerganov/llama.cpp.git cd llama.cpp cmake -B build cmake --build build -j --target llama-server llama-cli # Start a local OpenAI-compatible server with a web UI: ./build/bin/llama-server -hf neuphonic/neutts-air:BF16 # Run inference directly in the terminal: ./build/bin/llama-cli -hf neuphonic/neutts-air:BF16
Use Docker
docker model run hf.co/neuphonic/neutts-air:BF16
- LM Studio
- Jan
- Ollama
How to use neuphonic/neutts-air with Ollama:
ollama run hf.co/neuphonic/neutts-air:BF16
- Unsloth Studio new
How to use neuphonic/neutts-air with Unsloth Studio:
Install Unsloth Studio (macOS, Linux, WSL)
curl -fsSL https://unsloth.ai/install.sh | sh # Run unsloth studio unsloth studio -H 0.0.0.0 -p 8888 # Then open http://localhost:8888 in your browser # Search for neuphonic/neutts-air to start chatting
Install Unsloth Studio (Windows)
irm https://unsloth.ai/install.ps1 | iex # Run unsloth studio unsloth studio -H 0.0.0.0 -p 8888 # Then open http://localhost:8888 in your browser # Search for neuphonic/neutts-air to start chatting
Using HuggingFace Spaces for Unsloth
# No setup required # Open https://huggingface.co/spaces/unsloth/studio in your browser # Search for neuphonic/neutts-air to start chatting
- Pi new
How to use neuphonic/neutts-air with Pi:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama-server -hf neuphonic/neutts-air:BF16
Configure the model in Pi
# Install Pi: npm install -g @mariozechner/pi-coding-agent # Add to ~/.pi/agent/models.json: { "providers": { "llama-cpp": { "baseUrl": "http://localhost:8080/v1", "api": "openai-completions", "apiKey": "none", "models": [ { "id": "neuphonic/neutts-air:BF16" } ] } } }Run Pi
# Start Pi in your project directory: pi
- Hermes Agent new
How to use neuphonic/neutts-air with Hermes Agent:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama-server -hf neuphonic/neutts-air:BF16
Configure Hermes
# Install Hermes: curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash hermes setup # Point Hermes at the local server: hermes config set model.provider custom hermes config set model.base_url http://127.0.0.1:8080/v1 hermes config set model.default neuphonic/neutts-air:BF16
Run Hermes
hermes
- Docker Model Runner
How to use neuphonic/neutts-air with Docker Model Runner:
docker model run hf.co/neuphonic/neutts-air:BF16
- Lemonade
How to use neuphonic/neutts-air with Lemonade:
Pull the model
# Download Lemonade from https://lemonade-server.ai/ lemonade pull neuphonic/neutts-air:BF16
Run and chat with the model
lemonade run user.neutts-air-BF16
List all available models
lemonade list
How do I get it to use the GPU?
I understand that hooking it up into a llama-cpp instance that uses the GPU is the way, but the only way to do that without getting a bit complex is to use pre-existing binaries like those that come with oollama, lmstudio, etc.
Can the creators find a way to hook it up into a version of torch, or is it already set in stone?
here is a gradio demo that uses the gpu
import gradio as gr
import soundfile as sf
import tempfile
import os
from pathlib import Path
from neuttsair.neutts import NeuTTSAir
# Global variable to store the TTS model
tts_model = None
current_backbone = None
def initialize_model(backbone_choice):
"""Initialize or reinitialize the TTS model with the selected backbone."""
global tts_model, current_backbone
backbone_map = {
"Standard (PyTorch)": "neuphonic/neutts-air",
"Q8 GGUF (Faster)": "neuphonic/neutts-air-q8-gguf",
"Q4 GGUF (Fastest)": "neuphonic/neutts-air-q4-gguf"
}
backbone_repo = backbone_map[backbone_choice]
# Only reinitialize if the backbone changed
if current_backbone != backbone_repo:
print(f"Initializing model with {backbone_repo}...")
tts_model = NeuTTSAir(
backbone_repo=backbone_repo,
backbone_device="cuda", # Changed from "cpu"
codec_repo="neuphonic/neucodec",
codec_device="cuda" # Changed from "cpu"
)
current_backbone = backbone_repo
return f"β
Model loaded: {backbone_choice}"
return f"β
Using: {backbone_choice}"
def generate_speech(input_text, ref_audio, ref_text, backbone_choice, progress=gr.Progress()):
"""Generate speech from text using reference audio for voice cloning."""
try:
if not input_text or not input_text.strip():
return None, "β Please enter text to synthesize."
if ref_audio is None:
return None, "β Please upload a reference audio file."
if not ref_text or not ref_text.strip():
return None, "β Please enter the reference text."
# Initialize model if needed
progress(0.1, desc="Loading model...")
status = initialize_model(backbone_choice)
# Encode reference audio
progress(0.3, desc="Encoding reference audio...")
ref_codes = tts_model.encode_reference(ref_audio)
# Generate speech
progress(0.6, desc="Generating speech...")
wav = tts_model.infer(input_text, ref_codes, ref_text.strip())
# Save to temporary file
progress(0.9, desc="Saving audio...")
with tempfile.NamedTemporaryFile(delete=False, suffix=".wav") as tmp_file:
sf.write(tmp_file.name, wav, 24000)
output_path = tmp_file.name
return output_path, f"β
Speech generated successfully! ({len(wav)/24000:.2f}s)"
except Exception as e:
return None, f"β Error: {str(e)}"
def load_example(example_name):
"""Load example reference audio and text."""
example_map = {
"Dave": ("samples/dave.wav", open("samples/dave.txt").read().strip()),
"Jo": ("samples/jo.wav", open("samples/jo.txt").read().strip())
}
if example_name in example_map:
audio_path, text = example_map[example_name]
if os.path.exists(audio_path):
return audio_path, text, "β
Example loaded!"
else:
return None, "", "β Example file not found."
return None, "", ""
# Create Gradio interface
with gr.Blocks(title="NeuTTS Air - Voice Cloning Demo", theme=gr.themes.Soft()) as demo:
gr.Markdown("""
# ποΈ NeuTTS Air - Voice Cloning Demo
Create ultra-realistic voice clones with as little as 3 seconds of audio! This demo uses NeuTTS Air,
a state-of-the-art on-device TTS model with instant voice cloning capabilities.
### π How to use:
1. **Upload reference audio** (3-15 seconds, clean speech, WAV format recommended)
2. **Enter what the reference says** (the transcript of your reference audio)
3. **Type what you want to synthesize** (the text in the cloned voice)
4. **Choose a model** (Q4 GGUF is fastest for CPU)
5. **Click Generate!**
""")
with gr.Row():
with gr.Column(scale=1):
gr.Markdown("### π΅ Reference Audio (Voice to Clone)")
# Example selector
with gr.Row():
example_selector = gr.Radio(
choices=["Dave", "Jo", "Custom"],
value="Custom",
label="Quick Examples or Custom",
info="Try built-in examples or upload your own"
)
ref_audio_input = gr.Audio(
label="Reference Audio (3-15s of clean speech)",
type="filepath"
)
ref_text_input = gr.Textbox(
label="Reference Text (Transcript of the reference audio)",
placeholder="What does the reference audio say?",
lines=3
)
example_status = gr.Textbox(label="Status", interactive=False, visible=False)
with gr.Column(scale=1):
gr.Markdown("### βοΈ Text to Synthesize")
input_text = gr.Textbox(
label="Input Text (Text to synthesize in the cloned voice)",
placeholder="Enter the text you want to synthesize in the cloned voice...",
lines=5
)
backbone_choice = gr.Radio(
choices=["Standard (PyTorch)", "Q8 GGUF (Faster)", "Q4 GGUF (Fastest)"],
value="Q4 GGUF (Fastest)",
label="Model Selection (Q4 GGUF recommended for CPU)"
)
generate_btn = gr.Button("π΅ Generate Speech", variant="primary", size="lg")
with gr.Row():
with gr.Column():
output_audio = gr.Audio(
label="Generated Speech",
type="filepath"
)
status_output = gr.Textbox(label="Generation Status", interactive=False)
gr.Markdown("""
### π Tips for Best Results:
- **Reference audio should be**: mono, 16-44kHz, 3-15 seconds, clean with minimal background noise
- **Natural speech works best**: conversational tone with few pauses
- **GGUF models**: Much faster on CPU, slight quality trade-off
- **Longer texts**: May take more time but produce great results
### β οΈ Responsible Use:
- Only clone voices you have permission to use
- Generated audio is watermarked for detection
- Built by [Neuphonic](https://neuphonic.com)
""")
# Event handlers
def handle_example_change(example_name):
if example_name in ["Dave", "Jo"]:
return load_example(example_name)
return None, "", ""
example_selector.change(
fn=handle_example_change,
inputs=[example_selector],
outputs=[ref_audio_input, ref_text_input, example_status]
)
generate_btn.click(
fn=generate_speech,
inputs=[input_text, ref_audio_input, ref_text_input, backbone_choice],
outputs=[output_audio, status_output]
)
# Example inputs for quick testing
gr.Examples(
examples=[
["Hey there, I'm exploring the world of voice AI and it's absolutely fascinating!"],
["The quick brown fox jumps over the lazy dog."],
["My name is Alex, and I'm 28 years old. I work in technology and love building innovative products."],
],
inputs=[input_text],
label="Example Texts to Try"
)
if __name__ == "__main__":
demo.launch(
share=False,
server_name="0.0.0.0",
server_port=7868
)
Appears you've just changed CPU to CUDA -- doesn't seem to work,
"AssertionError: Torch not compiled with CUDA enabled"
@jattoedaltni
it's because in the requirements.txt you have "torch" compiled for CPU only. To change it to a CUDA version follow these steps:
check https://pytorch.org/get-started/locally/ to get the necessary pip command for your version of CUDA. Let's presume you have CUDA v12.6, then you will get
pip3 install torch torchvision --index-url https://download.pytorch.org/whl/cu126. You need only the link part.open requirements.txt. Remove torch and add this to the end of the file:
--extra-index-url https://download.pytorch.org/whl/cu126
torch
torchvisionexecute
pip uninstall torchto remove the previous version of torchexecute
pip install -r requirements.txt. A different type of torch must be downloading (weights about 2 GB)Use the example above with gradio from the previous commenter, and run the app. It must use GPU now
Note that actual layers of the model will only be offloaded to the GPU (when using GGUF) if the device is set to gpu, not if it's set to cuda.
If it's set to cuda you'll still be using the GPU (assuming llama_cpp_python was compiled with CUDA support) but the actual model will reside on the CPU.
From the code in the GitHub repo:
self.backbone = Llama.from_pretrained(
repo_id=backbone_repo,
filename="*.gguf",
verbose=False,
n_gpu_layers=-1 if backbone_device == "gpu" else 0,
n_ctx=self.max_context,
mlock=True,
flash_attn=True if backbone_device == "gpu" else False,
)