feat(api): include 7-day upcoming grooming context in routine suggestions
This commit is contained in:
parent
5d69a976c4
commit
1c457d62a3
3 changed files with 73 additions and 2 deletions
|
|
@ -327,6 +327,48 @@ def _build_grooming_context(
|
||||||
return "\n".join(lines) + "\n"
|
return "\n".join(lines) + "\n"
|
||||||
|
|
||||||
|
|
||||||
|
def _build_upcoming_grooming_context(
|
||||||
|
session: Session,
|
||||||
|
start_date: date,
|
||||||
|
days: int = 7,
|
||||||
|
) -> str:
|
||||||
|
entries = session.exec(
|
||||||
|
select(GroomingSchedule).order_by(col(GroomingSchedule.day_of_week))
|
||||||
|
).all()
|
||||||
|
if not entries:
|
||||||
|
return f"UPCOMING GROOMING (next {days} days): none\n"
|
||||||
|
|
||||||
|
entries_by_weekday: dict[int, list[GroomingSchedule]] = {}
|
||||||
|
for entry in entries:
|
||||||
|
entries_by_weekday.setdefault(entry.day_of_week, []).append(entry)
|
||||||
|
|
||||||
|
lines = [f"UPCOMING GROOMING (next {days} days):"]
|
||||||
|
for offset in range(days):
|
||||||
|
target_date = start_date + timedelta(days=offset)
|
||||||
|
day_entries = entries_by_weekday.get(target_date.weekday(), [])
|
||||||
|
if not day_entries:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if offset == 0:
|
||||||
|
relative_label = "dzisiaj"
|
||||||
|
elif offset == 1:
|
||||||
|
relative_label = "jutro"
|
||||||
|
else:
|
||||||
|
relative_label = f"za {offset} dni"
|
||||||
|
|
||||||
|
day_name = _DAY_NAMES[target_date.weekday()]
|
||||||
|
actions = ", ".join(
|
||||||
|
f"{_ev(entry.action)}" + (f" ({entry.notes})" if entry.notes else "")
|
||||||
|
for entry in day_entries
|
||||||
|
)
|
||||||
|
lines.append(f" {relative_label} ({target_date}, {day_name}): {actions}")
|
||||||
|
|
||||||
|
if len(lines) == 1:
|
||||||
|
lines.append(" (no entries in this window)")
|
||||||
|
|
||||||
|
return "\n".join(lines) + "\n"
|
||||||
|
|
||||||
|
|
||||||
def _build_recent_history(session: Session) -> str:
|
def _build_recent_history(session: Session) -> str:
|
||||||
cutoff = date.today() - timedelta(days=7)
|
cutoff = date.today() - timedelta(days=7)
|
||||||
routines = session.exec(
|
routines = session.exec(
|
||||||
|
|
@ -632,7 +674,11 @@ def suggest_routine(
|
||||||
weekday = data.routine_date.weekday()
|
weekday = data.routine_date.weekday()
|
||||||
skin_ctx = _build_skin_context(session)
|
skin_ctx = _build_skin_context(session)
|
||||||
profile_ctx = build_user_profile_context(session, reference_date=data.routine_date)
|
profile_ctx = build_user_profile_context(session, reference_date=data.routine_date)
|
||||||
grooming_ctx = _build_grooming_context(session, weekdays=[weekday])
|
upcoming_grooming_ctx = _build_upcoming_grooming_context(
|
||||||
|
session,
|
||||||
|
start_date=data.routine_date,
|
||||||
|
days=7,
|
||||||
|
)
|
||||||
history_ctx = _build_recent_history(session)
|
history_ctx = _build_recent_history(session)
|
||||||
day_ctx = _build_day_context(data.leaving_home)
|
day_ctx = _build_day_context(data.leaving_home)
|
||||||
available_products = _get_available_products(
|
available_products = _get_available_products(
|
||||||
|
|
@ -675,7 +721,7 @@ def suggest_routine(
|
||||||
f"na {data.routine_date} ({day_name}).\n\n"
|
f"na {data.routine_date} ({day_name}).\n\n"
|
||||||
f"{mode_line}\n"
|
f"{mode_line}\n"
|
||||||
"INPUT DATA:\n"
|
"INPUT DATA:\n"
|
||||||
f"{profile_ctx}\n{skin_ctx}\n{grooming_ctx}\n{history_ctx}\n{day_ctx}\n{products_ctx}\n{objectives_ctx}"
|
f"{profile_ctx}\n{skin_ctx}\n{upcoming_grooming_ctx}\n{history_ctx}\n{day_ctx}\n{products_ctx}\n{objectives_ctx}"
|
||||||
"\nNARZEDZIA:\n"
|
"\nNARZEDZIA:\n"
|
||||||
"- Masz dostep do funkcji: get_product_details.\n"
|
"- Masz dostep do funkcji: get_product_details.\n"
|
||||||
"- Wywoluj narzedzia tylko, gdy potrzebujesz detali do decyzji klinicznej/bezpieczenstwa.\n"
|
"- Wywoluj narzedzia tylko, gdy potrzebujesz detali do decyzji klinicznej/bezpieczenstwa.\n"
|
||||||
|
|
|
||||||
|
|
@ -249,6 +249,7 @@ def test_suggest_routine(client, session):
|
||||||
assert data["reasoning"] == "because"
|
assert data["reasoning"] == "because"
|
||||||
kwargs = mock_gemini.call_args.kwargs
|
kwargs = mock_gemini.call_args.kwargs
|
||||||
assert "USER PROFILE:" in kwargs["contents"]
|
assert "USER PROFILE:" in kwargs["contents"]
|
||||||
|
assert "UPCOMING GROOMING (next 7 days):" in kwargs["contents"]
|
||||||
assert "function_handlers" in kwargs
|
assert "function_handlers" in kwargs
|
||||||
assert "get_product_details" in kwargs["function_handlers"]
|
assert "get_product_details" in kwargs["function_handlers"]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ from innercontext.api.routines import (
|
||||||
_build_products_context,
|
_build_products_context,
|
||||||
_build_recent_history,
|
_build_recent_history,
|
||||||
_build_skin_context,
|
_build_skin_context,
|
||||||
|
_build_upcoming_grooming_context,
|
||||||
_contains_minoxidil_text,
|
_contains_minoxidil_text,
|
||||||
_ev,
|
_ev,
|
||||||
_extract_active_names,
|
_extract_active_names,
|
||||||
|
|
@ -121,6 +122,29 @@ def test_build_grooming_context(session: Session):
|
||||||
assert "(no entries for specified days)" in ctx2
|
assert "(no entries for specified days)" in ctx2
|
||||||
|
|
||||||
|
|
||||||
|
def test_build_upcoming_grooming_context(session: Session):
|
||||||
|
assert (
|
||||||
|
_build_upcoming_grooming_context(session, start_date=date(2026, 3, 2), days=7)
|
||||||
|
== "UPCOMING GROOMING (next 7 days): none\n"
|
||||||
|
)
|
||||||
|
|
||||||
|
monday = GroomingSchedule(
|
||||||
|
id=uuid.uuid4(), day_of_week=0, action="shaving_oneblade", notes="Morning"
|
||||||
|
)
|
||||||
|
wednesday = GroomingSchedule(id=uuid.uuid4(), day_of_week=2, action="dermarolling")
|
||||||
|
session.add_all([monday, wednesday])
|
||||||
|
session.commit()
|
||||||
|
|
||||||
|
ctx = _build_upcoming_grooming_context(
|
||||||
|
session,
|
||||||
|
start_date=date(2026, 3, 2),
|
||||||
|
days=7,
|
||||||
|
)
|
||||||
|
assert "UPCOMING GROOMING (next 7 days):" in ctx
|
||||||
|
assert "dzisiaj (2026-03-02, poniedziałek): shaving_oneblade (Morning)" in ctx
|
||||||
|
assert "za 2 dni (2026-03-04, środa): dermarolling" in ctx
|
||||||
|
|
||||||
|
|
||||||
def test_build_recent_history(session: Session):
|
def test_build_recent_history(session: Session):
|
||||||
assert _build_recent_history(session) == "RECENT ROUTINES: none\n"
|
assert _build_recent_history(session) == "RECENT ROUTINES: none\n"
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue