Skip to content

Feat: Best shot detection#57

Merged
duartebarbosadev merged 10 commits intomainfrom
feat-best-shot-detection
Nov 5, 2025
Merged

Feat: Best shot detection#57
duartebarbosadev merged 10 commits intomainfrom
feat-best-shot-detection

Conversation

@duartebarbosadev
Copy link
Copy Markdown
Owner

This pull request introduces advanced AI-powered photo ranking and rating features to PhotoSort, including both a local multi-model pipeline and support for OpenAI-compatible vision models. It also adds configuration options for these engines, updates documentation and keyboard shortcuts, and includes new utilities for model dependency checking.

AI Ranking & Rating Features

  • Added support for AI-powered best-shot ranking and star rating of photos, with the option to use either a local multi-model pipeline or an OpenAI-compatible vision model. These features are now documented in README.md. [1] [2]
  • Introduced src/core/ai/__init__.py to expose the experimental best-photo selector, and added a model dependency checker in src/core/ai/model_checker.py to verify required models are present before running best-shot analysis. [1] [2]

Settings & Configuration

  • Added new configuration keys and getter/setter functions in src/core/app_settings.py for selecting the best-shot engine, batch size, and OpenAI API parameters (API key, model, base URL, prompts, etc.), allowing users to persist and manage these settings via the preferences dialog. [1] [2] [3]
  • Updated default clustering parameters and batch sizes for improved similarity analysis and AI ranking performance.

Documentation & Usability

  • Expanded the README.md to include detailed instructions for setting up both local and OpenAI-based AI engines, including model download links and usage notes for new features.
  • Updated the keyboard shortcut map in assets/keyboard-layout.html to label new AI-related actions (Ctrl+A for AI Rate Images, Ctrl+B/Alt+B for Analyze Best Shots) for improved discoverability. [1] [2] [3]

Minor Improvements

  • Minor formatting change in the warning section of README.md for clarity.
  • Removed unnecessary HTML meta tags from assets/keyboard-layout.html for simplification.

- Added ModelChecker to verify required models for best shot analysis.
- Introduced BestShotWorker to handle background processing of best shot rankings.
- Updated AppController to manage best shot analysis workflow and UI interactions.
- Enhanced AppState to store and manage best shot results.
- Created dialogs to inform users of missing models and provide download instructions.
- Added UI components for triggering best shot analysis and displaying results.
- Implemented tests for model checking and best shot ranking functionality.
- Included necessary model files and updated paths for model dependencies.
- Added AI rating results storage in AppState.
- Enhanced DialogManager to include AI Rating Engine preferences.
- Introduced new menu actions for AI rating of images.
- Created WorkerManager methods for managing AI rating tasks.
- Developed AiRatingWorker to handle background AI rating processes.
- Updated BestShotWorker to support AI-driven analysis.
- Added tests for the new AI rating functionality.
Copilot AI review requested due to automatic review settings November 5, 2025 09:44
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds experimental AI-powered best-shot ranking and image rating functionality to PhotoSort. It introduces two analysis engines: a local multi-model pipeline using BlazeFace face detection, eye-state classification, and aesthetic scoring; and an LLM-based engine that connects to OpenAI-compatible vision models.

Key changes:

  • New BestShotWorker and AiRatingWorker background workers for AI analysis
  • Multi-model local pipeline (BestPhotoSelector) combining face detection, eye classification, and aesthetic scoring
  • LLM strategy for external vision model integration with configurable prompts
  • AnalysisCache for persisting AI results across sessions
  • UI updates including new menu actions, preferences dialog extensions, and filter menu refactoring

Reviewed Changes

Copilot reviewed 29 out of 33 changed files in this pull request and generated 10 comments.

Show a summary per file
File Description
workers/best_shot_worker.py New worker for ranking images within similarity clusters using AI strategies
src/workers/ai_rating_worker.py New worker for AI-driven 1-5 star ratings with retry logic
src/core/ai/best_shot_pipeline.py Strategy pattern implementation with local and LLM ranking engines
src/core/ai/best_photo_selector.py Multi-model pipeline for local AI analysis (face detection, eyes, aesthetics)
src/core/ai/model_checker.py Validation logic for required AI model dependencies
src/core/caching/analysis_cache.py Persistent cache for clustering and AI analysis results
src/core/image_pipeline.py Added get_preview_image method for AI analysis image loading
src/ui/app_controller.py Controller methods for AI workflows and result handling
src/ui/main_window.py UI integration including best-shot decoration and shortcut handling
src/ui/menu_manager.py New AI menu actions and filter menu refactoring from combos to submenus
src/ui/dialog_manager.py Extended preferences dialog with AI engine configuration
src/ui/worker_manager.py Worker lifecycle management for AI analysis threads
src/core/app_settings.py Settings persistence for AI engine config and OpenAI parameters
tests/* Comprehensive test coverage for AI workers, model checker, and cache

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

README.md Outdated
PhotoSort is a powerful desktop application focused on speed designed to streamline the management of large photo libraries, making it easier than ever to sort, cull, and organize your images.

**Warning - Use this at your personal risk. Always use backups.**
** Use this at your personal risk. Always use backups. **
Copy link

Copilot AI Nov 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The warning should be 'Warning - Use this at your personal risk. Always use backups.' (restored 'Warning -' prefix that was removed).

Suggested change
** Use this at your personal risk. Always use backups. **
**Warning - Use this at your personal risk. Always use backups.**

Copilot uses AI. Check for mistakes.
PREVIEW_ESTIMATED_SIZE_FACTOR = 1.35 # Factor for estimating preview sizes

# --- AI/ML Constants ---
# DBSCAN clustering parameters
Copy link

Copilot AI Nov 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The DBSCAN_EPS value changed from 0.05 to 0.055 without explanation. Document why this clustering threshold was adjusted (e.g., 'Increased to 0.055 to reduce over-clustering in photo sets') or revert if unintentional.

Suggested change
# DBSCAN clustering parameters
# DBSCAN clustering parameters
# Increased from 0.05 to 0.055 to reduce over-clustering in photo sets and improve cluster quality.

Copilot uses AI. Check for mistakes.
Comment on lines +989 to +990
self.main_window._rebuild_model_view()

Copy link

Copilot AI Nov 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Duplicate call to _rebuild_model_view() on consecutive lines. Remove one of these redundant calls.

Suggested change
self.main_window._rebuild_model_view()

Copilot uses AI. Check for mistakes.

self.parent._update_cache_dialog_labels()

self.parent._update_cache_dialog_labels()
Copy link

Copilot AI Nov 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Duplicate call to _update_cache_dialog_labels() on lines 1220 and 1222. Remove the redundant call.

Suggested change
self.parent._update_cache_dialog_labels()

Copilot uses AI. Check for mistakes.
@@ -1,4 +1,4 @@
<html xmlns="http://www.w3.org/1999/xhtml"><!-- This file was made using: https://archie-adams.github.io/keyboard-shortcut-map-maker/ It can be edited by loading it with the same website. --><head><meta charset="UTF-8" /><meta http-equiv="X-UA-Compatible" content="IE=edge" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="author" content="Archie Adams" /><title>New-Set.html</title><style>/* -------------------------------------------------------------------------- */
<html xmlns="http://www.w3.org/1999/xhtml"><!-- This file was made using: https://archie-adams.github.io/keyboard-shortcut-map-maker/ It can be edited by loading it with the same website. --><head><title>New-Set.html</title><style>/* -------------------------------------------------------------------------- */
Copy link

Copilot AI Nov 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed meta tags (charset, viewport, author) from the HTML head. These should be retained for proper HTML document structure and accessibility.

Suggested change
<html xmlns="http://www.w3.org/1999/xhtml"><!-- This file was made using: https://archie-adams.github.io/keyboard-shortcut-map-maker/ It can be edited by loading it with the same website. --><head><title>New-Set.html</title><style>/* -------------------------------------------------------------------------- */
<html xmlns="http://www.w3.org/1999/xhtml"><!-- This file was made using: https://archie-adams.github.io/keyboard-shortcut-map-maker/ It can be edited by loading it with the same website. --><head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="author" content="Archie Adams">
<title>New-Set.html</title><style>/* -------------------------------------------------------------------------- */

Copilot uses AI. Check for mistakes.
import logging
import os
import time
from typing import Dict, List, Optional, Set
Copy link

Copilot AI Nov 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Import of 'Optional' is not used.

Suggested change
from typing import Dict, List, Optional, Set
from typing import Dict, List, Set

Copilot uses AI. Check for mistakes.
@@ -1,19 +1,25 @@
import glob
Copy link

Copilot AI Nov 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Import of 'glob' is not used.

Suggested change
import glob

Copilot uses AI. Check for mistakes.
from __future__ import annotations

import importlib.util
import json
Copy link

Copilot AI Nov 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Import of 'json' is not used.

Suggested change
import json

Copilot uses AI. Check for mistakes.
from __future__ import annotations

import os
from unittest.mock import patch
Copy link

Copilot AI Nov 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Import of 'patch' is not used.

Suggested change
from unittest.mock import patch

Copilot uses AI. Check for mistakes.
parsed = json.loads(analysis)
if isinstance(parsed, dict) and "rating" in parsed:
return int(round(float(parsed["rating"])))
except (ValueError, TypeError, json.JSONDecodeError):
Copy link

Copilot AI Nov 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'except' clause does nothing but pass and there is no explanatory comment.

Suggested change
except (ValueError, TypeError, json.JSONDecodeError):
except (ValueError, TypeError, json.JSONDecodeError):
# If JSON parsing fails, fall back to regex extraction below.

Copilot uses AI. Check for mistakes.
- Adjusted formatting in model_checker.py for better readability.
- Updated DBSCAN_EPS value in app_settings.py for consistency.
- Simplified import statements in analysis_cache.py.
- Cleaned up whitespace in main.py.
- Streamlined signal connections in app_controller.py.
- Enhanced readability by aligning code in app_controller.py.
- Improved formatting in dialog_manager.py for better clarity.
- Refined logging statements in main_window.py for consistency.
- Standardized shortcut registration in menu_manager.py.
- Enhanced documentation in ui_components.py.
- Removed redundant code in worker_manager.py.
- Simplified error handling and logging in ai_rating_worker.py.
- Improved test readability in test_best_photo_selector.py.
- Enhanced clarity in test_best_shot_model_checker.py.
- Streamlined assertions in test_best_shot_worker.py.
- Refactored logging and error handling in best_shot_worker.py.
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 29 out of 33 changed files in this pull request and generated no new comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@duartebarbosadev duartebarbosadev merged commit 7963c43 into main Nov 5, 2025
9 checks passed
@duartebarbosadev duartebarbosadev deleted the feat-best-shot-detection branch November 5, 2025 10:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants