Smart Turn — बारी-समाप्ति पहचान

Smart Turn v3.2 VAD द्वारा विराम बताए जाने के बाद एक ही प्रश्न का उत्तर देता है: क्या वक्ता बोल चुका है, या वाक्य के बीच में है? यह ट्रांसक्रिप्ट के बजाय ऑडियो को ही सुनता है — प्रोसोडी, गति, स्वर-लहरी — 23 भाषाओं को कवर करता है, और हर विराम पर एक बार, बारी के अंतिम 8 सेकंड पर चलता है। वेट्स Pipecat की आधिकारिक Smart Turn v3.2 रिलीज़ (BSD-2-Clause) हैं, जो Apple प्लेटफ़ॉर्म के लिए CoreML में कंपाइल और Speech Core के लिए ONNX में एक्सपोर्ट किए गए हैं।

केवल VAD क्यों पर्याप्त नहीं है

वॉइस एक्टिविटी डिटेक्टर केवल मौन सुनता है। लोग सोचने के लिए वाक्य के बीच में रुकते हैं, इसलिए केवल VAD वाला एजेंट या तो उन्हें काट देता है या हर वाक्य के बाद लंबा, निश्चित टाइमआउट प्रतीक्षा करता है। Smart Turn हर विराम की पुष्टि करता है: पूरा हुआ वाक्य तुरंत उत्तर पाता है, वाक्य के बीच का विराम एजेंट को सुनते रहने देता है।

यह कैसे काम करता है

Smart Turn कोई VAD नहीं है और स्वयं वाक् का पता नहीं लगाता। इसे स्ट्रीमिंग Silero VAD के साथ जोड़ा जाता है, जो तय करता है कि कब पूछना है। क्लासिफ़ायर जुड़ने पर पुष्ट विराम निर्णय नहीं, बल्कि प्रश्न बन जाता है:

  1. हर विराम पर एक बार पूछें। जब Silero विराम की पुष्टि करता है (ऑफ़सेट सीमा के बाद minSilenceDuration), प्रोसेसर अब तक की बारी का ऑडियो क्लासिफ़ायर को देता है — VAD आरंभ से 0.5 सेकंड पहले से वर्तमान चंक तक, अधिकतम अंतिम 8 सेकंड।
  2. पूर्ण। संभावना threshold (0.5) पर या उससे ऊपर: .speechEnded सामान्य रूप से फ़ायर होता है।
  3. रोकें। सीमा से नीचे सेगमेंट खुला रहता है। यदि वक्ता फिर बोलता है, तो वही सेगमेंट जारी रहता है — दूसरा .speechStarted नहीं — और अगला पुष्ट विराम लंबी बारी के साथ फिर पूछता है।
  4. मौन की सीमा। यदि मौन maxSilenceDuration (2.0 सेकंड, विराम की शुरुआत से मापा गया) तक पहुँचता है, तो सेगमेंट वैसे भी समाप्त हो जाता है, ताकि धीरे-धीरे चुप होने वाले वक्ता को भी उत्तर मिले। सेगमेंट का endTime वहीं होता है जहाँ वाक् रुकी, न कि जहाँ सीमा समाप्त हुई।

flush() स्ट्रीम के अंत में रोके गए सेगमेंट को निपटाता है और reset() उसे साफ़ करता है। त्रुटि फेंकने वाला क्लासिफ़ायर "पूर्ण" माना जाता है, इसलिए विफल मॉडल बातचीत को कभी नहीं रोकता। isHoldingTurn रोक की स्थिति बताता है और lastTurnCompletionProbability सबसे हालिया उत्तर।

मॉडल

गुणमान
आर्किटेक्चरWhisper-Tiny एन्कोडर + अटेंशन पूलिंग + sigmoid आउटपुट वाला MLP हेड
पैरामीटर8.0M
इनपुट16 kHz मोनो ऑडियो के अंतिम 8 सेकंड (128,000 सैंपल); छोटी बारियों को आगे से शून्य से भरा जाता है, अन्य सैंपल रेट रीसैंपल किए जाते हैं
आउटपुट[0, 1] में संभावना कि बारी पूर्ण है; डिफ़ॉल्ट सीमा 0.5
भाषाएँ23 — Arabic, Bengali, Chinese, Danish, Dutch, English, Finnish, French, German, Hindi, Indonesian, Italian, Japanese, Korean, Marathi, Norwegian, Polish, Portuguese, Russian, Spanish, Turkish, Ukrainian, Vietnamese
लाइसेंसBSD-2-Clause

