The problem
A picdump is easy to make and slow to sort. Picking the best shots out of it is the chore.
What I decided
Build it inside a chat app people already use. There is no new app to install and nothing new to learn: you send the pictures to a Telegram bot.
Score every photo for the platform it is going to, then caption the picks, so what comes back is ready to post rather than a sorted folder.
How it works
- Send your picdump.
- It scores each photo out of 10 on clarity, face/scenery visibility, resolution and other factors.
- It returns the top 3 with scores (eval, tuned to the target platform).
- It captions each of the 3 and returns the final pick.
How it’s built
- Step in the code
- LLM or external API
- Data store
- Only some turns, or offline
- Step in the code
- LLM or external API
- Data store
- Only some turns, or offline
The same diagram, as a list
- A user in Telegram sends /start to the bot (python-telegram-bot handlers in curator/main.py and curator/bot/agent.py).
- They pick the target platform(s): Instagram, Facebook, Tinder, Bumble, Hinge or LinkedIn.
- The bot parses the intent: platforms, vibe and constraints (curator/session/intent.py).
- It receives the picdump into a session store with a timeout (curator/session/).
- Tier 1, local: technical checks for resolution (Pillow), blur (OpenCV Laplacian), near-duplicates (pHash) and faces (Haar).
- Tier 2, local: platform fit, with weights from config/platform_weights.yml, a face gate for dating apps and a LinkedIn suitability flag.
- Tier 3: vision scoring of composition, lighting, subject and mood through Groq (Llama 4 Scout vision). Without a key, it is skipped and the deterministic tiers stand.
- Each photo gets a composite score out of 10 (grading/composite.py).
- The photos are ranked for the target platform and the top 3 are kept (ranking_agent.rank).
- Each pick’s scene is described through Groq vision, or a BLIP-2 fallback, local or on Hugging Face (scene.py).
- Caption variants are written per photo: short, long and haiku, no hashtags, through Groq (Llama 3.3 70B), with prompts in config/prompts.yml.
- Scored cards with captions go back to the chat (ranking/card.py, presentation.py).
- The user picks the photo and caption, and gets a final card (ranking/selection.py).
- At any point /next, /platform, /retry and /shorter re-rank or re-caption.
- Python, deployed as a worker on Railway.
The result
A working Telegram bot that scores, ranks and captions a picdump. The source is public on GitHub.