Integrates cf-core reranker into the L1/L2 recipe engine. Paid+ tier gets a BGE cross-encoder pass over the top-20 FTS candidates, scoring each recipe against the user's full context: pantry state, dietary constraints, allergies, expiry urgency, style preference, and effort preference. Free tier keeps the existing overlap sort unchanged. - New app/services/recipe/reranker.py: build_query, build_candidate_string, rerank_suggestions with tier gate (_RERANKER_TIERS) and graceful fallback - rerank_score field added to RecipeSuggestion (None on free tier, float on paid+) - recipe_engine.py: single call after candidate assembly, before final sort; hard_day_mode tier grouping preserved as primary sort when reranker active - Fix pre-existing circular import in app/services/__init__.py (eager import of ReceiptService triggered store.py → services → receipt_service → store) - 27 unit tests (mock backend, no model weights) + 2 engine-level tier tests; 325 tests passing, no regressions
13 lines
331 B
Python
13 lines
331 B
Python
# app/services/__init__.py
|
|
"""
|
|
Business logic services for Kiwi.
|
|
"""
|
|
|
|
__all__ = ["ReceiptService"]
|
|
|
|
|
|
def __getattr__(name: str):
|
|
if name == "ReceiptService":
|
|
from app.services.receipt_service import ReceiptService
|
|
return ReceiptService
|
|
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|