एक्सपोर्ट में Whisper का log-mel फ्रंट-एंड शामिल है, जिसमें वह वेवफ़ॉर्म सामान्यीकरण भी है जिस पर अपस्ट्रीम मॉडल को प्रशिक्षित किया गया था, इसलिए कॉलर कच्चा ऑडियो पास करते हैं — Swift या C++ में कोई फ़ीचर निष्कर्षण नहीं है।

प्रदर्शन

एक्सपोर्टआकारसटीकताप्रति 8-सेकंड विंडो विलंबता
CoreML (CPU + Neural Engine)16.8 MB92.9%3.5 ms
ONNX fp32 (ONNX Runtime, CPU)33 MB92.9%2 थ्रेड पर ~36 ms, 4 पर 20 ms
ONNX int8 (ONNX Runtime, CPU)11.1 MB93.0%2 थ्रेड पर ~36 ms, 4 पर 20 ms

सटीकता अपस्ट्रीम टेस्ट सेट की 1,000 क्लिप पर मापी गई है; CoreML और fp32 ONNX एक्सपोर्ट उन क्लिप पर अपस्ट्रीम fp32 मॉडल से पूरी तरह मेल खाते हैं। विलंबता Apple M5 Pro पर एक 8-सेकंड विंडो की है। प्रति विराम एक कॉल उस विराम में कुछ भी ध्यान देने योग्य नहीं जोड़ती जिसकी VAD पहले ही प्रतीक्षा कर चुका है।

Swift API

रिकॉर्ड किए गए कथन की एक बार की जाँच:

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
}

स्ट्रीमिंग VAD से जुड़ा हुआ, ताकि सेगमेंट समाप्त होने से पहले हर पुष्ट विराम की जाँच हो:

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 AudioCommon के TurnCompletionProvider प्रोटोकॉल का पालन करता है, इसलिए उसी आकार का कोई भी अन्य क्लासिफ़ायर इसकी जगह जोड़ा जा सकता है। fromPretrained(cacheDir:offlineMode:) अन्य मॉडलों के समान कैश और ऑफ़लाइन नियमों का पालन करता है।

VoicePipeline

VoicePipeline वही क्लासिफ़ायर स्वीकार करता है, इसलिए वॉइस एजेंट अपनी STT, TTS या VAD सेटिंग बदले बिना लोगों को बीच में टोकना बंद कर देता है। PipelineConfig के दो फ़ील्ड और एक मेथड इसे जोड़ते हैं; इनके लिए speech-swift v0.0.27 या नया (speech-core v0.0.14 का SpeechCore.xcframework) चाहिए।

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डिफ़ॉल्टप्रभाव
turnCompletionThreshold0.5पूर्णता की वह संभावना जिस पर या उससे ऊपर VAD विराम उपयोगकर्ता की बारी समाप्त करता है। क्लासिफ़ायर जोड़ने के बाद ही उपयोग होता है।
turnCompletionMaxSilence2.0 सेकंडविराम की शुरुआत से मापे गए मौन के सेकंड, जिनके बाद क्लासिफ़ायर द्वारा रोकी गई बारी भी समाप्त हो जाती है। 0 = कभी नहीं।
setTurnCompletion(_:)कोई भी TurnCompletionProvider जोड़ता है। इसे start() से पहले कॉल करें; अलग करने के लिए nil दें। त्रुटि फेंकने वाला क्लासिफ़ायर "पूर्ण" माना जाता है, इसलिए विफल मॉडल बातचीत को कभी नहीं रोकता।

क्लासिफ़ायर जुड़ा होने पर VAD विराम उपयोगकर्ता की बारी तभी समाप्त करता है जब संभावना थ्रेशोल्ड तक पहुँचे; उससे नीचे पाइपलाइन सुनती रहती है, दोबारा शुरू हुई बोली उसी बारी को जारी रखती है (दूसरा speechStarted नहीं आता), और turnCompletionMaxSilence रोकी गई बारी को वैसे भी समाप्त कर देता है। Eager STT भी इस रोक का पालन करता है, और क्लासिफ़ायर ऑडियो थ्रेड पर हर विराम में एक बार चलता है, इसलिए लोड करने के बाद prewarm() कॉल करें।

ट्यूनिंग

सेटिंगडिफ़ॉल्टप्रभाव
threshold0.5कम मान बारी जल्दी समाप्त करते हैं और अधिक बार टोकते हैं; अधिक मान उत्तर देने से पहले लंबी प्रतीक्षा करते हैं। बदलने से पहले वास्तविक बातचीत में lastTurnCompletionProbability देखें।
maxSilenceDuration2.0 सेकंडकठोर सीमा, विराम की शुरुआत से मापी गई। अस्वीकृत विराम बारी को इससे अधिक समय तक कभी नहीं रोक सकता। 0 सीमा को अक्षम करता है: रोका गया सेगमेंट तब वाक् या flush() की प्रतीक्षा करता है।
preRollDuration0.5 सेकंडVAD आरंभ से पहले का ऑडियो जो क्लासिफ़ायर इनपुट में शामिल होता है, ताकि कटा हुआ पहला अक्षर भी मॉडल तक पहुँचे।

Silero का minSilenceDuration अब भी तय करता है कि विराम की पुष्टि कब होती है, और इसलिए क्लासिफ़ायर से कब पूछा जाता है। लोड करने के बाद prewarm() कॉल करें ताकि पहले वास्तविक विराम को ग्राफ़ कंपाइलेशन की कीमत न चुकानी पड़े।

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
विकल्पकमांडविवरण
--thresholdturnवह संभावना जिस पर या उससे ऊपर बारी पूर्ण मानी जाती है (डिफ़ॉल्ट 0.5)
--jsonturnprobability, threshold, complete और latency_ms को JSON में देता है
--model, -mturnसमान लेआउट वाला HuggingFace रिपॉज़िटरी (डिफ़ॉल्ट aufklarer/Smart-Turn-v3.2-CoreML)
--model-dirturnsmart_turn.mlmodelc और config.json वाली स्थानीय डायरेक्टरी; डाउनलोड छोड़ देता है
--smart-turnvad-streamसेगमेंट समाप्त करने से पहले हर विराम की Smart Turn से पुष्टि
--turn-thresholdvad-streamSmart Turn पूर्णता सीमा (डिफ़ॉल्ट 0.5)
--turn-max-silencevad-streamअस्वीकृत विराम के बाद मौन के इतने सेकंड होने पर सेगमेंट वैसे भी समाप्त (डिफ़ॉल्ट 2.0)

speech turn फ़ाइल (कोई भी सैंपल रेट) लोड करता है, अंतिम 8 सेकंड को स्कोर करता है और संभावना, सीमा पार हुई या नहीं, तथा अनुमान समय प्रिंट करता है। अपनी रिकॉर्डिंग पर सीमा ट्यून करने के लिए इसका उपयोग करें। पूरी फ़्लैग सूची CLI संदर्भ में है।

C++ / Android

Speech Core वही मॉडल OnnxSmartTurn के रूप में Linux, Windows और Android के लिए देता है (केवल ONNX Runtime; कोई LiteRT संस्करण नहीं)। VoicePipeline::set_turn_completion() इसे start() से पहले जोड़ता है; फिर VAD विराम उपयोगकर्ता की बारी तभी समाप्त करता है जब संभावना turn_completion_threshold (0.5) तक पहुँचे, और turn_completion_max_silence (2.0 सेकंड) रोकी गई बारी को वैसे भी समाप्त कर देता है। C API वही हुक sc_turn_completion_vtable_t + sc_pipeline_set_turn_completion() के रूप में देता है, इसलिए Kotlin या Swift होस्ट अपना क्लासिफ़ायर 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);

Speech Core का speech CLI रिकॉर्डिंग को macOS की तरह ही स्कोर करता है:

speech download-models        # fetches the int8 graph with the other ONNX models
speech turn recording.wav --threshold 0.5 --json

मॉडल फ़ाइलें, C API अनुबंध और CLI Speech Core पेज और रिपॉज़िटरी के docs/models.md में प्रलेखित हैं।

मॉडल डाउनलोड

मॉडलबैकएंडआकारHuggingFace
Smart-Turn-v3.2CoreML16.8 MBaufklarer/Smart-Turn-v3.2-CoreML
Smart-Turn-v3.2ONNX (fp32 + int8)33 MB / 11.1 MBsoniqo/Smart-Turn-v3.2-ONNX

स्रोत