Enhance smoking tracking features with AI next smoke time suggestions

- Added new API endpoint `GET /api/v1/smoke/next_smoke_time` to provide AI-generated suggestions for the next smoking time based on user data.
- Introduced a new database table `fa_smoke_ai_next_smoke` to store structured AI time node suggestions.
- Updated smoke handler and service to integrate the new AI next smoke time functionality.
- Enhanced documentation to reflect the new API endpoint and its usage, including details on how to generate AI time nodes.
This commit is contained in:
nepiedg
2026-01-20 07:08:52 +00:00
parent dc54c4e934
commit 6cf7eb2294
15 changed files with 1394 additions and 27 deletions
+95 -2
View File
@@ -22,7 +22,8 @@
说明:
- `smoke_time` 可选;不传则默认“当天”。
- `smoke_at` 可选;真实抽烟时间(格式 `YYYY-MM-DD HH:MM:SS`)。用于“按时间节点分析/AI 建议”;不传则可用 `createtime` 近似。
- `level/num` 可选;不传或传 `<=0` 时会按 `1` 处理。
- `level/num` 可选;不传时后端会按 `1` 处理。
- 如果要记录“想抽但忍住了”,请传 `level=0``num=0`(会在 `fa_smoke_log` 中展示为一条记录,但不会影响看板的支数累加)。
curl 示例:
@@ -120,7 +121,7 @@ curl -X GET 'http://127.0.0.1:8080/api/v1/smoke/logs/5202' \
字段说明:
- `today_count`:当天吸烟总支数(累加 `num`
- `minutes_since_last`:距最后一次抽烟的分钟数,通过最近一条 `smoke_at/smoke_time/createtime` 计算;若历史为空则字段不存在
- `minutes_since_last`:距最后一次“实际抽烟”(忽略 `level=0 && num=0` 的忍住记录)的分钟数,通过最近一条 `smoke_at/smoke_time/createtime` 计算;若历史为空则字段不存在
- `weekly`:起止日期内每日汇总,`count` 为当日总支数,`is_today` 标记当前日期(即便不在 `start/end` 范围内也会标记为 `false`
## 5) 最近记录列表(轻量版)
@@ -237,6 +238,8 @@ curl -X GET 'http://127.0.0.1:8080/api/v1/smoke/logs/5202' \
说明:
- 该接口用于记录“已完成观看广告”,落库到 `fa_smoke_ai_advice_unlocks``uid + unlock_date` 唯一)。
- `ad_watched_at` 可由后端取当前时间;如需审计/对账可保留前端上报并做校验。
- 解锁是“按天”的:观看一次广告解锁一天内的 AI 生成功能(可用于「每日 AI 建议」以及「AI 下次抽烟时间节点」)。
- 如果你要生成“明天”的 AI 时间节点,请把 `date` 传为明天日期(例如 `2026-01-06`)。
## 10) 获取用户基础信息(首次进入:判断是否需要补全)
@@ -321,3 +324,93 @@ curl -X GET 'http://127.0.0.1:8080/api/v1/smoke/logs/5202' \
```
成功响应:同 `GET /api/v1/smoke/profile`(返回最新 `profile` + `is_completed` + `baseline_interval_minutes`)。
## 12) 想抽但忍住了(写入一条 level=0,num=0 的记录)
`POST /api/v1/smoke/logs/resisted`
请求体(示例):
```json
{
"smoke_time": "2026-01-05",
"smoke_at": "2026-01-05 10:20:00",
"remark": "压力大,想抽但忍住了"
}
```
说明:
- 该接口会在 `fa_smoke_log` 中新增一条记录:`level=0``num=0`,用于更直观记录“想抽/忍住”的过程。
- 这类记录不会影响 `today_count/weekly.count` 的支数统计(因为 `num=0`)。
## 13) 获取“下次抽烟记录时间”(默认 + AI 自动切换)
`GET /api/v1/smoke/next_smoke_time`
说明:
- 用于首页展示“建议的下次记录时间”。
- 如果指定日期存在 AI 给出的时间节点(`time_nodes` 不为空),则优先使用 AI 的建议;否则使用默认策略。
- 可选参数:
- `date`:计划日期(默认今天),支持 `YYYY-MM-DD``today/tomorrow`
- `mode`(默认 `auto`
- `auto`:只在已存在 AI 时间节点时使用 AI(不主动生成)
- `ai`:生成该 `date` 的 AI 时间节点(需要先看广告解锁;生成一次缓存一天)
- `default`:永远返回默认策略
默认策略(不使用 AI):
- 基础间隔:优先使用 `GET /api/v1/smoke/profile` 返回的 `baseline_interval_minutes`;若不存在则默认 `60` 分钟。
- 阶梯式延时:最近 7 天内每累计 `5` 条“忍住记录(level=0,num=0)”,在基础间隔上 `+5` 分钟(最多 `+60` 分钟)。
- 若用户已补全作息时间,会自动规避睡眠区间:若计算出的时间落在睡眠区间,顺延到下一次起床时间。
AI 生成说明:
-`mode=ai` 时,会把最近 3 天的抽烟数据(含“忍住记录”)作为输入提供给 AI,用于更贴合近期模式生成时间节点。
- 未解锁时会返回 `403`:提示需要观看广告解锁。
成功响应(示例:回落到默认):
```json
{
"code": 200,
"message": "success",
"data": {
"source": "default",
"not_before_at": "2026-01-05T10:18:00+08:00",
"suggested_at": "2026-01-05T10:18:00+08:00",
"default": {
"last_smoke_at": "2026-01-05T09:30:00+08:00",
"next_smoke_at": "2026-01-05T10:18:00+08:00",
"base_interval_minutes": 48,
"interval_minutes": 48,
"stage": 0,
"resisted_7d": 3,
"sleep_adjusted": false,
"algorithm": "staircase_delay_v1",
"as_of": "2026-01-05T10:00:00+08:00"
}
}
}
```
当存在 AI 建议且包含 `time_nodes` 时,响应会是(示例):
```json
{
"code": 200,
"message": "success",
"data": {
"source": "ai",
"not_before_at": "2026-01-05T10:18:00+08:00",
"suggested_at": "2026-01-05T10:28:00+08:00",
"time_nodes": ["10:30", "11:10", "14:00", "16:30"],
"advice": "先把这次冲动延后到10:28,期间做一次5分钟快走+喝水,压力场景用深呼吸替代。",
"default": { "algorithm": "staircase_delay_v1" },
"ai": {
"plan_date": "2026-01-05",
"not_before_at": "2026-01-05T10:18:00+08:00",
"suggested_at": "2026-01-05T10:28:00+08:00",
"time_nodes": ["10:30", "11:10", "14:00", "16:30"],
"advice": "先把这次冲动延后到10:28,期间做一次5分钟快走+喝水,压力场景用深呼吸替代。",
"prompt_version": "v1",
"model": "gpt-4.1-mini",
"provider": "openai-compatible"
}
}
}
```