c9ebfd5873
- Added unified backend calculations for health recovery, savings, and motivation generation in the algorithm documentation. - Updated API documentation to include new endpoints for retrieving statistics and motivation messages, enhancing clarity on data retrieval processes. - Revised product documentation to reflect changes in API usage for health recovery and savings calculations, ensuring consistency across all related files.
8.5 KiB
8.5 KiB
戒烟算法与 AI 策略说明
1. 核心理念
采用渐进式递减策略,而非突然戒断:
- 科学研究表明,逐步减少比冷火鸡戒断成功率更高
- 通过延长抽烟间隔,让身体逐渐适应尼古丁减少
- AI 分析个人模式,提供个性化的递减计划
2. 默认递减算法 (staircase_delay_v1)
2.1 算法概述
下次建议时间 = 上次抽烟时间 + 基础间隔 + 奖励间隔
2.2 参数说明
| 参数 | 来源 | 默认值 | 说明 |
|---|---|---|---|
| base_interval | profile.baseline_interval_minutes | 60 分钟 | 用户初始平均抽烟间隔(为空/0 时默认 60) |
| resisted_7d | 近7天忍住次数 | 0 | level=0,num=0 的记录数 |
| bonus_interval | 计算得出 | 0 | 奖励延长时间 |
2.3 奖励机制
每累计 5 次忍住,基础间隔 +5 分钟,最多 +60 分钟:
bonus_interval = min(floor(resisted_7d / 5) * 5, 60)
final_interval = clamp(base_interval + bonus_interval, 5, 240)
示例:
- 用户基础间隔 48 分钟,近 7 天忍住 12 次
- bonus = floor(12/5) * 5 = 10 分钟
- 最终间隔 = 48 + 10 = 58 分钟
2.4 睡眠规避
若计算出的时间落在睡眠区间,顺延到下一次起床时间(可能是当天也可能是次日):
if suggested_time in [sleep_time, wake_up_time]:
suggested_time = next_day_wake_up_time
2.5 边界与兜底
- 若没有历史记录,则以“当前时间”作为
last_smoke_at参与计算。 - 若生成未来日期计划(如明天),默认建议不早于该日起床时间;未配置作息时按
07:00处理。
2.6 算法流程图
获取上次抽烟时间 (last_smoke_at, 若无记录则取当前时间)
↓
获取用户基础间隔 (base_interval_minutes)
↓
统计近7天忍住次数 (resisted_7d)
↓
计算奖励间隔: bonus = min(floor(resisted_7d / 5) * 5, 60)
↓
计算建议时间: suggested = last_smoke_at + base + bonus (并限制在 5~240 分钟区间)
↓
检查是否在睡眠时间?
├── 是 → 顺延到起床时间
└── 否 → 返回建议时间
3. AI 增强算法
3.1 AI 时间节点规划
当用户解锁 AI 功能后,系统会:
-
收集近 3 天数据:
- 每次抽烟的时间点
- 每次忍住的时间点
- 抽烟原因/场景标签
-
分析抽烟模式:
- 高峰时段识别(如下午 2-4 点)
- 触发场景识别(如压力、无聊、社交)
- 间隔规律分析
-
生成个性化时间节点:
- 避开高峰时段的前半小时
- 在用户通常能忍住的时段设置节点
- 逐日递增间隔
3.2 AI 建议内容
AI 会生成以下内容(实际接口格式):
{
"not_before_at": "2026-01-05T10:18:00+08:00",
"suggested_at": "2026-01-05T10:28:00+08:00",
"time_nodes": ["09:30", "12:30", "15:30", "19:00", "22:00"],
"advice": "昨天你的吸烟量比限额少了2支,这是一个巨大的胜利!数据显示你的烟瘾在下午2点左右达到顶峰——今天试着那个时候去散散步。"
}
3.3 AI Prompt 设计
你是一位专业的戒烟辅导教练。基于用户的抽烟数据,提供个性化的戒烟建议。
用户档案:
- 日均吸烟量:{baseline_cigs_per_day} 支
- 烟龄:{smoking_years} 年
- 抽烟动机:{smoke_motivations}
- 戒烟动力:{quit_motivations}
- 作息:{wake_up_time} - {sleep_time}
近3天数据:
{recent_logs}
请分析:
1. 用户的抽烟规律和高峰时段
2. 主要的触发场景
3. 成功忍住的模式
然后生成:
1. 一段鼓励性的分析总结(2-3句话)
2. 明天的建议抽烟时间节点(比今天少1支)
3. 2-3条实用的应对建议
4. 阶段划分
4.1 三阶段戒烟计划
| 阶段 | 时间 | 目标 | 策略 |
|---|---|---|---|
| 记录期 | Day 1-7 | 建立基线 | 正常抽烟,但每次都记录 |
| 减量期 | Day 8-21 | 减少 50% | 每周目标递减,AI 指导 |
| 巩固期 | Day 22-30 | 维持/归零 | 强化抵抗,心理建设 |
4.2 阶段进度计算
// utils/stage.js
function calculateStage(startDate) {
const daysSinceStart = daysBetween(startDate, new Date())
if (daysSinceStart <= 7) {
return {
stage: 1,
name: '记录期',
progress: daysSinceStart / 7,
daysLeft: 7 - daysSinceStart
}
} else if (daysSinceStart <= 21) {
return {
stage: 2,
name: '减量期',
progress: (daysSinceStart - 7) / 14,
daysLeft: 21 - daysSinceStart
}
} else {
return {
stage: 3,
name: '巩固期',
progress: Math.min((daysSinceStart - 21) / 9, 1),
daysLeft: Math.max(30 - daysSinceStart, 0)
}
}
}
4.3 每日目标计算
// utils/target.js
function calculateDailyTarget(baseline, stage, dayInStage) {
if (stage === 1) {
return baseline
}
if (stage === 2) {
const reduction = (dayInStage / 14) * 0.5
return Math.max(Math.round(baseline * (1 - reduction)), 1)
}
if (stage === 3) {
const targetRate = 0.25 - (dayInStage / 9) * 0.25
return Math.max(Math.round(baseline * targetRate), 0)
}
return baseline
}
5. 健康恢复计算(后端统一)
接口:GET /api/v1/smoke/stats?range=week|month|year(详见 docs/smoke/API.md)
基于医学研究的恢复时间线:
| 时间点 | 恢复指标 | 计算方式 |
|---|---|---|
| 20分钟 | 心率血压恢复正常 | 固定 |
| 8小时 | 血氧水平恢复 | 固定 |
| 24小时 | 心脏病风险开始下降 | 固定 |
| 48小时 | 嗅觉味觉开始恢复 | 固定 |
| 2周 | 肺功能提升 15% | 线性计算 |
| 1月 | 肺功能提升 30% | 线性计算 |
| 3月 | 肺功能提升 50% | 线性计算 |
| 1年 | 心脏病风险降低 50% | 线性计算 |
// utils/health.js
function calculateLungRecovery(smokeFreeMinutes) {
const days = smokeFreeMinutes / (24 * 60)
if (days < 14) {
return (days / 14) * 15
} else if (days < 30) {
return 15 + ((days - 14) / 16) * 15
} else if (days < 90) {
return 30 + ((days - 30) / 60) * 20
} else {
return Math.min(50 + ((days - 90) / 275) * 50, 100)
}
}
6. 省钱计算(后端统一)
接口:GET /api/v1/smoke/stats?range=week|month|year(详见 docs/smoke/API.md)
// utils/money.js
function calculateMoneySaved(packPriceCent, cigsPerPack, baselineCigsPerDay, actualCigsTotal, days) {
const expectedTotal = baselineCigsPerDay * days
const savedCigs = expectedTotal - actualCigsTotal
const savedPacks = savedCigs / cigsPerPack
return Math.round(savedPacks * packPriceCent)
}
7. 激励语生成(后端统一)
接口:GET /api/v1/smoke/motivation(详见 docs/smoke/API.md)
根据用户状态生成不同的激励语:
// utils/motivation.js
function getMotivationMessage(context) {
const {
minutesSinceLast,
todayCount,
dailyTarget,
resistedToday,
quitMotivations
} = context
if (resistedToday > 0 && minutesSinceLast < 30) {
return '太棒了!你刚刚成功抵抗了一次烟瘾'
}
if (todayCount < dailyTarget * 0.5) {
return '今天的表现非常出色,继续保持!'
}
if (todayCount === dailyTarget - 1) {
return '还剩最后一支配额,考虑把它留到睡前?'
}
if (todayCount > dailyTarget) {
return `没关系,明天是新的一天。记住你为什么要戒烟:${quitMotivations[0]}`
}
return '保持连胜纪录!'
}
8. 数据分析指标
8.1 关键指标
| 指标 | 计算方式 | 用途 |
|---|---|---|
| 日均吸烟量 | 周期内总量 / 天数 | 趋势对比 |
| 周同比变化 | (本周 - 上周) / 上周 | 进度评估 |
| 忍住成功率 | 忍住次数 / (忍住+抽烟次数) | 意志力评估 |
| 平均间隔 | 总时长 / 抽烟次数 | 递减效果 |
| 最长无烟时长 | 最大间隔记录 | 成就激励 |
| 较昨日减少 | 昨日支数 - 今日支数(可为负) | 若为负,表示今天超出昨日 |
8.2 周报数据结构
// 周报数据结构
const weeklyReport = {
period: { start: '2026-01-01', end: '2026-01-07' },
totalCigs: 35,
dailyAverage: 5,
comparedToLastWeek: -20, // 百分比变化
resistedCount: 12,
longestGap: 180, // 分钟
peakHours: ['14:00', '21:00'],
topTriggers: ['压力大', '无聊'],
achievements: ['连续7天记录', '单日忍住5次'],
nextWeekTarget: 4
}