-
Notifications
You must be signed in to change notification settings - Fork 0
β‘ Bolt: Implement LRU cache for AI fashion advice #21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| # Bolt's Performance Journal | ||
|
|
||
| ## 2024-05-15 - [LRU Caching for AI Recommendations] | ||
| **Learning:** Redundant LLM calls to Gemini are a major bottleneck (~2-5s latency). Standardizing input data (event type, garment attributes) allows for efficient caching with `functools.lru_cache`, which reduces repeated request latency to <1ms. | ||
| **Action:** Use primitive types for cache keys and ensure data consistency before calling the AI engine. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,5 @@ | ||
| import os | ||
| import functools | ||
| import google.generativeai as genai | ||
| from dotenv import load_dotenv | ||
|
|
||
|
|
@@ -17,26 +18,19 @@ | |
| genai.configure(api_key=api_key) | ||
| model = genai.GenerativeModel('gemini-1.5-flash') | ||
|
|
||
| def get_jules_advice(user_data, garment): | ||
| @functools.lru_cache(maxsize=128) | ||
| def _get_cached_jules_advice(event_type, garment_name, drape, elasticity): | ||
| """ | ||
| Generates an emotional styling tip without mentioning body numbers or sizes. | ||
| Cached helper function for Jules AI advice. | ||
| Uses primitive, hashable types for cache keys. | ||
| """ | ||
| # garment is a dict (from GARMENT_DB) or Garment object. | ||
| # The prompt usage implies dict access: garment['name'] | ||
|
|
||
| # Handle both dict and Pydantic model | ||
| if hasattr(garment, 'dict'): | ||
| garment_data = garment.dict() | ||
| else: | ||
| garment_data = garment | ||
|
|
||
| prompt = f""" | ||
| You are 'Jules', a high-end fashion consultant at Galeries Lafayette. | ||
| A client is interested in the '{garment_data['name']}' for a {user_data.event_type}. | ||
| A client is interested in the '{garment_name}' for a {event_type}. | ||
|
|
||
| Technical Context: | ||
| - Fabric Drape: {garment_data['drape']} | ||
| - Fabric Elasticity: {garment_data['elasticity']} | ||
| - Fabric Drape: {drape} | ||
| - Fabric Elasticity: {elasticity} | ||
|
|
||
| Task: | ||
| Explain why this garment is the perfect choice for their silhouette based | ||
|
|
@@ -51,3 +45,25 @@ def get_jules_advice(user_data, garment): | |
|
|
||
| response = model.generate_content(prompt) | ||
| return response.text | ||
|
|
||
| def get_jules_advice(user_data, garment): | ||
| """ | ||
| Generates an emotional styling tip without mentioning body numbers or sizes. | ||
| """ | ||
| # garment is a dict (from GARMENT_DB) or Garment object. | ||
| # The prompt usage implies dict access: garment['name'] | ||
|
|
||
| # Handle both dict and Pydantic model | ||
| if hasattr(garment, 'dict'): | ||
| garment_data = garment.dict() | ||
| else: | ||
| garment_data = garment | ||
|
|
||
| # Bolt Optimization: Use LRU cache to avoid redundant, expensive LLM calls. | ||
| # We extract primitive fields to ensure they are hashable for lru_cache. | ||
| event_type = getattr(user_data, 'event_type', 'special event') | ||
| garment_name = garment_data.get('name', 'selected item') | ||
| drape = garment_data.get('drape', 'Adaptive') | ||
| elasticity = garment_data.get('elasticity', 'Comfortable') | ||
|
Comment on lines
+64
to
+67
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The default values for For example: # At module level
DEFAULT_EVENT_TYPE = 'special event'
DEFAULT_GARMENT_NAME = 'selected item'
DEFAULT_DRAPE = 'Adaptive'
DEFAULT_ELASTICITY = 'Comfortable'
# In get_jules_advice()
event_type = getattr(user_data, 'event_type', DEFAULT_EVENT_TYPE)
garment_name = garment_data.get('name', DEFAULT_GARMENT_NAME)
drape = garment_data.get('drape', DEFAULT_DRAPE)
elasticity = garment_data.get('elasticity', DEFAULT_ELASTICITY) |
||
|
|
||
| return _get_cached_jules_advice(event_type, garment_name, drape, elasticity) | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The pattern
*$py.classappears to be a typo. It matches a literal dollar sign, which is likely not the intention. If the goal is to ignore compiled Python files for Jython, the correct pattern is*.class. Note that standard CPython compiled files (.pyc,.pyo) are already covered by*.py[cod]on the preceding line.