use crate::providers::openai;
use serde_json::{Value, json};
#[derive(Debug, thiserror::Error)]
pub enum ProviderError {
#[error("Missing connection parameters")]
MissingConnection,
#[error("Missing API key in connection parameters")]
MissingApiKey,
#[error("Unsupported LLM provider: {0}")]
UnsupportedProvider(String),
}
pub fn create_openai_model(
parameters: &Value,
model: Option<&str>,
) -> Result<openai::OpenAICompletionModel, ProviderError> {
create_openai_model_with_connection(parameters, model, None)
}
pub fn create_openai_model_with_connection(
parameters: &Value,
model: Option<&str>,
connection_id: Option<&str>,
) -> Result<openai::OpenAICompletionModel, ProviderError> {
let client = if let Some(conn_id) = connection_id
&& !conn_id.is_empty()
{
openai::Client::from_connection_id(conn_id)
} else {
let api_key = parameters
.get("api_key")
.and_then(|v| v.as_str())
.ok_or(ProviderError::MissingApiKey)?;
let base_url = parameters.get("base_url").and_then(|v| v.as_str());
if let Some(base_url) = base_url {
openai::Client::from_url(api_key, base_url)
} else {
openai::Client::new(api_key)
}
};
let model_id = model.unwrap_or("gpt-4o");
Ok(client.completion_model(model_id))
}
pub fn structured_output_params(integration_id: &str, json_schema: Value) -> Option<Value> {
match integration_id {
"openai_api_key" => Some(json!({
"response_format": {
"type": "json_schema",
"json_schema": {
"name": "structured_response",
"strict": true,
"schema": json_schema
}
}
})),
"anthropic_api_key" => Some(json!({
"response_format": {
"type": "json",
"schema": json_schema
}
})),
_ => None,
}
}
pub fn create_completion_model(
integration_id: &str,
parameters: &Value,
model: Option<&str>,
) -> Result<Box<dyn crate::CompletionModel>, ProviderError> {
create_completion_model_with_connection(integration_id, parameters, model, None)
}
pub fn create_completion_model_with_connection(
integration_id: &str,
parameters: &Value,
model: Option<&str>,
connection_id: Option<&str>,
) -> Result<Box<dyn crate::CompletionModel>, ProviderError> {
if connection_id.is_some_and(|id| !id.is_empty()) {
let m = create_openai_model_with_connection(parameters, model, connection_id)?;
return Ok(Box::new(m));
}
match integration_id {
"openai_api_key" => {
let m = create_openai_model_with_connection(parameters, model, connection_id)?;
Ok(Box::new(m))
}
other => Err(ProviderError::UnsupportedProvider(other.to_string())),
}
}