One-command training
Status: proposed decision for U1. This document defines a CLI workflow; it does not implement or change behavior.
Goal
Given a WAV directory, pronunciation dictionary, and prompt list, create a valid pstrain project and run a useful training target with one command:
pstrain train ./model \
--audio ./wav \
--prompts ./prompts.txt \
--dictionary ./dictionary.dict
The command is orchestration over the existing setup, validation, and build library boundaries. It must not introduce a second setup implementation or a second training pipeline.
Input contract
Required inputs are:
PROJECT_DIR, the new or resumable project directory;--audio DIR, containing.wavfiles recursively;--prompts FILE, mapping file IDs to prompt text; and--dictionary FILE, the pronunciation lexicon.
The preferred prompt format is leading-ID text, one utterance per line:
fileid WORDS. File IDs may include relative directory components and must
match WAV paths below --audio after removing .wav. The command may also
accept Sphinx transcript form and explicit --prompt-format, using the
existing parser/converter rather than shell transformations. Format detection
must fail when ambiguous.
Sensible defaults are:
experiment
default;profile
default;target
cd-8g, which gives a usable context-dependent model;deterministic split policy from the selected canonical profile (currently 95 percent training and seed 42 in the active pipeline defaults);
copy inputs into the project for portability;
extract the phoneset from the main and default filler dictionaries;
validate before scheduling work; and
runner auto-parallelism, with
-j/--jobsas an invocation override.
The full proposed surface is:
pstrain train PROJECT_DIR --audio DIR --prompts FILE --dictionary FILE
[--target TARGET] [--profile NAME] [--experiment NAME]
[--phoneset FILE] [--filler-dict FILE]
[--prompt-format auto|leading-id|sphinx|tsv|csv]
[--link-audio] [--resume] [--force] [-j N]
[--normalize-with POLICY] [--normalization-report FILE]
[--dry-run] [--json]
--resume means preserve the project inputs and continue the dependency-aware
build. --force retains the build command’s meaning of rebuilding reachable
tasks; it must not imply overwriting source corpus files. Replacing existing
inputs needs a separately explicit setup choice if supported. --dry-run
shows setup writes, validation, resolved configuration, and the build plan.
When combined with --json, standard output contains one JSON result document
and the human-readable build plan is written to standard error.
Pre-normalized prompts are the default
Prompt lists are assumed pre-normalized. Built-in normalization is opt-in only and must match the lexicon’s conventions. A normalizer that diverges from the lexicon silently manufactures out-of-vocabulary words.
Therefore the default path parses and validates text but does not change word spelling, case, punctuation, Unicode form, number expansion, or token boundaries. Validation compares prompt tokens exactly with dictionary lookup semantics and emits an OOV report. It surfaces likely normalization/lexicon mismatches—such as systematic case differences or punctuation-attached tokens—as diagnostics, not automatic fixes.
--normalize-with POLICY is an explicit transformation. A policy is named,
versioned, described before execution, and checked against the selected
lexicon. The command writes both the original and transformed prompt hashes,
the policy/version, and an OOV before/after report. It refuses a policy whose
declared casing or token conventions conflict with the lexicon unless the user
chooses a future, separately explicit override. A generic silent
--normalize switch is not sufficient.
The committed ARCTIC benchmark already proves this principle. Its training and
decoder transcripts are normalized, committed inputs with authenticated
hashes, paired with the exact dictionary used for measurement. The harness
does not reinterpret raw txt.done.data at run time. pstrain train should
apply the same committed-transcript pattern to ordinary projects: preserve the
prepared prompt list as an input artifact and record its identity.
Handoff to setup and build
The orchestration sequence is:
Parse arguments and resolve all source paths without writing.
Parse prompts, inventory WAV file IDs, load the dictionary, and produce a validation report: duplicate IDs, missing or extra audio, malformed entries, empty prompts, dictionary parse errors, phone errors, and OOV tokens with counts and example utterances.
If opt-in normalization was requested, transform into a separate staged prompt artifact, rerun the same validation, and retain both reports.
Call the setup library to create the project, install inputs, install or extract phoneset/filler resources, write canonical configuration, and retain the pre-normalized prompt identity.
Run project validation. No training task starts if validation has errors.
Construct
PipelineContextthrough the canonical resolver and hand the selected target to the existing dependency-aware build pipeline. Setup, split, features, and all model stages remain owned by their current library functions.On success, print the model path, resolved profile, target, experiment, elapsed summary, and the commands for resuming, testing, and inspecting configuration.
This sequence also removes a named defect in the current README quickstart:
the user must run an awk command and mv to rewrite the held-out
leading-ID transcript into Sphinx decoder form before pstrain test.
One-command training should produce correctly typed training and decoder
transcript artifacts at the split boundary. Users should never mutate a split
artifact in place to satisfy a later consumer.
Failure UX
Failures are grouped before work begins where possible. Human output starts with the blocking cause, then the affected count and a bounded sample. Full details go to stable report files under the project’s reports directory or to an explicitly requested path. JSON output uses stable error codes.
Important cases include:
prompt IDs with no WAV and WAVs with no prompt;
duplicate or unsafe IDs;
unsupported sample rates or inconsistent WAV properties;
malformed dictionary entries or phones outside the phoneset;
exact OOV tokens, counts, and example utterance IDs;
likely case, punctuation, or Unicode convention mismatches, labeled as suggestions rather than corrections;
an existing project whose installed inputs differ from the requested inputs;
unknown profile or target, with discoverable alternatives; and
interrupted builds, with an exact resume command.
No partial training begins after an input validation failure. Setup writes should be staged and committed atomically enough that a failure leaves either the old usable project or a resumable new project. Native or training failures retain the pipeline’s failed task name and logs rather than being collapsed to “training failed.”
CLI verb choice
Three shapes are plausible:
pstrain setup ...followed bypstrain build ...preserves existing primitives but does not meet the one-command goal.pstrain create ...followed bypstrain run ...is regular and leaves room for non-training workflows, but exposes two new verbs and still makes the common first-run path multi-command.pstrain train ...composes setup, validation, and build in one intent-level verb while leaving the lower-level commands available.
Recommendation: add pstrain train. “Train” is the outcome users seek, maps
directly to the required three inputs, and can resume through the existing
pipeline. Document setup, validate, and build as advanced/decomposed
equivalents. Do not make train a shell subprocess chain; call the shared
libraries so errors, dry-run output, and provenance remain structured.
Compatibility and rollout
The first release should create the same directory layout and build outputs as
manual setup plus build. Existing projects remain operable with pstrain build; pstrain train PROJECT --resume ... may adopt them only after config
migration and input-identity checks succeed. The command should initially
target the canonical configuration work from C1/C2 rather than encode the
current two-schema split.
Documentation should replace the quickstart’s manual transcript conversion
with pstrain train, while retaining a decomposed example for debugging and
automation. Tests should compare the one-command project and output plan with
the equivalent setup/build calls and verify that the default path never calls
a normalizer.
Open decisions for Kevin
Default target. The selected default is
cd-8g, a useful context-dependent model.ci-1gremains available as an explicit target for users who only need the bootstrap stage.Prompt syntax. Recommendation: make leading-ID text canonical, accept Sphinx/TSV/CSV through explicit or unambiguous detection, and store typed training and decoder derivatives. Supporting many formats is convenient but increases ambiguity and quoting edge cases.
Input ownership. Recommendation: copy prompts and dictionary, copy audio by default, and offer
--link-audio. Copying is portable and reproducible; linking avoids large duplication but lets external changes invalidate a project.OOV policy. Recommendation: any OOV blocks training by default, with a complete report and a future explicit threshold override if needed. A permissive default gets farther but can drop or fail utterances deep in the engine.
Normalization policy registry. Recommendation: ship no implicit default; add only named policies with documented lexicon compatibility. A bundled general-English normalizer is convenient but cannot truthfully match arbitrary user lexicons.
Existing destination behavior. Recommendation: require
--resumefor a compatible project and a separate explicit replacement option for changed inputs. Treating any existing directory as resumable risks mixing corpora; always refusing it makes recovery unnecessarily awkward.Default split. Recommendation: inherit the selected canonical profile rather than hard-code a train-specific default. A fixed CLI default is easier to explain but creates another configuration surface that can drift.