274 lines
9.1 KiB
Markdown
274 lines
9.1 KiB
Markdown
|
|
# Ingest 协议
|
|||
|
|
|
|||
|
|
> Ingest 不是追加文件,是编译——读旧、比新、改旧。
|
|||
|
|
|
|||
|
|
## 流程
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
1. 读取源文件
|
|||
|
|
├─ 提取关键信息:实体、概念、数据、结论、时间
|
|||
|
|
└─ 生成 source 摘要页(sources/{date}-{slug}.md)
|
|||
|
|
|
|||
|
|
2. 搜索已有 wiki
|
|||
|
|
├─ 读 index.md 获取全部页面列表
|
|||
|
|
├─ 识别与新信息相关的已有页面
|
|||
|
|
└─ 读取这些页面的当前内容
|
|||
|
|
|
|||
|
|
3. 逐页比较新旧(核心步骤)——三种结果,必须选一个
|
|||
|
|
│
|
|||
|
|
├─ A) 强化:新信息与已有结论一致,提供额外佐证
|
|||
|
|
│ → 在页面 sources 列表中加入新 source slug
|
|||
|
|
│ → 如果 confidence 是 medium/low → 升为 high
|
|||
|
|
│ → 正文不改或仅补充细节
|
|||
|
|
│ → log: "reinforced: {page}"
|
|||
|
|
│
|
|||
|
|
├─ B) 更新:新信息明确推翻或修正已有结论(有更新数据/更权威来源)
|
|||
|
|
│ → store.upsert_data() 写入新值(旧值自动进 history 表)
|
|||
|
|
│ → 改写 Markdown 正文为新结论
|
|||
|
|
│ → 更新 frontmatter 的 updated 日期和 sources 列表
|
|||
|
|
│ → log: "updated: {page}, reason: {简述}"
|
|||
|
|
│
|
|||
|
|
└─ C) 冲突:新旧信息矛盾,但无法判断谁对(数据口径不同/来源同级)
|
|||
|
|
→ 不改写,在页面中并列两种说法,标注各自来源
|
|||
|
|
→ confidence → contested
|
|||
|
|
→ log: "conflict: {page}, {说法A} vs {说法B}"
|
|||
|
|
|
|||
|
|
判定规则:新信息有更新日期或更权威来源 → B(更新);
|
|||
|
|
两者同级、无法分优劣 → C(冲突);其余 → A(强化)。
|
|||
|
|
|
|||
|
|
4. 结构化数据写入 data.db
|
|||
|
|
├─ 数值数据 → store.upsert_data()(自动处理 history)
|
|||
|
|
├─ 关系 → store.add_relation()
|
|||
|
|
└─ 页面元数据 → store.upsert_page()
|
|||
|
|
|
|||
|
|
5. 创建/更新 Markdown 页面
|
|||
|
|
├─ 新实体/概念 → 按 wiki-format.md 创建页面(frontmatter 只存元数据)
|
|||
|
|
├─ 正文写叙事分析,引述数据结论但不重复具体数值
|
|||
|
|
├─ 添加 wikilinks 到已有相关页面
|
|||
|
|
└─ 在已有相关页面中也加上指向新页面的 wikilink
|
|||
|
|
|
|||
|
|
6. 更新 index.md
|
|||
|
|
├─ 新页面加入对应分组
|
|||
|
|
├─ 更新页面计数和 Last updated 日期
|
|||
|
|
└─ 不修改已有条目的描述(除非页面标题变了)
|
|||
|
|
|
|||
|
|
7. 追加 log.md
|
|||
|
|
├─ 记录本次 ingest 的所有操作
|
|||
|
|
└─ 格式见 wiki-format.md
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 关键原则
|
|||
|
|
|
|||
|
|
**1. 改旧优先于建新**
|
|||
|
|
|
|||
|
|
搜索 wiki 后发现已有 `entities/alpha-corp.md`,新研报也提到该机构 → 更新已有页面,不要新建 `entities/alpha-corp-2.md`。
|
|||
|
|
|
|||
|
|
**2. 不删除,只归档**
|
|||
|
|
|
|||
|
|
过时的结论不删除,移入 "## 历史" 段落。这样 wiki 保留了知识的演化痕迹。
|
|||
|
|
|
|||
|
|
```markdown
|
|||
|
|
## 管理规模
|
|||
|
|
|
|||
|
|
截至 2025 年底,某机构管理规模达 XXX 亿元。(来源:[[2026-04-06-policy-doc]])
|
|||
|
|
|
|||
|
|
## 历史
|
|||
|
|
|
|||
|
|
- ~~管理规模约 XXX 亿元~~(来源:[[2024-12-annual-report]],已被更新数据替代)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**3. 冲突不调和**
|
|||
|
|
|
|||
|
|
两个来源说法矛盾时,不要编一个折中解释。并列呈现,标注来源,让用户或后续证据判断。
|
|||
|
|
|
|||
|
|
```markdown
|
|||
|
|
## 市场份额
|
|||
|
|
|
|||
|
|
> ⚠️ contested — 两个来源数据不一致
|
|||
|
|
|
|||
|
|
- 据 [[2026-04-06-policy-doc]]:某机构市场份额约 15%
|
|||
|
|
- 据 [[2025-annual-industry-report]]:某机构市场份额约 12%
|
|||
|
|
|
|||
|
|
差异可能来自统计口径不同(含/不含职业年金)。
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**4. 一次 ingest 触及多个页面是正常的**
|
|||
|
|
|
|||
|
|
一篇研报可能涉及 5-10 个实体和概念。一次 ingest 更新 8 个页面是正常的。在 log 中完整记录。
|
|||
|
|
|
|||
|
|
**5. Source 页面是不可变的**
|
|||
|
|
|
|||
|
|
`sources/` 目录下的摘要页在创建后不再修改(除非发现摘要有错误)。它是原始材料的忠实记录。其他页面通过 `sources` frontmatter 字段引用它。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Worked Example: 完整 Ingest 流程
|
|||
|
|
|
|||
|
|
> 以企业年金领域为例。实际执行时替换为用户的目标领域。
|
|||
|
|
|
|||
|
|
**场景**:用户 ingest 一篇政策文件到某领域 wiki。wiki 中已有相关实体页面。
|
|||
|
|
|
|||
|
|
### Step 1 — 读取源文件,生成 source 摘要页
|
|||
|
|
|
|||
|
|
新建 `sources/2026-04-06-hrss-policy.md`:
|
|||
|
|
|
|||
|
|
```yaml
|
|||
|
|
---
|
|||
|
|
title: 人社部2025年度企业年金基金统计报告
|
|||
|
|
type: source
|
|||
|
|
created: 2026-04-06
|
|||
|
|
updated: 2026-04-06
|
|||
|
|
sources: []
|
|||
|
|
confidence: high
|
|||
|
|
source_type: 一手
|
|||
|
|
source_origin: 人社部官网
|
|||
|
|
source_date: 2025-12-31
|
|||
|
|
---
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
正文写原文关键信息的忠实摘要。
|
|||
|
|
|
|||
|
|
### Step 2 — 搜索已有 wiki
|
|||
|
|
|
|||
|
|
读 index.md,发现 `entities/alpha-corp.md` 与新文件相关。查询 data.db 中该页面的当前数据:
|
|||
|
|
|
|||
|
|
```python
|
|||
|
|
store.query_data(page_slug="alpha-corp")
|
|||
|
|
# → [{ field: "管理规模", value: 800, unit: "亿元", period: "2024-12", source_slug: "2024-12-annual-report" }]
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Step 3 — 比较新旧,判定结果
|
|||
|
|
|
|||
|
|
新文件说:"截至 2025 年底,某机构管理规模达 1200 亿元。"
|
|||
|
|
|
|||
|
|
判定:新数据时点更新(2025 vs 2024)→ 选 **B) 更新**。
|
|||
|
|
|
|||
|
|
Agent 执行两步操作:
|
|||
|
|
|
|||
|
|
**a) 结构化数据写入 data.db**(自动记录 history):
|
|||
|
|
|
|||
|
|
```python
|
|||
|
|
old = store.upsert_data("alpha-corp", "管理规模", 1200, "亿元", "2025-12", "2026-04-06-policy-doc")
|
|||
|
|
# old = { value: 800, unit: "亿元", source_slug: "2024-12-annual-report" }
|
|||
|
|
# → history 表自动写入旧值
|
|||
|
|
store.add_relation("alpha-corp", "受托人市场格局", "part_of")
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**b) 更新 Markdown 页面**(frontmatter 只留元数据):
|
|||
|
|
|
|||
|
|
```yaml
|
|||
|
|
---
|
|||
|
|
title: Alpha Corp 养老金业务
|
|||
|
|
type: entity
|
|||
|
|
created: 2026-04-01
|
|||
|
|
updated: 2026-04-06
|
|||
|
|
sources: [2024-12-annual-report, 2026-04-06-policy-doc]
|
|||
|
|
confidence: high
|
|||
|
|
relations:
|
|||
|
|
- target: 受托人市场格局
|
|||
|
|
type: part_of
|
|||
|
|
---
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
正文更新分析内容(引述数据结论,不写具体数值——数值在 data.db 中)。
|
|||
|
|
|
|||
|
|
### Step 4-7 — 新建页面、写 DB、更新 index、追加 log
|
|||
|
|
|
|||
|
|
新文件还提到"可携带企业年金"概念(wiki 中不存在)→ 新建 `concepts/portable-annuity.md`:
|
|||
|
|
|
|||
|
|
```yaml
|
|||
|
|
---
|
|||
|
|
title: 可携带企业年金
|
|||
|
|
type: concept
|
|||
|
|
created: 2026-04-06
|
|||
|
|
updated: 2026-04-06
|
|||
|
|
sources: [2026-04-06-hrss-policy]
|
|||
|
|
confidence: medium # 仅单一来源首次提及
|
|||
|
|
relations:
|
|||
|
|
- target: 企业年金制度
|
|||
|
|
type: part_of
|
|||
|
|
---
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
log.md 追加:
|
|||
|
|
```
|
|||
|
|
## 2026-04-06 14:30 — ingest
|
|||
|
|
- Source: 2026-04-06-policy-doc
|
|||
|
|
- Updated: entities/alpha-corp (data.管理规模 800→1200亿)
|
|||
|
|
- Created: concepts/portable-annuity
|
|||
|
|
- Conflicts: none
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## From-Lint 流程(deep-dive 管道的 ingest 阶段)
|
|||
|
|
|
|||
|
|
当 ingest 由 deep-dive 管道触发时,输入不是用户提供的源文件,而是 lint Coverage 输出的缺口报告(Gap Report)。
|
|||
|
|
|
|||
|
|
### 与标准 ingest 的区别
|
|||
|
|
|
|||
|
|
| 方面 | 标准 ingest | from-lint ingest |
|
|||
|
|
|------|------------|------------------|
|
|||
|
|
| 输入 | 用户提供的源文件 | Gap Report 中的缺口条目 |
|
|||
|
|
| 来源获取 | 用户已提供 | Agent 通过搜索工具获取 |
|
|||
|
|
| 批量操作 | 通常 1 个源文件 | 可能 N 个缺口,逐个处理 |
|
|||
|
|
| 用户确认 | 不需要(用户已主动提供) | 需要(搜索前确认范围,搜索后确认质量) |
|
|||
|
|
|
|||
|
|
### 流程
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
输入:Gap Report(来自 lint Coverage)
|
|||
|
|
|
|||
|
|
For each confirmed gap:
|
|||
|
|
|
|||
|
|
1. 制定搜索计划
|
|||
|
|
├─ page_missing → 搜索该实体/概念的基本信息
|
|||
|
|
├─ concept_missing → 搜索该术语的定义和解释
|
|||
|
|
├─ data_missing → 搜索该指标的最新数据
|
|||
|
|
├─ single_source → 搜索额外来源以交叉验证
|
|||
|
|
└─ outdated → 搜索该指标/实体的最新信息
|
|||
|
|
|
|||
|
|
2. 执行搜索(需要搜索工具——主动模式)
|
|||
|
|
├─ 使用 WebSearch / 搜索类 MCP 获取候选来源
|
|||
|
|
├─ 搜索工具优先级:领域专业工具 > 通用搜索
|
|||
|
|
├─ 按 source-validation.md 分级筛选
|
|||
|
|
└─ 排除黑名单渠道,取 top 1-3 个可信来源
|
|||
|
|
|
|||
|
|
3. 展示搜索结果,请用户确认
|
|||
|
|
├─ 展示每个来源的标题、URL、可信度分级
|
|||
|
|
├─ 用户选择:接受 / 跳过 / 替换
|
|||
|
|
└─ 搜索结果质量不够 → 标注"未能补全",跳过
|
|||
|
|
|
|||
|
|
4. 对确认的每个来源,执行标准 ingest 流程
|
|||
|
|
├─ Step 1-7 与普通 ingest 完全一致
|
|||
|
|
└─ source 摘要页额外记录 deep-dive 元数据(见 source-validation.md)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 防扩散机制
|
|||
|
|
|
|||
|
|
- 每个 gap 最多搜索 3 次(换关键词)。3 次搜不到可信来源 → 标注"未能补全"
|
|||
|
|
- 单次 deep-dive 最多处理 10 个 gap(可通过 `--max-gaps` 调整)
|
|||
|
|
- 搜索到的来源如果引入了 wiki 中完全不存在的新实体,**不自动创建页面**——只填补已知缺口,不主动扩展 wiki 范围
|
|||
|
|
- 所有搜索来源的 confidence 上限为 medium(除非来源是一手/权威二手)
|
|||
|
|
|
|||
|
|
### 补全报告
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
## Deep-Dive 补全报告:{topic}
|
|||
|
|
执行时间:{date}
|
|||
|
|
|
|||
|
|
### 已补全:{N} / {total} 个缺口
|
|||
|
|
| # | Gap | Action | Source | Confidence |
|
|||
|
|
|---|-----|--------|--------|------------|
|
|||
|
|
| 1 | page_missing: portable-annuity | 新建页面 | [二手·权威] 财新报道 | medium |
|
|||
|
|
| 2 | single_source: alpha-corp | 增加 1 个来源 | [二手] 行业研报 | medium |
|
|||
|
|
|
|||
|
|
### 未能补全:{M} 个缺口
|
|||
|
|
| # | Gap | Reason |
|
|||
|
|
|---|-----|--------|
|
|||
|
|
| 3 | data_missing: beta-corp/市场份额 | 搜索 3 次未找到可信来源 |
|
|||
|
|
|
|||
|
|
### 建议
|
|||
|
|
- beta-corp 市场份额数据建议用户手动提供行业报告
|
|||
|
|
```
|