Files
geo/docs/ai-brand-monitoring-tech-design-v5.md
T
root 36451a613d feat: Introduce AI Brand Monitoring System V5 technical design document
- Added comprehensive technical design document for AI Brand Monitoring System V5, outlining system architecture, data models, sampling strategies, and monitoring protocols.
- Key changes include a shift to a sampling-based trend monitoring approach, updated data collection and storage strategies, and new metrics for performance evaluation.
- Implemented migration scripts to support the flattening of brand questions and versioning of question texts, ensuring historical data integrity and version control.
2026-04-09 14:43:20 +08:00

28 KiB
Raw Blame History

AI 品牌曝光监测系统技术方案 V5

1. 文档信息

项目 内容
文档名称 AI 品牌曝光监测系统技术方案 V5(采样型趋势监测 + 异步解耦)
文档版本 V5.1
文档状态 待评审
创建日期 2026-04-08
基线文档 docs/ai-brand-monitoring-tech-design-v4.md
适用范围 数据追踪模块全部页面
关联文档 docs/geo-platform-prd-v1.mdPRD 8.4 数据追踪)
关联文档 docs/question-driven-monitoring-design-v1.md(问题驱动模型)
核心约束 单租户仅 1 个监测插件实例,插件所在设备不保证全天在线

2. V5 核心结论

V5 不再把该能力定义为“全量、精确、准实时监控”,而是明确收敛为:

  1. 采样型趋势监测系统,不是审计系统。
  2. 单实例插件 + 非全天在线设备前提下,只承诺趋势参考,不承诺全量覆盖。
  3. 页面百分比全部按实际采样成功样本计算,不再暗示“全量真实占比”。
  4. 页面必须展示采样覆盖信息,包括计划采样数、实际采样数、覆盖率、最近更新时间。
  5. 引入 RabbitMQ 和独立 Monitoring PostgreSQL 隔离写链路,但聚合仍以日批为主,不承诺准实时展示。

2.1 相比 V4 的根本变化

维度 V4 V5
产品定位 全量品牌曝光监测 采样型趋势参考
采集目标 尽量覆盖全部问题 × 全平台 每日仅覆盖活跃监测题池
插件节点假设 大量用户端节点可互补 单租户单主插件实例
数据时效 准实时 + T+1 T+1 为主,允许延迟
数据精度承诺 接近真实全量 趋势可参考,精度受覆盖率影响
任务处理 PG + Redis 锁 + RabbitMQ Monitoring PG 任务表 + PG 租约状态机 + RabbitMQ 结果异步化
存储边界 单业务库承载配置与监测结果 主业务 PG 存配置,Monitoring PG 存监测数据
页面表达 指标卡直接展示百分比 指标卡 + 采样覆盖信息 + 置信度提示

2.2 非目标

V5 明确不做以下承诺:

  1. 不承诺所有问题每天都有结果。
  2. 不承诺所有 AI 平台每天都有样本。
  3. 不承诺分钟级实时更新。
  4. 不承诺百分比可用于财务、法务、投放结算或精确 KPI 审计。

3. 产品口径与页面表达

3.1 页面定位

数据追踪页展示的是:

  • 在“当前监测题池”上的 AI 曝光趋势
  • 在“实际采样成功样本”上的品牌表现
  • 在“可归因引用样本”上的文章引用趋势

不是:

  • 品牌在全网 AI 场景中的绝对真实份额
  • 所有问题、所有平台、所有时间点的完整监控

3.2 页面必须新增的展示项

为避免误导,数据追踪页和 Dashboard composite 接口必须返回并展示:

  1. planned_sample_count:计划采样数
  2. actual_sample_count:实际采样成功数
  3. coverage_rate:覆盖率 = actual / planned
  4. last_sampled_at:最近成功采样时间
  5. confidence_levelhigh / medium / low

推荐前端呈现方式:

  • 顶部右侧信息条:采样模式
  • 趋势图上方副文案:已采样 18/30,覆盖率 60%,更新于 04-08 09:20
  • 覆盖率过低时展示 样本不足,仅供参考

3.3 低覆盖场景的展示规则

覆盖率 置信度 页面表现
>= 70% high 正常展示百分比和趋势
40% - 69% medium 展示百分比,并提示“样本偏少”
< 40% low 保留原始计数,百分比弱化展示或标记“仅供参考”

actual_sample_count < 5 时:

  1. 不展示“精确到整数”的百分比变化解释。
  2. 趋势线可以显示,但需打低置信度标记。
  3. 引用排行允许为空,不用补零。

4. 采样配额与容量模型

4.1 套餐定义

V5 中配额控制的不是“题库总量”,而是“每日活跃监测问题数”。

配额项 Free Pro Enterprise
最大品牌数 1 3 自定义
题库总量 不限于监测能力,只做配置资产 不限于监测能力,只做配置资产 自定义
每日活跃监测问题数 3-5 5-10 自定义
采集频率 每天 每天 每天 / 自定义
平台范围 当前已接入且已登录的平台 当前已接入且已登录的平台 同左
数据承诺 趋势参考 趋势参考 趋势参考 / 专属增强

4.2 活跃监测题池

系统将问题分成两层:

  1. 问题题库:品牌下维护的全部问题,仅做配置和运营资产。
  2. 活跃监测题池:每日实际参与采样的问题集合,数量受套餐限制。

推荐实现:

  • brand_questions 保留全部题库
  • 新增 monitor_prioritymonitor_enabled
  • 调度器每日只选 Top N 问题进入任务生成

4.3 单实例前提下的目标任务量

按首批 6 个平台测算:

套餐 活跃问题数 平台数 目标计划任务/天
Free 3-5 6 18-30
Pro 5-10 6 30-60

说明:

  1. 这是 计划采样量,不是保证完成量。
  2. 实际完成量取决于:
    • 主监测插件是否在线
    • 插件机器当日在线时长
    • 对应 AI 平台是否已登录
    • 平台风控和采集成功率

4.4 核心调度原则

V5 的调度器不追求“补齐所有漏采任务”,而追求“稳定输出可比较样本”。

因此:

  1. 每天只生成当天计划任务,不补历史大积压。
  2. 超过 48 小时未完成的任务自动过期,不回补到新一天的分母中。
  3. 读侧按 planned_sample_countactual_sample_count 共同解释结果。

4.5 主插件在线约束

单租户只指定 1 个 primary_monitoring_installation 参与自动监测。

调度前先判断该插件是否活跃:

  • last_seen_at <= 24h:生成当天任务
  • last_seen_at > 24h:不生成新任务,页面沿用最近一次成功数据并提示“近期无新采样”

这条规则的目的:

  1. 防止设备长期离线时任务无限堆积
  2. 防止“未执行任务”污染覆盖率统计
  3. 让系统行为和单实例现实约束一致

5. 数据口径定义

5.1 顶部指标口径

所有百分比的分母统一为 实际采样成功回答数,不是计划任务数,也不是题库总数。

指标 定义
提及率 mentioned_count / actual_sample_count
首位提及率 top1_mentioned_count / actual_sample_count
首选推荐率 first_recommended_count / actual_sample_count
正面提及率 positive_mentioned_count / actual_sample_count
品牌可见率 与提及率同源,可作为 UI 别名展示
文章引用率 cited_answer_count / actual_sample_count

5.2 趋势图口径

趋势图展示的是按天聚合后的样本表现,不是平台真实总体份额。

每个点必须同时具备:

  • metric_value
  • actual_sample_count
  • coverage_rate

可选增强:

  • 默认展示 7 天滚动均值
  • 用户切换后可看原始日值

5.3 高频问题口径

高频问题区不再解释为“全站高频触发问题”,而是:

在当前时间窗口内,被实际采样成功次数最多的问题

推荐展示字段:

  • 问题文案
  • 成功采样次数
  • 提及率
  • 最近采样时间

5.4 引用排行口径

引用排行按模型平台展示:

  • 有过可归因引用的回答数
  • 引用文章数
  • 引用率

若平台当日无样本或平台未登录:

  • 展示为 未采样
  • 不强行按 0 并入分母

6. 数据模型修订

6.1 双 PostgreSQL 存储边界

V5.1 将数据按“业务配置”和“监测结果”拆到两个 PostgreSQL:

主业务 PostgreSQL

  • tenants
  • brands
  • brand_keywords
  • brand_questions
  • articles
  • publish_records
  • plugin_installations
  • tenant_monitoring_quotas

Monitoring PostgreSQL

  • monitoring_collect_tasks
  • question_monitor_runs
  • question_monitor_parse_results
  • monitoring_citation_facts
  • monitoring_article_url_aliases
  • monitoring_*_daily

设计原则:

  1. 不做跨库物理外键,只保留逻辑 ID 引用。
  2. 监测链路的高频写入、重试、归档不影响主业务 PG。
  3. 读侧监测查询优先从 Monitoring PG 获取。

6.2 question_version_id 移除后的替代方案

V5 接受原系统不再维护 question_version_id,但仍然保留“输入快照不可变”原则。

替代方案:

  1. 在任务表和运行表写入 question_text_snapshot
  2. 同时写入 question_hash
  3. 历史汇总按 question_hash 区分口径

这样即使 question_id 不变、文案发生修改,历史数据也不会被新文案污染。

6.3 tenant_monitoring_quotas

CREATE TABLE tenant_monitoring_quotas (
    tenant_id                    BIGINT PRIMARY KEY REFERENCES tenants(id),
    max_brands                   INT NOT NULL DEFAULT 1,
    daily_active_question_limit  INT NOT NULL DEFAULT 5,
    collect_frequency            VARCHAR(20) NOT NULL DEFAULT 'daily',
    enabled_platforms            JSONB NOT NULL DEFAULT '["deepseek","qwen","doubao"]',
    primary_installation_id      BIGINT REFERENCES plugin_installations(id),
    task_daily_hard_cap          INT NOT NULL DEFAULT 36,
    plan_tier                    VARCHAR(20) NOT NULL DEFAULT 'free',
    created_at                   TIMESTAMPTZ NOT NULL DEFAULT now(),
    updated_at                   TIMESTAMPTZ NOT NULL DEFAULT now()
);

建议默认值:

  • Freedaily_active_question_limit = 5task_daily_hard_cap = 36
  • Prodaily_active_question_limit = 10task_daily_hard_cap = 72

说明:

  1. tenant_monitoring_quotas 放在主业务 PostgreSQL。
  2. primary_installation_id 继续引用主业务库中的 plugin_installations

6.4 monitoring_collect_tasks

V5.1 使用 Monitoring PG 单表状态机进行任务租约,并用 RabbitMQ 解耦结果写入。

CREATE TABLE monitoring_collect_tasks (
    id                      BIGSERIAL PRIMARY KEY,
    tenant_id               BIGINT NOT NULL,
    brand_id                BIGINT NOT NULL,
    question_id             BIGINT NOT NULL,
    question_text_snapshot  TEXT NOT NULL,
    question_hash           VARCHAR(64) NOT NULL,
    ai_platform_id          VARCHAR(30) NOT NULL,
    run_mode                VARCHAR(30) NOT NULL DEFAULT 'plugin_standard',
    business_date           DATE NOT NULL,
    planned_at              TIMESTAMPTZ NOT NULL DEFAULT now(),
    status                  VARCHAR(20) NOT NULL DEFAULT 'pending',
    lease_token_hash        VARCHAR(128),
    leased_to_installation  BIGINT,
    leased_at               TIMESTAMPTZ,
    lease_expires_at        TIMESTAMPTZ,
    callback_received_at    TIMESTAMPTZ,
    completed_at            TIMESTAMPTZ,
    skip_reason             VARCHAR(50),
    error_message           TEXT,
    created_at              TIMESTAMPTZ NOT NULL DEFAULT now(),
    updated_at              TIMESTAMPTZ NOT NULL DEFAULT now(),

    CONSTRAINT uk_collect_task_idempotent
        UNIQUE (tenant_id, brand_id, question_id, question_hash, ai_platform_id, run_mode, business_date)
);

CREATE INDEX idx_collect_tasks_lease
    ON monitoring_collect_tasks(tenant_id, status, business_date, lease_expires_at);

状态流转:

  • pending
  • leased
  • received
  • completed
  • skipped
  • expired
  • failed

说明:

  1. 任务租约状态在 Monitoring PG 中维护。
  2. received 表示 API 已接收插件结果并成功投递 MQ,但 worker 尚未完成最终入库。

6.5 question_monitor_runs

在 V5 中至少补充:

ALTER TABLE question_monitor_runs
    ADD COLUMN IF NOT EXISTS tenant_id BIGINT,
    ADD COLUMN IF NOT EXISTS business_date DATE,
    ADD COLUMN IF NOT EXISTS run_mode VARCHAR(30),
    ADD COLUMN IF NOT EXISTS question_text_snapshot TEXT,
    ADD COLUMN IF NOT EXISTS question_hash VARCHAR(64),
    ADD COLUMN IF NOT EXISTS provider_model VARCHAR(100),
    ADD COLUMN IF NOT EXISTS request_id VARCHAR(100),
    ADD COLUMN IF NOT EXISTS raw_answer_storage_key TEXT;

