Skip to main content

quantum_sdk/
batch.rs

1//! Batch processing — submit multiple prompts in a single request.
2//!
3//! # Example
4//!
5//! ```no_run
6//! # async fn example() -> quantum_sdk::Result<()> {
7//! let client = quantum_sdk::Client::new("qai_key_xxx");
8//!
9//! let resp = client.batch_submit(&[quantum_sdk::BatchJob {
10//!     model: "claude-sonnet-4-6".into(),
11//!     prompt: "Summarize quantum computing".into(),
12//!     ..Default::default()
13//! }]).await?;
14//!
15//! for id in &resp.job_ids {
16//!     println!("Submitted: {id}");
17//! }
18//! # Ok(())
19//! # }
20//! ```
21
22use serde::{Deserialize, Serialize};
23
24use crate::client::Client;
25use crate::error::Result;
26
27/// A single job in a batch submission.
28#[derive(Debug, Clone, Serialize, Default)]
29pub struct BatchJob {
30    /// Model to use for this job.
31    pub model: String,
32
33    /// The prompt text.
34    pub prompt: String,
35
36    /// Optional title for this job.
37    #[serde(skip_serializing_if = "Option::is_none")]
38    pub title: Option<String>,
39
40    /// Optional system prompt.
41    #[serde(skip_serializing_if = "Option::is_none")]
42    pub system_prompt: Option<String>,
43
44    /// Optional maximum tokens to generate.
45    #[serde(skip_serializing_if = "Option::is_none")]
46    pub max_tokens: Option<i64>,
47}
48
49/// Response from batch submission.
50#[derive(Debug, Clone, Deserialize)]
51pub struct BatchSubmitResponse {
52    /// The IDs of the created jobs.
53    pub job_ids: Vec<String>,
54
55    /// Status of the batch submission.
56    #[serde(default)]
57    pub status: String,
58}
59
60/// Response from JSONL batch submission.
61#[derive(Debug, Clone, Deserialize)]
62pub struct BatchJsonlResponse {
63    /// The IDs of the created jobs.
64    pub job_ids: Vec<String>,
65}
66
67/// A single job in the batch jobs list.
68#[derive(Debug, Clone, Deserialize)]
69pub struct BatchJobInfo {
70    /// Job identifier.
71    pub job_id: String,
72
73    /// Current status (e.g. "pending", "running", "completed", "failed").
74    pub status: String,
75
76    /// Model used for this job.
77    #[serde(default)]
78    pub model: Option<String>,
79
80    /// Job title.
81    #[serde(default)]
82    pub title: Option<String>,
83
84    /// When the job was created.
85    #[serde(default)]
86    pub created_at: Option<String>,
87
88    /// When the job completed.
89    #[serde(default)]
90    pub completed_at: Option<String>,
91
92    /// Result data (present when completed).
93    #[serde(default)]
94    pub result: Option<serde_json::Value>,
95
96    /// Error message (present when failed).
97    #[serde(default)]
98    pub error: Option<String>,
99
100    /// Cost in ticks.
101    #[serde(default)]
102    pub cost_ticks: i64,
103}
104
105/// Response from listing batch jobs.
106#[derive(Debug, Clone, Deserialize)]
107pub struct BatchJobsResponse {
108    /// The list of batch jobs.
109    #[serde(default)]
110    pub jobs: Vec<BatchJobInfo>,
111}
112
113/// Alias for [`BatchJob`] — a single input in a batch submission.
114pub type BatchJobInput = BatchJob;
115
116/// Request body for batch submission (wraps a list of jobs).
117#[derive(Debug, Clone, Serialize, Default)]
118pub struct BatchSubmitRequest {
119    /// Jobs to submit.
120    pub jobs: Vec<BatchJob>,
121}
122
123impl Client {
124    /// Submit a batch of jobs for processing.
125    ///
126    /// Each job runs independently and can be polled via the Jobs API.
127    pub async fn batch_submit(&self, jobs: &[BatchJob]) -> Result<BatchSubmitResponse> {
128        let body = serde_json::json!({ "jobs": jobs });
129        let (resp, _meta) = self
130            .post_json::<serde_json::Value, BatchSubmitResponse>("/qai/v1/batch", &body)
131            .await?;
132        Ok(resp)
133    }
134
135    /// Submit a batch of jobs using JSONL format.
136    ///
137    /// Each line in the JSONL string is a JSON object with model, prompt, etc.
138    pub async fn batch_submit_jsonl(&self, jsonl: &str) -> Result<BatchJsonlResponse> {
139        let body = serde_json::json!({ "jsonl": jsonl });
140        let (resp, _meta) = self
141            .post_json::<serde_json::Value, BatchJsonlResponse>("/qai/v1/batch/jsonl", &body)
142            .await?;
143        Ok(resp)
144    }
145
146    /// List all batch jobs for the account.
147    pub async fn batch_jobs(&self) -> Result<BatchJobsResponse> {
148        let (resp, _meta) = self
149            .get_json::<BatchJobsResponse>("/qai/v1/batch/jobs")
150            .await?;
151        Ok(resp)
152    }
153
154    /// Get the status and result of a single batch job.
155    pub async fn batch_job(&self, id: &str) -> Result<BatchJobInfo> {
156        let path = format!("/qai/v1/batch/jobs/{id}");
157        let (resp, _meta) = self.get_json::<BatchJobInfo>(&path).await?;
158        Ok(resp)
159    }
160}