mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-27 06:13:07 +00:00
refactor(inference): rename RouteError to Error (#47771)
Every other crate names its error Error. The format crates already re-exported it under that name, so only the inference crate and a few importers change
This commit is contained in:
parent
3f93350411
commit
b6f91a221b
20 changed files with 104 additions and 104 deletions
|
|
@ -72,26 +72,26 @@ fn duration(seconds: f64) -> Result<Duration, Error> {
|
|||
#[derive(Clone, Default)]
|
||||
pub(crate) struct CacheHeaders(std::sync::Arc<std::sync::OnceLock<String>>);
|
||||
|
||||
impl litellm_host::interceptors::Interceptors<litellm_inference::RouteError> for CacheHeaders {
|
||||
impl litellm_host::interceptors::Interceptors<litellm_inference::Error> for CacheHeaders {
|
||||
async fn before_provider_request(
|
||||
&self,
|
||||
wire: litellm_host::interceptors::WireRequest,
|
||||
_: litellm_host::interceptors::RequestContext,
|
||||
) -> Result<litellm_host::interceptors::WireRequest, litellm_inference::RouteError> {
|
||||
) -> Result<litellm_host::interceptors::WireRequest, litellm_inference::Error> {
|
||||
Ok(wire)
|
||||
}
|
||||
|
||||
async fn after_provider_response(
|
||||
&self,
|
||||
_: litellm_host::interceptors::RawResponse,
|
||||
) -> Result<(), litellm_inference::RouteError> {
|
||||
) -> Result<(), litellm_inference::Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn result_ready(
|
||||
&self,
|
||||
facts: litellm_host::interceptors::ExecutionFacts,
|
||||
) -> Result<(), litellm_inference::RouteError> {
|
||||
) -> Result<(), litellm_inference::Error> {
|
||||
if let litellm_host::interceptors::ResultSource::Cache { key } = facts.source {
|
||||
let _ = self.0.set(key);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ use axum::{
|
|||
response::{IntoResponse, Response},
|
||||
};
|
||||
use litellm_http::transport::Error as TransportError;
|
||||
use litellm_inference::RouteError;
|
||||
use litellm_inference::Error as InferenceError;
|
||||
use litellm_llms::base_llm::ocr::error::Error as OcrError;
|
||||
use serde_json::{Map, Value, json};
|
||||
|
||||
|
|
@ -19,7 +19,7 @@ pub enum Error {
|
|||
)]
|
||||
UnknownModel(String),
|
||||
#[error(transparent)]
|
||||
Route(#[from] RouteError),
|
||||
Route(#[from] InferenceError),
|
||||
#[error(transparent)]
|
||||
Ocr(#[from] OcrError),
|
||||
#[error("{0} is not implemented by the Rust gateway")]
|
||||
|
|
@ -36,8 +36,8 @@ impl IntoResponse for Error {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<litellm_host_http::Error<RouteError>> for Error {
|
||||
fn from(error: litellm_host_http::Error<RouteError>) -> Self {
|
||||
impl From<litellm_host_http::Error<InferenceError>> for Error {
|
||||
fn from(error: litellm_host_http::Error<InferenceError>) -> Self {
|
||||
match error {
|
||||
litellm_host_http::Error::Call(error) => Self::Route(error),
|
||||
litellm_host_http::Error::Protocol => Self::Internal(error.to_string()),
|
||||
|
|
@ -50,7 +50,7 @@ impl Error {
|
|||
match self {
|
||||
Self::Auth(error) => error.status(),
|
||||
Self::Unsupported(_)
|
||||
| Self::Route(RouteError::Unsupported(_))
|
||||
| Self::Route(InferenceError::Unsupported(_))
|
||||
| Self::Ocr(OcrError::Unsupported(_)) => StatusCode::NOT_IMPLEMENTED,
|
||||
Self::BodyTooLarge => StatusCode::PAYLOAD_TOO_LARGE,
|
||||
Self::Ocr(
|
||||
|
|
@ -64,10 +64,10 @@ impl Error {
|
|||
.and_then(|status| StatusCode::from_u16(status).ok())
|
||||
.unwrap_or(StatusCode::INTERNAL_SERVER_ERROR),
|
||||
Self::InvalidBody(_) | Self::UnknownModel(_) => StatusCode::BAD_REQUEST,
|
||||
Self::Route(RouteError::Transport(TransportError::Http { status, .. })) => {
|
||||
Self::Route(InferenceError::Transport(TransportError::Http { status, .. })) => {
|
||||
StatusCode::from_u16(*status).unwrap_or(StatusCode::BAD_GATEWAY)
|
||||
}
|
||||
Self::Route(RouteError::Auth(litellm_auth::Error::MissingApiKey { .. })) => {
|
||||
Self::Route(InferenceError::Auth(litellm_auth::Error::MissingApiKey { .. })) => {
|
||||
StatusCode::UNAUTHORIZED
|
||||
}
|
||||
Self::Route(error) if error.is_request() => StatusCode::BAD_REQUEST,
|
||||
|
|
@ -97,7 +97,9 @@ impl Error {
|
|||
/// body already in that shape passes through, any other has its message extracted.
|
||||
pub fn body(&self, request_id: Option<&str>) -> Value {
|
||||
let raw = match self {
|
||||
Self::Route(RouteError::Transport(TransportError::Http { body, .. })) => body.clone(),
|
||||
Self::Route(InferenceError::Transport(TransportError::Http { body, .. })) => {
|
||||
body.clone()
|
||||
}
|
||||
other => other.to_string(),
|
||||
};
|
||||
let parsed = serde_json::from_str::<Value>(&raw).ok();
|
||||
|
|
@ -175,7 +177,7 @@ mod tests {
|
|||
use super::*;
|
||||
|
||||
fn upstream(status: u16, body: &str) -> Error {
|
||||
Error::Route(RouteError::Transport(TransportError::Http {
|
||||
Error::Route(InferenceError::Transport(TransportError::Http {
|
||||
status,
|
||||
body: body.into(),
|
||||
}))
|
||||
|
|
@ -225,16 +227,16 @@ mod tests {
|
|||
|
||||
#[rstest]
|
||||
#[case::upstream_status(upstream(429, ""), StatusCode::TOO_MANY_REQUESTS)]
|
||||
#[case::rejected_request(Error::Route(RouteError::InvalidRequest("top_k".into())), StatusCode::BAD_REQUEST)]
|
||||
#[case::rejected_request(Error::Route(InferenceError::InvalidRequest("top_k".into())), StatusCode::BAD_REQUEST)]
|
||||
#[case::missing_key(
|
||||
Error::Route(RouteError::Auth(litellm_auth::Error::MissingApiKey {
|
||||
Error::Route(InferenceError::Auth(litellm_auth::Error::MissingApiKey {
|
||||
provider: "Anthropic",
|
||||
environment_variable: "ANTHROPIC_API_KEY",
|
||||
})),
|
||||
StatusCode::UNAUTHORIZED,
|
||||
)]
|
||||
#[case::lost_connection(
|
||||
Error::Route(RouteError::Transport(TransportError::Network("reset".into()))),
|
||||
Error::Route(InferenceError::Transport(TransportError::Network("reset".into()))),
|
||||
StatusCode::INTERNAL_SERVER_ERROR,
|
||||
)]
|
||||
fn status_follows_who_is_at_fault(#[case] error: Error, #[case] status: StatusCode) {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use litellm_host::observation::ObservationSender;
|
||||
pub mod route;
|
||||
pub mod types;
|
||||
pub use litellm_inference::RouteError as Error;
|
||||
pub use litellm_inference::Error;
|
||||
mod common_utils;
|
||||
pub mod constants;
|
||||
pub(crate) mod handler;
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ use litellm_host::{
|
|||
lifecycle::{CallEvent, ExecutionEvent},
|
||||
observation::observation_channel,
|
||||
};
|
||||
use litellm_inference::RouteError;
|
||||
use litellm_inference::Error;
|
||||
use rstest::{fixture, rstest};
|
||||
use serde_json::{Value, json};
|
||||
|
||||
|
|
@ -166,12 +166,12 @@ struct ChangingHooks {
|
|||
facts: std::sync::Mutex<Vec<ExecutionFacts>>,
|
||||
}
|
||||
|
||||
impl Interceptors<RouteError> for ChangingHooks {
|
||||
impl Interceptors<Error> for ChangingHooks {
|
||||
async fn before_provider_request(
|
||||
&self,
|
||||
mut wire: WireRequest,
|
||||
_: RequestContext,
|
||||
) -> Result<WireRequest, RouteError> {
|
||||
) -> Result<WireRequest, Error> {
|
||||
let call = self.calls.fetch_add(1, Ordering::SeqCst);
|
||||
if self.rewrite {
|
||||
wire.body["temperature"] = json!(if call < 2 { 0.1 } else { 0.8 });
|
||||
|
|
@ -179,11 +179,11 @@ impl Interceptors<RouteError> for ChangingHooks {
|
|||
Ok(wire)
|
||||
}
|
||||
|
||||
async fn after_provider_response(&self, _: RawResponse) -> Result<(), RouteError> {
|
||||
async fn after_provider_response(&self, _: RawResponse) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn result_ready(&self, facts: ExecutionFacts) -> Result<(), RouteError> {
|
||||
async fn result_ready(&self, facts: ExecutionFacts) -> Result<(), Error> {
|
||||
self.facts.lock().unwrap().push(facts);
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ use std::sync::Arc;
|
|||
|
||||
use crate::common_utils::messages_provider;
|
||||
|
||||
pub use litellm_inference::RouteError as Error;
|
||||
pub use litellm_inference::Error;
|
||||
pub use types::{
|
||||
MessagesCall, MessagesCallResponse, MessagesSettings, MessagesShaping, litellm_params,
|
||||
messages_body,
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ use litellm_host::interceptors::{
|
|||
ResultSource, WireRequest,
|
||||
};
|
||||
use litellm_inference::{
|
||||
RouteError,
|
||||
Error,
|
||||
caching::{CacheRequest, execute_unary},
|
||||
};
|
||||
use rstest::{fixture, rstest};
|
||||
|
|
@ -133,12 +133,12 @@ struct ChangingHooks {
|
|||
facts: std::sync::Mutex<Vec<ExecutionFacts>>,
|
||||
}
|
||||
|
||||
impl Interceptors<RouteError> for ChangingHooks {
|
||||
impl Interceptors<Error> for ChangingHooks {
|
||||
async fn before_provider_request(
|
||||
&self,
|
||||
mut wire: WireRequest,
|
||||
_: RequestContext,
|
||||
) -> Result<WireRequest, RouteError> {
|
||||
) -> Result<WireRequest, Error> {
|
||||
let call = self.calls.fetch_add(1, Ordering::SeqCst);
|
||||
if self.rewrite {
|
||||
wire.body["temperature"] = json!(if call < 2 { 0.1 } else { 0.8 });
|
||||
|
|
@ -146,11 +146,11 @@ impl Interceptors<RouteError> for ChangingHooks {
|
|||
Ok(wire)
|
||||
}
|
||||
|
||||
async fn after_provider_response(&self, _: RawResponse) -> Result<(), RouteError> {
|
||||
async fn after_provider_response(&self, _: RawResponse) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn result_ready(&self, facts: ExecutionFacts) -> Result<(), RouteError> {
|
||||
async fn result_ready(&self, facts: ExecutionFacts) -> Result<(), Error> {
|
||||
self.facts.lock().unwrap().push(facts);
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,4 +3,4 @@
|
|||
- The route returns its completed response directly
|
||||
- Route closures supply OCR-specific host capabilities, such as the caller's Azure AD token provider (`src/route.rs`)
|
||||
- Provider code reaches the caller's hooks mid-call only through `litellm_llms::base_llm::ocr::handler::CallHooks`, which this crate implements over its host until it folds into `litellm_host::interceptors::Interceptors`
|
||||
- OCR failures use `base_llm/ocr/error.rs`, the recorded exception to `litellm_inference::RouteError` until OCR folds into `litellm_llms::Error`
|
||||
- OCR failures use `base_llm/ocr/error.rs`, the recorded exception to `litellm_inference::Error` until OCR folds into `litellm_llms::Error`
|
||||
|
|
|
|||
|
|
@ -249,7 +249,7 @@ pub(crate) fn resolve_provider_config<'a>(
|
|||
provider: LlmProviders::Mistral,
|
||||
}
|
||||
}
|
||||
Err(litellm_inference::RouteError::InvalidProvider(provider)) => {
|
||||
Err(litellm_inference::Error::InvalidProvider(provider)) => {
|
||||
return Err(Error::InvalidProvider(provider));
|
||||
}
|
||||
Err(error) => return Err(Error::InvalidProvider(error.to_string())),
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use litellm_host::observation::ObservationSender;
|
||||
pub use litellm_inference::RouteError as Error;
|
||||
pub use litellm_inference::Error;
|
||||
|
||||
pub mod ids;
|
||||
pub mod route;
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ use litellm_host::interceptors::{
|
|||
WireRequest,
|
||||
};
|
||||
use litellm_inference::{
|
||||
RouteError,
|
||||
Error,
|
||||
caching::{CacheRequest, execute_unary},
|
||||
};
|
||||
use rstest::{fixture, rstest};
|
||||
|
|
@ -124,12 +124,12 @@ struct ChangingHooks {
|
|||
facts: std::sync::Mutex<Vec<ExecutionFacts>>,
|
||||
}
|
||||
|
||||
impl Interceptors<RouteError> for ChangingHooks {
|
||||
impl Interceptors<Error> for ChangingHooks {
|
||||
async fn before_provider_request(
|
||||
&self,
|
||||
mut wire: WireRequest,
|
||||
_: RequestContext,
|
||||
) -> Result<WireRequest, RouteError> {
|
||||
) -> Result<WireRequest, Error> {
|
||||
let call = self.calls.fetch_add(1, Ordering::SeqCst);
|
||||
if self.rewrite {
|
||||
wire.body["temperature"] = json!(if call < 2 { 0.1 } else { 0.8 });
|
||||
|
|
@ -137,11 +137,11 @@ impl Interceptors<RouteError> for ChangingHooks {
|
|||
Ok(wire)
|
||||
}
|
||||
|
||||
async fn after_provider_response(&self, _: RawResponse) -> Result<(), RouteError> {
|
||||
async fn after_provider_response(&self, _: RawResponse) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn result_ready(&self, facts: ExecutionFacts) -> Result<(), RouteError> {
|
||||
async fn result_ready(&self, facts: ExecutionFacts) -> Result<(), Error> {
|
||||
self.facts.lock().unwrap().push(facts);
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
pub mod types;
|
||||
pub use litellm_inference::RouteError as Error;
|
||||
pub use litellm_inference::Error;
|
||||
mod constants;
|
||||
mod handler;
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
- `gateway-inference` (serving) -> `inference-<fmt>` (one API's call) -> `inference` (shared base)
|
||||
- This crate is the shared base every format crate builds on
|
||||
- `RouteError` (`src/error.rs`), `CallOptions` (`src/lib.rs`), `CallContext` (`src/context.rs`)
|
||||
- `Error` (`src/error.rs`), `CallOptions` (`src/lib.rs`), `CallContext` (`src/context.rs`)
|
||||
- diagnostic spans (`src/diagnostic.rs`), outbound send and signing (`src/outbound.rs`), provider resolution (`src/provider.rs`), `CoreResources` (`src/resources.rs`)
|
||||
- response caching (`src/caching.rs`): `Cachable`, `StreamCachable`, `CacheRequest`, `CallCache`, `execute_unary`, `execute_streaming`, stream capture
|
||||
- Shared test helpers belong in litellm-inference-testing, used only as a dev dependency
|
||||
|
|
@ -49,14 +49,14 @@
|
|||
- `litellm-inference-<fmt>` mirrors the route packages (`litellm/ocr/`, `litellm/messages/`, ...)
|
||||
- Provider code never imports from `inference` or `inference-*`
|
||||
- Handlers belong in `inference-*` or `llms`, never in a host crate
|
||||
- Import every item from its canonical path. Never re-export another crate's items or give an item a second public path. The only allowed re-exports are a private submodule surfacing its item at its module root (`mod error; pub use error::Error;`) and each format crate's `pub use litellm_inference::RouteError as Error;`, which keeps the pre-split `<fmt>::Error` name
|
||||
- Import every item from its canonical path. Never re-export another crate's items or give an item a second public path. The only allowed re-exports are a private submodule surfacing its item at its module root (`mod error; pub use error::Error;`) and each format crate's `pub use litellm_inference::Error;`, which keeps the pre-split `<fmt>::Error` name
|
||||
|
||||
## Error placement
|
||||
|
||||
- The workspace `Error definitions` rules shape each crate's error. This section decides which crate and module a failure belongs to
|
||||
- A failure is declared once, by the lowest crate that raises it
|
||||
- every crate above nests it unchanged (`#[error(transparent)] Auth(#[from] litellm_auth::Error)`) or maps it once at its boundary, as `src/error.rs` does for `litellm_llms::Error`
|
||||
- `RouteError` collects route failures for every format crate and never re-declares a variant a lower crate raises
|
||||
- `Error` collects route failures for every format crate and never re-declares a variant a lower crate raises
|
||||
- Scope follows the concept, not the first caller
|
||||
- an error type under `litellm-llms`'s `<provider>/` is private to that provider: no other provider and nothing in `base_llm` may import it
|
||||
- a failure two providers or two routes can hit (wire framing, stream event decoding, a malformed provider response) belongs to the crate that owns the concept: `litellm-framer` for framing, `litellm_llms::Error` for the transformation layer
|
||||
|
|
|
|||
|
|
@ -24,9 +24,9 @@ use serde::{Deserialize, Serialize, de::DeserializeOwned};
|
|||
use serde_json::Value;
|
||||
use tokio_util::codec::Decoder;
|
||||
|
||||
use crate::RouteError;
|
||||
use crate::Error;
|
||||
|
||||
pub trait Cachable: Protocol<Error = RouteError> {
|
||||
pub trait Cachable: Protocol<Error = Error> {
|
||||
const SURFACE: &'static str;
|
||||
|
||||
fn reusable(_response: &Self::Response) -> bool {
|
||||
|
|
@ -145,15 +145,15 @@ pub async fn execute_unary<P, F, Fut>(
|
|||
request: CacheRequest,
|
||||
cache: Option<Arc<dyn ResponseCacheService>>,
|
||||
options: Option<CacheOptions>,
|
||||
interceptors: &impl Interceptors<RouteError>,
|
||||
interceptors: &impl Interceptors<Error>,
|
||||
observers: Option<&ObservationSender>,
|
||||
provider: F,
|
||||
) -> Result<P::Response, RouteError>
|
||||
) -> Result<P::Response, Error>
|
||||
where
|
||||
P: Cachable,
|
||||
P::Response: Serialize + DeserializeOwned,
|
||||
F: FnOnce() -> Fut,
|
||||
Fut: Future<Output = Result<P::Response, RouteError>>,
|
||||
Fut: Future<Output = Result<P::Response, Error>>,
|
||||
{
|
||||
let identity = request.identity.clone();
|
||||
crate::diagnostic::provider(&identity.model, &identity.provider);
|
||||
|
|
@ -191,15 +191,15 @@ pub async fn execute_streaming<P, F, Fut>(
|
|||
request: CacheRequest,
|
||||
cache: Option<Arc<dyn ResponseCacheService>>,
|
||||
options: Option<CacheOptions>,
|
||||
interceptors: &impl Interceptors<RouteError>,
|
||||
interceptors: &impl Interceptors<Error>,
|
||||
observers: Option<&ObservationSender>,
|
||||
provider: F,
|
||||
) -> Result<OutputOf<P>, RouteError>
|
||||
) -> Result<OutputOf<P>, Error>
|
||||
where
|
||||
P: StreamCachable,
|
||||
P::Response: Serialize + DeserializeOwned,
|
||||
F: FnOnce() -> Fut,
|
||||
Fut: Future<Output = Result<OutputOf<P>, RouteError>>,
|
||||
Fut: Future<Output = Result<OutputOf<P>, Error>>,
|
||||
{
|
||||
let identity = request.identity.clone();
|
||||
crate::diagnostic::provider(&identity.model, &identity.provider);
|
||||
|
|
@ -299,9 +299,9 @@ impl<P: StreamCachable> CallCache<P> {
|
|||
}
|
||||
|
||||
fn capture_stream<P: StreamCachable>(
|
||||
chunks: futures_util::stream::BoxStream<'static, Result<P::Chunk, RouteError>>,
|
||||
chunks: futures_util::stream::BoxStream<'static, Result<P::Chunk, Error>>,
|
||||
session: CacheSession,
|
||||
) -> futures_util::stream::BoxStream<'static, Result<P::Chunk, RouteError>> {
|
||||
) -> futures_util::stream::BoxStream<'static, Result<P::Chunk, Error>> {
|
||||
stream::try_unfold(
|
||||
(chunks, Some(Vec::<u8>::new()), session),
|
||||
|(mut chunks, captured, session)| async move {
|
||||
|
|
@ -330,7 +330,7 @@ fn capture_stream<P: StreamCachable>(
|
|||
{
|
||||
session.store(entry).await;
|
||||
}
|
||||
Ok::<_, RouteError>(None)
|
||||
Ok::<_, Error>(None)
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -369,9 +369,9 @@ fn successful_stream(text: &str, terminal: &str) -> bool {
|
|||
|
||||
async fn publish(
|
||||
facts: ExecutionFacts,
|
||||
interceptors: &impl Interceptors<RouteError>,
|
||||
interceptors: &impl Interceptors<Error>,
|
||||
observers: Option<&ObservationSender>,
|
||||
) -> Result<(), RouteError> {
|
||||
) -> Result<(), Error> {
|
||||
if let Some(observers) = observers {
|
||||
observers.emit(CallEvent::Execution(ExecutionEvent::ResultReady {
|
||||
facts: facts.clone(),
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use litellm_host::{
|
|||
observation::ObservationSender,
|
||||
};
|
||||
|
||||
use crate::{CallOptions, RouteError};
|
||||
use crate::{CallOptions, Error};
|
||||
|
||||
pub struct CallContext<'a, I> {
|
||||
pub interceptors: &'a I,
|
||||
|
|
@ -13,7 +13,7 @@ pub struct CallContext<'a, I> {
|
|||
pub cache: CachePolicy,
|
||||
}
|
||||
|
||||
impl<'a, I: Interceptors<RouteError>> CallContext<'a, I> {
|
||||
impl<'a, I: Interceptors<Error>> CallContext<'a, I> {
|
||||
pub fn new(interceptors: &'a I, options: CallOptions) -> Self {
|
||||
Self {
|
||||
interceptors,
|
||||
|
|
@ -22,7 +22,7 @@ impl<'a, I: Interceptors<RouteError>> CallContext<'a, I> {
|
|||
}
|
||||
}
|
||||
|
||||
pub async fn result_ready(&self, facts: ExecutionFacts) -> Result<(), RouteError> {
|
||||
pub async fn result_ready(&self, facts: ExecutionFacts) -> Result<(), Error> {
|
||||
if let Some(observers) = &self.observers {
|
||||
observers.emit(CallEvent::Execution(ExecutionEvent::ResultReady {
|
||||
facts: facts.clone(),
|
||||
|
|
@ -31,7 +31,7 @@ impl<'a, I: Interceptors<RouteError>> CallContext<'a, I> {
|
|||
self.interceptors.result_ready(facts).await
|
||||
}
|
||||
|
||||
pub async fn response_received(&self, body: &str) -> Result<(), RouteError> {
|
||||
pub async fn response_received(&self, body: &str) -> Result<(), Error> {
|
||||
let raw = RawResponse {
|
||||
body: body.to_owned(),
|
||||
};
|
||||
|
|
@ -43,6 +43,6 @@ impl<'a, I: Interceptors<RouteError>> CallContext<'a, I> {
|
|||
self.interceptors
|
||||
.after_provider_response(raw)
|
||||
.await
|
||||
.map_err(RouteError::post_call)
|
||||
.map_err(Error::post_call)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ use litellm_http::transport::Error as TransportError;
|
|||
use litellm_llms::Error as LlmError;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, thiserror::Error)]
|
||||
pub enum RouteError {
|
||||
pub enum Error {
|
||||
#[error("expected {expected}, got {actual}")]
|
||||
InvalidType {
|
||||
expected: &'static str,
|
||||
|
|
@ -38,10 +38,10 @@ pub enum RouteError {
|
|||
#[error(transparent)]
|
||||
Secret(#[from] SecretError),
|
||||
#[error("post-call hook failed: {0}")]
|
||||
PostCallHook(#[source] Arc<RouteError>),
|
||||
PostCallHook(#[source] Arc<Error>),
|
||||
}
|
||||
|
||||
impl From<litellm_host::machine::MachineFault> for RouteError {
|
||||
impl From<litellm_host::machine::MachineFault> for Error {
|
||||
fn from(fault: litellm_host::machine::MachineFault) -> Self {
|
||||
use litellm_host::machine::MachineFault;
|
||||
Self::InvalidRequest(match fault {
|
||||
|
|
@ -51,7 +51,7 @@ impl From<litellm_host::machine::MachineFault> for RouteError {
|
|||
}
|
||||
}
|
||||
|
||||
impl RouteError {
|
||||
impl Error {
|
||||
pub fn post_call(error: Self) -> Self {
|
||||
Self::PostCallHook(Arc::new(error))
|
||||
}
|
||||
|
|
@ -76,7 +76,7 @@ impl RouteError {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<LlmError> for RouteError {
|
||||
impl From<LlmError> for Error {
|
||||
fn from(error: LlmError) -> Self {
|
||||
match error {
|
||||
LlmError::InvalidType { expected, actual } => Self::InvalidType { expected, actual },
|
||||
|
|
@ -99,7 +99,7 @@ impl SecretError {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<litellm_secrets::Error> for RouteError {
|
||||
impl From<litellm_secrets::Error> for Error {
|
||||
fn from(error: litellm_secrets::Error) -> Self {
|
||||
Self::Secret(SecretError(Arc::new(error)))
|
||||
}
|
||||
|
|
@ -115,22 +115,22 @@ impl Eq for SecretError {}
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::RouteError;
|
||||
use super::Error;
|
||||
use litellm_llms::{Error as LlmError, ErrorDetail};
|
||||
use rstest::rstest;
|
||||
|
||||
#[test]
|
||||
fn a_missing_api_key_is_the_environment_not_the_request() {
|
||||
assert!(
|
||||
!RouteError::Auth(litellm_auth::Error::MissingApiKey {
|
||||
!Error::Auth(litellm_auth::Error::MissingApiKey {
|
||||
provider: "Anthropic",
|
||||
environment_variable: "ANTHROPIC_API_KEY",
|
||||
})
|
||||
.is_request()
|
||||
);
|
||||
assert!(RouteError::Auth(litellm_auth::Error::InvalidHeader).is_request());
|
||||
assert!(RouteError::InvalidRequest("top_k".into()).is_request());
|
||||
assert!(!RouteError::InvalidResponse("bad json".into()).is_request());
|
||||
assert!(Error::Auth(litellm_auth::Error::InvalidHeader).is_request());
|
||||
assert!(Error::InvalidRequest("top_k".into()).is_request());
|
||||
assert!(!Error::InvalidResponse("bad json".into()).is_request());
|
||||
}
|
||||
#[rstest]
|
||||
#[case::request(true)]
|
||||
|
|
@ -139,7 +139,7 @@ mod tests {
|
|||
let source = serde_json::from_str::<serde_json::Value>("{").unwrap_err();
|
||||
let source_message = source.to_string();
|
||||
let detail = ErrorDetail::invalid("test payload", source);
|
||||
let error = RouteError::from(if request {
|
||||
let error = Error::from(if request {
|
||||
LlmError::InvalidRequest(detail)
|
||||
} else {
|
||||
LlmError::InvalidResponse(detail)
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ pub mod outbound;
|
|||
pub mod provider;
|
||||
pub mod resources;
|
||||
|
||||
pub use error::RouteError;
|
||||
pub use error::Error;
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
pub struct CallOptions {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use litellm_core_utils::get_llm_provider_logic::{
|
|||
CustomLlmProvider, LlmProviders, get_custom_llm_provider,
|
||||
};
|
||||
|
||||
use crate::error::RouteError as Error;
|
||||
use crate::error::Error;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ResolvedProvider<'a> {
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ use litellm_host::{
|
|||
protocol::Protocol,
|
||||
};
|
||||
use litellm_inference::{
|
||||
RouteError,
|
||||
Error,
|
||||
caching::{Cachable, CacheRequest, StreamCachable, execute_streaming, execute_unary},
|
||||
};
|
||||
use rstest::{fixture, rstest};
|
||||
|
|
@ -36,7 +36,7 @@ struct TestRoute;
|
|||
impl Protocol for TestRoute {
|
||||
type Request = Value;
|
||||
type Response = Value;
|
||||
type Error = RouteError;
|
||||
type Error = Error;
|
||||
type HostCall = Infallible;
|
||||
type Chunk = Bytes;
|
||||
type StreamHead = ();
|
||||
|
|
@ -204,7 +204,7 @@ async fn streamed(
|
|||
.chunks(3)
|
||||
.map(|bytes| Ok(Bytes::copy_from_slice(bytes)))
|
||||
.collect::<Vec<_>>();
|
||||
let ending = fail.then_some(Err(RouteError::Unsupported("test transport failure")));
|
||||
let ending = fail.then_some(Err(Error::Unsupported("test transport failure")));
|
||||
Ok(CallOutput::Stream {
|
||||
head: (),
|
||||
chunks: stream::iter(chunks.into_iter().chain(ending)).boxed(),
|
||||
|
|
@ -215,7 +215,7 @@ async fn streamed(
|
|||
.unwrap()
|
||||
}
|
||||
|
||||
async fn consume(output: OutputOf<TestRoute>) -> Result<Vec<u8>, RouteError> {
|
||||
async fn consume(output: OutputOf<TestRoute>) -> Result<Vec<u8>, Error> {
|
||||
let CallOutput::Stream { chunks, .. } = output else {
|
||||
panic!("expected a stream");
|
||||
};
|
||||
|
|
@ -315,7 +315,7 @@ async fn a_provider_failure_never_populates_the_cache(cache: Arc<dyn ResponseCac
|
|||
None,
|
||||
|| async {
|
||||
calls.fetch_add(1, Ordering::SeqCst);
|
||||
Err(RouteError::Unsupported("test provider failure"))
|
||||
Err(Error::Unsupported("test provider failure"))
|
||||
},
|
||||
)
|
||||
.await;
|
||||
|
|
@ -467,8 +467,8 @@ struct CacheHitAccounting {
|
|||
reject: bool,
|
||||
}
|
||||
|
||||
impl Interceptors<RouteError> for CacheHitAccounting {
|
||||
async fn result_ready(&self, facts: ExecutionFacts) -> Result<(), RouteError> {
|
||||
impl Interceptors<Error> for CacheHitAccounting {
|
||||
async fn result_ready(&self, facts: ExecutionFacts) -> Result<(), Error> {
|
||||
self.calls.fetch_add(1, Ordering::SeqCst);
|
||||
let ResultSource::Cache { key } = facts.source else {
|
||||
panic!("expected cache source")
|
||||
|
|
@ -482,7 +482,7 @@ impl Interceptors<RouteError> for CacheHitAccounting {
|
|||
);
|
||||
self.key.set(key).unwrap();
|
||||
if self.reject {
|
||||
return Err(RouteError::Unsupported("cache accounting rejected"));
|
||||
return Err(Error::Unsupported("cache accounting rejected"));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -491,11 +491,11 @@ impl Interceptors<RouteError> for CacheHitAccounting {
|
|||
&self,
|
||||
wire: WireRequest,
|
||||
_: RequestContext,
|
||||
) -> Result<WireRequest, RouteError> {
|
||||
) -> Result<WireRequest, Error> {
|
||||
Ok(wire)
|
||||
}
|
||||
|
||||
async fn after_provider_response(&self, _: RawResponse) -> Result<(), RouteError> {
|
||||
async fn after_provider_response(&self, _: RawResponse) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
@ -571,7 +571,7 @@ async fn cache_hits_notify_accounting_once_and_propagate_its_failure(
|
|||
if reject {
|
||||
assert!(matches!(
|
||||
result,
|
||||
Err(RouteError::Unsupported("cache accounting rejected"))
|
||||
Err(Error::Unsupported("cache accounting rejected"))
|
||||
));
|
||||
} else {
|
||||
assert_eq!(result.unwrap(), expected);
|
||||
|
|
@ -590,7 +590,7 @@ async fn cache_hits_notify_accounting_once_and_propagate_its_failure(
|
|||
impl Protocol for UnaryTestRoute {
|
||||
type Request = Value;
|
||||
type Response = Value;
|
||||
type Error = RouteError;
|
||||
type Error = Error;
|
||||
type HostCall = Infallible;
|
||||
type Chunk = Infallible;
|
||||
type StreamHead = Infallible;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use litellm_http::transport::Error as TransportError;
|
||||
use litellm_inference::RouteError;
|
||||
use litellm_inference::Error;
|
||||
use pyo3::{
|
||||
exceptions::{PyRuntimeError, PyValueError},
|
||||
prelude::*,
|
||||
|
|
@ -19,9 +19,9 @@ pyo3::create_exception!(
|
|||
"The provider call was already issued and failed. Args are (status, message); status is 0 when there was no HTTP response."
|
||||
);
|
||||
|
||||
pub(crate) fn route_error_to_pyerr(error: RouteError) -> PyErr {
|
||||
pub(crate) fn route_error_to_pyerr(error: Error) -> PyErr {
|
||||
match error {
|
||||
RouteError::Transport(TransportError::Http { status, body }) => {
|
||||
Error::Transport(TransportError::Http { status, body }) => {
|
||||
RustUpstreamError::new_err((status, body))
|
||||
}
|
||||
other => by_fault(other.is_request(), other.to_string()),
|
||||
|
|
@ -42,13 +42,13 @@ mod tests {
|
|||
use super::*;
|
||||
|
||||
#[rstest::rstest]
|
||||
#[case::unsupported(RouteError::Unsupported("test capability"), true)]
|
||||
#[case::invalid_provider(RouteError::InvalidProvider("unknown".into()), true)]
|
||||
#[case::invalid_request(RouteError::InvalidRequest("empty messages".into()), true)]
|
||||
#[case::unsupported(Error::Unsupported("test capability"), true)]
|
||||
#[case::invalid_provider(Error::InvalidProvider("unknown".into()), true)]
|
||||
#[case::invalid_request(Error::InvalidRequest("empty messages".into()), true)]
|
||||
#[case::connection(TransportError::Connect("unreachable".into()).into(), false)]
|
||||
#[case::network(TransportError::Network("timed out".into()).into(), false)]
|
||||
#[case::invalid_response(RouteError::InvalidResponse("missing usage".into()), false)]
|
||||
fn route_failures_are_terminal(#[case] error: RouteError, #[case] is_request: bool) {
|
||||
#[case::invalid_response(Error::InvalidResponse("missing usage".into()), false)]
|
||||
fn route_failures_are_terminal(#[case] error: Error, #[case] is_request: bool) {
|
||||
Python::initialize();
|
||||
Python::attach(|py| {
|
||||
let failure = route_error_to_pyerr(error);
|
||||
|
|
@ -86,14 +86,12 @@ mod tests {
|
|||
fn missing_api_key_stays_a_runtime_error_while_other_auth_failures_are_value_errors() {
|
||||
Python::initialize();
|
||||
Python::attach(|py| {
|
||||
let missing =
|
||||
route_error_to_pyerr(RouteError::Auth(litellm_auth::Error::MissingApiKey {
|
||||
provider: "Anthropic",
|
||||
environment_variable: "ANTHROPIC_API_KEY",
|
||||
}));
|
||||
let missing = route_error_to_pyerr(Error::Auth(litellm_auth::Error::MissingApiKey {
|
||||
provider: "Anthropic",
|
||||
environment_variable: "ANTHROPIC_API_KEY",
|
||||
}));
|
||||
assert!(missing.is_instance_of::<PyRuntimeError>(py));
|
||||
let invalid =
|
||||
route_error_to_pyerr(RouteError::Auth(litellm_auth::Error::InvalidHeader));
|
||||
let invalid = route_error_to_pyerr(Error::Auth(litellm_auth::Error::InvalidHeader));
|
||||
assert!(invalid.is_instance_of::<PyValueError>(py));
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use litellm_core_utils::get_llm_provider_logic::get_custom_llm_provider;
|
|||
use litellm_host::{call::HostedMachine, protocol::Protocol};
|
||||
use litellm_host_python::{PythonBinding, PythonHostCalls, from_py};
|
||||
use litellm_http::transport::Error as TransportError;
|
||||
use litellm_inference::RouteError;
|
||||
use litellm_inference::Error;
|
||||
use litellm_secrets::source::SecretSource;
|
||||
use pyo3::{
|
||||
exceptions::PyValueError,
|
||||
|
|
@ -119,14 +119,14 @@ impl InferenceHost {
|
|||
public_response(py, self.module, response)
|
||||
}
|
||||
|
||||
pub fn error(&self, py: Python<'_>, error: RouteError) -> PyResult<PyErr> {
|
||||
if let RouteError::Secret(source) = &error
|
||||
pub fn error(&self, py: Python<'_>, error: Error) -> PyResult<PyErr> {
|
||||
if let Error::Secret(source) = &error
|
||||
&& let Some(original) = crate::secrets::python_error(py, source.source_error())
|
||||
{
|
||||
return Ok(original);
|
||||
}
|
||||
let native = match error {
|
||||
RouteError::Transport(TransportError::Http { status, body }) => {
|
||||
Error::Transport(TransportError::Http { status, body }) => {
|
||||
let error = RustUpstreamError::new_err((status, body));
|
||||
error
|
||||
.value(py)
|
||||
|
|
@ -144,7 +144,7 @@ impl InferenceHost {
|
|||
}
|
||||
|
||||
pub(super) trait InferenceRoute: Sized + 'static {
|
||||
type Protocol: Protocol<Error = RouteError>;
|
||||
type Protocol: Protocol<Error = Error>;
|
||||
const OPERATION: LoggingOperation;
|
||||
const SYNC_CALL_TYPE: &'static str;
|
||||
const ASYNC_CALL_TYPE: &'static str;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue