#7 更新所有readme, 更新problem文件夹当前问题。

Merged
xueyiming merged 7 commits from Server/feature/zhangbo into Server/master 9 hours ago
6 changed files with 2790 additions and 2077 deletions
  1. 2079 0
      README.md
  2. 0 1252
      README_myself.md
  3. 2 2
      prd/README.md
  4. 467 0
      problem/2026-07-24_问题总结.md
  5. 242 0
      problem/2026-07-30_问题总结.md
  6. 0 823
      zhangbo.md

+ 2079 - 0
README.md

@@ -241,3 +241,2082 @@ pytest
 ## License
 
 MIT
+# SupplyAgent 业务框架设计
+
+## 1. 项目定位
+
+SupplyAgent 是一个面向平台内容供给的需求汇总工具。
+
+它要解决的核心问题不是“从数据中找出若干热门词”,而是:
+
+> 汇总来自不同渠道、不同时间尺度和不同验证阶段的需求信号,将其统一挂靠到一棵全局分类树上,形成一张可追溯、可解释、可持续反馈的需求关系图,最终输出数百条平台级需求。
+
+最终结果同时服务于两种业务视角:
+
+1. 从全局分类树和关系图观察平台需求版图、层级、覆盖和交织关系。
+2. 从排序后的需求清单直接开展内容发现、内容生产、供给调度和效果验证。
+
+项目最终交付的不是一张扁平需求表,而是:
+
+- 一棵稳定的全局分类树;
+- 数百条挂靠在树上的平台需求;
+- 需求与多个树节点之间的关系线;
+- 需求背后的多维数据证据;
+- 需求与内容、线上表现之间的反馈闭环。
+
+---
+
+## 2. 对现有项目业务结构的理解
+
+当前项目已经形成了需求汇总的基础业务链路。
+
+### 2.1 上游需求池
+
+项目从上游策略需求池接收不同类型的需求信号。目前已经体现出的主要维度包括:
+
+- 外部热度;
+- 平台持续热度;
+- 平台去年同期热度;
+- 平台近期供需缺口;
+- 近 7 日真实 ROV;
+- 近 7 日真实 VOV。
+
+前四类数据主要回答“什么需求可能值得做”,属于先验信号。
+
+真实 ROV、VOV 主要回答“需求被内容承接并上线后是否真的有效”,属于后验反馈。
+
+### 2.2 全局分类树
+
+`global_tree_category` 所表达的是一棵统一的全局语义分类树,而不是多棵相互独立的人物树、事件树或情感树。
+
+分类树从左向右按层级展开,例如:
+
+```text
+L1        L2        L3          L4          L5
+知识  →   历史  →   历史时期  →  古代史
+
+事件  →   社会事件  →  人物故事  →  个人经历
+                              →  名人故事
+```
+
+树上的正式节点是稳定、抽象、可治理的业务分类。具体的人物、事件、情感和需求表达,不一定都要成为正式树节点。
+
+### 2.3 需求词归类
+
+上游需求中的词语或短语会被挂靠到全局分类树的合适节点上。
+
+归类的业务意义是为需求建立稳定坐标,使需求可以:
+
+- 沿树向上汇总;
+- 在同类需求间比较;
+- 观察不同分支的需求覆盖;
+- 计算分类节点在不同信号维度下的强度;
+- 支撑后续平台需求生成。
+
+### 2.4 分类节点强度
+
+当前项目会把需求词级别的数据向分类树节点及其祖先聚合。
+
+因此分类树不仅承担知识组织,还承担需求统计和强度观察:
+
+- 叶子或挂载节点反映局部、具体需求;
+- 中间节点反映某个业务方向的整体强度;
+- 高层节点反映平台需求版图中的大方向。
+
+### 2.5 平台需求生成
+
+现有需求生成 Agent 已经体现了以下层次:
+
+```text
+来源维度 → 整体方向 → 汇总事件 → 原始需求名称
+```
+
+这个结构可以作为初始生成方式,但最终业务模型需要进一步升级为:
+
+```text
+全局分类树 + 需求节点 + 跨分支关系 + 多维证据 + 线上反馈闭环
+```
+
+---
+
+## 3. 核心设计原则
+
+### 3.1 一棵树,而不是多棵业务树
+
+全局分类树是整个系统唯一的正式分类骨架。
+
+人物、事件、情感、知识、历史、行为等概念分布在同一棵树的不同分支中。平台需求通过同时连接多个分支,表达真实用户兴趣的交织关系。
+
+### 3.2 以树确定归属,以图表达关系
+
+树内父子关系负责表达:
+
+- 层级;
+- 上下位关系;
+- 统计汇总路径;
+- 业务覆盖;
+- 正式分类治理。
+
+图上的跨节点关系负责表达:
+
+- 一个需求同时涉及哪些分类分支;
+- 人物、事件、行为、情感等元素如何共同组成需求;
+- 不同需求之间是否存在重合、包含、相似或关联;
+- 哪些上游信号共同支持同一个需求。
+
+### 3.3 每条需求必须挂树
+
+每条正式平台需求至少挂靠一个真实存在的分类树节点。
+
+一条需求可以同时挂靠多个正式树节点。多个挂靠点共同定义需求,不要求在业务语义上强制区分主次。
+
+例如同一条需求可以同时挂靠:
+
+- 人物故事;
+- 个人经历;
+- 历史解读;
+- 诗词创作;
+- 与具体战争时期相关的历史分类。
+
+如果某些统计、展示或资源分配场景必须使用唯一口径,可以额外指定一个“统计主归属节点”。统计主归属只用于避免重复计数,不代表其他挂靠点在业务语义上更次要。
+
+### 3.4 用户意图优先
+
+需求的多个挂靠点应共同表达“用户为什么对此感兴趣”,而不是只机械选择最具体的对象节点。
+
+例如需求:
+
+> 毛泽东在抗日战争和解放战争时期的诗词创作
+
+可能涉及:
+
+- 人物对象:毛泽东;
+- 历史背景:抗日战争、解放战争;
+- 行为:写诗、诗词创作;
+- 内容意图:人物经历、作品背景、历史解读。
+
+需求可以同时挂靠“人物故事”“个人经历”“历史解读”或与诗词创作相关的正式节点,具体取决于上游数据实际支持了哪些用户意图。
+
+“毛泽东”“抗日战争”“解放战争”“诗词创作”等相关语义通过多个挂靠点、需求元素和关系线共同表达。
+
+### 3.5 数据驱动为主,自由推演为辅
+
+平台需求必须主要来源于上游数据。
+
+建议的总体比例是:
+
+- 80%~90% 为上游数据直接支持的核心需求;
+- 10%~20% 为基于已有数据、节点和关联关系形成的邻近机会需求。
+
+自由推演不得:
+
+- 凭空创造没有来源的人物、事件、情感或主题;
+- 用模型常识替代上游证据;
+- 将弱关联包装成确定关系;
+- 与数据支持的需求混淆展示。
+
+推演需求必须单独标记,并能说明它是从哪些已有数据和关系扩展而来。
+
+### 3.6 原始事实与语义推断分离
+
+上游目前主要提供“关联”关系。
+
+系统必须永久保留原始“关联”边,不得覆盖或篡改。
+
+系统可以在有依据时,把普通关联扩展解释为新的语义关系,例如:
+
+- 人物参与事件;
+- 事件发生于某个历史时期;
+- 人物在某个时期进行诗词创作;
+- 作品表达某种精神或情感;
+- 某个历史背景影响作品主题。
+
+所有推断语义关系必须附带:
+
+- 推断说明;
+- 原始关联证据;
+- 数据来源;
+- 置信度;
+- 是否经过人工确认;
+- 创建或更新时间。
+
+证据不足时继续保留“关联”,不强行解释。
+
+---
+
+## 4. 整体业务图结构
+
+整张图由六类核心业务对象组成:
+
+- 分类树节点;
+- 细节元素;
+- 视频或内容实例;
+- 明确语言观点与长段讨论;
+- 平台需求;
+- 证据、状态与反馈。
+
+### 4.1 分类树节点
+
+正式、稳定、可治理的分类节点。
+
+分类树节点之间保留原始父子关系,并从左向右按层级展开。
+
+### 4.2 需求元素节点
+
+从上游需求中识别出的具体业务元素,例如:
+
+- 人物:毛泽东;
+- 历史事件:抗日战争、解放战争;
+- 行为:写诗;
+- 作品或内容:战争时期诗词;
+- 情感或精神:革命乐观主义、家国情怀。
+
+需求元素首先来自上游数据。系统只负责归一别名、识别类型并保留来源。
+
+### 4.3 平台需求节点
+
+平台需求是最终业务输出的核心实体,不等同于某个分类节点,也不等同于某个原始需求词。
+
+例如:
+
+> 毛泽东在抗日战争时期创作过哪些诗词
+
+> 毛泽东的战争诗词如何反映当时的历史环境
+
+> 从抗日战争到解放战争,毛泽东诗词主题发生了什么变化
+
+这些需求可以共同涉及“毛泽东、抗日战争、解放战争、写诗”等元素,但它们表达的是不同用户意图,因此应当是不同的平台需求节点。
+
+### 4.4 内容节点
+
+能够承接某条需求的真实内容,包括:
+
+- 已有内容;
+- 搜索发现的内容;
+- 新生产的内容;
+- 已上线并获得真实反馈的内容。
+
+需求和内容之间允许多对多关系:
+
+- 一条需求可以由多条内容承接;
+- 一条内容也可能同时承接多个需求。
+
+但需要区分内容的主需求和辅助需求,避免效果归因失真。
+
+### 4.5 证据与状态节点
+
+记录需求在各个独立维度上的证据、状态和变化,包括:
+
+- 外部热度;
+- 平台持续热度;
+- 去年同期热度;
+- 近期供需缺口;
+- 真实 ROV、VOV;
+- 样本量;
+- 数据日期;
+- 来源可信度;
+- 生命周期状态;
+- 推演标记;
+- 风险或抑制原因。
+
+### 4.6 分类节点下的证据子图
+
+正式分类树不是信息下钻的终点。
+
+每一个分类节点下面,还可以继续挂载与它相关的细节元素、真实视频和语言化内容,形成一套“节点下证据子图”:
+
+```text
+正式分类节点
+   ↓
+细节元素
+   ↓
+真实视频实例
+   ↓
+明确语言观点或问题
+   ↓
+长段讨论
+   ↓
+平台需求
+```
+
+这里的“继续下钻”是产品浏览和证据展开,不是继续增加正式分类树层级。
+
+元素、视频、短观点和长段讨论不应被强行定义成 L6、L7、L8 分类节点。它们挂在正式分类节点下面,但属于不同类型的业务对象。
+
+这样可以同时保证:
+
+- 全局分类树结构稳定、纯净;
+- 节点可以持续承载越来越丰富的细节信息;
+- 用户能够从抽象分类一路下卷到真实内容;
+- 平台需求能够追溯到具体视频和语言证据;
+- 真实内容表现能够逐层回流到元素、需求和分类节点。
+
+### 4.7 细节元素
+
+细节元素是分类节点下面更具体的语义索引。
+
+例如某个“人物故事”或“历史人物”分类节点下面,可以挂载:
+
+- 毛泽东;
+- 抗日战争;
+- 解放战争;
+- 写诗;
+- 诗词创作;
+- 战争时期诗词;
+- 革命乐观主义;
+- 家国情怀。
+
+元素来自真实上游数据、视频解析、内容标签或人工治理。
+
+一个元素可以:
+
+- 挂在多个正式分类节点下;
+- 与其他元素保留原始“关联”关系;
+- 连接多条真实视频;
+- 被多个平台需求共同引用;
+- 根据视频数量、出现次数和线上表现形成元素强度。
+
+分类节点下的元素列表应展示:
+
+- 元素名称;
+- 元素类型;
+- 出现次数;
+- 关联视频数量;
+- 支持的平台需求数量;
+- 线上表现摘要;
+- 数据来源;
+- 更新时间。
+
+### 4.8 视频实例
+
+元素可以继续下钻到具体视频。
+
+视频不是单纯的播放链接,而是需求提取和效果反馈的事实实例。每条视频应尽量保留:
+
+- 视频标题;
+- 视频链接;
+- 作者和发布时间;
+- 视频转写或内容描述;
+- 命中的分类节点;
+- 命中的细节元素;
+- 对应的平台需求;
+- 点赞、评论、分享、收藏等表现;
+- 真实 ROV、VOV;
+- 内容质量或解析可信度;
+- 是否属于主承接内容。
+
+同一条视频可以连接多个元素和需求,但需要区分主要承接和辅助承接。
+
+### 4.9 明确语言观点
+
+视频解析后,可以从内容中提取能够独立表达的短语言单元,例如:
+
+- 一个明确事实;
+- 一个观点;
+- 一个判断;
+- 一个问题;
+- 一句可用于需求命名的话;
+- 一条用户容易理解和传播的内容结论。
+
+例如:
+
+> 战争环境并未中断诗词创作,反而强化了作品的历史表达。
+
+> 毛泽东为什么在战争时期持续进行诗词创作?
+
+短语言单元可以用于:
+
+- 快速理解视频贡献了什么;
+- 比较不同视频是否表达同一观点;
+- 形成需求候选名称;
+- 聚合同义需求;
+- 支撑需求关系说明。
+
+所有语言提取都要保留对应视频、原始片段和提取说明,避免模型生成的语言脱离真实内容。
+
+### 4.10 长段讨论
+
+多个视频、观点和元素还可以进一步形成长段讨论。
+
+长段讨论用于表达短句无法承载的内容,例如:
+
+- 一个问题的完整背景;
+- 多个视频观点之间的共同点和差异;
+- 历史过程和人物行为之间的联系;
+- 一个需求为什么值得形成;
+- 某个需求存在什么争议;
+- 内容供给可以从哪些角度展开;
+- 线上反馈为什么支持或否定该需求。
+
+例如可以围绕以下主题形成讨论:
+
+> 从抗日战争到解放战争,毛泽东的诗词既记录时代环境,也呈现政治理想、个人情感和历史判断。不同视频分别提供作品背景、创作动机、表达方式和受众理解方面的证据。
+
+长段讨论不是脱离数据的自由文章。它必须引用实际元素、视频和明确观点,并标识:
+
+- 讨论依据;
+- 主要证据;
+- 推断内容;
+- 不确定点;
+- 支持或关联的平台需求。
+
+### 4.11 节点下钻的产品形态
+
+用户从全局分类树继续下卷时,建议按以下顺序展开:
+
+```text
+分类节点概览
+→ 高频或高价值元素
+→ 元素关联的视频
+→ 视频转写与明确观点
+→ 多视频形成的长段讨论
+→ 从证据中提取的平台需求
+→ 需求对应的线上验证结果
+```
+
+每一级都要能够返回上一级,并保留:
+
+- 来源;
+- 出现次数;
+- 贡献度;
+- 时间;
+- 置信度;
+- 真实线上表现;
+- 与需求之间的关系。
+
+节点下钻同时服务两个目的:
+
+1. 展示:让业务人员理解这个分类节点下具体有什么。
+2. 提取:让系统从元素、视频和语言证据中发现、生成、合并和验证需求。
+
+---
+
+## 5. 图中的关系类型
+
+### 5.1 树内父子关系
+
+正式分类树原有的层级关系,是全图最稳定的结构。
+
+### 5.2 需求多挂靠关系
+
+每条平台需求可以同时挂靠多个正式分类节点。每条挂靠关系都应记录:
+
+- 挂靠节点;
+- 挂靠理由;
+- 支持该挂靠的上游数据;
+- 关系置信度;
+- 是否属于正式挂靠或待审核挂靠;
+- 生效和更新时间。
+
+多个挂靠点共同表达需求的完整语义和跨分支交织关系。
+
+例如“毛泽东的战争诗词如何反映当时的历史环境”可以同时挂靠:
+
+- 历史解读;
+- 人物故事;
+- 个人经历;
+- 与诗词创作相关的正式节点;
+- 与抗日战争、解放战争所处历史时期相关的正式节点。
+
+当主题统计需要避免重复计数时,可以为需求设置一个“统计主归属节点”,或者按明确的分摊规则将需求计入多个节点。该统计属性与业务挂靠关系分开管理。
+
+### 5.4 原始关联关系
+
+来自上游数据的事实关系,关系类型统一为“关联”。
+
+原始关联边必须保留完整的来源和时间信息。
+
+### 5.5 推断语义关系
+
+系统根据多个原始关联、树上位置和上下文推断出的补充关系。
+
+推断边只用于:
+
+- 增强解释;
+- 帮助聚类;
+- 提供低权重排序增益;
+- 辅助发现邻近机会需求。
+
+推断边不能取代原始关联边。
+
+### 5.6 需求与内容关系
+
+表达内容承接了哪个需求,以及承接程度:
+
+- 主承接;
+- 辅助承接;
+- 部分覆盖;
+- 待验证;
+- 已上线;
+- 已形成有效样本。
+
+### 5.7 内容表现回流关系
+
+表达某批内容的真实线上表现如何反向影响需求强度。
+
+### 5.8 分类节点与元素关系
+
+表达某个细节元素下挂在哪些正式分类节点下。
+
+该关系应记录元素为何属于该分类、来源和出现次数。一个元素允许同时下挂多个分类节点。
+
+### 5.9 元素与视频关系
+
+表达某条视频包含、体现或讨论了哪些元素。
+
+上游只有“关联”时保留原始关联;需要扩展为“人物出现、事件涉及、行为发生、观点表达”等语义时,必须附带说明和置信度。
+
+### 5.10 视频与语言关系
+
+表达明确观点、问题和长段讨论是从哪些视频或视频片段中提取出来的。
+
+语言内容必须能回看原始视频或转写依据。
+
+### 5.11 语言与需求关系
+
+表达某个明确观点、问题或长段讨论支持、形成或验证了哪些平台需求。
+
+同一个需求可以由多个语言证据共同支持,同一个语言观点也可以被多个需求引用。
+
+---
+
+## 6. 需求汇总业务流程
+
+整体不是一次性的线性任务,而是持续循环的业务系统。
+
+```text
+上游需求信号
+    ↓
+数据归一与来源保留
+    ↓
+需求元素识别
+    ↓
+挂靠全局分类树
+    ↓
+保留原始关联并构建关系图
+    ↓
+连接真实视频并解析内容
+    ↓
+提取明确观点和长段讨论
+    ↓
+合并为唯一平台需求
+    ↓
+计算先验需求强度
+    ↓
+形成主题方向与需求池
+    ↓
+搜索或生产承接内容
+    ↓
+内容上线并产生真实表现
+    ↓
+归因到平台需求
+    ↓
+更新需求验证强度与生命周期
+    ↓
+影响下一周期的需求排序和内容供给
+```
+
+### 6.1 数据归一
+
+统一处理:
+
+- 同义词;
+- 简称与全称;
+- 人物别名;
+- 事件的不同表达;
+- 错别字;
+- 中英文表达;
+- 时间和周期口径。
+
+归一不等于覆盖原始数据。每个标准表达都必须能追溯到原始名称和来源。
+
+### 6.2 意图挂树
+
+优先挂靠现有正式树节点。
+
+如果现有树无法准确表达需求:
+
+1. 挂到当前最可靠的上级节点;
+2. 标记表达缺口;
+3. 进入候选节点治理区;
+4. 由人工审核是否需要增加正式节点。
+
+Agent 不直接修改正式分类树。
+
+### 6.3 需求合并
+
+多种来源命中同一个需求时,不按来源拆成重复需求,而是合并为一个平台需求节点。
+
+建议以以下组合判断需求是否相同:
+
+```text
+核心用户意图 + 关键对象 + 适用范围或约束
+```
+
+例如:
+
+- “毛泽东抗战时期写的诗”
+- “毛泽东在抗日战争阶段创作的诗词”
+
+可以合并为同一平台需求,并保留两个原始表达。
+
+但下面两条不应简单合并:
+
+- “毛泽东在抗日战争时期创作过哪些诗词”
+- “毛泽东的抗战诗词表达了什么情感”
+
+前者关注作品事实,后者关注作品解读,用户意图不同。
+
+### 6.4 少量邻近推演
+
+只有在已有数据能够支持时,才允许生成邻近机会需求。
+
+例如上游同时反复出现:
+
+- 毛泽东;
+- 抗日战争;
+- 解放战争;
+- 诗词创作;
+
+系统可以提出:
+
+> 从抗日战争到解放战争,毛泽东诗词主题发生了什么变化
+
+但必须说明:
+
+- 它由哪些上游关联组合而来;
+- 上游是否直接出现过该完整需求;
+- 哪些部分属于模型推断;
+- 当前属于核心需求还是机会需求。
+
+### 6.5 从视频和语言证据中提取需求
+
+需求不仅可以直接来自上游需求名称,也可以从节点下挂的真实内容中被发现。
+
+提取过程应遵循:
+
+1. 从分类节点下的高频、高表现元素开始;
+2. 找到承载这些元素的真实视频;
+3. 从视频转写和解析结果中抽取明确事实、观点和问题;
+4. 对多个视频的语言单元进行归并和比较;
+5. 形成有真实内容依据的需求候选;
+6. 将候选需求挂回一个或多个正式分类节点;
+7. 与已有平台需求去重或合并;
+8. 标记数据来源、视频证据和推断部分。
+
+例如,“毛泽东、抗日战争、解放战争、诗词创作”这些元素分别在多条视频中共同出现,并形成以下语言证据:
+
+- 毛泽东为何在战争时期持续进行诗词创作;
+- 战争环境如何影响诗词主题;
+- 抗日战争和解放战争时期的作品表达有何变化。
+
+系统可以据此提取平台需求,但不能只凭模型常识生成。每一条需求都必须能够回到具体视频和语言证据。
+
+---
+
+## 7. 需求—内容—线上表现闭环
+
+真实线上反馈不是普通的附属指标,而是需求汇总系统的核心后验闭环。
+
+```text
+平台需求
+   ↓
+找到或生产内容
+   ↓
+内容上线和分发
+   ↓
+获得真实线上表现
+   ↓
+校正并归因到需求
+   ↓
+更新需求强度
+   ↓
+调整下一周期供给
+```
+
+### 7.1 建立需求与内容的映射
+
+如果需求和内容之间没有明确映射,线上表现就无法准确回流。
+
+每条上线内容至少需要说明:
+
+- 主要承接哪个平台需求;
+- 是否辅助承接其他需求;
+- 对需求的覆盖程度;
+- 内容上线时间;
+- 当前是否形成有效样本。
+
+### 7.2 线上表现不能直接等同于需求表现
+
+内容表现还会受以下因素影响:
+
+- 内容本身质量;
+- 标题、封面和表达方式;
+- 分发流量;
+- 发布时间;
+- 平台环境;
+- 同类内容竞争;
+- 供给数量;
+- 样本量是否充足。
+
+因此需要把真实表现经过归因校正后,再反向更新需求强度。
+
+不能因为一条质量较差的内容表现不好,就直接判定需求不存在。
+
+### 7.3 反馈影响需求强度
+
+真实线上反馈应当能够:
+
+- 验证一个新需求是否真实成立;
+- 提高持续表现良好需求的强度;
+- 降低持续表现较差需求的优先级;
+- 判断某个需求是否已经过度供给;
+- 发现先验热度不高但真实表现很好的潜在需求;
+- 影响分类树中相关节点的整体强度;
+- 影响下一周期的主题配额和供给策略。
+
+---
+
+## 8. 需求强度模型
+
+需求不能只保留一个不可解释的总分。
+
+每条需求应至少保留“四类分数 + 一个综合等级”。
+
+### 8.1 先验需求分
+
+回答:
+
+> 在内容上线验证之前,这个需求有多值得尝试?
+
+主要来源:
+
+- 外部热度;
+- 平台近期供需缺口;
+- 平台持续热度;
+- 去年同期或周期性热度;
+- 上游来源数量;
+- 样本量和数据时效性。
+
+这些维度应保持正交,分别展示,然后再形成先验综合判断。
+
+### 8.2 线上验证分
+
+回答:
+
+> 内容实际承接该需求后,这个需求是否真实成立?
+
+主要来源:
+
+- 真实 ROV;
+- 真实 VOV;
+- 消费、互动或转化表现;
+- 多条内容的一致性;
+- 多个周期的稳定性;
+- 归因校正结果。
+
+### 8.3 关系增益分
+
+回答:
+
+> 图上的关系是否进一步增强了该需求成立的可能性?
+
+关系增益只作为低权重补充,不能代替原始数据。
+
+### 8.4 风险抑制分
+
+主要风险包括:
+
+- 后验效果持续较差;
+- 数据维度之间明显冲突;
+- 样本量不足;
+- 数据过期;
+- 内容承接失败;
+- 同类需求过度重复;
+- 某个主题过度集中;
+- 需求主要来自自由推演;
+- 关系推断置信度较低。
+
+### 8.5 综合需求强度
+
+业务上可以将其理解为:
+
+```text
+最终需求强度
+= 先验需求强度
++ 经归因校正的线上验证强度
++ 低权重关系增益
+- 风险抑制
+```
+
+具体权重不应在业务框架阶段固定死,应根据历史验证逐步校准。
+
+无论最终采用什么权重,都必须能够展开查看各个组成部分,避免形成黑盒分数。
+
+---
+
+## 9. 需求生命周期
+
+需求是动态实体,不是一经生成就永久有效。
+
+建议设置以下生命周期状态。
+
+### 9.1 新机会
+
+先验信号明显,但尚未有足够内容和线上反馈。
+
+### 9.2 待验证
+
+已经找到或安排了承接内容,正在等待有效线上样本。
+
+### 9.3 增长需求
+
+先验信号增强,或者真实线上表现持续改善。
+
+### 9.4 已验证需求
+
+已经由足量内容、有效样本或多个周期的表现证明。
+
+### 9.5 观察需求
+
+存在一定信号,但样本较少、数据冲突或结论不稳定。
+
+### 9.6 衰退需求
+
+需求热度、真实表现或用户兴趣持续下降。
+
+### 9.7 抑制需求
+
+经过验证后确认当前不值得继续投入,或供给已经明显过量。
+
+### 9.8 周期需求
+
+当前强度下降,但预计会在特定日期、节日、纪念日或社会周期重新激活。
+
+### 9.9 新老需求公平
+
+没有后验数据不等于后验表现差。
+
+为了避免旧需求永久占据高位:
+
+- 新需求主要依据先验分进入探索区;
+- 老需求的历史表现需要时间衰减;
+- 每个主题保留一定探索额度;
+- 只有形成有效样本后才提高后验权重;
+- 已验证需求也要接受持续复验。
+
+---
+
+## 10. 主题方向与数百条需求的组织
+
+最终输出采用两层结构。
+
+### 10.1 上层:主题方向
+
+主题方向不是另建一棵脱离现有分类树的新树。
+
+它应主要来自:
+
+- 全局分类树的中高层节点;
+- 某个树分支下的需求聚类;
+- 多个相关分支共同形成的稳定业务方向。
+
+例如:
+
+- 历史人物故事;
+- 历史人物个人经历;
+- 战争历史与人物;
+- 历史人物作品解读;
+- 历史事件影响;
+- 人物精神与情感。
+
+每个主题方向应包含:
+
+- 主题名称;
+- 对应的分类树范围;
+- 覆盖的用户意图;
+- 需求数量;
+- 各生命周期数量;
+- 整体需求强度;
+- 主要数据来源;
+- 趋势;
+- 需求集中度;
+- 探索需求占比。
+
+### 10.2 下层:平台需求
+
+每条平台需求应包含:
+
+- 唯一需求 ID;
+- 标准需求名称;
+- 原始需求表达;
+- 多个正式挂靠节点;
+- 可选的统计主归属节点;
+- 每个挂靠点的理由和证据;
+- 关联需求元素;
+- 原始关联边;
+- 推断语义边及说明;
+- 所属主题方向;
+- 各维先验信号;
+- 线上验证结果;
+- 关联内容及归因情况;
+- 需求强度;
+- 生命周期;
+- 是否属于推演需求;
+- 风险和抑制原因;
+- 数据更新时间;
+- 强度变化历史。
+
+### 10.3 需求数量分配
+
+数百条需求不按主题平均分配,也不能完全被少数热门主题占满。
+
+采用:
+
+> 数据驱动为主,最低覆盖和最高集中度约束为辅。
+
+具体原则:
+
+- 强信号主题可以拥有更多需求;
+- 弱主题允许较少需求;
+- 无真实信号的主题可以暂时为空;
+- 重要主题保留最低覆盖;
+- 单一主题设置最高集中度;
+- 每个主题保留少量探索位;
+- 推演需求总量保持在受控范围。
+
+---
+
+## 11. 最终展示方式
+
+最终使用同一份需求数据提供两个入口。
+
+### 11.1 全局树图入口
+
+从左向右浏览:
+
+```text
+L1 → L2 → L3 → L4 → L5 → 挂载需求
+```
+
+树图中需要保留:
+
+- 原有树内父子线;
+- 分类节点的需求数量和强度;
+- 平台需求与多个正式树节点之间的挂靠线;
+- 可选的统计主归属标记;
+- 跨分支关联线;
+- 原始关联与推断关系的区别;
+- 需求与内容的承接关系;
+- 线上反馈回流关系。
+
+用户点击某条需求后,应能看到完整追溯链路:
+
+```text
+上游数据
+→ 原始需求表达
+→ 标准化过程
+→ 多个挂靠节点及各自理由
+→ 关联元素
+→ 原始及推断关系
+→ 关联内容
+→ 线上表现
+→ 需求强度变化
+```
+
+### 11.2 需求清单入口
+
+以业务执行为目的,支持按以下维度查看:
+
+- 主题方向;
+- 需求强度;
+- 生命周期;
+- 多个挂靠节点;
+- 可选的统计主归属节点;
+- 数据来源;
+- 是否已经验证;
+- 是否已经有内容承接;
+- 是否存在供需缺口;
+- 是否属于推演需求;
+- 更新时间。
+
+树图入口和清单入口指向同一批需求实体,不维护两套独立结果。
+
+---
+
+## 12. 分类树治理
+
+现有分类树是基础权威骨架,但不是永远不变。
+
+### 12.1 正式节点
+
+已经审核并进入全局分类树,可以作为需求挂靠节点和统计归属节点。
+
+### 12.2 候选节点
+
+当大量上游需求反复出现,而现有树无法准确表达其核心意图时,可以提出候选节点。
+
+候选节点必须说明:
+
+- 哪些需求无法被现有节点准确表达;
+- 当前临时挂靠在哪里;
+- 出现频率和持续周期;
+- 预期父节点;
+- 与现有节点的差异;
+- 新增后能解决什么业务问题。
+
+### 12.3 人工审核
+
+Agent 只能提出候选节点,不能直接修改正式树。
+
+人工审核后可以:
+
+- 接受为正式节点;
+- 与现有节点合并;
+- 继续观察;
+- 拒绝新增。
+
+---
+
+## 13. 业务质量控制
+
+### 13.1 可追溯
+
+任何平台需求必须能够追溯到上游数据。
+
+### 13.2 可解释
+
+必须解释:
+
+- 为什么形成该需求;
+- 为什么挂在这些节点;
+- 为什么与其他表达合并或不合并;
+- 为什么获得当前强度和生命周期;
+- 线上反馈如何影响了它。
+
+### 13.3 防止过度聚合
+
+一个平台需求应表达一个清晰的用户意图。
+
+不能将大量弱相关人物、事件、作品和情感塞入一个“大合集需求”。
+
+### 13.4 防止过度拆分
+
+同一用户意图仅因为来源、措辞或时间不同,不应被拆成多个重复需求。
+
+### 13.5 防止自由推演失控
+
+所有推演需求必须:
+
+- 有数据起点;
+- 有推演路径;
+- 有置信度;
+- 有独立标识;
+- 有比例限制;
+- 可以被人工拒绝。
+
+### 13.6 防止后验误判
+
+线上反馈必须经过归因和样本校正,避免将内容质量、流量不足或供给不足误认为需求无效。
+
+---
+
+## 14. 项目业务模块的总体框架
+
+从业务职责看,整个项目可以划分为九个部分。
+
+### 14.1 信号接入
+
+负责接收内外部、近期远期、周期性和真实反馈数据。
+
+### 14.2 需求理解
+
+负责标准化原始表达、识别需求元素、保留来源和原始关联。
+
+### 14.3 分类树挂靠
+
+负责为需求建立正式分类坐标,并发现分类树表达缺口。
+
+### 14.4 树图汇总
+
+负责把分类树、需求元素、需求节点和关系边组织成统一业务图。
+
+### 14.5 元素与内容下钻
+
+负责展示分类节点下的细节元素,并将元素连接到真实视频、内容标签、转写和线上表现。
+
+### 14.6 语言观点与讨论提取
+
+负责从真实视频中提取明确事实、观点、问题和长段讨论,并完整保留视频依据和推断说明。
+
+### 14.7 需求生成与合并
+
+负责形成唯一平台需求,控制需求粒度,避免重复和过度聚合。
+
+### 14.8 需求决策
+
+负责计算需求强度、生命周期、主题配额和内容供给优先级。
+
+### 14.9 内容反馈闭环
+
+负责把需求与内容连接起来,并将内容真实线上表现回流到需求和分类节点。
+
+整体业务关系是:
+
+```text
+信号接入
+   ↓
+需求理解
+   ↓
+分类树挂靠
+   ↓
+树图汇总
+   ↓
+元素与视频下钻
+   ↓
+语言观点与讨论提取
+   ↓
+需求生成与合并
+   ↓
+需求决策
+   ↓
+内容承接和线上反馈
+   └──────────────→ 回到需求决策和树图强度
+```
+
+---
+
+## 15. 一句话总结
+
+SupplyAgent 的最终业务框架是:
+
+> 以一棵全局分类树作为稳定骨架,把上游多源需求统一挂树;以平台需求作为独立图节点连接多个分类分支和具体需求元素;以原始数据决定需求是否成立,以低权重语义推断补充关系,以内容真实线上表现持续反向更新需求强度,最终形成几十个主题方向和数百条可执行、可解释、可追溯的平台需求。
+
+---
+
+## 16. 业务可视化资料与服务
+
+本次业务框架讨论过程中形成的全部可视化材料统一保存在:
+
+```text
+visualization/
+```
+
+目录中同时包含:
+
+- 业务图结构方案;
+- 从左向右的树图示意;
+- 业务节点和关系模型;
+- 需求—内容—线上表现反馈闭环;
+- 最终主题和平台需求输出结构;
+- 对话过程中的阶段性可视页面;
+- 用户提供的全局分类树局部参考图;
+- 用于本地浏览全部图稿的可视化服务。
+
+目录结构如下:
+
+```text
+visualization/
+├── README.md
+├── run.sh
+├── assets/
+│   └── tree.jpeg
+├── pages/
+│   ├── graph-structure-options.html
+│   ├── graph-structure-left-to-right.html
+│   ├── business-graph-model.html
+│   ├── demand-feedback-loop.html
+│   ├── final-output-structure.html
+│   ├── node-drilldown-evidence-chain.html
+│   ├── waiting-business-scope.html
+│   ├── waiting-demand-pipeline.html
+│   └── waiting-strength-lifecycle.html
+└── service/
+    └── serve.py
+```
+
+### 16.1 启动可视化服务
+
+在项目根目录执行:
+
+```bash
+bash visualization/run.sh
+```
+
+服务默认使用:
+
+```text
+http://localhost:8765/
+```
+
+需要指定端口时:
+
+```bash
+bash visualization/run.sh --port 9000
+```
+
+如果不希望自动打开浏览器:
+
+```bash
+python3 visualization/service/serve.py
+```
+
+服务只依赖 Python 标准库,不要求安装额外前端依赖。
+
+### 16.2 图稿与最终业务口径的关系
+
+`visualization/pages/` 保留了整个讨论过程,因此早期图稿可能包含后来被修正的中间方案。
+
+最终应以本文档的业务定义为准:
+
+- 整体只有一棵全局分类树;
+- 分类树从左向右按层级展开;
+- 平台需求是独立的图节点;
+- 一条需求可以同时挂靠多个正式树节点;
+- 多个挂靠点共同定义需求,不强制区分业务主次;
+- 如统计需要唯一口径,可以另设“统计主归属节点”;
+- 上游原始“关联”边永久保留;
+- 推断语义关系必须附带说明、来源和置信度;
+- 内容的真实线上表现必须反向更新需求强度。
+
+### 16.3 各图稿用途
+
+| 图稿 | 主要用途 |
+|---|---|
+| `graph-structure-options.html` | 记录单一大树、自由图和树骨架关系图三种方案的比较 |
+| `graph-structure-left-to-right.html` | 确认整体从左向右的阅读方式 |
+| `business-graph-model.html` | 说明分类节点、需求元素、平台需求、关系和证据 |
+| `demand-feedback-loop.html` | 说明需求如何找到或生产内容,以及线上表现如何回流 |
+| `final-output-structure.html` | 说明主题方向、数百条平台需求和证据卡如何组织 |
+| `node-drilldown-evidence-chain.html` | 说明分类节点如何继续下挂元素、视频、明确观点、长段讨论并提取需求 |
+| `waiting-*.html` | 保留对话过程中的阶段性页面 |
+| `assets/tree.jpeg` | 作为现有全局分类树结构和阅读方式的参考 |
+| `assets/tree2.png` | 作为分类节点下挂大量细节元素的参考 |
+| `assets/case.jpeg` | 作为元素扩展为明确语言、长段讨论和最终选题的参考 |
+
+
+# SupplyAgent 代码仓库结构总结
+
+## 1. 阅读基线
+
+本文档完全基于当前代码仓库重新阅读后形成,不继承此前对项目的业务推演或可视化设计理解。
+
+代码快照:
+
+- 分支:`feature/zhangbo`
+- 阅读时提交:`2ab77ce`
+- Python 要求:`>= 3.11`
+- 后端:FastAPI + SQLAlchemy 2.x + PyMySQL
+- Agent:OpenRouter/OpenAI 兼容 API + 自研 Tool/Skill/ReAct 框架
+- 数据源:ODPS(MaxCompute)
+- 数据库:MySQL
+- 对象存储:阿里云 OSS
+- 前端:Vue 3 + TypeScript + Vite
+
+`.env` 已被 `.gitignore` 忽略。本文不会记录其中的密码、密钥、数据库地址或 Token。
+
+---
+
+## 2. 当前项目的实际定位
+
+当前 SupplyAgent 由两部分组成:
+
+1. 一套通用 AI Agent 运行框架;
+2. 一套围绕“需求词、全局分类树、热度、视频和需求生成”的业务系统。
+
+业务系统当前主要完成:
+
+- 从 ODPS 同步全局分类树和树下元素;
+- 从 ODPS 同步多策略需求池;
+- 将需求词挂到分类树节点;
+- 汇总四项先验热度和真实 ROV/VOV;
+- 把词级热度沿分类树向上聚合;
+- 按单一热度维度生成并保存平台需求;
+- 把需求词连接到真实视频和视频最终选题;
+- 通过 API 和 Vue 页面展示分类树、热力图和下钻证据;
+- 记录 Agent 完整执行过程,生成 HTML,上传 OSS 并在 MySQL 留档。
+
+当前系统的核心业务链路是:
+
+```text
+ODPS 全局分类与元素
+        ↓
+MySQL 全局分类树
+        ↑
+需求池词语 → 归类 Agent → 需求词挂靠
+        ↓
+四项先验 + 真实 ROV/VOV
+        ↓
+词级统计 → 分类树节点聚合 → 四维全局排名
+        ↓
+需求生成 Agent → generated_demand
+        ↓
+FastAPI → Vue 分类树/热力图/证据下钻
+```
+
+---
+
+## 3. 仓库分层
+
+```text
+SupplyAgent/
+├── supply_agent/       通用 Agent 框架
+├── agents/             业务 Agent 和专属工具
+├── supply_infra/       MySQL、ODPS、OSS、定时任务
+├── api/                FastAPI 查询接口和静态前端托管
+├── web/                Vue 3 业务前端
+├── scripts/            部署、日志上传、日志可视化脚本
+├── visualization/      早期/独立的业务设计可视化材料
+├── Dockerfile          前端构建 + Python 运行镜像
+├── pyproject.toml      Python 包、依赖和命令入口
+└── requirements.txt    另一份运行依赖清单
+```
+
+任务 CLI 已并入 `supply_infra/scheduler/jobs/`(`python -m ...`)。
+
+模块之间的依赖方向:
+
+```text
+web
+  ↓ HTTP
+api
+  ↓
+supply_infra.db.repositories
+  ↓
+MySQL
+
+agents
+  ↓
+supply_agent(Agent 框架)
+  ↓
+supply_infra(数据库/ODPS/OSS)
+
+jobs / scheduler
+  ↓
+supply_infra.scheduler.jobs
+  ↓
+ODPS + MySQL + 业务 Agent
+```
+
+---
+
+## 4. 通用 Agent 框架:`supply_agent/`
+
+### 4.1 `supply_agent/config.py`
+
+负责 Agent 侧配置:
+
+- OpenRouter API Key、模型和 Base URL;
+- Agent 最大迭代次数和温度;
+- Skills 目录;
+- 日志目录和日志开关。
+
+配置来自环境变量或项目根目录 `.env`,相对路径会解析到项目根目录。
+
+### 4.2 `supply_agent/llm/client.py`
+
+基于 OpenAI Python SDK 连接 OpenRouter,提供:
+
+- 同步对话 `chat`;
+- 异步对话 `achat`;
+- 同步文本流 `stream`;
+- 异步文本流 `astream`;
+- Tool Calling;
+- OpenRouter reasoning effort;
+- LLM 输入和输出日志。
+
+模型可以在运行时切换。
+
+### 4.3 `supply_agent/tools/`
+
+`base.py` 提供:
+
+- `@tool` 装饰器;
+- 从 Python 函数签名生成 JSON Schema;
+- Optional 和基础类型转换;
+- 同步/异步工具执行;
+- 异常转为 JSON 错误结果。
+
+`registry.py` 提供:
+
+- 工具注册、删除和查询;
+- OpenAI ToolDefinition 列表;
+- 根据模型返回的工具名执行工具;
+- 同步和异步执行;
+- 批量注册被 `@tool` 装饰的函数。
+
+### 4.4 `supply_agent/skills/`
+
+Skill 机制读取指定目录下的 `SKILL.md`:
+
+- 支持 YAML frontmatter 的名称和描述;
+- 启动时把 Skill 目录作为目录索引加入系统提示词;
+- Agent 通过内置 `load_skill` 工具按需加载全文;
+- Skill 加载后会重建系统消息并注入当前上下文。
+
+当前仓库根目录的 `skills/` 被 `.gitignore` 忽略,因此代码支持 Skill,但仓库没有可随代码分发的业务 Skill 内容。
+
+### 4.5 `supply_agent/agent/`
+
+`core.py` 的 `Agent` 负责组装:
+
+- LLMClient;
+- ToolRegistry;
+- SkillRegistry;
+- AgentLoop;
+- AgentLogger。
+
+对外提供:
+
+- `run`;
+- `arun`;
+- `stream`;
+- `astream`。
+
+`loop.py` 实现标准 ReAct/Tool Calling 循环:
+
+```text
+系统消息 + 对话历史
+        ↓
+调用 LLM
+        ↓
+有工具调用?──否──→ 返回最终结果
+        │是
+        ↓
+执行工具并写入 Tool Message
+        ↓
+下一轮 LLM
+```
+
+达到最大迭代次数时,同步和普通异步运行会追加一条用户消息,要求模型给出当前最佳答案;流式路径则直接发出 Max iterations reached。
+
+### 4.6 `supply_agent/logging/`
+
+每次 Agent 运行生成:
+
+- 人类可读 `.log`;
+- 结构化 `.jsonl`。
+
+日志记录:
+
+- run_start;
+- 完整 LLM 输入;
+- 模型输出和 reasoning;
+- 工具调用参数和结果;
+- Skill 加载;
+- run_end。
+
+运行结束后:
+
+1. 将日志渲染成 HTML;
+2. 上传 `.log`、`.jsonl`、`.html` 到 OSS;
+3. 把 HTML 公网地址写入 `oss_logs`;
+4. 上传失败只记录错误,不影响 Agent 主结果。
+
+---
+
+## 5. 三个业务 Agent
+
+## 5.1 `demand_belong_category_agent`
+
+目标:把需求词挂到真实存在的全局分类树节点。
+
+工具:
+
+- `query_global_tree_category`:读取整棵树或指定子树;
+- `batch_insert_demand_belong_category`:批量写入需求词、分类 ID 和原因。
+
+业务流程:
+
+1. 查看顶层分类;
+2. 选择最相关分支;
+3. 逐层下钻;
+4. 不确定时停在更可靠的上层节点;
+5. 将结果写入 `demand_belong_category`。
+
+系统提示允许一个词选择一个或多个高置信节点,但当前数据库和写入工具以 `name` 唯一:
+
+- `demand_belong_category.name` 有唯一约束;
+- 同一次请求也按 name 去重;
+- 因此当前实现实际上只能保存“一词一个分类节点”;
+- 多挂靠尚未在当前表结构中实现。
+
+定时任务会把新需求词按 100 个一批交给该 Agent。
+
+## 5.2 `generate_demand_agent`
+
+目标:从分类树局部热度和已挂靠需求词中,按单一维度生成平台需求结果。
+
+支持的来源维度只有四项先验:
+
+- `ext_pop`:外部热度;
+- `plat_sust_pop`:平台持续热度;
+- `plat_ly_pop`:平台去年同期热度;
+- `recent_pop`:近期热度。
+
+一次运行只允许处理一个维度。
+
+工具:
+
+- `query_latest_biz_dt`:取两张统计表都有数据的最新日期;
+- `query_category_tree_by_dim`:查看指定维度有数据的树;
+- `query_category_leaves_by_dim`:定位有数据的叶子节点;
+- `query_demand_words_by_category`:查询节点或子树下的真实需求词;
+- `query_category_path`:补充根到节点的路径;
+- `batch_save_generated_demands`:写入 `generated_demand`。
+
+输出结构固定为:
+
+```text
+source_dim
+  └── overall_direction
+        └── summary_event
+              └── demand_name
+```
+
+重要约束:
+
+- `demand_name` 必须原样来自 `demand_belong_category.name`;
+- Agent 不能新造需求词;
+- `summary_event` 尽量对应一个需求,最多轻量合并 2~3 个强相关需求;
+- 写入时保存类目、路径、维度 avg/count 快照、reason、业务日和 run_id;
+- 同一次工具调用按 `(source_dim, demand_name)` 去重;
+- 当前 `generated_demand` 没有数据库唯一约束,不同 run 可以重复生成相同需求。
+
+真实 ROV/VOV 当前不属于该 Agent 的 `source_dim`,也没有参与其单维生成工具链。
+
+## 5.3 `find_agent`
+
+目标:根据需求词、参考视频标题和相关点,寻找老年受众更可能观看和分享的抖音视频。
+
+当前注册的业务工具包括:
+
+- `douyin_search`:调用外部抖音关键词搜索服务;
+- `douyin_search_tikhub`:调用 TikHub 搜索并保留 search_id/backtrace 分页状态;
+- `douyin_user_videos`:按作者 sec_uid、排序和游标扩展历史作品;
+- `douyin_detail`:按 content_id 获取视频详情和可播放地址;
+- `get_content_fans_portrait`:获取视频点赞用户画像;
+- `get_account_fans_portrait`:获取作者粉丝画像;
+- `batch_fetch_portraits`:批量获取视频画像,并可同时获取作者画像;
+- `normalize_age_portraits`:标准化 `50-` 等年龄桶及双侧证据;
+- `audit_video_discovery_process`:结束前审计多词、翻页、扩展、证据和双池分流;
+- `qwen_video_analyze`:调用千问视频模型解析视频;
+- `create_video_discovery_run`:创建可追踪的找片运行;
+- `record_video_search_page`:保存 Agent 自主搜索词、扩展来源、游标与本页结果;
+- `batch_save_video_candidate_evaluations`:保存证据、评分并分为正式推荐/人工备选/淘汰;
+- `query_video_discovery_state`:查询搜索树和候选分池;
+- `review_video_discovery_candidate`:记录用户对推荐或备选的人工选择结果。
+
+搜索和详情接口有约 10 秒的请求间隔限制。
+
+Agent 以需求相关性、老年受众倾向和分享价值的联合目标做判断。系统提示明确区分
+“分享量高”和“受众偏老”两类证据,使用视频点赞画像作为内容侧证据、作者粉丝画像
+作为账号先验,并对画像缺失或冲突降低置信度。搜索词由 Agent 根据需求、参考标题、
+相关点和途中发现的有效标签自主决定;支持多关键词、游标翻页和标签扩展。与需求无关
+但老年倾向、分享价值双高的视频保存在人工备选池。
+
+搜索过程持久化到:
+
+- `video_discovery_run`:任务输入、意图、状态与计数;
+- `video_discovery_search`:逐关键词、逐游标页的搜索轨迹;
+- `video_discovery_candidate`:视频详情、双侧画像、标签、评分、分池与人工审核状态。
+
+---
+
+## 6. 基础设施:`supply_infra/`
+
+### 6.1 配置
+
+`supply_infra/config.py` 管理:
+
+- MySQL;
+- ODPS;
+- APScheduler;
+- 阿里云 OSS;
+- Agent 日志上传开关。
+
+配置文件固定从项目根目录 `.env` 读取,不依赖当前工作目录。
+
+### 6.2 数据库会话
+
+`supply_infra/db/session.py`:
+
+- 懒加载全局 SQLAlchemy Engine;
+- 使用连接池和 `pool_pre_ping`;
+- `get_session()` 自动提交;
+- 异常时自动回滚;
+- `init_db()` 通过 ORM metadata 创建缺失表。
+
+### 6.3 Repository 规则
+
+业务 Agent、API 和定时任务原则上不直接执行 MySQL SQL,而是通过 Repository:
+
+- 基础 CRUD;
+- 批量插入;
+- insert ignore;
+- upsert;
+- 条件查询;
+- 批量更新。
+
+ODPS 查询仍在 `supply_infra/odps/client.py` 内直接组织 SQL。
+
+### 6.4 ODPS 客户端
+
+当前读取的主要 ODPS 数据:
+
+- `public_pattern_mining_category`:全局分类;
+- `pattern_mining_element`:树下元素;
+- `dwd_multi_demand_pool_di`:多策略需求池;
+- `dwd_topic_decode_result_di`:视频解析和最终选题;
+- `dwd_video_produce_plan_stat_hour`:真实 ROV/VOV。
+
+### 6.5 OSS 客户端
+
+负责:
+
+- 生成对象路径;
+- 上传本地文件;
+- 返回 CDN 公网地址。
+
+---
+
+## 7. MySQL 数据模型
+
+当前 ORM 定义 10 张表。
+
+| 表 | 作用 | 关键唯一性/关联 |
+|---|---|---|
+| `global_tree_category` | 全局分类树节点 | `source_id` 唯一;`parent_id` 形成树 |
+| `global_tree_element` | ODPS 元素与分类挂靠 | `(name, category_id)` 唯一 |
+| `multi_demand_pool_di` | 按日同步的策略需求池 | 代码按 `(strategy, demand_id, biz_dt)` 管理差异 |
+| `demand_belong_category` | 需求词归属分类 | `name` 唯一;当前一词只能保存一个分类 |
+| `demand_belong_pool_rel` | 需求词与需求池行的匹配边 | `(demand_belong_category_id, multi_demand_pool_di_id)` 唯一 |
+| `demand_popularity_stats` | 词级六维 avg/count | `(demand_category_id, biz_dt)` 唯一 |
+| `category_tree_weight` | 分类树节点六维聚合和四维排名分 | `(category_id, biz_dt)` 唯一 |
+| `multi_demand_video_detail` | 视频标题与最终选题 JSON | `vid` 唯一 |
+| `generated_demand` | 需求生成 Agent 输出 | 按 run_id 记录,无数据库唯一约束 |
+| `oss_logs` | Agent 日志 HTML 的 OSS 地址 | 按 agent_name 查询 |
+
+### 7.1 关键关系
+
+```text
+global_tree_category.id
+  ├── global_tree_category.parent_id
+  ├── global_tree_element.category_id
+  ├── demand_belong_category.category_id
+  ├── category_tree_weight.category_id
+  └── generated_demand.category_id
+
+demand_belong_category.id
+  ├── demand_popularity_stats.demand_category_id
+  ├── demand_belong_pool_rel.demand_belong_category_id
+  └── generated_demand.demand_belong_id
+
+multi_demand_pool_di.id
+  └── demand_belong_pool_rel.multi_demand_pool_di_id
+```
+
+这些关联在 ORM 中主要以整数 ID 表达,没有使用 SQLAlchemy relationship,也没有显式数据库 ForeignKey。
+
+---
+
+## 8. 热度数据的真实代码口径
+
+### 8.1 策略到四项先验的映射
+
+代码把需求池策略映射为:
+
+| ODPS strategy | 统计字段 | 页面含义 |
+|---|---|---|
+| `新热事件` | `ext_pop` | 外部热度 |
+| `逐月` | `plat_sust_pop` | 平台持续热度 |
+| `去年同期阳历` | `plat_ly_pop` | 去年同期热度 |
+| `去年同期阴历` | `plat_ly_pop` | 去年同期热度 |
+| `当下供需gap` | `recent_pop` | 近期热度 |
+
+### 8.2 真实 ROV/VOV
+
+从近 7 日 `dwd_video_produce_plan_stat_hour` 获取人工 AGC 和自动 AGC 数据:
+
+- ROV = 回流 UV / 分发曝光 PV;
+- VOV = 拉回曝光 PV / 分发曝光 PV;
+- 同一特征值存在多行时,优先保留 `rov_diff`、`vov_diff` 较高的一行;
+- 按特征值与 `demand_name` 精确匹配,回填 `multi_demand_pool_di`。
+
+### 8.3 词级统计
+
+对每个 `demand_belong_category.name`:
+
+1. 在当日 `multi_demand_pool_di.demand_name` 中执行子串 LIKE 匹配;
+2. 按策略收集非零 weight;
+3. 分别计算四项先验的 avg/count;
+4. 汇总匹配行的真实 ROV/VOV avg/count;
+5. 写入 `demand_popularity_stats`。
+
+因此当前词与需求池的匹配核心是字符串包含关系,不是分词索引、向量匹配或显式语义关系。
+
+### 8.4 分类树节点聚合
+
+分类节点聚合六个独立维度:
+
+- 外部热度;
+- 平台持续热度;
+- 去年同期热度;
+- 近期热度;
+- 真实 ROV;
+- 真实 VOV。
+
+每个节点统计其整个子树内有需求词挂靠的节点:
+
+```text
+节点维度 avg = Σ(挂靠点 avg × count) / Σ(count)
+节点维度 count = Σ(count)
+```
+
+结果写入 `category_tree_weight`。
+
+### 8.5 四维排名分和全局热度
+
+`demand_pool/tree_weight.py` 在写入权重后会对四项先验排名:
+
+- 各维只让 `count > 0` 的节点参与;
+- 按 avg 降序排名;
+- 同分取平均名次;
+- 映射到 `(0, 1]`;
+- 无数据节点为 0;
+- `total_score` 是四个排名分直接相加,范围 `[0, 4]`。
+
+真实 ROV/VOV 会被聚合并通过 API 返回,但当前不进入 `total_score`。
+
+前端显示“全局热度”时再使用 `total_score / 4` 映射为 `0~1` 色阶。
+
+单一维度热度则由前端根据该维所有有数据节点的 avg 做百分位色阶,不直接使用数据库中的四维 rank score 字段。
+
+---
+
+## 9. 定时任务和数据流水线
+
+### 9.1 已注册的定时任务
+
+`supply_infra/scheduler/app.py` 当前只注册一条任务:
+
+1. 每天 `15:00`(`SCHEDULER_TIMEZONE`):串行执行全链路
+   `run_supply_pipeline`(全局树 → 需求池 → 分级 → 拓展 → 找片 → AIGC 发布)。
+
+### 9.2 全局树同步
+
+`sync_global_tree_odps_to_mysql`:
+
+1. 拉取有效元素;
+2. 拉取全部分类;
+3. 从元素命中的分类向上补齐祖先;
+4. 按 ODPS source_id 去重;
+5. 已有分类保持不变,只插入新分类;
+6. 给新分类分配 MySQL ID 并转换 parent_id;
+7. 写入元素及其 MySQL category_id。
+
+该任务是增量插入,不会根据 ODPS 当前状态自动删除或更新历史分类。
+
+### 9.3 策略需求池完整流水线
+
+`supply_infra.scheduler.jobs.demand_pool`(`sync_multi_demand_pool_odps_to_mysql`)实际执行顺序:
+
+1. 比较 ODPS 与 MySQL 当日去重行数;
+2. 行数不同时执行差异同步;
+3. 对当日所有 demand_name 按空格拆词;
+4. 调用归类 Agent 处理未出现过的新词;
+5. 建立需求词与需求池的子串匹配边,并回填词级 video_list;
+6. 获取并回填近 7 日真实 ROV/VOV;
+7. 计算词级六维 avg/count;
+8. 计算整棵分类树六维聚合;
+9. 计算四项先验全局排名分和 total_score;
+10. 同步全部待处理视频的标题和最终选题。
+
+当前有一个同步判断风险:只要 ODPS 和 MySQL 行数相同,就跳过需求池差异拉取;如果内容发生变化但总行数不变,该轮不会发现这些变化。
+
+### 9.4 手动任务入口
+
+用 `python -m` 调用(与定时流水线同源):
+
+- `python -m supply_infra.db`:初始化数据库;
+- `python -m supply_infra.scheduler.jobs.run_supply_pipeline`:全链路;
+- `python -m supply_infra.scheduler.jobs.demand_pool`:需求池同步(含内部阶段);
+- `python -m supply_infra.scheduler.jobs.grade_demand_pool`:分级(可加 `--retry-failed`);
+- 以及 global_tree / expand / discover / publish 各步骤模块。
+
+也可通过 API `POST /api/scheduler/jobs/{job_id}/run` 手动触发。
+
+---
+
+## 10. FastAPI:`api/`
+
+服务端口:`8080`。
+
+| 接口 | 作用 |
+|---|---|
+| `GET /health` | 健康检查 |
+| `GET /api/category-tree?biz_dt=YYYYMMDD` | 返回嵌套分类树、六维 avg/count、total_score 和挂靠词数 |
+| `GET /api/demand-belong-category` | 返回所有有效需求词挂靠 |
+| `GET /api/demand-belong-category/{id}/videos` | 返回需求词关联的视频标题和最终选题 JSON |
+| `GET /api/demand-belong-oss-logs` | 返回归类 Agent 的 OSS 日志列表 |
+
+如果 `web/dist` 存在,FastAPI 会把它挂到 `/`,同一个 8080 服务同时提供 API 和生产前端。
+
+API 当前是同步 SQLAlchemy 查询,没有分页、鉴权或缓存。
+
+---
+
+## 11. Vue 前端:`web/`
+
+### 11.1 路由
+
+| 路由 | 页面 |
+|---|---|
+| `/` | 平台全局需求地图 |
+| `/demand-tree` | 传统横向分类树 |
+| `/demand-process` | 需求归类 Agent 日志 |
+| `/demand-map` | 重定向到 `/` |
+
+当前顶部导航只显示“平台全局需求地图”,另外两个页面有路由但没有导航入口。
+
+### 11.2 平台全局需求地图
+
+`GlobalDemandMapView.vue` 并行读取:
+
+- 完整分类树和热度;
+- 全部需求词挂靠。
+
+`IcicleHeatTree.vue` 使用 Canvas 绘制从左到右的冰柱树:
+
+- 每层固定 `200px` 宽;
+- 全局状态适配视口高度;
+- 选择层级或聚焦节点后按可读高度纵向扩展;
+- 最大逻辑画布高度 `24000px`;
+- 实际 Canvas 始终只有视口大小,只绘制可见区域;
+- 普通滚轮滚动;
+- 拖拽平移;
+- `Ctrl/Command + 滚轮` 缩放;
+- 点击节点聚焦子树;
+- 支持层级起点和祖先面包屑。
+
+热力标签:
+
+- 全局树结构;
+- 全局热度 `total_score`;
+- 外部热度;
+- 平台持续热度;
+- 去年同期热度;
+- 近期热度。
+
+API 虽然返回真实 ROV/VOV,但当前冰柱图标签没有提供真实 ROV/VOV 的独立切换入口。
+
+### 11.3 节点证据下钻
+
+分类节点存在需求词时显示搜索标识。点击后通过 `DemandPathPanel.vue` 展开:
+
+```text
+当前分类节点
+  → 细节元素/需求词
+  → 真实视频实例
+  → 最终选题 JSON
+```
+
+这里展示的是 `demand_belong_category` 需求词,不是 `generated_demand` 中由生成 Agent 产出的四层平台需求。
+
+当前前端没有读取或展示 `generated_demand` 的 API。
+
+### 11.4 传统分类树页面
+
+`CategoryTree.vue` 使用 Vue DOM 递归组件展示:
+
+- 默认展开 3 层;
+- 支持选择展开深度;
+- 支持手动展开和收起;
+- 支持按维度过滤有数据的节点;
+- 支持拖动画布;
+- 支持导出包含数据的独立 HTML;
+- 同样可以下钻需求词、视频和最终选题。
+
+### 11.5 需求归类过程页面
+
+读取 `demand_belong_category_agent` 的 `oss_logs`,按时间倒序显示,点击打开 Agent 运行过程 HTML。
+
+---
+
+## 12. 部署和运行
+
+### 12.1 Python 命令入口
+
+`pyproject.toml` 注册:
+
+- `supply-api`;
+- `supply-visualize`。
+
+### 12.2 本地开发
+
+后端:
+
+```bash
+python -m api
+```
+
+前端:
+
+```bash
+cd web
+npm install
+npm run dev
+```
+
+Vite 在 `5173`,将 `/api` 代理到 `127.0.0.1:8080`。
+
+### 12.3 Docker
+
+Docker 使用两阶段构建:
+
+1. Node 20 构建 Vue;
+2. Python 3.11 安装项目和 ODPS 可选依赖;
+3. 把 `web/dist` 放入 Python 镜像;
+4. 通过 `python -m api` 启动 8080。
+
+`scripts/docker-deploy.sh` 可以构建并向指定镜像仓库推送时间戳标签和 `latest`。
+
+---
+
+## 13. 当前代码已经实现的能力
+
+- 通用同步/异步 Agent 和 Tool Calling;
+- 动态 Skill 加载机制;
+- 三个业务 Agent;
+- 全量 Agent 日志和 OSS 发布;
+- ODPS 到 MySQL 的全局树同步;
+- 多策略需求池增量同步;
+- 新词自动归类;
+- 需求词与需求池匹配边;
+- 真实 ROV/VOV 回填;
+- 词级六维统计;
+- 分类树六维向上聚合;
+- 四项先验排名和 total_score;
+- 单维度平台需求生成与落库;
+- 视频标题和最终选题同步;
+- FastAPI 查询接口;
+- Vue 全局冰柱热力图;
+- 分类节点到需求词、视频和最终选题的下钻;
+- Docker 构建和部署脚本。
+
+---
+
+## 14. 当前代码未完成或存在偏差的部分
+
+### 14.1 需求多挂靠尚未实现
+
+`demand_belong_category.name` 唯一,当前一个需求词只能保存一个 category_id。系统提示中的“一词多个节点”无法真实落库。
+
+### 14.2 `generated_demand` 未进入产品展示
+
+需求生成 Agent 已能写 `generated_demand`,但:
+
+- 没有对应 API;
+- 前端没有需求清单;
+- 没有与内容、反馈的展示闭环;
+- 当前全局图下钻的是需求词,不是最终生成需求。
+
+### 14.3 后验没有进入全局综合分
+
+真实 ROV/VOV 已采集、聚合并由 API 返回,但:
+
+- 不进入 `total_score`;
+- 不进入 generate_demand_agent 的 source_dim;
+- 当前主热力图没有 ROV/VOV 标签;
+- 尚未形成“后验反向调整最终需求排序”的完整实现。
+
+### 14.4 `find_agent` 的外部证据仍可增强
+
+当前已持久化搜索轨迹、正式推荐和人工备选,但画像接口提供的是点赞用户而非真实转发
+用户。后续若能补充转发用户画像、分年龄观看留存、相似视频和批量搜索接口,可进一步
+提高老年分享判断的直接性与多词多页探索效率。
+
+### 14.5 关系语义较弱
+
+当前主要关系是:
+
+- 树父子;
+- 需求词到单一分类;
+- 需求词和需求池的字符串子串匹配;
+- 需求词到视频列表。
+
+尚没有独立的语义关系表、关系类型、关系 reason、置信度和人工审核状态。
+
+### 14.6 同步完整性风险
+
+需求池同步先比较总行数。总行数相同但内容变化时,会跳过 ODPS 明细同步。
+
+### 14.7 测试体系缺失
+
+当前仓库没有 `tests/`,并且 `.gitignore` 直接忽略 `tests/`,会阻止正常提交测试目录。
+
+### 14.8 文档已滞后
+
+现有 `README.md`、`ARCHITECTURE.md` 和 `agents/README.md` 包含已经不存在或未实现的结构,例如:
+
+- `video_content` 模型/Repository;
+- find_agent 的保存和历史查询工具;
+- 旧的 Agent 数量和数据流。
+
+后续应以本文和源码为准,并更新旧文档。
+
+---
+
+## 15. 当前本地运行环境与数据库状态
+
+### 15.1 本地 Python 环境不匹配
+
+当前机器默认环境:
+
+- Python `3.10.19`;
+- SQLAlchemy `1.4.51`;
+- 项目根目录没有 `.venv`。
+
+源码要求:
+
+- Python `>=3.11`;
+- SQLAlchemy `>=2.0`。
+
+因此直接使用当前默认 `python3` 导入数据库层会在 `DeclarativeBase` 处失败。应建立 Python 3.11+ 虚拟环境后安装项目依赖。
+
+### 15.2 `.env` 的 MySQL 配置问题
+
+只读连接检查发现:
+
+1. `MYSQL_HOST` 的值开头多了一个 `=`,会导致主机名解析失败;
+2. 临时去掉该字符后可以到达 MySQL 服务,但返回错误 `1045 Access denied`;
+3. 需要核对用户名/密码、RDS 白名单或该用户允许连接的 Host 范围。
+
+由于未通过鉴权,本次无法确认数据库真实表数量、行数和最新业务日。本文的数据结构来自当前 ORM 和 Repository 源码,不冒充线上运行态数据。
+
+### 15.3 前端依赖未安装
+
+当前没有 `web/node_modules`。Node `20.11.1`、npm `10.2.4` 已存在,执行前需要先在 `web/` 运行 `npm install` 或 `npm ci`。
+
+---
+
+## 16. 建议的后续阅读顺序
+
+如果继续开发,建议按以下顺序进入代码:
+
+1. `supply_infra/scheduler/jobs/demand_pool/`:理解需求池同步主业务;
+2. `supply_infra/db/models/`:理解真实数据对象;
+3. `supply_infra/scheduler/jobs/demand_pool/tree_weight.py`:理解树上热度;
+4. `agents/demand_belong_category_agent/`:理解需求词挂树;
+5. `agents/generate_demand_agent/`:理解平台需求生成;
+6. `api/services/category_tree.py`:理解后端对前端的数据形态;
+7. `web/src/components/IcicleHeatTree.vue`:理解全局热力图;
+8. `web/src/components/DemandPathPanel.vue`:理解节点证据下钻;
+9. `supply_agent/agent/`:理解底层 Agent 执行机制;
+10. `supply_agent/logging/`:理解可追溯运行日志。
+
+---
+
+## 17. 一句话总结
+
+当前 SupplyAgent 是一套以 ODPS 和 MySQL 为数据底座、以全局分类树为组织骨架、以自研 Agent 框架完成需求词归类和单维需求生成、并通过 FastAPI/Vue 展示分类热度与视频证据的业务系统;核心数据流水线已经形成,但多挂靠、最终需求产品化、后验反馈进入综合决策、语义关系图和自动化测试仍未完成。

