
转型 FDE 的路线里,"攒三个可展示的项目"是最难启动的一步。本文给出一个能现场跑通的第一项目:从合同文本中批量抽取甲方、金额、期限、违约责任条款,输出结构化 CSV。场景真实(律所、法务、采购都有这个痛点)、技术门槛适中(正则规则 + 可插拔的模型兜底)、演示效果直观(一堆 txt 进去,一张表出来)。全程只用标准库。
输入:一个目录下的若干 .txt 合同文本(真实场景中是 PDF/Word,文末给出扩展说明)。输出:CSV,每行一份合同,列为各抽取字段。边界:规则抽取只覆盖写法规范的条款,对不规范文本返回空值并记入 miss 列,由后续的人工复核或模型兜底处理——知道规则系统在哪里失效,比假装它全能重要。
#!/usr/bin/env python3
"""合同关键信息抽取器:规则优先,结果落 CSV。仅依赖标准库。"""
import csv
import re
import sys
from pathlib import Path
# 字段名 -> (正则, 捕获组说明)。按合同常见写法设计,可按样本扩充。
RULES = {
"party_a": r"甲\s*方[::]\s*([^\n,。;]+)",
"party_b": r"乙\s*方[::]\s*([^\n,。;]+)",
"amount": r"(?:合同)?(?:总)?金额[为::]*\s*(人民币)?\s*([\d,]+(?:\.\d+)?)\s*元",
"term": r"(?:合同)?期限[为::]*\s*([^\n,。;]*?(?:年|月|日)[^\n,。;]*?)(?=[,。;\n])",
"breach": r"违约责任[::]\s*([^\n。]*。)",
}
def extract_field(text: str, pattern: str) -> str:
m = re.search(pattern, text)
if not m:
return ""
groups = [g for g in m.groups() if g]
return groups[-1].strip() if groups else m.group(0).strip()
def extract_file(path: Path) -> dict:
text = path.read_text(encoding="utf-8")
row = {"file": path.name}
miss = []
for field, pattern in RULES.items():
value = extract_field(text, pattern)
row[field] = value
if not value:
miss.append(field)
row["miss"] = "|".join(miss)
return row
def main(src_dir: str, out_csv: str):
rows = [extract_file(p) for p in sorted(Path(src_dir).glob("*.txt"))]
fields = ["file"] + list(RULES) + ["miss"]
with open(out_csv, "w", encoding="utf-8-sig", newline="") as f:
writer = csv.DictWriter(f, fieldnames=fields)
writer.writeheader()
writer.writerows(rows)
hit = sum(1 for r in rows if not r["miss"])
print(f"共处理 {len(rows)} 份,全字段命中 {hit} 份")
if __name__ == "__main__":
main(sys.argv[1] if len(sys.argv) > 1 else "contracts",
sys.argv[2] if len(sys.argv) > 2 else "result.csv")# make_sample.py:生成两份样例合同用于验证
from pathlib import Path
Path("contracts").mkdir(exist_ok=True)
Path("contracts/c1.txt").write_text(
"甲方:云启科技有限公司\n乙方:某律师事务所\n"
"合同总金额为人民币 1,200,000 元。\n"
"合同期限为两年,自签署之日起算。\n"
"违约责任:任何一方违约,应向对方支付合同总额 5% 的违约金。\n",
encoding="utf-8")
Path("contracts/c2.txt").write_text(
"甲方:恒通制造集团\n乙方:个人开发者\n"
"合同期限为六个月。\n",
encoding="utf-8") # 故意缺金额与违约条款,验证 miss 列
print("样例已生成")python3 make_sample.py && python3 extractor.py contracts result.csv输出:
共处理 2 份,全字段命中 1 份result.csv 中 c1 全部字段命中,c2 的 amount 和 breach 为空、miss 列标出缺失字段——这正是交付时要给客户演示的"系统知道自己的边界"。
第一步,接真实格式:PDF 用 pdfplumber 提取文本、docx 用 python-docx,抽取逻辑不用改,只是在 extract_file 前加一层格式转换。第二步,给规则兜底:对 miss 字段,把该字段上下文段落发给一个兼容 OpenAI 协议的模型服务(接口地址填 https://你的模型服务地址/v1/chat/completions),用提示词让它只回答字段值或"未提及",把结果与规则结果并列存入 CSV,人工抽查一致性。第三步,包装交付形态:加一个 30 行的 HTTP 上传页,客户拖文件进去、下载 CSV——能现场跑通的演示,比十页方案文档有说服力。
这个项目的价值不在代码量,而在它覆盖了 FDE 工作的完整链条:摸清需求边界、先跑通最小闭环、知道自己在哪里失效、留下扩展接口。把这个过程讲清楚,本身就是一次合格的现场演练。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。