Files
xiaobailing-turn-detection/labels/eot-studio/lib/score-models.ts
T

26 lines
4.3 KiB
TypeScript

import type { ModelId } from "./model-scores";
export const SCORE_MODELS: Record<ModelId, {
name: string; family: string; color: string; directory: string; scoreFile?: string;
thresholds: readonly number[]; defaultThreshold: number; defaultVisible: boolean; description: string;
}> = {
maai: { name: "VAP / MaAI", family: "活动预测", color: "#8866b2", directory: "maai-ch-kyoto", scoreFile: "streaming/cpc-stereo/score-timeline.json", thresholds: [.11, .5, .8], defaultThreshold: .5, defaultVisible: true, description: "CPC 编码器、降噪版,用户与机器人双声道;流式评分,圆点取判断前最后可用分数。1 − 用户近期发声分数,约每 100 ms 更新,不是校准的 EOT 概率。" },
maai_user_only: { name: "VAP / MaAI(仅用户)", family: "活动预测", color: "#6c8746", directory: "maai-ch-kyoto", scoreFile: "streaming/cpc-user-only/score-timeline.json", thresholds: [.11, .5, .8], defaultThreshold: .5, defaultVisible: false, description: "保留用户语音,机器人输入全程静音;流式评分,圆点取判断前最后可用分数。1 − 用户近期发声分数,约每 100 ms 更新,与双声道版使用相同权重。仅改变模型输入,回放仍为原录音;圆点取判断前最后可用的流式分数,不是校准的 EOT 概率。" },
maai_mimi_standard: { name: "VAP / MaAI Mimi(标准双声道)", family: "活动预测", color: "#4b859f", directory: "maai-ch-kyoto", scoreFile: "streaming/mimi-standard/score-timeline.json", thresholds: [.11, .5, .8], defaultThreshold: .5, defaultVisible: false, description: "Mimi 编码器、标准版,用户与机器人双声道;流式评分,圆点取判断前最后可用分数。1 − 用户近期发声分数,每 80 ms 更新,20 秒上下文,不是校准的 EOT 概率。" },
maai_mimi_mc: { name: "VAP / MaAI Mimi(降噪双声道)", family: "活动预测", color: "#a58537", directory: "maai-ch-kyoto", scoreFile: "streaming/mimi-mc/score-timeline.json", thresholds: [.11, .5, .8], defaultThreshold: .5, defaultVisible: false, description: "Mimi 编码器、降噪版,用户与机器人双声道;流式评分,圆点取判断前最后可用分数。1 − 用户近期发声分数,每 80 ms 更新,20 秒上下文,不是校准的 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<ModelId, boolean>; thresholds: Record<ModelId, number> }
export function readScorePreferences(value: unknown): ScorePreferences {
const saved = value && typeof value === "object" && "version" in value && value.version === 1
? value as { visibility?: Record<string, unknown>; thresholds?: Record<string, unknown> } : {};
return {
visibility: Object.fromEntries(SCORE_MODEL_IDS.map(id => [id, typeof saved.visibility?.[id] === "boolean" ? saved.visibility[id] : SCORE_MODELS[id].defaultVisible])) as Record<ModelId, boolean>,
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<ModelId, number>,
};
}