Migrate model_router.rs LLM classifier onto api::OpenAiCompatClient (RC-CRATES-B 3/5) - #23
Conversation
…RC-CRATES-B 3/5)
Switches `ModelRouter::llm_classify` from a raw `reqwest::Client` POST against
Ollama's native `/api/chat` endpoint to `api::OpenAiCompatClient` pointing at
the OpenAI-compatible `/v1/chat/completions` endpoint Ollama exposes.
What goes away:
- Five inline serde structs (`Req`, `Msg`, `Opts`, `Resp`, `RespMsg`)
- The inline `reqwest::Client::builder().timeout(...).build()` plumbing
- The `format!("{base}/api/chat")` URL construction
What replaces it:
- `OpenAiCompatClient::new("", OpenAiCompatConfig::openai()).with_base_url(...)`
with `local_base_url + "/v1"` (Ollama ignores the empty Bearer token)
- `.with_retry_policy(0, ...)` to preserve one-shot semantics (the keyword
classifier is the safety net, so transport retries here would just delay
the inevitable fallback)
- `MessageRequest { max_tokens: 16, system: Some(CLASSIFY_SYSTEM), ... }`
- `tokio::time::timeout(Duration::from_secs(8), ...)` to replace the per-client
reqwest timeout (the api crate doesn't expose a request-level timeout knob)
Behavioural caveat (documented in the module header and TODO.md):
the old payload set `options.temperature = 0.0` and `options.num_predict = 16`
on the Ollama-native call. `MessageRequest` carries `max_tokens` (kept) but
no `temperature`. The classifier therefore no longer pins determinism — the
keyword fallback already catches misclassifications via the `Unknown label`
arm, so accuracy degradation surfaces as a fallback rather than a wrong target.
Adding `temperature` to `api::MessageRequest` is the proper fix and is out
of scope here.
RC-CRATES-B is now 3/5 done. Remaining (`grok_reasoning.rs`,
`ollama_client.rs`) both need additional api-crate capabilities first
(xAI `/responses` endpoint and Ollama-native `num_ctx` / NDJSON streaming).
https://claude.ai/code/session_014DMg4gxA8VZv1MucmM7PV9
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughThis PR migrates the Ollama task classifier in ChangesOllama OpenAI-compatible endpoint migration
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes Poem
✨ Finishing Touches📝 Generate docstrings
🧪 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 |
Summary
Migrates
ModelRouter::llm_classifyfrom rawreqwest::Clientagainst Ollama's native/api/chattoapi::OpenAiCompatClientagainst Ollama's OpenAI-compatible/v1/chat/completions. Brings RC-CRATES-B from 2/5 → 3/5 done.What changed
src/model_router.rs::llm_classify:Req,Msg,Opts,Resp,RespMsg), thereqwest::Client::builder().timeout(...)plumbing, and the/api/chatURL construction.OpenAiCompatClient::new("", OpenAiCompatConfig::openai()).with_base_url(local_base_url + "/v1")(Ollama ignores the empty Bearer token),MessageRequestwithmax_tokens: 16and the system prompt insystem: Some(...), and atokio::time::timeout(8s, ...)wrapper (the api crate doesn't expose a request-level timeout knob).with_retry_policy(0, ...)to preserve the original one-shot semantics — the keyword classifier is the safety net, so transport retries here would just delay the inevitable fallback.Behavioural caveat (documented in module header and TODO.md)
The old payload set
options.temperature = 0.0andoptions.num_predict = 16on the Ollama-native call.api::MessageRequestcarriesmax_tokens(kept as 16) but notemperature, so the classifier no longer pins determinism. The existing keyword fallback already catches misclassifications via theUnknown labelarm, so the regression surfaces as a fallback rather than a wrong target.Adding
temperaturetoapi::MessageRequestis the proper fix and is out of scope for this PR.Note on the TODO description
The TODO had described this as a
GET /api/tagshealth-check. It was actually aPOST /api/chatLLM call (prompt classifier). The TODO entry has been corrected.Test plan
cargo check -p api→ cleancargo check -p rustcode(blocked locally by theort-sysCDN sandbox restriction; CI should verify)tests/test_grok_integration.rs::test_model_router_async_classification_matches_keyword_fallbackstill passes (it expects keyword fallback when Ollama is unreachable, which is unchanged behaviour)Remaining RC-CRATES-B work
src/grok_reasoning.rs— uses xAI's/responsesendpoint; needs api-crate extensionsrc/ollama_client.rs— depends on Ollama-nativenum_ctxand NDJSON streaming; needs api-crate extension or accepted feature losshttps://claude.ai/code/session_014DMg4gxA8VZv1MucmM7PV9
Generated by Claude Code
Summary by CodeRabbit
Refactor
Documentation