ai-fill 是一个本地智能文档抽取工作台,用于把合同、表单、扫描件解析为可审核、可入库的结构化数据。
它的目标流程是:
PDF / image / TXT / Markdown -> Markdown or text -> structured JSON -> human review -> local submission
当前版本聚焦可审计、可插件化的本地抽取能力:
- 导入 PDF 和图片文件
- 将文档解析为文本或 Markdown
- 从文档内容中自动发现字段,也允许用户半自动编辑字段清单
- 提取结构化字段值
- 识别 Markdown 表格并输出
columns/rows - 为每个字段保留证据
- 结果存入 SQLite
- 通过 harness 控制模型调用、工具执行和数据库写入
backend/ FastAPI 后端,Python 运行时、存储、适配器和测试
frontend/ React 工作台,使用 Vite 构建
harness/ Markdown 提示词、工具契约和工作流定义
当前项目适合技术验证和早期集成:
- 文本型 PDF、TXT、Markdown 和基础图片/OCR 适配边界已经可用
- MinerU Agent API 可用于将 PDF/图片解析为 Markdown
- 普通字段可以从文本或 Markdown 中抽取为 JSON
- Markdown 表格可以通过
markdown_table_parser插件结构化为表格 JSON - Web 工作台支持字段自动识别、字段编辑、字段确认、确认全部、提交已确认字段
- 文件上传在前端使用内存快照,支持“智能识别字段”和“开始抽取”任意顺序连续执行
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
pytest构建 React 工作台:
cd frontend
npm ci
npm run build
cd ..启动 Web 工作台:
ai-fill-web打开:
http://127.0.0.1:8000
可复制 .env.example 作为环境变量参考。不要把真实 API key 提交到仓库。
pytest -q
python -m compileall backend/src
cd frontend && npm run buildai-fill extract path/to/file.pdf "提取合同名称、甲方、乙方、合同金额、签署日期"Web 工作台是一个由 FastAPI 托管的本地 React 应用,需要 frontend/dist 目录下存在构建产物:
- 上传 PDF、图片或 TXT 文件
- 让模型发现字段,然后可选编辑字段列表
- 运行抽取管线
- 检查抽取的字段和证据
- 确认单个字段或确认全部待确认字段
- 编辑将要提交的值
- 将确认的字段提交为正式本地记录
- 在底部折叠式处理日志中查看 pipeline / agent 运行过程
Web 应用使用与 CLI 相同的本地 SQLite 数据库。设置 AI_FILL_DATA_DIR 可指定不同的数据目录。
CLI 将 JSON 输出到标准输出,并将文档、页面、抽取字段、字段证据、结果 JSON 以及助手执行记录存储在 SQLite 中。
字段发现和抽取可以先尝试使用兼容 Ollama 的模型,再回退到确定性规则。如需快速云端验证,通过环境变量配置 Ollama Cloud:
export AI_FILL_LOCAL_MODEL_PROVIDER=ollama
export AI_FILL_LOCAL_MODEL_URL=https://ollama.com/v1
export AI_FILL_LOCAL_MODEL_NAME=gemma4
export AI_FILL_LOCAL_MODEL_API_KEY=your-ollama-api-key
PYTHONPATH=backend/src uvicorn ai_fill.web:app --host 127.0.0.1 --port 8000AI_FILL_LOCAL_MODEL_URL 也支持原生 Ollama API 格式,例如 https://ollama.com/api 或 http://localhost:11434/api。使用 /v1 表示 OpenAI 兼容的聊天补全 API,使用 /api 表示 Ollama 原生的 /api/generate API。
项目已经采用轻量 harness 架构:
- Markdown 描述模型行为、DAG workflow、工具契约和副作用
- Python 执行工具、调用模型、校验 JSON、持久化数据,保持流程可审计
- 模型驱动字段发现和抽取,harness 控制 API 调用、OCR、MinerU 和数据库写入
- 模型生成的
ToolCall必须通过 allowlist、registry 和 schema 校验后才能执行
第一层 harness 是模型提示词 harness。默认提示词位于:
harness/prompts/model_harness.md
可通过以下方式覆盖:
export AI_FILL_PROMPT_HARNESS_PATH=/path/to/model_harness.md工具描述和工作流策略也以 Markdown 存放:
harness/tools/mineru_parser.md
harness/tools/text_recognition.md
harness/tools/markdown_table_parser.md
harness/tools/schema_discovery.md
harness/tools/information_extraction.md
harness/tools/result_validation.md
harness/tools/result_normalization.md
harness/tools/human_review.md
harness/tools/result_storage.md
harness/tools/sqlite_submit.md
harness/workflows/extraction.md
应用在以下地址暴露加载的 harness 元数据:
GET /api/harness
工具 Markdown 描述工具的用途、输入/输出契约、schema、上下文键、输出键和副作用。后端将这些契约加载到一个小型 harness 运行时中:
workflow.md -> DAG nodes -> HarnessRunner -> ToolRegistry -> registered Python executor
运行器在执行前验证每个节点是否满足依赖、条件和输入 schema,并验证每个执行器是否返回声明的输出 schema。Python 仍会判断工具是否在副作用执行前已注册 executor。
初始抽取响应还包括 tool_results,用于调试运行时路径。存储的结果继续使用 agent_runs 和审核事件作为面向用户的审计追踪。
默认抽取 DAG:
file_intake
-> mineru_parser 或 text_recognition
-> markdown_table_parser
-> schema_discovery
-> information_extraction
-> result_validation
-> result_normalization
-> human_review
-> result_storage
工具 executor 通过插件注册到 ToolRegistry。主流程加载内置 extraction 插件,也支持通过 extra_tool_plugins 注入额外工具插件。
新增业务能力的目标方式是:
新增 tool markdown -> 新增 plugin executor -> 修改 workflow 配置 -> 补测试
如果新增需求需要修改 HarnessRunner、ToolRegistry 或 workflow loader,通常说明框架抽象还不够,需要优先抽取通用能力。
当前内置插件包括:
ExtractionToolPlugin:文件接入、文本识别、字段发现、信息抽取、校验、归一化、审核和存储MarkdownTablePlugin:从 Markdown 文本中识别 GitHub-flavored Markdown 表格并输出结构化表格数据
PDF 和图片解析可以在模型驱动的字段发现和抽取之前,路由到 MinerU 的 API。轻量 Agent API 返回 Markdown,然后传入现有抽取管线:
export AI_FILL_DOCUMENT_READER=mineru_agent
export AI_FILL_MINERU_AGENT_URL=https://mineru.net/api/v1/agent
export AI_FILL_MINERU_LANGUAGE=ch
PYTHONPATH=backend/src uvicorn ai_fill.web:app --host 127.0.0.1 --port 8000当 AI_FILL_DOCUMENT_READER 保持为 default 时,应用走本地路径:文本 PDF 使用 pypdf,扫描件使用配置的渲染器加 OCR,图片使用配置的 OCR 引擎。
默认 workflow 会根据 AI_FILL_DOCUMENT_READER 做条件分支:
document_reader == "mineru_agent" -> mineru_parser
document_reader != "mineru_agent" -> text_recognition
Markdown 表格已经通过插件进入默认抽取流程。markdown_table_parser 会在文档解析之后、字段发现之前运行。
输出格式示例:
{
"page_number": 1,
"table_index": 1,
"columns": ["品名", "数量", "金额"],
"rows": [
{ "品名": "设备A", "数量": "2", "金额": "2000" },
{ "品名": "服务B", "数量": "1", "金额": "3000" }
],
"markdown": "| 品名 | 数量 | 金额 |\n| --- | ---: | ---: |\n| 设备A | 2 | 2000 |"
}下一阶段目标:
- 让模型在字段抽取时显式利用结构化表格上下文
- 支持多行明细字段抽取
- 将表格单元格作为更细粒度的证据保存
- 在前端独立展示表格结果
默认运行时数据存储在 data/ 目录下:
- SQLite 数据库:
data/ai_fill.sqlite - 上传的源文件:
data/uploads/
设置 AI_FILL_DATA_DIR 可使用不同的本地数据目录:
AI_FILL_DATA_DIR=/tmp/ai-fill-data ai-fill extract backend/tests/fixtures/sample_contract.txt "提取合同金额"当前版本支持:
.txt文件:确定性本地抽取.md/.markdown文件:按 Markdown 文本进入抽取流程,并解析 Markdown 表格- 文本型
.pdf文件:通过pypdf - 图片文件(
.png、.jpg、.jpeg、.webp、.tif、.tiff):通过 OCR 适配器边界
图片 OCR 在此版本中特意设计为适配器模式。默认 OCR 引擎会抛出明确的配置错误;生产环境 OCR 可通过安装 ai-fill[ocr] 和系统 Tesseract,或注入自定义 OCR 引擎来加入。
完成的首版抽取标记为 needs_review。这意味着管线已执行完毕,保存了结构化字段和证据,等待审核工作流确认或编辑值后再提交。
- 贡献说明见 CONTRIBUTING.md
- 安全说明见 SECURITY.md
- 路线图见 ROADMAP.md
- 本项目使用 MIT License,见 LICENSE