From e2e178cf0b98c75a005382fc29535abaebe771ba Mon Sep 17 00:00:00 2001 From: Christos Hadjiaslanis Date: Mon, 22 Jul 2024 18:52:05 +0100 Subject: [PATCH] feat: OpenAI resource (#1794) * Added OpenAI resource * Update scripts/patches.toml Co-authored-by: jonaro00 <54029719+jonaro00@users.noreply.github.com> * Update resources/openai/src/lib.rs Co-authored-by: jonaro00 <54029719+jonaro00@users.noreply.github.com> * Update resources/openai/src/lib.rs Co-authored-by: jonaro00 <54029719+jonaro00@users.noreply.github.com> * Update resources/openai/Cargo.toml Co-authored-by: jonaro00 <54029719+jonaro00@users.noreply.github.com> * feat: update to 0.47.0 * fmt --------- Co-authored-by: jonaro00 <54029719+jonaro00@users.noreply.github.com> --- .circleci/config.yml | 6 ++- resources/openai/Cargo.toml | 15 +++++++ resources/openai/src/lib.rs | 78 +++++++++++++++++++++++++++++++++++++ scripts/patches.toml | 1 + 4 files changed, 98 insertions(+), 2 deletions(-) create mode 100644 resources/openai/Cargo.toml create mode 100644 resources/openai/src/lib.rs diff --git a/.circleci/config.yml b/.circleci/config.yml index a9819b25f..a40a4b76c 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -622,11 +622,12 @@ workflows: parameters: path: - resources/aws-rds + - resources/openai + - resources/opendal - resources/persist - resources/qdrant - resources/shared-db - resources/turso - - resources/opendal - services/shuttle-actix-web - services/shuttle-axum - services/shuttle-poem @@ -883,11 +884,12 @@ workflows: parameters: path: - resources/aws-rds + - resources/openai + - resources/opendal - resources/persist - resources/qdrant - resources/shared-db - resources/turso - - resources/opendal name: publish-<< matrix.path >> requires: - publish-service diff --git a/resources/openai/Cargo.toml b/resources/openai/Cargo.toml new file mode 100644 index 000000000..f933267b8 --- /dev/null +++ b/resources/openai/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "shuttle-openai" +version = "0.47.0" +edition = "2021" +license = "Apache-2.0" +description = "Shuttle plugin for connecting to OpenAI" +repository = "https://github.com/shuttle-hq/shuttle" +keywords = ["shuttle-service", "openai"] + +[dependencies] +async-openai = "0.23.0" +async-trait = "0.1.56" +serde = { version = "1.0.203", features = ["derive"] } +serde_json = "1" +shuttle-service = { path = "../../service", version = "0.47.0" } diff --git a/resources/openai/src/lib.rs b/resources/openai/src/lib.rs new file mode 100644 index 000000000..e97de879a --- /dev/null +++ b/resources/openai/src/lib.rs @@ -0,0 +1,78 @@ +use async_openai::config::OpenAIConfig; +use async_openai::Client; +use async_trait::async_trait; +use serde::{Deserialize, Serialize}; +use shuttle_service::{CustomError, Error, IntoResource, ResourceFactory, ResourceInputBuilder}; + +pub use async_openai; + +#[derive(Default, Serialize)] +pub struct OpenAI { + api_base: Option, + api_key: Option, + org_id: Option, + project_id: Option, +} + +impl OpenAI { + pub fn api_base(mut self, api_base: &str) -> Self { + self.api_base = Some(api_base.to_string()); + self + } + pub fn api_key(mut self, api_key: &str) -> Self { + self.api_key = Some(api_key.to_string()); + self + } + pub fn org_id(mut self, org_id: &str) -> Self { + self.org_id = Some(org_id.to_string()); + self + } + pub fn project_id(mut self, project_id: &str) -> Self { + self.project_id = Some(project_id.to_string()); + self + } +} + +#[derive(Serialize, Deserialize)] +pub struct Config { + api_base: Option, + api_key: String, + org_id: Option, + project_id: Option, +} + +#[async_trait] +impl ResourceInputBuilder for OpenAI { + type Input = Config; + type Output = Config; + + async fn build(self, _factory: &ResourceFactory) -> Result { + let api_key = self + .api_key + .ok_or(Error::Custom(CustomError::msg("Open AI API key required")))?; + let config = Config { + api_base: self.api_base, + api_key, + org_id: self.org_id, + project_id: self.project_id, + }; + Ok(config) + } +} + +#[async_trait] +impl IntoResource> for Config { + async fn into_resource(self) -> Result, Error> { + let mut openai_config = OpenAIConfig::new().with_api_key(self.api_key); + if let Some(api_base) = self.api_base { + openai_config = openai_config.with_api_base(api_base) + } + if let Some(org_id) = self.org_id { + openai_config = openai_config.with_org_id(org_id) + } + if let Some(project_id) = self.project_id { + openai_config = openai_config.with_project_id(project_id) + } + Ok(Client::with_config(openai_config)) + } +} diff --git a/scripts/patches.toml b/scripts/patches.toml index b94c85fba..0c069ce25 100644 --- a/scripts/patches.toml +++ b/scripts/patches.toml @@ -6,6 +6,7 @@ shuttle-runtime = { path = "BASE/runtime" } shuttle-service = { path = "BASE/service" } shuttle-aws-rds = { path = "BASE/resources/aws-rds" } +shuttle-openai = { path = "BASE/resources/openai" } shuttle-opendal = { path = "BASE/resources/opendal" } shuttle-persist = { path = "BASE/resources/persist" } shuttle-qdrant = { path = "BASE/resources/qdrant" }