+ 0 - 1252
README_myself.md

@@ -1,1252 +0,0 @@
-# SupplyAgent 业务框架设计
-
-## 1. 项目定位
-
-SupplyAgent 是一个面向平台内容供给的需求汇总工具。
-
-它要解决的核心问题不是“从数据中找出若干热门词”,而是:
-
-> 汇总来自不同渠道、不同时间尺度和不同验证阶段的需求信号,将其统一挂靠到一棵全局分类树上,形成一张可追溯、可解释、可持续反馈的需求关系图,最终输出数百条平台级需求。
-
-最终结果同时服务于两种业务视角:
-
-1. 从全局分类树和关系图观察平台需求版图、层级、覆盖和交织关系。
-2. 从排序后的需求清单直接开展内容发现、内容生产、供给调度和效果验证。
-
-项目最终交付的不是一张扁平需求表,而是:
-
-- 一棵稳定的全局分类树;
-- 数百条挂靠在树上的平台需求;
-- 需求与多个树节点之间的关系线;
-- 需求背后的多维数据证据;
-- 需求与内容、线上表现之间的反馈闭环。
-
----
-
-## 2. 对现有项目业务结构的理解
-
-当前项目已经形成了需求汇总的基础业务链路。
-
-### 2.1 上游需求池
-
-项目从上游策略需求池接收不同类型的需求信号。目前已经体现出的主要维度包括:
-
-- 外部热度;
-- 平台持续热度;
-- 平台去年同期热度;
-- 平台近期供需缺口;
-- 近 7 日真实 ROV;
-- 近 7 日真实 VOV。
-
-前四类数据主要回答“什么需求可能值得做”,属于先验信号。
-
-真实 ROV、VOV 主要回答“需求被内容承接并上线后是否真的有效”,属于后验反馈。
-
-### 2.2 全局分类树
-
-`global_tree_category` 所表达的是一棵统一的全局语义分类树,而不是多棵相互独立的人物树、事件树或情感树。
-
-分类树从左向右按层级展开,例如:
-
-```text
-L1        L2        L3          L4          L5
-知识  →   历史  →   历史时期  →  古代史
-
-事件  →   社会事件  →  人物故事  →  个人经历
-                              →  名人故事
-```
-
-树上的正式节点是稳定、抽象、可治理的业务分类。具体的人物、事件、情感和需求表达,不一定都要成为正式树节点。
-
-### 2.3 需求词归类
-
-上游需求中的词语或短语会被挂靠到全局分类树的合适节点上。
-
-归类的业务意义是为需求建立稳定坐标,使需求可以:
-
-- 沿树向上汇总;
-- 在同类需求间比较;
-- 观察不同分支的需求覆盖;
-- 计算分类节点在不同信号维度下的强度;
-- 支撑后续平台需求生成。
-
-### 2.4 分类节点强度
-
-当前项目会把需求词级别的数据向分类树节点及其祖先聚合。
-
-因此分类树不仅承担知识组织,还承担需求统计和强度观察:
-
-- 叶子或挂载节点反映局部、具体需求;
-- 中间节点反映某个业务方向的整体强度;
-- 高层节点反映平台需求版图中的大方向。
-
-### 2.5 平台需求生成
-
-现有需求生成 Agent 已经体现了以下层次:
-
-```text
-来源维度 → 整体方向 → 汇总事件 → 原始需求名称
-```
-
-这个结构可以作为初始生成方式,但最终业务模型需要进一步升级为:
-
-```text
-全局分类树 + 需求节点 + 跨分支关系 + 多维证据 + 线上反馈闭环
-```
-
----
-
-## 3. 核心设计原则
-
-### 3.1 一棵树,而不是多棵业务树
-
-全局分类树是整个系统唯一的正式分类骨架。
-
-人物、事件、情感、知识、历史、行为等概念分布在同一棵树的不同分支中。平台需求通过同时连接多个分支,表达真实用户兴趣的交织关系。
-
-### 3.2 以树确定归属,以图表达关系
-
-树内父子关系负责表达:
-
-- 层级;
-- 上下位关系;
-- 统计汇总路径;
-- 业务覆盖;
-- 正式分类治理。
-
-图上的跨节点关系负责表达:
-
-- 一个需求同时涉及哪些分类分支;
-- 人物、事件、行为、情感等元素如何共同组成需求;
-- 不同需求之间是否存在重合、包含、相似或关联;
-- 哪些上游信号共同支持同一个需求。
-
-### 3.3 每条需求必须挂树
-
-每条正式平台需求至少挂靠一个真实存在的分类树节点。
-
-一条需求可以同时挂靠多个正式树节点。多个挂靠点共同定义需求,不要求在业务语义上强制区分主次。
-
-例如同一条需求可以同时挂靠:
-
-- 人物故事;
-- 个人经历;
-- 历史解读;
-- 诗词创作;
-- 与具体战争时期相关的历史分类。
-
-如果某些统计、展示或资源分配场景必须使用唯一口径,可以额外指定一个“统计主归属节点”。统计主归属只用于避免重复计数,不代表其他挂靠点在业务语义上更次要。
-
-### 3.4 用户意图优先
-
-需求的多个挂靠点应共同表达“用户为什么对此感兴趣”,而不是只机械选择最具体的对象节点。
-
-例如需求:
-
-> 毛泽东在抗日战争和解放战争时期的诗词创作
-
-可能涉及:
-
-- 人物对象:毛泽东;
-- 历史背景:抗日战争、解放战争;
-- 行为:写诗、诗词创作;
-- 内容意图:人物经历、作品背景、历史解读。
-
-需求可以同时挂靠“人物故事”“个人经历”“历史解读”或与诗词创作相关的正式节点,具体取决于上游数据实际支持了哪些用户意图。
-
-“毛泽东”“抗日战争”“解放战争”“诗词创作”等相关语义通过多个挂靠点、需求元素和关系线共同表达。
-
-### 3.5 数据驱动为主,自由推演为辅
-
-平台需求必须主要来源于上游数据。
-
-建议的总体比例是:
-
-- 80%~90% 为上游数据直接支持的核心需求;
-- 10%~20% 为基于已有数据、节点和关联关系形成的邻近机会需求。
-
-自由推演不得:
-
-- 凭空创造没有来源的人物、事件、情感或主题;
-- 用模型常识替代上游证据;
-- 将弱关联包装成确定关系;
-- 与数据支持的需求混淆展示。
-
-推演需求必须单独标记,并能说明它是从哪些已有数据和关系扩展而来。
-
-### 3.6 原始事实与语义推断分离
-
-上游目前主要提供“关联”关系。
-
-系统必须永久保留原始“关联”边,不得覆盖或篡改。
-
-系统可以在有依据时,把普通关联扩展解释为新的语义关系,例如:
-
-- 人物参与事件;
-- 事件发生于某个历史时期;
-- 人物在某个时期进行诗词创作;
-- 作品表达某种精神或情感;
-- 某个历史背景影响作品主题。
-
-所有推断语义关系必须附带:
-
-- 推断说明;
-- 原始关联证据;
-- 数据来源;
-- 置信度;
-- 是否经过人工确认;
-- 创建或更新时间。
-
-证据不足时继续保留“关联”,不强行解释。
-
----
-
-## 4. 整体业务图结构
-
-整张图由六类核心业务对象组成:
-
-- 分类树节点;
-- 细节元素;
-- 视频或内容实例;
-- 明确语言观点与长段讨论;
-- 平台需求;
-- 证据、状态与反馈。
-
-### 4.1 分类树节点
-
-正式、稳定、可治理的分类节点。
-
-分类树节点之间保留原始父子关系,并从左向右按层级展开。
-
-### 4.2 需求元素节点
-
-从上游需求中识别出的具体业务元素,例如:
-
-- 人物:毛泽东;
-- 历史事件:抗日战争、解放战争;
-- 行为:写诗;
-- 作品或内容:战争时期诗词;
-- 情感或精神:革命乐观主义、家国情怀。
-
-需求元素首先来自上游数据。系统只负责归一别名、识别类型并保留来源。
-
-### 4.3 平台需求节点
-
-平台需求是最终业务输出的核心实体,不等同于某个分类节点,也不等同于某个原始需求词。
-
-例如:
-
-> 毛泽东在抗日战争时期创作过哪些诗词
-
-> 毛泽东的战争诗词如何反映当时的历史环境
-
-> 从抗日战争到解放战争,毛泽东诗词主题发生了什么变化
-
-这些需求可以共同涉及“毛泽东、抗日战争、解放战争、写诗”等元素,但它们表达的是不同用户意图,因此应当是不同的平台需求节点。
-
-### 4.4 内容节点
-
-能够承接某条需求的真实内容,包括:
-
-- 已有内容;
-- 搜索发现的内容;
-- 新生产的内容;
-- 已上线并获得真实反馈的内容。
-
-需求和内容之间允许多对多关系:
-
-- 一条需求可以由多条内容承接;
-- 一条内容也可能同时承接多个需求。
-
-但需要区分内容的主需求和辅助需求,避免效果归因失真。
-
-### 4.5 证据与状态节点
-
-记录需求在各个独立维度上的证据、状态和变化,包括:
-
-- 外部热度;
-- 平台持续热度;
-- 去年同期热度;
-- 近期供需缺口;
-- 真实 ROV、VOV;
-- 样本量;
-- 数据日期;
-- 来源可信度;
-- 生命周期状态;
-- 推演标记;
-- 风险或抑制原因。
-
-### 4.6 分类节点下的证据子图
-
-正式分类树不是信息下钻的终点。
-
-每一个分类节点下面,还可以继续挂载与它相关的细节元素、真实视频和语言化内容,形成一套“节点下证据子图”:
-
-```text
-正式分类节点
-   ↓
-细节元素
-   ↓
-真实视频实例
-   ↓
-明确语言观点或问题
-   ↓
-长段讨论
-   ↓
-平台需求
-```
-
-这里的“继续下钻”是产品浏览和证据展开,不是继续增加正式分类树层级。
-
-元素、视频、短观点和长段讨论不应被强行定义成 L6、L7、L8 分类节点。它们挂在正式分类节点下面,但属于不同类型的业务对象。
-
-这样可以同时保证:
-
-- 全局分类树结构稳定、纯净;
-- 节点可以持续承载越来越丰富的细节信息;
-- 用户能够从抽象分类一路下卷到真实内容;
-- 平台需求能够追溯到具体视频和语言证据;
-- 真实内容表现能够逐层回流到元素、需求和分类节点。
-
-### 4.7 细节元素
-
-细节元素是分类节点下面更具体的语义索引。
-
-例如某个“人物故事”或“历史人物”分类节点下面,可以挂载:
-
-- 毛泽东;
-- 抗日战争;
-- 解放战争;
-- 写诗;
-- 诗词创作;
-- 战争时期诗词;
-- 革命乐观主义;
-- 家国情怀。
-
-元素来自真实上游数据、视频解析、内容标签或人工治理。
-
-一个元素可以:
-
-- 挂在多个正式分类节点下;
-- 与其他元素保留原始“关联”关系;
-- 连接多条真实视频;
-- 被多个平台需求共同引用;
-- 根据视频数量、出现次数和线上表现形成元素强度。
-
-分类节点下的元素列表应展示:
-
-- 元素名称;
-- 元素类型;
-- 出现次数;
-- 关联视频数量;
-- 支持的平台需求数量;
-- 线上表现摘要;
-- 数据来源;
-- 更新时间。
-
-### 4.8 视频实例
-
-元素可以继续下钻到具体视频。
-
-视频不是单纯的播放链接,而是需求提取和效果反馈的事实实例。每条视频应尽量保留:
-
-- 视频标题;
-- 视频链接;
-- 作者和发布时间;
-- 视频转写或内容描述;
-- 命中的分类节点;
-- 命中的细节元素;
-- 对应的平台需求;
-- 点赞、评论、分享、收藏等表现;
-- 真实 ROV、VOV;
-- 内容质量或解析可信度;
-- 是否属于主承接内容。
-
-同一条视频可以连接多个元素和需求,但需要区分主要承接和辅助承接。
-
-### 4.9 明确语言观点
-
-视频解析后,可以从内容中提取能够独立表达的短语言单元,例如:
-
-- 一个明确事实;
-- 一个观点;
-- 一个判断;
-- 一个问题;
-- 一句可用于需求命名的话;
-- 一条用户容易理解和传播的内容结论。
-
-例如:
-
-> 战争环境并未中断诗词创作,反而强化了作品的历史表达。
-
-> 毛泽东为什么在战争时期持续进行诗词创作?
-
-短语言单元可以用于:
-
-- 快速理解视频贡献了什么;
-- 比较不同视频是否表达同一观点;
-- 形成需求候选名称;
-- 聚合同义需求;
-- 支撑需求关系说明。
-
-所有语言提取都要保留对应视频、原始片段和提取说明,避免模型生成的语言脱离真实内容。
-
-### 4.10 长段讨论
-
-多个视频、观点和元素还可以进一步形成长段讨论。
-
-长段讨论用于表达短句无法承载的内容,例如:
-
-- 一个问题的完整背景;
-- 多个视频观点之间的共同点和差异;
-- 历史过程和人物行为之间的联系;
-- 一个需求为什么值得形成;
-- 某个需求存在什么争议;
-- 内容供给可以从哪些角度展开;
-- 线上反馈为什么支持或否定该需求。
-
-例如可以围绕以下主题形成讨论:
-
-> 从抗日战争到解放战争,毛泽东的诗词既记录时代环境,也呈现政治理想、个人情感和历史判断。不同视频分别提供作品背景、创作动机、表达方式和受众理解方面的证据。
-
-长段讨论不是脱离数据的自由文章。它必须引用实际元素、视频和明确观点,并标识:
-
-- 讨论依据;
-- 主要证据;
-- 推断内容;
-- 不确定点;
-- 支持或关联的平台需求。
-
-### 4.11 节点下钻的产品形态
-
-用户从全局分类树继续下卷时,建议按以下顺序展开:
-
-```text
-分类节点概览
-→ 高频或高价值元素
-→ 元素关联的视频
-→ 视频转写与明确观点
-→ 多视频形成的长段讨论
-→ 从证据中提取的平台需求
-→ 需求对应的线上验证结果
-```
-
-每一级都要能够返回上一级,并保留:
-
-- 来源;
-- 出现次数;
-- 贡献度;
-- 时间;
-- 置信度;
-- 真实线上表现;
-- 与需求之间的关系。
-
-节点下钻同时服务两个目的:
-
-1. 展示:让业务人员理解这个分类节点下具体有什么。
-2. 提取:让系统从元素、视频和语言证据中发现、生成、合并和验证需求。
-
----
-
-## 5. 图中的关系类型
-
-### 5.1 树内父子关系
-
-正式分类树原有的层级关系,是全图最稳定的结构。
-
-### 5.2 需求多挂靠关系
-
-每条平台需求可以同时挂靠多个正式分类节点。每条挂靠关系都应记录:
-
-- 挂靠节点;
-- 挂靠理由;
-- 支持该挂靠的上游数据;
-- 关系置信度;
-- 是否属于正式挂靠或待审核挂靠;
-- 生效和更新时间。
-
-多个挂靠点共同表达需求的完整语义和跨分支交织关系。
-
-例如“毛泽东的战争诗词如何反映当时的历史环境”可以同时挂靠:
-
-- 历史解读;
-- 人物故事;
-- 个人经历;
-- 与诗词创作相关的正式节点;
-- 与抗日战争、解放战争所处历史时期相关的正式节点。
-
-当主题统计需要避免重复计数时,可以为需求设置一个“统计主归属节点”,或者按明确的分摊规则将需求计入多个节点。该统计属性与业务挂靠关系分开管理。
-
-### 5.4 原始关联关系
-
-来自上游数据的事实关系,关系类型统一为“关联”。
-
-原始关联边必须保留完整的来源和时间信息。
-
-### 5.5 推断语义关系
-
-系统根据多个原始关联、树上位置和上下文推断出的补充关系。
-
-推断边只用于:
-
-- 增强解释;
-- 帮助聚类;
-- 提供低权重排序增益;
-- 辅助发现邻近机会需求。
-
-推断边不能取代原始关联边。
-
-### 5.6 需求与内容关系
-
-表达内容承接了哪个需求,以及承接程度:
-
-- 主承接;
-- 辅助承接;
-- 部分覆盖;
-- 待验证;
-- 已上线;
-- 已形成有效样本。
-
-### 5.7 内容表现回流关系
-
-表达某批内容的真实线上表现如何反向影响需求强度。
-
-### 5.8 分类节点与元素关系
-
-表达某个细节元素下挂在哪些正式分类节点下。
-
-该关系应记录元素为何属于该分类、来源和出现次数。一个元素允许同时下挂多个分类节点。
-
-### 5.9 元素与视频关系
-
-表达某条视频包含、体现或讨论了哪些元素。
-
-上游只有“关联”时保留原始关联;需要扩展为“人物出现、事件涉及、行为发生、观点表达”等语义时,必须附带说明和置信度。
-
-### 5.10 视频与语言关系
-
-表达明确观点、问题和长段讨论是从哪些视频或视频片段中提取出来的。
-
-语言内容必须能回看原始视频或转写依据。
-
-### 5.11 语言与需求关系
-
-表达某个明确观点、问题或长段讨论支持、形成或验证了哪些平台需求。
-
-同一个需求可以由多个语言证据共同支持,同一个语言观点也可以被多个需求引用。
-
----
-
-## 6. 需求汇总业务流程
-
-整体不是一次性的线性任务,而是持续循环的业务系统。
-
-```text
-上游需求信号
-    ↓
-数据归一与来源保留
-    ↓
-需求元素识别
-    ↓
-挂靠全局分类树
-    ↓
-保留原始关联并构建关系图
-    ↓
-连接真实视频并解析内容
-    ↓
-提取明确观点和长段讨论
-    ↓
-合并为唯一平台需求
-    ↓
-计算先验需求强度
-    ↓
-形成主题方向与需求池
-    ↓
-搜索或生产承接内容
-    ↓
-内容上线并产生真实表现
-    ↓
-归因到平台需求
-    ↓
-更新需求验证强度与生命周期
-    ↓
-影响下一周期的需求排序和内容供给
-```
-
-### 6.1 数据归一
-
-统一处理:
-
-- 同义词;
-- 简称与全称;
-- 人物别名;
-- 事件的不同表达;
-- 错别字;
-- 中英文表达;
-- 时间和周期口径。
-
-归一不等于覆盖原始数据。每个标准表达都必须能追溯到原始名称和来源。
-
-### 6.2 意图挂树
-
-优先挂靠现有正式树节点。
-
-如果现有树无法准确表达需求:
-
-1. 挂到当前最可靠的上级节点;
-2. 标记表达缺口;
-3. 进入候选节点治理区;
-4. 由人工审核是否需要增加正式节点。
-
-Agent 不直接修改正式分类树。
-
-### 6.3 需求合并
-
-多种来源命中同一个需求时,不按来源拆成重复需求,而是合并为一个平台需求节点。
-
-建议以以下组合判断需求是否相同:
-
-```text
-核心用户意图 + 关键对象 + 适用范围或约束
-```
-
-例如:
-
-- “毛泽东抗战时期写的诗”
-- “毛泽东在抗日战争阶段创作的诗词”
-
-可以合并为同一平台需求,并保留两个原始表达。
-
-但下面两条不应简单合并:
-
-- “毛泽东在抗日战争时期创作过哪些诗词”
-- “毛泽东的抗战诗词表达了什么情感”
-
-前者关注作品事实,后者关注作品解读,用户意图不同。
-
-### 6.4 少量邻近推演
-
-只有在已有数据能够支持时,才允许生成邻近机会需求。
-
-例如上游同时反复出现:
-
-- 毛泽东;
-- 抗日战争;
-- 解放战争;
-- 诗词创作;
-
-系统可以提出:
-
-> 从抗日战争到解放战争,毛泽东诗词主题发生了什么变化
-
-但必须说明:
-
-- 它由哪些上游关联组合而来;
-- 上游是否直接出现过该完整需求;
-- 哪些部分属于模型推断;
-- 当前属于核心需求还是机会需求。
-
-### 6.5 从视频和语言证据中提取需求
-
-需求不仅可以直接来自上游需求名称,也可以从节点下挂的真实内容中被发现。
-
-提取过程应遵循:
-
-1. 从分类节点下的高频、高表现元素开始;
-2. 找到承载这些元素的真实视频;
-3. 从视频转写和解析结果中抽取明确事实、观点和问题;
-4. 对多个视频的语言单元进行归并和比较;
-5. 形成有真实内容依据的需求候选;
-6. 将候选需求挂回一个或多个正式分类节点;
-7. 与已有平台需求去重或合并;
-8. 标记数据来源、视频证据和推断部分。
-
-例如,“毛泽东、抗日战争、解放战争、诗词创作”这些元素分别在多条视频中共同出现,并形成以下语言证据:
-
-- 毛泽东为何在战争时期持续进行诗词创作;
-- 战争环境如何影响诗词主题;
-- 抗日战争和解放战争时期的作品表达有何变化。
-
-系统可以据此提取平台需求,但不能只凭模型常识生成。每一条需求都必须能够回到具体视频和语言证据。
-
----
-
-## 7. 需求—内容—线上表现闭环
-
-真实线上反馈不是普通的附属指标,而是需求汇总系统的核心后验闭环。
-
-```text
-平台需求
-   ↓
-找到或生产内容
-   ↓
-内容上线和分发
-   ↓
-获得真实线上表现
-   ↓
-校正并归因到需求
-   ↓
-更新需求强度
-   ↓
-调整下一周期供给
-```
-
-### 7.1 建立需求与内容的映射
-
-如果需求和内容之间没有明确映射,线上表现就无法准确回流。
-
-每条上线内容至少需要说明:
-
-- 主要承接哪个平台需求;
-- 是否辅助承接其他需求;
-- 对需求的覆盖程度;
-- 内容上线时间;
-- 当前是否形成有效样本。
-
-### 7.2 线上表现不能直接等同于需求表现
-
-内容表现还会受以下因素影响:
-
-- 内容本身质量;
-- 标题、封面和表达方式;
-- 分发流量;
-- 发布时间;
-- 平台环境;
-- 同类内容竞争;
-- 供给数量;
-- 样本量是否充足。
-
-因此需要把真实表现经过归因校正后,再反向更新需求强度。
-
-不能因为一条质量较差的内容表现不好,就直接判定需求不存在。
-
-### 7.3 反馈影响需求强度
-
-真实线上反馈应当能够:
-
-- 验证一个新需求是否真实成立;
-- 提高持续表现良好需求的强度;
-- 降低持续表现较差需求的优先级;
-- 判断某个需求是否已经过度供给;
-- 发现先验热度不高但真实表现很好的潜在需求;
-- 影响分类树中相关节点的整体强度;
-- 影响下一周期的主题配额和供给策略。
-
----
-
-## 8. 需求强度模型
-
-需求不能只保留一个不可解释的总分。
-
-每条需求应至少保留“四类分数 + 一个综合等级”。
-
-### 8.1 先验需求分
-
-回答:
-
-> 在内容上线验证之前,这个需求有多值得尝试?
-
-主要来源:
-
-- 外部热度;
-- 平台近期供需缺口;
-- 平台持续热度;
-- 去年同期或周期性热度;
-- 上游来源数量;
-- 样本量和数据时效性。
-
-这些维度应保持正交,分别展示,然后再形成先验综合判断。
-
-### 8.2 线上验证分
-
-回答:
-
-> 内容实际承接该需求后,这个需求是否真实成立?
-
-主要来源:
-
-- 真实 ROV;
-- 真实 VOV;
-- 消费、互动或转化表现;
-- 多条内容的一致性;
-- 多个周期的稳定性;
-- 归因校正结果。
-
-### 8.3 关系增益分
-
-回答:
-
-> 图上的关系是否进一步增强了该需求成立的可能性?
-
-关系增益只作为低权重补充,不能代替原始数据。
-
-### 8.4 风险抑制分
-
-主要风险包括:
-
-- 后验效果持续较差;
-- 数据维度之间明显冲突;
-- 样本量不足;
-- 数据过期;
-- 内容承接失败;
-- 同类需求过度重复;
-- 某个主题过度集中;
-- 需求主要来自自由推演;
-- 关系推断置信度较低。
-
-### 8.5 综合需求强度
-
-业务上可以将其理解为:
-
-```text
-最终需求强度
-= 先验需求强度
-+ 经归因校正的线上验证强度
-+ 低权重关系增益
-- 风险抑制
-```
-
-具体权重不应在业务框架阶段固定死,应根据历史验证逐步校准。
-
-无论最终采用什么权重,都必须能够展开查看各个组成部分,避免形成黑盒分数。
-
----
-
-## 9. 需求生命周期
-
-需求是动态实体,不是一经生成就永久有效。
-
-建议设置以下生命周期状态。
-
-### 9.1 新机会
-
-先验信号明显,但尚未有足够内容和线上反馈。
-
-### 9.2 待验证
-
-已经找到或安排了承接内容,正在等待有效线上样本。
-
-### 9.3 增长需求
-
-先验信号增强,或者真实线上表现持续改善。
-
-### 9.4 已验证需求
-
-已经由足量内容、有效样本或多个周期的表现证明。
-
-### 9.5 观察需求
-
-存在一定信号,但样本较少、数据冲突或结论不稳定。
-
-### 9.6 衰退需求
-
-需求热度、真实表现或用户兴趣持续下降。
-
-### 9.7 抑制需求
-
-经过验证后确认当前不值得继续投入,或供给已经明显过量。
-
-### 9.8 周期需求
-
-当前强度下降,但预计会在特定日期、节日、纪念日或社会周期重新激活。
-
-### 9.9 新老需求公平
-
-没有后验数据不等于后验表现差。
-
-为了避免旧需求永久占据高位:
-
-- 新需求主要依据先验分进入探索区;
-- 老需求的历史表现需要时间衰减;
-- 每个主题保留一定探索额度;
-- 只有形成有效样本后才提高后验权重;
-- 已验证需求也要接受持续复验。
-
----
-
-## 10. 主题方向与数百条需求的组织
-
-最终输出采用两层结构。
-
-### 10.1 上层:主题方向
-
-主题方向不是另建一棵脱离现有分类树的新树。
-
-它应主要来自:
-
-- 全局分类树的中高层节点;
-- 某个树分支下的需求聚类;
-- 多个相关分支共同形成的稳定业务方向。
-
-例如:
-
-- 历史人物故事;
-- 历史人物个人经历;
-- 战争历史与人物;
-- 历史人物作品解读;
-- 历史事件影响;
-- 人物精神与情感。
-
-每个主题方向应包含:
-
-- 主题名称;
-- 对应的分类树范围;
-- 覆盖的用户意图;
-- 需求数量;
-- 各生命周期数量;
-- 整体需求强度;
-- 主要数据来源;
-- 趋势;
-- 需求集中度;
-- 探索需求占比。
-
-### 10.2 下层:平台需求
-
-每条平台需求应包含:
-
-- 唯一需求 ID;
-- 标准需求名称;
-- 原始需求表达;
-- 多个正式挂靠节点;
-- 可选的统计主归属节点;
-- 每个挂靠点的理由和证据;
-- 关联需求元素;
-- 原始关联边;
-- 推断语义边及说明;
-- 所属主题方向;
-- 各维先验信号;
-- 线上验证结果;
-- 关联内容及归因情况;
-- 需求强度;
-- 生命周期;
-- 是否属于推演需求;
-- 风险和抑制原因;
-- 数据更新时间;
-- 强度变化历史。
-
-### 10.3 需求数量分配
-
-数百条需求不按主题平均分配,也不能完全被少数热门主题占满。
-
-采用:
-
-> 数据驱动为主,最低覆盖和最高集中度约束为辅。
-
-具体原则:
-
-- 强信号主题可以拥有更多需求;
-- 弱主题允许较少需求;
-- 无真实信号的主题可以暂时为空;
-- 重要主题保留最低覆盖;
-- 单一主题设置最高集中度;
-- 每个主题保留少量探索位;
-- 推演需求总量保持在受控范围。
-
----
-
-## 11. 最终展示方式
-
-最终使用同一份需求数据提供两个入口。
-
-### 11.1 全局树图入口
-
-从左向右浏览:
-
-```text
-L1 → L2 → L3 → L4 → L5 → 挂载需求
-```
-
-树图中需要保留:
-
-- 原有树内父子线;
-- 分类节点的需求数量和强度;
-- 平台需求与多个正式树节点之间的挂靠线;
-- 可选的统计主归属标记;
-- 跨分支关联线;
-- 原始关联与推断关系的区别;
-- 需求与内容的承接关系;
-- 线上反馈回流关系。
-
-用户点击某条需求后,应能看到完整追溯链路:
-
-```text
-上游数据
-→ 原始需求表达
-→ 标准化过程
-→ 多个挂靠节点及各自理由
-→ 关联元素
-→ 原始及推断关系
-→ 关联内容
-→ 线上表现
-→ 需求强度变化
-```
-
-### 11.2 需求清单入口
-
-以业务执行为目的,支持按以下维度查看:
-
-- 主题方向;
-- 需求强度;
-- 生命周期;
-- 多个挂靠节点;
-- 可选的统计主归属节点;
-- 数据来源;
-- 是否已经验证;
-- 是否已经有内容承接;
-- 是否存在供需缺口;
-- 是否属于推演需求;
-- 更新时间。
-
-树图入口和清单入口指向同一批需求实体,不维护两套独立结果。
-
----
-
-## 12. 分类树治理
-
-现有分类树是基础权威骨架,但不是永远不变。
-
-### 12.1 正式节点
-
-已经审核并进入全局分类树,可以作为需求挂靠节点和统计归属节点。
-
-### 12.2 候选节点
-
-当大量上游需求反复出现,而现有树无法准确表达其核心意图时,可以提出候选节点。
-
-候选节点必须说明:
-
-- 哪些需求无法被现有节点准确表达;
-- 当前临时挂靠在哪里;
-- 出现频率和持续周期;
-- 预期父节点;
-- 与现有节点的差异;
-- 新增后能解决什么业务问题。
-
-### 12.3 人工审核
-
-Agent 只能提出候选节点,不能直接修改正式树。
-
-人工审核后可以:
-
-- 接受为正式节点;
-- 与现有节点合并;
-- 继续观察;
-- 拒绝新增。
-
----
-
-## 13. 业务质量控制
-
-### 13.1 可追溯
-
-任何平台需求必须能够追溯到上游数据。
-
-### 13.2 可解释
-
-必须解释:
-
-- 为什么形成该需求;
-- 为什么挂在这些节点;
-- 为什么与其他表达合并或不合并;
-- 为什么获得当前强度和生命周期;
-- 线上反馈如何影响了它。
-
-### 13.3 防止过度聚合
-
-一个平台需求应表达一个清晰的用户意图。
-
-不能将大量弱相关人物、事件、作品和情感塞入一个“大合集需求”。
-
-### 13.4 防止过度拆分
-
-同一用户意图仅因为来源、措辞或时间不同,不应被拆成多个重复需求。
-
-### 13.5 防止自由推演失控
-
-所有推演需求必须:
-
-- 有数据起点;
-- 有推演路径;
-- 有置信度;
-- 有独立标识;
-- 有比例限制;
-- 可以被人工拒绝。
-
-### 13.6 防止后验误判
-
-线上反馈必须经过归因和样本校正,避免将内容质量、流量不足或供给不足误认为需求无效。
-
----
-
-## 14. 项目业务模块的总体框架
-
-从业务职责看,整个项目可以划分为九个部分。
-
-### 14.1 信号接入
-
-负责接收内外部、近期远期、周期性和真实反馈数据。
-
-### 14.2 需求理解
-
-负责标准化原始表达、识别需求元素、保留来源和原始关联。
-
-### 14.3 分类树挂靠
-
-负责为需求建立正式分类坐标,并发现分类树表达缺口。
-
-### 14.4 树图汇总
-
-负责把分类树、需求元素、需求节点和关系边组织成统一业务图。
-
-### 14.5 元素与内容下钻
-
-负责展示分类节点下的细节元素,并将元素连接到真实视频、内容标签、转写和线上表现。
-
-### 14.6 语言观点与讨论提取
-
-负责从真实视频中提取明确事实、观点、问题和长段讨论,并完整保留视频依据和推断说明。
-
-### 14.7 需求生成与合并
-
-负责形成唯一平台需求,控制需求粒度,避免重复和过度聚合。
-
-### 14.8 需求决策
-
-负责计算需求强度、生命周期、主题配额和内容供给优先级。
-
-### 14.9 内容反馈闭环
-
-负责把需求与内容连接起来,并将内容真实线上表现回流到需求和分类节点。
-
-整体业务关系是:
-
-```text
-信号接入
-   ↓
-需求理解
-   ↓
-分类树挂靠
-   ↓
-树图汇总
-   ↓
-元素与视频下钻
-   ↓
-语言观点与讨论提取
-   ↓
-需求生成与合并
-   ↓
-需求决策
-   ↓
-内容承接和线上反馈
-   └──────────────→ 回到需求决策和树图强度
-```
-
----
-
-## 15. 一句话总结
-
-SupplyAgent 的最终业务框架是:
-
-> 以一棵全局分类树作为稳定骨架,把上游多源需求统一挂树;以平台需求作为独立图节点连接多个分类分支和具体需求元素;以原始数据决定需求是否成立,以低权重语义推断补充关系,以内容真实线上表现持续反向更新需求强度,最终形成几十个主题方向和数百条可执行、可解释、可追溯的平台需求。
-
----
-
-## 16. 业务可视化资料与服务
-
-本次业务框架讨论过程中形成的全部可视化材料统一保存在:
-
-```text
-visualization/
-```
-
-目录中同时包含:
-
-- 业务图结构方案;
-- 从左向右的树图示意;
-- 业务节点和关系模型;
-- 需求—内容—线上表现反馈闭环;
-- 最终主题和平台需求输出结构;
-- 对话过程中的阶段性可视页面;
-- 用户提供的全局分类树局部参考图;
-- 用于本地浏览全部图稿的可视化服务。
-
-目录结构如下:
-
-```text
-visualization/
-├── README.md
-├── run.sh
-├── assets/
-│   └── tree.jpeg
-├── pages/
-│   ├── graph-structure-options.html
-│   ├── graph-structure-left-to-right.html
-│   ├── business-graph-model.html
-│   ├── demand-feedback-loop.html
-│   ├── final-output-structure.html
-│   ├── node-drilldown-evidence-chain.html
-│   ├── waiting-business-scope.html
-│   ├── waiting-demand-pipeline.html
-│   └── waiting-strength-lifecycle.html
-└── service/
-    └── serve.py
-```
-
-### 16.1 启动可视化服务
-
-在项目根目录执行:
-
-```bash
-bash visualization/run.sh
-```
-
-服务默认使用:
-
-```text
-http://localhost:8765/
-```
-
-需要指定端口时:
-
-```bash
-bash visualization/run.sh --port 9000
-```
-
-如果不希望自动打开浏览器:
-
-```bash
-python3 visualization/service/serve.py
-```
-
-服务只依赖 Python 标准库,不要求安装额外前端依赖。
-
-### 16.2 图稿与最终业务口径的关系
-
-`visualization/pages/` 保留了整个讨论过程,因此早期图稿可能包含后来被修正的中间方案。
-
-最终应以本文档的业务定义为准:
-
-- 整体只有一棵全局分类树;
-- 分类树从左向右按层级展开;
-- 平台需求是独立的图节点;
-- 一条需求可以同时挂靠多个正式树节点;
-- 多个挂靠点共同定义需求,不强制区分业务主次;
-- 如统计需要唯一口径,可以另设“统计主归属节点”;
-- 上游原始“关联”边永久保留;
-- 推断语义关系必须附带说明、来源和置信度;
-- 内容的真实线上表现必须反向更新需求强度。
-
-### 16.3 各图稿用途
-
-| 图稿 | 主要用途 |
-|---|---|
-| `graph-structure-options.html` | 记录单一大树、自由图和树骨架关系图三种方案的比较 |
-| `graph-structure-left-to-right.html` | 确认整体从左向右的阅读方式 |
-| `business-graph-model.html` | 说明分类节点、需求元素、平台需求、关系和证据 |
-| `demand-feedback-loop.html` | 说明需求如何找到或生产内容,以及线上表现如何回流 |
-| `final-output-structure.html` | 说明主题方向、数百条平台需求和证据卡如何组织 |
-| `node-drilldown-evidence-chain.html` | 说明分类节点如何继续下挂元素、视频、明确观点、长段讨论并提取需求 |
-| `waiting-*.html` | 保留对话过程中的阶段性页面 |
-| `assets/tree.jpeg` | 作为现有全局分类树结构和阅读方式的参考 |
-| `assets/tree2.png` | 作为分类节点下挂大量细节元素的参考 |
-| `assets/case.jpeg` | 作为元素扩展为明确语言、长段讨论和最终选题的参考 |

