p99 และ VAP — โมเดลผลัดกันพูด

p99 ประเมินความน่าจะเป็นที่ผู้พูดจบเทิร์นจากเสียงช่องเดียว ส่วน VAP คาดการณ์กิจกรรมเสียงพูดจากช่องผู้ใช้และเอเจนต์ที่ตรงเวลากัน แอปเป็นผู้ตัดสินใจว่าจะตอบหรือพูดแทรกเมื่อใด

บิลด์ SDK จากซอร์สเพื่อใช้ API เหล่านี้ Swift ใช้ SpeechVAD ส่วน C++ ต้องเปิด SPEECH_CORE_WITH_ONNX=ON และ API ของ Android ใช้ ONNX Runtime ค่าเริ่มต้นของกระบวนการเดิมยังคงเดิม

โมเดล

p99 turn-1-mini5.3M · CoreML · Float3216 kHz · 160 ms · 1 chApache-2.0
VAP (otoSpeech)5.8M · CoreML / ONNX · Float3216 kHz · 20 s · 2 chCC BY 4.0 / MIT

Swift API

p99 เก็บข้อมูลที่ยังไม่ครบขั้นไว้ในบัฟเฟอร์ แต่ละขั้น 160 ms คืนค่าแปดเฟรมขนาด 20 ms ใช้ availableAfterSeconds เป็นเวลาตัดสินใจ และรีเซ็ตเซสชันระหว่างบทสนทนา

import SpeechVAD

let p99 = try await P99TurnModel.fromPretrained()
let session = try p99.createSession()
let frames = try session.pushAudio(pcm16k)
for frame in frames {
    print(frame.probability, frame.availableAfterSeconds)
}
try session.reset()

let vap = try await VAPModel.fromPretrained()
let forecast = try vap.forecast(userAudio: userPcm, agentAudio: agentPcm)
print(forecast.pNow, forecast.pFuture, forecast.voiceActivity)

VAP ใช้เสียง 16 kHz ในช่วง 20 วินาทีล่าสุด ทั้งสองช่องต้องยาวเท่ากัน และใช้ช่องศูนย์เมื่อเอเจนต์เงียบ อินพุตสั้นจะเติมความเงียบด้านหน้า ทุกครั้งจะคำนวณทั้งหน้าต่างใหม่ จึงควรเลือกช่วงเรียกให้เหมาะกับอุปกรณ์

C++

#include <speech_core/models/onnx_vap.h>

speech_core::OnnxVap model("models/vap.onnx");
auto forecast = model.forecast(user.data(), agent.data(), user.size(), 16000);
// p_now[0]: user, p_now[1]: agent
// p_future and voice_activity use the same channel order.

Android

val directory = ModelManager.ensureVapModels(context)
withContext(Dispatchers.Default) {
    VoiceActivityProjection(VoiceActivityProjectionConfig(directory)).use { model ->
        val forecast = model.forecast(userPcm, agentPcm)
        println(forecast.userNearTerm)
        println(forecast.agentNearTerm)
    }
}

ดาวน์โหลด

ผลการทดสอบ

TurnBench · Soniqo

สัญญาอนุญาต