Skip to main content

Voiceprint

A small model that writes like you. Train it on a few pages of your writing, then draft from the terminal or any MCP client.

Python 3.10+ PyPI License: MIT

Quickstart · Examples · MCP · Evaluation · Issues

Voiceprint terminal demo: train a voice, then draft a short reply

Voiceprint is built for first drafts: emails, posts, essays, and sections of longer work. It learns style from your prose while an agent or a set of notes supplies the facts and structure.

If Voiceprint is useful to you, star the repository so other writers and developers can find it.

Why Voiceprint

  • Your voice, not AI slop. A LoRA adapter learns from prose you already wrote.
  • A small corpus. About 1,000–2,000 words is enough for the tested setup.
  • CLI and MCP. Use it directly or let Claude Code, Codex, or another MCP client call it.
  • Runs in your account. Training and inference run in your own Modal workspace. There is no Voiceprint service or separate account.
  • Measurable. The built-in evaluation checks style similarity and memorization on held-out text.

Quickstart

1. Install

Install Voiceprint with uv:

uv tool install voiceprint

Or use pip install voiceprint in a Python 3.10 or newer environment.

2. Deploy

Create a Modal account, then deploy the training and serving images:

modal token new
voiceprint deploy
voiceprint check

3. Train

Train a voice from Markdown or text files:

voiceprint train ~/my-writing --name me

4. Write

voiceprint write "the wedge is trust, not features" "our users are ops leads"

The first setup takes roughly 15 minutes in the measured configuration. Training continues as a remote job if you close the terminal; reconnect with voiceprint resume.

What you can do

Draft from a brief

Pass each note as a separate argument:

voiceprint write \
  "the audience is engineering leaders" \
  "the wedge is trust, not features" \
  "end with an invitation to reply"

For longer briefs, use a file:

voiceprint write --notes-file brief.md

Continue a draft

Your existing words give the model both context and a strong style signal:

voiceprint write --continue-from draft.md

To write the next section from new notes:

voiceprint write --notes-file section3.md --continue-from section2.md

Rewrite existing text

voiceprint rewrite draft.md
pbpaste | voiceprint rewrite

Code blocks and headings pass through unchanged.

Generate short-form copy

voiceprint write --length short \
  "decline the intro politely" \
  "offer to reconnect in March"

Short-form works best when the training corpus includes short-form writing.

Use it from an agent

Voiceprint exposes an MCP server so an agent can research and plan while the adapter handles the prose. Register it with Claude Code:

claude mcp add voiceprint -- /full/path/to/.venv/bin/voiceprint mcp
cp SKILL.md ~/.claude/skills/voiceprint/SKILL.md

voiceprint check prints the MCP command with the path for your installation.

An agent can use Voiceprint in three ways:

  1. Continue text you already started.
  2. Turn an outline or brief into a draft.
  3. Interview you for the missing ideas and facts, then draft section by section.

The third workflow is useful for factual writing: your answers become notes instead of leaving the voice model to guess.

Prepare a good corpus

Use prose you wrote yourself. A directory of .md and .txt files works well:

voiceprint train ~/my-writing --name me
voiceprint train post.md --name me

The preparation step removes headings, code blocks, tables, quotes, and bulleted outlines. The CLI rejects fewer than 300 usable words and warns below 700.

Keep the corpus consistent. Use writing with the same voice, audience, and level of formality you want Voiceprint to reproduce. Mixing personal essays, corporate copy, academic prose, and heavily edited work gives the adapter conflicting signals.

Choose samples that match what you want to produce. Essays teach essay structure; short emails and posts teach short-form rhythm. Avoid transcripts, heavily co-edited work, and generic company copy.

How it works

Voiceprint builds training pairs from your corpus and trains a LoRA adapter on a Hugging Face base model. At generation time it:

  1. Formats the brief and optional draft prefix as a plain document rather than a chat turn.
  2. Generates multiple candidates with high-temperature min-p sampling.
  3. Ranks the candidates by stylometric similarity to your corpus.
  4. Returns the highest-scoring draft.

In tests, the style score flattened after roughly 700 words. The base model already knows how to write; the adapter is learning the distribution of choices that makes the writing sound like you.

Useful controls:

  • --all prints every candidate and its score.
  • --candidates N changes the number of candidates.
  • --temp controls variance. Lower values are more conservative; higher values vary more and make more mistakes.
  • --voice NAME selects a trained voice.
  • --scorer pangram uses the Pangram ranker and requires PANGRAM_API_KEY.

Evaluate the result

$ voiceprint eval me
voice: me  (5 drafts continuing held-out passages)
  stylometry   0.548   (your own unseen writing: 0.476)
  novelty      1.000   (1.000 = nothing lifted from the training text)

