Skip to content

feat(shopping): wire dynamic AI recommendations end-to-end (US-8.3)#99

Merged
Bogdan-ca merged 1 commit into
mainfrom
feat/dynamic-shopping
May 26, 2026
Merged

feat(shopping): wire dynamic AI recommendations end-to-end (US-8.3)#99
Bogdan-ca merged 1 commit into
mainfrom
feat/dynamic-shopping

Conversation

@Bogdan-ca

Copy link
Copy Markdown
Collaborator

Frontend now fetches /api/recommendations on mount, with refresh button, loading spinner, and error banner. Backend route proxies to a new ai-service /recommend-purchases endpoint that runs a LangGraph flow: analyze wardrobe gaps -> SerpAPI google_shopping (strict retailer
whitelist: Nike, Adidas, Zara, ASOS, Uniqlo, H&M, COS, Everlane) ->
Tavily fallback -> LLM re-rank with per-pick reasoning.

Per-user recommendations are cached in Mongo and invalidated via a wardrobe fingerprint (count + max updatedAt), so suggestions stay stable until the user changes their wardrobe. 30d TTL is GC only.

Optional X-Internal-Token shared secret between backend and ai-service gates the new endpoint when AI_SERVICE_TOKEN is set on both sides.

Frontend now fetches /api/recommendations on mount, with refresh button,
loading spinner, and error banner. Backend route proxies to a new
ai-service /recommend-purchases endpoint that runs a LangGraph flow:
analyze wardrobe gaps -> SerpAPI google_shopping (strict retailer
whitelist: Nike, Adidas, Zara, ASOS, Uniqlo, H&M, COS, Everlane) ->
Tavily fallback -> LLM re-rank with per-pick reasoning.

Per-user recommendations are cached in Mongo and invalidated via a
wardrobe fingerprint (count + max updatedAt), so suggestions stay
stable until the user changes their wardrobe. 30d TTL is GC only.

Optional X-Internal-Token shared secret between backend and ai-service
gates the new endpoint when AI_SERVICE_TOKEN is set on both sides.
@Bogdan-ca Bogdan-ca merged commit 8833464 into main May 26, 2026
8 of 10 checks passed
Comment thread ai-service/main.py
Comment on lines +579 to +580
f"Recommend-purchases for user {req.user_id} — wardrobe={len(req.wardrobe_items)}, "
f"styles={req.preferences.styles}, budget_max={req.preferences.budget_max}"
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