Spaces:
Sleeping
Sleeping
File size: 2,629 Bytes
e22cec2 b2673e1 e22cec2 b2673e1 e22cec2 b2673e1 e22cec2 647a656 e22cec2 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | import logging
from fastapi import APIRouter, Depends, HTTPException, status
from supabase import Client
from app.schemas.cards import LearningDeckRequest, LearningDeckResponse
from app.services.graph_service import get_existing_skills_for_strand
from app.services.llm_service import generate_learning_deck
from app.core.security import get_user_db_client
logger = logging.getLogger(__name__)
router = APIRouter()
@router.post("/generate-deck", response_model=LearningDeckResponse)
async def create_learning_deck(
request: LearningDeckRequest,
db_data: tuple[Client, str] = Depends(get_user_db_client),
):
db_client, user_id = db_data
try:
# --- 1. MEMORY CHECK (ANTI-CHEAT) ---
# Did the user already scan this exact object under this exact lens?
past_scan = (
db_client.table("scans")
.select("learning_deck")
.eq("user_id", user_id)
.eq("object_name", request.object_name)
.eq("chosen_lens", request.chosen_lens)
.execute()
)
if past_scan.data:
# DUPLICATE FOUND: Return the old deck, bypass Gemini, save API costs!
saved_deck = past_scan.data[0]["learning_deck"]
return LearningDeckResponse(
concept_card=saved_deck.get("concept_card", {}),
real_world_card=saved_deck.get("real_world_card", {}),
challenge_card=saved_deck.get("challenge_card", {}),
is_memory=True, # 🚀 Flag for the mobile UI
)
# --- 2. NEW DISCOVERY (Proceed normally) ---
existing_skills = await get_existing_skills_for_strand(request.chosen_lens)
deck = await generate_learning_deck(
object_name=request.object_name,
strand=request.chosen_lens,
grade_level=request.grade_level,
teaser_context=request.teaser_context,
existing_skills=existing_skills,
)
# Ensure the flag is false for new generations
deck.is_memory = False
return deck
except HTTPException:
raise
except RuntimeError as e:
logger.error(f"Deck Generation Error: {e}")
raise HTTPException(
status_code=status.HTTP_502_BAD_GATEWAY,
detail="Failed to generate the learning deck. The AI might be overloaded.",
)
except Exception as e:
logger.error(f"Unexpected error in /generate-deck: {e}")
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="An internal server error occurred.",
)
|