shinkan-jinkendo/backend/routers/planning_exercise_suggest.py
Lars 9cee862c32
All checks were successful
Deploy Development / deploy (push) Successful in 47s
Test Suite / pytest-backend (push) Successful in 49s
Test Suite / lint-backend (push) Successful in 0s
Test Suite / build-frontend (push) Successful in 15s
Test Suite / k6 /health Baseline (push) Successful in 34s
Test Suite / playwright-tests (push) Successful in 1m26s
Implement Planning Prompt Enhancements and LLM Usage Tracking
- Added new fields for goal query, user notes, max steps, and search query in the AiPromptPreviewBody to support planning prompts.
- Integrated planning prompt handling in the preview_ai_prompt function, allowing for distinct processing of planning and exercise prompts.
- Introduced LLM usage tracking in openrouter_chat_completion and planning_exercise_suggest functions to monitor AI call metrics.
- Updated frontend components to accommodate new input fields for planning prompts, enhancing user experience and functionality.
2026-06-15 07:50:49 +02:00

127 lines
4.7 KiB
Python

"""
POST /api/planning/exercise-suggest — planungsgebundene Übungssuche (Hybrid + Profil + optional LLM-Rerank).
"""
from fastapi import APIRouter, Depends
from db import get_db, get_cursor
from tenant_context import TenantContext, get_tenant_context
from planning_exercise_suggest import PlanningExerciseSuggestRequest, suggest_planning_exercises
from planning_exercise_path_builder import ProgressionPathSuggestRequest, suggest_progression_path
from planning_llm_usage import planning_llm_call_meter
from account_lifecycle import assert_min_account_state
from capabilities import probe_capability
from club_features import (
consume_club_feature_with_usage,
merge_feature_usage_into_response,
probe_club_feature_access,
resolve_club_id_for_probe,
)
router = APIRouter(prefix="/api/planning", tags=["planning_exercise_suggest"])
@router.post("/exercise-suggest")
def post_planning_exercise_suggest(
body: PlanningExerciseSuggestRequest,
tenant: TenantContext = Depends(get_tenant_context),
):
uses_ai = body.include_llm_intent or body.include_llm_rank
club_id = resolve_club_id_for_probe(tenant) if uses_ai else None
if uses_ai:
assert_min_account_state(tenant, "active_member", endpoint="POST /planning/exercise-suggest")
probe_capability(
tenant,
"planning.ai.suggest",
action="planning_suggest",
club_id=club_id,
endpoint="POST /planning/exercise-suggest",
)
probe_club_feature_access(
feature_id="ai_calls",
action="planning_suggest",
club_id=club_id,
profile_id=tenant.profile_id,
portal_role=tenant.global_role,
endpoint="POST /planning/exercise-suggest",
tenant=tenant,
)
with get_db() as conn:
cur = get_cursor(conn)
with planning_llm_call_meter() as llm_meter:
result = suggest_planning_exercises(cur, tenant=tenant, body=body)
if uses_ai and llm_meter.count > 0:
usage = consume_club_feature_with_usage(
feature_id="ai_calls",
club_id=club_id,
profile_id=tenant.profile_id,
portal_role=tenant.global_role,
action="planning_suggest",
amount=llm_meter.count,
cur=cur,
tenant=tenant,
conn=conn,
)
result = merge_feature_usage_into_response(result, usage)
if isinstance(result, dict):
result["llm_call_count"] = llm_meter.count
elif uses_ai and isinstance(result, dict):
result["llm_call_count"] = 0
return result
@router.post("/progression-path-suggest")
def post_progression_path_suggest(
body: ProgressionPathSuggestRequest,
tenant: TenantContext = Depends(get_tenant_context),
):
uses_ai = (
body.include_llm_intent
or body.include_llm_path_qa
or body.include_llm_roadmap
or body.include_llm_start_target
or (body.start_target_only and body.include_llm_start_target)
)
club_id = resolve_club_id_for_probe(tenant) if uses_ai else None
if uses_ai:
assert_min_account_state(
tenant, "active_member", endpoint="POST /planning/progression-path-suggest"
)
probe_capability(
tenant,
"planning.ai.progression_path",
action="progression_path_suggest",
club_id=club_id,
endpoint="POST /planning/progression-path-suggest",
)
probe_club_feature_access(
feature_id="ai_calls",
action="progression_path_suggest",
club_id=club_id,
profile_id=tenant.profile_id,
portal_role=tenant.global_role,
endpoint="POST /planning/progression-path-suggest",
tenant=tenant,
)
with get_db() as conn:
cur = get_cursor(conn)
with planning_llm_call_meter() as llm_meter:
result = suggest_progression_path(cur, tenant=tenant, body=body)
if uses_ai and llm_meter.count > 0:
usage = consume_club_feature_with_usage(
feature_id="ai_calls",
club_id=club_id,
profile_id=tenant.profile_id,
portal_role=tenant.global_role,
action="progression_path_suggest",
amount=llm_meter.count,
cur=cur,
tenant=tenant,
conn=conn,
)
result = merge_feature_usage_into_response(result, usage)
if isinstance(result, dict):
result["llm_call_count"] = llm_meter.count
elif uses_ai and isinstance(result, dict):
result["llm_call_count"] = 0
return result