+ 2 - 2
prd/README.md

@@ -13,7 +13,7 @@ SupplyAgent 每天自动接收变化的需求信号、外部信号和后验反
 系统最终形成:
 
 - 一张以全局分类树为稳定骨架、允许需求多点挂靠和跨树关联的需求图;
-- 数百条可搜索、可执行的平台需求;
+- 数百甚至上千条可搜索、可执行的平台需求;
 - 每条需求完整的来源、路径、reason、评价过程和历史版本;
 - 面向寻找 Agent 和人的统一需求任务包;
 - “需求—内容—表现—次日需求”的自动反馈闭环;
@@ -57,6 +57,6 @@ SupplyAgent 每天自动接收变化的需求信号、外部信号和后验反
 - 它在全局和局部分支中是热还是冷?
 - 它为什么进入当前行动层?
 - 人和寻找 Agent 今天应该寻找什么内容?
-- 找到的内容承接了哪些需求?
 - 真实 ROV/VOV 如何经过归因后影响次日判断?
 - 某条定义何时修改、由谁确认、影响了哪些历史结果?
+- 找到的内容承接了哪些需求?(下游寻找agent的工作,此处主要关注反馈,不关注寻找本身。)

+ 467 - 0
problem/2026-07-24_问题总结.md

@@ -0,0 +1,467 @@
+# 2026-07-24 问题总结:当前代码与 PRD 的匹配度
+
+## 1. 结论
+
+当前代码已从“分类树 + 需求词热度”明显推进到“每日供给流水线 + 分级 Agent + 视频点位扩展 + 可视化下钻”的阶段。
+
+尤其已经落地了:
+
+- 每日串行流水线;
+- 需求分级统筹与并发执行;
+- 需求自身来源内归一评分;
+- 分类树全局与局部热度查询;
+- S/A 级需求的视频点位扩展;
+- 分级需求在树上的多分类展示;
+- 调度任务执行记录;
+- 分级需求、视频和点位的前端下钻。
+
+但它尚未实现 PRD 定义的完整 Harness。当前的核心问题不是“缺少一个 Agent”,而是**需求对象、评分对象、内容对象、每日快照和策略对象还没有统一成同一条可追溯闭环**。
+
+现阶段更准确的定位是:
+
+> 已实现“每日需求词分级与视频点位拓展”的业务原型;尚未实现“证据—平台需求—供给分配—内容归因—后验反馈—策略协作”的完整系统。
+
+## 2. 本次核对范围
+
+- 核对基线:`prd/` 下已确认的业务 PRD。
+- 代码状态:`feature/zhangbo` 当前 `d2154ed`。
+- 重点审阅:新增 `demand_grade_agent`、`demand_grade_orchestrator_agent`、`demand_video_expand_agent`、调度流水线、数据模型、API 和 Vue 页面。
+- 本文结论基于代码静态阅读和构建级检查;没有以线上数据库结果替代代码事实。
+
+## 3. PRD 五个模块的匹配度
+
+| PRD 模块 | 当前匹配度 | 已实现部分 | 主要缺口 |
+|---|---|---|---|
+| 证据收集 Harness | 部分匹配 | ODPS→MySQL 同步、四项先验、真实 ROV/VOV、视频点位 | 没有不可变证据包、来源/事件版本、冲突和迟到数据机制 |
+| 需求认知与智能汇总 Harness | 初步匹配 | 需求词归类、需求词↔池行关系、分级需求可挂多个分类 | 没有“原始表达→标准需求词→平台需求”三层对象;无合并拆分和关系语义账本 |
+| 需求评估与供给分配 Harness | 部分匹配 | S/A/B/C/D 分级、来源内归一分、局部热度、ROV 后验 | 没有“成立度 + 局部供给优先级”双结果、行动层、探索配额和跨日稳定规则 |
+| 发布、可视化与反馈入口 Harness | 初步匹配 | 热力图、分级列表、多挂靠点击、视频/点位下钻 | 没有标准需求任务包、两个下游视图、反馈入口、完整评分解释和日期一致性保证 |
+| 业务协作与策略控制 Harness | 基本未实现 | 调度执行记录、Agent 运行日志 | 没有数据问答、自动分析、负向决策、定义管理、影响预览和策略版本 |
+
+## 4. 已实现能力与 PRD 的正向对应
+
+### 4.1 每日自动运行已有主干
+
+`run_supply_pipeline` 已按“全局树同步 → 需求池同步 → 分级 → 视频点位拓展”执行,调度器每天 12:00 触发。
+
+对应 PRD:每日自动运行、需求分级、内容证据扩展。
+
+相关代码:
+
+- `supply_infra/scheduler/app.py`
+- `supply_infra/scheduler/jobs/run_supply_pipeline.py`
+
+### 4.2 需求自身先验分已避免直接混加不同来源
+
+`demand_priority.py` 先在每个 strategy 内对原始 `weight` 排名归一,再对已有来源取均值;缺失来源不补零。
+
+对应 PRD:先验维度保持正交、缺失不当成零。
+
+相关代码:
+
+- `agents/demand_grade_agent/tools/demand_priority.py`
+
+### 4.3 后验已进入分级 Agent 的判断提示
+
+分级 Agent 同时读取分类树热度、需求自身来源分、真实 ROV/VOV、样本数、父节点和全部兄弟节点;提示明确“无后验不等于零”。
+
+对应 PRD:局部冷热、后验和样本量参与判断。
+
+相关代码:
+
+- `agents/demand_grade_agent/prompt/system_prompt.md`
+- `agents/demand_grade_agent/tools/query_category_local_heat.py`
+- `agents/demand_grade_agent/tools/query_demand_popularity_by_word.py`
+
+### 4.4 分级结果已经支持多分类展示
+
+`demand_grade_category_rel` 允许一条 `demand_grade` 映射多个分类,前端可从需求卡片直接选择分类。
+
+对应 PRD:需求可以有多个挂靠点。
+
+注意:这只是分级结果层的多分类展示,不等于原始需求认知层已具备可解释的多挂靠能力,详见问题 P1-3。
+
+### 4.5 视频点位扩展已提供内容证据雏形
+
+对 S/A 级需求,系统读取已关联视频的目的点、关键点和灵感点,再由 Agent 筛选可扩展的需求文本和 reason,并展示到前端。
+
+对应 PRD:需求向内容、语言证据下钻。
+
+相关代码:
+
+- `supply_infra/scheduler/jobs/expand_demand_from_video_points.py`
+- `agents/demand_video_expand_agent/`
+- `api/services/demand_grade_videos.py`
+
+## 5. P0:会导致每日结果不完整、失真或不可安全发布的问题
+
+### P0-1:需求池以“总行数相同”跳过同步,不能保证每日输入快照正确
+
+**现状**
+
+`_sync_pool_rows` 先比较 ODPS 和 MySQL 总行数;相同就跳过明细同步。两边行数相同、但同一条需求的权重、视频、名称或其他内容已经变化时,当日输入会保持旧值。
+
+**与 PRD 的差距**
+
+PRD 要求每天以变化的上游数据形成完整证据包。行数相同不是“数据未变化”的充分条件。
+
+**风险**
+
+- 当日热度、分级和后续视频扩展可能基于过期数据;
+- 历史上无法说明当日实际使用了哪个上游版本;
+- 结果看起来“每日运行成功”,但业务含义已失真。
+
+**代码证据**
+
+- `supply_infra/scheduler/jobs/sync_multi_demand_pool_odps_to_mysql.py`:`_sync_pool_rows`。
+
+### P0-2:分级组全部失败时,计划仍可能被判定为“执行完成”
+
+**现状**
+
+`DemandGradePlanRepository.get_execution_snapshot` 只把 `pending + running` 视为未完成,不把 `failed` 计入未完成。因此所有组都失败、但没有 pending/running 时,`execution_complete` 仍为真。
+
+`grade_demand_pool` 又直接把这个字段作为 `success`,使外层流水线有可能继续执行 S/A 视频拓展,并把当日流水线标为成功。
+
+**与 PRD 的差距**
+
+PRD 明确要求:模块整体失败或结果不完整时,不得静默发布;必须说明缺失模块、影响范围和最后稳定版本。
+
+**风险**
+
+- 空的或不完整的分级结果会被视为正式当日结果;
+- 视频拓展只基于残缺 S/A 集合;
+- 前端和下游无法区分“真实无需求”与“分级执行失败”。
+
+**代码证据**
+
+- `supply_infra/db/repositories/demand_grade_plan_repo.py`:`get_execution_snapshot`。
+- `supply_infra/scheduler/jobs/grade_demand_pool.py`:以 `execution_complete` 作为成功判断。
+- `supply_infra/scheduler/jobs/run_supply_pipeline.py`:失败步骤后仍继续后续步骤。
+
+### P0-3:前端可能将不同业务日的树热度和需求分级拼接在同一张图中
+
+**现状**
+
+`GlobalDemandMapView` 和 `CategoryTreeView` 并行调用:
+
+- `/api/category-tree`:默认取 `category_tree_weight` 最新日期;
+- `/api/demand-grade`:默认取 `demand_grade` 最新日期。
+
+两个“最新日期”没有被同一 `biz_dt` 约束,也没有 API 返回一致性状态。
+
+**与 PRD 的差距**
+
+PRD 要求每日全量业务结果是一个可追溯快照,树热度、需求、评分、内容和行动应属于同一运行批次。
+
+**风险**
+
+- 用户可能在 7 月 24 日树热度上看到 7 月 23 日分级需求;
+- 局部冷热、等级和 reason 无法解释;
+- 页面视觉上正确,业务上却不是同一日结果。
+
+**代码证据**
+
+- `web/src/views/GlobalDemandMapView.vue`
+- `web/src/views/CategoryTreeView.vue`
+- `api/services/category_tree.py`
+- `api/services/demand_grade.py`
+
+### P0-4:数据库仅使用 `create_all`,没有迁移机制,现网结构升级不可控
+
+**现状**
+
+应用启动时调用 `Base.metadata.create_all()`。该操作可以创建缺失表,但不会为既有表安全地新增字段、修改约束或迁移历史数据。
+
+本轮代码已新增多张表,并改动既有表使用方式;没有看到迁移目录或迁移脚本。
+
+**与 PRD 的差距**
+
+PRD 依赖历史版本、日快照、关系和运行账本。数据结构升级必须可控,不能依赖开发环境首次建表。
+
+**风险**
+
+- 已部署数据库可能缺列、缺索引或约束不一致;
+- 代码升级后在运行期才报 SQL 错误;
+- 无法可靠回滚或核对一次结构变更影响的历史数据。
+
+**代码证据**
+
+- `supply_infra/db/session.py`:`init_db`。
+- 仓库未发现迁移文件或迁移工具目录。
+
+## 6. P1:关键业务闭环尚未形成的问题
+
+### P1-1:没有 PRD 所需的三层标准需求对象,`demand_grade` 仍是需求池词的每日评级
+
+**现状**
+
+`demand_grade` 的唯一键是 `(biz_dt, demand_name)`,`demand_name` 直接来自 `multi_demand_pool_di`。它保存的是需求词某日的 S/A/B/C/D 评级,而不是独立、稳定、可跨日演进的平台需求。
+
+原有 `generated_demand` 仍存在,但当前新增 API、前端、分级流水线和视频扩展均不消费它。
+
+**与 PRD 的差距**
+
+PRD 要求:
+
+```text
+原始需求表达 → 标准需求词 → 平台需求 → 每日需求任务包
+```
+
+当前将“原始词/需求词”和“最终平台需求”合并为同一个 `demand_name`,无法稳定表达别名、合并、拆分、层级和生命周期。
+
+**风险**
+
+- 同义词或相近词可能每天各自评级,或被模型临时合并但没有正式主从关系;
+- 无法可靠回答“这条平台需求由哪些原始表达组成”;
+- 下游只能收到词级结果,而不是业务意图明确的需求任务。
+
+**代码证据**
+
+- `supply_infra/db/models/demand_grade.py`
+- `supply_infra/db/models/generated_demand.py`
+- `api/services/demand_grade.py`
+
+### P1-2:评分口径与 PRD 不一致,且没有“成立度 + 局部供给优先级”双结果
+
+**现状**
+
+- 分类树 `total_score` 是四项排名分的和,范围约为 `0~4`;
+- `demand_grade.score` 是来源内排名均值,范围为 `0~100`;
+- S/A/B/C/D 是 Agent 基于提示自行判定的单一等级;
+- `DemandGrade` 只持久化 `posterior_rov_avg`,没有持久化 VOV、归因结果或独立的局部优先级。
+
+**与 PRD 的差距**
+
+PRD 要求对人展示的分数统一为 `0~1`,并分别输出:
+
+1. 需求成立度;
+2. 局部供给优先级;
+3. 置信度和行动层。
+
+**风险**
+
+- 前端、Agent 和业务人员会把不同量纲的分数误作同一分数;
+- “高可信但当前无需供给”和“证据少但值得探索”无法区分;
+- 真实 VOV、内容归因和风险抑制无法进入统一决策。
+
+**代码证据**
+
+- `supply_infra/scheduler/jobs/update_category_tree_rank_scores.py`
+- `agents/demand_grade_agent/tools/demand_priority.py`
+- `supply_infra/db/models/demand_grade.py`
+
+### P1-3:多挂靠只在分级结果层存在,缺少原始认知层的关系语义与 reason
+
+**现状**
+
+`demand_grade_category_rel` 支持一个分级结果挂多个分类;但基础表 `demand_belong_category` 仍以 `name` 唯一且只有一个 `category_id`。
+
+更关键的是,需求词和池行、需求和分类的关联大量来自名称包含匹配;关系表不保存关系类型、来源、reason、置信度、审核状态或有效期。
+
+**与 PRD 的差距**
+
+PRD 要求树是稳定骨架,需求为独立图节点;所有跨树关系都要可解释,模型推断关系需标记。
+
+**风险**
+
+- 多挂靠可能是字符串匹配副产物,而不是业务上确认的关联;
+- 无法区分“上游关联”“模型推断”“人工确认”;
+- 用户点击路径时不能解释为什么挂到该节点。
+
+**代码证据**
+
+- `supply_infra/db/models/demand_belong_category.py`
+- `supply_infra/db/models/demand_grade_category_rel.py`
+- `supply_infra/scheduler/jobs/sync_demand_belong_pool_rel.py`
+
+### P1-4:名称包含匹配会制造错误关联,且关系没有业务日期
+
+**现状**
+
+`sync_demand_belong_pool_rel` 用 `name in demand_name` 生成关系,并读取全表需求池,不限定 `biz_dt`。这使一个历史词与历史/当前不同日期的池行都可能形成永久关系。
+
+**与 PRD 的差距**
+
+PRD 要求每条关系有来源、时间、reason 和可追溯性。
+
+**风险**
+
+- 短词、重名词和包含词容易误匹配;
+- 历史关系污染当日分级归属;
+- 需求与视频的证据链无法证明是哪个日期、哪条上游事实形成的。
+
+**代码证据**
+
+- `supply_infra/scheduler/jobs/sync_demand_belong_pool_rel.py`
+- `supply_infra/db/repositories/multi_demand_pool_di_repo.py`:`list_id_name_video_lists`。
+
+### P1-5:视频点位扩展不是“需求—内容—表现归因”关系
+
+**现状**
+
+视频拓展只对 S/A 级需求执行,并把视频点位中的文本保存为 `expanded_text`。它没有记录:
+
+- 内容主承接哪个需求;
+- 辅助承接哪些需求;
+- 覆盖程度;
+- 内容质量、分发条件和样本状态;
+- ROV/VOV 中多少可归因给某个需求;
+- 归因结果如何改变次日分级。
+
+**与 PRD 的差距**
+
+PRD 的核心闭环是“需求→内容→表现→归因→次日需求”,而不是“高等级需求从视频点位生成一些扩展词”。
+
+**风险**
+
+- 后验仍只是词或分类节点上的指标,不能证明某项内容验证了某个需求;
+- 低等级和冷区需求没有获得通过内容验证的机会;
+- 扩展词可能不断增加,却不形成正式需求生命周期。
+
+**代码证据**
+
+- `supply_infra/db/models/demand_video_expansion.py`
+- `supply_infra/scheduler/jobs/expand_demand_from_video_points.py`
+- `api/services/demand_grade_videos.py`
+
+### P1-6:寻找 Agent 没有接入标准任务包,且自身提示与工具不一致
+
+**现状**
+
+`find_agent` 仍是交互式搜索/分析 Agent;它没有从 `demand_grade` 或任何标准任务包读取当日任务,也没有将找到内容写回需求—内容关系。
+
+其提示要求调用 `save_video_content`、`query_video_content`,但注册工具中不存在这两个能力。
+
+**与 PRD 的差距**
+
+PRD 要求寻找 Agent 与人消费同一任务包,并把发现作为可追溯证据回流。
+
+**风险**
+
+- “自动寻找内容”无法成为每日闭环的一部分;
+- Agent 的结果没有业务 ID、主辅需求或覆盖度;
+- 提示与实际工具不一致时,执行会产生无效调用。
+
+**代码证据**
+
+- `agents/find_agent/agent.py`
+- `agents/find_agent/tools/__init__.py`
+
+### P1-7:没有人的反馈入口,也没有“为什么不是需求”的负向决策账本
+
+**现状**
+
+当前 API 和 Vue 页面只提供树、分级需求和视频点位查询。没有创建反馈、纠错、合并拆分建议、管理指令或负向候选查询接口。
+
+数据模型中也没有候选拒绝、证据不足、重复合并、人工复核等对象。
+
+**与 PRD 的差距**
+
+PRD 要求人可以补充需求和证据,系统能回答“为什么 XX 是需求”和“为什么 XX 不是需求”。
+
+**风险**
+
+- 人无法通过产品参与定义和数据纠错;
+- 只能解释已被评级的词,无法解释未生成/被拒绝的候选;
+- 业务判断不能沉淀为下一日证据。
+
+**代码证据**
+
+- `api/app.py`
+- `web/src/`
+- `supply_infra/db/models/`
+
+### P1-8:策略中心、对话式分析和定义版本管理未实现
+
+**现状**
+
+评分规则主要分散在 Agent prompt、Python 常量和调度流程中。没有策略版本实体、定义草案、影响模拟、确认操作或面向业务人员的数据问答服务。
+
+**与 PRD 的差距**
+
+PRD 要求你可以在对话中查看定义、查询数据、要求分析、提出修改,并在影响预览后确认生效。
+
+**风险**
+
+- 同一条需求的结论难以追溯使用了哪版规则;
+- 修改 prompt 或阈值会悄悄改变结果;
+- 不能把你的业务判断转成受控、可审计的系统策略。
+
+**代码证据**
+
+- `agents/demand_grade_agent/prompt/system_prompt.md`
+- `agents/demand_grade_orchestrator_agent/prompt/system_prompt.md`
+- `api/app.py`
+
+## 7. P2:历史、可观测性和工程质量问题
+
+### P2-1:运行记录是作业日志,不是需求级业务决策账本
+
+**现状**
+
+`scheduler_job_execution` 能记录流水线开始/结束、结果摘要和错误;分级计划也能记录组和组内项状态。
+
+但它们不能把某条需求的原始证据、认知版本、评分输入、模型解释、策略版本、发布任务、内容归因和人工操作串成一条可查询的历史链路。
+
+### P2-2:同一日重复运行会覆盖分级结果,缺少修订版本
+
+`demand_grade` 按 `(biz_dt, demand_name)` upsert;`demand_grade_category_rel` 会先删除再重写。若同一天重跑或人工纠正,旧等级、旧 reason 和旧挂靠将被覆盖。
+
+这不满足 PRD 对迟到数据、更正批次和历史版本的要求。
+
+### P2-3:跨日稳定、探索配额和行动层没有持久化
+
+当前 S/A/B/C/D 是单日等级,不等于 PRD 的“保供、优先、定向验证、探索、抑制”。没有主题配额、冷区分层随机保留、升级/降级滞后和历史衰减记录。
+
+### P2-4:全局树总热度仍只由四项先验构成
+
+`CategoryTreeWeight.total_score` 只累计外部、持续、去年同期和近期四项排名分。真实 ROV/VOV 可被查询,但没有进入树的全局综合热度,也没有形成单独的后验校正结果。
+
+这使“后验反馈反向影响需求强度”只在 Agent prompt 层存在,未成为可复算的业务结果。
+
+### P2-5:没有自动化测试,且本次代码差异存在格式问题
+
+- 仓库未发现受版本管理的 Python、TypeScript 或 Vue 测试文件;
+- 前端依赖未安装,本次无法执行真实前端构建;
+- `git diff --check afa8a6d..HEAD` 报告 `web/src/components/DemandGradeListPanel.vue` 末尾多一个空白行。
+
+这不直接改变业务语义,但会降低上述复杂调度、分级和关系逻辑的回归保障。
+
+## 8. 建议的处理顺序
+
+### 第一优先级:先保证每日结果可信
+
+1. 用内容级指纹或更新时间替代“总行数相同即跳过同步”。
+2. 修正分级失败状态:任何 failed 组都不能被视为执行完成;失败时禁止发布为完整当日结果。
+3. 以单一 `biz_dt + run_id` 对齐树、分级、视频扩展和前端查询。
+4. 引入数据库迁移,禁止仅依赖 `create_all` 升级现网结构。
+
+### 第二优先级:建立 PRD 的核心对象和评分结果
+
+1. 建立“原始表达、标准需求词、平台需求、每日任务包”四层对象。
+2. 把当前 `demand_grade` 明确定位为词级证据/评估,或升级为平台需求评估;不要同时承担两种含义。
+3. 持久化 `需求成立度(0~1)`、`局部供给优先级(0~1)`、置信度、行动层、各维贡献和风险抑制。
+4. 将真实 ROV 和真实 VOV 经过归因后进入可复算的后验结果。
+
+### 第三优先级:补齐关系、内容和反馈闭环
+
+1. 用显式关系表替代字符串包含作为最终关系依据;保存关系类型、来源、reason、置信度、审核状态和有效期。
+2. 建立需求—内容多对多映射,记录主/辅助需求、覆盖度、内容质量、分发和样本状态。
+3. 将寻找 Agent 改为消费任务包、返回结构化发现并写入证据。
+4. 增加人的反馈、候选拒绝/未决、人工复核和管理指令。
+
+### 第四优先级:完成业务协作能力
+
+1. 建立策略版本、定义草案、影响模拟和确认流程。
+2. 建立可查询的业务决策账本。
+3. 支持“为什么是需求/为什么不是需求/为什么今天变化”的数据驱动问答和自动分析。
+
+## 9. 本次验证记录
+
+- 已完成:全部受 Git 管理 Python 文件的 `py_compile` 语法检查。
+- 已完成:当前提交相对 PRD 基线的差异检查和主要数据/调度/API/前端链路阅读。
+- 未发现:受版本管理的自动化测试文件。
+- 未执行:前端构建;原因是 `web/node_modules` 不存在,未在本次分析任务中安装依赖。
+- 发现:`git diff --check afa8a6d..HEAD` 报告 `DemandGradeListPanel.vue` 末尾空白行。
+

