误报问题:校准危机检测,避免成为喊狼来了的孩子

发布: (2025年12月9日 GMT+8 22:00)
7 min read
原文: Dev.to

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;
}

每个触发器都有自己的阈值,可通过灵敏度设置进行调校:

TriggerLow SensitivityMediumHigh
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 …
};

让用户可以选择灵敏度,使他们能够根据个人偏好在安全性和侵入性之间取得平衡。

Back to Blog

相关文章

阅读更多 »

设计系统:治理与采用

引言:构建 design system 只是工作的一半。是的,评估多个选项、收集 stakeholders 的反馈并实现它们具有挑战性……