1use crate::common::parameters::{Name, ParameterProperty, Parameters};
4use crate::common::tool::Tool;
5use serde::{Deserialize, Serialize};
6
7use super::audio::{AudioFormat, InputAudioNoiseReduction, InputAudioTranscription, Voice};
8use super::vad::TurnDetection;
9
10#[derive(Debug, Clone, Serialize, Deserialize)]
28pub struct RealtimeTool {
29 #[serde(rename = "type")]
31 pub type_name: String,
32
33 pub name: String,
35
36 #[serde(skip_serializing_if = "Option::is_none")]
38 pub description: Option<String>,
39
40 #[serde(skip_serializing_if = "Option::is_none")]
42 pub parameters: Option<Parameters>,
43}
44
45impl RealtimeTool {
46 pub fn function<T, U, V>(name: T, description: U, parameters: Vec<(V, ParameterProperty)>) -> Self
48 where
49 T: Into<String>,
50 U: Into<String>,
51 V: AsRef<str>,
52 {
53 let params: Vec<(Name, ParameterProperty)> = parameters.into_iter().map(|(k, v)| (k.as_ref().to_string(), v)).collect();
54
55 Self {
56 type_name: "function".to_string(),
57 name: name.into(),
58 description: Some(description.into()),
59 parameters: Some(Parameters::new(params, None)),
60 }
61 }
62}
63
64impl From<Tool> for RealtimeTool {
65 fn from(tool: Tool) -> Self {
67 if let Some(func) = tool.function {
68 Self { type_name: "function".to_string(), name: func.name, description: func.description, parameters: func.parameters }
69 } else {
70 Self { type_name: tool.type_name, name: tool.name.unwrap_or_default(), description: None, parameters: tool.parameters }
72 }
73 }
74}
75
76#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
78#[serde(rename_all = "lowercase")]
79#[non_exhaustive]
80pub enum Modality {
81 Text,
83 Audio,
85}
86
87#[derive(Debug, Clone, Default, Serialize, Deserialize)]
89pub struct SessionConfig {
90 #[serde(skip_serializing_if = "Option::is_none")]
92 pub modalities: Option<Vec<Modality>>,
93
94 #[serde(skip_serializing_if = "Option::is_none")]
96 pub instructions: Option<String>,
97
98 #[serde(skip_serializing_if = "Option::is_none")]
100 pub voice: Option<Voice>,
101
102 #[serde(skip_serializing_if = "Option::is_none")]
104 pub input_audio_format: Option<AudioFormat>,
105
106 #[serde(skip_serializing_if = "Option::is_none")]
108 pub output_audio_format: Option<AudioFormat>,
109
110 #[serde(skip_serializing_if = "Option::is_none")]
112 pub input_audio_transcription: Option<InputAudioTranscription>,
113
114 #[serde(skip_serializing_if = "Option::is_none")]
116 pub input_audio_noise_reduction: Option<InputAudioNoiseReduction>,
117
118 #[serde(skip_serializing_if = "Option::is_none")]
120 pub turn_detection: Option<TurnDetection>,
121
122 #[serde(skip_serializing_if = "Option::is_none")]
124 pub tools: Option<Vec<RealtimeTool>>,
125
126 #[serde(skip_serializing_if = "Option::is_none")]
128 pub tool_choice: Option<ToolChoice>,
129
130 #[serde(skip_serializing_if = "Option::is_none")]
132 pub temperature: Option<f32>,
133
134 #[serde(skip_serializing_if = "Option::is_none")]
136 pub max_response_output_tokens: Option<MaxTokens>,
137}
138
139impl SessionConfig {
140 pub fn new() -> Self {
142 Self::default()
143 }
144
145 pub fn with_modalities(mut self, modalities: Vec<Modality>) -> Self {
147 self.modalities = Some(modalities);
148 self
149 }
150
151 pub fn with_instructions(mut self, instructions: impl Into<String>) -> Self {
153 self.instructions = Some(instructions.into());
154 self
155 }
156
157 pub fn with_voice(mut self, voice: Voice) -> Self {
159 self.voice = Some(voice);
160 self
161 }
162
163 pub fn with_input_audio_format(mut self, format: AudioFormat) -> Self {
165 self.input_audio_format = Some(format);
166 self
167 }
168
169 pub fn with_output_audio_format(mut self, format: AudioFormat) -> Self {
171 self.output_audio_format = Some(format);
172 self
173 }
174
175 pub fn with_transcription(mut self, config: InputAudioTranscription) -> Self {
177 self.input_audio_transcription = Some(config);
178 self
179 }
180
181 pub fn with_turn_detection(mut self, config: TurnDetection) -> Self {
183 self.turn_detection = Some(config);
184 self
185 }
186
187 pub fn with_tools(mut self, tools: Vec<Tool>) -> Self {
191 self.tools = Some(tools.into_iter().map(RealtimeTool::from).collect());
192 self
193 }
194
195 pub fn with_realtime_tools(mut self, tools: Vec<RealtimeTool>) -> Self {
197 self.tools = Some(tools);
198 self
199 }
200
201 pub fn with_tool_choice(mut self, choice: ToolChoice) -> Self {
203 self.tool_choice = Some(choice);
204 self
205 }
206
207 pub fn with_temperature(mut self, temp: f32) -> Self {
209 self.temperature = Some(temp);
210 self
211 }
212
213 pub fn with_max_tokens(mut self, max: MaxTokens) -> Self {
215 self.max_response_output_tokens = Some(max);
216 self
217 }
218}
219
220#[derive(Debug, Clone)]
222pub enum MaxTokens {
223 Count(u32),
225 Infinite,
227}
228
229impl serde::Serialize for MaxTokens {
230 fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
231 where
232 S: serde::Serializer,
233 {
234 match self {
235 MaxTokens::Count(n) => serializer.serialize_u32(*n),
236 MaxTokens::Infinite => serializer.serialize_str("inf"),
237 }
238 }
239}
240
241impl<'de> serde::Deserialize<'de> for MaxTokens {
242 fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
243 where
244 D: serde::Deserializer<'de>,
245 {
246 use serde::de::{self, Visitor};
247
248 struct MaxTokensVisitor;
249
250 impl<'de> Visitor<'de> for MaxTokensVisitor {
251 type Value = MaxTokens;
252
253 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
254 formatter.write_str("a positive integer or \"inf\"")
255 }
256
257 fn visit_u64<E>(self, value: u64) -> std::result::Result<MaxTokens, E>
258 where
259 E: de::Error,
260 {
261 Ok(MaxTokens::Count(value as u32))
262 }
263
264 fn visit_str<E>(self, value: &str) -> std::result::Result<MaxTokens, E>
265 where
266 E: de::Error,
267 {
268 if value == "inf" {
269 Ok(MaxTokens::Infinite)
270 } else {
271 Err(de::Error::custom(format!("unknown value: {}", value)))
272 }
273 }
274 }
275
276 deserializer.deserialize_any(MaxTokensVisitor)
277 }
278}
279
280impl From<u32> for MaxTokens {
281 fn from(count: u32) -> Self {
282 Self::Count(count)
283 }
284}
285
286#[derive(Debug, Clone, Serialize, Deserialize)]
288#[serde(untagged)]
289pub enum ToolChoice {
290 Simple(SimpleToolChoice),
292 Function(NamedToolChoice),
294}
295
296#[derive(Debug, Clone, Serialize, Deserialize)]
298#[serde(rename_all = "lowercase")]
299pub enum SimpleToolChoice {
300 Auto,
302 None,
304 Required,
306}
307
308impl Default for ToolChoice {
309 fn default() -> Self {
310 Self::Simple(SimpleToolChoice::Auto)
311 }
312}
313
314impl ToolChoice {
315 pub fn auto() -> Self {
317 Self::Simple(SimpleToolChoice::Auto)
318 }
319
320 pub fn none() -> Self {
322 Self::Simple(SimpleToolChoice::None)
323 }
324
325 pub fn required() -> Self {
327 Self::Simple(SimpleToolChoice::Required)
328 }
329
330 pub fn function(name: impl Into<String>) -> Self {
332 Self::Function(NamedToolChoice { type_name: "function".to_string(), function: NamedFunction { name: name.into() } })
333 }
334}
335
336#[derive(Debug, Clone, Serialize, Deserialize)]
338pub struct NamedToolChoice {
339 #[serde(rename = "type")]
340 pub type_name: String,
341 pub function: NamedFunction,
342}
343
344#[derive(Debug, Clone, Serialize, Deserialize)]
346pub struct NamedFunction {
347 pub name: String,
348}
349
350#[derive(Debug, Clone, Default, Serialize, Deserialize)]
352pub struct ResponseCreateConfig {
353 #[serde(skip_serializing_if = "Option::is_none")]
355 pub modalities: Option<Vec<Modality>>,
356
357 #[serde(skip_serializing_if = "Option::is_none")]
359 pub instructions: Option<String>,
360
361 #[serde(skip_serializing_if = "Option::is_none")]
363 pub voice: Option<Voice>,
364
365 #[serde(skip_serializing_if = "Option::is_none")]
367 pub output_audio_format: Option<AudioFormat>,
368
369 #[serde(skip_serializing_if = "Option::is_none")]
371 pub tools: Option<Vec<RealtimeTool>>,
372
373 #[serde(skip_serializing_if = "Option::is_none")]
375 pub tool_choice: Option<ToolChoice>,
376
377 #[serde(skip_serializing_if = "Option::is_none")]
379 pub temperature: Option<f32>,
380
381 #[serde(skip_serializing_if = "Option::is_none")]
383 pub max_output_tokens: Option<MaxTokens>,
384
385 #[serde(skip_serializing_if = "Option::is_none")]
388 pub conversation: Option<String>,
389
390 #[serde(skip_serializing_if = "Option::is_none")]
392 pub metadata: Option<serde_json::Value>,
393}
394
395impl ResponseCreateConfig {
396 pub fn new() -> Self {
398 Self::default()
399 }
400
401 pub fn with_modalities(mut self, modalities: Vec<Modality>) -> Self {
403 self.modalities = Some(modalities);
404 self
405 }
406
407 pub fn with_instructions(mut self, instructions: impl Into<String>) -> Self {
409 self.instructions = Some(instructions.into());
410 self
411 }
412
413 pub fn with_voice(mut self, voice: Voice) -> Self {
415 self.voice = Some(voice);
416 self
417 }
418
419 pub fn out_of_band(mut self) -> Self {
421 self.conversation = Some("none".to_string());
422 self
423 }
424}