How shaelilwang/jacque works
1. Repo shape: Jacque is a small, functionality-first product-finding system. It has a Flask backend plus a single unstyled static HTML/JS frontend (static/index.html). The backend is the integration hub; most other Python files are domain-specific modules or CLI entrypoints.
2. Primary user flow (Channel3 mode): The browser uploads an image to Flask at /api/search. The backend base64-encodes the image, calls Channel3’s search API with CHANNEL3_API_KEY, then returns a flattened list of product candidates shaped like {title, brand, price, image, url} for the frontend to render as buy links.
3. Alternative search mode (scoped sites): The repo also supports a second retrieval path, /api/search_scoped, which searches only a user-supplied allowlist of sites. That path uses the Serper.dev Google Search API with site: scoping and pagination. The site list is loaded from a local sites.txt-style file (sites.example.txt in the repo), keeping the search boundary explicit and controllable.
4. Text assistance layer: A separate backend endpoint, /api/assist, sends the uploaded image to Anthropic Sonnet (claude-sonnet-4-6) when the user clicks “Fill description.” Sonnet returns two structured descriptions: items and style. These are combined into an editable search query that then feeds either Channel3 search or scoped search.
5. Search result normalization boundary: Regardless of which retrieval backend is used, the system converges on a common “candidate product” shape before anything else happens. This normalization is important because the rest of the pipeline expects consistent fields even when source sites or APIs differ.
6. Ranking pipeline: The repo has a second major subsystem for turning retrieved candidates into a ranked list. It is intentionally split into two stages:
- Extraction in extract.py: a cheap LLM pass (Haiku) reads each candidate’s text and extracts garment type, silhouette/aesthetic tags, material/color, dimensions, and whether it is the target item. Missing facts remain None; they are not invented.
- Scoring in ranker.py: pure deterministic functions compute sub-scores for target match, fit, taste, and budget, then combine them into an overall score with confidence weighting.
7. User/profile model boundary: profiles.py defines the scoring inputs that are treated as user state: measurements, usual size, fit preference, budget, Kibbe body type, and a hardcoded taste spec. ranker.py consumes that profile rather than embedding user assumptions directly, which makes the scoring layer reusable and testable.
8. Confidence-aware ranking behavior: The ranking design explicitly treats uncertainty as first-class. Each extracted signal has confidence, and each sub-score’s effective weight is reduced by a confidence exponent. Items with no usable signal can fall out of the ranking entirely (overall = None), which is a deliberate “honest data” boundary.
9. Entry points and operational modes: app.py runs the Flask web app, run_harness.py is the CLI for the scoped-site search pipeline, and run_ranker.py is a demo runner for the ranking pipeline. This gives the repo three execution modes: interactive web search, CLI retrieval, and CLI ranking.
10. Validation and support files: test_ranker.py covers the deterministic scoring logic, which is the most stable and testable part of the system. requirements.txt, .env.example, and sites.example.txt define the external dependencies, secrets, and site allowlist needed to wire the architecture together.
11. External dependencies that matter architecturally: The system depends on Anthropic for description/extraction, Channel3 or Serper.dev for retrieval, and environment variables for API keys. Those services define the main network boundaries in the architecture diagram: browser → Flask → external AI/search APIs → normalized candidates → ranking → frontend display.
Main entry points: ranker.py Rank items · app.py Flask app · index.html Search UI · harness.py Scoped search
Components 15
Frontend
Browser-facing UI and static display layer
- Browser · Uploads images and renders candidate products
- Search UI · Single-page upload and results interface
static/index.html
Backend API
Flask app and request orchestration
- Flask app · Main integration hub exposing search and assist endpoints
app.py - Assist API · Generates structured item and style descriptions from an image
Retrieval
Channel3 and scoped-site search paths
- Search API · Channel3-backed image search entry point
- Scoped search · Searches allowlisted sites with site-scoped queries and pagination
harness.py - Site allowlist · Explicit allowlist used by scoped search
sites.example.txt - Normalize · Flattens retrieval results into a common product candidate shape
Ranking
Candidate extraction and scoring
- Extract facts · Reads candidate text and extracts garment, fit, material, color, and target signals
extract.py - Profile state · Measurements, size, fit preference, budget, Kibbe type, and taste spec
profiles.py - Rank items · Computes target, fit, taste, and budget scores with confidence weighting
ranker.py - Cost model · Support logic for ranking economics and weighting
cost.py
Entry points
CLI runners and support files
- Search CLI · Command-line runner for scoped-site retrieval
run_harness.py - Ranker demo · Command-line runner for the ranking pipeline
run_ranker.py - Rank tests · Validates deterministic scoring behavior
test_ranker.py
Connections 18
- Browser → Search UI: uses · Interactive upload and results display
- Search UI → Flask app: /api/search · Sends image search requests to Flask
- Search UI → Flask app: /api/assist · Requests generated item and style descriptions
- Flask app → Assist API: image to text · Calls Anthropic Sonnet for structured descriptions
- Flask app → Search API: Channel3 · Performs image-based product search
- Flask app → Scoped search: scoped retrieval · Searches only user-allowed sites
- Scoped search → Site allowlist: loads allowlist · Uses explicit site boundary for search scope
- Search API → Normalize: candidates · Returns raw products that are flattened into a common shape
- Scoped search → Normalize: candidates · Normalizes search results into product candidates
- Normalize → Extract facts: text fields · Feeds candidate text into feature extraction
- Extract facts → Profile state: signals · Produces structured signals evaluated against user state
- Profile state → Rank items: inputs · Supplies measurements, fit, budget, and taste context
- Extract facts → Rank items: scored features · Provides confidence-weighted item features
- Rank items → Cost model: pricing logic · Uses shared cost and budget-related helpers
- Rank items → Search UI: ranked results · Outputs sorted candidates for display
- Search CLI → Scoped search: CLI · Runs scoped-site retrieval from the command line
- Ranker demo → Rank items: CLI · Runs the ranking pipeline as a demo
- Rank tests → Rank items: verifies · Covers deterministic scoring logic