Add keyword cleanup governance workflow
This commit is contained in:
@@ -0,0 +1,461 @@
|
||||
# 日报级词元库与词元清洗 Skill 设计
|
||||
|
||||
## 1. 设计目标
|
||||
|
||||
当前项目已经具备:
|
||||
|
||||
`FreshRSS -> extraction -> LLM summary -> rule engine -> OpenClaw payload`
|
||||
|
||||
下一阶段希望新增“词元库”能力,目标不是做全文级检索索引,而是解决两件事:
|
||||
|
||||
1. 为后续规则配置提供稳定、轻量、可读的词元来源
|
||||
2. 为周期性的词元清洗、合并和兴趣词补充提供数据基础
|
||||
|
||||
因此这套设计的核心原则是:
|
||||
|
||||
- 词元来源轻量化
|
||||
- 数据粒度日报化
|
||||
- 主链路程序化维护
|
||||
- 清洗治理由独立 skill 周期性执行
|
||||
- LLM 不直接修改规则或兴趣词配置
|
||||
|
||||
## 2. 为什么不用逐篇词元库
|
||||
|
||||
逐篇记录每篇文章的词元事件,虽然可追溯,但当前阶段成本过高,收益不足:
|
||||
|
||||
- 生成文件会很多
|
||||
- 存储和调试负担更大
|
||||
- 后续真正调规则时,用户更关心“最近日报里反复出现什么词”,而不是“某一篇文章具体抽到了什么词”
|
||||
- 当前目标是服务日报与规则配置,不是做文章级分析平台
|
||||
|
||||
所以本项目不采用:
|
||||
|
||||
`article -> term event -> term store`
|
||||
|
||||
而采用:
|
||||
|
||||
`daily digest -> keyword aggregate -> daily term index -> global term stats`
|
||||
|
||||
## 3. 为什么只保留 `keywords`
|
||||
|
||||
当前 LLM 摘要结果里已经有两个候选字段:
|
||||
|
||||
- `keywords`
|
||||
- `topics`
|
||||
|
||||
本设计只使用 `keywords` 进入词元库,不使用 `topics` 作为主来源。
|
||||
|
||||
原因:
|
||||
|
||||
- `keywords` 更具体,适合后续规则配置
|
||||
- 例如 `Java`、`Go`、`Python`、`MCP`、`RAG`、`Kafka`
|
||||
- `topics` 更宽泛,适合摘要展示,不适合作为精确规则命中基础
|
||||
- 例如“后端工程”“AI Agent”“前沿科技”过于宽泛
|
||||
- 只保留一个字段可以显著控制词元库规模
|
||||
- 当前项目的真实需求是“词元可配置”,不是“主题聚类”
|
||||
|
||||
结论:
|
||||
|
||||
- `keywords` 进入词元库
|
||||
- `topics` 继续保留在单篇摘要结果中,但不纳入词元统计主流程
|
||||
|
||||
## 4. 词元库的上游边界
|
||||
|
||||
词元库不直接读取所有候选文章,而只读取“最终进入日报”的内容。
|
||||
|
||||
也就是说,真正的词元来源是:
|
||||
|
||||
- `DailyDigest`
|
||||
- 或等价的“已被日报选中”的 candidate 集合
|
||||
|
||||
不纳入词元库的内容:
|
||||
|
||||
- 被 `drop` 的内容
|
||||
- 仅在中间候选层出现、但未进入日报的内容
|
||||
- 调试产物中的临时摘要结果
|
||||
|
||||
这样做的好处是:
|
||||
|
||||
- 词元库只反映真正进入日级产物的内容
|
||||
- 高频词更接近长期兴趣,而不是临时噪声
|
||||
- 数据量更可控
|
||||
|
||||
## 5. 总体链路
|
||||
|
||||
目标链路调整为:
|
||||
|
||||
`DailyDigest -> keyword normalization -> daily term index -> global term stats -> cleaning skill review -> human confirm -> config update`
|
||||
|
||||
职责拆分如下:
|
||||
|
||||
### 5.1 程序负责
|
||||
|
||||
- 从日报中提取 `keywords`
|
||||
- 归一化词元
|
||||
- 应用别名映射
|
||||
- 应用停用词过滤
|
||||
- 生成每日词频
|
||||
- 更新全局累计统计
|
||||
|
||||
### 5.2 Skill 负责
|
||||
|
||||
- 周期性读取词频结果
|
||||
- 识别重复词、近义词、大小写变体
|
||||
- 识别泛词、噪声词、低价值词
|
||||
- 建议哪些词应合并、停用、加入兴趣词配置
|
||||
|
||||
### 5.3 人工负责
|
||||
|
||||
- 审核 skill 输出的建议
|
||||
- 决定是否更新:
|
||||
- `term_aliases`
|
||||
- `term_stopwords`
|
||||
- `filter_context.personal.json`
|
||||
|
||||
## 6. 数据文件设计
|
||||
|
||||
建议新增以下文件:
|
||||
|
||||
- `data/term_index/daily/YYYY-MM-DD.json`
|
||||
- 某一天日报的词元聚合结果
|
||||
- `data/term_index/term_stats.json`
|
||||
- 全局累计词元统计
|
||||
- `configs/term_aliases.json`
|
||||
- 词元别名归一配置
|
||||
- `configs/term_stopwords.json`
|
||||
- 词元停用词配置
|
||||
- `configs/term_cleanup_policy.json`
|
||||
- 清洗阈值与治理策略配置
|
||||
- `configs/term_watchlist.json`
|
||||
- 当前处于观察状态的词元列表
|
||||
- `configs/term_change_log.json`
|
||||
- 已确认生效的词元治理变更记录
|
||||
|
||||
说明:
|
||||
|
||||
- 不新增逐篇 `term_events.jsonl`
|
||||
- 不新增文章级明细文件
|
||||
- 默认只保留“日报聚合结果 + 全局统计结果”
|
||||
|
||||
## 7. 每日词元文件结构
|
||||
|
||||
文件路径示例:
|
||||
|
||||
- `data/term_index/daily/2026-03-26.json`
|
||||
|
||||
建议结构:
|
||||
|
||||
```json
|
||||
{
|
||||
"date": "2026-03-26",
|
||||
"source": "daily_digest",
|
||||
"digest_id": "digest-2026-03-26",
|
||||
"generated_at": "2026-03-26T21:30:00+08:00",
|
||||
"candidate_count": 8,
|
||||
"terms": [
|
||||
{
|
||||
"term": "AI Agent",
|
||||
"normalized_term": "AI Agent",
|
||||
"count": 4
|
||||
},
|
||||
{
|
||||
"term": "MCP",
|
||||
"normalized_term": "MCP",
|
||||
"count": 3
|
||||
},
|
||||
{
|
||||
"term": "RAG",
|
||||
"normalized_term": "RAG",
|
||||
"count": 2
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
字段说明:
|
||||
|
||||
- `date`
|
||||
- 日报日期
|
||||
- `source`
|
||||
- 固定标记为 `daily_digest`
|
||||
- `digest_id`
|
||||
- 日报对象唯一标识
|
||||
- `generated_at`
|
||||
- 该词元文件生成时间
|
||||
- `candidate_count`
|
||||
- 当天日报包含的条目数
|
||||
- `terms[]`
|
||||
- 当天词元聚合结果
|
||||
|
||||
其中单条 `terms[]` 只保留:
|
||||
|
||||
- `term`
|
||||
- `normalized_term`
|
||||
- `count`
|
||||
|
||||
不保留:
|
||||
|
||||
- 逐篇文章来源列表
|
||||
- 逐条命中明细
|
||||
- 本地文件路径
|
||||
|
||||
## 8. 全局统计文件结构
|
||||
|
||||
文件路径:
|
||||
|
||||
- `data/term_index/term_stats.json`
|
||||
|
||||
建议结构:
|
||||
|
||||
```json
|
||||
{
|
||||
"schema_version": "v1",
|
||||
"generated_at": "2026-03-26T21:30:00+08:00",
|
||||
"terms": [
|
||||
{
|
||||
"term": "AI Agent",
|
||||
"total_count": 18,
|
||||
"days_seen": 6,
|
||||
"first_seen": "2026-03-20",
|
||||
"last_seen": "2026-03-26"
|
||||
},
|
||||
{
|
||||
"term": "MCP",
|
||||
"total_count": 12,
|
||||
"days_seen": 5,
|
||||
"first_seen": "2026-03-21",
|
||||
"last_seen": "2026-03-26"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
字段说明:
|
||||
|
||||
- `term`
|
||||
- 最终归一后的词元
|
||||
- `total_count`
|
||||
- 累计出现次数
|
||||
- `days_seen`
|
||||
- 出现过的天数
|
||||
- `first_seen`
|
||||
- 首次出现日期
|
||||
- `last_seen`
|
||||
- 最近出现日期
|
||||
|
||||
当前阶段不额外记录:
|
||||
|
||||
- 各 category 分桶统计
|
||||
- keep/review/drop 分桶统计
|
||||
- 文章级来源列表
|
||||
|
||||
原因是:日报级词元库的第一目标是轻量稳定,不是分析平台。
|
||||
|
||||
## 9. 标准化与归一规则
|
||||
|
||||
程序在写入日报词元前,应先做标准化。
|
||||
|
||||
### 9.1 基础标准化
|
||||
|
||||
- 去除首尾空白
|
||||
- 保留中英文大小写风格中的稳定写法
|
||||
- 去重
|
||||
- 过滤空字符串
|
||||
|
||||
### 9.2 别名映射
|
||||
|
||||
通过 `configs/term_aliases.json` 做归一。
|
||||
|
||||
示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"Agent": "AI Agent",
|
||||
"智能体": "AI Agent",
|
||||
"Postgres": "PostgreSQL",
|
||||
"Model Context Protocol": "MCP"
|
||||
}
|
||||
```
|
||||
|
||||
### 9.3 停用词过滤
|
||||
|
||||
通过 `configs/term_stopwords.json` 过滤过泛词和噪声词。
|
||||
|
||||
示例:
|
||||
|
||||
```json
|
||||
[
|
||||
"技术",
|
||||
"系统",
|
||||
"方案",
|
||||
"实践",
|
||||
"文章"
|
||||
]
|
||||
```
|
||||
|
||||
## 10. 为什么不让 LLM 直接维护词元库
|
||||
|
||||
LLM 可以帮助做清洗建议,但不适合直接维护主词元库。
|
||||
|
||||
原因:
|
||||
|
||||
- 主词元库更新应该稳定、低成本、可复现
|
||||
- 词频统计属于纯程序逻辑,没必要消耗模型调用
|
||||
- 如果让 LLM 直接写词元库,会引入不稳定和难审计问题
|
||||
|
||||
因此主流程固定为:
|
||||
|
||||
- LLM 只负责在摘要结果里输出 `keywords`
|
||||
- 程序负责归一、聚合、统计
|
||||
|
||||
## 11. 词元清洗 Skill 设计
|
||||
|
||||
新增一个周期性清洗 skill,定位是“治理器”,不是“实时生产者”。
|
||||
|
||||
### 11.1 Skill 输入
|
||||
|
||||
建议输入:
|
||||
|
||||
- `data/term_index/term_stats.json`
|
||||
- 最近 N 天的 `data/term_index/daily/*.json`
|
||||
- `configs/term_aliases.json`
|
||||
- `configs/term_stopwords.json`
|
||||
- `configs/filter_context.personal.json`
|
||||
|
||||
### 11.2 Skill 输出
|
||||
|
||||
skill 不直接修改配置文件,而是生成建议文件,例如:
|
||||
|
||||
- `outputs/term_index/review/term-cleanup-suggestions-YYYY-MM-DD.md`
|
||||
- `outputs/term_index/review/term-cleanup-suggestions-YYYY-MM-DD.json`
|
||||
|
||||
低复杂治理层建议补充三类输入:
|
||||
|
||||
- `term_cleanup_policy`
|
||||
- 用来定义 watch 和 interest 的最小证据阈值
|
||||
- `term_watchlist`
|
||||
- 用来记录“先观察、暂不升级”的词元
|
||||
- `term_change_log`
|
||||
- 用来记录已经确认落地的配置变更,避免后续遗忘上下文
|
||||
|
||||
建议项包括:
|
||||
|
||||
- 建议合并的别名词
|
||||
- 建议新增的停用词
|
||||
- 建议加入 `interest_keywords` 的候选词
|
||||
- 建议降权观察的热点词
|
||||
|
||||
### 11.3 Skill 允许做什么
|
||||
|
||||
- 发现重复词
|
||||
- 发现大小写变体
|
||||
- 发现中英文混用的近义词
|
||||
- 发现持续高频但尚未进入兴趣配置的词
|
||||
- 发现明显过泛的词
|
||||
|
||||
### 11.4 Skill 不允许做什么
|
||||
|
||||
- 直接改 `filter_rules.json`
|
||||
- 直接改 `filter_context.personal.json`
|
||||
- 直接覆盖 `term_stats.json`
|
||||
- 在无人工确认的情况下自动生效
|
||||
|
||||
## 12. 建议的清洗建议文件结构
|
||||
|
||||
建议 JSON 文件结构如下:
|
||||
|
||||
```json
|
||||
{
|
||||
"date": "2026-03-26",
|
||||
"based_on_days": 7,
|
||||
"alias_suggestions": [
|
||||
{
|
||||
"from": "Agent",
|
||||
"to": "AI Agent",
|
||||
"reason": "和现有高频词语义一致,建议归并。"
|
||||
}
|
||||
],
|
||||
"stopword_suggestions": [
|
||||
{
|
||||
"term": "系统",
|
||||
"reason": "出现频繁但语义过泛,难以作为规则命中词。"
|
||||
}
|
||||
],
|
||||
"interest_keyword_suggestions": [
|
||||
{
|
||||
"term": "MCP",
|
||||
"reason": "最近多日持续高频,且符合当前 AI Agent 学习方向。"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## 13. 周期与触发方式
|
||||
|
||||
建议触发周期:
|
||||
|
||||
- 词元统计更新:每天一次,跟随日报生成
|
||||
- skill 清洗:每周一次,或人工手动触发
|
||||
|
||||
推荐流程:
|
||||
|
||||
1. 当天日报生成完成
|
||||
2. 程序更新 `daily/YYYY-MM-DD.json`
|
||||
3. 程序更新 `term_stats.json`
|
||||
4. 每周或人工触发一次词元清洗 skill
|
||||
5. skill 输出建议
|
||||
6. 人工确认后再更新配置文件
|
||||
|
||||
## 14. 与规则引擎的关系
|
||||
|
||||
这套词元库设计不是规则引擎的替代品,而是规则配置的辅助层。
|
||||
|
||||
关系如下:
|
||||
|
||||
- `keywords`
|
||||
- 是词元库来源
|
||||
- `term_stats`
|
||||
- 是观察与调优依据
|
||||
- `filter_context.personal.json`
|
||||
- 是真正给规则引擎使用的兴趣词配置
|
||||
- `filter_rules.json`
|
||||
- 是最终裁决逻辑
|
||||
|
||||
也就是说:
|
||||
|
||||
`日报词元统计 -> 清洗建议 -> 人工确认 -> 更新 interest_keywords -> 规则引擎命中`
|
||||
|
||||
而不是:
|
||||
|
||||
`日报词元统计 -> 自动改规则`
|
||||
|
||||
## 15. 分阶段落地建议
|
||||
|
||||
### Phase 1
|
||||
|
||||
先做最小可用版本:
|
||||
|
||||
- 只读取日报中的 `keywords`
|
||||
- 生成每日词元文件
|
||||
- 生成全局累计词频文件
|
||||
- 支持 `term_aliases` 和 `term_stopwords`
|
||||
|
||||
### Phase 2
|
||||
|
||||
再补治理层:
|
||||
|
||||
- 增加词元清洗 skill
|
||||
- 输出建议文件
|
||||
- 人工确认后更新配置
|
||||
|
||||
### Phase 3
|
||||
|
||||
最后再考虑增强:
|
||||
|
||||
- 增加趋势分析
|
||||
- 增加最近 7 天热点词视图
|
||||
- 增加“建议加入兴趣词”的自动排序
|
||||
|
||||
## 16. 一句话结论
|
||||
|
||||
这套设计选择“只统计日报中的 `keywords`,由程序维护轻量词元库,再由独立 skill 周期性做清洗建议”,目的是在控制数据规模的前提下,为规则配置和长期兴趣演化提供稳定、可审计、可扩展的基础设施。
|
||||
Reference in New Issue
Block a user