mirror of
https://github.com/whit3rabbit/anyllm-proxy.git
synced 2026-09-22 08:00:51 +00:00
fix: reject unknown models when model router is active (#13)
* fix: reject unknown models when model router is active * fix: use existing invalid request error for model router
This commit is contained in:
@@ -270,6 +270,9 @@ impl ChatCompletionRuntime {
|
||||
"all deployments for this model are at their RPM limit".to_string(),
|
||||
));
|
||||
}
|
||||
return Err(ChatCompletionError::InvalidRequest(format!(
|
||||
"model '{model}' is not configured in model_list"
|
||||
)));
|
||||
}
|
||||
|
||||
let state = self
|
||||
|
||||
@@ -96,6 +96,14 @@ pub(crate) async fn bedrock_passthrough(
|
||||
);
|
||||
return (StatusCode::TOO_MANY_REQUESTS, Json(err)).into_response();
|
||||
}
|
||||
super::state::ResolvedModel::UnknownModel => {
|
||||
let err = anyllm_translate::mapping::errors_map::create_anthropic_error(
|
||||
anyllm_translate::anthropic::ErrorType::InvalidRequestError,
|
||||
format!("model '{}' is not configured in model_list", model_id),
|
||||
None,
|
||||
);
|
||||
return (StatusCode::BAD_REQUEST, Json(err)).into_response();
|
||||
}
|
||||
super::state::ResolvedModel::Legacy(m) => m,
|
||||
};
|
||||
|
||||
|
||||
@@ -52,6 +52,8 @@ pub(crate) enum ResolvedModel {
|
||||
},
|
||||
/// Model is known but all deployments are at their RPM limit.
|
||||
AllAtLimit,
|
||||
/// Model router is active but the model alias is not configured.
|
||||
UnknownModel,
|
||||
/// No model router, or model not in router. Used legacy ModelMapping.
|
||||
Legacy(String),
|
||||
}
|
||||
@@ -140,6 +142,7 @@ impl AppState {
|
||||
if router.has_model(model) {
|
||||
return ResolvedModel::AllAtLimit;
|
||||
}
|
||||
return ResolvedModel::UnknownModel;
|
||||
}
|
||||
ResolvedModel::Legacy(self.map_model(model))
|
||||
}
|
||||
@@ -200,6 +203,14 @@ impl AppState {
|
||||
);
|
||||
Err((StatusCode::TOO_MANY_REQUESTS, Json(err)).into_response())
|
||||
}
|
||||
ResolvedModel::UnknownModel => {
|
||||
let err = mapping::errors_map::create_anthropic_error(
|
||||
anthropic::ErrorType::InvalidRequestError,
|
||||
format!("model '{model}' is not configured in model_list"),
|
||||
None,
|
||||
);
|
||||
Err((StatusCode::BAD_REQUEST, Json(err)).into_response())
|
||||
}
|
||||
ResolvedModel::Legacy(mapped) => Ok((mapped, self.clone(), None)),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -198,6 +198,42 @@ async fn runtime_model_router_selects_backend_and_mapped_model() {
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn runtime_model_router_rejects_unconfigured_model() {
|
||||
let captured_a = Arc::new(Mutex::new(None));
|
||||
let base_a = spawn_json_backend(captured_a.clone(), chat_response("unused")).await;
|
||||
|
||||
let mut backends = IndexMap::new();
|
||||
backends.insert("a".to_string(), backend_config(BackendKind::OpenAI, base_a));
|
||||
|
||||
let deployment = Arc::new(anyllm_proxy::config::model_router::Deployment::new(
|
||||
"a".to_string(),
|
||||
"actual-model".to_string(),
|
||||
None,
|
||||
None,
|
||||
));
|
||||
let mut routes = HashMap::new();
|
||||
routes.insert("virtual-model".to_string(), vec![deployment]);
|
||||
let router = Arc::new(RwLock::new(
|
||||
anyllm_proxy::config::model_router::ModelRouter::new(routes),
|
||||
));
|
||||
|
||||
let runtime = ChatCompletionRuntime::from_multi_config_with_model_router(
|
||||
multi_config(backends, "a"),
|
||||
Some(router),
|
||||
);
|
||||
let req = serde_json::from_value(json!({
|
||||
"model": "unconfigured-model",
|
||||
"messages": [{"role": "user", "content": "hello"}],
|
||||
"max_tokens": 32
|
||||
}))
|
||||
.unwrap();
|
||||
|
||||
let err = runtime.complete(req).await.unwrap_err();
|
||||
assert!(matches!(err, ChatCompletionError::InvalidRequest(_)));
|
||||
assert!(captured_a.lock().unwrap().is_none());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn runtime_returns_typed_error_for_unsupported_backend() {
|
||||
let mut backends = IndexMap::new();
|
||||
|
||||
Reference in New Issue
Block a user