+ 242 - 0
problem/2026-07-30_问题总结.md

@@ -0,0 +1,242 @@
+# 2026-07-30 问题总结:当前代码与 PRD 的匹配度
+
+## 1. 本次结论
+
+本次以当前 `feature/zhangbo` 分支(`693fe6b`)为准,并与上一次审查基线
+`d2154ed` 对比。代码已经从“多个脚本/Agent 拼接的日任务”明显推进到“可运行、可追踪的日批次流水线”:
+
+- 有了按 `biz_dt` 创建的 Pipeline Run、步骤状态、锁、重试/恢复/取消、健康检查与运行页面;
+- 日流程覆盖了全局树、上游需求池、分类挂靠、先验/真实 ROV/VOV、需求分级、需求扩展、找片和 AIGC 写入;
+- 找片 Agent 现在以已分级需求及其视频点位为输入,并保存搜索路径、候选内容和选择结果;
+- 分类节点热度保留了四类先验与真实 ROV/VOV,需求分级也保存了 reason、挂靠分类和部分后验快照。
+
+因此,项目已经具备 PRD 的“每日自动化骨架”和一部分“需求 → 找内容”的执行能力。
+
+但它尚未实现 PRD 定义的业务 Harness:当前的正式对象仍主要是“来源词/归属词/分级结果”,而不是可版本化的平台需求;后验还没有经过“内容覆盖与表现归因”回流到需求判断;控制台也还不能完成提问、数据查询、策略草案、影响预览和确认发布。若以 PRD 成功标准验收,当前总体匹配度约为 **45%**:运行可靠性进展较快,业务闭环与可解释决策仍是主要缺口。
+
+> 说明:本文件只记录审查结论,不修改任何业务实现。优先级中的 P0 表示可能造成错误数据、重复外部动作或无法按部署方式运行;P1 表示核心 PRD 业务能力缺失;P2 表示产品/治理完整度问题。
+
+## 2. PRD 模块匹配图
+
+```mermaid
+flowchart LR
+    A[上游需求/先验/关联] --> B[当前:需求池同步与分类]
+    B --> C[当前:树热度与需求分级]
+    C --> D[当前:找片 Agent]
+    D --> E[当前:AIGC 爬取计划写入]
+    E -. 尚未形成内容表现归因 .-> C
+
+    F[PRD:人/Agent反馈] -. 尚无反馈对象与入口 .-> B
+    G[PRD:策略草案/预览/确认/版本] -. 仅有提示词注入 .-> C
+    H[PRD:平台需求任务包] -. 尚未成为统一对象 .-> D
+```
+
+| PRD 模块 | 当前实现情况 | 匹配度 | 关键判断 |
+|---|---|---:|---|
+| 证据收集 | 已同步需求池、树、视频、四类先验及真实 ROV/VOV;Pipeline Run 有日期和配置快照 | 55% | 有日数据和运行记录,但原始证据未形成不可变、可引用的证据包;同数量更新会被跳过 |
+| 需求认知与汇总 | 有分类 Agent、`reason`、树节点、部分多挂靠(分级结果) | 35% | 没有“原始表达 → 标准需求词 → 平台需求”的三层稳定对象、版本和关系语义 |
+| 评估与供给分配 | 有四类先验、ROV/VOV diff、树热度、0–100 分级和 A/S/A/B/C/D 等级 | 40% | 尚未产出两个 0–1 决策结果、五类行动层、局部供给优先级、探索抽样和可展开贡献 |
+| 发布、可视化、反馈 | 有热力图、需求详情、运行页、找片搜索/候选存储 | 40% | 不是一份供人和 Agent 共用的任务包;没有人反馈入口、完整路径/关系/评分解释与内容归因 |
+| 业务协作与策略控制 | 可查看/编辑允许名单 Agent 的提示词追加内容 | 15% | 没有业务问答、直接数据分析、策略草案、影响预览、确认、版本和审计 |
+| 每日运行与可恢复性 | 新增持久化 DAG、门禁、锁、Worker、Reconciler、运行页面 | 75% | 是本次最显著进步;但部署迁移、数据正确性和外部副作用幂等仍未闭合 |
+
+## 3. 本次改动已解决或显著改善的事项
+
+### 3.1 日批次不再只是进程内任务
+
+`pipeline_run`、`pipeline_step_run`、`pipeline_lock`、`pipeline_outbox` 与 DAG/Worker/Reconciler 已形成控制面。每一步都有运行状态和输入日期,失败步骤会阻断下游;运行可以查看、重试、恢复或取消。这与 PRD“每天自动化执行、保留历史过程、异常不能静默发布”的方向一致。
+
+### 3.2 需求分级失败会阻断后续动作
+
+流水线 Gate 会检查业务失败信息,不再把分级 Agent 的异常结果直接当作可继续下发的成功结果。相较上一次审查,这是对“失败批次不能产出正式结果”的实质修复。
+
+### 3.3 找片的过程性证据开始沉淀
+
+`video_discovery_run/search/candidate` 已能记录:需求、搜索词、搜索原因、搜索父子关系、候选视频、选择/拒绝状态和部分评分。它是未来“寻找 Agent 输出可解释、可回查”的可用基础。
+
+### 3.4 前台和部署形态更接近日常运营
+
+增加了 Pipeline Run/健康状态界面、视频发现界面,以及 scheduler、worker、reconciler 的独立进程配置;容器入口也会先执行 `alembic upgrade head`。这些改变有助于把“每日计算”从手工运行转成可运营服务。
+
+## 4. P0:应先处理的正确性和发布风险
+
+### P0-1:找片数据表没有进入 Alembic,按当前部署会导致核心步骤缺表
+
+**事实**
+
+- `video_discovery_run`、`video_discovery_search`、`video_discovery_candidate` 的 DDL 位于 `sql/video_discovery_*.sql`;
+- `alembic/versions/` 中没有这些表及其后续字段的迁移;
+- 容器入口只执行 `alembic upgrade head`,而数据库自动 `create_all` 并不是该部署路径的保证。
+
+**影响**
+
+全新环境或仅按标准迁移升级的环境,流水线到 `video_discovery` 时可能直接失败。手工执行 SQL 即使暂时绕过,也会造成模型、SQL 文件、迁移历史三套事实漂移。
+
+**建议**
+
+把当前完整的找片表结构及所有增量字段收敛为一条或一组可重复升级的 Alembic 迁移;在 CI/预发中用空库执行 `alembic upgrade head`,再跑一次最小 Pipeline Run。
+
+### P0-2:外部 AIGC 动作在 Outbox 记录之前发生,重试可能重复创建计划
+
+**事实**
+
+`_aigc_write_record()` 先调用 `publish_videos_from_discovery()`;该函数会通过 `AigcClient.create_video_crawler_plan()` 和绑定接口写入外部 AIGC 平台。外部调用完成后,才根据返回 payload 计算哈希并写入 `pipeline_outbox`。AIGC 请求中也没有传递可供对方幂等的业务键。
+
+**影响**
+
+进程在外部创建成功、尚未写入本地 Outbox 时中断,或超时后重试,会再次创建爬取/生成计划。这既会重复消耗资源,也会让“一个需求被哪些内容承接”难以准确追溯。
+
+**建议**
+
+先以稳定业务键(例如 `biz_dt + demand/task/candidate version`)创建待发送的 Outbox 事件并提交;Worker 领取事件后再调外部接口;将该业务键传给外部系统或在本地保存外部返回 ID 后再确认。重试只重放未确认事件,不能重新生成业务请求。
+
+### P0-3:上游数据“行数相同即跳过同步”,会漏掉同数量的内容修订
+
+**事实**
+
+`_sync_pool_rows()` 只比较 ODPS 与 MySQL 的当天行数;两者相等即返回 `skipped_same_count=True`。即使同一天的词、权重、视频、真实 ROV/VOV 或关联发生替换,行数不变也不会执行差量同步。
+
+**影响**
+
+需求强度、后验表现和下游找片依据可能使用过期事实;而流水线仍显示该步骤成功,形成难以察觉的错误日快照。
+
+**建议**
+
+使用上游版本号、更新时间、水位线或逐行内容哈希决定是否同步;无此字段时至少执行主键/内容哈希差分。运行输出需明确记录上游版本和变更数。
+
+### P0-4:归属边以全历史子串匹配生成,容易写入跨日和误匹配关系
+
+**事实**
+
+`sync_demand_belong_pool_rel()` 调用不带 `biz_dt` 的 `list_id_name_video_lists()`,对所有可见需求池记录按 `name in demand_name` 建边,并把所有命中视频合并到词上。`demand_belong_category.name` 还是全局唯一,关系边没有关系类型、来源、时间或置信度。
+
+**影响**
+
+短词会命中不相关长词,历史数据会混入当天关系;后续热度、视频证据和分级的输入因此不再是可说明的“当天证据”。这直接违背 PRD“上游关联保留原样、推断关系须说明”的原则。
+
+**建议**
+
+关系边应至少保存 `biz_dt/证据版本、relation_type、relation_source、reason、confidence、推断标记`;优先消费上游显式关联。若保留文本匹配,只能作为低置信候选,需边界匹配、日期过滤和人工/模型判定,不应直接成为正式边。
+
+## 5. P1:核心业务闭环仍未实现
+
+### P1-1:没有平台需求这一稳定业务对象
+
+当前 `demand_belong_category` 是“名称全局唯一 + 单一 category_id”的归属词;`DemandGrade` 是某日分级结果;`generated_demand` 存在但未进入当前 Pipeline、API 和主界面。三者没有形成 PRD 所需的:
+
+```text
+原始需求表达(不可变证据) → 标准需求词(别名/归一) → 平台需求(稳定 ID、版本、可搜索意图)
+```
+
+因此系统无法可靠回答“这个平台需求今天为何成立、与昨天是否是同一个需求、哪些原话与别名支持它”,也无法在不覆盖历史的前提下合并、拆分和再激活。
+
+**建议**:先定义并落地三层对象、版本和证据引用;只让平台需求成为评估、下游任务和反馈归因的中心对象。
+
+### P1-2:多挂靠只有 ID 列表,没有业务关系图
+
+`demand_grade_category_rel` 支持一条分级结果对应多个分类,但没有主/辅挂靠、关系语义、证据来源、reason、置信度或有效日期;原始归属词仍只能有一个分类。前台可以显示部分分类名,却不能完整解释“为什么挂在这些树枝上、哪些是上游事实、哪些是系统推断”。
+
+**建议**:将“树骨架”和“横向关系图”分开建模。多挂靠边要有类型(主挂靠/辅助挂靠/上游关联/推断关联等)、来源、reason、置信度、版本和状态;需求详情按完整祖先路径展示所有边。
+
+### P1-3:评分体系与 PRD 的两个 0–1 决策结果不一致
+
+当前分类 `total_score` 是四项先验排名分之和(约 0–4);`DemandGrade.score` 是来源内排序均值(0–100);真实 ROV/VOV 作为 diff 和样本量展示/提示给 Agent。`DemandGrade` 仅保存 ROV 的平均值/计数快照,未保存 VOV 快照,更没有可复算的贡献项。
+
+这与 PRD 已确认的规则不一致:
+
+- 面向人展示统一为 0–1;
+- 同时输出“需求成立度”和“局部供给优先级”;
+- 后验不能因缺失被当成零,需要经过内容质量、曝光、时间、覆盖度和样本量归因;
+- 决策应能展开每项贡献、扣减与 reason。
+
+**建议**:保留全部原始维度,另建立按日版本化的 `validity_score`、`local_supply_priority`、贡献明细、数据质量/样本状态与决策 reason;用这两个结果映射保供、优先、定向验证、探索、抑制,不能由一个 0–100 等级兼任。
+
+### P1-4:真实 ROV/VOV 还不是“需求—内容—表现”的反馈闭环
+
+目前真实 ROV/VOV 来自需求池词级字段并聚合到词/树,找片结果虽然保存候选视频和 AIGC 计划字段,但没有需求—内容的多对多承接关系,更没有主需求/辅助需求、覆盖程度、上线时间、曝光/质量/供给量、表现归因置信度,或“次日评分受何种反馈影响”的记录。
+
+**影响**:可看到某个词的后验 diff,但不能证明它是由哪条内容、以什么覆盖程度带来的表现;也不能反向纠偏平台需求强度。
+
+**建议**:以平台需求为中心建立内容承接边和表现事实表;将 ROV/VOV 原值与归因判断分开。每日把有效反馈、置信度和影响值写入需求评估快照,且可从需求反查到内容与原始表现。
+
+### P1-5:找片 Agent 并未消费统一的每日需求任务包
+
+当前 Find Agent 从 `DemandGrade` 及 `demand_video_expansion` 读取上下文,主要依赖已分级需求和视频点位。它没有接收 PRD 规定的需求版本、全部挂靠路径和关系、两个分数、行动层、搜索/排除词、命中规则、待验证假设、证据缺口和已有内容覆盖。
+
+**建议**:由发布模块生成唯一、可版本化的“每日需求任务包”;人和 Find Agent 都从此任务包读取,Agent 的搜索结果再写回任务包引用的需求和内容承接边。不要让两个下游各自解释 `DemandGrade`。
+
+### P1-6:没有人反馈入口,也没有“为什么是/不是需求”的可查询业务服务
+
+仓库中目前可见的控制能力是 Agent Prompt 的 document injection:一个 Agent 名仅保留一份可覆盖的文本和启用状态。没有用于新需求、挂靠、合并拆分、reason 错误、内容、判断或数据问题的反馈对象/API;也没有“为什么 XX 是需求/不是需求”的查询、历史运行检索或自动分析服务。
+
+**建议**:普通反馈作为带来源、时间、对象、类型和证据的追加事件;管理指令单独进入受控工作流。问答先落到只读查询计划和结果记录,再由模型基于这些结果作答,不能只靠提示词生成解释。
+
+### P1-7:策略修改没有草案、预览、确认和历史版本
+
+`agent_document_injection` 以 `agent_name` 唯一键 upsert,更新会覆盖旧内容;没有编辑者、修改原因、审批状态、影响范围、模拟结果或版本号。它能调整提示词,但不能承担 PRD 的业务策略控制。
+
+**建议**:把业务定义(维度字典、合并/拆分规则、行动层、探索额度、后验门槛等)建成版本化策略;自然语言修改先生成结构化草案和历史数据影响预览,确认后才由新日批次引用该版本。
+
+### P1-8:全局热力图可能混合不同业务日的数据
+
+`GlobalDemandMapView` 先读取分类树的最新日期,再独立调用不带 `biz_dt` 的需求分级接口。两类数据更新节奏不一致时,树和需求可能来自不同日期,热力图会显示为同一天的全局结果,但实际并非同一快照。
+
+**建议**:页面先确定一个已成功完成的 Pipeline Run / `biz_dt`,随后所有树、需求、关系、评分和内容接口强制携带同一日期与策略版本;数据不完整时显示“该批次未发布”,不要回退拼接最新值。
+
+## 6. P2:可运营性与治理完整度问题
+
+### P2-1:Pipeline 的快照还不是完整的证据快照
+
+Pipeline Run 记录 `biz_dt`、代码/配置快照和步骤输出,十分有价值;但输入表会持续被同步更新,尚未把每条原始事实、关系和后验以可引用 ID 封存到“每日证据包”。历史 Run 因此不能完全在原始输入已变更后复算或逐项解释。
+
+### P2-2:找片过程有存储,但面向人的解释面没有接通
+
+搜索词、搜索 reason、候选和决策桶已保存;`/api/video-discovery` 当前主要返回分级需求、视频点位和来源视频,而非完整的搜索图、候选评分、拒绝原因、内容承接关系和表现反馈。前台不能完整展示 PRD 中要求的“决策全过程”。
+
+### P2-3:测试不能在当前环境运行
+
+本机执行 `python3.11 -m pytest -q` 在收集阶段失败:当前解释器载入的 SQLAlchemy 不包含 `sqlalchemy.orm.DeclarativeBase`,而项目声明 `sqlalchemy>=2.0`。共出现 14 个收集错误,Pipeline 与 Scheduler 测试均未真正执行;pytest 同时提示当前环境不识别 `asyncio_mode` 配置。
+
+这更像是环境依赖没有按项目要求安装,而非已证明的业务逻辑失败,但它仍阻断了本地/CI 对本次改动的可信验证。
+
+**建议**:固定 Python 与依赖锁定方式,在 CI 使用干净环境安装 `pyproject.toml`/requirements;增加空库迁移、单日最小流水线、外部副作用幂等、同数量内容变化、跨日关系隔离的集成测试。
+
+### P2-4:现有质量检查发现历史文档格式问题
+
+`git diff --check d2154ed..HEAD` 报告已有文件 `problem/2026-07-24_问题总结.md` 在 EOF 有多余空行。它不影响运行,但说明提交前的基础质量检查没有全绿。
+
+## 7. 建议的修复顺序
+
+```mermaid
+flowchart TD
+    A[P0:可信运行] --> B[迁移收敛:空库可升级]
+    A --> C[外部动作先出箱后发送]
+    A --> D[输入按版本/哈希差分]
+    A --> E[关系按日期与语义建边]
+
+    B --> F[P1:定义平台需求与证据包]
+    C --> F
+    D --> F
+    E --> F
+    F --> G[双 0–1 评估 + 五类行动层]
+    G --> H[统一每日任务包]
+    H --> I[需求—内容—表现归因]
+    I --> J[人反馈、问答与策略版本控制]
+```
+
+建议按以下四个阶段推进:
+
+1. **先使日运行可信**:解决 P0-1 至 P0-4,并用空库迁移、同数量更新、失败重试和重复外部调用测试作为发布门禁。
+2. **再统一业务对象**:定义证据包、原始表达、标准需求词、平台需求、树边/图边和版本;停止把字符串子串匹配直接当正式业务关系。
+3. **再建立可解释决策与下游契约**:输出两个 0–1 分数、行动层和统一任务包,热力图只消费该已发布任务包的同一批次快照。
+4. **最后闭合学习与协作**:建立内容承接和表现归因,再加入人的反馈、为什么问答、策略草案/影响预览/确认/审计。
+
+## 8. 本次审查验证记录
+
+| 检查 | 结果 | 说明 |
+|---|---|---|
+| 工作区状态 | 通过 | 审查开始时未见未提交业务代码改动;本次仅新增本文件 |
+| `git diff --check d2154ed..HEAD` | 有告警 | 发现 2026-07-24 旧问题总结文件 EOF 多余空行 |
+| `python3.11 -m pytest -q` | 未通过 | 14 个测试收集错误,当前环境 SQLAlchemy 版本低于项目所需 2.x;测试未进入业务断言 |
+| 代码静态核对 | 完成 | 核对了 Pipeline DAG/门禁、迁移、部署入口、数据同步、关系同步、评分、Find Agent、AIGC 外部写入、API 与前台取数 |
+

