openai_sdk_rs/types/
chat.rs

1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, Serialize, Deserialize, Default)]
4pub struct ChatCompletionRequest {
5    pub model: String,
6    pub messages: Vec<ChatMessage>,
7    #[serde(skip_serializing_if = "Option::is_none")] pub temperature: Option<f32>,
8    #[serde(skip_serializing_if = "Option::is_none")] pub top_p: Option<f32>,
9    #[serde(skip_serializing_if = "Option::is_none")] pub max_tokens: Option<u32>,
10    #[serde(skip_serializing_if = "Option::is_none")] pub presence_penalty: Option<f32>,
11    #[serde(skip_serializing_if = "Option::is_none")] pub frequency_penalty: Option<f32>,
12    #[serde(skip_serializing_if = "Option::is_none")] pub n: Option<u32>,
13    #[serde(skip_serializing_if = "Option::is_none")] pub stop: Option<Stop>,
14    #[serde(skip_serializing_if = "Option::is_none")] pub user: Option<String>,
15    #[serde(skip_serializing_if = "Option::is_none")] pub response_format: Option<ResponseFormat>,
16    #[serde(skip_serializing_if = "Option::is_none")] pub stream: Option<bool>,
17}
18
19#[derive(Debug, Clone, Serialize, Deserialize)]
20#[serde(untagged)]
21pub enum Stop {
22    Single(String),
23    Many(Vec<String>),
24}
25
26#[derive(Debug, Clone, Serialize, Deserialize)]
27#[serde(rename_all = "snake_case")]
28pub enum ResponseFormat {
29    Text,
30    JsonObject,
31}
32
33#[derive(Debug, Clone, Serialize, Deserialize)]
34pub struct ChatMessage {
35    pub role: Role,
36    pub content: String,
37    #[serde(skip_serializing_if = "Option::is_none")] pub name: Option<String>,
38}
39
40impl ChatMessage {
41    pub fn system<T: Into<String>>(content: T) -> Self { Self { role: Role::System, content: content.into(), name: None } }
42    pub fn user<T: Into<String>>(content: T) -> Self { Self { role: Role::User, content: content.into(), name: None } }
43    pub fn assistant<T: Into<String>>(content: T) -> Self { Self { role: Role::Assistant, content: content.into(), name: None } }
44}
45
46#[derive(Debug, Clone, Serialize, Deserialize)]
47#[serde(rename_all = "lowercase")]
48pub enum Role {
49    System,
50    User,
51    Assistant,
52}
53
54#[derive(Debug, Clone, Serialize, Deserialize)]
55pub struct ChatCompletionResponse {
56    pub id: String,
57    pub object: String,
58    pub created: u64,
59    pub model: String,
60    pub choices: Vec<ChatChoice>,
61}
62
63impl ChatCompletionResponse {
64    pub fn first_choice_text(&self) -> Option<&str> {
65        self.choices.get(0).map(|c| c.message.content.as_str())
66    }
67}
68
69#[derive(Debug, Clone, Serialize, Deserialize)]
70pub struct ChatChoice {
71    pub index: u32,
72    pub message: ChatMessage,
73    #[serde(skip_serializing_if = "Option::is_none")] pub finish_reason: Option<String>,
74}
75
76// Streaming chunk types for chat.completions
77#[derive(Debug, Clone, Serialize, Deserialize)]
78pub struct ChatCompletionChunk {
79    pub id: String,
80    pub object: String,
81    pub created: u64,
82    pub model: String,
83    pub choices: Vec<ChatChunkChoice>,
84}
85
86#[derive(Debug, Clone, Serialize, Deserialize)]
87pub struct ChatChunkChoice {
88    pub index: u32,
89    pub delta: ChatDelta,
90    #[serde(skip_serializing_if = "Option::is_none")] pub finish_reason: Option<String>,
91}
92
93#[derive(Debug, Clone, Serialize, Deserialize, Default)]
94pub struct ChatDelta {
95    #[serde(skip_serializing_if = "Option::is_none")] pub role: Option<Role>,
96    #[serde(skip_serializing_if = "Option::is_none")] pub content: Option<String>,
97}