use serde::{Deserialize, Serialize};
pub use crate::shared::MaxResponseTokens;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "structured", derive(schemars::JsonSchema))]
#[serde(rename_all = "snake_case")]
#[non_exhaustive]
pub enum RealtimeAudioFormat {
Pcm16,
G711Ulaw,
G711Alaw,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "structured", derive(schemars::JsonSchema))]
#[serde(rename_all = "snake_case")]
#[non_exhaustive]
pub enum TurnDetectionType {
ServerVad,
SemanticVad,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "structured", derive(schemars::JsonSchema))]
#[serde(rename_all = "snake_case")]
#[non_exhaustive]
pub enum Eagerness {
Low,
Medium,
High,
Auto,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "structured", derive(schemars::JsonSchema))]
#[serde(rename_all = "snake_case")]
#[non_exhaustive]
pub enum NoiseReductionType {
NearField,
FarField,
}
#[derive(Debug, Clone, Serialize)]
pub struct SessionCreateRequest {
#[serde(skip_serializing_if = "Option::is_none")]
pub model: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub voice: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub instructions: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub input_audio_format: Option<RealtimeAudioFormat>,
#[serde(skip_serializing_if = "Option::is_none")]
pub output_audio_format: Option<RealtimeAudioFormat>,
#[serde(skip_serializing_if = "Option::is_none")]
pub modalities: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub temperature: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub max_response_output_tokens: Option<MaxResponseTokens>,
#[serde(skip_serializing_if = "Option::is_none")]
pub tools: Option<Vec<RealtimeTool>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub tool_choice: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub turn_detection: Option<TurnDetection>,
#[serde(skip_serializing_if = "Option::is_none")]
pub input_audio_transcription: Option<InputAudioTranscription>,
#[serde(skip_serializing_if = "Option::is_none")]
pub speed: Option<f64>,
}
impl SessionCreateRequest {
pub fn new() -> Self {
Self {
model: None,
voice: None,
instructions: None,
input_audio_format: None,
output_audio_format: None,
modalities: None,
temperature: None,
max_response_output_tokens: None,
tools: None,
tool_choice: None,
turn_detection: None,
input_audio_transcription: None,
speed: None,
}
}
pub fn model(mut self, model: impl Into<String>) -> Self {
self.model = Some(model.into());
self
}
pub fn voice(mut self, voice: impl Into<String>) -> Self {
self.voice = Some(voice.into());
self
}
pub fn instructions(mut self, instructions: impl Into<String>) -> Self {
self.instructions = Some(instructions.into());
self
}
pub fn modalities(mut self, modalities: Vec<String>) -> Self {
self.modalities = Some(modalities);
self
}
}
impl Default for SessionCreateRequest {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RealtimeTool {
#[serde(rename = "type")]
pub type_: String,
pub name: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub parameters: Option<serde_json::Value>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TurnDetection {
#[serde(rename = "type")]
pub type_: TurnDetectionType,
#[serde(skip_serializing_if = "Option::is_none")]
pub threshold: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub prefix_padding_ms: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub silence_duration_ms: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub create_response: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub interrupt_response: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub eagerness: Option<Eagerness>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct InputAudioTranscription {
#[serde(skip_serializing_if = "Option::is_none")]
pub model: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub language: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub prompt: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct InputAudioNoiseReduction {
#[serde(rename = "type")]
pub type_: NoiseReductionType,
}
#[derive(Debug, Clone, Deserialize)]
pub struct ClientSecret {
pub value: String,
pub expires_at: i64,
}
#[derive(Debug, Clone, Deserialize)]
pub struct SessionCreateResponse {
pub client_secret: ClientSecret,
#[serde(default)]
pub model: Option<String>,
#[serde(default)]
pub voice: Option<String>,
#[serde(default)]
pub instructions: Option<String>,
#[serde(default)]
pub modalities: Option<Vec<String>>,
#[serde(default)]
pub temperature: Option<f64>,
#[serde(default)]
pub max_response_output_tokens: Option<MaxResponseTokens>,
#[serde(default)]
pub input_audio_format: Option<RealtimeAudioFormat>,
#[serde(default)]
pub output_audio_format: Option<RealtimeAudioFormat>,
#[serde(default)]
pub tools: Option<Vec<RealtimeTool>>,
#[serde(default)]
pub tool_choice: Option<String>,
#[serde(default)]
pub turn_detection: Option<TurnDetection>,
#[serde(default)]
pub speed: Option<f64>,
}
#[derive(Debug, Clone, Serialize)]
pub struct ClientSecretConfig {
#[serde(skip_serializing_if = "Option::is_none")]
pub expires_at: Option<ClientSecretExpiresAt>,
}
#[derive(Debug, Clone, Serialize)]
pub struct ClientSecretExpiresAt {
pub anchor: String,
pub seconds: i64,
}
#[derive(Debug, Clone, Serialize)]
pub struct TranscriptionSessionCreateRequest {
#[serde(skip_serializing_if = "Option::is_none")]
pub client_secret: Option<ClientSecretConfig>,
#[serde(skip_serializing_if = "Option::is_none")]
pub include: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub input_audio_format: Option<RealtimeAudioFormat>,
#[serde(skip_serializing_if = "Option::is_none")]
pub input_audio_noise_reduction: Option<InputAudioNoiseReduction>,
#[serde(skip_serializing_if = "Option::is_none")]
pub input_audio_transcription: Option<InputAudioTranscription>,
#[serde(skip_serializing_if = "Option::is_none")]
pub modalities: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub turn_detection: Option<TurnDetection>,
}
impl TranscriptionSessionCreateRequest {
pub fn new() -> Self {
Self {
client_secret: None,
include: None,
input_audio_format: None,
input_audio_noise_reduction: None,
input_audio_transcription: None,
modalities: None,
turn_detection: None,
}
}
pub fn input_audio_format(mut self, format: RealtimeAudioFormat) -> Self {
self.input_audio_format = Some(format);
self
}
pub fn transcription(mut self, model: impl Into<String>, language: impl Into<String>) -> Self {
self.input_audio_transcription = Some(InputAudioTranscription {
model: Some(model.into()),
language: Some(language.into()),
prompt: None,
});
self
}
pub fn turn_detection(mut self, td: TurnDetection) -> Self {
self.turn_detection = Some(td);
self
}
pub fn noise_reduction(mut self, type_: NoiseReductionType) -> Self {
self.input_audio_noise_reduction = Some(InputAudioNoiseReduction { type_ });
self
}
pub fn include(mut self, items: Vec<String>) -> Self {
self.include = Some(items);
self
}
pub fn modalities(mut self, modalities: Vec<String>) -> Self {
self.modalities = Some(modalities);
self
}
pub fn expires_in(mut self, seconds: i64) -> Self {
self.client_secret = Some(ClientSecretConfig {
expires_at: Some(ClientSecretExpiresAt {
anchor: "created_at".into(),
seconds,
}),
});
self
}
}
impl Default for TranscriptionSessionCreateRequest {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone, Deserialize)]
pub struct TranscriptionSession {
pub client_secret: ClientSecret,
#[serde(default)]
pub input_audio_format: Option<String>,
#[serde(default)]
pub input_audio_transcription: Option<InputAudioTranscription>,
#[serde(default)]
pub modalities: Option<Vec<String>>,
#[serde(default)]
pub turn_detection: Option<TurnDetection>,
}