fix(api): handle dict vs object in build_product_context_summary
When products are loaded from PostgreSQL, JSON columns (effect_profile,
context_rules) are deserialized as plain dicts, not Pydantic models.
The build_product_context_summary function was accessing these fields
as object attributes (.safe_with_compromised_barrier) which caused:
AttributeError: 'dict' object has no attribute 'safe_with_compromised_barrier'
Fix: Add isinstance(dict) checks like build_product_context_detailed already does.
Handle both dict (from DB) and object (from Pydantic) cases.
Traceback from production:
File "llm_context.py", line 91, in build_product_context_summary
if product.context_rules.safe_with_compromised_barrier:
AttributeError: 'dict' object has no attribute...
This commit is contained in:
parent
594dae474b
commit
3ef1f249b6
1 changed files with 35 additions and 14 deletions
|
|
@ -72,26 +72,47 @@ def build_product_context_summary(product: Product, has_inventory: bool = False)
|
||||||
if hasattr(product, "effect_profile") and product.effect_profile:
|
if hasattr(product, "effect_profile") and product.effect_profile:
|
||||||
profile = product.effect_profile
|
profile = product.effect_profile
|
||||||
# Only include notable effects (score > 0)
|
# Only include notable effects (score > 0)
|
||||||
if profile.hydration_immediate and profile.hydration_immediate > 0:
|
# Handle both dict (from DB) and object (from Pydantic)
|
||||||
effects.append(f"hydration={profile.hydration_immediate}")
|
if isinstance(profile, dict):
|
||||||
if profile.exfoliation_strength and profile.exfoliation_strength > 0:
|
if profile.get("hydration_immediate", 0) > 0:
|
||||||
effects.append(f"exfoliation={profile.exfoliation_strength}")
|
effects.append(f"hydration={profile['hydration_immediate']}")
|
||||||
if profile.retinoid_strength and profile.retinoid_strength > 0:
|
if profile.get("exfoliation_strength", 0) > 0:
|
||||||
effects.append(f"retinoid={profile.retinoid_strength}")
|
effects.append(f"exfoliation={profile['exfoliation_strength']}")
|
||||||
if profile.irritation_risk and profile.irritation_risk > 0:
|
if profile.get("retinoid_strength", 0) > 0:
|
||||||
effects.append(f"irritation_risk={profile.irritation_risk}")
|
effects.append(f"retinoid={profile['retinoid_strength']}")
|
||||||
if profile.barrier_disruption_risk and profile.barrier_disruption_risk > 0:
|
if profile.get("irritation_risk", 0) > 0:
|
||||||
effects.append(f"barrier_risk={profile.barrier_disruption_risk}")
|
effects.append(f"irritation_risk={profile['irritation_risk']}")
|
||||||
|
if profile.get("barrier_disruption_risk", 0) > 0:
|
||||||
|
effects.append(f"barrier_risk={profile['barrier_disruption_risk']}")
|
||||||
|
else:
|
||||||
|
if profile.hydration_immediate and profile.hydration_immediate > 0:
|
||||||
|
effects.append(f"hydration={profile.hydration_immediate}")
|
||||||
|
if profile.exfoliation_strength and profile.exfoliation_strength > 0:
|
||||||
|
effects.append(f"exfoliation={profile.exfoliation_strength}")
|
||||||
|
if profile.retinoid_strength and profile.retinoid_strength > 0:
|
||||||
|
effects.append(f"retinoid={profile.retinoid_strength}")
|
||||||
|
if profile.irritation_risk and profile.irritation_risk > 0:
|
||||||
|
effects.append(f"irritation_risk={profile.irritation_risk}")
|
||||||
|
if profile.barrier_disruption_risk and profile.barrier_disruption_risk > 0:
|
||||||
|
effects.append(f"barrier_risk={profile.barrier_disruption_risk}")
|
||||||
|
|
||||||
effects_str = f" effects={{{','.join(effects)}}}" if effects else ""
|
effects_str = f" effects={{{','.join(effects)}}}" if effects else ""
|
||||||
|
|
||||||
# Safety flags
|
# Safety flags
|
||||||
safety_flags = []
|
safety_flags = []
|
||||||
if hasattr(product, "context_rules") and product.context_rules:
|
if hasattr(product, "context_rules") and product.context_rules:
|
||||||
if product.context_rules.safe_with_compromised_barrier:
|
rules = product.context_rules
|
||||||
safety_flags.append("barrier_ok")
|
# Handle both dict (from DB) and object (from Pydantic)
|
||||||
if not product.context_rules.safe_after_shaving:
|
if isinstance(rules, dict):
|
||||||
safety_flags.append("!post_shave")
|
if rules.get("safe_with_compromised_barrier"):
|
||||||
|
safety_flags.append("barrier_ok")
|
||||||
|
if not rules.get("safe_after_shaving", True):
|
||||||
|
safety_flags.append("!post_shave")
|
||||||
|
else:
|
||||||
|
if rules.safe_with_compromised_barrier:
|
||||||
|
safety_flags.append("barrier_ok")
|
||||||
|
if not rules.safe_after_shaving:
|
||||||
|
safety_flags.append("!post_shave")
|
||||||
|
|
||||||
safety_str = f" safety={{{','.join(safety_flags)}}}" if safety_flags else ""
|
safety_str = f" safety={{{','.join(safety_flags)}}}" if safety_flags else ""
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue