$npx -y skills add OpenRaiser/PaperFit --skill visual-inspector本技能是 PaperFit 视觉排版优化闭环中的关键环节,专门负责 PDF 页图渲染与视觉验收指导。它封装了将 PDF 转换为逐页高分辨率图片的标准化流程,并为 layout-detective-agent 和 quality-gatekeeper-agent 提供详细的逐页视觉检查清单。
| 1 | # Visual Inspector Skill |
| 2 | |
| 3 | ## 概述 |
| 4 | |
| 5 | 本技能是 PaperFit 视觉排版优化闭环中的关键环节,专门负责 **PDF 页图渲染与视觉验收指导**。它封装了将 PDF 转换为逐页高分辨率图片的标准化流程,并为 `layout-detective-agent` 和 `quality-gatekeeper-agent` 提供详细的逐页视觉检查清单。 |
| 6 | |
| 7 | 该技能由 `orchestrator-agent` 在每次编译后调用,确保多模态证据链中的“页图”环节可靠、一致且可复现。 |
| 8 | |
| 9 | ## 适用场景 |
| 10 | |
| 11 | - 每次编译成功后,需生成页图供视觉 Agent 审查。 |
| 12 | - 手动触发视觉检查(如 `/check-visual` 命令)。 |
| 13 | - 修复前后对比验证。 |
| 14 | |
| 15 | ## 输入规范 |
| 16 | |
| 17 | | 输入项 | 来源 | 必需 | 说明 | |
| 18 | |--------|------|------|------| |
| 19 | | PDF 文件路径 | 编译输出 | ✅ | 通常为 `main.pdf` | |
| 20 | | 输出目录 | 配置或默认 | ✅ | 页图存放目录,默认为 `data/pages/` | |
| 21 | | DPI 参数 | 配置或调用方指定 | ✅ | 渲染分辨率,默认 220 DPI | |
| 22 | | 页码范围 | 调用方指定 | ⚠️ | 若为空,渲染全部页面 | |
| 23 | | 局部裁剪参数 | 调用方指定 | ⚠️ | 如 `{page: 5, bbox: [x,y,w,h]}`,用于表格/公式局部复查 | |
| 24 | |
| 25 | ## 输出规范 |
| 26 | |
| 27 | 本技能输出两份产物: |
| 28 | |
| 29 | 1. **页图文件集**:PNG 或 JPG 格式的逐页图片,命名规则为 `page_001.png`、`page_002.png` 等。 |
| 30 | 2. **渲染报告 JSON**: |
| 31 | |
| 32 | ```json |
| 33 | { |
| 34 | "skill": "visual-inspector", |
| 35 | "status": "success | partial | failed", |
| 36 | "pdf_path": "main.pdf", |
| 37 | "output_dir": "data/pages/", |
| 38 | "dpi": 220, |
| 39 | "pages_rendered": 9, |
| 40 | "page_files": [ |
| 41 | {"page": 1, "file": "data/pages/page_001.png", "width": 1700, "height": 2200}, |
| 42 | {"page": 2, "file": "data/pages/page_002.png", "width": 1700, "height": 2200} |
| 43 | ], |
| 44 | "cropped_regions": [ |
| 45 | { |
| 46 | "page": 5, |
| 47 | "object": "Table 2", |
| 48 | "file": "data/pages/page_005_table2.png", |
| 49 | "bbox": [100, 450, 800, 300] |
| 50 | } |
| 51 | ], |
| 52 | "errors": [] |
| 53 | } |
| 54 | ``` |
| 55 | |
| 56 | ## 渲染流程 |
| 57 | |
| 58 | ### 第一步:环境检查 |
| 59 | |
| 60 | 1. 确认 PDF 文件存在且可读。 |
| 61 | 2. 检查 Python 环境及所需依赖: |
| 62 | - `pdf2image` 库 |
| 63 | - Poppler 工具(`pdftoppm` 或 `pdftocairo`) |
| 64 | |
| 65 | 若 Poppler 未安装,根据操作系统提供安装指引: |
| 66 | |
| 67 | ```bash |
| 68 | # Debian/Ubuntu |
| 69 | sudo apt-get install poppler-utils |
| 70 | |
| 71 | # macOS |
| 72 | brew install poppler |
| 73 | |
| 74 | # Windows |
| 75 | # 下载 poppler 并添加到 PATH,或使用 conda install -c conda-forge poppler |
| 76 | ``` |
| 77 | |
| 78 | 3. 若依赖缺失,报告错误并终止,由上层 Agent 提示用户安装。 |
| 79 | |
| 80 | ### 第二步:执行渲染 |
| 81 | |
| 82 | **禁止**在用户 LaTeX 项目里假设存在 `scripts/render_pages.py`。页图渲染由 **PaperFit npm/CLI 包**提供,在论文项目根目录执行: |
| 83 | |
| 84 | ```bash |
| 85 | paperfit render <相对或绝对路径的.pdf> --output data/pages --dpi 220 |
| 86 | # 示例 |
| 87 | paperfit render main.pdf --dpi 300 |
| 88 | ``` |
| 89 | |
| 90 | 前提:`npm install -g paperfit-cli`(或等价全局安装),`paperfit` 在 `PATH` 中。输出目录 `--output` 相对于**当前工作目录**(一般为论文根目录)。 |
| 91 | |
| 92 | **其它包内 Python/Bash**(如 `parse_log.py`、`state_manager.py`)一律在论文根目录使用 **`paperfit run scripts/<文件名> [参数…]`**,勿在用户项目里假设存在同名 `scripts/`。 |
| 93 | |
| 94 | 若仅能通过 Python 调用包内脚本,先执行 `paperfit root` 得到包根目录,再: |
| 95 | |
| 96 | `python3 "$(paperfit root)/scripts/render_pages.py" main.pdf --dpi 220` |
| 97 | |
| 98 | (或直接调用 `pdf2image` 库,逻辑须与下方一致。)全局未装 `paperfit` 时可用:`npx paperfit-cli render …`。 |
| 99 | |
| 100 | #### 基础渲染命令(库级参考) |
| 101 | |
| 102 | ```python |
| 103 | from pdf2image import convert_from_path |
| 104 | |
| 105 | pages = convert_from_path( |
| 106 | pdf_path, |
| 107 | dpi=220, |
| 108 | fmt='png', |
| 109 | thread_count=2, |
| 110 | grayscale=False, |
| 111 | size=None |
| 112 | ) |
| 113 | |
| 114 | for i, page in enumerate(pages, start=1): |
| 115 | page.save(f"{output_dir}/page_{i:03d}.png", "PNG") |
| 116 | ``` |
| 117 | |
| 118 | #### 渲染参数建议 |
| 119 | |
| 120 | | 场景 | DPI | 说明 | |
| 121 | |------|-----|------| |
| 122 | | 整页常规检查 | 180-220 | 平衡清晰度与文件大小 | |
| 123 | | 表格/公式细节复查 | 260-320 | 需清晰辨认小字号或密集内容 | |
| 124 | | 局部裁剪复查 | 320 | 聚焦特定区域,可接受较大文件 | |
| 125 | |
| 126 | ### 第三步:局部区域裁剪(可选) |
| 127 | |
| 128 | 当 `layout-detective-agent` 需要对特定表格、公式或段落进行高精度复查时,可请求渲染局部区域。 |
| 129 | |
| 130 | 1. 首先以较高 DPI(如 320)渲染整页。 |
| 131 | 2. 根据调用方提供的边界框(bbox)裁剪图片。 |
| 132 | 3. 保存裁剪后的图片,命名包含对象标识(如 `page_005_table2.png`)。 |
| 133 | |
| 134 | 裁剪示例: |
| 135 | |
| 136 | ```python |
| 137 | from PIL import Image |
| 138 | |
| 139 | full_page = Image.open(f"{output_dir}/page_005.png") |
| 140 | cropped = full_page.crop((x1, y1, x2, y2)) |
| 141 | cropped.save(f"{output_dir}/page_005_table2.png") |
| 142 | ``` |
| 143 | |
| 144 | ### 第四步:生成渲染报告 |
| 145 | |
| 146 | 记录渲染结果,包括: |
| 147 | - 成功渲染的页数 |
| 148 | - 每页图片的路径和尺寸 |
| 149 | - 裁剪区域信息(如有) |
| 150 | - 错误或警告(如某些页渲染失败) |
| 151 | |
| 152 | ## 视觉检查清单 |
| 153 | |
| 154 | 以下清单供 `layout-detective-agent` 在逐页审查时参考。本技能不执行检查,仅提供指导框架。 |
| 155 | |
| 156 | ### 通用检查项(每页必查) |
| 157 | |
| 158 | - [ ] 页面整体信息密度是否均衡?是否存在大面积无意义留白? |
| 159 | - [ ] 页眉、页脚、页码是否完整且位置正确? |
| 160 | - [ ] 是否有内容伸出页边距或栏宽? |
| 161 | - [ ] 图表是否清晰可读,无模糊或锯齿? |
| 162 | - [ ] 段落末尾是否有孤行或短尾巴? |
| 163 | |
| 164 | ### 首页专项 |
| 165 | |
| 166 | - [ ] 标题、作者、机构信息是否完整,格式是否正确? |
| 167 | - [ ] 摘要段是否与模板风格一致? |
| 168 | - [ ] 是否有不必要的空白或过大的标题间距? |
| 169 | |
| 170 | ### 正文页专项 |
| 171 | |
| 172 | - [ ] 章节标题是否突出且一致? |
| 173 | - [ ] 图表与正文的衔接是否自然?图表是否在引用附近? |
| 174 | - [ ] 跨页段落是否合理断开? |
| 175 | - [ ] 双栏布局中左右栏高度是否平衡(尤其末页)? |
| 176 | - [ ] **(A5 必查)双栏每一页**:左右栏**分别**审视是否存在「栏内中段占栏高约 30%+、无图无表、无正文」的竖向空洞,且另一栏同期仍有连续正文(节标题下大块白缝是典型的漏检点) |
| 177 | - [ ] **(A5 可选)** 已安装 OpenCV 时运行 **`paperfit run scripts/detect_column_void.py data/pages -o data/column_void_report.json`**,将机器投影结果与肉眼结论交叉验证 |
| 178 | |
| 179 | ### 末页专项 |
| 180 | |
| 181 | - [ ] 参考文献是否完整,无被浮动体切断? |
| 182 | - [ ] 含 `Acknowledgements` / `References` / `Bibliography` 的页上是否出现正文图表标题或正文浮动体?若有,按硬失败处理。 |
| 183 | - [ ] 末页留白是否在可接受范围(<20%)? |
| 184 | - [ ] 若为双栏,左右栏底部是否对齐? |
| 185 | |
| 186 | ### 表格专项 |
| 187 | |
| 188 | - [ ] 表格宽度是否匹配栏宽?有无超宽或过窄? |
| 189 | - [ ] 列宽分配是否均衡?有无单列过宽挤压其他列? |
| 190 | - [ ] 表格字号是否与全篇其他表格一致? |
| 191 | - [ ] 表格线是否清晰?推荐使用 `booktabs` 风格。 |
| 192 | |
| 193 | ### 图片专项 |
| 194 | |
| 195 | - [ ] 图片是否清晰,分辨率足够? |
| 196 | - [ ] 图片宽度是否充分利用栏宽? |
| 197 | - [ ] 图片标题是否在图片下方(表格标题在上方)? |
| 198 | - [ ] 图片中的文字(坐标轴标签、图例)是否可读? |
| 199 | |
| 200 | ### 公式专项 |
| 201 | |
| 202 | - [ ] 公式是否超出栏宽? |
| 203 | - [ ] 多行公式是否在合理位置断行并对齐? |
| 204 | - [ ] 公式编号是否在正确位置(通常右侧)? |
| 205 | |
| 206 | ## 与其它 Agent 的协作 |
| 207 | |
| 208 | - **上游调用者**:`orchestrator-agent` 在编译成功后调用本技能。 |
| 209 | - **下游消费者**: |
| 210 | - `layout-detective-agent` 使用页图进行视觉缺陷检测。 |
| 211 | - `quality-gatekeeper-agent` 使用页图进行最终验收对比。 |
| 212 | - `code-surgeon-agent` 在修复后可能请求局部页图验证特定修改。 |
| 213 | |
| 214 | ## 异常处理 |
| 215 | |
| 216 | | 异常情况 | 处理方式 | |
| 217 | |----------|----------| |
| 218 | | Poppler 未安装 | 返回明确错误信息,包含安装指引 | |
| 219 | | PDF 文件损坏 | 报告错误,请求重新编译 | |
| 220 | | 部分页渲染失败 | 记录失败页码,尽可能渲染其余页,状态标记为 `partial` | |
| 221 | | 磁盘空间不足 | 报告错误,清理临时目录或提示用户释放空间 | |
| 222 | |
| 223 | ## 性能优化建议 |
| 224 | |
| 225 | - 对于大型 PDF(>20 页),可考虑仅渲染指定页码范围,避免不必要开销。 |
| 226 | - 缓存机制:若 PDF 文件未修改且渲染参数相同,可复用已有页图。通过比较 PDF 文件哈希和渲染参数实现。 |
| 227 | |
| 228 | ## 注意事项 |
| 229 | |
| 230 | - **页图是视觉验收的唯一依据**:严禁仅凭 PDF 文本抽取或日志判断排版质量。 |
| 231 | - **保持页码对应**:页图文件名必须明确反映页码,便于缺陷定位。 |
| 232 | - **高 DPI 不宜滥用**:过高 DPI 会导致图片体积庞大,影响传 |