Qualche tempo fa ho scritto di aver costruito un selezionatore AI per PhotoPrism, un piccolo strumento che usa modelli locali per scegliere le foto migliori e creare album automatici. Il post originale raccontava il primo prototipo: ranking estetico puro, clustering semantico, e una CLI minimale.

Da allora ho lavorato molto sul progetto, aggiungendo funzionalità, migliorando la stabilità e rendendo tutto più facile da usare.

Da Ollama a Ollama e LM Studio

Una delle richiesta più comuni che ho visto in giro per progetti simili è la possibilità di usare backend diversi. Nel primo post parlavo solo di Ollama come backend AI. Ora lo strumento supporta anche LM Studio, con API OpenAI-compatibili.

Che significa, in pratica? Se desideri avere più controllo e scelta di modelli, puoi usare LM Studio senza cambiare nulla nel flusso di lavoro. Nell’interfaccia web e nella CLI il passaggio è trasparente: basta cambiare il backend nei parametri e puntare all’URL del server corretto.

Deduplicazione tempo e spazio, non solo semantica

Nel post originale parlavo di clustering semantico: le foto venivano raggruppate per similarità di descrizione e poi selezionate a rotazione per evitare ripetizioni. Funzionava, ma a volte finivo comunque con foto troppo simili, scattate nello stesso istante e nella stessa posizione.

Ho aggiunto un secondo livello di deduplicazione temporale e geografica. Dopo la selezione iniziale, lo strumento rimuove automaticamente le foto che sono entro 30 secondi e 100 metri l’una dall’altra, tenendo sempre quella con il ranking estetico migliore.

Il risultato è un album più vario, con meno “serie di foto quasi identiche” e più momenti distinti.

Logging professionale con Logback

Il primo prototipo scriveva log in modo un po’ artigianale, spesso su stdout o in file senza gestione. Per un tool che può girare automaticamente su grandi archivi, serve qualcosa di più robusto.

Ora il progetto usa Logback con:

  • logging su file (logs/photoprism-ai.log)
  • rotazione giornaliera
  • retention di 7 giorni
  • nessun output su stdout, tranne barre di progresso essenziali

Nel log trovi:

  • prompt di clustering (DEBUG)
  • rimozioni per dedup temporale/spaziale (INFO)
  • nomi dei cluster finali (INFO)

Prompt emozionale e descrizioni più ricche

Uno dei problemi iniziali era che il modello multimodale produceva descrizioni troppo brevi o generiche, il che rendeva il clustering meno efficace.

Ho:

  • aumentato la descrizione a 30 parole per ogni foto
  • introdotto un prompt emozionale più ricco, per spingere il modello a valutare anche composizione, originalità e “atmosfera”, non solo要素 tecnici

Il clustering ne beneficia molto: le categorie sono più pulite e coerenti.

Batch, thread e performance

Nel primo post parlavo di timeout e latenza come principali colli di bottiglia. Ho fatto diversi affini:

  • batch da 30 richieste per il clustering
  • 3 thread per il processing parallelo
  • caching più intelligente di takenAt, titolo, coordinate e luogo
  • retry automatico per le chiamate AI in caso di errore

Questi cambiamenti hanno reso il tool più stabile e veloce, soprattutto su archivi grandi.

Barra di progresso e Web UI

La CLI funziona bene, ma per molti utenti un’interfaccia visuale è più comoda. Ho quindi sviluppato una Web UI leggera con:

  • Javalin come server embedded
  • HTMX per dinamicità senza scrivere JavaScript complesso
  • una barra di progresso per il clustering, con conteggio batch in tempo reale

La Web UI permette di:

  • scegliere mese singolo o anno intero
  • specificare quante foto selezionare
  • personalizzare il prompt di valutazione
  • scegliere il nome dell’album

Il form è semplice, ma copre tutti i casi d’uso principali.

Modalità anno intero

Nel post originale parlavo solo di selezione per mese. Ora c’è anche una modalità anno intero: lo strumento processa tutti i 12 mesi in sequenza, accumulando le foto migliori di ogni mese in un unico album annuale.

È utile per creare album tipo “Best of 2025” o “Viaggi 2025” senza dover lanciare manualmente 12 selezioni separate.

Cache arricchita e pool temporaneo

La cache (ai-cache.json) ora conserva per ogni foto:

  • score estetico
  • descrizione generata dall’AI
  • cluster assegnato
  • titolo, coordinate, takenAt, placeLabel, placeCity, placeState, placeCountry

Il pool temporaneo pre-dedup viene salvato in {albumName}.json, utile per debug e analisi.

CLI più flessibile

Oltre alla Web UI, la CLI è più potente:

bash# Mese singolo
java -jar target/photoprism-ai-curator-1.0.1.jar \
  --no-web --mode month --month 1 --year 2026 \
  --count 20 --album "Mia Selezione"

# Anno intero
java -jar target/photoprism-ai-curator-1.0.1.jar \
  --no-web --mode year --year 2026 \
  --count 20 --album "Best of 2026"

# Prompt personalizzato
java -jar target/photoprism-ai-curator-1.0.1.jar \
  --no-web --mode month --month 1 --year 2026 \
  --count 20 \
  --prompt "Rate composition and originality"

Sono disponibili flag per:

  • percorso del config file
  • forzatura modalità CLI
  • modalità mese/anno
  • mese, anno, conteggio foto
  • nome album
  • prompt di valutazione

Struttura del progetto

Il progetto è ora più maturo e meglio organizzato:

  • AiBackend come interfaccia comune per rating e clustering
  • OllamaClient e LmStudioClient come implementazioni separate
  • PhotoFetcher, AISelector, AlbumManager, ImageHasher come servizi puliti
  • WebServer con Javalin + HTMX
  • JobContext per lo stato thread-safe dei job

Tutto il codice è in Java 17+, con Maven, JUnit 5 e Mockito per i test.

Perché questi aggiornamenti contano

Per me, il punto non è solo automatizzare una classifica di bellezza. Il vero valore sta nel:

  • combinare giudizio estetico, varietà narrativa e vincoli pratici
  • gestire cache, timeout e costi computazionali in modo intelligente
  • offrire un’alternativa locale e controllabile ai servizi cloud per la selezione foto

Con LM Studio, dedup tempo/spazio, Logback, Web UI e modalità anno intero, ritengo che il progetto sia oggi molto più pronto per l’uso quotidiano.


Tutti i dettagli tecnici, commit e modifiche sono disponibili su GitHub.
La commit history è qui: https://github.com/b0sh-net/photoprism-ai-curator/commits/master/.