Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove generics of Client, enabling dynamic dispatch #125

Open
wants to merge 15 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion async-openai/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "async-openai"
version = "0.18.1"
version = "0.19.0"
authors = [
"Himanshu Neema"
]
Expand Down
9 changes: 4 additions & 5 deletions async-openai/src/assistant_files.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use serde::Serialize;

use crate::{
config::Config,
error::OpenAIError,
types::{
AssistantFileObject, CreateAssistantFileRequest, DeleteAssistantFileResponse,
Expand All @@ -11,13 +10,13 @@ use crate::{
};

/// Files attached to an assistant.
pub struct AssistantFiles<'c, C: Config> {
client: &'c Client<C>,
pub struct AssistantFiles<'c> {
client: &'c Client,
pub assistant_id: String,
}

impl<'c, C: Config> AssistantFiles<'c, C> {
pub fn new(client: &'c Client<C>, assistant_id: &str) -> Self {
impl<'c> AssistantFiles<'c> {
pub fn new(client: &'c Client, assistant_id: &str) -> Self {
Self {
client,
assistant_id: assistant_id.into(),
Expand Down
11 changes: 5 additions & 6 deletions async-openai/src/assistants.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use serde::Serialize;

use crate::{
config::Config,
error::OpenAIError,
types::{
AssistantObject, CreateAssistantRequest, DeleteAssistantResponse, ListAssistantsResponse,
Expand All @@ -13,17 +12,17 @@ use crate::{
/// Build assistants that can call models and use tools to perform tasks.
///
/// [Get started with the Assistants API](https://platform.openai.com/docs/assistants)
pub struct Assistants<'c, C: Config> {
client: &'c Client<C>,
pub struct Assistants<'c> {
client: &'c Client,
}

impl<'c, C: Config> Assistants<'c, C> {
pub fn new(client: &'c Client<C>) -> Self {
impl<'c> Assistants<'c> {
pub fn new(client: &'c Client) -> Self {
Self { client }
}

/// Assistant [AssistantFiles] API group
pub fn files(&self, assistant_id: &str) -> AssistantFiles<C> {
pub fn files(&self, assistant_id: &str) -> AssistantFiles {
AssistantFiles::new(self.client, assistant_id)
}

Expand Down
9 changes: 4 additions & 5 deletions async-openai/src/audio.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use crate::{
config::Config,
error::OpenAIError,
types::{
CreateSpeechRequest, CreateSpeechResponse, CreateTranscriptionRequest,
Expand All @@ -10,12 +9,12 @@ use crate::{

/// Turn audio into text
/// Related guide: [Speech to text](https://platform.openai.com/docs/guides/speech-to-text)
pub struct Audio<'c, C: Config> {
client: &'c Client<C>,
pub struct Audio<'c> {
client: &'c Client,
}

impl<'c, C: Config> Audio<'c, C> {
pub fn new(client: &'c Client<C>) -> Self {
impl<'c> Audio<'c> {
pub fn new(client: &'c Client) -> Self {
Self { client }
}

Expand Down
9 changes: 4 additions & 5 deletions async-openai/src/chat.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use crate::{
config::Config,
error::OpenAIError,
types::{
ChatCompletionResponseStream, CreateChatCompletionRequest, CreateChatCompletionResponse,
Expand All @@ -10,12 +9,12 @@ use crate::{
/// Given a list of messages comprising a conversation, the model will return a response.
///
/// Related guide: [Chat completions](https://platform.openai.com//docs/guides/text-generation)
pub struct Chat<'c, C: Config> {
client: &'c Client<C>,
pub struct Chat<'c> {
client: &'c Client,
}

impl<'c, C: Config> Chat<'c, C> {
pub fn new(client: &'c Client<C>) -> Self {
impl<'c> Chat<'c> {
pub fn new(client: &'c Client) -> Self {
Self { client }
}

Expand Down
71 changes: 36 additions & 35 deletions async-openai/src/client.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::pin::Pin;
use std::sync::Arc;

use bytes::Bytes;
use futures::{stream::StreamExt, Stream};
Expand All @@ -18,29 +19,29 @@ use crate::{
#[derive(Debug, Clone)]
/// Client is a container for config, backoff and http_client
/// used to make API calls.
pub struct Client<C: Config> {
pub struct Client {
http_client: reqwest::Client,
config: C,
config: Arc<dyn Config>,
backoff: backoff::ExponentialBackoff,
}

impl Client<OpenAIConfig> {
impl Client {
/// Client with default [OpenAIConfig]
pub fn new() -> Self {
Self {
http_client: reqwest::Client::new(),
config: OpenAIConfig::default(),
config: Arc::new(OpenAIConfig::default()),
backoff: Default::default(),
}
}
}

impl<C: Config> Client<C> {
impl Client {
/// Create client with [OpenAIConfig] or [crate::config::AzureConfig]
pub fn with_config(config: C) -> Self {
pub fn with_config<C: Config>(config: C) -> Self {
Self {
http_client: reqwest::Client::new(),
config,
config: Arc::new(config),
backoff: Default::default(),
}
}
Expand All @@ -62,80 +63,80 @@ impl<C: Config> Client<C> {
// API groups

/// To call [Models] group related APIs using this client.
pub fn models(&self) -> Models<C> {
pub fn models(&self) -> Models {
Models::new(self)
}

/// To call [Completions] group related APIs using this client.
pub fn completions(&self) -> Completions<C> {
pub fn completions(&self) -> Completions {
Completions::new(self)
}

/// To call [Chat] group related APIs using this client.
pub fn chat(&self) -> Chat<C> {
pub fn chat(&self) -> Chat {
Chat::new(self)
}

/// To call [Edits] group related APIs using this client.
#[deprecated(since = "0.15.0", note = "By OpenAI")]
pub fn edits(&self) -> Edits<C> {
pub fn edits(&self) -> Edits {
Edits::new(self)
}

/// To call [Images] group related APIs using this client.
pub fn images(&self) -> Images<C> {
pub fn images(&self) -> Images {
Images::new(self)
}

/// To call [Moderations] group related APIs using this client.
pub fn moderations(&self) -> Moderations<C> {
pub fn moderations(&self) -> Moderations {
Moderations::new(self)
}

/// To call [Files] group related APIs using this client.
pub fn files(&self) -> Files<C> {
pub fn files(&self) -> Files {
Files::new(self)
}

/// To call [FineTunes] group related APIs using this client.
#[deprecated(since = "0.15.0", note = "By OpenAI")]
pub fn fine_tunes(&self) -> FineTunes<C> {
pub fn fine_tunes(&self) -> FineTunes {
FineTunes::new(self)
}

/// To call [FineTuning] group related APIs using this client.
pub fn fine_tuning(&self) -> FineTuning<C> {
pub fn fine_tuning(&self) -> FineTuning {
FineTuning::new(self)
}

/// To call [Embeddings] group related APIs using this client.
pub fn embeddings(&self) -> Embeddings<C> {
pub fn embeddings(&self) -> Embeddings {
Embeddings::new(self)
}

/// To call [Audio] group related APIs using this client.
pub fn audio(&self) -> Audio<C> {
pub fn audio(&self) -> Audio {
Audio::new(self)
}

/// To call [Assistants] group related APIs using this client.
pub fn assistants(&self) -> Assistants<C> {
pub fn assistants(&self) -> Assistants {
Assistants::new(self)
}

/// To call [Threads] group related APIs using this client.
pub fn threads(&self) -> Threads<C> {
pub fn threads(&self) -> Threads {
Threads::new(self)
}

pub fn config(&self) -> &C {
pub fn config(&self) -> &Arc<dyn Config> {
&self.config
}

/// Make a GET request to {path} and deserialize the response body
pub(crate) async fn get<O>(&self, path: &str) -> Result<O, OpenAIError>
where
O: DeserializeOwned,
where
O: DeserializeOwned,
{
let request_maker = || async {
Ok(self
Expand Down Expand Up @@ -170,8 +171,8 @@ impl<C: Config> Client<C> {

/// Make a DELETE request to {path} and deserialize the response body
pub(crate) async fn delete<O>(&self, path: &str) -> Result<O, OpenAIError>
where
O: DeserializeOwned,
where
O: DeserializeOwned,
{
let request_maker = || async {
Ok(self
Expand Down Expand Up @@ -205,9 +206,9 @@ impl<C: Config> Client<C> {

/// Make a POST request to {path} and deserialize the response body
pub(crate) async fn post<I, O>(&self, path: &str, request: I) -> Result<O, OpenAIError>
where
I: Serialize,
O: DeserializeOwned,
where
I: Serialize,
O: DeserializeOwned,
{
let request_maker = || async {
Ok(self
Expand All @@ -224,10 +225,10 @@ impl<C: Config> Client<C> {

/// POST a form at {path} and deserialize the response body
pub(crate) async fn post_form<O, F>(&self, path: &str, form: F) -> Result<O, OpenAIError>
where
O: DeserializeOwned,
reqwest::multipart::Form: async_convert::TryFrom<F, Error = OpenAIError>,
F: Clone,
where
O: DeserializeOwned,
reqwest::multipart::Form: async_convert::TryFrom<F, Error=OpenAIError>,
F: Clone,
{
let request_maker = || async {
Ok(self
Expand All @@ -248,9 +249,9 @@ impl<C: Config> Client<C> {
/// to retry API call after getting rate limited. request_maker is async because
/// reqwest::multipart::Form is created by async calls to read files for uploads.
async fn execute_raw<M, Fut>(&self, request_maker: M) -> Result<Bytes, OpenAIError>
where
M: Fn() -> Fut,
Fut: core::future::Future<Output = Result<reqwest::Request, OpenAIError>>,
where
M: Fn() -> Fut,
Fut: core::future::Future<Output=Result<reqwest::Request, OpenAIError>>,
{
let client = self.http_client.clone();

Expand Down
10 changes: 5 additions & 5 deletions async-openai/src/completion.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use crate::{
client::Client,
config::Config,
error::OpenAIError,
types::{CompletionResponseStream, CreateCompletionRequest, CreateCompletionResponse},
};
Expand All @@ -11,12 +10,13 @@ use crate::{
/// [Learn more](https://platform.openai.com/docs/deprecations/2023-07-06-gpt-and-embeddings)
///
/// Related guide: [Legacy Completions](https://platform.openai.com/docs/guides/gpt/completions-api)
pub struct Completions<'c, C: Config> {
client: &'c Client<C>,

pub struct Completions<'c> {
client: &'c Client,
}

impl<'c, C: Config> Completions<'c, C> {
pub fn new(client: &'c Client<C>) -> Self {
impl<'c> Completions<'c> {
pub fn new(client: &'c Client) -> Self {
Self { client }
}

Expand Down
3 changes: 2 additions & 1 deletion async-openai/src/config.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
//! Client configurations: [OpenAIConfig] for OpenAI, [AzureConfig] for Azure OpenAI Service.
use std::fmt::Debug;
use reqwest::header::{HeaderMap, AUTHORIZATION};
use secrecy::{ExposeSecret, Secret};
use serde::Deserialize;
Expand All @@ -13,7 +14,7 @@ pub const OPENAI_BETA_HEADER: &str = "OpenAI-Beta";

/// [crate::Client] relies on this for every API call on OpenAI
/// or Azure OpenAI service
pub trait Config: Clone {
pub trait Config: 'static + Debug + Send + Sync {
fn headers(&self) -> HeaderMap;
fn url(&self, path: &str) -> String;
fn query(&self) -> Vec<(&str, &str)>;
Expand Down
9 changes: 4 additions & 5 deletions async-openai/src/edit.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
use crate::{
config::Config,
error::OpenAIError,
types::{CreateEditRequest, CreateEditResponse},
Client,
};

/// Given a prompt and an instruction, the model will return
/// an edited version of the prompt.
pub struct Edits<'c, C: Config> {
client: &'c Client<C>,
pub struct Edits<'c> {
client: &'c Client,
}

impl<'c, C: Config> Edits<'c, C> {
pub fn new(client: &'c Client<C>) -> Self {
impl<'c> Edits<'c> {
pub fn new(client: &'c Client) -> Self {
Self { client }
}

Expand Down
9 changes: 4 additions & 5 deletions async-openai/src/embedding.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use crate::{
config::Config,
error::OpenAIError,
types::{CreateEmbeddingRequest, CreateEmbeddingResponse},
Client,
Expand All @@ -9,12 +8,12 @@ use crate::{
/// consumed by machine learning models and algorithms.
///
/// Related guide: [Embeddings](https://platform.openai.com/docs/guides/embeddings/what-are-embeddings)
pub struct Embeddings<'c, C: Config> {
client: &'c Client<C>,
pub struct Embeddings<'c> {
client: &'c Client,
}

impl<'c, C: Config> Embeddings<'c, C> {
pub fn new(client: &'c Client<C>) -> Self {
impl<'c> Embeddings<'c> {
pub fn new(client: &'c Client) -> Self {
Self { client }
}

Expand Down
Loading