Skip to main content

zai_rs/model/audio_to_text/
response.rs

1use serde::{Deserialize, Serialize};
2
3/// Complete non-streaming ASR transcription response.
4#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
5pub struct AudioToTextResponse {
6    /// Task ID.
7    pub id: String,
8
9    /// Request created time, Unix timestamp (seconds)
10    #[serde(skip_serializing_if = "Option::is_none")]
11    pub created: Option<i64>,
12
13    /// Client-provided request id
14    #[serde(skip_serializing_if = "Option::is_none")]
15    pub request_id: Option<String>,
16
17    /// Model name.
18    pub model: String,
19
20    /// Full transcription text.
21    pub text: String,
22}
23
24/// One typed event from a streaming ASR transcription.
25#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
26pub struct SpeechToTextEvent {
27    /// Task ID, when supplied by this event.
28    #[serde(skip_serializing_if = "Option::is_none")]
29    pub id: Option<String>,
30    /// Request creation time as Unix seconds.
31    #[serde(skip_serializing_if = "Option::is_none")]
32    pub created: Option<i64>,
33    /// Model name, when supplied by this event.
34    #[serde(skip_serializing_if = "Option::is_none")]
35    pub model: Option<String>,
36    /// Upstream event type, such as `transcript.text.delta` or
37    /// `transcript.text.done`. Kept open for forward compatibility.
38    #[serde(rename = "type", skip_serializing_if = "Option::is_none")]
39    pub event_type: Option<String>,
40    /// Incremental transcription text.
41    #[serde(skip_serializing_if = "Option::is_none")]
42    pub delta: Option<String>,
43}
44
45#[cfg(test)]
46mod tests {
47    use super::*;
48
49    #[test]
50    fn nonstream_response_requires_id_model_and_text() {
51        for missing in ["id", "model", "text"] {
52            let mut value = serde_json::json!({
53                "id": "asr-1",
54                "model": "glm-asr-2512",
55                "text": "hello"
56            });
57            value.as_object_mut().unwrap().remove(missing);
58            assert!(serde_json::from_value::<AudioToTextResponse>(value).is_err());
59        }
60    }
61
62    #[test]
63    fn stream_event_preserves_open_event_type() {
64        let event: SpeechToTextEvent = serde_json::from_value(serde_json::json!({
65            "id": "asr-1",
66            "type": "transcript.text.future",
67            "delta": "hi"
68        }))
69        .unwrap();
70        assert_eq!(event.event_type.as_deref(), Some("transcript.text.future"));
71        assert_eq!(event.delta.as_deref(), Some("hi"));
72    }
73}