From fffe483c028cfcbdbcc8888635c19a801dec51e4 Mon Sep 17 00:00:00 2001 From: Chris Coutinho Date: Sat, 22 Nov 2025 02:42:28 +0100 Subject: [PATCH] fix: Centralize PDF processing and generate separate images per chunk MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously, pymupdf4llm.to_markdown() was called twice - once in PyMuPDFProcessor during indexing and again in PDFHighlighter during visualization. Different image path lengths caused different character offsets, leading to highlighted pages not matching their chunks. Also fixed issue where all chunks on the same page showed all highlights instead of just their own highlight. Now restores original page contents between chunks using xref stream caching. Changes: - Add PDFHighlighter class requiring pre-computed page_boundaries and full_text from document processor (no fallback extraction) - Pass pre-computed data from processor to highlighter - Extract page-relative portion of chunk text for cross-page chunks - Add bounding box highlighting using text anchor search - Run highlight generation in parallel with embedding/BM25 - Cache and restore page contents to isolate highlights per chunk Results: Highlighting success rate improved from 51% to 95% (121/128). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .../auth/static/vector-viz.css | 27 + .../auth/templates/vector_viz.html | 14 + nextcloud_mcp_server/auth/viz_routes.py | 75 +- .../document_processors/pymupdf.py | 4 +- .../embedding/bm25_provider.py | 2 +- .../search/pdf_highlighter.py | 824 ++++++++++++++++++ .../vector/document_chunker.py | 2 +- nextcloud_mcp_server/vector/processor.py | 376 +++++--- 8 files changed, 1211 insertions(+), 113 deletions(-) create mode 100644 nextcloud_mcp_server/search/pdf_highlighter.py diff --git a/nextcloud_mcp_server/auth/static/vector-viz.css b/nextcloud_mcp_server/auth/static/vector-viz.css index 3e9398b..9d94d8c 100644 --- a/nextcloud_mcp_server/auth/static/vector-viz.css +++ b/nextcloud_mcp_server/auth/static/vector-viz.css @@ -190,3 +190,30 @@ color: var(--color-text-maxcontrast); font-style: italic; } + +/* PDF highlighted image styles */ +.chunk-image-container { + margin-bottom: 16px; + border: 1px solid var(--color-border); + border-radius: var(--border-radius); + overflow: hidden; + background: #fff; +} +.chunk-image-header { + background: var(--color-background-dark); + padding: 8px 12px; + font-size: 12px; + font-weight: 500; + color: var(--color-text-maxcontrast); + border-bottom: 1px solid var(--color-border); + font-family: var(--font-face); +} +.chunk-highlighted-image { + display: block; + max-width: 100%; + height: auto; + cursor: zoom-in; +} +.chunk-highlighted-image:hover { + opacity: 0.95; +} diff --git a/nextcloud_mcp_server/auth/templates/vector_viz.html b/nextcloud_mcp_server/auth/templates/vector_viz.html index de91f2f..c36a0eb 100644 --- a/nextcloud_mcp_server/auth/templates/vector_viz.html +++ b/nextcloud_mcp_server/auth/templates/vector_viz.html @@ -147,6 +147,20 @@