eval continues passages held out during training. Stylometry measures similarity to the corpus; novelty checks whether the adapter repeats training text. A novelty score below 0.95 suggests memorization.

The example comes from an 8,800-word corpus. Voiceprint selects the best of several candidates by style score, so its score is not directly comparable to a single human sample. Three training epochs are the default: in testing, eight epochs reduced novelty and made rewrites less faithful to their input.

Models and voices

Manage multiple voices from the CLI:

voiceprint voices
voiceprint use work
voiceprint write --voice work "..."
voiceprint delete old-voice

Two base-model presets have been tested:

Preset Model Result
qwen14b Qwen/Qwen2.5-14B Default; 0.548 style, 1.000 novelty
qwen7b Qwen/Qwen2.5-7B Smaller; 0.541 style, 1.000 novelty

Use a preset or another Hugging Face base-model ID:

voiceprint train ~/writing --name me --model qwen7b
voiceprint train ~/writing --name me --model someone/Their-Base-7B

Instruct and chat models are rejected. Voices that use the same base model share a serving container. Training and serving default to an A100-80GB; change TRAIN_GPU and SERVE_GPU in voiceprint/modal_app.py to use different hardware.

Privacy, accuracy, and cost

Source files stay on your machine. Derived training chunks are sent to the GPU container in your Modal account, and adapters and model weights are stored in your Modal volumes. The project has no hosted backend.

The sampling settings that preserve variation also increase factual errors. Put names, dates, numbers, and URLs in the notes, and verify the finished draft. Voiceprint is not a fact checker.

Voiceprint does not charge for usage. Modal bills your account for GPU time and storage.

Operation Measured result
Deploy the images About 4 minutes, once
Train one voice About 6 minutes on one A100
Store one adapter About 270 MB
Generate with a warm container About 3 seconds
First generation after idle 364 seconds in the measured run

Serving containers stop after 10 minutes of inactivity. Model weights remain in a shared Modal volume, so a cold start loads them from storage rather than downloading them again.

Troubleshooting

Symptom Fix
Voiceprint isn't deployed to your Modal workspace yet Run voiceprint deploy.
The first write takes several minutes Wait for the container to start and load the model.
Deployed code looks stale Run modal app stop voiceprint --yes, then deploy again.
several voices exist Pass --voice or run voiceprint use <name>.
Training finds little usable prose Add prose paragraphs; headings, code, tables, and outlines do not count.
The terminal disconnected during training Run voiceprint resume.

If the problem persists, open an issue with the command you ran and the full error output.

Contributing

Issues and pull requests are welcome. For local development:

uv pip install -e ".[dev]"
pytest

The prompt format and sampling defaults live in voiceprint/scaffold.py. tests/test_scaffold.py verifies that training and generation build prompts the same way.

Before opening a pull request, run the test suite and explain any behavior or default that changes. For larger changes, start with an issue so the approach can be discussed first.

Responsible use

Only train on your own voice or a voice you have explicit permission to use. Do not use Voiceprint for impersonation, deceptive accounts or reviews, or work that must be written without assistance. See the use policy.

License

MIT © Voiceprint contributors

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

voiceprint-0.1.0.tar.gz (41.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

voiceprint-0.1.0-py3-none-any.whl (39.0 kB view details)

Uploaded Python 3

File details

Details for the file voiceprint-0.1.0.tar.gz.

File metadata

  • Download URL: voiceprint-0.1.0.tar.gz
  • Upload date:
  • Size: 41.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for voiceprint-0.1.0.tar.gz
Algorithm Hash digest
SHA256 e5367f99acefc7769073fe28173d4e03005e922d4e53df1c6c3f06baa42e3fe6
MD5 574465aae3cab5247c956262b3fa9279
BLAKE2b-256 e5248f720344b2f9338355d8c833e6c999489f5a821fd1cacdb243c7e491db87

See more details on using hashes here.

Provenance

The following attestation bundles were made for voiceprint-0.1.0.tar.gz:

Publisher: release.yml on samzliu/voiceprint

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file voiceprint-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: voiceprint-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 39.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for voiceprint-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 10c9b081b352b6e80134a71c39b9ce9016272dc09653da5f2fb35e90ff13aa79
MD5 905f21b1865abe4ef1c507ae965eb8c8
BLAKE2b-256 298f501d82ffec07067a86e46a4c3ac7a065b22cd802af5f6cd155e48009471c

See more details on using hashes here.

Provenance

The following attestation bundles were made for voiceprint-0.1.0-py3-none-any.whl:

Publisher: release.yml on samzliu/voiceprint

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page