Postmortem: When the PDF Pipeline Needed a Manual Override
TLDR
Our PDF extraction tool initially relied on five global threshold sliders (row band tolerance, paragraph gap, column gap minimum, stream confidence, confidence filter) to allow users to tweak document parsing. In practice, users spent minutes "slider-hunting", adjusting global settings only to find that fixing one page broke another. We deprecated slider-only correction and implemented a direct canvas spatial region editor, reducing document correction time from minutes to seconds.| Incident Aspect | Initial Slider-Based UX | Refactored Canvas Region Editor |
|---|---|---|
| Correction Mechanism | Adjust 5 global numeric threshold sliders | Direct mouse manipulation on canvas |
| Scope of Modification | Document-wide (All pages affected) | Single target page & region only |
| User Correction Time | 3 to 5 minutes of trial-and-error slider hunting | 5 to 10 seconds (Point, click, resize) |
Problem statement: the friction of slider-hunting
Our document processing application provided automatic extraction powered by five configurable threshold sliders.
When an extraction misedited a complex page (e.g., merging a table with body copy), users had to guess which slider to adjust.
Users adjusted sliders, clicked "Re-extract", inspected the canvas, and repeated the process. Often, no single global threshold value satisfied all pages simultaneously, leading to user frustration and support tickets.
Technical failure mode: the global parameter abstraction leak
Global thresholds fail when document errors are local:
- Conflicting Demands: Page 2 required a wide column gap threshold (
20px), while Page 5 required a narrow threshold (10px). - Structural Misclassification: A text block located adjacent to a table was absorbed into the table due to local proximity. No global numeric slider could fix the local proximity error without breaking valid tables elsewhere.
The fix & architecture: direct spatial manipulation layer
We retained automatic detection as the default first pass, but introduced an interactive canvas spatial editor for local corrections:
// REFACTORED: Interactive Canvas Overlay Handler
export class CanvasRegionEditor {
constructor(canvasElement, pageNum) {
this.canvas = canvasElement;
this.pageNum = pageNum;
this.selectedRegionId = null;
this.bindEvents();
}
bindEvents() { // 1. Direct Selection & Hotkey Reclassification window.addEventListener('keydown', (e) => { if (!this.selectedRegionId) return;
if (e.key === 't' || e.key === 'T') { this.reclassifySelectedRegion('LATTICE_TABLE'); } else if (e.key === 'p' || e.key === 'P') { this.reclassifySelectedRegion('PARAGRAPH'); } else if (e.key === 'Delete' || e.key === 'Backspace') { this.suppressSelectedRegion(); } });
// 2. Eight-Handle Mouse Resize & Drag Translation this.canvas.addEventListener('mousedown', (e) => this.handlePointerDown(e)); this.canvas.addEventListener('mousemove', (e) => this.handlePointerMove(e)); }
reclassifySelectedRegion(newType) { updateLocalPageOverride(this.pageNum, this.selectedRegionId, { type: newType, algorithm: 'user-override' }); triggerFastPageReassembly(this.pageNum); } }
Direct manipulation capabilities
- Resize & Translate: Drag eight bounding box handles or translate region centers directly.
- Hotkey Reclassification: Press
Tto reclassify as Table,Pfor Paragraph,Hfor Heading. - Region Suppression: Press
Deleteto exclude unwanted regions from extraction. - Manual Column Split Lines: Click to place vertical split lines that override automatic column detection.
Rule of thumb: Use global thresholds for automated first-pass extraction, and provide direct spatial canvas editing tools for local edge-case corrections.