Skip to main content

gproxy_protocol/protocol/openai/audio/
stream.rs

1use std::collections::BTreeMap;
2
3use serde::{Deserialize, Serialize, de};
4use serde_json::Value;
5
6use super::super::common::Extra;
7use super::{AudioTokenUsage, TranscriptionLanguage, TranscriptionLogprob};
8
9#[derive(Debug, Clone, PartialEq, Serialize)]
10#[serde(untagged)]
11#[non_exhaustive]
12pub enum TranscriptionStreamEvent {
13    Known(KnownTranscriptionStreamEvent),
14    Unknown(UnknownTranscriptionStreamEvent),
15}
16
17impl<'de> Deserialize<'de> for TranscriptionStreamEvent {
18    fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
19        let value = Value::deserialize(deserializer)?;
20        match value.get("type").and_then(Value::as_str) {
21            Some("transcript.text.delta" | "transcript.text.done" | "transcript.text.segment") => {
22                if let Ok(event) = serde_json::from_value(value.clone()) {
23                    return Ok(Self::Known(event));
24                }
25                serde_json::from_value(value)
26                    .map(Self::Unknown)
27                    .map_err(de::Error::custom)
28            }
29            _ => serde_json::from_value(value)
30                .map(Self::Unknown)
31                .map_err(de::Error::custom),
32        }
33    }
34}
35
36#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
37#[serde(tag = "type")]
38#[non_exhaustive]
39pub enum KnownTranscriptionStreamEvent {
40    #[serde(rename = "transcript.text.delta")]
41    TextDelta {
42        delta: String,
43        #[serde(skip_serializing_if = "Option::is_none")]
44        logprobs: Option<Vec<TranscriptionLogprob>>,
45        #[serde(skip_serializing_if = "Option::is_none")]
46        segment_id: Option<String>,
47        #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
48        extra: Extra,
49    },
50    #[serde(rename = "transcript.text.done")]
51    TextDone {
52        text: String,
53        #[serde(skip_serializing_if = "Option::is_none")]
54        languages: Option<Vec<TranscriptionLanguage>>,
55        #[serde(skip_serializing_if = "Option::is_none")]
56        logprobs: Option<Vec<TranscriptionLogprob>>,
57        #[serde(skip_serializing_if = "Option::is_none")]
58        usage: Option<AudioTokenUsage>,
59        #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
60        extra: Extra,
61    },
62    #[serde(rename = "transcript.text.segment")]
63    TextSegment {
64        id: String,
65        end: f64,
66        speaker: String,
67        start: f64,
68        text: String,
69        #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
70        extra: Extra,
71    },
72}
73
74#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder)]
75#[non_exhaustive]
76pub struct UnknownTranscriptionStreamEvent {
77    #[serde(rename = "type", skip_serializing_if = "Option::is_none")]
78    pub type_: Option<String>,
79    #[serde(default, flatten, skip_serializing_if = "BTreeMap::is_empty")]
80    pub extra: Extra,
81}