+ 0 - 823
zhangbo.md

@@ -1,823 +0,0 @@
-# SupplyAgent 代码仓库结构总结
-
-## 1. 阅读基线
-
-本文档完全基于当前代码仓库重新阅读后形成,不继承此前对项目的业务推演或可视化设计理解。
-
-代码快照:
-
-- 分支:`feature/zhangbo`
-- 阅读时提交:`2ab77ce`
-- Python 要求:`>= 3.11`
-- 后端:FastAPI + SQLAlchemy 2.x + PyMySQL
-- Agent:OpenRouter/OpenAI 兼容 API + 自研 Tool/Skill/ReAct 框架
-- 数据源:ODPS(MaxCompute)
-- 数据库:MySQL
-- 对象存储:阿里云 OSS
-- 前端:Vue 3 + TypeScript + Vite
-
-`.env` 已被 `.gitignore` 忽略。本文不会记录其中的密码、密钥、数据库地址或 Token。
-
----
-
-## 2. 当前项目的实际定位
-
-当前 SupplyAgent 由两部分组成:
-
-1. 一套通用 AI Agent 运行框架;
-2. 一套围绕“需求词、全局分类树、热度、视频和需求生成”的业务系统。
-
-业务系统当前主要完成:
-
-- 从 ODPS 同步全局分类树和树下元素;
-- 从 ODPS 同步多策略需求池;
-- 将需求词挂到分类树节点;
-- 汇总四项先验热度和真实 ROV/VOV;
-- 把词级热度沿分类树向上聚合;
-- 按单一热度维度生成并保存平台需求;
-- 把需求词连接到真实视频和视频最终选题;
-- 通过 API 和 Vue 页面展示分类树、热力图和下钻证据;
-- 记录 Agent 完整执行过程,生成 HTML,上传 OSS 并在 MySQL 留档。
-
-当前系统的核心业务链路是:
-
-```text
-ODPS 全局分类与元素
-        ↓
-MySQL 全局分类树
-        ↑
-需求池词语 → 归类 Agent → 需求词挂靠
-        ↓
-四项先验 + 真实 ROV/VOV
-        ↓
-词级统计 → 分类树节点聚合 → 四维全局排名
-        ↓
-需求生成 Agent → generated_demand
-        ↓
-FastAPI → Vue 分类树/热力图/证据下钻
-```
-
----
-
-## 3. 仓库分层
-
-```text
-SupplyAgent/
-├── supply_agent/       通用 Agent 框架
-├── agents/             业务 Agent 和专属工具
-├── supply_infra/       MySQL、ODPS、OSS、定时任务
-├── api/                FastAPI 查询接口和静态前端托管
-├── web/                Vue 3 业务前端
-├── scripts/            部署、日志上传、日志可视化脚本
-├── visualization/      早期/独立的业务设计可视化材料
-├── Dockerfile          前端构建 + Python 运行镜像
-├── pyproject.toml      Python 包、依赖和命令入口
-└── requirements.txt    另一份运行依赖清单
-```
-
-任务 CLI 已并入 `supply_infra/scheduler/jobs/`(`python -m ...`)。
-
-模块之间的依赖方向:
-
-```text
-web
-  ↓ HTTP
-api
-  ↓
-supply_infra.db.repositories
-  ↓
-MySQL
-
-agents
-  ↓
-supply_agent(Agent 框架)
-  ↓
-supply_infra(数据库/ODPS/OSS)
-
-jobs / scheduler
-  ↓
-supply_infra.scheduler.jobs
-  ↓
-ODPS + MySQL + 业务 Agent
-```
-
----
-
-## 4. 通用 Agent 框架:`supply_agent/`
-
-### 4.1 `supply_agent/config.py`
-
-负责 Agent 侧配置:
-
-- OpenRouter API Key、模型和 Base URL;
-- Agent 最大迭代次数和温度;
-- Skills 目录;
-- 日志目录和日志开关。
-
-配置来自环境变量或项目根目录 `.env`,相对路径会解析到项目根目录。
-
-### 4.2 `supply_agent/llm/client.py`
-
-基于 OpenAI Python SDK 连接 OpenRouter,提供:
-
-- 同步对话 `chat`;
-- 异步对话 `achat`;
-- 同步文本流 `stream`;
-- 异步文本流 `astream`;
-- Tool Calling;
-- OpenRouter reasoning effort;
-- LLM 输入和输出日志。
-
-模型可以在运行时切换。
-
-### 4.3 `supply_agent/tools/`
-
-`base.py` 提供:
-
-- `@tool` 装饰器;
-- 从 Python 函数签名生成 JSON Schema;
-- Optional 和基础类型转换;
-- 同步/异步工具执行;
-- 异常转为 JSON 错误结果。
-
-`registry.py` 提供:
-
-- 工具注册、删除和查询;
-- OpenAI ToolDefinition 列表;
-- 根据模型返回的工具名执行工具;
-- 同步和异步执行;
-- 批量注册被 `@tool` 装饰的函数。
-
-### 4.4 `supply_agent/skills/`
-
-Skill 机制读取指定目录下的 `SKILL.md`:
-
-- 支持 YAML frontmatter 的名称和描述;
-- 启动时把 Skill 目录作为目录索引加入系统提示词;
-- Agent 通过内置 `load_skill` 工具按需加载全文;
-- Skill 加载后会重建系统消息并注入当前上下文。
-
-当前仓库根目录的 `skills/` 被 `.gitignore` 忽略,因此代码支持 Skill,但仓库没有可随代码分发的业务 Skill 内容。
-
-### 4.5 `supply_agent/agent/`
-
-`core.py` 的 `Agent` 负责组装:
-
-- LLMClient;
-- ToolRegistry;
-- SkillRegistry;
-- AgentLoop;
-- AgentLogger。
-
-对外提供:
-
-- `run`;
-- `arun`;
-- `stream`;
-- `astream`。
-
-`loop.py` 实现标准 ReAct/Tool Calling 循环:
-
-```text
-系统消息 + 对话历史
-        ↓
-调用 LLM
-        ↓
-有工具调用?──否──→ 返回最终结果
-        │是
-        ↓
-执行工具并写入 Tool Message
-        ↓
-下一轮 LLM
-```
-
-达到最大迭代次数时,同步和普通异步运行会追加一条用户消息,要求模型给出当前最佳答案;流式路径则直接发出 Max iterations reached。
-
-### 4.6 `supply_agent/logging/`
-
-每次 Agent 运行生成:
-
-- 人类可读 `.log`;
-- 结构化 `.jsonl`。
-
-日志记录:
-
-- run_start;
-- 完整 LLM 输入;
-- 模型输出和 reasoning;
-- 工具调用参数和结果;
-- Skill 加载;
-- run_end。
-
-运行结束后:
-
-1. 将日志渲染成 HTML;
-2. 上传 `.log`、`.jsonl`、`.html` 到 OSS;
-3. 把 HTML 公网地址写入 `oss_logs`;
-4. 上传失败只记录错误,不影响 Agent 主结果。
-
----
-
-## 5. 三个业务 Agent
-
-## 5.1 `demand_belong_category_agent`
-
-目标:把需求词挂到真实存在的全局分类树节点。
-
-工具:
-
-- `query_global_tree_category`:读取整棵树或指定子树;
-- `batch_insert_demand_belong_category`:批量写入需求词、分类 ID 和原因。
-
-业务流程:
-
-1. 查看顶层分类;
-2. 选择最相关分支;
-3. 逐层下钻;
-4. 不确定时停在更可靠的上层节点;
-5. 将结果写入 `demand_belong_category`。
-
-系统提示允许一个词选择一个或多个高置信节点,但当前数据库和写入工具以 `name` 唯一:
-
-- `demand_belong_category.name` 有唯一约束;
-- 同一次请求也按 name 去重;
-- 因此当前实现实际上只能保存“一词一个分类节点”;
-- 多挂靠尚未在当前表结构中实现。
-
-定时任务会把新需求词按 100 个一批交给该 Agent。
-
-## 5.2 `generate_demand_agent`
-
-目标:从分类树局部热度和已挂靠需求词中,按单一维度生成平台需求结果。
-
-支持的来源维度只有四项先验:
-
-- `ext_pop`:外部热度;
-- `plat_sust_pop`:平台持续热度;
-- `plat_ly_pop`:平台去年同期热度;
-- `recent_pop`:近期热度。
-
-一次运行只允许处理一个维度。
-
-工具:
-
-- `query_latest_biz_dt`:取两张统计表都有数据的最新日期;
-- `query_category_tree_by_dim`:查看指定维度有数据的树;
-- `query_category_leaves_by_dim`:定位有数据的叶子节点;
-- `query_demand_words_by_category`:查询节点或子树下的真实需求词;
-- `query_category_path`:补充根到节点的路径;
-- `batch_save_generated_demands`:写入 `generated_demand`。
-
-输出结构固定为:
-
-```text
-source_dim
-  └── overall_direction
-        └── summary_event
-              └── demand_name
-```
-
-重要约束:
-
-- `demand_name` 必须原样来自 `demand_belong_category.name`;
-- Agent 不能新造需求词;
-- `summary_event` 尽量对应一个需求,最多轻量合并 2~3 个强相关需求;
-- 写入时保存类目、路径、维度 avg/count 快照、reason、业务日和 run_id;
-- 同一次工具调用按 `(source_dim, demand_name)` 去重;
-- 当前 `generated_demand` 没有数据库唯一约束,不同 run 可以重复生成相同需求。
-
-真实 ROV/VOV 当前不属于该 Agent 的 `source_dim`,也没有参与其单维生成工具链。
-
-## 5.3 `find_agent`
-
-目标:根据需求词、参考视频标题和相关点,寻找老年受众更可能观看和分享的抖音视频。
-
-当前注册的业务工具包括:
-
-- `batch_search_and_record`:批量执行多个关键词和分页搜索,每页创建独立搜索及候选记录;
-- `douyin_search`:调用外部抖音关键词搜索服务并返回数据库记录 ID;
-- `douyin_search_tikhub`:调用 TikHub 搜索,保存分页状态并返回数据库记录 ID;
-- `douyin_user_videos`:按作者 sec_uid、排序和游标扩展历史作品并返回数据库记录 ID;
-- `douyin_detail`:按 content_id 获取视频详情和可播放地址;
-- `get_content_fans_portrait`:获取视频点赞用户画像;
-- `get_account_fans_portrait`:获取作者粉丝画像;
-- `batch_fetch_portraits`:批量获取视频画像,并可同时获取作者画像;
-- `normalize_age_portraits`:标准化 `50-` 等年龄桶及双侧证据;
-- `create_video_discovery_run`:创建可追踪的找视频运行;
-- `batch_update_video_discovery_candidates`:按 candidate_id 更新证据、评分和最终分池;
-- `update_video_discovery_run_status`:独立更新找视频运行状态;
-- `query_video_discovery_state`:查询搜索树和候选分池。
-
-搜索和详情接口有约 10 秒的请求间隔限制。
-
-Agent 以需求相关性、老年受众倾向和分享价值的联合目标做判断。系统提示明确区分
-“分享量高”和“受众偏老”两类证据,使用视频点赞画像作为内容侧证据、作者粉丝画像
-作为账号先验,并对画像缺失或冲突降低置信度。搜索词由 Agent 根据需求、参考标题、
-相关点和途中发现的有效标签自主决定;支持多关键词、游标翻页和标签扩展。与需求无关
-但老年倾向、分享价值双高的视频保存在人工备选池。
-
-搜索过程持久化到:
-
-- `video_discovery_run`:任务输入、意图、状态与计数;
-- `video_discovery_search`:逐关键词、逐游标页的搜索轨迹;
-- `video_discovery_candidate`:视频详情、双侧画像、标签、评分、分池与人工审核状态。
-
----
-
-## 6. 基础设施:`supply_infra/`
-
-### 6.1 配置
-
-`supply_infra/config.py` 管理:
-
-- MySQL;
-- ODPS;
-- APScheduler;
-- 阿里云 OSS;
-- Agent 日志上传开关。
-
-配置文件固定从项目根目录 `.env` 读取,不依赖当前工作目录。
-
-### 6.2 数据库会话
-
-`supply_infra/db/session.py`:
-
-- 懒加载全局 SQLAlchemy Engine;
-- 使用连接池和 `pool_pre_ping`;
-- `get_session()` 自动提交;
-- 异常时自动回滚;
-- `init_db()` 通过 ORM metadata 创建缺失表。
-
-### 6.3 Repository 规则
-
-业务 Agent、API 和定时任务原则上不直接执行 MySQL SQL,而是通过 Repository:
-
-- 基础 CRUD;
-- 批量插入;
-- insert ignore;
-- upsert;
-- 条件查询;
-- 批量更新。
-
-ODPS 查询仍在 `supply_infra/odps/client.py` 内直接组织 SQL。
-
-### 6.4 ODPS 客户端
-
-当前读取的主要 ODPS 数据:
-
-- `public_pattern_mining_category`:全局分类;
-- `pattern_mining_element`:树下元素;
-- `dwd_multi_demand_pool_di`:多策略需求池;
-- `dwd_topic_decode_result_di`:视频解析和最终选题;
-- `dwd_video_produce_plan_stat_hour`:真实 ROV/VOV。
-
-### 6.5 OSS 客户端
-
-负责:
-
-- 生成对象路径;
-- 上传本地文件;
-- 返回 CDN 公网地址。
-
----
-
-## 7. MySQL 数据模型
-
-当前 ORM 定义 10 张表。
-
-| 表 | 作用 | 关键唯一性/关联 |
-|---|---|---|
-| `global_tree_category` | 全局分类树节点 | `source_id` 唯一;`parent_id` 形成树 |
-| `global_tree_element` | ODPS 元素与分类挂靠 | `(name, category_id)` 唯一 |
-| `multi_demand_pool_di` | 按日同步的策略需求池 | 代码按 `(strategy, demand_id, biz_dt)` 管理差异 |
-| `demand_belong_category` | 需求词归属分类 | `name` 唯一;当前一词只能保存一个分类 |
-| `demand_belong_pool_rel` | 需求词与需求池行的匹配边 | `(demand_belong_category_id, multi_demand_pool_di_id)` 唯一 |
-| `demand_popularity_stats` | 词级六维 avg/count | `(demand_category_id, biz_dt)` 唯一 |
-| `category_tree_weight` | 分类树节点六维聚合和四维排名分 | `(category_id, biz_dt)` 唯一 |
-| `multi_demand_video_detail` | 视频标题与最终选题 JSON | `vid` 唯一 |
-| `generated_demand` | 需求生成 Agent 输出 | 按 run_id 记录,无数据库唯一约束 |
-| `oss_logs` | Agent 日志 HTML 的 OSS 地址 | 按 agent_name 查询 |
-
-### 7.1 关键关系
-
-```text
-global_tree_category.id
-  ├── global_tree_category.parent_id
-  ├── global_tree_element.category_id
-  ├── demand_belong_category.category_id
-  ├── category_tree_weight.category_id
-  └── generated_demand.category_id
-
-demand_belong_category.id
-  ├── demand_popularity_stats.demand_category_id
-  ├── demand_belong_pool_rel.demand_belong_category_id
-  └── generated_demand.demand_belong_id
-
-multi_demand_pool_di.id
-  └── demand_belong_pool_rel.multi_demand_pool_di_id
-```
-
-这些关联在 ORM 中主要以整数 ID 表达,没有使用 SQLAlchemy relationship,也没有显式数据库 ForeignKey。
-
----
-
-## 8. 热度数据的真实代码口径
-
-### 8.1 策略到四项先验的映射
-
-代码把需求池策略映射为:
-
-| ODPS strategy | 统计字段 | 页面含义 |
-|---|---|---|
-| `新热事件` | `ext_pop` | 外部热度 |
-| `逐月` | `plat_sust_pop` | 平台持续热度 |
-| `去年同期阳历` | `plat_ly_pop` | 去年同期热度 |
-| `去年同期阴历` | `plat_ly_pop` | 去年同期热度 |
-| `当下供需gap` | `recent_pop` | 近期热度 |
-
-### 8.2 真实 ROV/VOV
-
-从近 7 日 `dwd_video_produce_plan_stat_hour` 获取人工 AGC 和自动 AGC 数据:
-
-- ROV = 回流 UV / 分发曝光 PV;
-- VOV = 拉回曝光 PV / 分发曝光 PV;
-- 同一特征值存在多行时,优先保留 `rov_diff`、`vov_diff` 较高的一行;
-- 按特征值与 `demand_name` 精确匹配,回填 `multi_demand_pool_di`。
-
-### 8.3 词级统计
-
-对每个 `demand_belong_category.name`:
-
-1. 在当日 `multi_demand_pool_di.demand_name` 中执行子串 LIKE 匹配;
-2. 按策略收集非零 weight;
-3. 分别计算四项先验的 avg/count;
-4. 汇总匹配行的真实 ROV/VOV avg/count;
-5. 写入 `demand_popularity_stats`。
-
-因此当前词与需求池的匹配核心是字符串包含关系,不是分词索引、向量匹配或显式语义关系。
-
-### 8.4 分类树节点聚合
-
-分类节点聚合六个独立维度:
-
-- 外部热度;
-- 平台持续热度;
-- 去年同期热度;
-- 近期热度;
-- 真实 ROV;
-- 真实 VOV。
-
-每个节点统计其整个子树内有需求词挂靠的节点:
-
-```text
-节点维度 avg = Σ(挂靠点 avg × count) / Σ(count)
-节点维度 count = Σ(count)
-```
-
-结果写入 `category_tree_weight`。
-
-### 8.5 四维排名分和全局热度
-
-`demand_pool/tree_weight.py` 在写入权重后会对四项先验排名:
-
-- 各维只让 `count > 0` 的节点参与;
-- 按 avg 降序排名;
-- 同分取平均名次;
-- 映射到 `(0, 1]`;
-- 无数据节点为 0;
-- `total_score` 是四个排名分直接相加,范围 `[0, 4]`。
-
-真实 ROV/VOV 会被聚合并通过 API 返回,但当前不进入 `total_score`。
-
-前端显示“全局热度”时再使用 `total_score / 4` 映射为 `0~1` 色阶。
-
-单一维度热度则由前端根据该维所有有数据节点的 avg 做百分位色阶,不直接使用数据库中的四维 rank score 字段。
-
----
-
-## 9. 定时任务和数据流水线
-
-### 9.1 已注册的定时任务
-
-`supply_infra/scheduler/app.py` 当前只注册一条任务:
-
-1. 每天 `15:00`(`SCHEDULER_TIMEZONE`):串行执行全链路
-   `run_supply_pipeline`(全局树 → 需求池 → 分级 → 拓展 → 找视频 → AIGC 发布)。
-
-### 9.2 全局树同步
-
-`sync_global_tree_odps_to_mysql`:
-
-1. 拉取有效元素;
-2. 拉取全部分类;
-3. 从元素命中的分类向上补齐祖先;
-4. 按 ODPS source_id 去重;
-5. 已有分类保持不变,只插入新分类;
-6. 给新分类分配 MySQL ID 并转换 parent_id;
-7. 写入元素及其 MySQL category_id。
-
-该任务是增量插入,不会根据 ODPS 当前状态自动删除或更新历史分类。
-
-### 9.3 策略需求池完整流水线
-
-`supply_infra.scheduler.jobs.demand_pool`(`sync_multi_demand_pool_odps_to_mysql`)实际执行顺序:
-
-1. 比较 ODPS 与 MySQL 当日去重行数;
-2. 行数不同时执行差异同步;
-3. 对当日所有 demand_name 按空格拆词;
-4. 调用归类 Agent 处理未出现过的新词;
-5. 建立需求词与需求池的子串匹配边,并回填词级 video_list;
-6. 获取并回填近 7 日真实 ROV/VOV;
-7. 计算词级六维 avg/count;
-8. 计算整棵分类树六维聚合;
-9. 计算四项先验全局排名分和 total_score;
-10. 同步全部待处理视频的标题和最终选题。
-
-当前有一个同步判断风险:只要 ODPS 和 MySQL 行数相同,就跳过需求池差异拉取;如果内容发生变化但总行数不变,该轮不会发现这些变化。
-
-### 9.4 手动任务入口
-
-用 `python -m` 调用(与定时流水线同源):
-
-- `python -m supply_infra.db`:初始化数据库;
-- `python -m supply_infra.scheduler.jobs.run_supply_pipeline`:全链路;
-- `python -m supply_infra.scheduler.jobs.demand_pool`:需求池同步(含内部阶段);
-- `python -m supply_infra.scheduler.jobs.grade_demand_pool`:分级(可加 `--retry-failed`);
-- 以及 global_tree / expand / discover / publish 各步骤模块。
-
-也可通过 API `POST /api/scheduler/jobs/{job_id}/run` 手动触发。
-
----
-
-## 10. FastAPI:`api/`
-
-服务端口:`8080`。
-
-| 接口 | 作用 |
-|---|---|
-| `GET /health` | 健康检查 |
-| `GET /api/category-tree?biz_dt=YYYYMMDD` | 返回嵌套分类树、六维 avg/count、total_score 和挂靠词数 |
-| `GET /api/demand-belong-category` | 返回所有有效需求词挂靠 |
-| `GET /api/demand-belong-category/{id}/videos` | 返回需求词关联的视频标题和最终选题 JSON |
-| `GET /api/demand-belong-oss-logs` | 返回归类 Agent 的 OSS 日志列表 |
-
-如果 `web/dist` 存在,FastAPI 会把它挂到 `/`,同一个 8080 服务同时提供 API 和生产前端。
-
-API 当前是同步 SQLAlchemy 查询,没有分页、鉴权或缓存。
-
----
-
-## 11. Vue 前端:`web/`
-
-### 11.1 路由
-
-| 路由 | 页面 |
-|---|---|
-| `/` | 平台全局需求地图 |
-| `/demand-tree` | 传统横向分类树 |
-| `/demand-process` | 需求归类 Agent 日志 |
-| `/demand-map` | 重定向到 `/` |
-
-当前顶部导航只显示“平台全局需求地图”,另外两个页面有路由但没有导航入口。
-
-### 11.2 平台全局需求地图
-
-`GlobalDemandMapView.vue` 并行读取:
-
-- 完整分类树和热度;
-- 全部需求词挂靠。
-
-`IcicleHeatTree.vue` 使用 Canvas 绘制从左到右的冰柱树:
-
-- 每层固定 `200px` 宽;
-- 全局状态适配视口高度;
-- 选择层级或聚焦节点后按可读高度纵向扩展;
-- 最大逻辑画布高度 `24000px`;
-- 实际 Canvas 始终只有视口大小,只绘制可见区域;
-- 普通滚轮滚动;
-- 拖拽平移;
-- `Ctrl/Command + 滚轮` 缩放;
-- 点击节点聚焦子树;
-- 支持层级起点和祖先面包屑。
-
-热力标签:
-
-- 全局树结构;
-- 全局热度 `total_score`;
-- 外部热度;
-- 平台持续热度;
-- 去年同期热度;
-- 近期热度。
-
-API 虽然返回真实 ROV/VOV,但当前冰柱图标签没有提供真实 ROV/VOV 的独立切换入口。
-
-### 11.3 节点证据下钻
-
-分类节点存在需求词时显示搜索标识。点击后通过 `DemandPathPanel.vue` 展开:
-
-```text
-当前分类节点
-  → 细节元素/需求词
-  → 真实视频实例
-  → 最终选题 JSON
-```
-
-这里展示的是 `demand_belong_category` 需求词,不是 `generated_demand` 中由生成 Agent 产出的四层平台需求。
-
-当前前端没有读取或展示 `generated_demand` 的 API。
-
-### 11.4 传统分类树页面
-
-`CategoryTree.vue` 使用 Vue DOM 递归组件展示:
-
-- 默认展开 3 层;
-- 支持选择展开深度;
-- 支持手动展开和收起;
-- 支持按维度过滤有数据的节点;
-- 支持拖动画布;
-- 支持导出包含数据的独立 HTML;
-- 同样可以下钻需求词、视频和最终选题。
-
-### 11.5 需求归类过程页面
-
-读取 `demand_belong_category_agent` 的 `oss_logs`,按时间倒序显示,点击打开 Agent 运行过程 HTML。
-
----
-
-## 12. 部署和运行
-
-### 12.1 Python 命令入口
-
-`pyproject.toml` 注册:
-
-- `supply-api`;
-- `supply-visualize`。
-
-### 12.2 本地开发
-
-后端:
-
-```bash
-python -m api
-```
-
-前端:
-
-```bash
-cd web
-npm install
-npm run dev
-```
-
-Vite 在 `5173`,将 `/api` 代理到 `127.0.0.1:8080`。
-
-### 12.3 Docker
-
-Docker 使用两阶段构建:
-
-1. Node 20 构建 Vue;
-2. Python 3.11 安装项目和 ODPS 可选依赖;
-3. 把 `web/dist` 放入 Python 镜像;
-4. 通过 `python -m api` 启动 8080。
-
-`scripts/docker-deploy.sh` 可以构建并向指定镜像仓库推送时间戳标签和 `latest`。
-
----
-
-## 13. 当前代码已经实现的能力
-
-- 通用同步/异步 Agent 和 Tool Calling;
-- 动态 Skill 加载机制;
-- 三个业务 Agent;
-- 全量 Agent 日志和 OSS 发布;
-- ODPS 到 MySQL 的全局树同步;
-- 多策略需求池增量同步;
-- 新词自动归类;
-- 需求词与需求池匹配边;
-- 真实 ROV/VOV 回填;
-- 词级六维统计;
-- 分类树六维向上聚合;
-- 四项先验排名和 total_score;
-- 单维度平台需求生成与落库;
-- 视频标题和最终选题同步;
-- FastAPI 查询接口;
-- Vue 全局冰柱热力图;
-- 分类节点到需求词、视频和最终选题的下钻;
-- Docker 构建和部署脚本。
-
----
-
-## 14. 当前代码未完成或存在偏差的部分
-
-### 14.1 需求多挂靠尚未实现
-
-`demand_belong_category.name` 唯一,当前一个需求词只能保存一个 category_id。系统提示中的“一词多个节点”无法真实落库。
-
-### 14.2 `generated_demand` 未进入产品展示
-
-需求生成 Agent 已能写 `generated_demand`,但:
-
-- 没有对应 API;
-- 前端没有需求清单;
-- 没有与内容、反馈的展示闭环;
-- 当前全局图下钻的是需求词,不是最终生成需求。
-
-### 14.3 后验没有进入全局综合分
-
-真实 ROV/VOV 已采集、聚合并由 API 返回,但:
-
-- 不进入 `total_score`;
-- 不进入 generate_demand_agent 的 source_dim;
-- 当前主热力图没有 ROV/VOV 标签;
-- 尚未形成“后验反向调整最终需求排序”的完整实现。
-
-### 14.4 `find_agent` 的外部证据仍可增强
-
-当前已持久化搜索轨迹、正式推荐和人工备选,但画像接口提供的是点赞用户而非真实转发
-用户。后续若能补充转发用户画像、分年龄观看留存、相似视频和批量搜索接口,可进一步
-提高老年分享判断的直接性与多词多页探索效率。
-
-### 14.5 关系语义较弱
-
-当前主要关系是:
-
-- 树父子;
-- 需求词到单一分类;
-- 需求词和需求池的字符串子串匹配;
-- 需求词到视频列表。
-
-尚没有独立的语义关系表、关系类型、关系 reason、置信度和人工审核状态。
-
-### 14.6 同步完整性风险
-
-需求池同步先比较总行数。总行数相同但内容变化时,会跳过 ODPS 明细同步。
-
-### 14.7 测试体系缺失
-
-当前仓库没有 `tests/`,并且 `.gitignore` 直接忽略 `tests/`,会阻止正常提交测试目录。
-
-### 14.8 文档已滞后
-
-现有 `README.md`、`ARCHITECTURE.md` 和 `agents/README.md` 包含已经不存在或未实现的结构,例如:
-
-- `video_content` 模型/Repository;
-- find_agent 的保存和历史查询工具;
-- 旧的 Agent 数量和数据流。
-
-后续应以本文和源码为准,并更新旧文档。
-
----
-
-## 15. 当前本地运行环境与数据库状态
-
-### 15.1 本地 Python 环境不匹配
-
-当前机器默认环境:
-
-- Python `3.10.19`;
-- SQLAlchemy `1.4.51`;
-- 项目根目录没有 `.venv`。
-
-源码要求:
-
-- Python `>=3.11`;
-- SQLAlchemy `>=2.0`。
-
-因此直接使用当前默认 `python3` 导入数据库层会在 `DeclarativeBase` 处失败。应建立 Python 3.11+ 虚拟环境后安装项目依赖。
-
-### 15.2 `.env` 的 MySQL 配置问题
-
-只读连接检查发现:
-
-1. `MYSQL_HOST` 的值开头多了一个 `=`,会导致主机名解析失败;
-2. 临时去掉该字符后可以到达 MySQL 服务,但返回错误 `1045 Access denied`;
-3. 需要核对用户名/密码、RDS 白名单或该用户允许连接的 Host 范围。
-
-由于未通过鉴权,本次无法确认数据库真实表数量、行数和最新业务日。本文的数据结构来自当前 ORM 和 Repository 源码,不冒充线上运行态数据。
-
-### 15.3 前端依赖未安装
-
-当前没有 `web/node_modules`。Node `20.11.1`、npm `10.2.4` 已存在,执行前需要先在 `web/` 运行 `npm install` 或 `npm ci`。
-
----
-
-## 16. 建议的后续阅读顺序
-
-如果继续开发,建议按以下顺序进入代码:
-
-1. `supply_infra/scheduler/jobs/demand_pool/`:理解需求池同步主业务;
-2. `supply_infra/db/models/`:理解真实数据对象;
-3. `supply_infra/scheduler/jobs/demand_pool/tree_weight.py`:理解树上热度;
-4. `agents/demand_belong_category_agent/`:理解需求词挂树;
-5. `agents/generate_demand_agent/`:理解平台需求生成;
-6. `api/services/category_tree.py`:理解后端对前端的数据形态;
-7. `web/src/components/IcicleHeatTree.vue`:理解全局热力图;
-8. `web/src/components/DemandPathPanel.vue`:理解节点证据下钻;
-9. `supply_agent/agent/`:理解底层 Agent 执行机制;
-10. `supply_agent/logging/`:理解可追溯运行日志。
-
----
-
-## 17. 一句话总结
-
-当前 SupplyAgent 是一套以 ODPS 和 MySQL 为数据底座、以全局分类树为组织骨架、以自研 Agent 框架完成需求词归类和单维需求生成、并通过 FastAPI/Vue 展示分类热度与视频证据的业务系统;核心数据流水线已经形成,但多挂靠、最终需求产品化、后验反馈进入综合决策、语义关系图和自动化测试仍未完成。