pub struct ChatCompletionChunk { /* private fields */ }Expand description
A streaming chunk from a chat completion response.
Each chunk represents a delta update from the model as it generates the response.
Implementations§
Source§impl ChatCompletionChunk
impl ChatCompletionChunk
Sourcepub fn new(response: CreateChatCompletionStreamResponse) -> Self
pub fn new(response: CreateChatCompletionStreamResponse) -> Self
Create a new chunk from a stream response.
Sourcepub fn content(&self) -> Option<&str>
pub fn content(&self) -> Option<&str>
Get the content delta from this chunk, if any.
Returns the text content that was generated in this chunk.
Examples found in repository?
examples/chat_streaming.rs (line 59)
49async fn basic_streaming(client: &Client) -> Result<()> {
50 println!("Question: Tell me a short joke");
51
52 let builder = client.chat().user("Tell me a short joke");
53
54 let mut stream = client.send_chat_stream(builder).await?;
55
56 print!("Response: ");
57 while let Some(chunk) = stream.next().await {
58 let chunk = chunk?;
59 if let Some(content) = chunk.content() {
60 print!("{}", content);
61 }
62 }
63 println!();
64
65 Ok(())
66}
67
68async fn streaming_with_parameters(client: &Client) -> Result<()> {
69 println!("Question: Write a creative tagline for a bakery");
70
71 let builder = client
72 .chat()
73 .user("Write a creative tagline for a bakery")
74 .temperature(0.9)
75 .max_tokens(50);
76
77 let mut stream = client.send_chat_stream(builder).await?;
78
79 print!("Response: ");
80 while let Some(chunk) = stream.next().await {
81 let chunk = chunk?;
82 if let Some(content) = chunk.content() {
83 print!("{}", content);
84 }
85 }
86 println!();
87
88 Ok(())
89}
90
91async fn collect_content(client: &Client) -> Result<()> {
92 println!("Question: What is the capital of France?");
93
94 let builder = client.chat().user("What is the capital of France?");
95
96 let mut stream = client.send_chat_stream(builder).await?;
97
98 // Manually collect all content
99 let mut content = String::new();
100 while let Some(chunk) = stream.next().await {
101 let chunk = chunk?;
102 if let Some(text) = chunk.content() {
103 content.push_str(text);
104 }
105 }
106 println!("Full response: {}", content);
107
108 Ok(())
109}
110
111async fn streaming_with_system(client: &Client) -> Result<()> {
112 println!("System: You are a helpful assistant that speaks like a pirate");
113 println!("Question: Tell me about the weather");
114
115 let builder = client
116 .chat()
117 .system("You are a helpful assistant that speaks like a pirate")
118 .user("Tell me about the weather")
119 .max_tokens(100);
120
121 let mut stream = client.send_chat_stream(builder).await?;
122
123 print!("Response: ");
124 while let Some(chunk) = stream.next().await {
125 let chunk = chunk?;
126 if let Some(content) = chunk.content() {
127 print!("{}", content);
128 }
129 }
130 println!();
131
132 Ok(())
133}
134
135async fn multiple_turns(client: &Client) -> Result<()> {
136 println!("Building a conversation with multiple turns...\n");
137
138 // First turn
139 println!("User: What is 2+2?");
140 let builder = client.chat().user("What is 2+2?");
141
142 let mut stream = client.send_chat_stream(builder).await?;
143
144 print!("Assistant: ");
145 let mut first_response = String::new();
146 while let Some(chunk) = stream.next().await {
147 let chunk = chunk?;
148 if let Some(content) = chunk.content() {
149 print!("{}", content);
150 first_response.push_str(content);
151 }
152 }
153 println!();
154
155 // Second turn - continuing the conversation
156 println!("\nUser: Now multiply that by 3");
157 let builder = client
158 .chat()
159 .user("What is 2+2?")
160 .assistant(&first_response)
161 .user("Now multiply that by 3");
162
163 let mut stream = client.send_chat_stream(builder).await?;
164
165 print!("Assistant: ");
166 while let Some(chunk) = stream.next().await {
167 let chunk = chunk?;
168 if let Some(content) = chunk.content() {
169 print!("{}", content);
170 }
171 }
172 println!();
173
174 Ok(())
175}More examples
examples/langfuse_streaming.rs (line 105)
94async fn basic_streaming(client: &Client<LangfuseState<Span>>) -> Result<()> {
95 println!("Question: Tell me a short joke");
96
97 let builder = client.chat().user("Tell me a short joke");
98
99 let mut stream = client.send_chat_stream(builder).await?;
100
101 print!("Response: ");
102 let mut chunk_count = 0;
103 while let Some(chunk) = stream.next().await {
104 let chunk = chunk?;
105 if let Some(content) = chunk.content() {
106 print!("{}", content);
107 chunk_count += 1;
108 }
109 }
110 println!(
111 "\n(Received {} chunks, all traced to Langfuse)",
112 chunk_count
113 );
114
115 Ok(())
116}
117
118async fn streaming_with_parameters(client: &Client<LangfuseState<Span>>) -> Result<()> {
119 println!("Question: Write a creative tagline for a bakery");
120
121 let builder = client
122 .chat()
123 .user("Write a creative tagline for a bakery")
124 .temperature(0.9)
125 .max_tokens(50);
126
127 let mut stream = client.send_chat_stream(builder).await?;
128
129 print!("Response: ");
130 let mut chunk_count = 0;
131 while let Some(chunk) = stream.next().await {
132 let chunk = chunk?;
133 if let Some(content) = chunk.content() {
134 print!("{}", content);
135 chunk_count += 1;
136 }
137 }
138 println!(
139 "\n(Received {} chunks, all traced to Langfuse)",
140 chunk_count
141 );
142
143 Ok(())
144}
145
146async fn collect_content(client: &Client<LangfuseState<Span>>) -> Result<()> {
147 println!("Question: What is the capital of France?");
148
149 let builder = client.chat().user("What is the capital of France?");
150
151 let mut stream = client.send_chat_stream(builder).await?;
152
153 // Manually collect content (interceptor hooks are still called for each chunk)
154 let mut content = String::new();
155 while let Some(chunk) = stream.next().await {
156 let chunk = chunk?;
157 if let Some(text) = chunk.content() {
158 content.push_str(text);
159 }
160 }
161 println!("Full response: {}", content);
162 println!("(All chunks were traced to Langfuse during collection)");
163
164 Ok(())
165}examples/quickstart.rs (line 146)
38async fn main() -> Result<()> {
39 // Initialize logging to see what's happening under the hood
40 tracing_subscriber::fmt().with_env_filter("info").init();
41
42 println!(" OpenAI Ergonomic Quickstart");
43 println!("==============================\n");
44
45 // ==========================================
46 // 1. ENVIRONMENT SETUP & CLIENT CREATION
47 // ==========================================
48
49 println!(" Step 1: Setting up the client");
50
51 // The simplest way to get started - reads OPENAI_API_KEY from environment
52 let client = match Client::from_env() {
53 Ok(client_builder) => {
54 println!(" Client created successfully!");
55 client_builder.build()
56 }
57 Err(e) => {
58 eprintln!(" Failed to create client: {e}");
59 eprintln!(" Make sure you've set OPENAI_API_KEY environment variable");
60 eprintln!(" Example: export OPENAI_API_KEY=\"sk-your-key-here\"");
61 return Err(e);
62 }
63 };
64
65 // ==========================================
66 // 2. BASIC CHAT COMPLETION
67 // ==========================================
68
69 println!("\n Step 2: Basic chat completion");
70
71 // The simplest way to get a response from ChatGPT
72 let builder = client.chat_simple("What is Rust programming language in one sentence?");
73 let response = client.send_chat(builder).await;
74
75 match response {
76 Ok(chat_response) => {
77 println!(" Got response!");
78 if let Some(content) = chat_response.content() {
79 println!(" AI: {content}");
80 }
81
82 // Show usage information for cost tracking
83 if let Some(usage) = &chat_response.inner().usage {
84 println!(
85 " Usage: {} prompt + {} completion = {} total tokens",
86 usage.prompt_tokens, usage.completion_tokens, usage.total_tokens
87 );
88 }
89 }
90 Err(e) => {
91 println!(" Chat completion failed: {e}");
92 // Continue with other examples even if this one fails
93 }
94 }
95
96 // ==========================================
97 // 3. CHAT WITH SYSTEM MESSAGE
98 // ==========================================
99
100 println!("\n Step 3: Chat with system context");
101
102 // System messages help set the AI's behavior and context
103 let builder = client.chat_with_system(
104 "You are a helpful coding mentor who explains things simply",
105 "Explain what a HashMap is in Rust",
106 );
107 let response = client.send_chat(builder).await;
108
109 match response {
110 Ok(chat_response) => {
111 println!(" Got contextual response!");
112 if let Some(content) = chat_response.content() {
113 println!(" Mentor: {content}");
114 }
115 }
116 Err(e) => {
117 println!(" Contextual chat failed: {e}");
118 }
119 }
120
121 // ==========================================
122 // 4. STREAMING RESPONSES
123 // ==========================================
124
125 println!("\n Step 4: Streaming response (real-time)");
126
127 // Streaming lets you see the response as it's being generated
128 // This is great for chatbots and interactive applications
129 print!(" AI is typing: ");
130 io::stdout().flush().unwrap();
131
132 let builder = client
133 .responses()
134 .user("Write a short haiku about programming")
135 .temperature(0.7);
136
137 // Use send_responses_stream for real streaming
138 let stream_result = client.send_responses_stream(builder).await;
139
140 match stream_result {
141 Ok(mut stream) => {
142 // Process each chunk as it arrives
143 while let Some(chunk_result) = stream.next().await {
144 match chunk_result {
145 Ok(chunk) => {
146 if let Some(content) = chunk.content() {
147 print!("{content}");
148 io::stdout().flush().unwrap();
149 }
150 }
151 Err(e) => {
152 println!("\n Error processing chunk: {e}");
153 break;
154 }
155 }
156 }
157 println!(); // New line after streaming
158 }
159 Err(e) => {
160 println!("\n Failed to get streaming response: {e}");
161 }
162 }
163
164 // ==========================================
165 // 5. FUNCTION/TOOL CALLING
166 // ==========================================
167
168 println!("\n Step 5: Using tools/functions");
169
170 // Tools let the AI call external functions to get real data
171 // Here we define a weather function as an example
172 let weather_tool = tool_function(
173 "get_current_weather",
174 "Get the current weather for a given location",
175 json!({
176 "type": "object",
177 "properties": {
178 "location": {
179 "type": "string",
180 "description": "The city name, e.g. 'San Francisco, CA'"
181 },
182 "unit": {
183 "type": "string",
184 "enum": ["celsius", "fahrenheit"],
185 "description": "Temperature unit"
186 }
187 },
188 "required": ["location"]
189 }),
190 );
191
192 let builder = client
193 .responses()
194 .user("What's the weather like in Tokyo?")
195 .tool(weather_tool);
196 let response = client.send_responses(builder).await;
197
198 match response {
199 Ok(chat_response) => {
200 println!(" Got response with potential tool calls!");
201
202 // Check if the AI wants to call our weather function
203 let tool_calls = chat_response.tool_calls();
204 if !tool_calls.is_empty() {
205 println!(" AI requested tool calls:");
206 for tool_call in tool_calls {
207 let function_name = tool_call.function_name();
208 println!(" Function: {function_name}");
209 let function_args = tool_call.function_arguments();
210 println!(" Arguments: {function_args}");
211
212 // In a real app, you'd execute the function here
213 // and send the result back to the AI
214 println!(" In a real app, you'd call your weather API here");
215 }
216 } else if let Some(content) = chat_response.content() {
217 println!(" AI: {content}");
218 }
219 }
220 Err(e) => {
221 println!(" Tool calling example failed: {e}");
222 }
223 }
224
225 // ==========================================
226 // 6. ERROR HANDLING PATTERNS
227 // ==========================================
228
229 println!("\n Step 6: Error handling patterns");
230
231 // Show how to handle different types of errors gracefully
232 let builder = client.chat_simple(""); // Empty message might cause an error
233 let bad_response = client.send_chat(builder).await;
234
235 match bad_response {
236 Ok(response) => {
237 println!(" Unexpectedly succeeded with empty message");
238 if let Some(content) = response.content() {
239 println!(" AI: {content}");
240 }
241 }
242 Err(Error::Api {
243 status, message, ..
244 }) => {
245 println!(" API Error (HTTP {status}):");
246 println!(" Message: {message}");
247 println!(" This is normal - we sent an invalid request");
248 }
249 Err(Error::RateLimit { .. }) => {
250 println!(" Rate limited - you're sending requests too fast");
251 println!(" In a real app, you'd implement exponential backoff");
252 }
253 Err(Error::Http(_)) => {
254 println!(" HTTP/Network error");
255 println!(" Check your internet connection and API key");
256 }
257 Err(e) => {
258 println!(" Other error: {e}");
259 }
260 }
261
262 // ==========================================
263 // 7. COMPLETE REAL-WORLD EXAMPLE
264 // ==========================================
265
266 println!("\n Step 7: Complete real-world example");
267 println!("Building a simple AI assistant that can:");
268 println!("- Answer questions with context");
269 println!("- Track conversation costs");
270 println!("- Handle errors gracefully");
271
272 let mut total_tokens = 0;
273
274 // Simulate a conversation with context and cost tracking
275 let questions = [
276 "What is the capital of France?",
277 "What's special about that city?",
278 "How many people live there?",
279 ];
280
281 for (i, question) in questions.iter().enumerate() {
282 println!("\n User: {question}");
283
284 let builder = client
285 .responses()
286 .system(
287 "You are a knowledgeable geography expert. Keep answers concise but informative.",
288 )
289 .user(*question)
290 .temperature(0.1); // Lower temperature for more factual responses
291 let response = client.send_responses(builder).await;
292
293 match response {
294 Ok(chat_response) => {
295 if let Some(content) = chat_response.content() {
296 println!(" Assistant: {content}");
297 }
298
299 // Track token usage for cost monitoring
300 if let Some(usage) = chat_response.usage() {
301 total_tokens += usage.total_tokens;
302 println!(
303 " This exchange: {} tokens (Running total: {})",
304 usage.total_tokens, total_tokens
305 );
306 }
307 }
308 Err(e) => {
309 println!(" Question {} failed: {}", i + 1, e);
310 // In a real app, you might retry or log this error
311 }
312 }
313 }
314
315 // ==========================================
316 // 8. WRAP UP & NEXT STEPS
317 // ==========================================
318
319 println!("\n Quickstart Complete!");
320 println!("======================");
321 println!("You've successfully:");
322 println!(" Created an OpenAI client");
323 println!(" Made basic chat completions");
324 println!(" Used streaming responses");
325 println!(" Implemented tool/function calling");
326 println!(" Handled errors gracefully");
327 println!(" Built a complete conversational AI");
328 println!("\n Total tokens used in examples: {total_tokens}");
329 println!(
330 " Estimated cost: ~${:.4} (assuming GPT-4 pricing)",
331 f64::from(total_tokens) * 0.03 / 1000.0
332 );
333
334 println!("\n Next Steps:");
335 println!("- Check out other examples in the examples/ directory");
336 println!("- Read the documentation: https://docs.rs/openai-ergonomic");
337 println!("- Explore advanced features like vision, audio, and assistants");
338 println!("- Build your own AI-powered applications!");
339
340 Ok(())
341}Sourcepub fn role(&self) -> Option<&str>
pub fn role(&self) -> Option<&str>
Get the role from this chunk, if any.
This is typically only present in the first chunk.
Sourcepub fn tool_calls(&self) -> Option<&Vec<ChatCompletionMessageToolCallChunk>>
pub fn tool_calls(&self) -> Option<&Vec<ChatCompletionMessageToolCallChunk>>
Get tool calls from this chunk, if any.
Sourcepub fn finish_reason(&self) -> Option<&str>
pub fn finish_reason(&self) -> Option<&str>
Get the finish reason, if any.
This indicates why the generation stopped and is only present in the last chunk.
Sourcepub fn raw_response(&self) -> &CreateChatCompletionStreamResponse
pub fn raw_response(&self) -> &CreateChatCompletionStreamResponse
Get the underlying raw response.
Sourcepub fn delta(&self) -> Option<&ChatCompletionStreamResponseDelta>
pub fn delta(&self) -> Option<&ChatCompletionStreamResponseDelta>
Get the delta object directly.
Trait Implementations§
Source§impl Clone for ChatCompletionChunk
impl Clone for ChatCompletionChunk
Source§fn clone(&self) -> ChatCompletionChunk
fn clone(&self) -> ChatCompletionChunk
Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
Performs copy-assignment from
source. Read moreAuto Trait Implementations§
impl Freeze for ChatCompletionChunk
impl RefUnwindSafe for ChatCompletionChunk
impl Send for ChatCompletionChunk
impl Sync for ChatCompletionChunk
impl Unpin for ChatCompletionChunk
impl UnsafeUnpin for ChatCompletionChunk
impl UnwindSafe for ChatCompletionChunk
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more