Uh oh!
There was an error while loading. Please reload this page.
perf(tutor): cap Pro thinking budget + switch Fast to Flash-Lite - #80
Conversation
Smart was taking too long because Pro ran with dynamic thinking (`thinking_budget=-1`) — Gemini decided how long to think and could spend 10s+ in the planning phase before any tokens streamed. Cap it at 2048 tokens, which keeps multi-step pedagogical reasoning intact for tutor-length responses while shaving meaningful latency off every Smart turn. Applied in both the legacy `call_gemini_multiturn` path (`gemini_service.py:114`) and the agent path via a new `_build_pro_model_settings()` helper that's threaded into `agent.run()` whenever the effective model is Pro (explicit "smart" or no-pref → agent default). Fast was already lighter than Smart but still on `gemini-2.5-flash`. Switch the "fast" mapping to `gemini-2.5-flash-lite` (Lite) — same model the quiz route already uses as its baseline per ADR 0008. Fast becomes meaningfully cheaper + snappier, with the explicit "opt-in for speed" semantics the tooltip describes. Quiz route's `_PREF_MODEL_NAMES` and legacy fallback are updated in lockstep — ADR 0013 keeps these two routes symmetric so a user choosing "fast" gets the same model whether they're on Learn or Quiz. Tests: 4 tests rewritten to assert the new mappings; full backend suite green except the 3 pre-existing live-Supabase failures (same baseline as PR #71 / #78). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Warning Rate limit exceeded
To keep reviews running without waiting, you can enable usage-based add-on for your organization. This allows additional reviews beyond the hourly cap. Account admins can enable it under billing. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (8)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Deploying with |
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs | frontend | abd93a1 | Commit Preview URL Branch Preview URL | May 05 2026, 04:59 AM |
…tings, doc agent sharp edge - Drop unused MODEL_DEFAULT import from routes/quiz.py (last caller replaced by MODEL_LITE in this PR; learn.py already pruned theirs). - Add 3 tests pinning the model_settings contract that previously had no coverage: - test_smart_pref_attaches_thinking_cap — asserts budget == 2048 (regression guard against accidentally restoring dynamic thinking) - test_no_pref_attaches_thinking_cap — confirms no-pref → Pro default still gets capped, not just explicit "smart" - test_fast_pref_does_not_attach_thinking_cap — confirms Lite runs skip thinking_config (it'd be wasted at best) - Document the route-layer-only enforcement on agents/chat_tutor.py so any future direct caller of chat_tutor_agent.run(...) knows the cap isn't on the agent itself. 73 targeted + 581 full suite pass; same 3 pre-existing live-Supabase failures as the baseline. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Add legacy-path thinking-budget tests in test_gemini_service.py: - test_pro_uses_capped_thinking_budget — pins 2048 on Pro - test_flash_disables_thinking — pins 0 on Flash + Flash-Lite Symmetric to the agent-path coverage in test_learn_routes.py so a refactor can't silently restore Pro to dynamic (-1) on either side. - Split the chained `budget == _PRO_THINKING_BUDGET == 2048` assertion into two lines for readability — same regression guarantee. - Add direct unit test on `_build_pro_model_settings` so the helper's contract is pinned even if the integration tests above are refactored. - Update tooltip copy in ModelToggle.tsx — drop "don't mind waiting" framing now that Smart's thinking is capped (it's snappier than the old copy implied). 100 targeted + 584 full suite pass; same 3 pre-existing live-Supabase failures. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Summary
gemini-2.5-prothinking budget at 2048 tokens (was dynamic / unbounded). Applies on both the legacycall_gemini_multiturnpath (services/gemini_service.py) and the agent path via a new_build_pro_model_settings()helper threaded intoagent.run()whenever the effective model is Pro."fast"mapping fromgemini-2.5-flash→gemini-2.5-flash-litein bothroutes/learn.pyandroutes/quiz.py(kept symmetric per ADR 0013).Why
User-reported: "Smart is taking too long to think." Pro on dynamic thinking can spend 10s+ in the planning phase before streaming any tokens. 2048 tokens is enough for a multi-step pedagogical explanation without burning latency the student can feel — strong reasoning, snappier response. Tunable via
_PRO_THINKING_BUDGETinroutes/learn.pyand the2048literal inservices/gemini_service.py:114if we want to dial further.Fast was already lighter than Smart but still on full Flash. Lite gives meaningfully cheaper + snappier responses for the "I just want a quick answer" use case the tooltip describes.
Behavior matrix
"fast"gemini-2.5-flash-lite"smart"gemini-2.5-progemini-2.5-pro(agent default)Test plan
python -m pytest tests/test_learn_routes.py tests/test_quiz_routes.py tests/test_chat_tutor_imports.py -q— 70 passpython -m pytest tests/ -q --ignore=tests/evals— 597 pass; 3 pre-existing live-Supabase failures unchanged (test_skips_self_edges,test_save_to_db,test_full_pipeline— same baseline as PR refactor(quiz): convert generate_quiz to quiz_agent (refactor #2) #71 / refactor(learn): convert chat tutor to chat_tutor_agent (refactor #3) #78)test_fast_returns_lite,test_fast_pref_overrides_agent_model(×2 — learn + quiz),test_legacy_fallback_uses_lite_when_pref_fastNotes
_PREF_MODEL_NAMESdicts and the legacy quiz fallback all resolve"fast"→ Lite identically.model_prefwire format unchanged.🤖 Generated with Claude Code