ESP32-S3 Bench Guide
ESP32‑S3 N16R8 벤치 가이드: 실시간 핀아웃, 강의, 시뮬레이터 및 벤치 로그
PrepAI는 인도 수능·시험 준비생에게 기출문제·모의고사·AI 문제 스캐너·개인 AI 학습 도우미를 제공합니다
PrepAI helps Indian board exam students prepare with question papers, previous-year papers, mock tests, an AI question scanner and a personal AI study assistant.
교육Python · HTMLGitHub @shubhkanojiya온라인운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기clg project2026
저장소 README에서 가져옴
README 전체를 불러오는 중입니다.
README 전문 보기 ↗PrepAI is a full-stack Django platform for Indian students preparing for board examinations (CBSE, ICSE and state boards). Students pick their board, class, subject and chapter, then study notes, solve question papers and previous-year papers, take timed tests, track performance, scan questions with AI, and chat with an AI study assistant.
All educational content (boards, classes, subjects, chapters, topics, questions, papers, tests, materials) is data, managed in Django Admin. There are no hard-coded boards or subjects in the code.
| Layer | What it does | |---|---|the upcoming exam. The estimate uses a transparent formula (appearance rate 60%, recency 25%, concept rate 15%, +5 points if the pattern points to the upcoming year), is capped between 3% and 85%, and always shows the disclaimer. Its accuracy depends on how many real previous-year papers are loaded.
Python 3.12+ · Django 5.2/6.0 · Django REST Framework · django-filter · PostgreSQL (psycopg 3) · Bootstrap 5.3 + Bootstrap Icons · Chart.js · PDF.js · KaTeX · WhiteNoise · Anthropic Python SDK.
git clone <your-repo-url> prepai && cd prepai
python -m venv .venv
# Windows
.venv\Scripts\activate
# macOS / Linux
source .venv/bin/activate
pip install -r requirements.txt
-- psql -U postgres
CREATE DATABASE prepai;
CREATE USER prepai WITH PASSWORD 'change-me';
ALTER DATABASE prepai OWNER TO prepai;
Then set DATABASE_URL=postgres://prepai:change-me@localhost:5432/prepai in .env.
DATABASE_URL must point to a PostgreSQL database (a free one from https://neon.tech works).
cp .env.example .env # Windows: copy .env.example .env
| Variable | Purpose |
|---|---|
DEBUG | True locally, False in production |
SECRET_KEY | Required when DEBUG=False. Generate: `python -c "import secrets; |
| Django templates + Bootstrap 5.3 | Responsive UI with light/dark themes, reusable components |
| Django REST Framework | Versioned REST API at /api/v1/ (session + token auth) |
| PostgreSQL | Database (required) |
services/ai_service.py | Provider-agnostic AI layer (Anthropic Claude by default) |
services/ocr_service.py | Optional OCR step for the scanner (vision model or Tesseract) |
| Django Admin | Complete content workflow with publish/unpublish |
config/ settings, root URLs, API router, WSGI/ASGI
core/ base models, validators, permissions, home, error pages, template tags, seed command
accounts/ custom User (email login), Profile, auth views, auth API
boards/ Board → ClassLevel → Subject → Chapter → Topic + board explorer
questions/ Question bank, options, concepts, historical appearances, frequency analysis
papers/ Question papers, previous-year papers (proxy model), PDF viewer/download
content/ Study material library
testengine/ Tests, attempts, answers, grading, results (the spec's "tests" app*)
bookmarks/ Generic bookmarks
analytics/ Activity log, performance records, analytics queries
recommendations/ Rule-based recommendation engine
notifications/ Notifications + admin announcements
search/ Global search, suggestions, search history
scanner/ AI question scanner + scan history
assistant/ AI study assistant conversations
dashboard/ Student dashboard + analytics pages
services/ ai_service.py, ocr_service.py (no views; pure service layer)
templates/ static/ media/
* Named testengine because a top-level package called tests collides with Python/Django test discovery.
/questions/predictor/) — paste any question, or send one from the AI Scanner. PrepAI matches it to stored questions (exact repeats and reworded versions), shows how many times it appeared, in which years and in which papers (a year-by-year timeline), finds the recurrence pattern (e.g. "about every 2 years → next around 2027"), and gives a history-based likelihood estimate for print(secrets.token_urlsafe(50))"| |ALLOWED_HOSTS, CSRF_TRUSTED_ORIGINS| Comma-separated hostnames / origins | |DATABASE_URL| PostgreSQL URL (required) | |REDIS_URL| Optional cache (installredis) | | AI_PROVIDER|anthropic\|groq\|openrouter\|openai_compatible\|mock\|disabled| |AI_API_KEY, AI_MODELAI_VISION_MODELAI_BASE_URLAI_TIMEOUTAI_MAX_TOKENSAI_EFFORTAI_REFUSAL_FALLBACKOCR_BACKENDvision_llmtesseractnoneTHROTTLE_locals3EMAIL_*DEFAULT_FROM_EMAILGOOGLE_OAUTH_CLIENT_ID/SECRET` | Optional Google sign-in (see below) |No secret is hard-coded anywhere; all configuration is read in config/settings.py.
python manage.py migrate
python manage.py createsuperuser # asks for email, username and password
Admin is at /admin/.
python manage.py runserver
Open http://localhost:8000.
python manage.py seed_demo # idempotent
python manage.py seed_demo --reset # remove existing sample content first
This creates 9 boards (CBSE, ICSE, Maharashtra, Gujarat, Karnataka, Tamil Nadu, UP, Bihar, West Bengal), classes, subjects, chapters, topics, 30 questions, demo papers with generated PDFs, 8 tests, study material, an announcement, and a demo student:
[email protected]demo-student-2026The demo student has three completed attempts, so the dashboard, analytics and recommendations are populated.
All seeded content is flagged
is_sample=Trueand shows a "Sample" badge. Demo "previous-year" papers are titled[Demo] … (sample previous-year format), state that they are not official board papers, and exist only to demonstrate the frequency analysis. Do not present them as real examination statistics. Replace them with real papers before launch.
Put the PDFs in one folder per board → class → subject, named by year:
papers_import/
cbse/10/mathematics/2025.pdf
cbse/10/mathematics/2025-solutions.pdf # attached as the solution PDF
cbse/12/physics/2024-supplementary.pdf # also: term-1, term-2, pre-board, other
msbshse/class-10/science-and-technology-part-1/2023.pdf
Folder names match a board/class/subject slug, name, short name or class number. Subjects must already exist: python manage.py load_subjects creates every board's Class 10/12 subjects listed in boards/catalog.py (or add them in admin).
python manage.py load_subjects # classes + subjects from boards/catalog.py
python manage.py import_papers papers_import --dry-run # preview matches and skips
python manage.py import_papers papers_import # import (safe to re-run)
python manage.py import_papers papers_import --board cbse # only one board folder
python manage.py import_papers papers_import --unpublished # import hidden, review in admin
python manage.py import_papers papers_import --max-mb 120 # allow large scanned PDFs for this import
python manage.py import_papers papers_import_model --paper-type model # boards' official model papers
Existing PDFs are kept unless you pass --replace. Students aren't notified unless you pass --notify. Imported papers show up at /previous-year-papers/, where students filter by board → class → subject → chapter, year and exam, and see a grid of subjects × the last 5 exam years. The same year strip appears on every subject page. Choosing a chapter lists the previous-paper questions tagged to it.
CBSE papers can be fetched straight from cbse.gov.in each year (one set per subject and exam, read from CBSE's zips without downloading them whole):
python manage.py fetch_cbse_papers # → papers_import/cbse/<class>/<subject>/<year>[-supplementary].pdf
python manage.py import_papers papers_import --board cbse
What the other boards' official websites publish (checked October 2026):
| Board | Previous-year papers available officially |
|---|---|
| ICSE / ISC | No standalone papers. CISCE's "Analysis of Pupil Performance" (2023–2025) reproduces the exam questions with marking scheme; imported under that title |
| Maharashtra | 2024–2026, March and July/June exams |
| Gujarat | 2022 only (scanned) |
| Karnataka | SSLC 2022–2026 (all exams), II PUC 2025–2026 |
| Tamil Nadu | 2022–2026 main exams, one combined PDF per year (split per subject on import) |
| UP, Bihar | Model papers only (imported as model, never as previous-year papers) |
| West Bengal | Nothing published |
python manage.py test
63 tests cover the question predictor (matching, years, bounded estimates, patterns, API), grading (MCQ, multi-select, numeric, fill-in-the-blank, subjective), negative marking, deadlines and auto-submit, attempt limits, answer-leak prevention, per-user access control, frequency analysis correctness and disclaimers, AI failure handling (503 plus friendly message, rollback), the Anthropic and Groq/OpenRouter request shapes (mocked SDKs, no network), scanner upload validation, guest scans, accounts and token auth, bookmarks, search filters and recommendations.
All AI calls go through services/ai_service.py. Views never call an SDK directly.
AI_PROVIDER=anthropic
AI_API_KEY=sk-ant-... # or leave empty and set ANTHROPIC_API_KEY
AI_MODEL=claude-opus-5
AI_TIMEOUT=90
AI_EFFORT= # optional: low | medium | high | xhigh | max
AI_REFUSAL_FALLBACK=True
claude-opus-5. Any Claude model ID can be set in AI_MODEL.AI_PROVIDER=groq # or: openrouter
AI_API_KEY=your-provider-key
AI_MODEL= # optional: text model (empty = preset default)
AI_VISION_MODEL= # optional: model used by the scanner for images
groq and openrouter fill in the base URL and default Llama models. For another provider (Together, a self-hosted vLLM/Ollama server, etc.) use AI_PROVIDER=openai_compatible and set AI_BASE_URL. The scanner needs a model that accepts images, and these providers don't enforce the JSON schema, so the response is parsed and fitted to the expected fields. Model IDs change often, so check your provider's model list if you see "model not found".claude-opus-5 (and claude-fable-5-1), requests use the server-side fallback beta (fallbacks="default"), so a declined request is retried on a fallback model within the same call. Set AI_REFUSAL_FALLBACK=False to turn it off.output_config.format) and sends images as base64 content blocks, downscaled to at most 1568 px and EXIF-rotated.AIServiceError. The API returns HTTP 503 with "AI service is temporarily unavailable. Please try again." (or a more specific safe message), and the UI shows a retry button. The site never crashes because of the AI.AI_PROVIDER=mock returns clearly labelled placeholder responses, so every AI screen works without a key. disabled hides AI features behind a friendly notice.BaseAIProvider, implement complete(), and register it in _PROVIDERS.OCR_BACKEND=vision_llm (default) lets the vision model read the image. tesseract runs Tesseract first (install pytesseract and the binary) and passes the text as a hint.THROTTLE_AI_ASSISTANT and THROTTLE_AI_SCANNER cap AI usage per user/IP.%PDF-, and images must decode with Pillow (JPG/PNG/WEBP/GIF). Size limits come from MAX_*_UPLOAD_MB.media/. In development Django serves it; in production serve /media/ from your web server or use S3.pip install django-storages[s3], set STORAGE_BACKEND=s3 and the AWS_* variables. PDF downloads then redirect to signed URLs instead of streaming through Django./papers/<slug>/file/), which counts views and downloads.DEBUG=False, a strong SECRET_KEY, ALLOWED_HOSTS, CSRF_TRUSTED_ORIGINS, DATABASE_URL (PostgreSQL), REDIS_URL (recommended), email and AI settings.pip install -r requirements.txtpython manage.py migratepython manage.py collectstatic --noinput (WhiteNoise serves hashed, compressed assets)python manage.py check --deploy. Fix any prepai.W00x warnings: they flag console email, a missing REDIS_URL and unserved local media.gunicorn config.wsgi:application
gunicorn.conf.py sets threaded workers and a timeout above AI_TIMEOUT, because scanner and assistant requests wait for the AI. Set NUM_PROXIES to the number of proxies in front of the app so rate limits see real client IPs.DEBUG=False, HTTPS redirect, secure cookies and 1-year HSTS are on by default. Forward X-Forwarded-Proto from your proxy.GET /healthz/ (returns 503 if the database is unreachable).Google authentication (optional): the login page shows "Continue with Google" when GOOGLE_OAUTH_CLIENT_ID is set. To enable it, install django-allauth, add its apps, backend and URLs (/accounts/google/login/), and keep EmailOrUsernameBackend in AUTHENTICATION_BACKENDS. The rest of the app needs no changes because users are keyed by email.
notifications/services.py), recommendation regeneration and AI scans to Celery/RQ. Callers already go through service functions.search/services._text_filter can be swapped for PostgreSQL full-text search (SearchVector/SearchRank with GIN indexes), or for OpenSearch/Meilisearch, without changing views.reason per item. An ML ranker can replace generate_for_user behind the same interface.USE_I18N=True), and profiles already store a preferred language that the AI assistant respects./api/v1/auth/login/)./api/v1/)| Endpoint | Methods | Notes |
|---|---|---|
auth/register/, auth/login/, auth/logout/, auth/me/, auth/change-password/, auth/theme/ | POST / GET / PATCH | Token + session auth |
boards/, classes/, subjects/, chapters/, topics/ | GET (staff: write) | Filters e.g. ?board=, ?class_level= |
questions/, questions/{id}/frequency/ | GET | Historical frequency analysis |
questions/predict/ | POST {"text", "board"?, "class_level"?, "subject"?} | Times appeared, years, papers, pattern, likelihood estimate |
papers/, previous-year-papers/, …/{slug}/important-questions/ | GET | Filters: subject, year, type… |
materials/ | GET | |
tests/, tests/{slug}/start/ | GET / POST | |
attempts/, attempts/{id}/questions/, …/answer/, …/submit/, …/result/ | GET / POST | Owner only; no answers leaked before submit |
bookmarks/, bookmarks/toggle/ | GET / POST / DELETE | |
scanner/ | POST (multipart image or question), GET history | Throttled |
assistant/conversations/, …/{id}/messages/ | CRUD / POST | Throttled |
dashboard/, recommendations/, recommendations/{id}/dismiss/ | GET / POST | |
notifications/, …/{id}/read/, …/read-all/, …/unread-count/ | GET / POST | |
search/, search/suggestions/, |
Errors always look like {"error": {"message": "...", "code": "...", "details": ...}}.
, , , , , , | AI configuration (section 13) | ||\|\|| || API rate limits (e.g.60/hour) | | MAX_PDF_UPLOAD_MB, MAX_IMAGE_UPLOAD_MB| Upload limits | |STORAGE_BACKEND+AWS_|ormedia storage | |, | Email (password reset). The console backend prints emails to the terminal | |search/history/| GET / DELETE |