feat: export core Hermes skills
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
OCR乱码检测器 — Step1 OCR完成后必跑。
|
||||
扫描OCR文本中所有疑似乱码行,输出vision核实清单。
|
||||
每一处乱码都必须vision对应PDF页面核实后才能进Step2。
|
||||
|
||||
用法: python3 ocr-garble-detect.py <ocr_file.md>
|
||||
|
||||
判定规则:
|
||||
1. 多个无意义英文片段(连续3+字母非常见词)
|
||||
2. 中文占比过低(正常合同行>50%,低于30%标红)
|
||||
3. 中英混杂碎片(典型OCR乱码模式)
|
||||
4. 异常符号密集(>20%非正常字符)
|
||||
|
||||
误报处理:
|
||||
- 纯数字表格行(日期+金额)→ 正常,核对数字即可
|
||||
- 邮箱/网址/银行账号 → 正常
|
||||
- 英文缩写(USD/RMB/PDF)→ 正常
|
||||
真正需要vision的是:含中文碎片+英文乱码的混合行(如"oe方,同Se")
|
||||
|
||||
教训(凤凰文化0701):
|
||||
Line 204 "Se【2024】年【10】月【15】日" 被跳过未核实,
|
||||
导致整段违约金条款丢失(实际是"初年年租金20%作为违约金")。
|
||||
代价=审查结论反转("无违约金"→"有20%违约金")。
|
||||
"""
|
||||
import re, sys
|
||||
|
||||
def is_garbled(line):
|
||||
"""判断一行是否疑似乱码,返回原因或None"""
|
||||
stripped = line.strip()
|
||||
if not stripped or len(stripped) < 5:
|
||||
return None
|
||||
|
||||
# 1. 连续3+个无意义英文字母组合(非常见英文词)
|
||||
nonsense_en = re.findall(r'[a-zA-Z]{3,}', stripped)
|
||||
common_words = {'pdf','ocr','usd','rmb','the','and','for','with','from',
|
||||
'www','com','xdf','jpg','png','doc','docx','xlsx','occ',
|
||||
'vision','step','check','null','true','false'}
|
||||
real_nonsense = [w for w in nonsense_en
|
||||
if w.lower() not in common_words
|
||||
and not re.match(r'^[A-Z]{1,4}$', w)]
|
||||
if len(real_nonsense) >= 2:
|
||||
return f"多个无意义英文片段: {real_nonsense[:3]}"
|
||||
|
||||
# 2. 单行中文字符占比过低(正常合同行中文应>50%)
|
||||
chinese_chars = len(re.findall(r'[\u4e00-\u9fff]', stripped))
|
||||
total_chars = len(re.findall(r'\S', stripped))
|
||||
if total_chars > 10 and chinese_chars / total_chars < 0.3:
|
||||
# 排除纯数字表格行(日期+金额)和邮箱/账号行
|
||||
if re.match(r'^[\d\.\-\s\|/,]+$', stripped):
|
||||
return None # 纯数字表格行
|
||||
if '@' in stripped or re.match(r'^[A-Z]{2,4}:', stripped):
|
||||
return None # 邮箱或字段标签
|
||||
return f"中文占比过低({chinese_chars}/{total_chars}={chinese_chars/total_chars:.0%})"
|
||||
|
||||
# 3. 常见OCR乱码模式:小写英文碎片+中文混杂
|
||||
if re.search(r'[a-z]{2,}\s+[a-z]{2,}\s+[a-z]{2,}', stripped) and chinese_chars > 0:
|
||||
return "中英混杂碎片(典型OCR乱码)"
|
||||
|
||||
# 3b. 日期区域英文字母污染(凤凰文化10.2教训:Se【2024】年【10】月→整段丢失)
|
||||
if re.search(r'[A-Za-z]{2,}\s*【\d{4}】', stripped) and chinese_chars > 0:
|
||||
return "日期区域字母污染(高风险:可能整段条款被OCR吃掉)"
|
||||
|
||||
# 4. 特殊符号异常密集
|
||||
special = len(re.findall(r'[^\w\u4e00-\u9fff\s,。、;:""''()【】《》\-\+\.\%\/\|]', stripped))
|
||||
if special > 5 and total_chars > 0 and special / total_chars > 0.2:
|
||||
return f"异常符号密集({special}个)"
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def main():
|
||||
if len(sys.argv) < 2:
|
||||
print("用法: python3 ocr-garble-detect.py <ocr_file.md>")
|
||||
sys.exit(1)
|
||||
|
||||
filepath = sys.argv[1]
|
||||
with open(filepath, 'r') as f:
|
||||
lines = f.readlines()
|
||||
|
||||
garbled = []
|
||||
for i, line in enumerate(lines, 1):
|
||||
reason = is_garbled(line)
|
||||
if reason:
|
||||
garbled.append((i, line.strip()[:80], reason))
|
||||
|
||||
if not garbled:
|
||||
print("✅ 未检测到明显乱码行。可以进入Step 2。")
|
||||
else:
|
||||
# 区分真乱码 vs 可能误报(纯数字/邮箱等)
|
||||
real_garble = [g for g in garbled if '无意义英文' in g[2] or '中英混杂' in g[2]]
|
||||
maybe_garble = [g for g in garbled if g not in real_garble]
|
||||
|
||||
print(f"⚠️ 检测到 {len(garbled)} 处疑似乱码(其中 {len(real_garble)} 处高危)\n")
|
||||
|
||||
if real_garble:
|
||||
print("🔴 高危乱码(必须vision核实,不核实不进Step2):")
|
||||
for lineno, text, reason in real_garble:
|
||||
print(f" Line {lineno:3d} | {reason}")
|
||||
print(f" | {text}")
|
||||
print()
|
||||
|
||||
if maybe_garble:
|
||||
print("🟡 疑似乱码(核对数字/格式是否正确):")
|
||||
for lineno, text, reason in maybe_garble:
|
||||
print(f" Line {lineno:3d} | {reason}")
|
||||
print(f" | {text}")
|
||||
print()
|
||||
|
||||
print(f"--- 高危 {len(real_garble)} 处必须vision核实 + 疑似 {len(maybe_garble)} 处核对数值 ---")
|
||||
print("操作:对每处高危乱码,定位PDF页码 → vision精读 → 记录修正内容")
|
||||
print("全部消灭后才能进入 Step 2。")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Reference in New Issue
Block a user