- AI 应用
- 人工智能
- AI Agent
- 本地部署
- 前端
- 后端
- 工作流自动化
【免费下载链接】ekko-studio
Ekko Studio is a local-first AI workspace for multi-agent chat, coding, and visual workflows, available on desktop and the web.
导读
Ekko Studio(本地优先的多 Agent 协作工作区)内置了一组 Agent Skills,其中ocr-and-documents专门解决"普通文本提取失效"的场景——扫描件、纯图片型 PDF 和复杂版式文档。本文基于 ocr-and-documents 技能目录 及其 SKILL.md,系统讲解该技能的适用判断、轻重两条提取路径、命令行用法、隐私边界与结果校验方法,并结合仓库内两个 Python 助手脚本的源码与测试用例,带你掌握一套可复制、可落地的本地文档 OCR 工作流。
一、这个 Skill 解决什么问题
ocr-and-documents在 DESCRIPTION.md 中的定位非常明确:
Skills for extracting text from PDFs, scanned documents, images, and other file formats using OCR and document parsing tools.
而在 SKILL.md 中则进一步收敛了使用边界:
Use this Skill when ordinary document extraction fails because the source is scanned, image-based, or layout-heavy.
即:只有当普通文本提取失效时才启用。对于生来就是数字文本的文档(born-digital),应该走各自的常规技能——PDF 用pdfSkill,Word 用docxSkill,而不是盲目地对一切文件做 OCR。
在 ekko-agent/README.md 的内置技能清单中,ocr-and-documents与pdf、docx、xlsx、powerpoint等一同被列为包内置(package-owned)技能,随 Agent 自动同步安装,属于skill_list/skill_view/skill_manage工具可发现的默认能力之一。这意味着:你不需要手动部署,Agent 会通过skill_list检索、skill_view加载技能目录,并返回可执行脚本所在的baseDirectory。
典型触发场景
| 场景 | 特征 | 推荐路径 |
|---|---|---|
| 扫描版 PDF(合同、票据) | 纯图片页,无文本层 | 先用pdfSkill 渲染页面 + 视觉检查,再按需转录 |
| 文本型扫描 PDF | 有文本层但质量差 | extract_pymupdf.py(轻量) |
| 复杂版式:表格、公式、多页扫描 | 版式密集、结构复杂 | extract_marker.py(重量级,需谨慎) |
| URL 指向的文档 | HTML 或文件不确定 | 先用浏览器/HTTP 工具判别,再下载本地处理 |
二、核心原则:先走最轻的路
SKILL.md 给出了明确的四步决策阶梯,这是整个技能的灵魂——不要一上来就上重型 OCR:
- 常规提取优先:PDF 用
pdfSkill,.docx用docxSkill,不对数字文本做 OCR。这与 pdf/SKILL.md 中的约定相互印证——pdf Skill 明确写着"Use OCR only when normal text extraction is empty or clearly incomplete. Route scanned documents through the ocr-and-documents Skill",两个技能形成了清晰的分工与转介关系。 - 少量扫描页:先用
pdfSkill 渲染页面,再用view_image查看渲染图,只转录用户要求的页面。 - 文本型扫描 PDF:尝试
extract_pymupdf.py——这是更轻的本地路径,依赖只有 PyMuPDF。 - 复杂版式/表格/公式/大量扫描页:确认需求并检查资源后,才使用
extract_marker.py。
这个阶梯设计的背后是对资源成本的清醒认识:marker-pdf 可能需要数 GB 的包和模型下载,而 PyMuPDF 路径只需一个 pip 包。仓库中extract_marker.py的--check参数(见下文第四节)正是为这一决策提供磁盘空间依据。
三、轻量路径:extract_pymupdf.py 全解
3.1 基本用法
python3 <baseDirectory>/scripts/extract_pymupdf.py input.pdf -o extracted.md其中<baseDirectory>是调用skill_view后返回的技能目录绝对路径。运行依赖:
python3 -m pip install pymupdf而--markdown模式额外需要pymupdf4llm。
从源码看,extract_pymupdf.py 采用延迟导入策略:pymupdf、pymupdf4llm、pandas都在各自函数内部导入,因此只跑普通文本提取时无需安装全套依赖,这也与"轻量优先"的定位一致。
3.2 五种提取模式(互斥)
脚本通过argparse的add_mutually_exclusive_group定义了四种互斥模式,外加默认的纯文本模式:
| 参数 | 作用 | 底层实现要点 |
|---|---|---|
| (无参数) | 纯文本提取 | 逐页document[index].get_text(),输出带--- Page N/M ---分页标记 |
--markdown | 结构化 Markdown 提取 | pymupdf4llm.to_markdown(path, pages=pages),需额外安装pymupdf4llm |
--tables | 表格识别为 Markdown 表格 | page.find_tables()检测表格,table.to_pandas().to_markdown(index=False)输出 |
--images DIRECTORY | 提取 PDF 内嵌图片 | 遍历page.get_images(full=True),输出page{N}_img{M}.png;当pixmap.n >= 5(如 CMYK)时先转换到 RGB 再保存 |
--metadata | 输出文档元数据 JSON | 返回页数、标题、作者、主题、创建者、生产者、格式等字段,json.dumps(..., ensure_ascii=False)保留中文 |
3.3 页面范围选择
--pages参数接受从 0 开始的页索引,支持逗号分隔的单个页和-连接的区间,例如:
# 提取第 1~5 页(内部为索引 0-4) python3 <baseDirectory>/scripts/extract_pymupdf.py input.pdf --pages 0-4 -o first5.md # 提取第 1、3、6 页 python3 <baseDirectory>/scripts/extract_pymupdf.py input.pdf --pages 0,2,5 -o selected.md源码中的parse_pages函数会做两类合法性校验:区间起点不能大于终点(否则抛ArgumentTypeError),页索引不能为负;超出文档实际页数的索引会被静默跳过(if index >= len(document): continue),因此可以放心给大范围。这个能力让"只转录用户要求的页面"这一轻量原则有了落地的抓手。
3.4 输出行为
- 不传
-o/--output时,结果直接打印到 stdout; - 传
-o时,结果以 UTF-8 写入文件,同时 stdout 输出一行 JSON:{"output": "/abs/path/to/extracted.md"},方便 Agent 拿到绝对路径返回给用户。
任何ImportError、OSError、ValueError、RuntimeError都会以Error: ...形式写到 stderr 并返回退出码 2,便于上层捕获失败。
四、重量级路径:extract_marker.py 与资源检查
4.1 定位与风险提示
extract_marker.py基于marker-pdf(脚本源码),对复杂版式的处理能力远超 PyMuPDF 路径——它在内部调用PdfConverter与create_model_dict(),会加载真实的视觉/版面模型。代价是:
- 依赖包与模型下载可能占用数 GB 空间;
- SKILL.md 明确要求:绝不可自动安装,必须先检查磁盘空间并征求用户同意。
4.2 --check:先查资源再干活
python3 <baseDirectory>/scripts/extract_marker.py --checkcheck_requirements()函数用shutil.disk_usage计算当前磁盘可用空间(单位 GiB):
- 可用空间 < 5GB:打印
Only X.XGB free. marker-pdf needs about 5GB.并提示改用extract_pymupdf.py或释放空间,返回退出码 1; - 空间充足:打印
X.XGB free; sufficient for marker-pdf.,返回 0。
关键设计:--check分支在import marker之前返回,因此即使 marker 尚未安装也能执行,用于快速、零成本地评估可行性。
4.3 转换用法与输出格式
# 默认 Markdown 输出 python3 <baseDirectory>/scripts/extract_marker.py input.pdf -o extracted.md # 结构化 JSON 输出(markdown + metadata 双字段) python3 <baseDirectory>/scripts/extract_marker.py input.pdf --json -o extracted.json # 同时把提取出的图片保存到目录 python3 <baseDirectory>/scripts/extract_marker.py input.pdf -o extracted.md --output-dir assets/ # 启用 marker 配置的 LLM 增强 python3 <baseDirectory>/scripts/extract_marker.py input.pdf --use-llm -o extracted.md参数说明:
| 参数 | 含义 |
|---|---|
document | 输入文档路径(--check模式下可省略) |
-o/--output | 结果写入 UTF-8 文件;stdout 返回{"output": ...}JSON |
--output-dir | 提取出的图片保存目录(脚本从rendered.images中逐张落盘) |
--json | 输出{"markdown": ..., "metadata": ...}结构化 JSON |
--use-llm | 将{"use_llm": True}注入 marker 的ConfigParser,启用其配置的 LLM 增强环节 |
--check | 只做磁盘空间检查,不加载 marker |
五、URL 来源的处理规范
当来源是 URL 时,SKILL.md 给出的流程是:
- 先用可用的浏览器或 HTTP 工具判别目标到底是 HTML 页面还是文档文件;
- 只下载被请求的那一份文档,并尊重认证与访问边界(不要越权抓取);
- 下载为本地副本后,再走上述提取流程;
- 不要假设存在某个特定的 Web 工具——工具可用性以当前环境为准。
这保证了 URL 场景下依然保持"本地处理 + 最小权限"的隐私姿态。
六、隐私与依赖安全边界
整个技能有一条贯穿始终的红线,SKILL.md 与 pdf Skill 的约定一致:
- 优先本地处理:未经用户明确授权,不得把私人文档上传到外部 OCR 服务;
- 重型依赖不自动安装:marker-pdf 及其模型下载必须先检查磁盘空间、先征得用户同意;
- 敏感内容不外泄:不要向外部服务发送敏感文档内容。
这与 ekko-agent/README.md 中对技能工具的描述相辅相成——skill_view只加载SKILL.md或允许的支持文件并返回baseDirectory,脚本由 Agent 在本地执行,天然适合处理含隐私信息的合同、票据、证件类文档。
七、结果校验清单(Verification)
OCR 结果的可靠性与校验投入成正比,SKILL.md 给出了明确的验收标准,这也是"提取 ≠ 完成"的关键一步:
- 保留结构与引用:阅读顺序、页码引用、标题、表格、脚注、置信度提示都要保留在输出中;
- 视觉比对:用
view_image将提取文本与代表性渲染页面逐页对照(渲染页面可用pdfSkill 的pdf_page_image.py,参见 pdf/SKILL.md); - 不猜不补:对不确定的字符和字段要显式标记,而不是凭猜测补全;
- 表格单独核验:列对齐与数值需要单独逐一核对(OCR 对表格数字的误识别率远高于正文);
- 返回映射关系:尽可能同时给出提取产物路径与原始来源/页码的映射,方便用户回溯验证。
八、自动化测试如何守护这两个脚本
仓库在 tests/test_ocr_documents.py 中为两个助手脚本提供了三个关键测试,可作为理解脚本契约的权威参考:
test_helpers_expose_non_loading_help:对两个脚本执行--help,断言退出码为 0 且输出中包含--output。注意测试名中的 "non-loading"——--help路径不触发重型依赖导入,保证在任何环境下都能查看用法;test_marker_disk_check_does_not_import_marker:执行extract_marker.py --check,断言退出码为 0 或 1,且输出中包含GB。这正是对"检查不加载 marker"这一设计的直接验证;test_pymupdf_writes_requested_output:用 PyMuPDF 现场生成一页含 "OCR helper smoke test" 文本的 PDF,运行extract_pymupdf.py --output,断言返回码为 0 且输出文件中包含该文本,端到端验证了"写文件 + UTF-8 编码 + 文本提取"全链路。
这三个测试覆盖了"无依赖可自检、轻量路径端到端可用"两条关键承诺,也是你在自己的环境中复现脚本行为的最小验证集。
九、端到端实战示例
综合以上内容,一个完整的"扫描 PDF 提取"典型会话流程如下:
# 1. Agent 加载技能,拿到 baseDirectory(示意路径) # skill_view -> <base>/skills/ocr-and-documents # 2. 先确认是否真的需要 OCR:渲染第 1 页看内容 python3 <base>/skills/pdf/scripts/pdf_page_image.py scan.pdf -o rendered --pages 1-3 # 3. 用 view_image 查看渲染图,确认是扫描件、需要提取的页码范围 # 4. 走轻量路径提取文本(假设第 1~10 页) python3 <base>/skills/ocr-and-documents/scripts/extract_pymupdf.py scan.pdf --pages 0-9 -o extracted.md # 5. 若版式复杂(表格/公式)且资源允许,先检查再走重量级路径 python3 <base>/skills/ocr-and-documents/scripts/extract_marker.py --check python3 <base>/skills/ocr-and-documents/scripts/extract_marker.py scan.pdf -o extracted_marker.md # 6. 渲染关键页,用 view_image 与提取结果逐一比对,标记不确定字符 # 7. 返回提取产物绝对路径 + 页码映射,说明置信度限制整个过程无需任何外部 OCR 服务,文档全程留在本机,符合该技能"本地优先、用户授权优先"的核心理念。
参考资源
- 技能说明:packages/ekko-agent/skills/ocr-and-documents/DESCRIPTION.md
- 技能指南:packages/ekko-agent/skills/ocr-and-documents/SKILL.md
- 轻量提取脚本:scripts/extract_pymupdf.py
- 重型提取脚本:scripts/extract_marker.py
- 自动化测试:tests/test_ocr_documents.py
- 协作技能:pdf/SKILL.md、docx/SKILL.md
- 技能机制总览:ekko-agent/README.md
- AI 应用
- 人工智能
- AI Agent
- 本地部署
- 前端
- 后端
- 工作流自动化
【免费下载链接】ekko-studio
Ekko Studio is a local-first AI workspace for multi-agent chat, coding, and visual workflows, available on desktop and the web.
相关推荐
IsaacLab 自碰撞过滤完整指南:3 步配好机器人碰撞组,让仿真不再"自己撞自己"
IsaacLab 自碰撞过滤完整指南:3 步配好机器人碰撞组,让仿真不再"自己撞自己" 在 IsaacLab 机器人学习仿真框架里做机械臂、灵巧手这类多连杆任务
人工智能强化学习机器人具身智能深度学习OCRmyPDF文本提取:从扫描文档中提取结构化数据
OCRmyPDF文本提取:从扫描文档中提取结构化数据 你是否还在为无法编辑的扫描PDF烦恼?是否曾因找不到文档中的关键信息而反复翻阅?OCRmyPDF(Opti
OCRCLIEkko Studio(原 Hermes Studio)本地优先多智能体工作区:架构、功能全景与部署实践
Ekko Studio(原 Hermes Studio)本地优先多智能体工作区:架构、功能全景与部署实践 Ekko Studio 是一个 local first
AI 应用人工智能AI Agent本地部署前端后端工作流自动化
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考