06: Add API service for the-mcculloughs.org integration#6
Merged
Conversation
- pydantic-settings for environment-based config - httpx for async HTTP client to the-mcculloughs.org API - pytest-httpx for testing HTTP calls - Add CLI entry point for indexatron command Co-Authored-By: Stephen McCullough <stephen@swm.cc>
- pydantic-settings for type-safe config
- Load from .env.{INDEXATRON_ENV} files
- Support debug mode, API settings, Ollama config
- Auto-create download directory
Co-Authored-By: Stephen McCullough <stephen@swm.cc>
- Debug HTTP requests/responses with masked secrets - Debug LLaVA prompts and responses - Debug embedding generation with previews - Pretty config display in debug mode Co-Authored-By: Stephen McCullough <stephen@swm.cc>
- fetch_pending_uploads(): Get photos needing analysis - download_image(): Download images to temp dir - post_analysis(): Submit analysis + embedding - test_connection(): Verify API key works - Full debug logging support Co-Authored-By: Stephen McCullough <stephen@swm.cc>
- config/.env.example with all options documented - Update .gitignore for env files Co-Authored-By: Stephen McCullough <stephen@swm.cc>
IndexatronService: - Fetches pending uploads from API - Downloads images to temp directory - Analyzes with LLaVA, generates embeddings - Posts results back to API - Progress bar with rich output - Connection verification for API and Ollama Co-Authored-By: Stephen McCullough <stephen@swm.cc>
Commands: - run: Process pending uploads (default) - test: Verify API and Ollama connections - config: Show current configuration Options: - --debug: Enable verbose output - --limit N: Process max N uploads - --env: Override environment - --dry-run: Fetch but don't process Co-Authored-By: Stephen McCullough <stephen@swm.cc>
Co-Authored-By: Stephen McCullough <stephen@swm.cc>
Scripts wrapper for development use. Co-Authored-By: Stephen McCullough <stephen@swm.cc>
pydantic-settings looks for env files in the working directory. Co-Authored-By: Stephen McCullough <stephen@swm.cc>
Co-Authored-By: Stephen McCullough <stephen@swm.cc>
Rails Active Storage uses redirects to serve files. Co-Authored-By: Stephen McCullough <stephen@swm.cc>
LLaVA 7b crashes on WebP images. Convert to JPG using Pillow after download. Also improved extension detection using Content-Type header instead of URL. Co-Authored-By: Stephen McCullough <stephen@swm.cc>
- Improved prompt to ask for hierarchical tags (puppy → dog → pet) - Post-process categories with CATEGORY_HIERARCHY mapping - Covers pets, holidays, celebrations, family members Co-Authored-By: Stephen McCullough <stephen@swm.cc>
LLaVA sometimes returns nested lists for categories. Flatten before processing. Co-Authored-By: Stephen McCullough <stephen@swm.cc>
- Update default vision_model to llama3.2-vision in config - Update PhotoAnalysis model default - Make PhotoAnalyzer use settings.vision_model dynamically - Pass actual model used to analysis results - Fix linting issues (bare except, line length, import order) Llama 3.2 Vision provides better era detection for family photos spanning from 1920s to present. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Build analysis prompt with title, caption, and date_taken context - AI can now identify people by name from captions (e.g., "John's wedding") - Confirm/refine era estimates when actual date is known - Extract location hints from metadata - Add name field to PersonInfo model for identified people - Display context in console output during analysis This makes the AI much smarter for family photos with existing metadata. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Vision models don't need full resolution to understand photo content. Resizing to 1024px max dimension before sending to Ollama significantly reduces inference time with no meaningful loss of analysis quality. Also converts all images to JPG for better model compatibility. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add blocklist for inappropriate terms (grooming, beauty, etc.) - Sanitize descriptions to remove inappropriate phrases - Detect and handle repetition loops in model output - Limit categories to 20 max to prevent runaway repetition - Filter blocked terms from categories Llama 3.2 Vision was producing inappropriate descriptions and endless category loops for family photos. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Shows what title/caption/date is being used for AI context. Helps debug when metadata isn't being picked up. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Extract names from caption/title and tell model to use them: "IMPORTANT: This photo includes Emily. Use this name..." - Extract decade from date and force high confidence: "IMPORTANT: This photo is from 2015 (2010s). Use this era." - Simplified JSON schema to reduce repetition loops - Added explicit "Max 10 categories. No repetition." rule Should make the model actually use the metadata instead of ignoring it. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Gallery names like "Moffett Family" provide context about who's in photos. Now extracts names from gallery name + title + caption combined. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- New CLI option: python scripts/run.py --shortcode ABC123 - Fetches single upload via new API endpoint - Uses gallery_description for additional AI context - Useful for reprocessing photos after improving prompts Example: python scripts/run.py -s M3JnZV --debug Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Maps family nicknames to real names so AI identifies people correctly:
- "Wee Mamie" / "Mamie" → Isobel McCullough (Mum)
- "The Oul Man" / "The Oul Fella" → Edmund McCullough (Dad)
- "The Leech" → Christina McCullough (sister)
- "Asshole" / "The Bro" → John McCullough (brother)
When caption says "Mamie at Christmas", AI will output:
"people": [{"name": "Isobel McCullough", ...}]
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When we have the real date_taken, don't trust the AI's era estimate. Override it with the actual decade from the date, with "high" confidence and reasoning that explains it came from the actual date. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Llama 3.2 Vision was producing garbage output (repetition loops, inappropriate content). LLaVA 7b is more reliable for this use case. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Shows a spinner with model name while waiting for Ollama response, instead of just hanging with HTTP trace messages. Also shows elapsed time when response completes. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Complete AI photo analysis service that integrates with the-mcculloughs.org:
Features
date_takeninstead of AI guessingCLI Usage
Family Nickname Mappings
Configuration
# .env.development INDEXATRON_API_KEY=sk_xxx INDEXATRON_API_BASE_URL=http://localhost:3000 INDEXATRON_VISION_MODEL=llava:7b INDEXATRON_DEBUG=trueTest plan
python scripts/run.py testpasses--shortcode🤖 Generated with Claude Code