Skip to content

Commit 62b3aa6

Browse files
authored
feat: add executable CosyVoice lifecycle (#11)
1 parent 4399fe4 commit 62b3aa6

7 files changed

Lines changed: 919 additions & 3 deletions

File tree

.github/workflows/instavar-voice-contract.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ jobs:
1717
uses: actions/checkout@v5
1818
with:
1919
repository: instavar/instavar-voice-evaluation
20-
ref: 56b32c954e950fe915d4c6595c0630985576a9b7
20+
ref: d63ab559a8e0592bd373f9b51421040b540fb2b7
2121
path: .instavar-voice-evaluation
2222
- uses: actions/setup-python@v6
2323
with:
@@ -26,3 +26,7 @@ jobs:
2626
run: python .instavar-voice-evaluation/main.py validate-repository "$GITHUB_WORKSPACE"
2727
- name: Validate historical run evidence
2828
run: python .instavar-voice-evaluation/main.py validate historical historical-run.json
29+
- name: Validate executable lifecycle backend
30+
run: python .instavar-voice-evaluation/main.py validate-backend instavar-voice-backend.json
31+
- name: Test lifecycle wrapper without model dependencies
32+
run: python -m unittest tests/test_lifecycle_backend.py -v

INSTAVAR_VOICE_CONFORMANCE.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# Instavar Voice conformance
22

3-
This repository declares its model-specific adaptation and runtime surface in `instavar-voice-capabilities.json`. The manifest uses the public [Instavar Voice evaluation contract](https://github.com/instavar/instavar-voice-evaluation) pinned by CI to merge commit `56b32c954e950fe915d4c6595c0630985576a9b7`.
3+
This repository declares its model-specific adaptation and runtime surface in `instavar-voice-capabilities.json`. The manifest and executable [`instavar-voice-backend.json`](instavar-voice-backend.json) PyTorch LoRA recipe use the public [Instavar Voice evaluation contract](https://github.com/instavar/instavar-voice-evaluation) pinned by CI to merge commit `d63ab559a8e0592bd373f9b51421040b540fb2b7`.
4+
5+
The executable recipe proves that the external CosyVoice checkout equals its recorded upstream revision plus exactly the companion patch set. It applies explicit `MAX_EPOCH` and `LEARNING_RATE` values after loading the full model graph, audits grouped splits, selects one safe adapter, reloads it in a fresh process, evaluates the frozen plan, and packages evidence. A DeepSpeed run must use the same learning rate in its JSON optimizer configuration. The merged vLLM path remains outside this PyTorch lifecycle and needs a separate matched equivalence run.
46

57
Capability schema 1.2 records each LoRA lifecycle stage separately and preserves the six invalid emotion-control rows as a negative lifecycle result. It also names the exact blockers for a matched base-model comparison.
68

README.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,28 @@ The upstream `cosyvoice3.yaml` sets `max_epoch: 200`. If you pass a custom confi
186186

187187
## Evaluation
188188

189+
### Executable Instavar Voice lifecycle
190+
191+
[`instavar-voice-backend.json`](instavar-voice-backend.json) binds the PyTorch
192+
LoRA path to a five-stage executable recipe. Preflight verifies that the
193+
external CosyVoice checkout equals its recorded upstream commit plus exactly
194+
the four companion patches. The trainer now accepts explicit `--max_epoch` and
195+
`--learning_rate` overrides after loading the full HyperPyYAML model graph. The
196+
lifecycle requires both values, preventing the earlier 20-versus-200 epoch
197+
mismatch and an implicit optimizer-rate mismatch from recurring silently. For
198+
DeepSpeed, the JSON optimizer rate must equal `LEARNING_RATE`.
199+
Set `DEEPSPEED_CONFIG` only when `TRAIN_ENGINE=deepspeed`; the PyTorch DDP path
200+
does not require it.
201+
202+
The lifecycle audits grouped raw splits, writes model output under its unique
203+
work directory, promotes only one exact adapter directory, strips optimizer
204+
state from the inference package, reloads in a fresh process, runs the frozen
205+
evaluation plan, and packages provenance. Validate it with evaluator merge
206+
`d63ab559a8e0592bd373f9b51421040b540fb2b7`. Use the companion tools directly;
207+
do not copy them into the external checkout, because unexpected checkout files
208+
fail provenance verification. A pass covers the PyTorch adapter path only. The
209+
merged vLLM path still requires a separate matched equivalence lifecycle.
210+
189211
### Frozen multi-prompt runtime evaluation
190212

191213
Use `tools/run_evaluation_suite.py` to execute a complete Instavar Voice plan

instavar-voice-backend.json

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
{
2+
"schema_version": "1.2.0",
3+
"backend_id": "cosyvoice3-lora-pytorch",
4+
"capability_binding": {
5+
"manifest": "instavar-voice-capabilities.json",
6+
"adaptation": "lora",
7+
"runtime_ids": ["pytorch"]
8+
},
9+
"required_environment": [
10+
{ "name": "COSYVOICE_DIR", "purpose": "Pinned CosyVoice checkout with the exact companion patch set applied." },
11+
{ "name": "PRETRAINED_DIR", "purpose": "Pinned local Fun-CosyVoice3-0.5B runtime model directory." },
12+
{ "name": "BASE_LLM_CHECKPOINT", "purpose": "Pinned base llm.pt used to initialize LoRA training." },
13+
{ "name": "QWEN_PRETRAIN_DIR", "purpose": "Pinned CosyVoice-BlankEN tokenizer and configuration directory." },
14+
{ "name": "TRAIN_CONFIG", "purpose": "CosyVoice3 HyperPyYAML training configuration." },
15+
{ "name": "MAX_EPOCH", "purpose": "Explicit positive train_conf.max_epoch override applied after loading the full model config." },
16+
{ "name": "LEARNING_RATE", "purpose": "Explicit positive LoRA optimizer learning rate." },
17+
{ "name": "TRAIN_DATA_LIST", "purpose": "Prepared CosyVoice parquet training data list." },
18+
{ "name": "CV_DATA_LIST", "purpose": "Prepared CosyVoice parquet cross-validation data list." },
19+
{ "name": "RAW_TRAIN_JSONL", "purpose": "Raw training split used for grouped corpus audit." },
20+
{ "name": "RAW_VALIDATION_JSONL", "purpose": "Raw validation split used for grouped corpus audit." },
21+
{ "name": "RAW_TEST_JSONL", "purpose": "Raw test split used for grouped corpus audit." },
22+
{ "name": "REFERENCE_AUDIO", "purpose": "Authorized reference-speaker audio for reload and held-out synthesis." },
23+
{ "name": "REFERENCE_TEXT", "purpose": "Transcript matching the authorized reference audio." },
24+
{ "name": "SELECTED_ADAPTER_NAME", "purpose": "Single safe LoRA checkpoint directory selected for reload." },
25+
{ "name": "GENERATION_PLAN", "purpose": "Frozen Instavar Voice generation plan containing this candidate." },
26+
{ "name": "CANDIDATE_ID", "purpose": "Candidate identifier present in the frozen generation plan." },
27+
{ "name": "TRAIN_ENGINE", "purpose": "Explicit torch_ddp or deepspeed training engine." }
28+
],
29+
"commands": {
30+
"preflight": ["{python}", "scripts/instavar_voice_lifecycle.py", "preflight"],
31+
"train": ["{python}", "scripts/instavar_voice_lifecycle.py", "train"],
32+
"infer": ["{python}", "scripts/instavar_voice_lifecycle.py", "infer"],
33+
"evaluate": ["{python}", "scripts/instavar_voice_lifecycle.py", "evaluate"],
34+
"package": ["{python}", "scripts/instavar_voice_lifecycle.py", "package"]
35+
},
36+
"expected_artifacts": {
37+
"preflight": ["preflight/preflight.json"],
38+
"train": ["train/selected-adapter.tar"],
39+
"infer": ["infer/candidate.wav"],
40+
"evaluate": ["evaluate/evaluation-bundle.tar"],
41+
"package": ["package/adapter-package.tar"]
42+
},
43+
"timeout_seconds": {
44+
"preflight": 1800,
45+
"train": 86400,
46+
"infer": 3600,
47+
"evaluate": 21600,
48+
"package": 1800
49+
}
50+
}

0 commit comments

Comments
 (0)