建议幂等键:

CREATE UNIQUE INDEX uk_monitor_run_idempotent
ON question_monitor_runs(tenant_id, brand_id, question_id, question_hash, ai_platform_id, run_mode, business_date);

建议:

  1. question_monitor_runs 落在 Monitoring PostgreSQL。
  2. 若原始回答文本不超过阈值,可直接存库;超大原文再转对象存储。

6.6 文章 URL 归因表

为支撑“总引用数 / 文章引用率 / 引用文章数”,新增 URL 归因别名表:

CREATE TABLE monitoring_article_url_aliases (
    id                  BIGSERIAL PRIMARY KEY,
    tenant_id           BIGINT NOT NULL,
    article_id          BIGINT NOT NULL,
    publish_record_id   BIGINT,
    platform_id         VARCHAR(64),
    external_article_id VARCHAR(128),
    original_url        TEXT NOT NULL,
    normalized_url      TEXT NOT NULL,
    last_path_segment   VARCHAR(255),
    confidence          VARCHAR(20) NOT NULL DEFAULT 'high',
    created_at          TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE UNIQUE INDEX uk_article_url_alias
ON monitoring_article_url_aliases(tenant_id, normalized_url);

7. 解析标准化与 SoV 统计模型

7.1 解析分层

V5.1 的解析分为 3 层:

  1. 回答层:品牌提及、首位提及、首选推荐、情感倾向
  2. 引用层:从回答、citation JSON、search_results 中提取 URL 事实
  3. 来源层:基于域名清洗和站点聚合生成 SoV 统计结果

7.2 基于 tldextract 的顶级域名清洗

为避免 www、二级域名、国家后缀等问题导致同一站点重复计数,引用归因与来源排行统一采用 Public Suffix List + tldextract 口径。

处理目标:

  1. 从原始 URL 中提取 subdomain / domain / suffix
  2. 生成 registrable_domain
  3. 生成统一站点主键 site_key
  4. 为页面级和站点级聚合提供稳定维度

示例:

原始 URL registrable_domain 说明
https://www.zhihu.com/question/123 zhihu.com www 折叠
https://zhuanlan.zhihu.com/p/123 zhihu.com 子域归并到站点
https://mp.weixin.qq.com/s/abc weixin.qq.com 基于 PSL 提取可注册域
https://finance.sina.com.cn/roll/123.html sina.com.cn 正确处理 com.cn
https://sub.example.co.uk/a example.co.uk 正确处理 co.uk

推荐清洗流程:

  1. URL 小写化主机名
  2. 去掉默认端口
  3. 去掉 fragment
  4. path 做基础规范化
  5. host 通过 tldextract 计算 registrable_domain
  6. 保存:
    • normalized_url
    • host
    • registrable_domain
    • subdomain
    • suffix

7.3 monitoring_citation_facts 推荐字段

为支撑域名清洗和来源排行,建议引用事实表至少包含:

CREATE TABLE monitoring_citation_facts (
    id                   BIGSERIAL PRIMARY KEY,
    tenant_id            BIGINT NOT NULL,
    run_id               BIGINT NOT NULL,
    brand_id             BIGINT NOT NULL,
    ai_platform_id       VARCHAR(30) NOT NULL,
    business_date        DATE NOT NULL,
    cited_url            TEXT NOT NULL,
    normalized_url       TEXT NOT NULL,
    host                 VARCHAR(255) NOT NULL,
    registrable_domain   VARCHAR(255) NOT NULL,
    subdomain            VARCHAR(255),
    suffix               VARCHAR(50),
    site_key             VARCHAR(255) NOT NULL,
    article_id           BIGINT,
    publish_record_id    BIGINT,
    resolution_status    VARCHAR(20) NOT NULL DEFAULT 'resolved',
    resolution_confidence VARCHAR(20) NOT NULL DEFAULT 'high',
    created_at           TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE INDEX idx_citation_facts_domain
ON monitoring_citation_facts(tenant_id, business_date, registrable_domain);

约定:

  1. normalized_url 用于页面级去重和文章归因
  2. registrable_domain 用于站点级来源排行
  3. site_key 默认等于 registrable_domain
  4. 如业务需要区分站群,可对特定域名做覆写映射

7.4 site_key 映射规则

默认规则:

  • site_key = registrable_domain

可选增强规则:

  1. mp.weixin.qq.comweixin.qq.com 统一到 weixin.qq.com
  2. 将业务上需要区分的站群写入 site_domain_mapping
  3. 对同集团但不同产品是否合并,必须通过配置显式决定,不靠临时规则猜测

推荐新增配置表:

CREATE TABLE site_domain_mappings (
    id                  BIGSERIAL PRIMARY KEY,
    registrable_domain  VARCHAR(255) NOT NULL,
    site_key            VARCHAR(255) NOT NULL,
    site_name           VARCHAR(255) NOT NULL,
    is_active           BOOLEAN NOT NULL DEFAULT true,
    created_at          TIMESTAMPTZ NOT NULL DEFAULT now()
);

7.5 SoV 统计模型

V5.1 中的 SoV 统一解释为:

在当前采样窗口内,某品牌、某站点或某文章在全部有效样本中的相对占比

必须明确分母,禁止不同口径混用。

7.6 品牌 SoV

品牌 SoV 适用于品牌曝光类页面。

定义:

brand_sov = brand_mentioned_answers / actual_sample_count

其中:

  • brand_mentioned_answers:成功采样回答中,提及目标品牌的回答数
  • actual_sample_count:成功采样回答总数

这和页面上的“提及率”同源,可视为品牌在样本回答中的 Share of Voice

7.7 引用来源 SoV

引用来源 SoV 适用于“引用来源排行”“来源平台占比”。

定义:

source_sov = source_citation_count / total_resolved_citation_count

其中:

  • source_citation_count:某 site_key 在窗口内被引用的次数
  • total_resolved_citation_count:全部已成功解析并完成站点归类的引用次数

补充口径:

  • unresolved 引用不进入分子
  • unresolved 是否进入分母,要固定为“不进入”
  • unresolved 单独展示占比,作为质量指标

7.8 文章 SoV

文章 SoV 用于内部文章在可归因引用中的占比。

定义:

article_sov = article_citation_count / total_article_resolved_citation_count

其中:

  • article_citation_count:某篇内部文章被 AI 引用的次数
  • total_article_resolved_citation_count:全部成功归因到内部文章的引用次数

注意:

  1. 文章 SoV 不是品牌 SoV
  2. 文章 SoV 的分母不能拿全部回答数
  3. 若用户看的是“文章引用率”,仍然应使用 cited_answer_count / actual_sample_count

7.9 覆盖率与 SoV 的关系

覆盖率和 SoV 必须分开解释:

  1. coverage_rate 反映“今天采样够不够”
  2. SoV 反映“在已采样样本里占比多少”

因此页面解释顺序应为:

  1. 先看覆盖率
  2. 再看 SoV / 提及率 / 引用率

coverage_rate < 40% 时:

  • 允许展示 SoV
  • 但必须附带低置信度提示

7.10 聚合输出建议

建议在 monitoring_citation_source_dailymonitoring_citation_page_daily 中增加:

  1. citation_count
  2. citation_sov
  3. resolved_count
  4. unresolved_count
  5. confidence_level

这样前端可以同时展示:

  • 引用次数
  • SoV
  • 数据质量

8. 任务协议与插件侧流程

8.1 统一为租约式协议

V5 删除 GET tasks -> POST claim 两步式协议,统一改为:

  1. 插件请求租约
  2. 服务端原子分配任务并返回 lease_token
  3. 插件执行采集
  4. 插件带 lease_token 回传结果
  5. 服务端校验归属、先写任务状态为 received 并投递 RabbitMQ
  6. Monitor Worker 异步写入运行结果、解析结果并完成任务

8.2 插件 API

POST /api/plugin/monitoring/tasks/lease
POST /api/plugin/monitoring/tasks/{id}/result
POST /api/plugin/monitoring/tasks/{id}/skip

请求头:

  • X-Geo-Installation-Token
  • X-Geo-Installation-Id

8.3 租约接口行为

租约接口建议按 PG 原子领取:

SELECT id
FROM monitoring_collect_tasks
WHERE tenant_id = $1
  AND status = 'pending'
  AND business_date = $2
ORDER BY planned_at ASC, id ASC
FOR UPDATE SKIP LOCKED
LIMIT $3;

服务端完成以下动作:

  1. 选出任务
  2. 生成短期 lease_token
  3. 更新 status = leased
  4. 写入 lease_expires_at = now() + interval '15 minutes'

8.4 插件执行策略

V5 继续复用现有插件基础设施:

但采样策略改为“小批量、固定预算”:

项目 建议值
心跳频率 15 分钟
单次租约任务数 2-3
单任务超时 60 秒
租约时长 15 分钟
每日硬上限 按套餐 36 / 72

8.5 任务过期与回收

定时任务每 30 分钟处理一次:

  1. lease_expires_at < now() 且状态仍为 leased 的任务改为 expired
  2. received 状态超过阈值未被 worker 完成时,进入异常告警
  3. 同一 business_dateexpired 任务最多重试 1 次
  4. 超过 business_date + 2 days 的未完成任务不再重试

9. 采集、解析、聚合架构

9.1 首期简化版链路

每日 00:10 调度器生成当天任务
      ↓
插件后台 15 分钟心跳租约任务
      ↓
插件执行提问并回传结果
      ↓
tenant-api:校验租约 -> 标记 received -> 投递 RabbitMQ
      ↓
Monitor Worker:消费结果 -> 写 Monitoring PG -> 解析结果 -> 完成任务
      ↓
每日 06:30 聚合 Job 汇总到 monitoring_*_daily
      ↓
读侧 API + Redis 缓存

9.2 RabbitMQ 的职责边界

V5.1 中 RabbitMQ 只承担“结果异步化”,不承担“任务分发”。

使用 RabbitMQ 的原因:

  1. 插件回调接口可以快速返回,降低超时和重试风险
  2. 解析、引用归因、写库失败不会直接影响插件侧体验
  3. 方便把高频写入隔离到独立 worker
  4. 后续若企业版放大量级,不需要重做写链路

但 RabbitMQ 不参与以下事项:

  1. 不做任务租约
  2. 不做读侧查询
  3. 不强制引入准实时前端刷新

推荐队列:

  • monitor.result.ingest
  • monitor.result.dlq
  • monitor.aggregate.trigger

9.3 Monitoring PostgreSQL 的职责

独立 Monitoring PG 的目的不是“多一套库”,而是隔离监测链路的写放大。

承载内容:

  1. 任务表
  2. 原始回答
  3. 解析结果
  4. 引用事实
  5. 日聚合结果

收益:

  1. 主业务 PG 不承受高频插入和大文本更新
  2. Monitoring PG 可独立做分区、归档、VACUUM 策略
  3. 监测表膨胀不会影响文章、品牌、发布主链路

9.4 原始回答存储

V5.1 中抓取结果优先进入 Monitoring PG

  1. 原始回答文本
  2. 平台响应元数据
  3. 引用与搜索结果原始 JSON
  4. 解析后的结构化字段

可选归档策略:

  1. 小于 64 KB 的原文直接存 Monitoring PG
  2. 超大原文或完整调试负载转存对象存储
  3. Monitoring PG 仅保留摘要、关键字段和存储路径

10. 文章引用归因策略

10.1 为什么不能只看 URL 最后一段

仅按最后一段匹配存在以下问题:

  1. 不同平台可能出现相同 path segment
  2. 同一平台 PC / H5 / 分享页 URL 可能不同
  3. AI 引用结果可能带参数、重定向或 canonical URL
  4. 同一篇文章可能存在多个可访问别名

因此 V5 的归因策略是 分层匹配 + 置信度标记

10.2 归因顺序

  1. normalized_url 精确匹配
  2. (platform_id, external_article_id) 精确匹配
  3. (domain, last_path_segment) 唯一匹配
  4. 无法唯一命中时,记为 unresolved

10.3 低置信度处理

当仅通过 last_path_segment 命中时:

  1. 给归因结果打 low_confidence
  2. 可以进入趋势参考视图
  3. 不建议进入需要精确计费或精确归属的报表

这与 V5 的“趋势参考”定位是一致的。


11. 平台接入范围

11.1 V5 交付范围

数据模型支持 6 平台扩展,但首期交付只承诺首批 3 平台:

  1. DeepSeek
  2. 通义千问
  3. 豆包

11.2 页面与套餐表达

页面和套餐都必须按“当前已接入且已登录的平台”解释:

  • 已接入且已登录:进入采样计划
  • 已接入未登录:展示 未登录
  • 未接入:展示 未接入

不得再用“全 6 平台稳定可用”作为首期对外承诺。


12. 读侧与汇总表

V5 读侧继续沿用 V3 的聚合表和缓存思路,但口径增加采样字段:

  1. planned_sample_count
  2. actual_sample_count
  3. coverage_rate
  4. confidence_level

推荐所有 monitoring_*_daily 汇总表统一增加以上字段。

12.1 Dashboard composite

/api/tenant/monitoring/dashboard/composite 继续保留,但返回结构需扩展:

{
  "overview": {
    "mention_rate": 0.42,
    "citation_rate": 0.18,
    "planned_sample_count": 30,
    "actual_sample_count": 21,
    "coverage_rate": 0.70,
    "confidence_level": "high",
    "last_sampled_at": "2026-04-08T09:20:00Z"
  }
}

12.2 缓存策略

读侧缓存策略可继续沿用 V3

  • composite 聚合缓存
  • singleflight
  • TTL 抖动
  • stale-while-revalidate

但缓存失效触发点改为:

  1. 每日聚合完成
  2. 用户切换品牌 / 时间窗口

不需要为单条采样结果做准实时逐条失效。


13. 降级、告警与风险

13.1 降级策略

场景 V5 行为
插件 24h 未活跃 暂停生成新任务,页面展示上次数据
平台未登录 该平台不进入当天计划样本
当日覆盖率低 页面提示“样本不足,仅供参考”
某平台 adapter 失效 该平台展示“暂不可用”,其余平台继续
URL 无法归因 计入 unresolved,不强行挂到文章

13.2 关键告警

指标 阈值
主插件离线时长 > 24h
日覆盖率 < 40%
单平台连续失败 > 20 次 / 天
unresolved 引用占比 > 30%
每日聚合延迟 > 08:00 未完成

13.3 风险接受说明

V5 明确接受以下风险:

  1. 单日样本偏少导致波动大
  2. 插件离线导致当天无新数据
  3. 部分 URL 只能低置信度归因

但不接受以下风险:

  1. 任务重复执行导致统计翻倍
  2. 输入口径变更污染历史数据
  3. 未授权回调写入虚假监测结果

14. 实施计划

14.1 Phase 分期

Phase 内容 估时
A 双库方案落地:主业务 PG / Monitoring PG schema 与连接配置 4 天
B RabbitMQ 基础设施 + Monitor Worker 骨架 + DLQ 4 天
C 插件:AI adapter 框架 + 3 平台 + 租约式任务执行 6 天
D 后端:租约 API、结果回调、MQ 消费、解析入库、日聚合 7 天
E 前端:数据追踪页补覆盖率、更新时间、置信度提示 4 天
F 联调、坏样本验证、口径验收 4 天
合计 29 天

14.2 验收标准

  1. 页面可展示 planned_sample_count / actual_sample_count / coverage_rate
  2. 页面可正常展示趋势图、高频问题、引用排行
  3. 当覆盖率不足时,页面有明确提示
  4. 同一任务不会被重复计入统计
  5. 问题文案修改后,历史趋势不被污染
  6. 引用文章数可通过 URL alias 规则稳定归因,无法归因时进入 unresolved

15. V4 → V5 变更摘要

编号 V4 V5
C1 全量监测叙事 采样趋势叙事
C2 Free 1 品牌 / 40 问题 Free 3-5 个每日活跃问题
C3 Pro 3 品牌 / 40 问题 Pro 5-10 个每日活跃问题
C4 GET + claim 两步任务协议 一步租约式任务协议
C5 question_version_id question_hash + question_text_snapshot
C6 RabbitMQ + 增量聚合 RabbitMQ 仅做结果异步化,不参与任务分发或前端准实时
C7 准实时可见 T+1 / 延迟可接受
C8 仅展示百分比 百分比 + 采样覆盖信息
C9 首期 6 平台叙事 首期只承诺 3 平台
C10 单一业务库承载全部数据 主业务 PG + Monitoring PG 双库隔离

16. 最终建议

V5 适合当前阶段的原因不是“它最强”,而是“它和当前约束一致”:

  1. 和单实例插件现实相符
  2. 和 PRD 的 V1 边界相符
  3. 和用户对“趋势参考”的接受度相符

如果未来要升级到 V6,再考虑:

  1. 专用在线采集节点
  2. 企业版更高采样量
  3. 更细粒度的增量聚合和近实时刷新
  4. 更强的 URL 归因与多次重复采样校准