mirror of
https://github.com/mii443/rust-genai.git
synced 2025-08-29 19:49:40 +00:00
! re-refactor of Error - back to genai::Error (as adapter::Error was unnecessarily exposing internal responsibility)
This commit is contained in:
@ -1,8 +1,8 @@
|
||||
use crate::adapter::Result;
|
||||
use crate::adapter::{AdapterConfig, AdapterKind};
|
||||
use crate::chat::{ChatRequest, ChatRequestOptionsSet, ChatResponse, ChatStreamResponse};
|
||||
use crate::webc::WebResponse;
|
||||
use crate::ConfigSet;
|
||||
use crate::Result;
|
||||
use reqwest::RequestBuilder;
|
||||
use serde_json::Value;
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::adapter::anthropic::AnthropicStreamer;
|
||||
use crate::adapter::support::get_api_key_resolver;
|
||||
use crate::adapter::Result;
|
||||
use crate::Result;
|
||||
use crate::adapter::{Adapter, AdapterConfig, AdapterKind, ServiceType, WebRequestData};
|
||||
use crate::chat::{
|
||||
ChatRequest, ChatRequestOptionsSet, ChatResponse, ChatRole, ChatStream, ChatStreamResponse, MessageContent,
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::adapter::adapters::support::{StreamerCapturedData, StreamerOptions};
|
||||
use crate::adapter::inter_stream::{InterStreamEnd, InterStreamEvent};
|
||||
use crate::adapter::{Error, Result};
|
||||
use crate::{Error, Result};
|
||||
use crate::chat::{ChatRequestOptionsSet, MetaUsage};
|
||||
use crate::support::value_ext::ValueExt;
|
||||
use reqwest_eventsource::{Event, EventSource};
|
||||
|
@ -1,7 +1,6 @@
|
||||
use crate::adapter::cohere::CohereStreamer;
|
||||
use crate::adapter::support::get_api_key_resolver;
|
||||
use crate::adapter::{Adapter, AdapterConfig, AdapterKind, ServiceType, WebRequestData};
|
||||
use crate::adapter::{Error, Result};
|
||||
use crate::chat::{
|
||||
ChatRequest, ChatRequestOptionsSet, ChatResponse, ChatRole, ChatStream, ChatStreamResponse, MessageContent,
|
||||
MetaUsage,
|
||||
@ -9,6 +8,7 @@ use crate::chat::{
|
||||
use crate::support::value_ext::ValueExt;
|
||||
use crate::webc::{WebResponse, WebStream};
|
||||
use crate::ConfigSet;
|
||||
use crate::{Error, Result};
|
||||
use reqwest::RequestBuilder;
|
||||
use serde_json::{json, Value};
|
||||
use std::sync::OnceLock;
|
||||
@ -96,15 +96,17 @@ impl Adapter for CohereAdapter {
|
||||
Ok(WebRequestData { url, headers, payload })
|
||||
}
|
||||
|
||||
fn to_chat_response(_kind: AdapterKind, web_response: WebResponse) -> Result<ChatResponse> {
|
||||
fn to_chat_response(adapter_kind: AdapterKind, web_response: WebResponse) -> Result<ChatResponse> {
|
||||
let WebResponse { mut body, .. } = web_response;
|
||||
|
||||
// -- Get usage
|
||||
let usage = body.x_take("/meta/tokens").map(Self::into_usage).unwrap_or_default();
|
||||
|
||||
// -- Get response
|
||||
let mut last_chat_history_item =
|
||||
body.x_take::<Vec<Value>>("chat_history")?.pop().ok_or(Error::NoChatResponse)?;
|
||||
let mut last_chat_history_item = body
|
||||
.x_take::<Vec<Value>>("chat_history")?
|
||||
.pop()
|
||||
.ok_or(Error::NoChatResponse { adapter_kind })?;
|
||||
|
||||
let content: Option<MessageContent> = last_chat_history_item
|
||||
.x_take::<Option<String>>("message")?
|
||||
@ -173,7 +175,7 @@ impl CohereAdapter {
|
||||
}
|
||||
|
||||
// -- Build extract the last user message
|
||||
let last_chat_msg = chat_req.messages.pop().ok_or(Error::ChatReqHasNoMessages)?;
|
||||
let last_chat_msg = chat_req.messages.pop().ok_or(Error::ChatReqHasNoMessages { adapter_kind })?;
|
||||
if !matches!(last_chat_msg.role, ChatRole::User) {
|
||||
return Err(Error::LastChatMessageIsNoUser {
|
||||
actual_role: last_chat_msg.role,
|
||||
@ -193,7 +195,7 @@ impl CohereAdapter {
|
||||
ChatRole::User => chat_history.push(json! ({"role": "USER", "content": content})),
|
||||
ChatRole::Assistant => chat_history.push(json! ({"role": "CHATBOT", "content": content})),
|
||||
ChatRole::Tool => {
|
||||
return Err(Error::MessageRoleNotSupport {
|
||||
return Err(Error::MessageRoleNotSupported {
|
||||
adapter_kind,
|
||||
role: ChatRole::Tool,
|
||||
})
|
||||
|
@ -1,10 +1,11 @@
|
||||
use crate::adapter::adapters::support::{StreamerCapturedData, StreamerOptions};
|
||||
use crate::adapter::cohere::CohereAdapter;
|
||||
use crate::adapter::inter_stream::{InterStreamEnd, InterStreamEvent};
|
||||
use crate::adapter::{Error, Result};
|
||||
use crate::adapter::AdapterKind;
|
||||
use crate::chat::ChatRequestOptionsSet;
|
||||
use crate::support::value_ext::ValueExt;
|
||||
use crate::webc::WebStream;
|
||||
use crate::{Error, Result};
|
||||
use serde::Deserialize;
|
||||
use serde_json::Value;
|
||||
use std::pin::Pin;
|
||||
@ -118,7 +119,10 @@ impl futures::Stream for CohereStreamer {
|
||||
}
|
||||
Some(Err(err)) => {
|
||||
println!("Cohere Adapter Stream Error: {}", err);
|
||||
return Poll::Ready(Some(Err(Error::WebStream)));
|
||||
return Poll::Ready(Some(Err(Error::WebStream {
|
||||
adapter_kind: AdapterKind::Cohere,
|
||||
cause: err.to_string(),
|
||||
})));
|
||||
}
|
||||
None => {
|
||||
self.done = true;
|
||||
|
@ -1,7 +1,6 @@
|
||||
use crate::adapter::gemini::GeminiStreamer;
|
||||
use crate::adapter::support::get_api_key_resolver;
|
||||
use crate::adapter::{Adapter, AdapterConfig, AdapterKind, ServiceType, WebRequestData};
|
||||
use crate::adapter::{Error, Result};
|
||||
use crate::chat::{
|
||||
ChatRequest, ChatRequestOptionsSet, ChatResponse, ChatRole, ChatStream, ChatStreamResponse, MessageContent,
|
||||
MetaUsage,
|
||||
@ -9,6 +8,7 @@ use crate::chat::{
|
||||
use crate::support::value_ext::ValueExt;
|
||||
use crate::webc::{WebResponse, WebStream};
|
||||
use crate::ConfigSet;
|
||||
use crate::{Error, Result};
|
||||
use reqwest::RequestBuilder;
|
||||
use serde_json::{json, Value};
|
||||
use std::sync::OnceLock;
|
||||
@ -177,7 +177,7 @@ impl GeminiAdapter {
|
||||
ChatRole::User => contents.push(json! ({"role": "user", "parts": [{"text": content}]})),
|
||||
ChatRole::Assistant => contents.push(json! ({"role": "model", "parts": [{"text": content}]})),
|
||||
ChatRole::Tool => {
|
||||
return Err(Error::MessageRoleNotSupport {
|
||||
return Err(Error::MessageRoleNotSupported {
|
||||
adapter_kind,
|
||||
role: ChatRole::Tool,
|
||||
})
|
||||
|
@ -1,9 +1,10 @@
|
||||
use crate::adapter::adapters::support::{StreamerCapturedData, StreamerOptions};
|
||||
use crate::adapter::gemini::{GeminiAdapter, GeminiChatResponse};
|
||||
use crate::adapter::inter_stream::{InterStreamEnd, InterStreamEvent};
|
||||
use crate::adapter::{Error, Result};
|
||||
use crate::adapter::AdapterKind;
|
||||
use crate::chat::ChatRequestOptionsSet;
|
||||
use crate::webc::WebStream;
|
||||
use crate::{Error, Result};
|
||||
use serde_json::Value;
|
||||
use std::pin::Pin;
|
||||
use std::task::{Context, Poll};
|
||||
@ -106,7 +107,10 @@ impl futures::Stream for GeminiStreamer {
|
||||
}
|
||||
Some(Err(err)) => {
|
||||
println!("Gemini Adapter Stream Error: {}", err);
|
||||
return Poll::Ready(Some(Err(Error::WebStream)));
|
||||
return Poll::Ready(Some(Err(Error::WebStream {
|
||||
adapter_kind: AdapterKind::Gemini,
|
||||
cause: err.to_string(),
|
||||
})));
|
||||
}
|
||||
None => {
|
||||
self.done = true;
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::adapter::openai::OpenAIAdapter;
|
||||
use crate::adapter::support::get_api_key_resolver;
|
||||
use crate::adapter::Result;
|
||||
use crate::Result;
|
||||
use crate::adapter::{Adapter, AdapterConfig, AdapterKind, ServiceType, WebRequestData};
|
||||
use crate::chat::{ChatRequest, ChatRequestOptionsSet, ChatResponse, ChatStreamResponse};
|
||||
use crate::webc::WebResponse;
|
||||
|
@ -1,12 +1,12 @@
|
||||
//! API DOC: https://github.com/ollama/ollama/blob/main/docs/openai.md
|
||||
|
||||
use crate::adapter::openai::OpenAIAdapter;
|
||||
use crate::adapter::Result;
|
||||
use crate::adapter::{Adapter, AdapterConfig, AdapterKind, ServiceType, WebRequestData};
|
||||
use crate::chat::{ChatRequest, ChatRequestOptionsSet, ChatResponse, ChatStreamResponse};
|
||||
use crate::support::value_ext::ValueExt;
|
||||
use crate::webc::WebResponse;
|
||||
use crate::ConfigSet;
|
||||
use crate::{Error, Result};
|
||||
use reqwest::RequestBuilder;
|
||||
use serde_json::Value;
|
||||
use std::sync::OnceLock;
|
||||
@ -22,12 +22,15 @@ const OLLAMA_BASE_URL: &str = "http://localhost:11434/api/";
|
||||
/// Since the base ollama API supports `application/x-ndjson` for streaming whereas others support `text/event-stream`
|
||||
impl Adapter for OllamaAdapter {
|
||||
/// Note: For now returns empty as it should probably do a request to the ollama server
|
||||
async fn all_model_names(_kind: AdapterKind) -> Result<Vec<String>> {
|
||||
async fn all_model_names(adapter_kind: AdapterKind) -> Result<Vec<String>> {
|
||||
let url = format!("{OLLAMA_BASE_URL}tags");
|
||||
|
||||
// TODO: need to get the WebClient from the client.
|
||||
let web_c = crate::webc::WebClient::default();
|
||||
let mut res = web_c.do_get(&url, &[]).await?;
|
||||
let mut res = web_c.do_get(&url, &[]).await.map_err(|webc_error| Error::WebCall {
|
||||
adapter_kind,
|
||||
webc_error,
|
||||
})?;
|
||||
|
||||
let mut models: Vec<String> = Vec::new();
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
use crate::adapter::openai::OpenAIStreamer;
|
||||
use crate::adapter::support::get_api_key_resolver;
|
||||
use crate::adapter::{Adapter, AdapterConfig, AdapterKind, ServiceType, WebRequestData};
|
||||
use crate::adapter::{Error, Result};
|
||||
use crate::chat::{
|
||||
ChatRequest, ChatRequestOptionsSet, ChatResponse, ChatRole, ChatStream, ChatStreamResponse, MessageContent,
|
||||
MetaUsage,
|
||||
@ -9,6 +8,7 @@ use crate::chat::{
|
||||
use crate::support::value_ext::ValueExt;
|
||||
use crate::webc::WebResponse;
|
||||
use crate::ConfigSet;
|
||||
use crate::{Error, Result};
|
||||
use reqwest::RequestBuilder;
|
||||
use reqwest_eventsource::EventSource;
|
||||
use serde_json::{json, Value};
|
||||
@ -194,7 +194,7 @@ impl OpenAIAdapter {
|
||||
ChatRole::User => messages.push(json! ({"role": "user", "content": content})),
|
||||
ChatRole::Assistant => messages.push(json! ({"role": "assistant", "content": content})),
|
||||
ChatRole::Tool => {
|
||||
return Err(Error::MessageRoleNotSupport {
|
||||
return Err(Error::MessageRoleNotSupported {
|
||||
adapter_kind,
|
||||
role: ChatRole::Tool,
|
||||
})
|
||||
|
@ -2,9 +2,9 @@ use crate::adapter::adapters::support::{StreamerCapturedData, StreamerOptions};
|
||||
use crate::adapter::inter_stream::{InterStreamEnd, InterStreamEvent};
|
||||
use crate::adapter::openai::OpenAIAdapter;
|
||||
use crate::adapter::AdapterKind;
|
||||
use crate::adapter::{Error, Result};
|
||||
use crate::chat::ChatRequestOptionsSet;
|
||||
use crate::support::value_ext::ValueExt;
|
||||
use crate::{Error, Result};
|
||||
use reqwest_eventsource::{Event, EventSource};
|
||||
use serde_json::Value;
|
||||
use std::pin::Pin;
|
||||
|
@ -3,11 +3,11 @@ use crate::adapter::cohere::CohereAdapter;
|
||||
use crate::adapter::gemini::GeminiAdapter;
|
||||
use crate::adapter::ollama::OllamaAdapter;
|
||||
use crate::adapter::openai::OpenAIAdapter;
|
||||
use crate::adapter::Result;
|
||||
use crate::adapter::{Adapter, AdapterConfig, AdapterKind, ServiceType, WebRequestData};
|
||||
use crate::chat::{ChatRequest, ChatRequestOptionsSet, ChatResponse, ChatStreamResponse};
|
||||
use crate::webc::WebResponse;
|
||||
use crate::ConfigSet;
|
||||
use crate::Result;
|
||||
use reqwest::RequestBuilder;
|
||||
|
||||
use super::groq::GroqAdapter;
|
||||
|
@ -1,66 +0,0 @@
|
||||
use crate::adapter::AdapterKind;
|
||||
use crate::chat::ChatRole;
|
||||
use crate::{resolver, webc};
|
||||
use derive_more::From;
|
||||
|
||||
pub type Result<T> = core::result::Result<T, Error>;
|
||||
|
||||
#[derive(Debug, From)]
|
||||
pub enum Error {
|
||||
// -- Adapter Chat Request
|
||||
ChatReqHasNoMessages,
|
||||
LastChatMessageIsNoUser {
|
||||
actual_role: ChatRole,
|
||||
},
|
||||
|
||||
// -- Adapter Chat Response
|
||||
NoChatResponse,
|
||||
|
||||
// -- Adapter
|
||||
RequiresApiKey {
|
||||
adapter_kind: AdapterKind,
|
||||
},
|
||||
MessageRoleNotSupport {
|
||||
adapter_kind: AdapterKind,
|
||||
role: ChatRole,
|
||||
},
|
||||
HasNoDefaultApiKeyEnvName,
|
||||
NoAuthResolver {
|
||||
adapter_kind: AdapterKind,
|
||||
},
|
||||
AuthResolverNoAuthData {
|
||||
adapter_kind: AdapterKind,
|
||||
},
|
||||
|
||||
// -- Stream
|
||||
StreamParse(serde_json::Error),
|
||||
StreamEventError(serde_json::Value),
|
||||
WebStream,
|
||||
|
||||
// -- Modules
|
||||
#[from]
|
||||
Webc(webc::Error),
|
||||
#[from]
|
||||
Resolver(resolver::Error),
|
||||
|
||||
// -- Utils
|
||||
#[from]
|
||||
XValue(crate::support::value_ext::Error),
|
||||
|
||||
// -- Externals
|
||||
#[from]
|
||||
EventSourceClone(reqwest_eventsource::CannotCloneRequestError),
|
||||
ReqwestEventSource(reqwest_eventsource::Error),
|
||||
}
|
||||
|
||||
// region: --- Error Boilerplate
|
||||
|
||||
impl core::fmt::Display for Error {
|
||||
fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::result::Result<(), core::fmt::Error> {
|
||||
write!(fmt, "{self:?}")
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for Error {}
|
||||
|
||||
// endregion: --- Error Boilerplate
|
@ -14,7 +14,6 @@ mod adapter_kind;
|
||||
mod adapter_types;
|
||||
mod adapters;
|
||||
mod dispatcher;
|
||||
mod error;
|
||||
mod support;
|
||||
|
||||
// -- Flatten (private, crate, public)
|
||||
@ -23,7 +22,6 @@ use adapters::*;
|
||||
pub(crate) use adapter_types::*;
|
||||
pub(crate) use dispatcher::*;
|
||||
|
||||
pub use self::error::{Error, Result};
|
||||
pub use adapter_config::*;
|
||||
pub use adapter_kind::*;
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::adapter::AdapterKind;
|
||||
use crate::adapter::{Error, Result};
|
||||
use crate::ConfigSet;
|
||||
use crate::{Error, Result};
|
||||
|
||||
/// Returns the `api_key` value from the config_set auth_resolver
|
||||
/// This function should be called if the adapter must have a api_key
|
||||
|
@ -5,7 +5,7 @@ use futures::Stream;
|
||||
use std::pin::Pin;
|
||||
use std::task::{Context, Poll};
|
||||
|
||||
type InterStreamType = Pin<Box<dyn Stream<Item = crate::adapter::Result<InterStreamEvent>>>>;
|
||||
type InterStreamType = Pin<Box<dyn Stream<Item = crate::Result<InterStreamEvent>>>>;
|
||||
|
||||
pub struct ChatStream {
|
||||
inter_stream: InterStreamType,
|
||||
@ -18,7 +18,7 @@ impl ChatStream {
|
||||
|
||||
pub fn from_inter_stream<T>(inter_stream: T) -> Self
|
||||
where
|
||||
T: Stream<Item = crate::adapter::Result<InterStreamEvent>> + Unpin + 'static,
|
||||
T: Stream<Item = crate::Result<InterStreamEvent>> + Unpin + 'static,
|
||||
{
|
||||
let boxed_stream: InterStreamType = Box::pin(inter_stream);
|
||||
ChatStream::new(boxed_stream)
|
||||
@ -28,7 +28,7 @@ impl ChatStream {
|
||||
// region: --- Stream Impl
|
||||
|
||||
impl Stream for ChatStream {
|
||||
type Item = crate::adapter::Result<ChatStreamEvent>;
|
||||
type Item = crate::Result<ChatStreamEvent>;
|
||||
|
||||
fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
|
||||
let this = self.get_mut();
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::adapter::{Adapter, AdapterDispatcher, AdapterKind, ServiceType, WebRequestData};
|
||||
use crate::chat::{ChatRequest, ChatRequestOptions, ChatRequestOptionsSet, ChatResponse, ChatStreamResponse};
|
||||
use crate::client::Client;
|
||||
use crate::{ConfigSet, Result};
|
||||
use crate::{ConfigSet, Error, Result};
|
||||
|
||||
/// Public AI Functions
|
||||
impl Client {
|
||||
@ -66,7 +66,14 @@ impl Client {
|
||||
options_set,
|
||||
)?;
|
||||
|
||||
let web_res = self.web_client().do_post(&url, &headers, payload).await?;
|
||||
let web_res =
|
||||
self.web_client()
|
||||
.do_post(&url, &headers, payload)
|
||||
.await
|
||||
.map_err(|webc_error| Error::WebCall {
|
||||
adapter_kind,
|
||||
webc_error,
|
||||
})?;
|
||||
|
||||
let chat_res = AdapterDispatcher::to_chat_response(adapter_kind, web_res)?;
|
||||
|
||||
@ -100,7 +107,13 @@ impl Client {
|
||||
options_set.clone(),
|
||||
)?;
|
||||
|
||||
let reqwest_builder = self.web_client().new_req_builder(&url, &headers, payload)?;
|
||||
let reqwest_builder = self
|
||||
.web_client()
|
||||
.new_req_builder(&url, &headers, payload)
|
||||
.map_err(|webc_error| Error::WebCall {
|
||||
adapter_kind,
|
||||
webc_error,
|
||||
})?;
|
||||
|
||||
let res = AdapterDispatcher::to_chat_stream(adapter_kind, reqwest_builder, options_set)?;
|
||||
|
||||
|
62
src/error.rs
62
src/error.rs
@ -1,16 +1,68 @@
|
||||
use crate::adapter::{self};
|
||||
use crate::webc;
|
||||
use crate::adapter::AdapterKind;
|
||||
use crate::chat::ChatRole;
|
||||
use crate::{resolver, webc};
|
||||
use derive_more::From;
|
||||
|
||||
pub type Result<T> = core::result::Result<T, Error>;
|
||||
|
||||
#[derive(Debug, From)]
|
||||
pub enum Error {
|
||||
#[from]
|
||||
Webc(webc::Error),
|
||||
// -- Chat Input
|
||||
ChatReqHasNoMessages {
|
||||
adapter_kind: AdapterKind,
|
||||
},
|
||||
LastChatMessageIsNoUser {
|
||||
actual_role: ChatRole,
|
||||
},
|
||||
MessageRoleNotSupported {
|
||||
adapter_kind: AdapterKind,
|
||||
role: ChatRole,
|
||||
},
|
||||
|
||||
// -- Chat Output
|
||||
NoChatResponse {
|
||||
adapter_kind: AdapterKind,
|
||||
},
|
||||
|
||||
// -- Auth
|
||||
RequiresApiKey {
|
||||
adapter_kind: AdapterKind,
|
||||
},
|
||||
NoAuthResolver {
|
||||
adapter_kind: AdapterKind,
|
||||
},
|
||||
AuthResolverNoAuthData {
|
||||
adapter_kind: AdapterKind,
|
||||
},
|
||||
|
||||
// -- Web Call error
|
||||
WebCall {
|
||||
adapter_kind: AdapterKind,
|
||||
webc_error: webc::Error,
|
||||
},
|
||||
|
||||
// -- Chat Stream
|
||||
StreamParse(serde_json::Error),
|
||||
StreamEventError(serde_json::Value),
|
||||
WebStream {
|
||||
adapter_kind: AdapterKind,
|
||||
cause: String,
|
||||
},
|
||||
|
||||
// -- Modules
|
||||
// #[from]
|
||||
// Webc(webc::Error),
|
||||
#[from]
|
||||
Adapter(adapter::Error),
|
||||
Resolver(resolver::Error),
|
||||
|
||||
// -- Utils
|
||||
#[from]
|
||||
XValue(crate::support::value_ext::Error),
|
||||
|
||||
// -- Externals
|
||||
#[from]
|
||||
EventSourceClone(reqwest_eventsource::CannotCloneRequestError),
|
||||
ReqwestEventSource(reqwest_eventsource::Error),
|
||||
}
|
||||
|
||||
// region: --- Error Boilerplate
|
||||
|
@ -9,8 +9,8 @@ mod adapter_kind_resolver;
|
||||
mod auth_resolver;
|
||||
mod error;
|
||||
|
||||
pub use self::error::{Error, Result};
|
||||
pub use adapter_kind_resolver::*;
|
||||
pub use auth_resolver::*;
|
||||
pub use error::{Error, Result};
|
||||
|
||||
// endregion: --- Modules
|
||||
|
@ -5,7 +5,7 @@ mod web_client;
|
||||
// for when not `text/event-stream`
|
||||
mod web_stream;
|
||||
|
||||
pub use self::error::{Error, Result};
|
||||
pub use error::{Error, Result};
|
||||
pub use web_client::*;
|
||||
pub use web_stream::*;
|
||||
|
||||
|
Reference in New Issue
Block a user