mirror of
https://github.com/mii443/rust-genai.git
synced 2025-12-09 14:08:21 +00:00
! add ChatRequestOption and upgraded the client exec_chat and adapters APIs
This commit is contained in:
@@ -4,7 +4,7 @@ version = "0.0.12-alpha.1"
|
|||||||
edition = "2021"
|
edition = "2021"
|
||||||
rust-version = "1.78"
|
rust-version = "1.78"
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
description = "Multiprovider generative AI client (Ollama, OpenAI, Gemini, Anthropic, Cohere, ...)"
|
description = "Multi-Provider Generative AI Rust Library. (Ollama, OpenAI, Gemini, Anthropic, Cohere, ...)"
|
||||||
keywords = [
|
keywords = [
|
||||||
"generative-ai",
|
"generative-ai",
|
||||||
"library",
|
"library",
|
||||||
|
|||||||
@@ -50,11 +50,11 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
println!("\n--- Question:\n{question}");
|
println!("\n--- Question:\n{question}");
|
||||||
|
|
||||||
println!("\n--- Answer: (oneshot response)");
|
println!("\n--- Answer: (oneshot response)");
|
||||||
let chat_res = client.exec_chat(model, chat_req.clone()).await?;
|
let chat_res = client.exec_chat(model, chat_req.clone(), None).await?;
|
||||||
println!("{}", chat_res.content.as_deref().unwrap_or("NO ANSWER"));
|
println!("{}", chat_res.content.as_deref().unwrap_or("NO ANSWER"));
|
||||||
|
|
||||||
println!("\n--- Answer: (streaming)");
|
println!("\n--- Answer: (streaming)");
|
||||||
let chat_res = client.exec_chat_stream(model, chat_req.clone()).await?;
|
let chat_res = client.exec_chat_stream(model, chat_req.clone(), None).await?;
|
||||||
print_chat_stream(chat_res).await?;
|
print_chat_stream(chat_res).await?;
|
||||||
|
|
||||||
println!();
|
println!();
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
chat_req = chat_req.append_message(ChatMessage::user(question));
|
chat_req = chat_req.append_message(ChatMessage::user(question));
|
||||||
|
|
||||||
println!("\n--- Question:\n{question}");
|
println!("\n--- Question:\n{question}");
|
||||||
let chat_res = client.exec_chat_stream(MODEL, chat_req.clone()).await?;
|
let chat_res = client.exec_chat_stream(MODEL, chat_req.clone(), None).await?;
|
||||||
|
|
||||||
println!("\n--- Answer: (streaming)");
|
println!("\n--- Answer: (streaming)");
|
||||||
let assistant_answer = print_chat_stream(chat_res).await?;
|
let assistant_answer = print_chat_stream(chat_res).await?;
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
chat_req = chat_req.append_message(ChatMessage::user(question));
|
chat_req = chat_req.append_message(ChatMessage::user(question));
|
||||||
|
|
||||||
println!("\n--- Question:\n{question}");
|
println!("\n--- Question:\n{question}");
|
||||||
let chat_res = client.exec_chat_stream(MODEL, chat_req.clone()).await?;
|
let chat_res = client.exec_chat_stream(MODEL, chat_req.clone(), None).await?;
|
||||||
|
|
||||||
println!("\n--- Answer: (streaming)");
|
println!("\n--- Answer: (streaming)");
|
||||||
let assistant_answer = print_chat_stream(chat_res).await?;
|
let assistant_answer = print_chat_stream(chat_res).await?;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use crate::adapter::support::get_api_key_resolver;
|
use crate::adapter::support::get_api_key_resolver;
|
||||||
use crate::adapter::AdapterConfig;
|
use crate::adapter::AdapterConfig;
|
||||||
use crate::chat::{ChatRequest, ChatResponse, ChatStreamResponse};
|
use crate::chat::{ChatRequest, ChatRequestOptions, ChatResponse, ChatStreamResponse};
|
||||||
use crate::webc::WebResponse;
|
use crate::webc::WebResponse;
|
||||||
use crate::{ConfigSet, Result};
|
use crate::{ConfigSet, Result};
|
||||||
use derive_more::Display;
|
use derive_more::Display;
|
||||||
@@ -19,7 +19,7 @@ pub enum AdapterKind {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl AdapterKind {
|
impl AdapterKind {
|
||||||
/// Very simplistic getter for now.
|
/// Very simplistic mapper for now.
|
||||||
pub fn from_model(model: &str) -> Result<Self> {
|
pub fn from_model(model: &str) -> Result<Self> {
|
||||||
if model.starts_with("gpt") {
|
if model.starts_with("gpt") {
|
||||||
Ok(AdapterKind::OpenAI)
|
Ok(AdapterKind::OpenAI)
|
||||||
@@ -42,6 +42,8 @@ pub trait Adapter {
|
|||||||
/// Note: Implementation typically using OnceLock
|
/// Note: Implementation typically using OnceLock
|
||||||
fn default_adapter_config(kind: AdapterKind) -> &'static AdapterConfig;
|
fn default_adapter_config(kind: AdapterKind) -> &'static AdapterConfig;
|
||||||
|
|
||||||
|
/// The base service url for this AdapterKind for this given service type.
|
||||||
|
/// NOTE: For some services, the url will be further updated in the to_web_request_data
|
||||||
fn get_service_url(kind: AdapterKind, service_type: ServiceType) -> String;
|
fn get_service_url(kind: AdapterKind, service_type: ServiceType) -> String;
|
||||||
|
|
||||||
/// Get the api_key, with default implementation.
|
/// Get the api_key, with default implementation.
|
||||||
@@ -53,9 +55,10 @@ pub trait Adapter {
|
|||||||
fn to_web_request_data(
|
fn to_web_request_data(
|
||||||
kind: AdapterKind,
|
kind: AdapterKind,
|
||||||
config_set: &ConfigSet<'_>,
|
config_set: &ConfigSet<'_>,
|
||||||
|
service_type: ServiceType,
|
||||||
model: &str,
|
model: &str,
|
||||||
chat_req: ChatRequest,
|
chat_req: ChatRequest,
|
||||||
service_type: ServiceType,
|
chat_req_options: Option<&ChatRequestOptions>,
|
||||||
) -> Result<WebRequestData>;
|
) -> Result<WebRequestData>;
|
||||||
|
|
||||||
/// To be implemented by Adapters
|
/// To be implemented by Adapters
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use crate::adapter::anthropic::AnthropicMessagesStream;
|
use crate::adapter::anthropic::AnthropicMessagesStream;
|
||||||
use crate::adapter::support::get_api_key_resolver;
|
use crate::adapter::support::get_api_key_resolver;
|
||||||
use crate::adapter::{Adapter, AdapterConfig, AdapterKind, ServiceType, WebRequestData};
|
use crate::adapter::{Adapter, AdapterConfig, AdapterKind, ServiceType, WebRequestData};
|
||||||
use crate::chat::{ChatRequest, ChatResponse, ChatRole, ChatStream, ChatStreamResponse};
|
use crate::chat::{ChatRequest, ChatRequestOptions, ChatResponse, ChatRole, ChatStream, ChatStreamResponse};
|
||||||
use crate::utils::x_value::XValue;
|
use crate::utils::x_value::XValue;
|
||||||
use crate::webc::WebResponse;
|
use crate::webc::WebResponse;
|
||||||
use crate::{ConfigSet, Result};
|
use crate::{ConfigSet, Result};
|
||||||
@@ -31,9 +31,10 @@ impl Adapter for AnthropicAdapter {
|
|||||||
fn to_web_request_data(
|
fn to_web_request_data(
|
||||||
kind: AdapterKind,
|
kind: AdapterKind,
|
||||||
config_set: &ConfigSet<'_>,
|
config_set: &ConfigSet<'_>,
|
||||||
|
service_type: ServiceType,
|
||||||
model: &str,
|
model: &str,
|
||||||
chat_req: ChatRequest,
|
chat_req: ChatRequest,
|
||||||
service_type: ServiceType,
|
_chat_req_options: Option<&ChatRequestOptions>,
|
||||||
) -> Result<WebRequestData> {
|
) -> Result<WebRequestData> {
|
||||||
let stream = matches!(service_type, ServiceType::ChatStream);
|
let stream = matches!(service_type, ServiceType::ChatStream);
|
||||||
let url = Self::get_service_url(kind, service_type);
|
let url = Self::get_service_url(kind, service_type);
|
||||||
@@ -78,7 +79,10 @@ impl Adapter for AnthropicAdapter {
|
|||||||
Some(content.join(""))
|
Some(content.join(""))
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(ChatResponse { content })
|
Ok(ChatResponse {
|
||||||
|
content,
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_chat_stream(_kind: AdapterKind, reqwest_builder: RequestBuilder) -> Result<ChatStreamResponse> {
|
fn to_chat_stream(_kind: AdapterKind, reqwest_builder: RequestBuilder) -> Result<ChatStreamResponse> {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use crate::adapter::cohere::CohereStream;
|
use crate::adapter::cohere::CohereStream;
|
||||||
use crate::adapter::support::get_api_key_resolver;
|
use crate::adapter::support::get_api_key_resolver;
|
||||||
use crate::adapter::{Adapter, AdapterConfig, AdapterKind, ServiceType, WebRequestData};
|
use crate::adapter::{Adapter, AdapterConfig, AdapterKind, ServiceType, WebRequestData};
|
||||||
use crate::chat::{ChatRequest, ChatResponse, ChatRole, ChatStream, ChatStreamResponse};
|
use crate::chat::{ChatRequest, ChatRequestOptions, ChatResponse, ChatRole, ChatStream, ChatStreamResponse};
|
||||||
use crate::utils::x_value::XValue;
|
use crate::utils::x_value::XValue;
|
||||||
use crate::webc::{WebResponse, WebStream};
|
use crate::webc::{WebResponse, WebStream};
|
||||||
use crate::{ConfigSet, Error, Result};
|
use crate::{ConfigSet, Error, Result};
|
||||||
@@ -29,9 +29,10 @@ impl Adapter for CohereAdapter {
|
|||||||
fn to_web_request_data(
|
fn to_web_request_data(
|
||||||
kind: AdapterKind,
|
kind: AdapterKind,
|
||||||
config_set: &ConfigSet<'_>,
|
config_set: &ConfigSet<'_>,
|
||||||
|
service_type: ServiceType,
|
||||||
model: &str,
|
model: &str,
|
||||||
chat_req: ChatRequest,
|
chat_req: ChatRequest,
|
||||||
service_type: ServiceType,
|
_chat_req_options: Option<&ChatRequestOptions>,
|
||||||
) -> Result<WebRequestData> {
|
) -> Result<WebRequestData> {
|
||||||
let stream = matches!(service_type, ServiceType::ChatStream);
|
let stream = matches!(service_type, ServiceType::ChatStream);
|
||||||
|
|
||||||
@@ -79,7 +80,10 @@ impl Adapter for CohereAdapter {
|
|||||||
|
|
||||||
let content: Option<String> = last_chat_history_item.x_take("message")?;
|
let content: Option<String> = last_chat_history_item.x_take("message")?;
|
||||||
|
|
||||||
Ok(ChatResponse { content })
|
Ok(ChatResponse {
|
||||||
|
content,
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_chat_stream(_kind: AdapterKind, reqwest_builder: RequestBuilder) -> Result<ChatStreamResponse> {
|
fn to_chat_stream(_kind: AdapterKind, reqwest_builder: RequestBuilder) -> Result<ChatStreamResponse> {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use crate::adapter::gemini::GeminiStream;
|
use crate::adapter::gemini::GeminiStream;
|
||||||
use crate::adapter::support::get_api_key_resolver;
|
use crate::adapter::support::get_api_key_resolver;
|
||||||
use crate::adapter::{Adapter, AdapterConfig, AdapterKind, ServiceType, WebRequestData};
|
use crate::adapter::{Adapter, AdapterConfig, AdapterKind, ServiceType, WebRequestData};
|
||||||
use crate::chat::{ChatRequest, ChatResponse, ChatRole, ChatStream, ChatStreamResponse};
|
use crate::chat::{ChatRequest, ChatRequestOptions, ChatResponse, ChatRole, ChatStream, ChatStreamResponse};
|
||||||
use crate::utils::x_value::XValue;
|
use crate::utils::x_value::XValue;
|
||||||
use crate::webc::{WebResponse, WebStream};
|
use crate::webc::{WebResponse, WebStream};
|
||||||
use crate::{ConfigSet, Error, Result};
|
use crate::{ConfigSet, Error, Result};
|
||||||
@@ -33,12 +33,15 @@ impl Adapter for GeminiAdapter {
|
|||||||
fn to_web_request_data(
|
fn to_web_request_data(
|
||||||
kind: AdapterKind,
|
kind: AdapterKind,
|
||||||
config_set: &ConfigSet<'_>,
|
config_set: &ConfigSet<'_>,
|
||||||
|
service_type: ServiceType,
|
||||||
model: &str,
|
model: &str,
|
||||||
chat_req: ChatRequest,
|
chat_req: ChatRequest,
|
||||||
service_type: ServiceType,
|
_chat_req_options: Option<&ChatRequestOptions>,
|
||||||
) -> Result<WebRequestData> {
|
) -> Result<WebRequestData> {
|
||||||
let api_key = get_api_key_resolver(kind, config_set)?;
|
let api_key = get_api_key_resolver(kind, config_set)?;
|
||||||
|
|
||||||
|
// For gemini, the service url returned is just the base url
|
||||||
|
// since model and API key is part of the url (see below)
|
||||||
let url = Self::get_service_url(kind, service_type);
|
let url = Self::get_service_url(kind, service_type);
|
||||||
|
|
||||||
// e.g., '...models/gemini-1.5-flash-latest:generateContent?key=YOUR_API_KEY'
|
// e.g., '...models/gemini-1.5-flash-latest:generateContent?key=YOUR_API_KEY'
|
||||||
@@ -65,6 +68,7 @@ impl Adapter for GeminiAdapter {
|
|||||||
|
|
||||||
Ok(ChatResponse {
|
Ok(ChatResponse {
|
||||||
content: gemini_response.content,
|
content: gemini_response.content,
|
||||||
|
..Default::default()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
use crate::adapter::openai::OpenAIAdapter;
|
use crate::adapter::openai::OpenAIAdapter;
|
||||||
use crate::adapter::{Adapter, AdapterConfig, AdapterKind, ServiceType, WebRequestData};
|
use crate::adapter::{Adapter, AdapterConfig, AdapterKind, ServiceType, WebRequestData};
|
||||||
use crate::chat::{ChatRequest, ChatResponse, ChatStreamResponse};
|
use crate::chat::{ChatRequest, ChatRequestOptions, ChatResponse, ChatStreamResponse};
|
||||||
use crate::webc::WebResponse;
|
use crate::webc::WebResponse;
|
||||||
use crate::{ConfigSet, Result};
|
use crate::{ConfigSet, Result};
|
||||||
use reqwest::RequestBuilder;
|
use reqwest::RequestBuilder;
|
||||||
@@ -28,9 +28,10 @@ impl Adapter for OllamaAdapter {
|
|||||||
fn to_web_request_data(
|
fn to_web_request_data(
|
||||||
kind: AdapterKind,
|
kind: AdapterKind,
|
||||||
_config_set: &ConfigSet<'_>,
|
_config_set: &ConfigSet<'_>,
|
||||||
|
service_type: ServiceType,
|
||||||
model: &str,
|
model: &str,
|
||||||
chat_req: ChatRequest,
|
chat_req: ChatRequest,
|
||||||
service_type: ServiceType,
|
_chat_req_options: Option<&ChatRequestOptions>,
|
||||||
) -> Result<WebRequestData> {
|
) -> Result<WebRequestData> {
|
||||||
let url = Self::get_service_url(kind, service_type);
|
let url = Self::get_service_url(kind, service_type);
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use crate::adapter::openai::OpenAIMessagesStream;
|
use crate::adapter::openai::OpenAIMessagesStream;
|
||||||
use crate::adapter::support::get_api_key_resolver;
|
use crate::adapter::support::get_api_key_resolver;
|
||||||
use crate::adapter::{Adapter, AdapterConfig, AdapterKind, ServiceType, WebRequestData};
|
use crate::adapter::{Adapter, AdapterConfig, AdapterKind, ServiceType, WebRequestData};
|
||||||
use crate::chat::{ChatRequest, ChatResponse, ChatRole, ChatStream, ChatStreamResponse};
|
use crate::chat::{ChatRequest, ChatRequestOptions, ChatResponse, ChatRole, ChatStream, ChatStreamResponse};
|
||||||
use crate::utils::x_value::XValue;
|
use crate::utils::x_value::XValue;
|
||||||
use crate::webc::WebResponse;
|
use crate::webc::WebResponse;
|
||||||
use crate::{ConfigSet, Error, Result};
|
use crate::{ConfigSet, Error, Result};
|
||||||
@@ -27,9 +27,10 @@ impl Adapter for OpenAIAdapter {
|
|||||||
fn to_web_request_data(
|
fn to_web_request_data(
|
||||||
kind: AdapterKind,
|
kind: AdapterKind,
|
||||||
config_set: &ConfigSet<'_>,
|
config_set: &ConfigSet<'_>,
|
||||||
|
service_type: ServiceType,
|
||||||
model: &str,
|
model: &str,
|
||||||
chat_req: ChatRequest,
|
chat_req: ChatRequest,
|
||||||
service_type: ServiceType,
|
_chat_req_options: Option<&ChatRequestOptions>,
|
||||||
) -> Result<WebRequestData> {
|
) -> Result<WebRequestData> {
|
||||||
// -- api_key (this Adapter requires it)
|
// -- api_key (this Adapter requires it)
|
||||||
let api_key = get_api_key_resolver(kind, config_set)?;
|
let api_key = get_api_key_resolver(kind, config_set)?;
|
||||||
@@ -42,7 +43,10 @@ impl Adapter for OpenAIAdapter {
|
|||||||
let WebResponse { mut body, .. } = web_response;
|
let WebResponse { mut body, .. } = web_response;
|
||||||
let first_choice: Option<Value> = body.x_take("/choices/0")?;
|
let first_choice: Option<Value> = body.x_take("/choices/0")?;
|
||||||
let content: Option<String> = first_choice.map(|mut c| c.x_take("/message/content")).transpose()?;
|
let content: Option<String> = first_choice.map(|mut c| c.x_take("/message/content")).transpose()?;
|
||||||
Ok(ChatResponse { content })
|
Ok(ChatResponse {
|
||||||
|
content,
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_chat_stream(_kind: AdapterKind, reqwest_builder: RequestBuilder) -> Result<ChatStreamResponse> {
|
fn to_chat_stream(_kind: AdapterKind, reqwest_builder: RequestBuilder) -> Result<ChatStreamResponse> {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ use crate::adapter::gemini::GeminiAdapter;
|
|||||||
use crate::adapter::ollama::OllamaAdapter;
|
use crate::adapter::ollama::OllamaAdapter;
|
||||||
use crate::adapter::openai::OpenAIAdapter;
|
use crate::adapter::openai::OpenAIAdapter;
|
||||||
use crate::adapter::{Adapter, AdapterConfig, AdapterKind, ServiceType, WebRequestData};
|
use crate::adapter::{Adapter, AdapterConfig, AdapterKind, ServiceType, WebRequestData};
|
||||||
use crate::chat::{ChatRequest, ChatResponse, ChatStreamResponse};
|
use crate::chat::{ChatRequest, ChatRequestOptions, ChatResponse, ChatStreamResponse};
|
||||||
use crate::webc::WebResponse;
|
use crate::webc::WebResponse;
|
||||||
use crate::{ConfigSet, Result};
|
use crate::{ConfigSet, Result};
|
||||||
use reqwest::RequestBuilder;
|
use reqwest::RequestBuilder;
|
||||||
@@ -35,18 +35,27 @@ impl Adapter for AdapterDispatcher {
|
|||||||
fn to_web_request_data(
|
fn to_web_request_data(
|
||||||
kind: AdapterKind,
|
kind: AdapterKind,
|
||||||
config_set: &ConfigSet<'_>,
|
config_set: &ConfigSet<'_>,
|
||||||
|
service_type: ServiceType,
|
||||||
model: &str,
|
model: &str,
|
||||||
chat_req: ChatRequest,
|
chat_req: ChatRequest,
|
||||||
service_type: ServiceType,
|
chat_req_options: Option<&ChatRequestOptions>,
|
||||||
) -> Result<WebRequestData> {
|
) -> Result<WebRequestData> {
|
||||||
match kind {
|
match kind {
|
||||||
AdapterKind::OpenAI => OpenAIAdapter::to_web_request_data(kind, config_set, model, chat_req, service_type),
|
AdapterKind::OpenAI => {
|
||||||
AdapterKind::Anthropic => {
|
OpenAIAdapter::to_web_request_data(kind, config_set, service_type, model, chat_req, chat_req_options)
|
||||||
AnthropicAdapter::to_web_request_data(kind, config_set, model, chat_req, service_type)
|
}
|
||||||
|
AdapterKind::Anthropic => {
|
||||||
|
AnthropicAdapter::to_web_request_data(kind, config_set, service_type, model, chat_req, chat_req_options)
|
||||||
|
}
|
||||||
|
AdapterKind::Cohere => {
|
||||||
|
CohereAdapter::to_web_request_data(kind, config_set, service_type, model, chat_req, chat_req_options)
|
||||||
|
}
|
||||||
|
AdapterKind::Ollama => {
|
||||||
|
OllamaAdapter::to_web_request_data(kind, config_set, service_type, model, chat_req, chat_req_options)
|
||||||
|
}
|
||||||
|
AdapterKind::Gemini => {
|
||||||
|
GeminiAdapter::to_web_request_data(kind, config_set, service_type, model, chat_req, chat_req_options)
|
||||||
}
|
}
|
||||||
AdapterKind::Cohere => CohereAdapter::to_web_request_data(kind, config_set, model, chat_req, service_type),
|
|
||||||
AdapterKind::Ollama => OllamaAdapter::to_web_request_data(kind, config_set, model, chat_req, service_type),
|
|
||||||
AdapterKind::Gemini => GeminiAdapter::to_web_request_data(kind, config_set, model, chat_req, service_type),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
17
src/chat/chat_options.rs
Normal file
17
src/chat/chat_options.rs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
//! ChatRequestOptions is a struct that can be passed into the `client::exec_chat...` as the last argument
|
||||||
|
//! to customize the request behavior per call.
|
||||||
|
//! Note: Splitting it out of the `ChatRequest` object allows for better reusability of each component.
|
||||||
|
//!
|
||||||
|
//! IMPORTANT: These are not implemented yet, but here to show some of the directions and start having them part of the client APIs.
|
||||||
|
|
||||||
|
pub struct ChatRequestOptions {
|
||||||
|
/// Will capture the `MetaUsage`
|
||||||
|
/// - In the `ChatResponse` for `exec_chat`
|
||||||
|
/// - In the `StreamEnd` of `StreamEvent::End(StreamEnd)` for `exec_chat_stream`
|
||||||
|
pub capture_usage: Option<bool>,
|
||||||
|
|
||||||
|
// -- For Stream only (for now, we flat them out)
|
||||||
|
/// Tell the chat stream executor to capture and concatenate all of the text chunk
|
||||||
|
/// to the last `StreamEvent::End(StreamEnd)` event as `StreamEnd.captured_content` (so, will be `Some(concatenated_chunks)`)
|
||||||
|
pub capture_content: Option<bool>,
|
||||||
|
}
|
||||||
@@ -2,9 +2,12 @@ use crate::chat::ChatStream;
|
|||||||
|
|
||||||
// region: --- ChatResponse
|
// region: --- ChatResponse
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone, Default)]
|
||||||
pub struct ChatResponse {
|
pub struct ChatResponse {
|
||||||
pub content: Option<String>,
|
pub content: Option<String>,
|
||||||
|
/// NOT SUPPORTED
|
||||||
|
#[allow(unused)]
|
||||||
|
pub meta_usage: Option<MetaUsage>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// endregion: --- ChatResponse
|
// endregion: --- ChatResponse
|
||||||
@@ -16,3 +19,16 @@ pub struct ChatStreamResponse {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// endregion: --- ChatStreamResponse
|
// endregion: --- ChatStreamResponse
|
||||||
|
|
||||||
|
// region: --- MetaUsage
|
||||||
|
|
||||||
|
// IMPORTANT: This is NOT used for now. To show the API direction.
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct MetaUsage {
|
||||||
|
pub input_token: Option<i32>,
|
||||||
|
pub output_token: Option<i32>,
|
||||||
|
pub total_token: Option<i32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
// endregion: --- MetaUsage
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
use crate::adapter::inter_stream::InterStreamEvent;
|
use crate::adapter::inter_stream::InterStreamEvent;
|
||||||
|
use crate::chat::MetaUsage;
|
||||||
use crate::Result;
|
use crate::Result;
|
||||||
use derive_more::From;
|
use derive_more::From;
|
||||||
use futures::Stream;
|
use futures::Stream;
|
||||||
@@ -67,6 +68,9 @@ pub struct StreamChunk {
|
|||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct StreamEnd {
|
pub struct StreamEnd {
|
||||||
|
/// The eventual capture UsageMeta
|
||||||
|
pub meta_usage: Option<MetaUsage>,
|
||||||
|
|
||||||
/// The optional captured full content
|
/// The optional captured full content
|
||||||
/// NOTE: NOT SUPPORTED YET (always None for now)
|
/// NOTE: NOT SUPPORTED YET (always None for now)
|
||||||
/// Probably allow to toggle this on at the client_config, adapter_config
|
/// Probably allow to toggle this on at the client_config, adapter_config
|
||||||
|
|||||||
@@ -3,12 +3,14 @@
|
|||||||
|
|
||||||
// region: --- Modules
|
// region: --- Modules
|
||||||
|
|
||||||
|
mod chat_options;
|
||||||
mod chat_req;
|
mod chat_req;
|
||||||
mod chat_res;
|
mod chat_res;
|
||||||
mod chat_stream;
|
mod chat_stream;
|
||||||
mod tool;
|
mod tool;
|
||||||
|
|
||||||
// -- Flatten
|
// -- Flatten
|
||||||
|
pub use chat_options::*;
|
||||||
pub use chat_req::*;
|
pub use chat_req::*;
|
||||||
pub use chat_res::*;
|
pub use chat_res::*;
|
||||||
pub use chat_stream::*;
|
pub use chat_stream::*;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use crate::adapter::{Adapter, AdapterDispatcher, AdapterKind, ServiceType, WebRequestData};
|
use crate::adapter::{Adapter, AdapterDispatcher, AdapterKind, ServiceType, WebRequestData};
|
||||||
use crate::chat::{ChatRequest, ChatResponse, ChatStreamResponse};
|
use crate::chat::{ChatRequest, ChatRequestOptions, ChatResponse, ChatStreamResponse};
|
||||||
use crate::client::Client;
|
use crate::client::Client;
|
||||||
use crate::{ConfigSet, Result};
|
use crate::{ConfigSet, Result};
|
||||||
|
|
||||||
@@ -9,7 +9,13 @@ impl Client {
|
|||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn exec_chat(&self, model: &str, chat_req: ChatRequest) -> Result<ChatResponse> {
|
pub async fn exec_chat(
|
||||||
|
&self,
|
||||||
|
model: &str,
|
||||||
|
chat_req: ChatRequest,
|
||||||
|
// options not implemented yet
|
||||||
|
options: Option<&ChatRequestOptions>,
|
||||||
|
) -> Result<ChatResponse> {
|
||||||
let adapter_kind = AdapterKind::from_model(model)?;
|
let adapter_kind = AdapterKind::from_model(model)?;
|
||||||
|
|
||||||
let adapter_config = self
|
let adapter_config = self
|
||||||
@@ -18,8 +24,14 @@ impl Client {
|
|||||||
|
|
||||||
let config_set = ConfigSet::new(self.config(), adapter_config);
|
let config_set = ConfigSet::new(self.config(), adapter_config);
|
||||||
|
|
||||||
let WebRequestData { headers, payload, url } =
|
let WebRequestData { headers, payload, url } = AdapterDispatcher::to_web_request_data(
|
||||||
AdapterDispatcher::to_web_request_data(adapter_kind, &config_set, model, chat_req, ServiceType::Chat)?;
|
adapter_kind,
|
||||||
|
&config_set,
|
||||||
|
ServiceType::Chat,
|
||||||
|
model,
|
||||||
|
chat_req,
|
||||||
|
options,
|
||||||
|
)?;
|
||||||
|
|
||||||
let web_res = self.web_client().do_post(&url, &headers, payload).await?;
|
let web_res = self.web_client().do_post(&url, &headers, payload).await?;
|
||||||
|
|
||||||
@@ -28,7 +40,12 @@ impl Client {
|
|||||||
Ok(chat_res)
|
Ok(chat_res)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn exec_chat_stream(&self, model: &str, chat_req: ChatRequest) -> Result<ChatStreamResponse> {
|
pub async fn exec_chat_stream(
|
||||||
|
&self,
|
||||||
|
model: &str,
|
||||||
|
chat_req: ChatRequest, // options not implemented yet
|
||||||
|
options: Option<&ChatRequestOptions>,
|
||||||
|
) -> Result<ChatStreamResponse> {
|
||||||
let adapter_kind = AdapterKind::from_model(model)?;
|
let adapter_kind = AdapterKind::from_model(model)?;
|
||||||
|
|
||||||
let adapter_config = self
|
let adapter_config = self
|
||||||
@@ -40,9 +57,10 @@ impl Client {
|
|||||||
let WebRequestData { url, headers, payload } = AdapterDispatcher::to_web_request_data(
|
let WebRequestData { url, headers, payload } = AdapterDispatcher::to_web_request_data(
|
||||||
adapter_kind,
|
adapter_kind,
|
||||||
&config_set,
|
&config_set,
|
||||||
|
ServiceType::ChatStream,
|
||||||
model,
|
model,
|
||||||
chat_req,
|
chat_req,
|
||||||
ServiceType::ChatStream,
|
options,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let reqwest_builder = self.web_client().new_req_builder(&url, &headers, payload)?;
|
let reqwest_builder = self.web_client().new_req_builder(&url, &headers, payload)?;
|
||||||
|
|||||||
Reference in New Issue
Block a user