Doc:Remove the document on question-driven monitoring design V1 and add a new image related to problem-driven data.

This commit is contained in:
2026-04-09 23:58:13 +08:00
parent 36451a613d
commit 9b4dd09780
3 changed files with 1300 additions and 685 deletions
File diff suppressed because it is too large Load Diff
@@ -1,494 +0,0 @@
# GEO 平台问题驱动的数据监控设计 V1
## 1. 文档信息
| 项目 | 内容 |
| --- | --- |
| 文档名称 | GEO 平台问题驱动的数据监控设计 V1 |
| 文档版本 | V1.0 |
| 文档状态 | 待评审 |
| 创建日期 | 2026-03-25 |
| 适用范围 | 品牌词库、问题集、数据追踪页 |
| 关联文档 | `docs/geo-platform-prd-v1.md` |
| 关联文档 | `docs/geo-platform-tech-architecture-v1-50k.md` |
## 2. 设计背景
当前数据监控页不是通用 BI,而是明确来源于:
- 品牌
- 关键词
- 关键词下的问题集
- 模型
- 最近 30 天时间窗口
因此,数据监控的真实逻辑源头不是“文章”本身,也不是“关键词”本身,而是:
- `品牌关键词下配置的问题`
- `系统按周期执行这些问题后的模型回答结果`
这意味着整套监控系统必须按“问题驱动”来设计,否则后续会出现:
- 指标口径不清
- 历史数据与问题版本混淆
- 任务量失控
- 查询逻辑和数据模型对不上
## 3. 核心结论
V1 建议采用以下原则:
1. `问题` 是监控数据的最小采集单元。
2. `关键词` 只是问题集合的容器和聚合维度。
3. `品牌监控页` 展示的是问题运行结果的聚合视图。
4. `历史数据必须绑定问题版本`,不能因为改了问题文案就覆盖历史口径。
5. `页面查询只查汇总表`,不扫描原始问答记录。
## 4. 页面逻辑拆解
结合当前页面,用户选择条件是:
- 品牌
- 关键词
- 模型
- 时间范围,最多近 30 天
页面展示内容包括:
- 提及率
- 首位提及率
- 首选推荐率
- 正面提及率
- 日趋势折线
- 高频问题
- 引用排行榜
这些数据不应该直接从原始问答明细实时计算,而应该来自预聚合结果。
## 5. 数据采集逻辑
## 5.1 问题来源
问题来源于品牌词库中的关键词问题集。
例如:
- 品牌:12
- 关键词:数字时尚
- 问题:
- 数字时尚品牌有哪些值得关注的新趋势
- 如何选择适合自己的数字时尚单品
- 数字时尚和传统时尚的主要区别是什么
这些问题是监控任务的输入,不是单纯展示内容。
## 5.2 采集单元
建议将一次监控采集定义为:
- 一个问题
- 一个模型
- 一次执行时间
即:
`1 question x 1 model x 1 run_time = 1 条原始监控记录`
## 5.3 指标来源
每次模型回答返回后,系统进行解析,得到结构化结果:
- 是否提及品牌
- 是否首位提及品牌
- 是否首选推荐品牌
- 情感倾向是否正向
- 是否引用系统文章
- 引用了哪篇文章
然后再做日级汇总。
## 6. 推荐数据模型
## 6.1 主数据表
### `brand_keywords`
- `id`
- `brand_id`
- `name`
- `status`
- `created_at`
### `brand_questions`
- `id`
- `brand_id`
- `keyword_id`
- `current_version_id`
- `status`
- `created_at`
说明:
- 一条问题属于一个品牌和一个关键词
- 数据监控页中的“高频问题”和“问题集”都可以从这里关联出来
### `brand_question_versions`
- `id`
- `question_id`
- `question_text`
- `question_hash`
- `version_no`
- `is_active`
- `created_at`
说明:
- 问题文案一旦修改,新增版本,不覆盖历史版本
- 历史监控记录绑定到具体 `question_version_id`
## 6.2 原始采集表
### `question_monitor_runs`
- `id`
- `brand_id`
- `keyword_id`
- `question_id`
- `question_version_id`
- `model_id`
- `run_date`
- `run_at`
- `task_batch_id`
- `status`
- `raw_answer_storage_key`
- `created_at`
说明:
- 一次执行一条记录
- 模型原始回答建议放对象存储,数据库只存引用路径和摘要字段
### `question_monitor_parse_results`
- `id`
- `run_id`
- `mentioned_brand`
- `top1_mentioned`
- `first_recommended`
- `positive_mentioned`
- `citation_article_count`
- `citation_platform_count`
- `parser_version`
- `created_at`
说明:
- 解析结果是后续聚合的直接来源
## 6.3 汇总表
### `question_model_daily_metrics`
粒度:
- `brand_id + keyword_id + question_id + question_version_id + model_id + date`
字段:
- `ask_count`
- `mention_count`
- `top1_mention_count`
- `first_recommend_count`
- `positive_mention_count`
- `citation_count`
- `updated_at`
用途:
- 回看单个问题在每天的表现
- 支撑高频问题排行和问题详情
### `keyword_model_daily_metrics`
粒度:
- `brand_id + keyword_id + model_id + date`
字段:
- `question_count`
- `ask_count`
- `mention_count`
- `top1_mention_count`
- `first_recommend_count`
- `positive_mention_count`
- `citation_count`
- `mention_rate`
- `top1_mention_rate`
- `first_recommend_rate`
- `positive_mention_rate`
- `updated_at`
用途:
- 直接支撑你截图里的 30 天趋势和顶部指标卡
### `keyword_model_top_questions_daily`
粒度:
- `brand_id + keyword_id + model_id + date + question_id`
字段:
- `question_text_snapshot`
- `ask_count`
- `mention_count`
- `score`
用途:
- 支撑右侧“高频问题”
### `keyword_model_citation_rank_daily`
粒度:
- `brand_id + keyword_id + model_id + date + cited_article_id`
字段:
- `citation_count`
- `citation_rate`
用途:
- 支撑引用排行榜
## 7. 查询口径定义
## 7.1 顶部指标卡
以所选:
- 品牌
- 关键词
- 模型
- 时间范围
为过滤条件,从 `keyword_model_daily_metrics` 汇总得出:
- 提及率 = `sum(mention_count) / sum(ask_count)`
- 首位提及率 = `sum(top1_mention_count) / sum(ask_count)`
- 首选推荐率 = `sum(first_recommend_count) / sum(ask_count)`
- 正面提及率 = `sum(positive_mention_count) / sum(ask_count)`
## 7.2 趋势图
直接查询 `keyword_model_daily_metrics` 最近 30 天数据。
每个点只是一行日汇总,查询量很小。
## 7.3 高频问题
`keyword_model_top_questions_daily` 取最近 30 天累计 TopN。
## 7.4 引用排行榜
`keyword_model_citation_rank_daily` 取最近 30 天累计 TopN。
## 8. 任务调度设计
## 8.1 为什么要控制任务量
监控任务量不是由页面访问量决定,而是由:
- 品牌数
- 每个品牌下关键词数
- 每个关键词下问题数
- 模型数
- 每天执行次数
共同决定。
## 8.2 数据量公式
每日原始采集量近似为:
`品牌数 x 每品牌关键词数 x 每关键词问题数 x 模型数 x 每日执行次数`
例如:
### 轻量场景
- 50 个品牌
- 每品牌 10 个关键词
- 每关键词 10 个问题
- 5 个模型
- 每天 1 次
则:
`50 x 10 x 10 x 5 x 1 = 25,000 条/天`
### 中等场景
- 100 个品牌
- 每品牌 20 个关键词
- 每关键词 20 个问题
- 5 个模型
- 每天 2 次
则:
`100 x 20 x 20 x 5 x 2 = 400,000 条/天`
如果每条原始回答按 5KB 估算:
- 每天约 2GB 原始文本
- 30 天约 60GB 原始文本
因此:
- 原始回答不建议长期放 PostgreSQL
- 建议放对象存储
- PostgreSQL 只保存解析结果和汇总结果
## 8.3 V1 推荐执行频率
为了控制数据量,V1 建议:
- 每个问题每天默认执行 `1 次`
- 重要品牌或付费用户可提升为 `2 次`
- 不建议 V1 做高频小时级轮询
## 8.4 去重策略
如果同一品牌下多个关键词出现完全相同的问题文案,建议:
- 通过 `question_hash` 检测重复问题
- 同一品牌、同一模型、同一天内同 hash 的问题尽量复用一次执行结果
但聚合归属仍可按映射关系分别记账。
这样可以显著减少任务量。
## 9. 版本与历史口径
## 9.1 为什么必须版本化
如果用户把问题:
- “数字时尚品牌有哪些值得关注的新趋势”
改成:
- “2026 年数字时尚品牌有哪些值得关注的新趋势”
那前后两者其实已经不是同一个监控口径。
如果直接覆盖旧问题,历史趋势就会失真。
## 9.2 推荐做法
- 问题修改时新建 `question_version`
- 新运行记录绑定到新版本
- 历史数据仍归属旧版本
- 页面默认展示当前版本问题的聚合数据
如果要做历史总览,可按 `question_id` 聚合,但需要在文档里说明“跨版本聚合”。
## 10. 页面查询策略
## 10.1 页面不查原始表
数据页不能直接查:
- `question_monitor_runs`
- `question_monitor_parse_results`
这些表只用于:
- 问题详情
- badcase 回放
- 算法验证
## 10.2 页面只查汇总表
数据页查询路径应为:
1. 先查 Redis
2. Redis miss 后查 PostgreSQL 汇总表
3. 后台异步更新缓存
## 10.3 Redis Key 建议
可按以下维度缓存:
- `brand:{brand_id}:keyword:{keyword_id}:model:{model_id}:range:30d:summary`
- `brand:{brand_id}:keyword:{keyword_id}:model:{model_id}:range:30d:trend`
- `brand:{brand_id}:keyword:{keyword_id}:model:{model_id}:range:30d:top_questions`
- `brand:{brand_id}:keyword:{keyword_id}:model:{model_id}:range:30d:citation_rank`
## 11. V1 性能判断
针对当前页面,如果采用“按问题采集、按天汇总、按 30 天查询”的模型,PostgreSQL 是够用的。
原因是:
- 页面查询只查 30 天汇总数据
- 每次查询最多几十到几百行
- 高频问题和排行榜都可提前汇总
- Redis 可以承接高频重复查询
真正可能变大的不是页面查询,而是:
- 原始问题执行任务量
- 原始模型回答存储量
所以要重点控制的是任务调度和原始结果留存,而不是页面 SQL 本身。
## 12. V1 推荐保留策略
建议:
- 原始运行记录保留 `30 ~ 90 天`
- 原始回答正文放对象存储
- PostgreSQL 解析结果保留 `90 天`
- 日级汇总表保留 `180 天` 或更久
如果页面只看 30 天,也建议汇总表多保留一段时间,方便后续扩展。
## 13. 升级边界
当出现以下情况时,再升级架构:
- 问题量暴涨
- 模型数明显增加
- 每日执行次数明显增加
- 页面支持自由筛选、明细钻取
- 监控维度从 30 天扩展到半年、一年
此时可以逐步升级为:
- 独立分析库
- 更大规模任务调度
- 更复杂的去重复用逻辑
- 专用分析引擎
## 14. V1 最终建议
结合你当前页面和品牌词库结构,V1 最合理的设计是:
1.`问题` 为最小监控采集单元。
2.`关键词` 作为问题的聚合容器。
3.`问题版本` 保证历史口径稳定。
4.`日级汇总表` 支撑页面查询。
5.`对象存储` 保存原始回答,避免 PostgreSQL 膨胀。
6.`问题 hash 去重` 控制执行量。
7. 默认每题每天执行 1 次,避免 V1 数据量失控。
这样做,逻辑、数据量、页面性能三者才能对齐。
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB