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 function_name(&self) -> &str;
91
92 fn function_arguments(&self) -> &str;
94
95 fn parse_arguments<T: serde::de::DeserializeOwned>(&self) -> Result<T, serde_json::Error>;
97}
98
99impl ToolCallExt for ChatCompletionMessageToolCallsInner {
100 fn function_name(&self) -> &str {
101 match self {
102 ChatCompletionMessageToolCallsInner::ChatCompletionMessageToolCall(tool_call) => {
103 &tool_call.function.name
104 }
105 ChatCompletionMessageToolCallsInner::ChatCompletionMessageCustomToolCall(_) => {
106 ""
108 }
109 }
110 }
111
112 fn function_arguments(&self) -> &str {
113 match self {
114 ChatCompletionMessageToolCallsInner::ChatCompletionMessageToolCall(tool_call) => {
115 &tool_call.function.arguments
116 }
117 ChatCompletionMessageToolCallsInner::ChatCompletionMessageCustomToolCall(_) => {
118 ""
120 }
121 }
122 }
123
124 fn parse_arguments<T: serde::de::DeserializeOwned>(&self) -> Result<T, serde_json::Error> {
125 serde_json::from_str(self.function_arguments())
126 }
127}
128
129pub use openai_client_base::models::{
131 ChatCompletionResponseMessage as ChatMessage,
132 CreateChatCompletionResponse as ChatCompletionResponse,
133 CreateChatCompletionResponseChoicesInner as ChatChoice,
134};
135
136pub use openai_client_base::models::{
138 ChatCompletionMessageToolCallFunction as FunctionCall,
139 ChatCompletionResponseMessageFunctionCall,
140};
141
142pub use openai_client_base::models::ChatCompletionMessageToolCallsInner as ToolCall;