kc-beta 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/kc-beta.js +16 -0
- package/package.json +32 -0
- package/src/agent/confidence-scorer.js +120 -0
- package/src/agent/context.js +124 -0
- package/src/agent/corner-case-registry.js +119 -0
- package/src/agent/engine.js +224 -0
- package/src/agent/events.js +27 -0
- package/src/agent/history.js +101 -0
- package/src/agent/llm-client.js +131 -0
- package/src/agent/pipelines/base.js +14 -0
- package/src/agent/pipelines/distillation.js +113 -0
- package/src/agent/pipelines/extraction.js +92 -0
- package/src/agent/pipelines/index.js +23 -0
- package/src/agent/pipelines/initializer.js +163 -0
- package/src/agent/pipelines/production-qc.js +99 -0
- package/src/agent/pipelines/skill-authoring.js +83 -0
- package/src/agent/pipelines/skill-testing.js +111 -0
- package/src/agent/tools/agent-tool.js +100 -0
- package/src/agent/tools/base.js +35 -0
- package/src/agent/tools/dashboard-render.js +146 -0
- package/src/agent/tools/document-parse.js +184 -0
- package/src/agent/tools/document-search.js +111 -0
- package/src/agent/tools/evolution-cycle.js +150 -0
- package/src/agent/tools/qc-sample.js +94 -0
- package/src/agent/tools/registry.js +55 -0
- package/src/agent/tools/rule-catalog.js +113 -0
- package/src/agent/tools/sandbox-exec.js +106 -0
- package/src/agent/tools/tier-downgrade.js +114 -0
- package/src/agent/tools/worker-llm-call.js +109 -0
- package/src/agent/tools/workflow-run.js +138 -0
- package/src/agent/tools/workspace-file.js +122 -0
- package/src/agent/version-manager.js +130 -0
- package/src/agent/workspace.js +82 -0
- package/src/cli/components.js +164 -0
- package/src/cli/index.js +329 -0
- package/src/cli/init.js +80 -0
- package/src/cli/onboard.js +182 -0
- package/src/cli/terminal.js +143 -0
- package/src/config.js +93 -0
- package/template/.env.template +31 -0
- package/template/CLAUDE.md +137 -0
- package/template/Input/.gitkeep +0 -0
- package/template/Output/.gitkeep +0 -0
- package/template/Rules/.gitkeep +0 -0
- package/template/Samples/.gitkeep +0 -0
- package/template/skills/en/meta/compliance-judgment/SKILL.md +114 -0
- package/template/skills/en/meta/compliance-judgment/references/output-format.md +151 -0
- package/template/skills/en/meta/confidence-system/SKILL.md +117 -0
- package/template/skills/en/meta/corner-case-management/SKILL.md +111 -0
- package/template/skills/en/meta/cross-document-verification/SKILL.md +131 -0
- package/template/skills/en/meta/cross-document-verification/references/contradiction-taxonomy.md +73 -0
- package/template/skills/en/meta/data-sensibility/SKILL.md +115 -0
- package/template/skills/en/meta/document-parsing/SKILL.md +108 -0
- package/template/skills/en/meta/document-parsing/references/parser-catalog.md +40 -0
- package/template/skills/en/meta/entity-extraction/SKILL.md +129 -0
- package/template/skills/en/meta/tree-processing/SKILL.md +103 -0
- package/template/skills/en/meta-meta/bootstrap-workspace/SKILL.md +70 -0
- package/template/skills/en/meta-meta/dashboard-reporting/SKILL.md +106 -0
- package/template/skills/en/meta-meta/dashboard-reporting/scripts/generate_dashboard.py +178 -0
- package/template/skills/en/meta-meta/evolution-loop/SKILL.md +210 -0
- package/template/skills/en/meta-meta/evolution-loop/references/convergence-guide.md +62 -0
- package/template/skills/en/meta-meta/quality-control/SKILL.md +138 -0
- package/template/skills/en/meta-meta/quality-control/references/qa-layers.md +92 -0
- package/template/skills/en/meta-meta/quality-control/references/sampling-strategies.md +76 -0
- package/template/skills/en/meta-meta/rule-extraction/SKILL.md +100 -0
- package/template/skills/en/meta-meta/rule-extraction/references/chunking-strategies.md +80 -0
- package/template/skills/en/meta-meta/rule-graph/SKILL.md +118 -0
- package/template/skills/en/meta-meta/skill-authoring/SKILL.md +108 -0
- package/template/skills/en/meta-meta/skill-authoring/references/skill-format-spec.md +78 -0
- package/template/skills/en/meta-meta/skill-to-workflow/SKILL.md +150 -0
- package/template/skills/en/meta-meta/skill-to-workflow/references/worker-llm-catalog.md +50 -0
- package/template/skills/en/meta-meta/task-decomposition/SKILL.md +129 -0
- package/template/skills/en/meta-meta/task-decomposition/references/decision-matrix.md +81 -0
- package/template/skills/en/meta-meta/version-control/SKILL.md +152 -0
- package/template/skills/en/meta-meta/version-control/references/trace-id-spec.md +79 -0
- package/template/skills/en/skill-creator/LICENSE.txt +202 -0
- package/template/skills/en/skill-creator/SKILL.md +479 -0
- package/template/skills/en/skill-creator/agents/analyzer.md +274 -0
- package/template/skills/en/skill-creator/agents/comparator.md +202 -0
- package/template/skills/en/skill-creator/agents/grader.md +223 -0
- package/template/skills/en/skill-creator/assets/eval_review.html +146 -0
- package/template/skills/en/skill-creator/eval-viewer/generate_review.py +471 -0
- package/template/skills/en/skill-creator/eval-viewer/viewer.html +1325 -0
- package/template/skills/en/skill-creator/references/schemas.md +430 -0
- package/template/skills/en/skill-creator/scripts/__init__.py +0 -0
- package/template/skills/en/skill-creator/scripts/aggregate_benchmark.py +401 -0
- package/template/skills/en/skill-creator/scripts/generate_report.py +326 -0
- package/template/skills/en/skill-creator/scripts/improve_description.py +248 -0
- package/template/skills/en/skill-creator/scripts/package_skill.py +136 -0
- package/template/skills/en/skill-creator/scripts/quick_validate.py +103 -0
- package/template/skills/en/skill-creator/scripts/run_eval.py +310 -0
- package/template/skills/en/skill-creator/scripts/run_loop.py +332 -0
- package/template/skills/en/skill-creator/scripts/utils.py +47 -0
- package/template/skills/zh/meta/compliance-judgment/SKILL.md +303 -0
- package/template/skills/zh/meta/compliance-judgment/references/output-format.md +151 -0
- package/template/skills/zh/meta/confidence-system/SKILL.md +228 -0
- package/template/skills/zh/meta/corner-case-management/SKILL.md +235 -0
- package/template/skills/zh/meta/cross-document-verification/SKILL.md +241 -0
- package/template/skills/zh/meta/cross-document-verification/references/contradiction-taxonomy.md +73 -0
- package/template/skills/zh/meta/data-sensibility/SKILL.md +235 -0
- package/template/skills/zh/meta/document-parsing/SKILL.md +168 -0
- package/template/skills/zh/meta/document-parsing/references/parser-catalog.md +40 -0
- package/template/skills/zh/meta/entity-extraction/SKILL.md +276 -0
- package/template/skills/zh/meta/tree-processing/SKILL.md +233 -0
- package/template/skills/zh/meta-meta/bootstrap-workspace/SKILL.md +147 -0
- package/template/skills/zh/meta-meta/dashboard-reporting/SKILL.md +281 -0
- package/template/skills/zh/meta-meta/dashboard-reporting/scripts/generate_dashboard.py +178 -0
- package/template/skills/zh/meta-meta/evolution-loop/SKILL.md +302 -0
- package/template/skills/zh/meta-meta/evolution-loop/references/convergence-guide.md +62 -0
- package/template/skills/zh/meta-meta/quality-control/SKILL.md +269 -0
- package/template/skills/zh/meta-meta/quality-control/references/qa-layers.md +92 -0
- package/template/skills/zh/meta-meta/quality-control/references/sampling-strategies.md +76 -0
- package/template/skills/zh/meta-meta/rule-extraction/SKILL.md +208 -0
- package/template/skills/zh/meta-meta/rule-extraction/references/chunking-strategies.md +80 -0
- package/template/skills/zh/meta-meta/rule-graph/SKILL.md +203 -0
- package/template/skills/zh/meta-meta/skill-authoring/SKILL.md +235 -0
- package/template/skills/zh/meta-meta/skill-authoring/references/skill-format-spec.md +78 -0
- package/template/skills/zh/meta-meta/skill-to-workflow/SKILL.md +275 -0
- package/template/skills/zh/meta-meta/skill-to-workflow/references/worker-llm-catalog.md +50 -0
- package/template/skills/zh/meta-meta/task-decomposition/SKILL.md +224 -0
- package/template/skills/zh/meta-meta/task-decomposition/references/decision-matrix.md +81 -0
- package/template/skills/zh/meta-meta/version-control/SKILL.md +284 -0
- package/template/skills/zh/meta-meta/version-control/references/trace-id-spec.md +79 -0
- package/template/skills/zh/skill-creator/LICENSE.txt +202 -0
- package/template/skills/zh/skill-creator/SKILL.md +479 -0
- package/template/skills/zh/skill-creator/agents/analyzer.md +274 -0
- package/template/skills/zh/skill-creator/agents/comparator.md +202 -0
- package/template/skills/zh/skill-creator/agents/grader.md +223 -0
- package/template/skills/zh/skill-creator/assets/eval_review.html +146 -0
- package/template/skills/zh/skill-creator/eval-viewer/generate_review.py +471 -0
- package/template/skills/zh/skill-creator/eval-viewer/viewer.html +1325 -0
- package/template/skills/zh/skill-creator/references/schemas.md +430 -0
- package/template/skills/zh/skill-creator/scripts/__init__.py +0 -0
- package/template/skills/zh/skill-creator/scripts/aggregate_benchmark.py +401 -0
- package/template/skills/zh/skill-creator/scripts/generate_report.py +326 -0
- package/template/skills/zh/skill-creator/scripts/improve_description.py +248 -0
- package/template/skills/zh/skill-creator/scripts/package_skill.py +136 -0
- package/template/skills/zh/skill-creator/scripts/quick_validate.py +103 -0
- package/template/skills/zh/skill-creator/scripts/run_eval.py +310 -0
- package/template/skills/zh/skill-creator/scripts/run_loop.py +332 -0
- package/template/skills/zh/skill-creator/scripts/utils.py +47 -0
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: document-parsing
|
|
3
|
+
description: Parse source documents into machine-readable text with maximum fidelity. Use when processing any document in Samples/ or Input/ for the first time, when parsed text quality is poor, or when tables and charts need special handling. Covers multi-level parser selection from simple text extraction to OCR and vision models. Also use when a verification rule fails due to parsing issues (garbled text, missing tables, mangled layouts) and the parser needs to be upgraded for that document type.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# 文档解析
|
|
7
|
+
|
|
8
|
+
解析是核查工作的地基。文本提取有误,后续所有判定都将失去意义。但解析同时也是成本中心——简单文本提取能解决的问题,绝不要动用视觉模型。
|
|
9
|
+
|
|
10
|
+
## 最小可用解析器原则
|
|
11
|
+
|
|
12
|
+
从最简单的解析器开始,仅在质量不达标时逐级升级。这不是为了省钱,而是因为简单解析器的失败模式更少、输出更稳定。复杂工具引入的变量越多,排查问题越困难。
|
|
13
|
+
|
|
14
|
+
把解析器想象成一架梯子:你需要够到的是那个高度,而不是梯子的最高一级。
|
|
15
|
+
|
|
16
|
+
### Level 1:直接文本提取
|
|
17
|
+
|
|
18
|
+
- **工具**:pymupdf(PyMuPDF)或同类 PDF 文本提取库。
|
|
19
|
+
- **适用场景**:内嵌文字层的数字原生 PDF。覆盖绝大多数现代金融文档——年报、招股说明书、贷款合同、监管报告。
|
|
20
|
+
- **输出**:带基础段落结构的原始文本。
|
|
21
|
+
- **局限**:表格可能被拆散为凌乱文本;图表和扫描页无法处理。
|
|
22
|
+
- **成本**:零 API 调用,毫秒级速度。
|
|
23
|
+
|
|
24
|
+
这是默认起点。只有当输出质量不合格时才考虑升级。
|
|
25
|
+
|
|
26
|
+
### Level 2:版面感知提取
|
|
27
|
+
|
|
28
|
+
- **工具**:pdfplumber 或同类版面感知解析器。
|
|
29
|
+
- **适用场景**:Level 1 的表格输出混乱、多栏排版文档、表单类文档(贷款申请表、尽调清单等)。
|
|
30
|
+
- **输出**:保留空间布局的文本,支持单元格级别的表格提取。
|
|
31
|
+
- **局限**:仍基于文本层,无法处理扫描件。
|
|
32
|
+
- **典型触发条件**:当 Level 1 提取的财务报表数字与列头错位、合并单元格导致数据串行时,升级到此级别。
|
|
33
|
+
|
|
34
|
+
### Level 3:OCR 识别
|
|
35
|
+
|
|
36
|
+
- **工具**:`.env` 中 `OCR_MODEL_TIER` 配置的视觉识别模型(PaddleOCR、GLM-4V 等)。
|
|
37
|
+
- **适用场景**:扫描件 PDF、影印版监管文件、历史档案(2010年以前的银行文件很多是扫描件)。
|
|
38
|
+
- **输出**:从图像中识别出的文字。
|
|
39
|
+
- **局限**:速度慢、消耗 API 调用、可能引入识别错误(繁体/简体混淆、表格线干扰等)。
|
|
40
|
+
- **注意事项**:OCR 对中文竖排文本、印章遮盖区域、手写批注的处理能力有限。遇到这些情况要做额外质量检查。
|
|
41
|
+
|
|
42
|
+
### Level 4:视觉模型解读
|
|
43
|
+
|
|
44
|
+
- **工具**:高能力视觉模型(`OCR_MODEL_TIER1`)。
|
|
45
|
+
- **适用场景**:
|
|
46
|
+
- 复杂表格:跨页表格、不规则合并单元格、嵌套表头(银行资本充足率报表常见此类结构)。
|
|
47
|
+
- 图表数据提取:柱状图、折线图、饼图中包含核查所需的关键数值。
|
|
48
|
+
- 混合排版:文字与图像交织的页面。
|
|
49
|
+
- **输出**:对视觉内容的结构化解读(表格转 markdown、图表数据转 JSON)。
|
|
50
|
+
- **局限**:成本高、速度慢。只在视觉内容确实需要语义理解时使用。
|
|
51
|
+
|
|
52
|
+
## 质量检测
|
|
53
|
+
|
|
54
|
+
解析完成后,不要直接进入下一步。先跑一遍质量检查,判断是否需要升级解析器。
|
|
55
|
+
|
|
56
|
+
### 检测指标
|
|
57
|
+
|
|
58
|
+
- **字符数过少**:文档有 200 页但提取文本不到 5000 字——大概率是扫描件,Level 1 只拿到了页眉页脚。
|
|
59
|
+
- **乱码检测**:出现大量连续非常用字符、编码错误符号(□、■、?)、或无意义字符序列。常见于编码不匹配或字体嵌入异常的 PDF。
|
|
60
|
+
- **章节缺失**:目录显示有"第五章 风险管理",但提取文本中找不到对应内容。可能该章节是扫描插页或图片格式。
|
|
61
|
+
- **表格异常**:
|
|
62
|
+
- 数字列缺少对齐,数值与表头无法对应。
|
|
63
|
+
- 单元格内容与相邻单元格混合。
|
|
64
|
+
- 表格线字符(|、+、-)出现在文本中。
|
|
65
|
+
- 关键财务数据缺失(资本充足率、不良贷款率、净利润等数字在文本中找不到)。
|
|
66
|
+
- **页码断裂**:连续页码中有跳跃,说明某些页面可能未被提取。
|
|
67
|
+
|
|
68
|
+
### 质量检查流程
|
|
69
|
+
|
|
70
|
+
```
|
|
71
|
+
解析完成 → 检查字符数 → 检查乱码比例 → 检查章节完整性 → 检查关键表格
|
|
72
|
+
↓ 任一项不合格
|
|
73
|
+
升级到下一级解析器 → 重新解析 → 再次检查
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
在工作流中实现此逻辑时,记录每次升级的原因(哪个指标触发了升级)。这些日志对演进循环有价值。
|
|
77
|
+
|
|
78
|
+
### 解析质量评分
|
|
79
|
+
|
|
80
|
+
将上述检测指标量化为一个综合评分(0.0–1.0),让升级决策从主观判断变为系统化流程。
|
|
81
|
+
|
|
82
|
+
**推荐信号与参考权重:**
|
|
83
|
+
- **字符密度**(~0.3):实际提取字符数 / 按页数估算的预期字符数。远低于预期说明大量内容未被提取。
|
|
84
|
+
- **乱码比例**(~0.2):常用字符占比与异常序列占比的对比。编码问题在此暴露。
|
|
85
|
+
- **章节完整性**(~0.3):目录条目在正文中有对应内容的比例。缺失章节是解析失败的强信号。
|
|
86
|
+
- **表格完整性**(~0.2):关键数值(如总资产、净利润、资本充足率)在提取文本中是否可检索到。
|
|
87
|
+
|
|
88
|
+
**升级阈值(推荐默认值):**
|
|
89
|
+
- ≥ 0.7:接受当前解析器级别,进入下一步。
|
|
90
|
+
- 0.4–0.7:升级一级解析器,重新解析后再评分。
|
|
91
|
+
- < 0.4:跳过中间级别,直接使用 OCR 或视觉模型。
|
|
92
|
+
|
|
93
|
+
**锁定机制:** 一旦评分达标,记录当前解析器级别。仅在下游核查失败且回溯至解析质量时重新评估,避免反复试探。
|
|
94
|
+
|
|
95
|
+
**重要提示:** 以上权重、阈值和评分方式本身都是起点,不是定论。编程智能体应根据实际文档特征自由调整、增删参数。真正重要的是这个框架——度量质量 → 对比阈值 → 做出决策——而非具体公式。公式会随着业务数据的积累不断演化。
|
|
96
|
+
|
|
97
|
+
这套"评分 → 阈值 → 分级处理"的模式与 `skill-to-workflow` 中的模型层级选择逻辑完全同构。如果你已经理解了模型层级的逐级升级机制,这里的解析器升级遵循相同范式。
|
|
98
|
+
|
|
99
|
+
## 表格处理
|
|
100
|
+
|
|
101
|
+
金融文档的核心信息大量存在于表格中:资产负债表、利润表、资本充足率明细表、贷款五级分类表、关联交易汇总表。表格处理不好,核查就无法开展。
|
|
102
|
+
|
|
103
|
+
### 四步流程
|
|
104
|
+
|
|
105
|
+
1. **检测**:识别表格区域。寻找网格模式、一致的列间距、或显式的表格标记。对金融文档而言,数字密集且纵向对齐的区域几乎都是表格。
|
|
106
|
+
|
|
107
|
+
2. **提取**:逐单元格提取内容。关键是保持行列关系——第三行第二列的数字必须对应正确的行标题和列标题。
|
|
108
|
+
- 常见陷阱:合并单元格导致行列错位;跨页表格的表头在第一页、数据在第二页;千分位逗号与单元格分隔符混淆。
|
|
109
|
+
|
|
110
|
+
3. **重建**:转换为结构化格式。
|
|
111
|
+
- 首选 markdown 表格(人可读、LLM 可理解)。
|
|
112
|
+
- 复杂表格可用 JSON 行数组(便于程序处理)。
|
|
113
|
+
- 保留原始表头层级(如"期末余额"下分"本期"和"上期"两个子列)。
|
|
114
|
+
|
|
115
|
+
4. **验证**:抽检重建后的表格与原文档是否一致。
|
|
116
|
+
- 选取 3-5 个关键数值,对照原 PDF 页面确认。
|
|
117
|
+
- 检查行数和列数是否匹配。
|
|
118
|
+
- 验证合计行是否等于明细行之和(财务报表通常有此约束)。
|
|
119
|
+
|
|
120
|
+
### 表格提取失败时
|
|
121
|
+
|
|
122
|
+
当 Level 1-2 无法正确提取表格:
|
|
123
|
+
- 从 PDF 中裁剪表格区域的图片。
|
|
124
|
+
- 发送给视觉模型,提示词要求输出 markdown 表格。
|
|
125
|
+
- 对视觉模型的输出做与上述相同的验证步骤。
|
|
126
|
+
|
|
127
|
+
不要因为一页表格提取失败就对整份文档使用 Level 4。只对出问题的表格页面升级。
|
|
128
|
+
|
|
129
|
+
## 图表处理
|
|
130
|
+
|
|
131
|
+
图表(柱状图、折线图、饼图、散点图)偶尔包含核查所需的数据:
|
|
132
|
+
|
|
133
|
+
- 从文档中提取图表图片(按页面或按区域裁剪)。
|
|
134
|
+
- 发送给视觉模型,提示词示例:
|
|
135
|
+
```
|
|
136
|
+
请提取此图表中的所有数据点、标签和数值。
|
|
137
|
+
返回 JSON 数组格式,每个元素包含 label 和 value 字段。
|
|
138
|
+
如有多个系列,请分别标注系列名称。
|
|
139
|
+
```
|
|
140
|
+
- 将提取的数据与文档中其他位置的文本或表格交叉验证——图表的数据通常在正文或附表中也能找到。
|
|
141
|
+
|
|
142
|
+
这是高成本操作。只在核查规则明确要求图表中的数据、且该数据无法从文本中获取时才执行。
|
|
143
|
+
|
|
144
|
+
## 输出格式
|
|
145
|
+
|
|
146
|
+
解析后的文档应保存为干净的 markdown 文件:
|
|
147
|
+
|
|
148
|
+
- **保留标题层级**:`# 第一章 总则`、`## 第一节 定义`、`### 一、适用范围`。与原文档的层级结构一一对应。
|
|
149
|
+
- **保留列表**:有序列表和无序列表保持原有编号方式。
|
|
150
|
+
- **表格转换**:转为 markdown 表格格式。复杂表格保留足够的上下文说明。
|
|
151
|
+
- **页码标注**:在页面边界处标注 `<!-- Page X -->`。部分核查规则引用特定页码。
|
|
152
|
+
- **清除噪声**:页眉、页脚、页码、水印一律去除(除非某条规则专门检查这些内容)。
|
|
153
|
+
- **保留原文措辞**:不要改写原文语句。解析是忠实转录,不是翻译或摘要。
|
|
154
|
+
|
|
155
|
+
文件命名建议:原文件名加 `.parsed.md` 后缀,存放在同一目录下。
|
|
156
|
+
|
|
157
|
+
## 缓存与复用
|
|
158
|
+
|
|
159
|
+
解析是耗时操作(尤其 Level 3-4),必须缓存结果以避免重复劳动:
|
|
160
|
+
|
|
161
|
+
- 将解析后的 markdown 文件保存在原文件旁边,供所有规则复用。
|
|
162
|
+
- 记录解析器级别:在 markdown 文件开头或配套的元数据文件中注明使用了哪个级别的解析器。
|
|
163
|
+
- 仅在以下情况重新解析:
|
|
164
|
+
- 原始文件被替换或更新。
|
|
165
|
+
- 某条规则的核查失败被追溯到解析质量问题,需要升级解析器。
|
|
166
|
+
- 缓存文件损坏或丢失。
|
|
167
|
+
|
|
168
|
+
跨规则共享解析结果是效率的关键。一份 300 页的年报可能被 50 条规则引用——解析一次,使用 50 次。
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Parser Catalog
|
|
2
|
+
|
|
3
|
+
## Text-Based Parsers (No LLM Required)
|
|
4
|
+
|
|
5
|
+
| Parser | Type | Strengths | Limitations | Install |
|
|
6
|
+
|--------|------|-----------|-------------|---------|
|
|
7
|
+
| PyMuPDF (fitz) | Text extraction | Fast, reliable, basic structure | No table awareness, no OCR | `pip install pymupdf` |
|
|
8
|
+
| pdfplumber | Layout-aware | Good table detection, spatial layout | Text-only, no OCR | `pip install pdfplumber` |
|
|
9
|
+
| python-docx | DOCX parser | Native DOCX support, preserves structure | DOCX only | `pip install python-docx` |
|
|
10
|
+
| openpyxl | XLSX parser | Full spreadsheet support | XLSX only | `pip install openpyxl` |
|
|
11
|
+
| MarkItDown | Multi-format | Handles PDF, DOCX, PPTX, XLSX → markdown | Basic parsing, may miss complex layouts | `pip install markitdown` |
|
|
12
|
+
|
|
13
|
+
## OCR / Vision Models (Via SiliconFlow API)
|
|
14
|
+
|
|
15
|
+
| Model | Tier | Strengths | Best For |
|
|
16
|
+
|-------|------|-----------|----------|
|
|
17
|
+
| zai-org/GLM-4.6V | OCR_TIER1 | Best accuracy, strong Chinese OCR | Complex tables, mixed layouts |
|
|
18
|
+
| Qwen/Qwen3.5-397B-A17B | OCR_TIER2 | Good general vision, large model | Tables with context-dependent interpretation |
|
|
19
|
+
| PaddlePaddle/PaddleOCR-VL-1.5 | OCR_TIER3 | Fast, lightweight | Standard text, simple tables |
|
|
20
|
+
|
|
21
|
+
## Local Deployment Options
|
|
22
|
+
|
|
23
|
+
For developer users who prefer local processing:
|
|
24
|
+
|
|
25
|
+
| Tool | Type | Notes |
|
|
26
|
+
|------|------|-------|
|
|
27
|
+
| PaddleOCR | Local OCR | Open source, supports Chinese/English |
|
|
28
|
+
| Surya | Local OCR | Modern OCR with table detection |
|
|
29
|
+
| pdf2md-local | PDF → Markdown | Reference: github.com/Ruilin-mmwa/pdf2md-local |
|
|
30
|
+
|
|
31
|
+
## Selection Decision Tree
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
Is the PDF text-based (not scanned)?
|
|
35
|
+
├─ Yes → PyMuPDF or pdfplumber
|
|
36
|
+
│ └─ Are tables parsed correctly?
|
|
37
|
+
│ ├─ Yes → Done
|
|
38
|
+
│ └─ No → Try pdfplumber → If still bad → Vision model on table regions
|
|
39
|
+
└─ No (scanned) → OCR_TIER3 → If quality insufficient → OCR_TIER1
|
|
40
|
+
```
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: entity-extraction
|
|
3
|
+
description: Extract specific entities, values, and text segments from documents as required by verification rules. Use after tree processing has located the relevant section, when a rule needs a specific number, date, name, amount, clause, or any domain-specific entity extracted. Covers extraction method selection (regex vs LLM), schema design, postprocessing, and confidence annotation. Also use when designing the extraction step of a workflow for worker LLMs.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# 实体提取
|
|
7
|
+
|
|
8
|
+
实体是核查的对象。一个数字、一个日期、一个金额、一个比率、一段条款。规则告诉你要检查什么,实体提取是你把这个"什么"从文档中拿出来的过程。
|
|
9
|
+
|
|
10
|
+
## 实体是什么
|
|
11
|
+
|
|
12
|
+
在文档核查语境下,实体不是 NLP 教科书中的"命名实体"。实体是**规则所关心的任何可提取信息片段**:
|
|
13
|
+
|
|
14
|
+
- 资本充足率:12.5%
|
|
15
|
+
- 贷款到期日:2025年6月30日
|
|
16
|
+
- 借款人名称:某某股份有限公司
|
|
17
|
+
- 贷款金额:人民币伍仟万元整
|
|
18
|
+
- 担保方式:抵押+保证
|
|
19
|
+
- 风险披露段落(整段文本)
|
|
20
|
+
- 签字页是否存在(布尔值)
|
|
21
|
+
|
|
22
|
+
实体的类型和粒度由规则决定,不是预先定义的。
|
|
23
|
+
|
|
24
|
+
## 提取类型分类
|
|
25
|
+
|
|
26
|
+
不同的提取场景需要不同的策略:
|
|
27
|
+
|
|
28
|
+
### 单章单实体
|
|
29
|
+
|
|
30
|
+
最简单的情况。一条规则需要从一个章节中提取一个值。
|
|
31
|
+
|
|
32
|
+
- **示例**:"从关键指标表中提取资本充足率。"
|
|
33
|
+
- **方法**:定位到章节,用正则或 LLM 提取。
|
|
34
|
+
- **这是最常见的情况**,优先为此场景优化工作流。
|
|
35
|
+
|
|
36
|
+
### 单章多实体
|
|
37
|
+
|
|
38
|
+
一条规则需要从同一位置提取若干相关值。
|
|
39
|
+
|
|
40
|
+
- **示例**:"从贷款协议摘要中提取借款人名称、贷款金额、利率、到期日。"
|
|
41
|
+
- **方法**:设计一次提取调用返回所有值。比分别调用更高效,也更容易保持值之间的关系一致性。
|
|
42
|
+
- **注意**:如果用 LLM 提取,在提示词中一次性要求所有字段。如果用正则,对同一文本段逐个匹配。
|
|
43
|
+
|
|
44
|
+
### 多章单实体
|
|
45
|
+
|
|
46
|
+
一个值分散在多个位置,或需要交叉核对。
|
|
47
|
+
|
|
48
|
+
- **示例**:"提取总担保物价值,可能出现在担保章节或附录 A 中。"
|
|
49
|
+
- **方法**:从所有相关章节收集内容,然后统一提取。记录值的来源位置——如果同一实体在不同位置出现不同值,这本身就是一个需要判定的问题。
|
|
50
|
+
- **金融文档中的典型场景**:净利润可能出现在"主要财务指标"、"利润表"、"董事长致辞"等多处。
|
|
51
|
+
|
|
52
|
+
### 全文实体
|
|
53
|
+
|
|
54
|
+
值可能在任何位置,或规则适用于整份文档。
|
|
55
|
+
|
|
56
|
+
- **示例**:"检查文档是否包含有效的签字页。"
|
|
57
|
+
- **方法**:
|
|
58
|
+
- 编程智能体执行时:扫描全文。
|
|
59
|
+
- Worker LLM(执行模型)工作流:设计两遍扫描——第一遍定位候选位置,第二遍精确提取。
|
|
60
|
+
- **成本较高**,尽量避免。如果能通过文档树缩小范围(签字页通常在文末),优先使用树导航。
|
|
61
|
+
|
|
62
|
+
## 方法选择
|
|
63
|
+
|
|
64
|
+
### 正则/Python(成本:零,速度:瞬时)
|
|
65
|
+
|
|
66
|
+
当实体具有可预测的格式时,优先使用正则表达式。
|
|
67
|
+
|
|
68
|
+
**日期提取**:
|
|
69
|
+
```python
|
|
70
|
+
# 中文日期格式
|
|
71
|
+
r'\d{4}年\d{1,2}月\d{1,2}日'
|
|
72
|
+
# ISO 格式
|
|
73
|
+
r'\d{4}[-/]\d{1,2}[-/]\d{1,2}'
|
|
74
|
+
# 混合格式
|
|
75
|
+
r'\d{4}年?\d{1,2}月?\d{1,2}日?'
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
**金额提取**:
|
|
79
|
+
```python
|
|
80
|
+
# 数字金额
|
|
81
|
+
r'[\d,]+\.?\d*\s*(?:元|万元|亿元|百万元)'
|
|
82
|
+
# 大写金额
|
|
83
|
+
r'人民币[壹贰叁肆伍陆柒捌玖拾佰仟万亿零]+(?:元整?)'
|
|
84
|
+
# 带币种标记
|
|
85
|
+
r'(?:人民币|美元|港币|EUR|USD)\s*[\d,.]+\s*(?:元|万元|亿元)?'
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
**百分比提取**:
|
|
89
|
+
```python
|
|
90
|
+
# 标准百分比
|
|
91
|
+
r'\d+\.?\d*\s*[%%]'
|
|
92
|
+
# 基点表示
|
|
93
|
+
r'\d+\.?\d*\s*(?:个基点|BP|bps)'
|
|
94
|
+
# 千分比(部分监管指标使用)
|
|
95
|
+
r'\d+\.?\d*\s*[‰]'
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
**监管编号提取**:
|
|
99
|
+
```python
|
|
100
|
+
# 银保监会发文编号
|
|
101
|
+
r'银保监发〔\d{4}〕\d+号'
|
|
102
|
+
# 证监会发文编号
|
|
103
|
+
r'证监[a-z]*〔\d{4}〕\d+号'
|
|
104
|
+
# 统一社会信用代码
|
|
105
|
+
r'[0-9A-Z]{18}'
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
好的正则表达式比好的 LLM 提示词更适合结构化值——更快、确定性、免费。在样本文档上构建和测试正则,确认覆盖率后再部署。
|
|
109
|
+
|
|
110
|
+
### LLM 提取(成本:API 调用,速度:秒级)
|
|
111
|
+
|
|
112
|
+
当实体需要语义理解时使用 LLM:
|
|
113
|
+
|
|
114
|
+
- **上下文相关的实体**:"担保人的主要经营业务"——需要理解谁是担保人、哪段文字描述了其业务。
|
|
115
|
+
- **条件性值**:"含调整后的利率"——需要理解什么构成调整。
|
|
116
|
+
- **语义匹配**:"充分的风险披露"——需要判断哪些文本构成风险披露。
|
|
117
|
+
- **不规则表格**:表格结构不统一,正则无法可靠提取单元格。
|
|
118
|
+
- **隐含信息**:"是否提及了流动性风险"——可能不是一个明确的章节标题,而是散布在多处的讨论。
|
|
119
|
+
|
|
120
|
+
设计 LLM 提取提示词的要点:
|
|
121
|
+
1. 包含缩窄后的上下文(来自文档树处理)。
|
|
122
|
+
2. 精确说明要提取什么,不要模糊。
|
|
123
|
+
3. 定义输出格式(JSON,含命名字段)。
|
|
124
|
+
4. 如果提取对象不直观,提供一个示例。
|
|
125
|
+
5. 明确要求:如果找不到,返回 null 而不是猜测。
|
|
126
|
+
|
|
127
|
+
### 混合方法
|
|
128
|
+
|
|
129
|
+
最常用的实际策略:
|
|
130
|
+
|
|
131
|
+
1. 先用正则提取候选值(快速,捕获明显匹配)。
|
|
132
|
+
2. 如果正则找到高置信度匹配,直接使用。
|
|
133
|
+
3. 如果正则失败或不确定,回退到 LLM 提取。
|
|
134
|
+
4. 在置信度要求高的场景,用 LLM 验证正则结果。
|
|
135
|
+
|
|
136
|
+
混合方法兼顾了成本和准确率。90% 的提取用正则完成(免费),10% 的困难情况用 LLM 兜底。
|
|
137
|
+
|
|
138
|
+
## 数据模式设计
|
|
139
|
+
|
|
140
|
+
为每次提取定义期望输出。保持简单,按需扩展(JIT 原则):
|
|
141
|
+
|
|
142
|
+
```json
|
|
143
|
+
{
|
|
144
|
+
"entity_name": "capital_adequacy_ratio",
|
|
145
|
+
"value": 12.5,
|
|
146
|
+
"unit": "%",
|
|
147
|
+
"raw_text": "本行资本充足率为12.50%",
|
|
148
|
+
"source_location": "第二章 > 第一节 主要财务指标 > 表1 第3行",
|
|
149
|
+
"confidence": 0.93,
|
|
150
|
+
"extraction_method": "regex"
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
模式应包含:
|
|
155
|
+
- **value**:提取的值,经标准化处理。数字用数字类型,日期用 ISO 格式,文本保持原文。
|
|
156
|
+
- **unit**:适用时注明单位(%、元、天、个基点等)。单位错误是常见的核查失败原因。
|
|
157
|
+
- **raw_text**:值在原文中的原始文本片段。这是判定步骤的证据,也是人工审查的依据。
|
|
158
|
+
- **source_location**:在文档中的位置(章节路径、表格坐标、页码)。
|
|
159
|
+
- **confidence**:提取置信度(参见下方"置信度标注"和 `confidence-system` 技能)。
|
|
160
|
+
- **extraction_method**:使用的方法(regex、python、LLM-TIER2、LLM-TIER3 等)。对演进循环有用。
|
|
161
|
+
|
|
162
|
+
不要过度设计模式。在测试过程中发现需要新字段时再添加。
|
|
163
|
+
|
|
164
|
+
## 后处理
|
|
165
|
+
|
|
166
|
+
原始提取值通常需要标准化才能用于判定:
|
|
167
|
+
|
|
168
|
+
### 中文数字转换
|
|
169
|
+
```python
|
|
170
|
+
# 中文大写 → 数字
|
|
171
|
+
"壹仟贰佰叁拾肆万伍仟陆佰柒拾捌元" → 12345678
|
|
172
|
+
"叁拾伍亿零贰仟万元" → 3520000000
|
|
173
|
+
|
|
174
|
+
# 中文小写 → 数字
|
|
175
|
+
"一百二十万" → 1200000
|
|
176
|
+
"三千五百" → 3500
|
|
177
|
+
"十二点五" → 12.5
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
这在金融文档中极为常见。贷款合同几乎总是用大写数字书写金额。建一个可靠的中文数字转换函数放在工具库中。
|
|
181
|
+
|
|
182
|
+
### 日期标准化
|
|
183
|
+
```python
|
|
184
|
+
"2024年3月15日" → "2024-03-15"
|
|
185
|
+
"二〇二四年三月十五日" → "2024-03-15"
|
|
186
|
+
"2024/03/15" → "2024-03-15"
|
|
187
|
+
"2024.3.15" → "2024-03-15"
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### 单位换算
|
|
191
|
+
```python
|
|
192
|
+
# 统一到基本单位进行比较
|
|
193
|
+
"1,500万元" → 15000000 元
|
|
194
|
+
"3.5亿元" → 350000000 元
|
|
195
|
+
"150个基点" → 1.5%
|
|
196
|
+
"0.125" → 12.5% # 小数表示的百分比
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
单位换算要特别小心。"万元"和"元"差四个数量级——一个换算错误可能让 1500 万的贷款变成 1500 元,核查结果完全失真。在后处理代码中加入合理性检查。
|
|
200
|
+
|
|
201
|
+
### 格式清理
|
|
202
|
+
```python
|
|
203
|
+
# 去除千分位分隔符
|
|
204
|
+
"12,345,678" → "12345678"
|
|
205
|
+
# 去除多余空格和换行
|
|
206
|
+
"资本充足率\n为 12.5 %" → "资本充足率为12.5%"
|
|
207
|
+
# 全角转半角
|
|
208
|
+
"12.5%" → "12.5%"
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
将后处理函数写成独立的 Python 工具,放在规则技能的 `scripts/` 目录中。它们是确定性的、可复用的。
|
|
212
|
+
|
|
213
|
+
## 置信度标注
|
|
214
|
+
|
|
215
|
+
每次提取都应附带一个置信度估计。这不是模型的自信程度,而是对提取结果正确概率的预判:
|
|
216
|
+
|
|
217
|
+
### 初始先验值
|
|
218
|
+
|
|
219
|
+
| 提取方法 | 置信度范围 | 说明 |
|
|
220
|
+
|---------|-----------|------|
|
|
221
|
+
| 正则匹配+格式验证 | 0.90-0.95 | 格式对了,值大概率对 |
|
|
222
|
+
| LLM 提取,高确定性 | 0.80-0.85 | 模型明确找到了值 |
|
|
223
|
+
| LLM 提取,有歧义 | 0.60-0.75 | 模型不太确定或有多个候选 |
|
|
224
|
+
| 回退/推断值 | 0.40-0.60 | 非直接提取,有猜测成分 |
|
|
225
|
+
| 未找到值 | 0.0 | 标记为 MISSING |
|
|
226
|
+
|
|
227
|
+
这些是起始值。通过实际的质量控制审查校准(参见 `confidence-system`)。
|
|
228
|
+
|
|
229
|
+
### 置信度调整因素
|
|
230
|
+
|
|
231
|
+
- **原文验证**:提取的值能在原文中找到完全匹配 → 置信度 +0.05。
|
|
232
|
+
- **多处一致**:同一值在文档多处出现且一致 → 置信度 +0.05。
|
|
233
|
+
- **格式异常**:值的格式与预期不符(如百分比用小数表示)→ 置信度 -0.10。
|
|
234
|
+
- **边缘案例匹配**:文档匹配已知边缘案例模式 → 置信度 -0.10。
|
|
235
|
+
|
|
236
|
+
## 适配 Worker LLM 上下文窗口
|
|
237
|
+
|
|
238
|
+
为 Worker LLM 工作流设计提取步骤时,做好 token 预算:
|
|
239
|
+
|
|
240
|
+
1. **计算提示词大小**:系统提示 + 提取指令 + 输出格式说明 + 示例 = N tokens。
|
|
241
|
+
2. **可用文档内容空间** = 模型上下文窗口 - N - 回复预留。
|
|
242
|
+
3. 如果章节内容超出可用空间,通过文档树进一步缩小范围。
|
|
243
|
+
4. 始终为模型回复留出足够空间(至少 1K-2K tokens)。
|
|
244
|
+
5. **用实际模型测试**——编程智能体的 token 计数可能与Worker LLM 的分词器不同。中文文本在不同分词器间的 token 数差异可达 30%。
|
|
245
|
+
|
|
246
|
+
### Worker LLM 提取提示词模板
|
|
247
|
+
|
|
248
|
+
```
|
|
249
|
+
你是一个金融文档实体提取助手。
|
|
250
|
+
|
|
251
|
+
任务:从以下文档内容中提取指定实体。
|
|
252
|
+
|
|
253
|
+
要提取的实体:{entity_description}
|
|
254
|
+
|
|
255
|
+
文档位置:{document_path}
|
|
256
|
+
|
|
257
|
+
文档内容:
|
|
258
|
+
---
|
|
259
|
+
{section_content}
|
|
260
|
+
---
|
|
261
|
+
|
|
262
|
+
输出格式(JSON):
|
|
263
|
+
{
|
|
264
|
+
"value": <提取的值>,
|
|
265
|
+
"unit": "<单位>",
|
|
266
|
+
"raw_text": "<原文中包含该值的完整句子>",
|
|
267
|
+
"found": true/false
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
注意:
|
|
271
|
+
- 如果找不到该实体,将 found 设为 false,value 设为 null。
|
|
272
|
+
- 不要猜测或推断,只提取文档中明确存在的信息。
|
|
273
|
+
- raw_text 必须是文档中的原文,不要改写。
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
根据实际测试结果调整提示词。不同的 Worker LLM 对提示词格式的敏感度不同。
|