视觉画布设计
canvas-design
基于设计原则创作静态视觉作品,用于海报与品牌图形。
pdf-organizer【文档与办公】当需要整理法律 PDF 时使用:检测文字层,生成页面索引、整理草稿和下游交接文件,按内容拆分、合并或直接重命名 OCR 后双层扫描件并规范命名;支持跨源页引用拼合与页覆盖审计(孤儿页/重复引用);可做旋转与倾斜校正,不做 OCR 或压缩。
独立 GitHub 快照 · 自动分类 · 以原作者文档为准
本技能处理“PDF 文件和法律文书逻辑不一致”的问题。它关注的不是普通文件拼接,而是按文书内容把 PDF 整理成律师实际会使用的文件。
核心职责:
handoff.json,附页级来源引用,供案件材料整理、合同审查、诉讼分析等 Skill 协同使用。本技能不做 OCR、不压缩 PDF,也不替代案件材料整体归类。若 PDF 还没有可检索文字层,先使用 OCR 工具;若需要复杂裁边、压缩、批量 OCR 或高质量图像预处理,优先使用 PDF Processor。
| 依赖 | 安装方式 |
|---|---|
python3 | macOS 通常已内置 |
ocrmypdf | 可选,仅 deskew 倾斜校正需要;macOS: brew install ocrmypdf |
| 包名 | 用途 | 安装命令 |
|---|---|---|
pypdf | 拆分、合并、复制、页面旋转 | python3 -m pip install -r scripts/requirements.txt |
只做清单规划时不需要安装依赖;执行拆分、合并或旋转时需要 pypdf。倾斜校正依赖 ocrmypdf 命令行工具,未安装时应提示用户改用 PDF Processor 或先安装。
第 1-2 页.pdf、第 3-4 页.pdf。archive/YYYYMMDD_HHMMSS_{来源名}/。archive 默认包含:
organize_manifest.input.json:本次输入清单副本。organize_manifest.resolved.json:实际输出路径、页码、状态和命名依据。organize_report.md:给人工复核的摘要报告。handoff.json:面向下游 Skill 的交接文件。run_meta.json:运行元数据。organize_manifest.json 草稿,再由 AI 根据页面证据和命名规则复核。deskew,但复杂图像问题优先交给 PDF Processor。拆分场景:
1/N 重新开始。合并场景:
重命名场景:
input_file 指定来源,用 suggested_filename 给出规范文件名。rotate 或 deskew。如果边界不确定,不要强行合并或拆开;在 manifest 中标记 needs_review: true,并在文件名中保留页码提示。
常见法律文书的细分识别规则见 references/recognition-rules.md。
默认文件名格式:
文书名称 关键主体 补充区分.pdf
规则:
YYYYMMDD;日期缺失或 OCR 可疑时省略。 1、 2,不覆盖已有文件。待确认 页码.pdf 或 疑似文书名称 页码.pdf。示例:
专项法律服务合同 北京青柏教育咨询有限公司.pdf
委托代理合同 张家宁与杭州叠影科技有限公司 著作权权属侵权纠纷.pdf
授权委托书 张家宁.pdf
律师事务所函 张家宁诉杭州叠影科技有限公司.pdf
民事起诉状 张家宁诉杭州叠影科技有限公司 普通版.pdf
民事起诉状 张家宁诉杭州叠影科技有限公司 要素式.pdf
执行前先生成 organize_manifest.json。字段说明见 references/organize-manifest-schema.md。
所有 segment 在执行前都会被编译为「文件 + 页码」的页引用集合:拆分、复制、合并、跨源拼合都只是引用运算,manifest 即引用表,物理 PDF 在确认执行前一个字节不动。执行器只消费引用表;整文件单源段保留字节级复制。
{
"source_pdf": "/path/to/ocr.pdf",
"output_dir": "/path/to/output",
"segments": [
{
"id": "D001",
"pages": "1-2",
"suggested_filename": "专项法律服务合同 北京青柏教育咨询有限公司.pdf",
"title": "专项法律服务合同",
"confidence": "high",
"needs_review": false,
"evidence": "第 1 页标题为专项法律服务合同,页脚显示第1页共2页。"
}
]
}
{
"output_dir": "/path/to/output",
"segments": [
{
"id": "D001",
"source_items": [
{"file": "/path/to/起诉状 第1-2页.pdf"},
{"file": "/path/to/起诉状 第3-4页.pdf"}
],
"suggested_filename": "民事起诉状 张家宁诉杭州叠影科技有限公司 普通版.pdf",
"title": "民事起诉状",
"confidence": "high",
"needs_review": false,
"evidence": "两份 PDF 标题一致且页码连续,第二份为同一份起诉状续页。"
}
]
}
从多份来源 PDF 各取若干页拼成一份新材料(如证据组合卷),使用 refs 字段:
{
"output_dir": "/path/to/output",
"segments": [
{
"id": "D001",
"refs": [
{"file": "/path/to/起诉状.pdf", "pages": "5"},
{"file": "/path/to/证据卷.pdf", "pages": "1-3"},
{"file": "/path/to/补充说明.pdf"}
],
"suggested_filename": "证据组合 原告提交.pdf",
"confidence": "medium",
"needs_review": true,
"evidence": "起诉状第5页列明的证据与证据卷第1-3页对应。"
}
]
}
refs 按数组顺序拼合;每项 pages 可省略(默认整份)。segment 的有效 id 必须唯一;省略时生成 D001、D002 等,显式编号也不能与这些默认值冲突。
{
"output_dir": "/path/to/output",
"segments": [
{
"id": "D001",
"input_file": "/path/to/横向扫描.pdf",
"rotate": 90,
"suggested_filename": "授权委托书 张家宁.pdf",
"confidence": "medium",
"needs_review": true
}
]
}
不需要拆分或合并,只根据内容识别结果规范命名:
{
"output_dir": "/path/to/output",
"segments": [
{
"id": "D001",
"input_file": "/path/to/scan_20260531_001.pdf",
"suggested_filename": "民事起诉状 张家宁诉杭州叠影科技有限公司 普通版.pdf",
"title": "民事起诉状",
"document_type": "民事起诉状",
"confidence": "high",
"needs_review": false,
"evidence": "首页标题为民事起诉状,正文提及张家宁与杭州叠影科技有限公司著作权权属侵权纠纷。"
},
{
"id": "D002",
"input_file": "/path/to/scan_20260531_002.pdf",
"suggested_filename": "授权委托书 张家宁.pdf",
"title": "授权委托书",
"document_type": "授权委托书",
"confidence": "high",
"needs_review": false,
"evidence": "首页标题为授权委托书,委托人张家宁。"
}
]
}
首次执行拆分、合并或旋转时,先安装依赖:
python3 -m pip install -r scripts/requirements.txt
预览计划:
python3 scripts/pdf_organizer.py --manifest organize_manifest.json --dry-run
只做页引用编译与覆盖审计(不写任何 PDF),检查文件存在、页码越界、孤儿页与重复引用页:
python3 scripts/pdf_organizer.py --validate-manifest organize_manifest.json
覆盖审计模式(off / warn / strict):默认 warn(孤儿页/重复引用页提示不拦截);strict 时发现孤儿页或重复引用页直接终止,一个 PDF 都不写。可命令行 --coverage-check strict 或 manifest 顶层 "coverage_check": "strict" 指定:
python3 scripts/pdf_organizer.py --manifest organize_manifest.json --coverage-check strict
拆分整份扫描件时推荐 strict:它在完整引用表编译成功后,检查已引用来源的每一页是否被且仅被引用一次,避免漏页或多切。重复有效 ID、段编译失败、覆盖异常或审计异常均在写 PDF 前阻断;单独验证遇到审计异常也返回非零退出码。
这是执行前检查,不是整批事务:warn / off 模式保留逐段处理,某段失败时此前成功文件可能已写出;所有模式在后续写入、旋转或倾斜校正失败时也可能留下文件,退出码非零不代表输出目录为空。交付前必须核对 resolved manifest 的逐段 status、实际文件和报告,失败段不得当作完成。详见 清单契约与回归边界。
只检测 PDF 是否有可检索文字层:
python3 scripts/pdf_organizer.py --check-text-layer "/path/to/file.pdf"
生成页面检查索引:
python3 scripts/pdf_organizer.py \
--inspect "/path/to/ocr.pdf" \
--inspect-output "/path/to/page_inspection.json"
生成 manifest 草稿:
python3 scripts/pdf_organizer.py \
--suggest-manifest "/path/to/ocr.pdf" \
--output-dir "/path/to/organized" \
--manifest-output "/path/to/organize_manifest.json"
将一个或多个 PDF 的每页标准化为 A4 尺寸,横向页面→A4 横版,竖向页面→A4 竖版:
# 原地覆盖
python3 scripts/pdf_organizer.py --normalize-a4 file1.pdf file2.pdf
# 输出到指定目录
python3 scripts/pdf_organizer.py --normalize-a4 file1.pdf file2.pdf --normalize-output-dir /path/to/output
草稿只作为复核起点。脚本会保守使用 待确认,不要跳过人工/AI 复核直接执行。
确认后执行:
python3 scripts/pdf_organizer.py --manifest organize_manifest.json
常用覆盖参数:
python3 scripts/pdf_organizer.py \
--manifest organize_manifest.json \
--source "/path/to/ocr.pdf" \
--output-dir "/path/to/organized" \
--archive-root "/path/to/archive-root"
脚本默认以 strict 模式检测来源 PDF 的文字层;检测不到可检索文字层时会停止执行。只有在纯旋转、复制等不依赖内容判断的场景,才可在 manifest 中设置 "text_check": "off" 或命令行使用 --text-check off。
脚本只向输出目录写入最终 PDF,不修改源 PDF;manifest、resolved JSON、报告、handoff.json 和元数据写入 archive。
每次正式执行都会在 archive 中生成 handoff.json。下游 Skill 优先读取该文件,而不是重新猜测文件名和文书类型。
来源数组按输出页顺序排列,仅合并连续的同源页组;同一个 file 可以在列表里重复出现,下游不得按文件名重新分组、排序或去重。pages 保持整数数组类型,包含原始顺序和重复页。
每份输出文书都带页级溯源:source_refs(归一化页引用 [{file, pages}])和 source_refs_label(人读标签如 起诉状.pdf P5 + 证据卷.pdf P1-3),下游引用任何关键信息时可回溯到具体来源页。
suggested_downstream 按文书类别给出路由标签,不绑定具体 Skill 名称:
合同审查。诉讼分析。材料整理。材料整理。具体由哪个 Skill 消费,由下游根据当前可用的 Skill 和案件上下文自行决定。
完成后检查:
pages 对应;合并文件页数等于来源页数之和。organize_report.md 没有 low 且 needs_review: true 的未处理项;如果有,明确提示用户人工复核。