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.

Chỉ tiếng Anh

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ạnChi tiết
fbanktương thích kaldi (25 ms / 10 ms, cửa sổ Povey, 80 mel bin, high_freq=-400, không CMVN)
EncoderZipformer2 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
DecoderTransducer không trạng thái, vocab BPE-500, context size 2 — 525 KB FP16
JoinerLinear + tanh output projection — 160 KB INT8
DecodeBeam 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,0426× 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ôn0,2760 phát ngôn âm
CoreML INT8 vs PyTorch FP3299%Đồ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
phraseCụ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.
acThresholdXá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).
boostBoost 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).
tokensDanh 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.
Khi nào nên dùng tokens đã tokenize sẵn

Vocab 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ìnhTham sốKích thướcHuggingFace
KWS-Zipformer-3M3,49M~4 MBaufklarer/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