Featured image of post Hybrid Image Search Dev Log #12 — Reranking Pipeline Fixes, Dual-Batch Generation, Frontend Sprint

Hybrid Image Search Dev Log #12 — Reranking Pipeline Fixes, Dual-Batch Generation, Frontend Sprint

Fixed four simultaneous bugs in the reranking pipeline, overhauled image generation from single-tone to dual-batch (3-tone/5-tone), and shipped a batch of frontend components including reactions, likes, and feedback.

Previous: Hybrid Image Search Dev Log #11

Dev log #12 covers three major tracks. First, I tracked down and fixed four bugs that had been quietly breaking the reranking pipeline. Second, I replaced the single-tone + angle-image generation approach with a dual-batch system (3-tone and 5-tone) driven by text-based angle directives. Third, I implemented a batch of frontend components — AnglePicker, ReactionButtons, LikesTab, ImageLightbox, and FeedbackModal. Total diff: 42 files, +2,749/-662 lines.

Overall Work Flow

1. Reranking Pipeline — Four Bugs Fixed at Once

Reranking was effectively doing nothing. When I traced the root cause, I found not one bug but four.

Problem Analysis

BugSymptomImpact
CE weight 0.03Cross-Encoder scores contributed only 3% to the final scoreReranking had almost zero effect
Model not fine-tuned on KoreanPoor relevance judgment for Korean queriesDegraded search quality
Passing expanded_query to CEExpanded query distorted CE scores away from the original intentIrrelevant results ranked higher
Geometric meanA single low sub-score dragged down otherwise strong partial matchesGood partial matches disappeared from results

Fix

All four were fixed together. CE weight was restored to a sensible value, original_query replaced expanded_query as the Cross-Encoder input, and geometric mean was replaced with arithmetic mean.

I also attempted a model upgrade. bge-reranker-v2-m3 (568M parameters) showed noticeably better Korean performance, but took 16 seconds per component on an EC2 CPU — not viable in production. I rolled back to mmarco-mMiniLMv2 (136M) and kept the other three fixes.

2. Multi-Tone + Angle Text Overhaul

The previous approach injected a single tone and a single angle reference image per generation. This sprint replaced that entirely.

Angle: From Images to Text Directives

I removed angle reference images and switched to text-based presets. angle_text.py defines presets like “45-degree downward angle,” “overhead,” and “eye level.” lens.py adds per-category focal length presets (e.g., 85mm for portraits, 24mm for landscapes).

The advantage is straightforward: no more cost of finding and managing angle reference images, and finer control is possible at the prompt level.

Tone: Single → Dual Batch (3-tone / 5-tone)

A single generation request now runs a 3-tone batch and a 5-tone batch in parallel. Users can compare results via a tone3/tone5 toggle in the frontend. The DB schema was updated to add multi-tone columns, and log_generation was updated accordingly.

person-intent Auto Model Injection

An intent_person field was added to the Gemini classification prompt. If the user’s reference images contain no people but the query implies a person, the system automatically injects a model image from the refs/model_image_ref/ directory. This covers the case where the intent is person-focused but the uploaded references don’t include any people.

3. Frontend Feature Sprint

Frontend components were built out to match the backend changes.

New Components

  • AnglePicker — Search and select angle presets. Fetches the list from /api/angle-presets. Integrated into the detail page so the angle can be changed after generation.
  • ReactionButtons — Quick emoji reaction buttons for generated images.
  • LikesTab — A gallery tab collecting all images the user has liked.
  • ImageLightbox — Expanded view on thumbnail click.
  • FeedbackModal — A modal for submitting detailed text-based feedback.

Dual-Batch UI

MAX_REFS was raised to 7 on the frontend, and dual-batch generation is now supported. The detail page shows multi-tone metadata and a tone3/tone5 toggle.

API Endpoints

Added GET /api/angle-presets, reaction and feedback endpoints, and updated API interface type definitions.

4. Production Server Debugging & Infrastructure

Grafana Data Missing

DEPLOYMENT_ENV was not set, and a missing newline in the .env file was causing the S3 path to be assembled incorrectly. Both were fixed to restore monitoring data collection.

Missing DB Migration

The injected_model_filename column was absent from the production database, causing the auto model injection feature to fail. A migration script was added to resolve this.

Infrastructure Improvements

  • Switched prod SSH key to ed25519 and added a lifecycle guard
  • Closed open ports and configured nginx reverse proxy
  • Removed duplicate 401 errors that occurred during startup auth checks
  • Fixed mobile responsive layout
  • Updated Security Group descriptions to match AWS validation requirements
  • Removed APP_ENVIRONMENT from ecosystem.config.js

Wrap-Up

The most meaningful work in this sprint was the reranking fix. Four bugs coexisted in a way that masked each other’s effects — fixing them one at a time actually made results worse in some cases. Only after fixing all four simultaneously did reranking start working correctly.

The dual-batch generation and text-based angle directives haven’t gathered enough user feedback yet. The next step is to use reaction and feedback data to validate whether 3-tone or 5-tone is preferred, and whether text angle presets actually outperform angle reference images.

Built with Hugo
Theme Stack designed by Jimmy