refactor: remove routine_role, recommended_frequency, evidence_level, cumulative_with
Drop fields identified as redundant or low-value from the Product model, API schemas, frontend types, and forms. Raise effect_profile threshold in to_llm_context() from >0 to >=2 to suppress noise values. Remove sku/barcode from LLM context output (kept on model for catalog use). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
9bf94a979c
commit
9a069508af
9 changed files with 464 additions and 142 deletions
|
|
@ -21,11 +21,8 @@ from innercontext.models.product import (
|
|||
from innercontext.models.enums import (
|
||||
AbsorptionSpeed,
|
||||
DayTime,
|
||||
EvidenceLevel,
|
||||
PriceTier,
|
||||
RoutineRole,
|
||||
TextureType,
|
||||
UsageFrequency,
|
||||
SkinType,
|
||||
)
|
||||
|
||||
|
|
@ -46,7 +43,6 @@ class ProductCreate(SQLModel):
|
|||
barcode: Optional[str] = None
|
||||
|
||||
category: ProductCategory
|
||||
routine_role: RoutineRole
|
||||
recommended_time: DayTime
|
||||
|
||||
texture: Optional[TextureType] = None
|
||||
|
|
@ -61,13 +57,10 @@ class ProductCreate(SQLModel):
|
|||
actives: Optional[list[ActiveIngredient]] = None
|
||||
|
||||
recommended_for: list[SkinType] = []
|
||||
recommended_frequency: Optional[UsageFrequency] = None
|
||||
|
||||
targets: list[SkinConcern] = []
|
||||
contraindications: list[str] = []
|
||||
usage_notes: Optional[str] = None
|
||||
evidence_level: Optional[EvidenceLevel] = None
|
||||
claims: list[str] = []
|
||||
|
||||
fragrance_free: Optional[bool] = None
|
||||
essential_oils_free: Optional[bool] = None
|
||||
|
|
@ -104,7 +97,6 @@ class ProductUpdate(SQLModel):
|
|||
barcode: Optional[str] = None
|
||||
|
||||
category: Optional[ProductCategory] = None
|
||||
routine_role: Optional[RoutineRole] = None
|
||||
recommended_time: Optional[DayTime] = None
|
||||
|
||||
texture: Optional[TextureType] = None
|
||||
|
|
@ -119,13 +111,10 @@ class ProductUpdate(SQLModel):
|
|||
actives: Optional[list[ActiveIngredient]] = None
|
||||
|
||||
recommended_for: Optional[list[SkinType]] = None
|
||||
recommended_frequency: Optional[UsageFrequency] = None
|
||||
|
||||
targets: Optional[list[SkinConcern]] = None
|
||||
contraindications: Optional[list[str]] = None
|
||||
usage_notes: Optional[str] = None
|
||||
evidence_level: Optional[EvidenceLevel] = None
|
||||
claims: Optional[list[str]] = None
|
||||
|
||||
fragrance_free: Optional[bool] = None
|
||||
essential_oils_free: Optional[bool] = None
|
||||
|
|
|
|||
|
|
@ -11,17 +11,14 @@ from .domain import Domain
|
|||
from .enums import (
|
||||
AbsorptionSpeed,
|
||||
DayTime,
|
||||
EvidenceLevel,
|
||||
IngredientFunction,
|
||||
InteractionScope,
|
||||
PriceTier,
|
||||
ProductCategory,
|
||||
RoutineRole,
|
||||
SkinConcern,
|
||||
SkinType,
|
||||
StrengthLevel,
|
||||
TextureType,
|
||||
UsageFrequency,
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -60,8 +57,6 @@ class ActiveIngredient(SQLModel):
|
|||
strength_level: StrengthLevel | None = None
|
||||
irritation_potential: StrengthLevel | None = None
|
||||
|
||||
cumulative_with: list[IngredientFunction] | None = None
|
||||
|
||||
|
||||
class ProductInteraction(SQLModel):
|
||||
target: str
|
||||
|
|
@ -106,7 +101,6 @@ class Product(SQLModel, table=True):
|
|||
barcode: str | None = Field(default=None, max_length=64)
|
||||
|
||||
category: ProductCategory
|
||||
routine_role: RoutineRole
|
||||
recommended_time: DayTime
|
||||
|
||||
texture: TextureType | None = None
|
||||
|
|
@ -127,7 +121,6 @@ class Product(SQLModel, table=True):
|
|||
recommended_for: list[SkinType] = Field(
|
||||
default_factory=list, sa_column=Column(JSON, nullable=False)
|
||||
)
|
||||
recommended_frequency: UsageFrequency | None = None
|
||||
|
||||
targets: list[SkinConcern] = Field(
|
||||
default_factory=list, sa_column=Column(JSON, nullable=False)
|
||||
|
|
@ -136,10 +129,6 @@ class Product(SQLModel, table=True):
|
|||
default_factory=list, sa_column=Column(JSON, nullable=False)
|
||||
)
|
||||
usage_notes: str | None = None
|
||||
evidence_level: EvidenceLevel | None = Field(default=None, index=True)
|
||||
claims: list[str] = Field(
|
||||
default_factory=list, sa_column=Column(JSON, nullable=False)
|
||||
)
|
||||
|
||||
fragrance_free: bool | None = None
|
||||
essential_oils_free: bool | None = None
|
||||
|
|
@ -221,12 +210,11 @@ class Product(SQLModel, table=True):
|
|||
"name": self.name,
|
||||
"brand": self.brand,
|
||||
"category": _ev(self.category),
|
||||
"routine_role": _ev(self.routine_role),
|
||||
"recommended_time": _ev(self.recommended_time),
|
||||
"leave_on": self.leave_on,
|
||||
}
|
||||
|
||||
for field in ("line_name", "sku", "url", "barcode"):
|
||||
for field in ("line_name", "url"):
|
||||
val = getattr(self, field)
|
||||
if val is not None:
|
||||
ctx[field] = val
|
||||
|
|
@ -241,11 +229,6 @@ class Product(SQLModel, table=True):
|
|||
ctx["size_ml"] = self.size_ml
|
||||
if self.pao_months is not None:
|
||||
ctx["pao_months"] = self.pao_months
|
||||
if self.recommended_frequency is not None:
|
||||
ctx["recommended_frequency"] = _ev(self.recommended_frequency)
|
||||
if self.evidence_level is not None:
|
||||
ctx["evidence_level"] = _ev(self.evidence_level)
|
||||
|
||||
if self.inci:
|
||||
ctx["inci"] = self.inci
|
||||
if self.recommended_for:
|
||||
|
|
@ -254,8 +237,6 @@ class Product(SQLModel, table=True):
|
|||
ctx["targets"] = [_ev(s) for s in self.targets]
|
||||
if self.contraindications:
|
||||
ctx["contraindications"] = self.contraindications
|
||||
if self.claims:
|
||||
ctx["claims"] = self.claims
|
||||
|
||||
if self.actives:
|
||||
actives_ctx = []
|
||||
|
|
@ -270,8 +251,6 @@ class Product(SQLModel, table=True):
|
|||
a_dict["functions"] = [_ev(f) for f in a.functions]
|
||||
if a.strength_level is not None:
|
||||
a_dict["strength_level"] = a.strength_level.name.lower()
|
||||
if a.cumulative_with:
|
||||
a_dict["cumulative_with"] = [_ev(f) for f in a.cumulative_with]
|
||||
actives_ctx.append(a_dict)
|
||||
ctx["actives"] = actives_ctx
|
||||
|
||||
|
|
@ -288,9 +267,9 @@ class Product(SQLModel, table=True):
|
|||
ep = self.product_effect_profile
|
||||
if ep is not None:
|
||||
if isinstance(ep, dict):
|
||||
nonzero = {k: v for k, v in ep.items() if v}
|
||||
nonzero = {k: v for k, v in ep.items() if v >= 2}
|
||||
else:
|
||||
nonzero = {k: v for k, v in ep.model_dump().items() if v}
|
||||
nonzero = {k: v for k, v in ep.model_dump().items() if v >= 2}
|
||||
if nonzero:
|
||||
ctx["effect_profile"] = nonzero
|
||||
|
||||
|
|
|
|||
|
|
@ -53,7 +53,6 @@ def product_data():
|
|||
"name": "CeraVe Moisturising Cream",
|
||||
"brand": "CeraVe",
|
||||
"category": "moisturizer",
|
||||
"routine_role": "seal",
|
||||
"recommended_time": "both",
|
||||
"leave_on": True,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ from innercontext.models.enums import (
|
|||
IngredientFunction,
|
||||
InteractionScope,
|
||||
ProductCategory,
|
||||
RoutineRole,
|
||||
)
|
||||
from innercontext.models.product import (
|
||||
ActiveIngredient,
|
||||
|
|
@ -25,7 +24,6 @@ def _make(**kwargs):
|
|||
name="Test",
|
||||
brand="B",
|
||||
category=ProductCategory.MOISTURIZER,
|
||||
routine_role=RoutineRole.SEAL,
|
||||
recommended_time=DayTime.BOTH,
|
||||
leave_on=True,
|
||||
)
|
||||
|
|
@ -41,7 +39,7 @@ def _make(**kwargs):
|
|||
def test_always_present_keys():
|
||||
p = _make()
|
||||
ctx = p.to_llm_context()
|
||||
for key in ("id", "name", "brand", "category", "routine_role", "recommended_time", "leave_on"):
|
||||
for key in ("id", "name", "brand", "category", "recommended_time", "leave_on"):
|
||||
assert key in ctx, f"Expected '{key}' in to_llm_context() output"
|
||||
|
||||
|
||||
|
|
@ -53,17 +51,17 @@ def test_always_present_keys():
|
|||
def test_optional_string_fields_absent_when_none():
|
||||
p = _make()
|
||||
ctx = p.to_llm_context()
|
||||
for key in ("line_name", "sku", "url", "barcode"):
|
||||
for key in ("line_name", "url"):
|
||||
assert key not in ctx, f"'{key}' should not appear when None"
|
||||
|
||||
|
||||
def test_optional_string_fields_present_when_set():
|
||||
p = _make(line_name="Hydrating", sku="CV-001", url="https://example.com", barcode="123456")
|
||||
p = _make(line_name="Hydrating", url="https://example.com")
|
||||
ctx = p.to_llm_context()
|
||||
assert ctx["line_name"] == "Hydrating"
|
||||
assert ctx["sku"] == "CV-001"
|
||||
assert ctx["url"] == "https://example.com"
|
||||
assert ctx["barcode"] == "123456"
|
||||
assert "sku" not in ctx
|
||||
assert "barcode" not in ctx
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -52,7 +52,6 @@ def test_list_filter_category(client, client_and_data=None):
|
|||
# Create a moisturizer and a serum
|
||||
base = {
|
||||
"brand": "B",
|
||||
"routine_role": "seal",
|
||||
"recommended_time": "both",
|
||||
"leave_on": True,
|
||||
}
|
||||
|
|
@ -72,7 +71,6 @@ def test_list_filter_category(client, client_and_data=None):
|
|||
|
||||
def test_list_filter_brand(client):
|
||||
base = {
|
||||
"routine_role": "seal",
|
||||
"recommended_time": "both",
|
||||
"leave_on": True,
|
||||
"category": "serum",
|
||||
|
|
@ -90,7 +88,6 @@ def test_list_filter_brand(client):
|
|||
def test_list_filter_is_medication(client):
|
||||
base = {
|
||||
"brand": "B",
|
||||
"routine_role": "seal",
|
||||
"recommended_time": "both",
|
||||
"leave_on": True,
|
||||
"category": "serum",
|
||||
|
|
@ -113,7 +110,6 @@ def test_list_filter_is_medication(client):
|
|||
def test_list_filter_targets(client):
|
||||
base = {
|
||||
"brand": "B",
|
||||
"routine_role": "seal",
|
||||
"recommended_time": "both",
|
||||
"leave_on": True,
|
||||
"category": "serum",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue