asr-phowhisper / README.md
ducdatit2002
Add portable PhoWhisper runtime
18ece05
|
Raw
History Blame Contribute Delete
12.6 kB
# PhoWhisper Runtime
Production runtime for PhoWhisper ASR API. This package is designed to be
portable: copy the prepared `phowhisper/` directory to another Linux host,
install Python dependencies, create `.env`, validate `models/`, then run
`server_api.py`. No training repository is required on the target host.
## Repository Contents
Runtime package contents:
- API/runtime code
- Post-processing rules
- Runtime configuration templates
- Model tokenizer/config metadata and prepared checkpoint directories under `models/`
- Optional ChunkFormer reference ASR package under `vendor/chunkformer/`
- Optional ChunkFormer launcher and checkpoint under `scripts/chunkformer.py` and `models/chunkformer-model/`
- Lightweight validation scripts
Not included in a clean git checkout unless restored through Git LFS or an
artifact bundle:
- Primary PhoWhisper and punctuation model weight files
- Optional base-model weight files
Not part of the portable runtime package:
- Environment secrets
- Uploaded audio
- Runtime outputs and logs
If you copy the whole prepared directory from a working machine, model weights
under `models/` are carried with it. If you clone from git, run `git lfs pull`
or restore the model artifact bundle before starting the API.
## 1. System Requirements
Minimum supported environment:
| Component | Requirement |
| --- | --- |
| OS | Ubuntu 22.04/24.04 LTS or compatible Linux x86_64 |
| Python | 3.12 |
| Audio tooling | `ffmpeg` |
| RAM | 16GB minimum, 32GB recommended |
| Disk | 15GB minimum for model artifacts and runtime cache |
| GPU | NVIDIA GPU recommended for production throughput |
CPU execution is supported for validation and low-volume workloads. Production traffic should use a CUDA-capable GPU with a PyTorch build matching the host driver.
Install host packages:
```bash
sudo apt-get update
sudo apt-get install -y git ffmpeg python3.12 python3.12-venv python3-pip
```
## 2. Deployment Layout
Recommended installation path:
```text
/opt/phowhisper
```
Create the deployment directory:
```bash
sudo mkdir -p /opt/phowhisper
sudo chown "$USER":"$USER" /opt/phowhisper
```
Clone the repository:
```bash
git clone <repo-url> /opt/phowhisper
cd /opt/phowhisper
```
Or copy a prepared runtime folder from another machine:
```bash
cd /path/to/source
tar \
--exclude='phowhisper/.env' \
--exclude='phowhisper/.venv' \
--exclude='phowhisper/tmp/*' \
--exclude='phowhisper/outputs/*' \
--exclude='*/__pycache__' \
-czf phowhisper-runtime.tar.gz phowhisper
tar -xzf phowhisper-runtime.tar.gz -C /opt
cd /opt/phowhisper
```
## 3. Python Environment
Use Conda when the target machine standardizes Python runtimes through Conda:
```bash
conda create -y -n phowhisper_runtime python=3.12
conda activate phowhisper_runtime
export PYTHONNOUSERSITE=1
python -m pip install -U pip setuptools wheel
python -m pip install -r requirements.txt
```
Use `venv` when Conda is not available:
```bash
python3.12 -m venv .venv
. .venv/bin/activate
export PYTHONNOUSERSITE=1
python -m pip install -U pip setuptools wheel
python -m pip install -r requirements.txt
```
Validate PyTorch and CUDA visibility:
```bash
PYTHONNOUSERSITE=1 python - <<'PY'
import torch
print("torch_version:", torch.__version__)
print("cuda_available:", torch.cuda.is_available())
print("cuda_device:", torch.cuda.get_device_name(0) if torch.cuda.is_available() else "cpu")
PY
```
If `cuda_available` is `False` on a GPU host, install the PyTorch wheel that matches the installed NVIDIA driver and CUDA runtime.
`PYTHONNOUSERSITE=1` is intentional. It prevents the runtime from importing packages from `~/.local` and makes dependency validation reflect the active environment only.
## 4. Model Artifacts
The runtime expects all model paths to live under `models/` unless overridden in
`.env`.
Required for normal API startup:
```text
models/phowhisper-merged/model.safetensors
models/punctuation-bartpho/model.safetensors
models/phowhisper-base/
```
`models/phowhisper-base/` must exist because the server uses its tokenizer and
configuration metadata. Its large `pytorch_model.bin` weight is only required
when the ASR checkpoint is used as a LoRA adapter or when a base-model fallback
is explicitly needed.
Required only when `PHOWHISPER_CRITICAL_COMPARE_PROVIDER=chunkformer`:
```text
models/chunkformer-model/pytorch_model.pt
models/chunkformer-model/config.yaml
models/chunkformer-model/global_cmvn
models/chunkformer-model/vocab.txt
models/chunkformer-model/tokenizer/
```
The runtime already includes `scripts/chunkformer.py` and `vendor/chunkformer/`,
so the target host does not need the original ChunkFormer training repository.
Pyannote diarization weights are resolved by `pyannote.audio` through Hugging Face. For online deployments, provide `HF_TOKEN`. For offline deployments, pre-populate the Hugging Face cache on the target machine or disable pyannote diarization in `.env`.
Package artifacts from the source machine:
```bash
cd /path/to/source/phowhisper
tar -czf phowhisper-model-artifacts.tar.gz \
models/phowhisper-merged/model.safetensors \
models/punctuation-bartpho/model.safetensors \
models/phowhisper-base \
models/chunkformer-model
```
Restore artifacts on the target machine:
```bash
cd /opt/phowhisper
tar -xzf /path/to/phowhisper-model-artifacts.tar.gz
```
Validate artifact placement:
```bash
. .venv/bin/activate
export PYTHONNOUSERSITE=1
python scripts/check_models.py
```
With Conda:
```bash
conda activate phowhisper_runtime
export PYTHONNOUSERSITE=1
python scripts/check_models.py
```
Expected output:
```text
model artifacts look ready
```
If you copied the entire prepared `phowhisper/` folder, this check is still the
source of truth. It confirms the copied model layout is usable before the server
loads large checkpoints.
## 5. Runtime Configuration
Create a local environment file:
```bash
cp .env.example .env
chmod 600 .env
```
Baseline configuration:
```env
PORT=8000
USE_NGROK=false
PHOWHISPER_ASR_MODEL_PATH=models/phowhisper-merged
PHOWHISPER_BASE_MODEL_PATH=models/phowhisper-base
PHOWHISPER_PUNCT_MODEL_PATH=models/punctuation-bartpho
PHOWHISPER_DOMAIN_CONFIG=configs/domain_correction.yaml
PHOWHISPER_CRITICAL_COMPARE_PROVIDER=none
PHOWHISPER_CHUNKFORMER_SCRIPT=scripts/chunkformer.py
PHOWHISPER_CHUNKFORMER_MODEL_PATH=models/chunkformer-model
PHOWHISPER_CHUNKFORMER_DEVICE=auto
PHOWHISPER_ENABLE_DURATION_CONFUSION_RULE=true
PHOWHISPER_USE_VAD=false
PHOWHISPER_TURN_MODE=off
PHOWHISPER_DIARIZATION_SIDECAR=true
PHOWHISPER_NUM_SPEAKERS=2
```
Keep `PHOWHISPER_CRITICAL_COMPARE_PROVIDER=none` for the fastest default API
path. Set it to `chunkformer` only when the secondary ASR comparison is needed.
`PHOWHISPER_ENABLE_DURATION_CONFUSION_RULE=true` can run independently of
ChunkFormer and fixes duration phrases such as `hai mươi lăm` in supported
duration contexts.
Pyannote configuration for mono speaker diarization:
```env
HF_TOKEN=<huggingface-token>
PHOWHISPER_ENABLE_PYANNOTE=true
PHOWHISPER_PYANNOTE_MODEL_ID=pyannote/speaker-diarization-community-1
PHOWHISPER_PYANNOTE_FALLBACK_MODEL_IDS=pyannote/speaker-diarization-3.1
```
Ngrok configuration, only when a public tunnel is required:
```env
USE_NGROK=true
NGROK_AUTHTOKEN=<ngrok-token>
NGROK_REGION=ap
NGROK_DOMAIN=
```
Do not commit `.env`. It may contain service tokens and deployment-specific paths.
## 6. Preflight Checks
Run syntax and artifact checks before starting the service:
```bash
. .venv/bin/activate
export PYTHONNOUSERSITE=1
python -m py_compile \
server_api.py \
scripts/chunkformer.py \
scripts/infer_audio.py \
scripts/check_models.py \
src/domain_correction/*.py \
src/punctuation/*.py \
src/turns/*.py
python scripts/check_models.py
```
## 7. Start The API
Foreground start:
```bash
. .venv/bin/activate
export PYTHONNOUSERSITE=1
python server_api.py
```
The service exposes:
```text
GET /health
POST /transcribe
POST /api/transcribe
POST /upload
```
Health check:
```bash
curl -fsS http://127.0.0.1:8000/health
```
Minimum healthy response fields:
```json
{
"status": "ok",
"asr_ready": true,
"punctuation_ready": true,
"domain_ready": true
}
```
## 8. API Usage
Multipart upload:
```bash
curl -X POST \
-F "file=@/path/to/audio.wav" \
http://127.0.0.1:8000/transcribe
```
Multipart upload with speaker count hint:
```bash
curl -X POST \
-F "file=@/path/to/audio.wav" \
-F "num_speakers=2" \
http://127.0.0.1:8000/transcribe
```
Supported request formats:
| Format | Field |
| --- | --- |
| multipart/form-data | `file` |
| multipart/form-data | `audio` |
| application/json | `audio_base64` |
Primary response fields:
| Field | Description |
| --- | --- |
| `text`, `full_transcription` | Final transcript after post-processing |
| `text_raw` | Raw ASR text |
| `segments` | Speaker turns returned to clients |
| `conversation_text` | Timestamped conversation transcript |
| `diarization_segments` | Raw diarization timeline |
| `elapsed_seconds` | End-to-end processing time |
## 9. CLI Inference
Single-file inference:
```bash
. .venv/bin/activate
export PYTHONNOUSERSITE=1
python scripts/infer_audio.py /path/to/audio.wav \
--turn-mode off \
--output-json outputs/result.json \
--output-text outputs/result.txt
```
VAD-based chunking:
```bash
export PYTHONNOUSERSITE=1
python scripts/infer_audio.py /path/to/audio.wav \
--vad \
--vad-max-segment-s 18 \
--output-json outputs/result.json
```
## 10. systemd Service
Create `/etc/systemd/system/phowhisper.service`:
```bash
sudo tee /etc/systemd/system/phowhisper.service >/dev/null <<'EOF'
[Unit]
Description=PhoWhisper Runtime API
After=network.target
[Service]
Type=simple
WorkingDirectory=/opt/phowhisper
Environment=PYTHONUNBUFFERED=1
Environment=PYTHONNOUSERSITE=1
ExecStart=/opt/phowhisper/.venv/bin/python /opt/phowhisper/server_api.py
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
```
Enable and start:
```bash
sudo systemctl daemon-reload
sudo systemctl enable phowhisper
sudo systemctl start phowhisper
sudo systemctl status phowhisper --no-pager
```
Logs:
```bash
journalctl -u phowhisper -f
```
Restart after code/config changes:
```bash
sudo systemctl restart phowhisper
```
## 11. Diarization Behavior
Default runtime flow:
1. Run ASR on the full audio to preserve transcript continuity.
2. Run pyannote as a sidecar diarization pass.
3. Align ASR timestamps to the diarization timeline.
4. Smooth short speaker blips.
5. Apply punctuation, capitalization, domain correction, money normalization and phone normalization.
Mono speaker diarization is probabilistic. Accuracy can degrade when speakers overlap, responses are very short, voices are similar, or the recording is heavily compressed. Stereo or dual-channel call recordings are preferred when available.
## 12. Artifact And Secret Policy
Do not commit secrets or runtime output:
```text
.env
tmp/
outputs/
```
Large model files should be copied as deployment artifacts or committed only
through Git LFS. This package intentionally allows
`models/chunkformer-model/pytorch_model.pt` through Git LFS when ChunkFormer is
part of the portable release.
Recommended artifact storage:
- Hugging Face Hub
- S3-compatible object storage
- Internal artifact registry
- Git LFS, only if the repository is explicitly configured for large files
Git LFS setup, if required:
```bash
git lfs install
git lfs track "*.safetensors" "*.bin" "*.pt" "*.pth" "*.ckpt"
git add .gitattributes
```
## 13. Troubleshooting
Port already in use:
```bash
lsof -tiTCP:8000 -sTCP:LISTEN -n -P
kill <pid>
```
Missing model artifacts:
```bash
python scripts/check_models.py
```
Pyannote fails to load:
- Verify `HF_TOKEN`.
- Confirm model access has been accepted on Hugging Face.
- Keep `PHOWHISPER_PYANNOTE_FALLBACK_MODEL_IDS=pyannote/speaker-diarization-3.1` enabled for compatibility fallback.
CUDA out of memory:
```env
PHOWHISPER_ASR_BATCH_SIZE=1
PHOWHISPER_PUNCT_BATCH_SIZE=1
```
CPU-only mode:
```env
PHOWHISPER_ASR_DEVICE=cpu
PHOWHISPER_PUNCT_DEVICE=cpu
```
CPU-only mode is intended for functional validation or low-throughput jobs.
## 14. Release Checklist
Before handing over a deployment:
```bash
. .venv/bin/activate
export PYTHONNOUSERSITE=1
python -m py_compile \
server_api.py \
scripts/chunkformer.py \
scripts/infer_audio.py \
scripts/check_models.py \
src/domain_correction/*.py \
src/punctuation/*.py \
src/turns/*.py
python scripts/check_models.py
curl -fsS http://127.0.0.1:8000/health
git status --short
git check-ignore -v .env
```