kind_openai/endpoints/
chat_reasoning.rs1use std::{borrow::Cow, collections::HashMap};
2
3use bon::{builder, Builder};
4use reqwest::Method;
5use serde::{Deserialize, Serialize};
6
7use super::OpenAIRequestProvider;
8
9#[derive(Serialize, Clone, Copy, Debug)]
11#[allow(non_camel_case_types)]
12pub enum ReasoningModel {
13 #[serde(rename = "o1-preview")]
14 O1Preview,
15 #[serde(rename = "o1-mini")]
16 O1Mini,
17 #[serde(rename = "o1-mini-2024-09-12")]
18 O1Mini_2024_09_12,
19 #[serde(rename = "o1")]
20 O1,
21 #[serde(rename = "o1-2024-12-17")]
22 O1_2024_12_17,
23 #[serde(rename = "o3-mini")]
24 O3Mini,
25 #[serde(rename = "o3-mini-2025-01-31")]
26 O3Mini_2025_01_31,
27}
28
29#[derive(Serialize, Debug, Deserialize, Clone, Copy)]
31#[serde(rename_all = "snake_case")]
32pub enum Role {
33 User,
35 Assistant,
37 Developer,
39}
40
41#[derive(Serialize, Debug, Clone, Copy)]
44#[serde(rename_all = "snake_case")]
45pub enum ReasoningEffort {
46 Low,
47 Medium,
48 High,
49}
50
51#[derive(Serialize, Debug, Clone, Builder)]
53#[builder(start_fn = model, state_mod(vis = "pub"))]
54pub struct ChatReasoningCompletion<'a> {
55 #[builder(start_fn)]
56 model: ReasoningModel,
57 messages: Vec<ReasoningMessage<'a>>,
58 store: Option<bool>,
59 metadata: Option<HashMap<String, String>>,
60 reasoning_effort: Option<ReasoningEffort>,
61}
62
63impl OpenAIRequestProvider for ChatReasoningCompletion<'_> {
64 type Response = ChatReasoningCompletionResponse;
65
66 const METHOD: Method = Method::POST;
67
68 fn path_with_leading_slash() -> String {
69 "/chat/completions".to_string()
70 }
71}
72
73impl super::private::Sealed for ChatReasoningCompletion<'_> {}
74
75#[derive(Serialize, Debug, Clone, Builder)]
77#[builder(start_fn = role)]
78pub struct ReasoningMessage<'a> {
79 #[builder(start_fn)]
80 role: Role,
81 content: Cow<'a, str>,
82}
83
84#[macro_export]
85macro_rules! reasoning_developer_message {
86 ($($arg:tt)*) => {
87 ::kind_openai::endpoints::chat_reasoning::ReasoningMessage::role(
88 ::kind_openai::endpoints::chat_reasoning::Role::Developer
89 )
90 .content(format!($($arg)*).into())
91 .build();
92 };
93}
94
95#[macro_export]
96macro_rules! reasoning_user_message {
97 ($($arg:tt)*) => {
98 ::kind_openai::endpoints::chat_reasoning::ReasoningMessage::role(
99 ::kind_openai::endpoints::chat_reasoning::Role::User
100 )
101 .content(format!($($arg)*).into())
102 .build();
103 };
104}
105
106#[macro_export]
107macro_rules! reasoning_assistant_message {
108 ($($arg:tt)*) => {
109 ::kind_openai::endpoints::chat_reasoning::ReasoningMessage::role(
110 ::kind_openai::endpoints::chat_reasoning::Role::Assistant
111 )
112 .content(format!($($arg)*).into())
113 .build();
114 };
115}
116
117#[derive(Deserialize)]
118pub struct ChatReasoningCompletionResponse {
119 choices: Vec<ChatReasoningCompletionResponseChoice>,
120}
121
122impl ChatReasoningCompletionResponse {
123 pub fn take_first_choice(self) -> Option<ChatReasoningCompletionResponseChoice> {
124 self.choices.into_iter().next()
125 }
126}
127
128#[derive(Deserialize)]
129pub struct ChatReasoningCompletionResponseChoice {
130 message: ChatReasoningCompletionResponseMessage,
131}
132
133impl ChatReasoningCompletionResponseChoice {
134 pub fn message(self) -> String {
135 self.message.content
136 }
137}
138
139#[derive(Deserialize)]
140pub struct ChatReasoningCompletionResponseMessage {
141 content: String,
142}