openai_ergonomic/responses/
chat.rs1use openai_client_base::models::{
4 ChatCompletionMessageToolCallsInner, ChatCompletionResponseMessage,
5 CreateChatCompletionResponse, CreateChatCompletionResponseChoicesInner,
6};
7
8pub trait ChatCompletionResponseExt {
10 fn content(&self) -> Option<&str>;
12
13 fn tool_calls(&self) -> Vec<&ChatCompletionMessageToolCallsInner>;
15
16 fn has_tool_calls(&self) -> bool;
18
19 fn first_choice(&self) -> Option<&CreateChatCompletionResponseChoicesInner>;
21
22 fn first_message(&self) -> Option<&ChatCompletionResponseMessage>;
24
25 fn is_refusal(&self) -> bool;
27
28 fn refusal(&self) -> Option<&str>;
30
31 fn finish_reason(&self) -> Option<String>;
33}
34
35impl ChatCompletionResponseExt for CreateChatCompletionResponse {
36 fn content(&self) -> Option<&str> {
37 self.choices
38 .first()
39 .and_then(|choice| choice.message.content.as_deref())
40 }
41
42 fn tool_calls(&self) -> Vec<&ChatCompletionMessageToolCallsInner> {
43 self.choices
44 .first()
45 .and_then(|choice| choice.message.tool_calls.as_ref())
46 .map(|calls| calls.iter().collect())
47 .unwrap_or_default()
48 }
49
50 fn has_tool_calls(&self) -> bool {
51 !self.tool_calls().is_empty()
52 }
53
54 fn first_choice(&self) -> Option<&CreateChatCompletionResponseChoicesInner> {
55 self.choices.first()
56 }
57
58 fn first_message(&self) -> Option<&ChatCompletionResponseMessage> {
59 self.first_choice().map(|choice| choice.message.as_ref())
60 }
61
62 fn is_refusal(&self) -> bool {
63 self.first_message()
64 .and_then(|msg| msg.refusal.as_ref())
65 .is_some()
66 }
67
68 fn refusal(&self) -> Option<&str> {
69 self.first_message()
70 .and_then(|msg| msg.refusal.as_ref())
71 .map(std::string::String::as_str)
72 }
73
74 fn finish_reason(&self) -> Option<String> {
75 use openai_client_base::models::create_chat_completion_response_choices_inner::FinishReason;
76 self.first_choice()
77 .map(|choice| match &choice.finish_reason {
78 FinishReason::Stop => "stop".to_string(),
79 FinishReason::Length => "length".to_string(),
80 FinishReason::ToolCalls => "tool_calls".to_string(),
81 FinishReason::ContentFilter => "content_filter".to_string(),
82 FinishReason::FunctionCall => "function_call".to_string(),
83 })
84 }
85}
86
87pub trait ToolCallExt {
89 fn id(&self) -> &str;
91
92 fn function_name(&self) -> &str;
94
95 fn function_arguments(&self) -> &str;
97
98 fn parse_arguments<T: serde::de::DeserializeOwned>(&self) -> Result<T, serde_json::Error>;
100}
101
102impl ToolCallExt for ChatCompletionMessageToolCallsInner {
103 fn id(&self) -> &str {
104 match self {
105 ChatCompletionMessageToolCallsInner::ChatCompletionMessageToolCall(tool_call) => {
106 &tool_call.id
107 }
108 ChatCompletionMessageToolCallsInner::ChatCompletionMessageCustomToolCall(tool_call) => {
109 &tool_call.id
110 }
111 }
112 }
113
114 fn function_name(&self) -> &str {
115 match self {
116 ChatCompletionMessageToolCallsInner::ChatCompletionMessageToolCall(tool_call) => {
117 &tool_call.function.name
118 }
119 ChatCompletionMessageToolCallsInner::ChatCompletionMessageCustomToolCall(_) => {
120 ""
122 }
123 }
124 }
125
126 fn function_arguments(&self) -> &str {
127 match self {
128 ChatCompletionMessageToolCallsInner::ChatCompletionMessageToolCall(tool_call) => {
129 &tool_call.function.arguments
130 }
131 ChatCompletionMessageToolCallsInner::ChatCompletionMessageCustomToolCall(_) => {
132 ""
134 }
135 }
136 }
137
138 fn parse_arguments<T: serde::de::DeserializeOwned>(&self) -> Result<T, serde_json::Error> {
139 serde_json::from_str(self.function_arguments())
140 }
141}
142
143pub use openai_client_base::models::{
145 ChatCompletionResponseMessage as ChatMessage,
146 CreateChatCompletionResponse as ChatCompletionResponse,
147 CreateChatCompletionResponseChoicesInner as ChatChoice,
148};
149
150pub use openai_client_base::models::{
152 ChatCompletionMessageToolCallFunction as FunctionCall,
153 ChatCompletionResponseMessageFunctionCall,
154};
155
156pub use openai_client_base::models::ChatCompletionMessageToolCallsInner as ToolCall;