use reqwest::Method;
use serde_json::{Value, json};
use crate::client::files::TRANSFER_TIMEOUT_FLOOR;
use crate::client::{Client, meta::parse_json};
use crate::error::Result;
use crate::http::{PreparedRequest, headers};
use crate::retry::RetryPolicy;
use crate::types::{Batch, BatchList};
pub const DEFAULT_BATCH_ENDPOINT: &str = "/v1/embeddings";
pub const DEFAULT_COMPLETION_WINDOW: &str = "24h";
#[derive(Debug, Clone)]
pub struct Batches {
client: Client,
}
impl Client {
pub fn batches(&self) -> Batches {
Batches {
client: self.clone(),
}
}
}
impl Batches {
pub fn create(&self, input_file_id: impl Into<String>) -> BatchCreate {
BatchCreate {
client: self.client.clone(),
input_file_id: input_file_id.into(),
endpoint: DEFAULT_BATCH_ENDPOINT.to_string(),
completion_window: DEFAULT_COMPLETION_WINDOW.to_string(),
metadata: None,
}
}
pub async fn retrieve(&self, batch_id: &str) -> Result<Batch> {
let request = self
.client
.request(Method::GET, &format!("/v1/batches/{batch_id}"))?
.header("accept", headers::JSON_CONTENT_TYPE);
let response = self.client.send_once(request, RetryPolicy::NONE).await?;
parse_json(&response, "batch")
}
pub async fn cancel(&self, batch_id: &str) -> Result<Batch> {
let request = self
.client
.request(Method::POST, &format!("/v1/batches/{batch_id}/cancel"))?
.json_headers();
let response = self.client.send_once(request, RetryPolicy::NONE).await?;
parse_json(&response, "batch")
}
pub fn list(&self) -> BatchListRequest {
BatchListRequest {
client: self.client.clone(),
after: None,
limit: None,
}
}
}
#[derive(Debug, Clone)]
pub struct BatchCreate {
client: Client,
input_file_id: String,
endpoint: String,
completion_window: String,
metadata: Option<Value>,
}
impl BatchCreate {
pub fn endpoint(mut self, endpoint: impl Into<String>) -> Self {
self.endpoint = endpoint.into();
self
}
pub fn completion_window(mut self, window: impl Into<String>) -> Self {
self.completion_window = window.into();
self
}
pub fn metadata(mut self, metadata: Value) -> Self {
self.metadata = Some(metadata);
self
}
pub async fn send(self) -> Result<Batch> {
let mut body = json!({
"input_file_id": self.input_file_id,
"endpoint": self.endpoint,
"completion_window": self.completion_window,
});
if let Some(metadata) = self.metadata
&& let Some(object) = body.as_object_mut()
{
object.insert("metadata".to_string(), metadata);
}
let request = self
.client
.request(Method::POST, "/v1/batches")?
.json_headers()
.body(serde_json::to_vec(&body).unwrap_or_default());
let response = self
.client
.send_with_timeout(request, RetryPolicy::NONE, TRANSFER_TIMEOUT_FLOOR)
.await?;
parse_json(&response, "batch")
}
}
#[derive(Debug, Clone)]
pub struct BatchListRequest {
client: Client,
after: Option<String>,
limit: Option<u32>,
}
impl BatchListRequest {
pub fn after(mut self, after: impl Into<String>) -> Self {
self.after = Some(after.into());
self
}
pub fn limit(mut self, limit: u32) -> Self {
self.limit = Some(limit);
self
}
pub async fn page(self) -> Result<BatchList> {
let mut url = self.client.url("/v1/batches")?;
{
let mut query = url.query_pairs_mut();
if let Some(after) = &self.after {
query.append_pair("after", after);
}
if let Some(limit) = self.limit {
query.append_pair("limit", &limit.to_string());
}
}
let request =
PreparedRequest::new(Method::GET, url).header("accept", headers::JSON_CONTENT_TYPE);
let response = self.client.send_once(request, RetryPolicy::NONE).await?;
parse_json(&response, "batch list")
}
pub async fn send(self) -> Result<Vec<Batch>> {
Ok(self.page().await?.data)
}
}