|
Download SOURCE_README.md from suvradeepp/tiny-hinglish-turn-detector: direct link, hf CLI and curl.
- Browser
- Download file 21.6 kB
-
https://huggingface.co/suvradeepp/tiny-hinglish-turn-detector/resolve/main/SOURCE_README.md
- Command line
-
hf download hf://suvradeepp/tiny-hinglish-turn-detector/SOURCE_README.md
-
curl -L -o SOURCE_README.md https://huggingface.co/suvradeepp/tiny-hinglish-turn-detector/resolve/main/SOURCE_README.md
21.6 kB
| # Tiny Hinglish Turn Detector | |
| An audio-native, low-latency **HOLD vs END** classifier for voice agents, built | |
| for the Shiprocket Data Scientist challenge. The model is evaluated only at VAD | |
| pause checkpoints: `HOLD` means “keep listening”; `END` means “the agent may | |
| respond.” | |
| The packaged artifact is a development preview: a 151,812-parameter causal | |
| TinyTCN using the most recent four seconds of audio. It exports to a 625,431-byte | |
| FP32 ONNX file and runs waveform-to-probability inference at 1.63 ms p95 on the | |
| measured Apple-arm CPU setup. It does **not** beat the acoustic logistic baseline | |
| on the current IID development split, and it has not been evaluated on the | |
| official test or on verified Hinglish speech. The repository is submission-grade | |
| engineering evidence, not a production-readiness claim. | |
| ## Current evidence, at a glance | |
| | Item | Status | What is actually established | | |
| |---|---|---| | |
| | Upstream train snapshot | Partial locally | 1 of 83 Parquet shards audited: 3,265 rows, 6.857 hours | | |
| | Data integrity on that shard | Measured | 3,265/3,265 valid; no exact-audio, ID, or label-conflict duplicates | | |
| | Split integrity | Measured, best effort | IID and source-held-out manifests pass observed-key crossing checks; all 3,265 groups are singletons because speaker/conversation/voice IDs are absent | | |
| | Interpretable development baseline | Measured, partial-shard only | 10 acoustic statistics: AP 0.7310, AUROC 0.7522, END recall 0.1313 at FPR 0.0181 | | |
| | TinyTCN preview | Measured, partial-shard only | 151,812 parameters: AP 0.6881, AUROC 0.7390, END recall 0.0625 at FPR 0.0181 | | |
| | Paired comparison | Baseline remains winner | TinyTCN minus baseline: AP −0.0429 (95% bootstrap CI −0.1195 to 0.0352); constrained recall −0.0688 (−0.1330 to −0.0122) | | |
| | Domain-shift stress | Measured, confounded | Source-held-out AP 0.5500/0.5368 for TinyTCN/baseline; both near chance in ranking, with wide nine-source bootstrap intervals | | |
| | Runtime/export | Measured | 611 KiB FP32 ONNX; exact PyTorch/ONNX parity; ONNX p95 0.956 ms neural-only and 1.629 ms waveform-to-probability | | |
| | Controller integration | Synthetic only | Metadata-bound 8-checkpoint/3-turn fixture emits 3 response edges with 0 duplicates; not model or product-quality evidence | | |
| | Code quality gate | Passed | Ruff 0.15.16; 136/136 automated tests passed via `unittest` discovery | | |
| | Accuracy/generalization | **Not established** | No full-corpus run, collected Hinglish recordings, real conversation replay, or official-test evaluation | | |
| | Publication tooling | Guarded | Hash-verified HF publisher plus curated Kaggle/GitHub upload builders; verify each remote runtime separately | | |
| The official test set remains deliberately sealed. The preview is real | |
| development evidence, but validation was reused for threshold selection, | |
| checkpoint selection, and bounded follow-up experiments. It is therefore | |
| adaptive development evidence—not an independent estimate. See | |
| [REPORT.md](REPORT.md) for the full reasoning and [MODEL_CARD.md](MODEL_CARD.md) | |
| for the release contract. | |
| The acoustic baseline is the first real-data development result: logistic | |
| regression on ten waveform statistics, trained on all 2,939 train rows and | |
| scored on all 326 validation rows in the single audited shard. At a threshold | |
| selected on that same validation split for `FPR <= 0.02`, it has 3 FP, 21 TP, | |
| 163 TN, and 139 FN (`FPR 0.0181`, END recall `0.1313`, AUROC `0.7522`, AP | |
| `0.7310`). The selected TinyTCN reaches 3 FP, 10 TP, 163 TN, and 150 FN at | |
| threshold `0.7410008` on the same split (`FPR 0.0181`, END recall `0.0625`, | |
| AUROC `0.7390`, AP `0.6881`, Brier `0.2133`). Its FPR bootstrap interval is | |
| `[0, 0.0407]`, so this sample does not establish a population 2% interruption | |
| bound. Neither result is independent-test or Hinglish evidence. | |
| Because that baseline is the evidence winner, its 10-weight JSON artifact is | |
| packaged beside the neural model under `reference_models/`; the Gradio Space | |
| continues to demonstrate the ONNX TinyTCN and labels that choice explicitly. | |
| ## Why this design | |
| Turn detection is asymmetric. A false `END` interrupts the user and can derail | |
| an entire transaction; a false `HOLD` adds latency. Accuracy at an arbitrary | |
| 0.5 threshold therefore is not the primary target. The selection criterion is | |
| **maximum END recall subject to a false-positive (false-interruption) budget**, | |
| with FPR reported at 1%, 2%, and 5% operating points. | |
| The production boundary is also explicit: | |
| ```text | |
| 16 kHz audio suffix | |
| -> 80-bin log-mel frontend | |
| -> causal depthwise-separable TinyTCN | |
| -> mask-aware attentive mean/std pooling | |
| -> END probability + optional filler auxiliary heads | |
| -> calibrated SPEAKING / HOLD / END controller | |
| ``` | |
| The selected preview has 151,812 parameters, six 128-channel blocks, and a | |
| four-second suffix. Its convolutions are causal; final attentive pooling makes | |
| this a suffix-level classifier, not a state-cached streaming network. The | |
| repository retains a larger 396,164-parameter/eight-second configuration as a | |
| proposed full-data experiment, not as the packaged model. The controller—not | |
| the neural network—owns minimum silence, threshold relaxation, debounce, and | |
| maximum wait. | |
| No ASR transcript is required at inference. That keeps the path small and | |
| avoids coupling endpoint latency to transcription, while the auxiliary | |
| `midfiller` and `endfiller` objectives encourage the representation to notice | |
| exactly the failure cases the challenge emphasizes. A Whisper-tiny teacher | |
| configuration is included as an experiment, not assumed to be the best serving | |
| model. | |
| ## Repository map | |
| | Path | Purpose | | |
| |---|---| | |
| | `src/turn_detection/data/` | Lazy Parquet/HF ingestion, schema normalization, audio audit, transitive grouping, split validation | | |
| | `src/turn_detection/models/` | Canonical log-mel frontend, TinyTCN student, Whisper teacher, attentive pooling | | |
| | `src/turn_detection/training/` | Lazy dataloaders, masked multitask loss, threshold calibration, product metrics, trainer | | |
| | `src/turn_detection/runtime/` | NumPy preprocessing, ONNX inference, turn controller, replay evaluation | | |
| | `configs/` | Reproducible student, teacher, and smoke configurations | | |
| | `scripts/` | Download, audit, split, train, evaluate, export, benchmark, package, publish | | |
| | `data/collection/` | Deterministic 900-recording Hinglish assignment plan; no recordings are included | | |
| | `reports/` | Measured one-shard audit and split reports | | |
| | `tests/` | Unit and integration coverage across data, model, metrics, runtime, and prompts | | |
| | `deployment/kaggle/` | Flat, standalone ONNX inference templates for Kaggle Models | | |
| | `upload-ready/` | Generated Kaggle and GitHub upload folders; never a source input | | |
| ## Reproduce the pipeline | |
| Python 3.10–3.12 and [`uv`](https://docs.astral.sh/uv/) are recommended. | |
| These commands target a full source checkout. Raw audio, downloaded Parquet, | |
| processed manifests, and per-example predictions are intentionally not | |
| redistributed; recreate them with the pinned download/audit commands below. | |
| ```bash | |
| uv sync --extra all | |
| uv run pytest | |
| ``` | |
| The curated public repository already includes the selected ONNX artifact, so | |
| the demo resolves it without an environment variable: | |
| ```bash | |
| uv sync --extra demo | |
| uv run python app.py | |
| ``` | |
| Place the Hugging Face token in the ignored `.env` file; never commit it: | |
| ```bash | |
| cp .env.example .env | |
| # edit .env and set HF_TOKEN | |
| ``` | |
| ### 1. Download the pinned train snapshot | |
| ```bash | |
| bash scripts/download_dataset.sh | |
| ``` | |
| The script pins revision | |
| `e564e2ac567f774d1880aa1db6ce97afb8c519b7`, resumes safely, and refuses to | |
| declare success until all 83 Parquet shards are present. | |
| ### 2. Audit and create manifests | |
| ```bash | |
| uv run python scripts/audit_dataset.py \ | |
| data/raw/smart-turn-data-v3.2-train \ | |
| --output data/processed/manifest.jsonl \ | |
| --report artifacts/data_audit.json \ | |
| --fail-on-error | |
| uv run python scripts/prepare_splits.py \ | |
| --input data/processed/manifest.jsonl \ | |
| --output data/processed/splits.jsonl \ | |
| --report artifacts/split_report.json \ | |
| --split train=0.9 --split validation=0.1 \ | |
| --stratify endpoint,language,synthetic,dataset | |
| ``` | |
| The audit hashes encoded audio and creates privacy-preserving linkage keys for | |
| conversation, speaker, voice, recording, prompt, record, and repeated normalized | |
| text. Union-find turns overlapping keys into transitive components; the split | |
| tool assigns whole components and fails validation if any group, audio hash, or | |
| metadata key crosses splits. | |
| On the available shard, however, upstream rows expose no usable speaker, | |
| conversation, or TTS-voice identity: all 3,265 base linkage groups used by the | |
| IID split contain one row. (The separate stress split deliberately regroups rows | |
| by 12 source-dataset values.) | |
| The measured split is therefore best-effort row-disjoint and duplicate-safe, | |
| **not speaker-disjoint**. Its grouped bootstrap is effectively a row bootstrap; | |
| speaker/voice leakage remains unknown until richer identity metadata or a new | |
| consented speaker-disjoint set exists. | |
| For a harsher domain-shift test, add `--holdout-field dataset`. Interpret that | |
| result carefully: in the currently inspected shard, source is strongly | |
| confounded with language and synthetic status. Leave-one-source-out helpers are | |
| also available in `turn_detection.data.splits`. | |
| ### 3. Prove the training path, then run the real experiment | |
| ```bash | |
| # Fast generated-feature integration check; never report as model quality. | |
| uv run python scripts/train.py --config configs/smoke.json --smoke-test | |
| # Reproduce the selected one-shard preview (development evidence only). | |
| uv run python scripts/train.py \ | |
| --config configs/partial_shard_warmstart_lr3e4_5ep.json | |
| # Proposed primary full-data student experiment, once all shards are audited. | |
| uv run python scripts/train.py --config configs/tiny_tcn.yaml | |
| ``` | |
| Run the interpretable partial-shard sanity baseline independently: | |
| ```bash | |
| uv run python scripts/run_baselines.py audio \ | |
| --manifest data/processed/partial-iid-splits.jsonl \ | |
| --source-root . \ | |
| --output artifacts/partial-baseline \ | |
| --epochs 1000 --fpr-budget 0.02 | |
| ``` | |
| The trainer writes the resolved configuration, epoch history, calibrated | |
| threshold, and best checkpoint. Deterministic mode seeds model initialization, | |
| data order, and training. Missing filler labels stay missing and are masked from | |
| their auxiliary BCE losses. | |
| ### 4. Evaluate without touching the official test | |
| ```bash | |
| uv run python scripts/evaluate.py \ | |
| --checkpoint artifacts/partial-shard-warmstart-lr3e4-5ep/best.pt \ | |
| --source data/processed/partial-iid-splits.jsonl \ | |
| --source-root . \ | |
| --split validation \ | |
| --output reports/partial_tinytcn_metrics.json | |
| ``` | |
| Evaluation reports confusion counts, FPR/FNR, AUROC, average precision, Brier | |
| score, ECE/reliability bins, operating points under FPR budgets, and | |
| language/source/synthetic slices. Turn-level interruption rates are emitted only | |
| when genuine turn/conversation IDs exist; this shard supports only a clearly | |
| labelled clip-normalized per-audio-hour proxy. Final comparisons need real | |
| speaker- or conversation-cluster confidence intervals. | |
| The selected checkpoint was chosen by average precision after earlier runs had | |
| already been inspected on this validation set. Its threshold was also selected | |
| on the same 326 examples. Reproduction should yield the stored numbers, but they | |
| must not be treated as a fresh holdout result. | |
| ### 5. Freeze, unseal once, and evaluate the official test | |
| Only an experiment trained with exact `run.status: final` can be frozen. The | |
| freeze manifest hashes the checkpoint, selected config, source tree, | |
| preprocessing, controller policy, split manifest, threshold, and pinned test | |
| identity. `configs/final.yaml` and `artifacts/final/*` below are intentionally | |
| future-candidate placeholders; create them only after completing the full-data | |
| experiment. Only then: | |
| ```bash | |
| uv run python scripts/freeze_candidate.py \ | |
| --checkpoint artifacts/final/best.pt \ | |
| --config configs/final.yaml \ | |
| --output artifacts/final/frozen_manifest.json | |
| UNSEAL_OFFICIAL_TEST=I_HAVE_FROZEN_MODEL_AND_THRESHOLD \ | |
| FROZEN_MANIFEST=artifacts/final/frozen_manifest.json \ | |
| bash scripts/download_test_dataset.sh | |
| uv run python scripts/evaluate.py \ | |
| --checkpoint artifacts/final/best.pt \ | |
| --source data/raw/smart-turn-data-v3.2-test \ | |
| --dataset-id pipecat-ai/smart-turn-data-v3.2-test \ | |
| --revision 0500378e8ed6d38e37b016e24d261e8e6c6a6859 \ | |
| --split test \ | |
| --allow-sealed-test \ | |
| --frozen-manifest artifacts/final/frozen_manifest.json \ | |
| --output artifacts/final/test_metrics.json | |
| ``` | |
| Do not tune after reading the test result. A new model requires a new untouched | |
| test set or a clearly labeled exploratory result. | |
| ### 6. Export and benchmark | |
| ```bash | |
| uv run python scripts/export_onnx.py \ | |
| --checkpoint artifacts/final/best.pt \ | |
| --output artifacts/final/model.onnx | |
| uv run python scripts/benchmark.py \ | |
| --model artifacts/final/model.onnx \ | |
| --metadata artifacts/final/model_metadata.json \ | |
| --threads 1 --batch-size 1 \ | |
| --output artifacts/final/cpu_benchmark.json | |
| ``` | |
| ONNX export checks PyTorch/ONNX numerical parity. Runtime preprocessing, | |
| I/O names, activation semantics, threshold, parameter count, and evidence scope | |
| live in `model_metadata.json`; hashes, shapes, checkpoint/config/split bindings, | |
| parity, and quantization status live in `export_manifest.json`. Static INT8 is | |
| supported with representative calibration features; quantized scores require | |
| threshold recalibration before release. | |
| The packaged preview is | |
| `artifacts/partial-shard-warmstart-lr3e4-5ep/model.onnx`: 625,431 bytes, | |
| 151,812 parameters, and FP32 maximum absolute parity error `0.0`. On the | |
| recorded Apple-arm/one-thread runs, ONNX neural-only p50/p95/p99 is | |
| 0.919/0.956/0.974 ms; four-second waveform-to-probability p50/p95/p99 is | |
| 1.572/1.629/1.651 ms. These are local implementation measurements, not a | |
| deployment SLA. | |
| ### 7. Run the demo and exercise the controller | |
| ```bash | |
| TURN_MODEL_PATH=artifacts/partial-shard-warmstart-lr3e4-5ep/model.onnx \ | |
| uv run python app.py | |
| uv run python scripts/replay_stream.py \ | |
| --input data/collection/controller_replay_fixture.jsonl \ | |
| --output reports/controller_replay_integration.jsonl \ | |
| --metadata artifacts/partial-shard-warmstart-lr3e4-5ep/model_metadata.json \ | |
| --evidence-scope synthetic_integration | |
| ``` | |
| The exported metadata binds the endpoint threshold and the complete controller | |
| policy. `END` is latched until new speech or an explicit reset; only the first | |
| END transition sets `emit_response=true`, preventing duplicate agent replies. | |
| The bundled replay fixture is hand-authored integration data: its probabilities, | |
| targets, and latency values are synthetic. It validates policy binding, | |
| threshold relaxation, timeout, END latching, and edge emission only—it is not | |
| model, conversation, latency, or product-quality evidence. Replace its input | |
| with private, human-annotated VAD checkpoint logs for a real sequence study. | |
| If weights are absent, the demo displays a conspicuous heuristic fallback. That | |
| fallback validates only the UI and must never be cited as a model result. See | |
| [docs/demo.md](docs/demo.md) for the pause-checkpoint contract. | |
| ### 8. Build and publish a guarded release | |
| ```bash | |
| uv run python scripts/build_release.py \ | |
| --model artifacts/final/model.onnx \ | |
| --metadata artifacts/final/model_metadata.json \ | |
| --metrics artifacts/final/test_metrics.json \ | |
| --frozen-manifest artifacts/final/frozen_manifest.json | |
| # Dry validation first. | |
| uv run python scripts/publish_hf.py --username suvradeepp | |
| # Creates/uploads the model repo and Gradio Space only after identity validation. | |
| uv run python scripts/publish_hf.py --username suvradeepp --execute | |
| ``` | |
| For a personal account without Hugging Face PRO, the publisher requests the | |
| free-account-compatible ZeroGPU tier (`--space-hardware zero-a10g`) only when it | |
| must create a new Space. Hugging Face currently gates new personal Gradio CPU | |
| Spaces behind PRO even when CPU Basic has no hourly charge. ZeroGPU eligibility | |
| still requires a verified account in good standing and an available hosted | |
| Space slot. Paid accounts may override this with `--space-hardware cpu-basic`. | |
| The release builder refuses smoke checkpoints or a release without measured | |
| test metrics unless `--allow-development-artifact` is passed explicitly. That | |
| override must remain visibly development-only. For a reviewable partial-data | |
| preview, pass that flag to the builder and `--allow-development-release` to both | |
| publisher invocations. Development validation metrics are packaged as | |
| `development_metrics.json`, never `test_metrics.json`. | |
| The exact development-preview package command is: | |
| ```bash | |
| uv run python scripts/build_release.py \ | |
| --model artifacts/partial-shard-warmstart-lr3e4-5ep/model.onnx \ | |
| --metadata artifacts/partial-shard-warmstart-lr3e4-5ep/model_metadata.json \ | |
| --metrics reports/partial_tinytcn_metrics.json \ | |
| --output release \ | |
| --allow-development-artifact \ | |
| --include-synthetic-controller-replay | |
| uv run python scripts/publish_hf.py \ | |
| --username suvradeepp \ | |
| --release-dir release \ | |
| --allow-development-release | |
| uv run python scripts/build_upload_folders.py \ | |
| --release-dir release \ | |
| --output upload-ready \ | |
| --allow-development-release | |
| ``` | |
| `upload-ready/kaggle-model/` is a flat drag-and-drop ONNX bundle. | |
| `upload-ready/github-repository/` is a public-repository allowlist containing | |
| source, CI, tests, aggregate evidence, ONNX weights, and the two checkpoints | |
| needed to reproduce the selected warm start. It excludes credentials, caches, | |
| raw/processed data, per-example predictions, stale releases, and publish | |
| receipts. Keep the Kaggle variation private until the derived-weight rights | |
| review described in `NOTICE` and `MODEL_CARD.md` is resolved. | |
| Add `--execute` only after the dry validation succeeds. The publisher verifies | |
| the authenticated owner and every packaged hash before creating or updating the | |
| remote model repository and Space. Its receipt binds exact remote HEAD commits, | |
| requires a visible build/start transition for a new Space upload, and records | |
| the final `RUNNING` stage. Because the installed Hub API does not expose the | |
| commit actually serving behind a Space runtime, the receipt explicitly records | |
| `runtime_commit_bound=false` instead of overstating that guarantee. | |
| The release hash-binds the 2.7 MB split manifest but intentionally does not | |
| redistribute it because it contains upstream text and record identifiers. The | |
| public package carries deterministic preparation code, the pinned revision, | |
| manifest SHA-256, and aggregate reports; per-example rows stay private. | |
| ## Hinglish evaluation protocol | |
| The upstream corpus is multilingual, but a `hin` or `eng` tag is not evidence | |
| of within-utterance code-switching. This repository therefore includes a | |
| separate, consent-first Shiprocket-domain protocol: | |
| - 30 speakers × 30 assignments = 900 intended recordings; | |
| - 450 `HOLD` and 450 `END` targets; | |
| - 21/4/5 speaker-disjoint train/dev/test speakers; | |
| - minimal pairs with natural 0.3–2.0 second internal pauses plus roleplay; | |
| - three annotators answer whether responding at the checkpoint feels like an | |
| interruption; uncertain votes remain disagreement, not forced labels. | |
| Only the assignments and protocol exist today—**no participant audio has been | |
| collected**. Do not infer Hinglish performance until that benchmark is recorded | |
| and evaluated. See [docs/data_collection_protocol.md](docs/data_collection_protocol.md) | |
| and [DATA_CARD.md](DATA_CARD.md). | |
| ## What “good enough” means | |
| A candidate is releaseable only after all of these gates pass: | |
| 1. all 83 train shards audited with zero unresolved hard validation errors; | |
| 2. group-safe validation and source/speaker stress tests completed; | |
| 3. threshold frozen under a predeclared false-interruption budget; | |
| 4. real Hinglish minimal-pair test collected with consent and held out by speaker; | |
| 5. official test opened once and reported without subsequent tuning; | |
| 6. preprocessing parity, ONNX parity, batch-1 CPU latency, and controller replay measured; | |
| 7. failure slices reviewed for language, source, synthetic/human, filler, duration, | |
| device/noise, gender/region where consented, and uncertainty; | |
| 8. upstream data/model redistribution terms reviewed before publishing weights. | |
| The current repository passes export/runtime engineering gates and supplies | |
| honest bounded development evidence. It does not pass the full-data, Hinglish, | |
| official-test, sequence-replay, or rights-review gates. | |
| ## Documentation | |
| - [Technical report](REPORT.md) | |
| - [Model card](MODEL_CARD.md) | |
| - [Data card](DATA_CARD.md) | |
| - [Experiment registry](docs/experiment_registry.md) | |
| - [Failure-analysis protocol](docs/failure_analysis.md) | |
| - [Hinglish collection protocol](docs/data_collection_protocol.md) | |
| - [Demo/runtime contract](docs/demo.md) | |
| ## License and responsible use | |
| Repository-authored code is Apache-2.0; see [LICENSE](LICENSE) and | |
| [NOTICE](NOTICE). The upstream | |
| dataset card did not provide an explicit dataset license at the inspected | |
| revision. This repository does not redistribute its audio. Apache-2.0 on the | |
| code does **not** grant rights to upstream audio, recordings collected under the | |
| local protocol, speaker likeness, customer data, or the development model | |
| weights. The preview weights carry no license grant pending an upstream-rights | |
| review; review data and derived-weight terms before use or redistribution. | |
| This system decides conversational timing; it should not be used for speaker | |
| identification, emotion inference, surveillance, or consequential decisions. | |