Từ kích hoạt / Keyword Spotting
Module SpeechWakeWord chạy một bộ keyword spotter trên thiết bị: bạn đăng ký một danh sách các cụm từ, đẩy các chunk âm thanh vào, và nhận các phát hiện. Dựa trên streaming Zipformer transducer của icefall (3,49M tham số, Apache-2.0), được biên dịch sang CoreML với palettization INT8.
Checkpoint được phát hành là bản fine-tune KWS trên gigaspeech. Các từ khóa không phải tiếng Anh cần một bản fine-tune icefall riêng và xuất lại.
Kiến trúc
| Giai đoạn | Chi tiết |
|---|---|
| fbank | tương thích kaldi (25 ms / 10 ms, cửa sổ Povey, 80 mel bin, high_freq=-400, không CMVN) |
| Encoder | Zipformer2 nhân quả 6 giai đoạn (128 chiều), 45 mel frame vào → 8 frame ra (40 ms / frame) — 3,3 MB INT8 |
| Decoder | Transducer không trạng thái, vocab BPE-500, context size 2 — 525 KB FP16 |
| Joiner | Linear + tanh output projection — 160 KB INT8 |
| Decode | Beam search sửa đổi (beam=4) trên Aho-Corasick ContextGraph của các từ khóa người dùng |
Kích thước biên dịch trên đĩa: ~4 MB tổng cộng (encoder.mlmodelc + decoder.mlmodelc + joiner.mlmodelc). Bộ nhớ runtime: ~6 MB bao gồm các cache trạng thái encoder.
Hiệu năng
| Chỉ số | Giá trị | Ghi chú |
|---|---|---|
| RTF (CPU + Neural Engine) | 0,04 | 26× thời gian thực trên dòng M |
| Recall (12 từ khóa) | 88% | LibriSpeech test-clean, 158 phát ngôn dương |
| False positive / phát ngôn | 0,27 | 60 phát ngôn âm |
| CoreML INT8 vs PyTorch FP32 | 99% | Đồng thuận phát hiện |
Mặc định đã hiệu chỉnh: acThreshold=0.15, contextScore=0.5, numTrailingBlanks=1. Hỗ trợ ghi đè theo từng từ khóa.
Sử dụng CLI
Dạng cụm từ thuần (greedy BPE — hoạt động tốt cho các từ phổ biến):
speech wake recording.wav --keywords "hey soniqo"
speech wake recording.wav --keywords "hey soniqo:0.15:0.5" "cancel"
Dạng đã tokenize sẵn (kiểu sherpa-onnx — khuyến nghị khi bạn biết phân rã chính xác mà mô hình đã được huấn luyện):
# Định dạng: "phrase|piece1 piece2 ...:threshold:boost"
speech wake recording.wav \
--keywords "LIGHT UP|▁ L IGHT ▁UP:0.25:2.0"
# Nhiều từ khóa + đầu ra JSON
speech wake recording.wav \
--keywords "LIGHT UP|▁ L IGHT ▁UP:0.25:2.0" \
"LOVELY CHILD|▁LOVE LY ▁CHI L D:0.25:2.0" \
--json
Hoặc một tệp từ khóa, mỗi mục một dòng (# cho chú thích):
speech wake recording.wav --keywords-file keywords.txt
API Swift
import SpeechWakeWord
// Load mô hình với danh sách từ khóa của bạn.
let detector = try await WakeWordDetector.fromPretrained(
keywords: [
KeywordSpec(phrase: "hey soniqo", acThreshold: 0.15, boost: 0.5),
KeywordSpec(phrase: "cancel")
]
)
// Streaming: đẩy các chunk vào, tiêu thụ các phát hiện khi chúng kích hoạt.
let session = try detector.createSession()
for chunk in micAudioChunks { // Float32 @ 16 kHz
for detection in try session.pushAudio(chunk) {
print("[\(detection.time(frameShiftSeconds: 0.04))s] \(detection.phrase)")
}
}
// Batch: một lần duy nhất trên toàn bộ buffer.
let detections = try detector.detect(audio: samples, sampleRate: 16000)
KeywordSpec
| Trường | Ý nghĩa |
|---|---|
phrase | Cụm từ hiển thị, ví dụ "hey soniqo". Cũng được dùng làm nguồn cho mã hóa greedy BPE khi tokens là nil. |
acThreshold | Xác suất âm học trung bình bắt buộc trên đoạn được khớp. 0 → dùng mặc định đã hiệu chỉnh (0,15). |
boost | Boost ngữ cảnh theo từng token. Giá trị dương làm cụm từ dễ kích hoạt hơn. 0 → dùng mặc định đã hiệu chỉnh (0,5). |
tokens | Danh sách piece BPE tường minh tùy chọn. Khi non-nil, detector tra cứu từng piece trong tokens.txt của mô hình và bỏ qua bộ mã hóa greedy BPE. |
tokens đã tokenize sẵnVocab KWS icefall là BPE chữ hoa. Việc tokenize greedy của một cụm từ có thể chọn phân rã BPE khác với phân rã mô hình đã được huấn luyện để phát ra — "LIGHT UP" mã hóa greedy thành ▁LI GHT ▁UP nhưng phân rã huấn luyện là ▁ L IGHT ▁UP. Khi việc phát hiện trên giọng nói được tổng hợp bằng TTS hoặc giọng đọc sạch bỏ qua các kết quả khớp rõ ràng, hãy thử dạng đã tokenize sẵn kiểu sherpa-onnx.
Tải xuống mô hình
| Mô hình | Tham số | Kích thước | HuggingFace |
|---|---|---|---|
| KWS-Zipformer-3M | 3,49M | ~4 MB | aufklarer/KWS-Zipformer-3M-CoreML-INT8 |
Tích hợp pipeline
Module phơi ra một giao thức WakeWordProvider phản chiếu StreamingVADProvider, vì vậy một pipeline giọng nói có thể gate kích hoạt trên VAD, từ kích hoạt, hoặc cả hai. WakeWordStreamingAdapter bọc một detector đã load + một session đơn lẻ thành một đối tượng provider có thể tái sử dụng.
let adapter = try WakeWordStreamingAdapter(detector: detector)
// pipeline.configure(wakeWord: adapter)
Nguồn
- Sources/SpeechWakeWord — module Swift
- docs/models/kws-zipformer.md — ghi chú kiến trúc
- docs/inference/wake-word.md — pipeline suy luận
- Upstream: k2-fsa/icefall KWS recipe / pkufool/keyword-spotting-models