StreamPA / README.md
faeea's picture
Release frozen StreamPA seed 1337 with validated standalone inference
f8a1702 verified
|
Raw
History Blame Contribute Delete
10.4 kB
---
tags:
- speech
- pronunciation-assessment
- streaming
- whisper
- charsiu
language:
- en
license: other
---
# StreamPA
Frozen StreamPA pronunciation-assessment inference: fine-tuned Whisper Base
N-best -> G2P / prefix-local Charsiu / PCN / prosody -> slot and utterance scores.
This is a downloadable, multi-component Python system, not a hosted endpoint
or a standard Transformers `AutoModel`/`pipeline` implementation.
## Published identity
* Experiment: `M_stress_scalar_gate_capacity64` (Ours-M), primary seed **1337**.
* Original checkpoint SHA256:
`870df8dbe3c787487f094e0c4d4ade6bed8fcc5d86b578c4edc57581e81023b4`.
* All original tensors are retained losslessly in `scorer/model.safetensors`.
Strict loading retains the historical inactive `utt_head`; the active
utterance path is the frozen `gru_visible` head.
* 64 hidden dimensions, three local-attention blocks, four heads, scalar
reliability gate, detached stress branch, 64-dimensional recurrent state.
Inputs: 40 phone columns including epsilon, 14 global prosody features,
17 slot prosody features, and at most **72 PCN slots**.
* The included Whisper weights are the actual fine-tuned Base checkpoint,
SHA256 `8917c9612b44f73bb5ef2ffec48cf44a4ee0dfa5a94af25e9e6710b9fd66a17f`.
They must not be replaced with generic Whisper Base. Beam size 8, N-best 5,
maximum 128 decoded tokens; original hypothesis-score computation retained.
* The paper's four-seed aggregate (1337, 202601, 202602, 202603) is not the
performance of this single checkpoint. No unverified paper metric is copied
into this card. Interface tests do not establish assessment PCC.
## Download and install
Verified platform: **Python 3.10 on Ubuntu in local Windows WSL2, CPU FP32**.
Native Windows and GPU inference are not part of the verified platform.
Use a new Python 3.10 environment. The fixed release tag below is created only
after fresh Hub-download inference verification succeeds.
```bash
python3.10 -m venv .venv-streampa
source .venv-streampa/bin/activate
python -m pip install huggingface_hub==0.36.0
python -c "from huggingface_hub import snapshot_download; snapshot_download('faeea/StreamPA', revision='streampa-v1.0.0', local_dir='./StreamPA')"
cd StreamPA
python -m pip install --extra-index-url https://download.pytorch.org/whl/cpu -r requirements-lock.txt
python -m pip install --no-deps --no-build-isolation .
python scripts/setup_assets.py
python scripts/verify_bundle.py
```
The public bundle contains the scorer and fine-tuned Whisper weights. Setup
downloads Charsiu and G2P resources from official, **fixed revisions**, checks
their SHA256s, and installs them inside this bundle. There is no runtime
reference to a training checkout or private server. See `THIRD_PARTY_NOTICES.md`
for licenses and third-party weight terms. Internet is needed for initial
installation/setup, not for subsequent inference. No author token is required
for the public release or its official runtime resources.
## One WAV and streaming CLI
Input: your own English **mono 16,000-Hz WAV**, no transcript or labels.
The frontend supports at most 30 seconds per recording and 72 current PCN
slots; longer inputs return an explicit error/status, never hidden truncation.
Output files must not already exist.
```bash
python -m streampa.infer --audio /path/to/demo.wav --bundle-dir . --device cpu --output scores.json
python -m streampa.stream --audio /path/to/demo.wav --bundle-dir . --device cpu --output prefixes.jsonl
```
The single-file CLI returns all prefixes plus the EOF result. The streaming
CLI actually reads and appends waveform blocks, then signals EOF. Both run
the same causal implementation. CLI block size does not change the fixed
0.64-second schedule and 0.16-second lookahead.
For an appropriate CUDA installation, select one device externally and use
`--device cuda`. Do not use a broken/busy device. The inherited frontend uses
FP16 Whisper on CUDA, FP32 Charsiu/scorer; CPU is FP32 throughout. CUDA is
**untested in this release validation**, and changing precision can change ASR
decoding. The CPU lockfile deliberately selects CPU PyTorch.
## Python sessions
```python
import soundfile as sf
from streampa import StreamPAPipeline
pipeline = StreamPAPipeline('./StreamPA', device='cpu', threads=2)
session = pipeline.create_session()
with sf.SoundFile('demo.wav') as f:
assert f.samplerate == 16000 and f.channels == 1
while True:
block = f.read(1600, dtype='float32') # 100 ms received audio
if len(block) == 0:
break
for result in session.append(block):
print(result['audio_end'], result['status'], result['scores'])
print(session.finish()) # process the exact EOF, including a short final block
session.reset() # required before a new recording in this session
assert session.current() is None
```
The pipeline owns frozen models; sessions have separate audio and recurrent
state. Use sessions sequentially (concurrent GPU service scheduling is not
provided). `StreamPAPipeline.from_pretrained(repo_id, revision=...)` is also
implemented, but its downloaded directory must have `setup_assets.py` run
before loading; use the explicit local-bundle example for first setup.
## JSON and state semantics
* `commit_time`: scheduling boundary; `audio_end`: exact prefix waveform end
supplied to **every** frontend; `received_audio_end`: audio received by the
caller so far, which may be later when a block spans multiple boundaries.
A normal prefix is processed only after `commit_time + 0.16` is received.
EOF alone defines the final endpoint. No reference boundary is consulted.
* `slots`: raw independent phone-head and word-head predictions per current
PCN slot, ASR word assignment, slot time, validity and commitment masks.
Epsilon/gap slots are retained; `valid_phone=false` means their phone score
is not a localized phone assessment. `asr_word_id=-1` has no word assignment.
* `words`: mean **word-head** predictions over visible slots assigned to each
current ASR word. This is a presentation aggregation, not mean phone accuracy.
It is not the paper's offline reference-word-identity evaluation. ASR words
and scores may be revised at later prefixes, including committed words.
* `new_commit_mask`: the frozen legacy boundary-aware state-update rule.
Only newly committed word representations are consumed by the GRU. With
no new words the persistent state remains unchanged, but visible features
still enter the sentence head and may change current utterance scores.
This heuristic has **no formal exactly-once guarantee** for every possible
mixed predecessor merge. It is not silently replaced with a corrected rule.
* `scores.utterance_network_raw` retains native model outputs, including the
untrained completeness dimension for audit only. Displayed utterance scores
omit completeness. ASR confidence is not a probability of correct pronunciation.
* Historical target normalization divides all source scores by 5: native
word/utterance source scores span 0--10; phone source scores span 0--2.
Thus displayed 0--5 word/utterance = network output x 2.5, and phone = network
output x 12.5. Outputs are **not clipped**; out-of-range estimates remain
visible. Stress has a trained head but is not a calibrated correctness probability.
* `status != 'ok'` returns `scores=null`, never a false zero grade. Statuses
include empty/too-short/silent audio, no usable hypothesis, G2P/alignment/
acoustic failures, nonfinite values and unsupported slot length. Failed
prefixes remain in the output; previously successful state is preserved.
* `stages` and `wall_time_sec` measure actual local computation, not capture
waiting or a universal real-time guarantee. Model loading is separate.
## Offline operation and checks
```bash
python scripts/setup_assets.py --offline
HF_HUB_OFFLINE=1 TRANSFORMERS_OFFLINE=1 python -m streampa.infer --audio /path/to/demo.wav --bundle-dir . --device cpu --output offline_scores.json
python -m pytest tests -q
```
Keep the entire prepared bundle, including `charsiu/` and `assets/nltk_data/`.
Do not delete those setup-generated directories when preparing an offline copy.
For hash mismatch, stop and re-download the specified revision rather than
replacing a resource with another model. Missing G2P/tagger resources require
`setup_assets.py`; inference does not intentionally download them. Proxy
configuration may be needed during setup in restricted networks. Use a fresh
output filename for each command. Convert sample rate/channels before opening
a session; the inference entry point does not resample a hidden full recording.
## Scope and limitations
Inference accepts audio only. Training used human annotations and teacher
supervision. Historical evaluation data were selected by preprocessing filters
and predominantly contain read speech. Deployment removes the historical
reference-phone-count ratio filter and uses received-audio/EOF scheduling;
it does not claim to reproduce historical test membership or PCC on arbitrary
WAVs. The frozen dictionary is a corpus-derived pronunciation vocabulary, not
an utterance-specific reference transcript. Original PCN gap semantics,
alignment, normalization, repetition filtering and legacy commitment are retained.
No claim of validated spontaneous/open-ended speech generalization, formal
exactly-once commitment, GRU-induced stability improvement, or end-to-end
real-time performance is made. Synthetic validation clips test computation
and interfaces, not pronunciation-assessment accuracy. See
`validation_summary.json` for actually completed and untested checks.
Observed interface-test limitation: several short prefixes produce repeated
Whisper hypotheses and are explicitly unscorable. A synthetic "Good morning"
clip was unscorable at all three prefixes; three separately selected licensed
read-speech clips all produced valid EOF scores, with 9 valid prefixes out of
15 attempted. These failures were not hidden or repaired by changing decoding.
CPU frontend computation was much slower than the audio duration in these tests.
The old v6 47-feature system remains historical only at
`faeea/StreamPA`, revision `legacy-v6-before-streampa`. It is not this checkpoint
and must not be mixed with these configurations or entry points.