Conversation
Greptile SummaryThis PR implements a new endpoint for generating 10 flashcards via Gemini AI with difficulty levels and Supabase storage. The implementation includes comprehensive validation, well-structured prompts, and extensive unit tests. Major Issues:
Positive aspects:
Confidence Score: 1/5
Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[Client sends POST request] --> B[Validate request body]
B --> C{text or topic provided?}
C -->|No| D[Return 422 error]
C -->|Yes| E[Build prompt with difficulty]
E --> F[Call Gemini API]
F --> G{Response valid?}
G -->|No| H[Return 500 error]
G -->|Yes| I[Parse and validate JSON]
I --> J{Exactly 10 flashcards?}
J -->|No| H
J -->|Yes| K[Insert into Supabase]
K --> L{Insert successful?}
L -->|No| M[Return 500 error]
L -->|Yes| N[Return flashcards to client]
Last reviewed commit: 68850ee |
| }, | ||
| "dependencies": { | ||
| "@supabase/supabase-js": "^2.97.0", | ||
| "@supabase/supabase-js": "^2.98.0", |
There was a problem hiding this comment.
Update to @supabase/supabase-js ^2.98.0 not mentioned in PR description. Verify this change is intentional.
There was a problem hiding this comment.
Must have happened by accident, I can revert or if its fine, we can keep version 2.98
| print(f"[flashcards] Failed to parse JSON: {e}") | ||
| print(f"[flashcards] Raw response: {raw_response}") |
There was a problem hiding this comment.
Use logger.error() instead of print() for consistency
| print(f"[flashcards] Failed to parse JSON: {e}") | |
| print(f"[flashcards] Raw response: {raw_response}") | |
| logger.error(f"[flashcards] Failed to parse JSON: {e}") | |
| logger.debug(f"[flashcards] Raw response: {raw_response}") |
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
There was a problem hiding this comment.
dosent match our coding style, ignore this
| "cards": [fc.model_dump() for fc in flashcards], | ||
| }).execute() | ||
| except Exception as e: | ||
| print(f"[flashcards] DB insert failed: {e}") |
There was a problem hiding this comment.
Use logger.error() instead of print() for consistency
| print(f"[flashcards] DB insert failed: {e}") | |
| logger.error(f"[flashcards] DB insert failed: {e}") |
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
There was a problem hiding this comment.
dosent match our coding style, ignore this
| sb = get_supabase() | ||
| try: | ||
| sb.table("flashcards").insert({ | ||
| "user_id": user["user_id"] if user else "00000000-0000-0000-0000-000000000001", |
There was a problem hiding this comment.
All unauthenticated users share the same fallback user_id. When auth is not required, multiple users' flashcards will be mixed under this single UUID, causing data integrity issues.
…cause rate limit keeps getting hit
5db16a4 to
68850ee
Compare
| sb.table("flashcards").insert({ | ||
| "user_id": user["user_id"] if user else "00000000-0000-0000-0000-000000000001", | ||
| "source_text": request.text, | ||
| "topic": request.topic, | ||
| "difficulty": difficulty, | ||
| "cards": [fc.model_dump() for fc in flashcards], | ||
| }).execute() |
There was a problem hiding this comment.
No migration file creates the flashcards table. This will fail at runtime with "relation does not exist".
There was a problem hiding this comment.
NA as we're using supabase
Feature(Flashcard Generation Endpoint 5.1): Implement endpoint to generate 10 Q/A flashcards via Gemini.
🎉 New feature (Extends application, non-breaking feature)
PR Summary
This PR introduces the Flashcard Generation Endpoint, which generates exactly 10 question-and-answer flashcards using Gemini. The endpoint validates input, enforces structured JSON output, supports difficulty levels, and stores the generated flashcards in Supabase.
Overview
What feature/problem does this PR address?
This PR introduces a new endpoint that generates 10 flashcards from the provided notes or topic, ensures the output is returned in a consistent and structured JSON format, validates the correctness and formatting of the response from Gemini, and stores each flashcard along with its difficulty level and source input.
What approach was taken?
POST /api/v1/flashcardsendpoint in FastAPI.FlashcardRequestaccepts eithertext(notes) ortopicas input, with an optionaldifficultyfield (easy,medium,hard) defaulting tomedium.FlashcardDifficultyintroduced as astrEnum to enforce valid difficulty values.parse_and_validate_flashcards()helper to enforce strict JSON structure from Gemini — exactly 10 flashcards, each with a non-emptyquestionandanswer.build_flashcard_generation_prompt()added toprompts/study_gen_v1.py, consistent with existing prompt architecture.flashcardstable withuser_id,source_text,topic,difficulty, andcardscolumns.test_flashcards_unit.py(mocked) to manage quota usage.Any important design decisions or trade-offs?
study_gen_v1.pyrather than inline in the route, keepingmain.pyconsistent with the existing codebase pattern.user_idis pulled from the authenticated user viarequire_user, ensuring flashcards are always associated with the correct user.Checklist
Unit Test Evidence
Testing Method
Additional Notes
API Quota Warning: use
test_flashcards_unit.pyfor regular development as curl testing consumes Gemini quota by making real API calls.Environment Setup: Ensure
GEMINI_API_KEYandSUPABASE_URLandSUPABASE_SERVICE_ROLE_KEYare set in the root.envfile before running.Jira Ticket
Jira Ticket(s) - [SOC-26]