import type { ModelId } from "./model-scores"; export const SCORE_MODELS: Record = { maai: { name: "VAP / MaAI", family: "活动预测", color: "#8866b2", directory: "maai-ch-kyoto", thresholds: [.11, .5, .8], defaultThreshold: .5, defaultVisible: true, description: "1 − 用户近期发声分数;约每 100 ms 更新,不是校准的 EOT 概率。" }, smart_turn: { name: "Smart Turn", family: "话轮检测", color: "#278d95", directory: "smart-turn-v3.2", thresholds: [.5, .8], defaultThreshold: .5, defaultVisible: true, description: "完成倾向;最近最多 8 秒用户音频,每 200 ms 更新。" }, silero_vad: { name: "Silero VAD", family: "活动预测", color: "#c47b32", directory: "silero-vad", thresholds: [.5, .8], defaultThreshold: .5, defaultVisible: false, description: "1 − 发声概率;每 32 ms 更新,仅为非发声基线,不是语义 EOT 概率。" }, livekit_mini: { name: "LiveKit v1-mini", family: "话轮检测", color: "#5378c4", directory: "livekit-v1-mini", thresholds: [.355, .5, .8], defaultThreshold: .355, defaultVisible: false, description: "P(turn ended);最近 1.2 秒用户音频,每 200 ms 更新。0.355 为中文参考阈值。" }, turnsense: { name: "TurnSense 1.0", family: "话轮检测", color: "#b65378", directory: "turnsense-1.0", thresholds: [.5, .8], defaultThreshold: .5, defaultVisible: true, description: "FP32 · P(complete);最近 8 秒用户音频,每 200 ms 更新。参考线不等同原生三分类 argmax。" }, }; export const SCORE_MODEL_IDS = Object.keys(SCORE_MODELS) as ModelId[]; export interface ScorePreferences { visibility: Record; thresholds: Record } export function readScorePreferences(value: unknown): ScorePreferences { const saved = value && typeof value === "object" && "version" in value && value.version === 1 ? value as { visibility?: Record; thresholds?: Record } : {}; return { visibility: Object.fromEntries(SCORE_MODEL_IDS.map(id => [id, typeof saved.visibility?.[id] === "boolean" ? saved.visibility[id] : SCORE_MODELS[id].defaultVisible])) as Record, thresholds: Object.fromEntries(SCORE_MODEL_IDS.map(id => [id, SCORE_MODELS[id].thresholds.includes(saved.thresholds?.[id] as number) ? saved.thresholds![id] : SCORE_MODELS[id].defaultThreshold])) as Record, }; }