Skip to content

Repository files navigation

ai-fill

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 build

CLI

ai-fill extract path/to/file.pdf "提取合同名称、甲方、乙方、合同金额、签署日期"

Web 工作台

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 8000

AI_FILL_LOCAL_MODEL_URL 也支持原生 Ollama API 格式,例如 https://ollama.com/apihttp://localhost:11434/api。使用 /v1 表示 OpenAI 兼容的聊天补全 API,使用 /api 表示 Ollama 原生的 /api/generate API。

Harness 模式

项目已经采用轻量 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 配置 -> 补测试

如果新增需求需要修改 HarnessRunnerToolRegistry 或 workflow loader,通常说明框架抽象还不够,需要优先抽取通用能力。

当前内置插件包括:

  • ExtractionToolPlugin:文件接入、文本识别、字段发现、信息抽取、校验、归一化、审核和存储
  • MarkdownTablePlugin:从 Markdown 文本中识别 GitHub-flavored Markdown 表格并输出结构化表格数据

MinerU 文档解析 API

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 表格已经通过插件进入默认抽取流程。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。这意味着管线已执行完毕,保存了结构化字段和证据,等待审核工作流确认或编辑值后再提交。

贡献和安全

About

No description, website, or topics provided.

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages