kalosm_language_model/openai/
mod.rsuse std::sync::OnceLock;
use thiserror::Error;
mod embedding;
pub use embedding::*;
mod chat;
pub use chat::*;
#[derive(Debug, Clone)]
pub struct OpenAICompatibleClient {
reqwest_client: reqwest::Client,
base_url: String,
api_key: Option<String>,
resolved_api_key: OnceLock<String>,
organization_id: Option<String>,
project_id: Option<String>,
}
impl Default for OpenAICompatibleClient {
fn default() -> Self {
Self::new()
}
}
impl OpenAICompatibleClient {
pub fn new() -> Self {
Self {
reqwest_client: reqwest::Client::new(),
base_url: "https://api.openai.com/v1/".to_string(),
resolved_api_key: OnceLock::new(),
api_key: None,
organization_id: None,
project_id: None,
}
}
pub fn with_api_key(mut self, api_key: impl ToString) -> Self {
self.api_key = Some(api_key.to_string());
self
}
pub fn with_base_url(mut self, base_url: impl ToString) -> Self {
self.base_url = base_url.to_string();
self
}
pub fn with_organization_id(mut self, organization_id: impl ToString) -> Self {
self.organization_id = Some(organization_id.to_string());
self
}
pub fn with_project_id(mut self, project_id: impl ToString) -> Self {
self.project_id = Some(project_id.to_string());
self
}
pub fn with_reqwest_client(mut self, client: reqwest::Client) -> Self {
self.reqwest_client = client;
self
}
pub fn resolve_api_key(&self) -> Result<String, NoOpenAIAPIKeyError> {
if let Some(api_key) = self.resolved_api_key.get() {
return Ok(api_key.clone());
}
let open_api_key = match self.api_key.clone() {
Some(api_key) => api_key,
None => std::env::var("OPENAI_API_KEY").map_err(|_| NoOpenAIAPIKeyError)?,
};
self.resolved_api_key.set(open_api_key.clone()).unwrap();
Ok(open_api_key)
}
pub(crate) fn base_url(&self) -> &str {
self.base_url.trim_end_matches('/')
}
}
#[derive(Debug, Error)]
#[error("No API key was provided in the [OpenAICompatibleClient] builder or the environment variable `OPENAI_API_KEY` was not set")]
pub struct NoOpenAIAPIKeyError;