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:
Piotr Oleszczyk 2026-02-27 10:22:59 +01:00
parent 9bf94a979c
commit 9a069508af
9 changed files with 464 additions and 142 deletions

View file

@ -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

View file

@ -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