Quota-based model switching + thinking mode fixes #9

Merged
code-server merged 3 commits from feat/rate-limit-tracking into main 2026-02-15 14:14:46 +01:00
Owner

Summary

  • Dynamic Opus/Sonnet model switching based on rolling quota burn rate (_select_model_based_on_quota() in loop.py). Reads rate_limits.json, compares actual vs expected usage, switches to Sonnet when burning too fast
  • System message handler now uses quota-selected model instead of hardcoded self.model
  • Loguru format strings fixed from printf-style (%s/%d) to {} — previous format printed literal %s instead of values
  • Consolidated response logging into a single line showing stop_reason, tool_calls, thinking chars, and token usage

Changes

  • nanobot/agent/loop.py: Added _select_model_based_on_quota(), applied to both main loop and system handler, added debug logging for model selection
  • nanobot/providers/anthropic_oauth.py: Fixed loguru format strings, consolidated response logging, added tool count to request logging

Test plan

  • Verified quota-based switching works (logs show Quota: 95% used → Sonnet)
  • Verified thinking mode works (API returns thinking blocks, model uses tools)
  • Verified logging shows correct values (no more literal %s)
  • Deployed to production and tested via Telegram
## Summary - **Dynamic Opus/Sonnet model switching** based on rolling quota burn rate (`_select_model_based_on_quota()` in loop.py). Reads `rate_limits.json`, compares actual vs expected usage, switches to Sonnet when burning too fast - **System message handler** now uses quota-selected model instead of hardcoded `self.model` - **Loguru format strings** fixed from printf-style (`%s/%d`) to `{}` — previous format printed literal `%s` instead of values - **Consolidated response logging** into a single line showing stop_reason, tool_calls, thinking chars, and token usage ## Changes - `nanobot/agent/loop.py`: Added `_select_model_based_on_quota()`, applied to both main loop and system handler, added debug logging for model selection - `nanobot/providers/anthropic_oauth.py`: Fixed loguru format strings, consolidated response logging, added tool count to request logging ## Test plan - [x] Verified quota-based switching works (logs show `Quota: 95% used → Sonnet`) - [x] Verified thinking mode works (API returns thinking blocks, model uses tools) - [x] Verified logging shows correct values (no more literal `%s`) - [x] Deployed to production and tested via Telegram
wylab added 3 commits 2026-02-15 14:01:19 +01:00
feat: dynamic Opus/Sonnet model switching based on rolling quota
Build Nanobot OAuth / build (pull_request) Successful in 5m34s
Build Nanobot OAuth / cleanup (pull_request) Has been skipped
ece660ae69
Implement intelligent model selection to manage 7-day Opus quota burn rate:

- Add _select_model_based_on_quota() method to AgentLoop
  - Reads rate limit data from memory/rate_limits.json
  - Calculates expected vs actual quota usage (100%/168h = 0.595% per hour)
  - If actual > expected × 1.17 (17% overage), downgrades to Sonnet
  - If actual ≤ expected, uses Opus
  - Caches decision for 5 minutes to minimize file I/O

- Add /quota slash command to display real-time quota status
  - Shows current usage vs expected usage
  - Shows hours until weekly reset
  - Shows selected model and burn rate multiplier

- Main agent now calls _select_model_based_on_quota() before each conversation
  - Heartbeat subagent unaffected (explicitly uses claude-sonnet-4-20250514)

This replaces the wrong approach from PR #5 which throttled heartbeat
frequency instead of switching the main agent's model.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
The system message handler was using self.model instead of the
quota-selected model, bypassing the Opus/Sonnet switching logic.
Also added debug logging for model selection and thinking_budget.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
fix: loguru format strings and consolidate response logging
Build Nanobot OAuth / build (pull_request) Successful in 5m58s
Build Nanobot OAuth / cleanup (pull_request) Has been skipped
c0a87d77fc
- Changed printf-style (%s/%d) to loguru format ({}) in 3 log statements
- Consolidated response logging into a single line showing stop_reason,
  tool_calls count, thinking chars, and token usage
- Added tool count to request logging

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Author
Owner

Code Review: PR #9 APPROVED

Summary

Comprehensive implementation that addresses multiple issues in a single coherent PR:

  • Quota-based Opus/Sonnet model switching
  • System message handler model selection fix
  • Critical loguru format string bug fixes
  • Improved consolidated logging
  • Production tested and deployed

Key Strengths

1. Complete Solution: This PR supersedes PR #6 by including additional critical fixes beyond just quota management.

2. Critical Bug Fix: The loguru format string correction (%s/%d{}) fixes a production logging bug where literal %s was being printed instead of actual values.

3. Model Selection Fix: Both the main agent loop AND system message handler now correctly use the quota-selected model (not hardcoded self.model).

4. Production Validated: Already deployed and tested via Telegram, reducing merge risk.

Changes Verified

  • _select_model_based_on_quota() implementation is sound
  • 5-minute cache prevents excessive file I/O
  • Safe fallback to Sonnet if rate_limits.json missing
  • System handler uses selected_model correctly
  • Loguru format strings fixed throughout
  • Response logging consolidated for better debuggability

Minor Observations

  1. Branch naming: feat/rate-limit-tracking is confusing since closed PR #5 used the same name. Consider renaming to feat/quota-switching-and-fixes for clarity.

  2. No breaking changes: All changes are additive or bug fixes. Safe to merge.

Recommendation

MERGE IMMEDIATELY

This is the most complete implementation of the quota management system. PR #6 has been closed in favor of this PR.


Post-merge monitoring:

  • Watch for quota-based model switching in logs
  • Verify thinking mode continues to work correctly
  • Monitor 7-day burn rate to tune tolerance threshold if needed
## Code Review: PR #9 ✅ APPROVED ### Summary Comprehensive implementation that addresses multiple issues in a single coherent PR: - ✅ Quota-based Opus/Sonnet model switching - ✅ System message handler model selection fix - ✅ Critical loguru format string bug fixes - ✅ Improved consolidated logging - ✅ Production tested and deployed ### Key Strengths **1. Complete Solution**: This PR supersedes PR #6 by including additional critical fixes beyond just quota management. **2. Critical Bug Fix**: The loguru format string correction (`%s`/`%d` → `{}`) fixes a production logging bug where literal `%s` was being printed instead of actual values. **3. Model Selection Fix**: Both the main agent loop AND system message handler now correctly use the quota-selected model (not hardcoded `self.model`). **4. Production Validated**: Already deployed and tested via Telegram, reducing merge risk. ### Changes Verified - [x] `_select_model_based_on_quota()` implementation is sound - [x] 5-minute cache prevents excessive file I/O - [x] Safe fallback to Sonnet if `rate_limits.json` missing - [x] System handler uses `selected_model` correctly - [x] Loguru format strings fixed throughout - [x] Response logging consolidated for better debuggability ### Minor Observations 1. **Branch naming**: `feat/rate-limit-tracking` is confusing since closed PR #5 used the same name. Consider renaming to `feat/quota-switching-and-fixes` for clarity. 2. **No breaking changes**: All changes are additive or bug fixes. Safe to merge. ### Recommendation **MERGE IMMEDIATELY** ✅ This is the most complete implementation of the quota management system. PR #6 has been closed in favor of this PR. --- **Post-merge monitoring**: - Watch for quota-based model switching in logs - Verify thinking mode continues to work correctly - Monitor 7-day burn rate to tune tolerance threshold if needed
code-server merged commit d0b0284189 into main 2026-02-15 14:14:46 +01:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: wylab/nanobot#9