Class: VisualImageSearchService
- Inherits:
-
Object
- Object
- VisualImageSearchService
- Defined in:
- app/services/visual_image_search_service.rb
Overview
Service for searching images using visual input (URL, uploaded file, or pasted image).
Supports two search modes:
- pHash: Perceptual hash for finding exact/near duplicates
- clip: Gemini Embedding 2 for semantic similarity (similar concepts)
Defined Under Namespace
Classes: DownloadError, Error, ProcessingError
Constant Summary collapse
- SEARCH_MODES =
%i[phash clip].freeze
- DEFAULT_LIMIT =
50- MAX_DOWNLOAD_SIZE =
50MB
50 * 1024 * 1024
Instance Method Summary collapse
-
#call ⇒ Hash
Execute the visual search.
-
#initialize(url: nil, file: nil, base64: nil, phash: nil, mode: :phash, threshold: nil, limit: DEFAULT_LIMIT) ⇒ VisualImageSearchService
constructor
A new instance of VisualImageSearchService.
Constructor Details
#initialize(url: nil, file: nil, base64: nil, phash: nil, mode: :phash, threshold: nil, limit: DEFAULT_LIMIT) ⇒ VisualImageSearchService
Returns a new instance of VisualImageSearchService.
37 38 39 40 41 42 43 44 45 46 47 |
# File 'app/services/visual_image_search_service.rb', line 37 def initialize(url: nil, file: nil, base64: nil, phash: nil, mode: :phash, threshold: nil, limit: DEFAULT_LIMIT) @url = url @file = file @base64 = base64 @phash = phash @mode = mode.to_sym @threshold = threshold @limit = limit.to_i.clamp(1, 100) validate_input! end |
Instance Method Details
#call ⇒ Hash
Execute the visual search
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
# File 'app/services/visual_image_search_service.rb', line 53 def call start_time = Time.current # Fast path: client provided pre-computed pHash if @phash.present? results = search_by_precomputed_phash else tempfile = acquire_image_file results = search_with_mode(tempfile) end { success: true, images: results[:images], mode: @mode, processing_time: (Time.current - start_time).round(3), query_fingerprint: results[:fingerprint], query_embedding_size: results[:embedding]&.size } rescue Error => e { success: false, error: e., mode: @mode } ensure cleanup_tempfile(tempfile) if defined?(tempfile) && tempfile end |