误报问题:校准危机检测,避免成为喊狼来了的孩子
Source: Dev.to
Part of the CrisisCore Build Log – trauma‑informed systems engineering
当我在 Pain Tracker 中加入危机检测时,我知道两方面的风险都很高:
- 漏掉真实危机 → 当用户需要帮助时得不到帮助。
- 对正常行为触发 → 系统变成恼人的噪音,用户关闭它,真正需要时就失去了他们。
这就是校准问题。下面是我的处理思路。
核心挑战:快速点击 ≠ 恐慌
我最初的危机检测实现得非常天真:
// 🚫 Don't do this
if (clicksPerSecond > 5) {
activateEmergencyMode(); // 😬
}
几个小时内,我就收到报告说有人在以下情况下意外触发了紧急模式:
- 在身体地图上滚动定位
- 快速为多个症状打分
- 仅仅是正常使用手机应用
快速输入并不等同于痛苦;它往往只是效率的体现。
多信号检测:加权方法
解决方案是不再寻找任何单一指示器,而是跟踪加权的信号星座:
// Calculate overall stress level from multiple factors
const overallStress =
(currentIndicators.painLevel / 10) * 0.3 + // User‑reported pain
currentIndicators.cognitiveLoad * 0.25 + // Task difficulty signals
currentIndicators.inputErraticBehavior * 0.2 + // Click pattern variance
currentIndicators.errorRate * 0.15 + // Mistakes and corrections
currentIndicators.frustrationMarkers * 0.1; // Back navigation, help requests
// Only escalate when composite score crosses threshold
let severity = 'none';
if (overallStress >= 0.8) severity = 'critical';
else if (overallStress >= 0.6) severity = 'severe';
else if (overallStress >= 0.4) severity = 'moderate';
else if (overallStress >= 0.2) severity = 'mild';
没有任何单一信号能够单独触发紧急模式。必须要有汇聚的证据。
什么算作“异常输入”?
快速点击并不重要。不规则的点击才重要。
熟练的用户在熟悉的流程中点击间隔基本一致;而挣扎的用户会表现出高方差——长时间停顿后紧跟着快速点击。
const calculateInputErraticBehavior = useCallback(() => {
if (clickTimes.current.length Date.now() - time a + b, 0) / intervals.length;
const variance = intervals.reduce(
(sum, interval) => sum + Math.pow(interval - avgInterval, 2),
0
) / intervals.length;
return Math.min(1, variance / 10000); // Normalize to 0‑1
});
- 高方差 + 高错误率 + 疼痛水平升高 → 很可能出现问题。
- 高点击率 + 间隔一致 + 错误率正常 → 高手用户;保持安静。
挫败感堆栈
除了点击模式之外,我们还跟踪我称之为挫败感堆栈的内容:
interface CrisisTrigger {
type: 'pain_spike' | 'cognitive_fog' | 'rapid_input' |
'error_pattern' | 'emotional_distress' | 'timeout';
value: number;
threshold: number;
timestamp: Date;
context: string;
}
每个触发器都有自己的阈值,可通过灵敏度设置进行调校:
| Trigger | Low Sensitivity | Medium | High |
|---|---|---|---|
| Pain spike | ≥ 9/10 | ≥ 8/10 | ≥ 7/10 |
| Cognitive load | ≥ 0.8 | ≥ 0.6 | ≥ 0.5 |
| Error rate | ≥ 0.5 | ≥ 0.3 | ≥ 0.2 |
| Frustration markers | ≥ 0.7 | ≥ 0.5 | ≥ 0.3 |
用户可以自行选择灵敏度。有的人希望系统密切监控;有的人则觉得侵入性太强。两者都是合理的需求。
Cognitive Load ≠ Crisis
将“我正在处理复杂任务”与“我快要崩溃”区分开来并不容易。单纯的高认知负荷并不是问题;当它与错误率上升、求助请求以及返回导航一起出现时,才构成信号。
const calculateCognitiveLoad = useCallback(() => {
const recentErrors = errorEvents.current.filter(
time => Date.now() - time.getTime() Date.now() - time.getTime() {
if (crisisSettings.autoActivation.enabled) {
// … activation logic …
} else if (crisisLevel === 'none' && isCrisisModeActive) {
// Auto‑deactivate when stress returns to normal
setTimeout(() => {
setIsCrisisModeActive(false);
setCrisisFeatures(prev => ({
...prev,
emergencyMode: false,
cognitiveFogSupport: false,
multiModalInput: false,
}));
}, 5000); // 5‑second delay to prevent flapping
}
}, [crisisLevel, crisisSettings.autoActivation, isCrisisModeActive]);
为什么要延迟? 危机状态并非二元开关。用户可能短暂平静后再次出现高峰。快速切换模式会让人感到迷惑并削弱信任。5 秒的缓冲产生滞后——系统只有在状态持续稳定后才会降级。
恢复流程:从紧急模式优雅退出
紧急模式的激活是即时的,而停用则是渐进的。
当用户手动解决危机或系统检测到持续平静时:
const deactivateEmergencyMode = useCallback(() => {
setIsCrisisModeActive(false);
setCrisisFeatures({
emergencyMode: false,
cognitiveFogSupport: false,
multiModalInput: false,
stressResponsiveUI: true, // This stays on
});
resetCrisisDetection('resolved');
}, [resetCrisisDetection]);
保持激活的功能: 压力响应 UI。即使危机已解决,我们仍然继续监控。防护措施的持续时间要长于紧急警报。
会话记录:从每一次事件中学习
每一次危机事件都是学习的机会,既对用户也对系统:
interface CrisisSession {
id: string;
startTime: Date;
endTime?: Date;
triggers: CrisisTrigger[];
responses: CrisisResponse[];
userActions: string[];
outcome: 'resolved' | 'escalated' | 'timed_out' | 'user_dismissed' | 'ongoing';
duration: number;
effectiveInterventions: string[];
userFeedback?: string;
}
这些数据本地保存,帮助用户自行识别模式。随着时间推移,他们可能会注意到:
- “我的危机通常从返回导航循环开始。”
- “简化模式真的帮助我完成条目。”
- “我倾向于过早放弃。”
自我认知是终极的校准手段。
灵敏度调节:用户控制
不同的人需要不同的触发点。系统提供三种灵敏度级别:
const thresholds = {
painLevel:
preferences.crisisDetectionSensitivity === 'high' ? 7 :
preferences.crisisDetectionSensitivity === 'medium' ? 8 : 9,
// … other thresholds follow the same pattern …
};
让用户可以选择低、中或高灵敏度,使他们能够根据个人偏好在安全性和侵入性之间取得平衡。