Skip to content

feat: preserve embedded images as assets + serve to multimodal agents (not lossy text extraction) #76

Description

@rajnavakoti

Description

Many source docs (Confluence, incident/architecture docs) embed diagrams/images that hold high-value knowledge — especially architecture diagrams, which encode system relationships (the #1 context class for incident resolution). Current text-only extraction drops them.

Primary approach (preferred): preserve, don't rewrite. Instead of "read the diagram and convert it to entities" (interpret-at-write-time, lossy), extract the raw images as-is, store them as assets in the block, have the relevant entity point to the image path, and serve the image to the multimodal consuming agent on-demand. The agent reads the original diagram at query time — zero information loss, interpretation deferred to the consumer, and it fits cache/router + progressive disclosure (#75).

Vision models are used only lightly — to generate a short caption/alt-text for retrievability, and (optionally) to classify ambiguous survivors — not to replace the image.

Why preserve-and-serve beats vision-rewrite

  • Zero loss: the original diagram survives, not a lossy text summary.
  • Same diagram interpreted per-question by the agent, not baked into one write-time interpretation.
  • Cheaper/deterministic: pulling images from a PDF/PPTX is mechanical, no vision API at extraction.
  • Consuming agents are multimodal anyway.

Extraction mechanics (per format — all mechanical, no AI)

  • PDF: PyMuPDF (page.get_images() / extract_image()) or pdfimages (poppler).
  • DOCX / PPTX: ZIP archives — images in word/media/ and ppt/media/.
  • HTML / Confluence export: <img> tags — linked (download) or base64-embedded (decode).
  • Wrinkle: raster images extract cleanly; vector diagrams (native PPTX shapes, PDF vector paths) have no image stream — render the page/region to a raster instead.

MCP transport

Filtering — codified-first, vision optional

Decision of which images to keep is codified first, not vision-driven:

  1. Extract ALL images mechanically (no decision yet).
  2. Dedup by hash + frequency — an image repeated on most/all pages is chrome (e.g. a per-page logo): identical bytes → hash-match → high frequency → drop. Appears on only 1–2 pages → content → keep. Frequency is the discriminator. No vision needed — this is how the per-page-logo case is handled.
  3. Size threshold — drop tiny images (icons, bullets).
  4. Vision only as an optional light second pass on the few ambiguous survivors — classify "diagram/screenshot vs decorative." Runs on a handful, not every image.

Acceptance Criteria

  • Extract embedded images from source docs (PDF, PPTX, DOCX, HTML, Confluence export) as asset files stored in the block; render vector diagrams to raster
  • Relevant entity references the image path(s)
  • Generate a short text hook (caption/alt-text) per kept image for retrievability
  • Codified filter: dedup-by-hash-and-frequency (drops per-page logos/chrome) + size threshold, BEFORE any vision call
  • Optional vision classify only on ambiguous survivors
  • Images served to the consuming agent on-demand (via feat: richer MCP tool surface — get_full_entity + progressive disclosure for agents #75 tools), not always-injected
  • Tests: a PDF with N content images + a repeated per-page logo yields N asset files (logo dropped) + entity pointers + retrievable hooks

Out of Scope

  • Lossy vision-to-text rewrite as the primary mechanism (vision used only for caption hook + ambiguous classify)
  • OCR-only text recovery

Metadata

Metadata

Assignees

No one assigned

    Labels

    pipelineExtraction pipeline

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions