Lossless Changelog
component

Image-Based PDF Support: Batch Processing with Claude Vision API

Complete implementation of image-based PDF deck analysis using Claude's Vision API with intelligent batch processing. This solves the recurring issue of Docsend-exported decks that contain only images with no extractable text.

Changelog - 2025-11-21

Image-Based PDF Support: Batch Processing with Claude Vision API

Overview

Complete implementation of image-based PDF deck analysis using Claude's Vision API with intelligent batch processing. This solves the recurring issue of Docsend-exported decks that contain only images with no extractable text.


Breaking Changes

None - This is a backward-compatible addition to the deck analyst agent.


New Features

Deck Analyst Agent (src/agents/deck_analyst.py)

Image-Based PDF Detection

  • NEW: Automatic detection of image-based PDFs via text extraction threshold

  • Threshold: 1000 characters (accounts for page headers on image PDFs)

  • Text-based decks have substantially more extractable content

  • Falls back to vision API when text extraction is minimal

Batch Processing System

  • NEW: analyze_pdf_with_vision() function for image-based PDFs

  • NEW: Processes decks in batches of 5 slides to avoid API payload limits

  • NEW: Intelligent merging of results from all batches

  • NEW: Per-batch progress logging with batch numbers (e.g., "batch 1/5")

  • NEW: Graceful error handling - continues with remaining batches if one fails

Image Processing Pipeline

  • NEW: PyMuPDF (fitz) integration for page rendering

  • NEW: 0.5x scale rendering to reduce payload size while maintaining readability

  • NEW: PIL (Pillow) integration for JPEG compression

  • NEW: JPEG quality: 85 with optimization enabled

  • NEW: Base64 encoding for Claude Messages API

Batch Merging Logic

  • NEW: Intelligent data consolidation from multiple batches

  • NEW: String fields: Uses first non-"Not mentioned" value

  • NEW: List fields: Appends unique items (team_members, traction_metrics, etc.)

  • NEW: Dict fields: Merges non-"Not mentioned" values (market_size TAM/SAM/SOM)

  • NEW: Final page count from PDF document, not individual batch reports

Artifact Saving

  • FIXED: Vision-based analysis now saves deck analysis artifacts

  • FIXED: Added missing save_deck_analysis_artifacts() call in vision path

  • FIXED: Matches artifact saving behavior of text-based analysis


Bug Fixes

Socials Enrichment Agent (src/agents/socials_enrichment.py)

Team Member Extraction

  • FIXED: Now handles both structured and string format team data

  • FIXED: Prefers structured company.founders format (dict with name/title/background)

  • FIXED: Falls back to parsing string format from team.founders

  • FIXED: Improved regex parsing for name and role extraction from strings

  • FIXED: Filters out "Data not available" entries from key_hires

  • FIXED: Eliminates duplicate variable definitions


Technical Details

Vision API Integration

Batch Processing Flow

  1. Open PDF with PyMuPDF

  2. Calculate total batches (ceil(page_count / 5))

  3. For each batch:

    • Extract 5 pages (or remaining pages for final batch)

    • Render each page at 0.5x scale

    • Convert to PIL Image

    • Compress as JPEG (quality=85, optimize=True)

    • Encode as base64

    • Send to Claude Vision API

    • Parse JSON response (with markdown code block fallback)

    • Collect batch results

  4. Merge all batch results intelligently

  5. Save final consolidated analysis

API Payload Structure

PYTHON
{
  "model": "claude-sonnet-4-5-20250929",
  "max_tokens": 4000,
  "messages": [{
    "role": "user",
    "content": [
      {"type": "image", "source": {...}},  # 5 images
      {"type": "image", "source": {...}},
      {"type": "image", "source": {...}},
      {"type": "image", "source": {...}},
      {"type": "image", "source": {...}},
      {"type": "text", "text": "..."}     # Analysis prompt
    ]
  }]
}

Merge Algorithm Example

PYTHON
# Batch 1: company_name="RubyData", team_members=[]
# Batch 2: company_name="Not mentioned", team_members=[Alice, Bob]
# Batch 3: company_name="Not mentioned", team_members=[Carol, Dan, Eve]
# Batch 4: company_name="Not mentioned", team_members=[]
# Batch 5: company_name="Not mentioned", team_members=[]
#
# Merged: company_name="RubyData", team_members=[Alice, Bob, Carol, Dan, Eve]

Error Handling

Robust Failure Recovery

  • Individual batch failures don't crash entire pipeline

  • Continues processing remaining batches

  • Collects all successful batch results

  • Only fails if zero batches succeed

  • Per-batch error logging with specific batch number


Dependencies

New Python Packages

  • PyMuPDF (fitz) - PDF page rendering

  • Pillow (PIL) - Image compression and format conversion

  • anthropic - Direct Messages API client (was already available)

Existing Dependencies

  • base64 (stdlib) - Image encoding

  • io.BytesIO (stdlib) - In-memory image buffer

  • os (stdlib) - Environment variable access


Performance Improvements

Before

  • Image-based PDFs failed completely (no text to extract)

  • Docsend exports were unusable

  • Manual PDF text conversion required

  • ~5 decks rejected due to image-only format

After

  • All 22 slides analyzed successfully in batches

  • Total analysis time: ~60-90 seconds for 22-page deck

  • Per-batch time: ~12-18 seconds (5 slides)

  • Zero timeouts with batch size of 5

  • Comprehensive data extraction: 9 team members, 23 traction metrics from RubyData deck


Testing

Test Case: RubyData Pitch Deck

  • Format: Docsend export (image-based PDF)

  • Pages: 22 slides

  • File size: 2.2 MB

  • Text extraction: Only 386 characters (page headers)

  • Batch processing: 5 batches (5+5+5+5+2 slides)

  • Results:

    • Batch 1 (slides 1-5): 4 traction metrics

    • Batch 2 (slides 6-10): 2 team members, 6 traction metrics

    • Batch 3 (slides 11-15): 7 team members, 5 traction metrics

    • Batch 4 (slides 16-20): 6 traction metrics

    • Batch 5 (slides 21-22): 2 traction metrics

    • Merged total: 9 team members, 23 traction metrics

  • Artifacts saved: ✓ 0-deck-analysis.json, ✓ 0-deck-analysis.md


Files Changed

Core Agents

  • src/agents/deck_analyst.py - Batch processing implementation

  • src/agents/socials_enrichment.py - Team data extraction fix

Documentation

  • .claude/settings.local.json - Tool permissions (minor)

  • CASUAL_USER_GUIDE.md - Updated deck support notes

  • context-vigilance/Improving-Memo-Output.md - Context updates

  • context-vigilance/Format-Memo-According-to-Template-Input.md - NEW file

New Assets

  • templates/brand-configs/brand-avalanche-config.yaml - Avalanche branding

  • templates/fonts/Bison/ - Bison font family for branding

  • data/RubyData.json - RubyData company config

  • data/WorkBack.json - WorkBack company config


Usage Examples

Image-Based PDF (Automatic Detection)

BASH
# PDF with minimal extractable text - automatically uses vision API
python -m src.main "RubyData"

Console Output:

Extracting text from PDF deck (deckFor__RubyData.pdf)...
Extracted 386 characters from deck
⚠️  Minimal text extracted - PDF appears to be image-based
Using Claude's PDF vision to analyze deck...
Extracting images from PDF...
Processing slides 1-5 (batch 1/5)...
Sending batch 1 (5 slides) to Claude...
✓ Batch 1 complete, parsing results...
✓ Batch 1: Parsed JSON from code block
✓ Batch 1: Found 0 team members, 4 traction metrics
Processing slides 6-10 (batch 2/5)...
...
Merging 5 batch analyses...
✓ Merged analysis complete: 22 pages analyzed
✓ Final totals: 9 team members, 23 traction metrics

Migration Notes

For Future Development

  • Batch size of 5 is optimal for API limits and response times

  • Can adjust batch_size constant if API limits change

  • Merge logic handles missing/incomplete data gracefully

  • Vision API path now has feature parity with text-based path

API Considerations

  • Vision API calls are more expensive than text processing

  • Each batch costs ~1 image API call worth of tokens

  • 22-page deck = 5 API calls (vs 1 call for text-based)

  • Consider cost when processing large decks


Known Issues

Image Quality

  • 0.5x scale rendering may reduce readability of very small text

  • JPEG compression (quality=85) balances size vs clarity

  • Very complex slides may need manual review

Batch Size Limitation

  • Maximum tested batch size: 5 slides

  • Larger batches may exceed API payload limits

  • Smaller batches increase API calls and cost

Text Detection Threshold

  • 1000 character threshold works for most decks

  • Edge case: Very sparse text-based decks may trigger vision API unnecessarily

  • Can adjust threshold in deck_analyst_agent() function


Future Enhancements

Potential Improvements

  • Adaptive batch size based on slide complexity/size

  • OCR fallback for hybrid text+image PDFs

  • Parallel batch processing (currently sequential)

  • Configurable image quality and scale factors

  • Slide thumbnail generation for review

  • Page range selection for partial deck analysis


Contributors

  • Batch processing architecture and implementation

  • PyMuPDF and PIL integration

  • Intelligent merge algorithm

  • Error handling and progress logging

  • Socials enrichment team data extraction fix


References

  • Issue: "Fifth fucking deck" unable to analyze (Docsend exports)

  • Issue: Deck analysis artifacts not saved for vision-based analysis

  • Issue: Team member extraction failing for structured founder data

  • Anthropic Vision API documentation

  • PyMuPDF documentation for image rendering