Smart Turn — Phát hiện kết thúc lượt nói
Smart Turn v3.2 trả lời một câu hỏi duy nhất sau khi VAD báo có khoảng dừng: người nói đã nói xong hay đang ở giữa câu? Mô hình lắng nghe chính âm thanh — ngữ điệu, tốc độ, cao độ — thay vì bản chép lời, hỗ trợ 23 ngôn ngữ và chạy một lần cho mỗi khoảng dừng trên 8 giây cuối của lượt nói. Trọng số là bản phát hành Smart Turn v3.2 chính thức của Pipecat (BSD-2-Clause), được biên dịch sang CoreML cho nền tảng Apple và xuất sang ONNX cho Speech Core.
Bộ phát hiện hoạt động giọng nói chỉ nghe được khoảng lặng. Người ta hay dừng giữa câu để suy nghĩ, nên tác nhân chỉ dựa vào VAD sẽ hoặc ngắt lời họ, hoặc phải chờ một khoảng thời gian cố định khá dài sau mỗi câu. Smart Turn xác nhận từng khoảng dừng: câu đã nói xong được trả lời ngay, khoảng dừng giữa câu giữ cho tác nhân tiếp tục lắng nghe.
Cách hoạt động
Smart Turn không phải là VAD và không tự phát hiện giọng nói. Nó được ghép với Silero VAD dạng streaming, bộ này quyết định khi nào cần hỏi. Khi có bộ phân loại được gắn vào, một khoảng dừng đã xác nhận trở thành câu hỏi thay vì phán quyết:
- Hỏi một lần mỗi khoảng dừng. Khi Silero xác nhận khoảng dừng (
minSilenceDurationsau ngưỡng offset), bộ xử lý đưa cho bộ phân loại âm thanh của lượt nói tính đến lúc đó — từ 0,5 giây trước thời điểm VAD bắt đầu cho đến chunk hiện tại, tối đa 8 giây cuối. - Hoàn tất. Xác suất bằng hoặc vượt
threshold(0,5):.speechEndedphát ra như bình thường. - Giữ. Dưới ngưỡng thì đoạn vẫn mở. Nếu người nói tiếp tục, cùng đoạn đó tiếp diễn — không có
.speechStartedthứ hai — và khoảng dừng xác nhận tiếp theo sẽ hỏi lại với lượt nói dài hơn. - Giới hạn im lặng. Nếu im lặng đạt
maxSilenceDuration(2,0 giây, tính từ lúc bắt đầu dừng), đoạn vẫn kết thúc, nên người nói bỏ lửng câu vẫn nhận được phản hồi.endTimecủa đoạn là lúc giọng nói dừng, không phải lúc giới hạn hết hạn.
flush() chốt đoạn đang giữ khi luồng kết thúc và reset() xóa nó. Bộ phân loại ném lỗi được tính là "hoàn tất", nên mô hình gặp sự cố không bao giờ làm cuộc hội thoại bị kẹt. isHoldingTurn báo trạng thái giữ và lastTurnCompletionProbability cho biết câu trả lời gần nhất.
Mô hình
| Thuộc tính | Giá trị |
|---|---|
| Kiến trúc | Bộ mã hóa Whisper-Tiny + attention pooling + đầu MLP với đầu ra sigmoid |
| Tham số | 8,0M |
| Đầu vào | 8 giây cuối của âm thanh mono 16 kHz (128.000 mẫu); lượt nói ngắn hơn được đệm số 0 ở đầu, các tần số lấy mẫu khác được lấy mẫu lại |
| Đầu ra | Xác suất trong [0, 1] rằng lượt nói đã hoàn tất; ngưỡng mặc định 0,5 |
| Ngôn ngữ | 23 — Arabic, Bengali, Chinese, Danish, Dutch, English, Finnish, French, German, Hindi, Indonesian, Italian, Japanese, Korean, Marathi, Norwegian, Polish, Portuguese, Russian, Spanish, Turkish, Ukrainian, Vietnamese |
| Giấy phép | BSD-2-Clause |
Các bản xuất nhúng sẵn front-end log-mel của Whisper, bao gồm cả bước chuẩn hóa dạng sóng mà mô hình gốc được huấn luyện, nên bên gọi chỉ cần truyền âm thanh thô — không có bước trích xuất đặc trưng nào trong Swift hay C++.
Hiệu năng
| Bản xuất | Kích thước | Độ chính xác | Độ trễ mỗi cửa sổ 8 giây |
|---|---|---|---|
| CoreML (CPU + Neural Engine) | 16,8 MB | 92,9% | 3,5 ms |
| ONNX fp32 (ONNX Runtime, CPU) | 33 MB | 92,9% | ~36 ms với 2 luồng, 20 ms với 4 |
| ONNX int8 (ONNX Runtime, CPU) | 11,1 MB | 93,0% | ~36 ms với 2 luồng, 20 ms với 4 |
Độ chính xác đo trên 1.000 clip từ tập kiểm thử gốc; bản xuất CoreML và ONNX fp32 khớp hoàn toàn với mô hình fp32 gốc trên các clip đó. Độ trễ là một cửa sổ 8 giây trên Apple M5 Pro. Một lần gọi mỗi khoảng dừng không thêm gì đáng kể vào khoảng dừng mà VAD đã chờ sẵn.
API Swift
Kiểm tra một lần trên một phát ngôn đã ghi:
import SpeechVAD
let turn = try await SmartTurnModel.fromPretrained()
try turn.prewarm() // compile the graph before the first real pause
let probability = try turn.turnCompleteProbability(
audio: utterance, sampleRate: 16_000)
if probability >= SmartTurnModel.defaultThreshold {
// finished turn — reply now
}
Gắn vào VAD streaming, để mọi khoảng dừng đã xác nhận đều được kiểm tra trước khi đoạn kết thúc:
let vad = try await SileroVADModel.fromPretrained(engine: .coreml)
let turn = try await SmartTurnModel.fromPretrained()
let processor = StreamingVADProcessor(
model: vad,
config: .sileroDefault,
turnCompletion: turn,
turnCompletionConfig: TurnCompletionConfig(threshold: 0.5, maxSilenceDuration: 2.0))
for chunk in microphoneChunks { // Float32 @ 16 kHz
for event in processor.process(samples: chunk) {
switch event {
case .speechStarted(let time): print("speech at \(time)s")
case .speechEnded(let segment): print("turn \(segment.startTime)–\(segment.endTime)s")
}
}
}
let remaining = processor.flush()
SmartTurnModel tuân theo giao thức TurnCompletionProvider trong AudioCommon, nên có thể gắn bất kỳ bộ phân loại nào khác có cùng hình dạng thay thế. fromPretrained(cacheDir:offlineMode:) tuân theo cùng quy tắc bộ nhớ đệm và ngoại tuyến như các mô hình khác.
VoicePipeline
VoicePipeline nhận cùng bộ phân loại này, nên tác nhân giọng nói không còn ngắt lời người dùng mà không cần đổi gì trong thiết lập STT, TTS hay VAD. Chỉ cần hai trường của PipelineConfig và một phương thức; chúng yêu cầu speech-swift v0.0.27 trở lên (SpeechCore.xcframework từ speech-core v0.0.14).
import SpeechCore
import SpeechVAD
let smartTurn = try await SmartTurnModel.fromPretrained()
try smartTurn.prewarm()
var config = PipelineConfig()
config.turnCompletionThreshold = 0.5 // pause ends the turn when p >= this
config.turnCompletionMaxSilence = 2.0 // seconds of silence that end a held turn anyway; 0 = never
let pipeline = VoicePipeline(stt: stt, tts: tts, vad: vad, config: config, onEvent: { print($0) })
pipeline.setTurnCompletion(smartTurn) // before start(); nil detaches
pipeline.start()
| API | Mặc định | Tác dụng |
|---|---|---|
turnCompletionThreshold | 0,5 | Xác suất hoàn tất mà tại đó hoặc cao hơn, khoảng dừng của VAD sẽ kết thúc lượt nói của người dùng. Chỉ dùng khi đã gắn bộ phân loại. |
turnCompletionMaxSilence | 2,0 giây | Số giây im lặng, tính từ lúc bắt đầu khoảng dừng, sau đó lượt nói bị bộ phân loại từ chối vẫn kết thúc. 0 = không bao giờ. |
setTurnCompletion(_:) | — | Gắn bất kỳ TurnCompletionProvider nào. Gọi trước start(); truyền nil để tháo ra. Bộ phân loại ném lỗi được coi là "hoàn tất", nên mô hình hỏng không bao giờ làm cuộc trò chuyện bị kẹt. |
Khi đã gắn bộ phân loại, khoảng dừng của VAD chỉ kết thúc lượt nói của người dùng khi xác suất đạt ngưỡng; dưới ngưỡng, pipeline tiếp tục lắng nghe, giọng nói tiếp tục sẽ nối vào cùng lượt (không có speechStarted thứ hai), và turnCompletionMaxSilence vẫn kết thúc lượt đang giữ. Eager STT tôn trọng quyết định từ chối này, và bộ phân loại chạy một lần mỗi khoảng dừng trên luồng âm thanh, vì vậy hãy gọi prewarm() sau khi tải.
Tinh chỉnh
| Thiết lập | Mặc định | Tác dụng |
|---|---|---|
threshold | 0,5 | Giá trị thấp hơn kết thúc lượt sớm hơn và ngắt lời thường xuyên hơn; giá trị cao hơn chờ lâu hơn trước khi trả lời. Hãy theo dõi lastTurnCompletionProbability trên các hội thoại thật trước khi thay đổi. |
maxSilenceDuration | 2,0 giây | Giới hạn cứng, tính từ lúc bắt đầu dừng. Một khoảng dừng bị từ chối không bao giờ giữ lượt lâu hơn mức này. 0 tắt giới hạn: đoạn đang giữ sẽ chờ giọng nói hoặc flush(). |
preRollDuration | 0,5 giây | Âm thanh trước thời điểm VAD bắt đầu được đưa vào đầu vào của bộ phân loại, để âm tiết đầu bị cắt vẫn đến được mô hình. |
minSilenceDuration của Silero vẫn quyết định khi nào khoảng dừng được xác nhận, và do đó khi nào bộ phân loại được hỏi. Gọi prewarm() sau khi tải để khoảng dừng thật đầu tiên không phải trả giá cho việc biên dịch đồ thị.
Sử dụng CLI
# Probability, complete/incomplete verdict and inference time for one utterance
speech turn utterance.wav
# Custom threshold, JSON output
speech turn utterance.wav --threshold 0.7 --json
# Local bundle, no download
speech turn utterance.wav --model-dir ~/smart-turn-coreml
# Streaming VAD with Smart Turn confirming each pause; mid-sentence pauses merge
speech vad-stream call.wav --smart-turn
speech vad-stream call.wav --smart-turn --turn-threshold 0.6 --turn-max-silence 1.5
| Tùy chọn | Lệnh | Mô tả |
|---|---|---|
--threshold | turn | Xác suất từ mức này trở lên thì lượt nói được coi là hoàn tất (mặc định 0,5) |
--json | turn | Xuất probability, threshold, complete và latency_ms dưới dạng JSON |
--model, -m | turn | Kho HuggingFace có cùng cấu trúc (mặc định aufklarer/Smart-Turn-v3.2-CoreML) |
--model-dir | turn | Thư mục cục bộ chứa smart_turn.mlmodelc và config.json; bỏ qua bước tải |
--smart-turn | vad-stream | Xác nhận từng khoảng dừng bằng Smart Turn trước khi kết thúc đoạn |
--turn-threshold | vad-stream | Ngưỡng hoàn tất của Smart Turn (mặc định 0,5) |
--turn-max-silence | vad-stream | Số giây im lặng sau một khoảng dừng bị từ chối mà vẫn kết thúc đoạn (mặc định 2,0) |
speech turn tải tệp (mọi tần số lấy mẫu), chấm điểm 8 giây cuối và in ra xác suất, có vượt ngưỡng hay không, cùng thời gian suy luận. Dùng nó để tinh chỉnh ngưỡng trên bản ghi của chính bạn. Danh sách đầy đủ các cờ nằm trong tài liệu tham khảo CLI.
C++ / Android
Speech Core cung cấp cùng mô hình này dưới tên OnnxSmartTurn cho Linux, Windows và Android (chỉ ONNX Runtime; không có bản LiteRT). VoicePipeline::set_turn_completion() gắn nó trước start(); sau đó khoảng dừng của VAD chỉ kết thúc lượt nói của người dùng khi xác suất đạt turn_completion_threshold (0,5), và turn_completion_max_silence (2,0 giây) vẫn kết thúc lượt đang giữ. C API cung cấp cùng điểm móc nối qua sc_turn_completion_vtable_t + sc_pipeline_set_turn_completion(), nên host Kotlin hoặc Swift có thể nối bộ phân loại riêng của mình giống như với VAD.
#include <speech_core/models/onnx_smart_turn.h>
speech_core::OnnxSmartTurn model("/models/smart-turn-v3.2-int8.onnx");
// Audio of the turn so far at any rate (resampled to 16 kHz internally).
float p = model.turn_complete_probability(turn.data(), turn.size(), rate);
// Or let the pipeline ask it on every VAD pause (before start()).
pipeline.set_turn_completion(&model);
CLI speech của Speech Core chấm điểm bản ghi giống như trên macOS:
speech download-models # fetches the int8 graph with the other ONNX models
speech turn recording.wav --threshold 0.5 --json
Tệp mô hình, hợp đồng C API và CLI được mô tả trên trang Speech Core và trong docs/models.md của kho mã.
Tải xuống mô hình
| Mô hình | Backend | Kích thước | HuggingFace |
|---|---|---|---|
| Smart-Turn-v3.2 | CoreML | 16,8 MB | aufklarer/Smart-Turn-v3.2-CoreML |
| Smart-Turn-v3.2 | ONNX (fp32 + int8) | 33 MB / 11,1 MB | soniqo/Smart-Turn-v3.2-ONNX |
Nguồn
- Sources/SpeechVAD —
SmartTurnModelvàStreamingVADProcessor - docs/models/smart-turn-v3.md — ghi chú về mô hình
- docs/inference/smart-turn.md — suy luận và tinh chỉnh
- speech-core docs/models.md —
OnnxSmartTurn - Nguồn gốc: pipecat-ai/smart-turn / pipecat-ai/smart-turn-v3 (Daily / Pipecat, BSD-2-Clause)