threads/
threads.rs

1//! Comprehensive threads example demonstrating conversation management with OpenAI Assistants.
2//!
3//! This example showcases the OpenAI Threads API, which provides a way to manage
4//! conversations between users and assistants.
5//!
6//! ## Features Demonstrated
7//!
8//! - **Thread Creation**: Create conversation threads
9//! - **Thread Configuration**: Set up threads with metadata
10//! - **Message Management**: Add messages to threads
11//! - **Thread Persistence**: Maintain conversation state
12//! - **Error Handling**: Robust error handling
13//!
14//! ## Prerequisites
15//!
16//! Set your OpenAI API key:
17//! ```bash
18//! export OPENAI_API_KEY="your-key-here"
19//! ```
20//!
21//! ## Usage
22//!
23//! ```bash
24//! cargo run --example threads
25//! ```
26//!
27//! ## Overview
28//!
29//! Threads allow you to maintain conversation history and context across
30//! multiple messages and runs with OpenAI assistants.
31
32#![allow(clippy::uninlined_format_args)]
33#![allow(clippy::no_effect_underscore_binding)]
34#![allow(clippy::doc_markdown)]
35#![allow(clippy::cast_possible_wrap)]
36#![allow(clippy::missing_docs_in_private_items)]
37#![allow(clippy::too_many_lines)]
38#![allow(clippy::cast_possible_truncation)]
39#![allow(clippy::cast_lossless)]
40#![allow(unused_variables)]
41#![allow(missing_docs)]
42#![allow(dead_code)]
43
44use openai_ergonomic::{builders::threads::ThreadRequestBuilder, Client};
45
46/// Thread metadata for demonstration
47#[derive(Debug, Clone)]
48pub struct ThreadInfo {
49    pub id: String,
50    pub created_at: i64,
51    pub metadata: std::collections::HashMap<String, String>,
52}
53
54impl ThreadInfo {
55    pub fn new(id: impl Into<String>) -> Self {
56        Self {
57            id: id.into(),
58            created_at: std::time::SystemTime::now()
59                .duration_since(std::time::UNIX_EPOCH)
60                .unwrap()
61                .as_secs() as i64,
62            metadata: std::collections::HashMap::new(),
63        }
64    }
65
66    #[must_use]
67    pub fn with_metadata(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
68        self.metadata.insert(key.into(), value.into());
69        self
70    }
71
72    pub fn display(&self) {
73        println!("  Thread ID: {}", self.id);
74        println!("  Created At: {}", self.created_at);
75        if !self.metadata.is_empty() {
76            println!("  Metadata:");
77            for (key, value) in &self.metadata {
78                println!("    {}: {}", key, value);
79            }
80        }
81    }
82}
83
84#[tokio::main]
85async fn main() -> Result<(), Box<dyn std::error::Error>> {
86    println!(" OpenAI Ergonomic - Comprehensive Threads Example\n");
87
88    // Initialize client from environment variables
89    println!(" Initializing OpenAI client...");
90    let client = match Client::from_env() {
91        Ok(c) => {
92            println!(" Client initialized successfully\n");
93            c.build()
94        }
95        Err(e) => {
96            eprintln!(" Failed to initialize client: {}", e);
97            eprintln!(" Make sure OPENAI_API_KEY is set");
98            return Ok(());
99        }
100    };
101
102    // Example 1: Create a simple thread
103    println!();
104    println!(" Example 1: Create Simple Thread");
105    println!("\n");
106
107    println!("Creating new thread...");
108
109    let builder = ThreadRequestBuilder::new();
110
111    println!("\n Note: This would create a real thread with your API key.");
112    println!("   Commented out to avoid accidental API calls.\n");
113
114    // Uncomment to actually create thread:
115    // match client.threads().create(builder).await {
116    //     Ok(thread) => {
117    //         println!(" Thread created successfully!");
118    //         println!("  Thread ID: {}", thread.id);
119    //         println!("  Created At: {}", thread.created_at);
120    //     }
121    //     Err(e) => {
122    //         eprintln!(" Failed to create thread: {}", e);
123    //     }
124    // }
125
126    // Simulate thread creation for demonstration
127    let demo_thread = ThreadInfo::new("thread_demo123");
128    println!(" Demo Thread Created:");
129    demo_thread.display();
130
131    // Example 2: Create thread with metadata
132    println!("\n");
133    println!(" Example 2: Create Thread with Metadata");
134    println!("\n");
135
136    println!("Creating thread with metadata...");
137
138    let builder_with_metadata = ThreadRequestBuilder::new()
139        .metadata("user_id", "user_12345")
140        .metadata("session_id", "session_abc")
141        .metadata("context", "customer_support");
142
143    println!("  Metadata:");
144    println!("    user_id: user_12345");
145    println!("    session_id: session_abc");
146    println!("    context: customer_support");
147
148    // Uncomment to actually create thread:
149    // match client.threads().create(builder_with_metadata).await {
150    //     Ok(thread) => {
151    //         println!("\n Thread with metadata created!");
152    //         println!("  Thread ID: {}", thread.id);
153    //     }
154    //     Err(e) => {
155    //         eprintln!(" Failed to create thread: {}", e);
156    //     }
157    // }
158
159    let demo_thread_with_meta = ThreadInfo::new("thread_demo456")
160        .with_metadata("user_id", "user_12345")
161        .with_metadata("session_id", "session_abc")
162        .with_metadata("context", "customer_support");
163
164    println!("\n Demo Thread Created:");
165    demo_thread_with_meta.display();
166
167    // Example 3: Create thread with initial messages
168    println!("\n");
169    println!(" Example 3: Create Thread with Initial Messages");
170    println!("\n");
171
172    println!("Creating thread with initial messages...");
173
174    // Note: The ThreadRequestBuilder supports adding messages during creation
175    let builder_with_messages =
176        ThreadRequestBuilder::new().metadata("conversation_type", "onboarding");
177
178    println!("  Initial message: 'Hello, I need help getting started'");
179
180    // In a real implementation, you would add messages like:
181    // .message("user", "Hello, I need help getting started")
182
183    println!("\n Note: Messages can be added during thread creation or afterwards");
184
185    // Example 4: Thread lifecycle management
186    println!("\n");
187    println!(" Example 4: Thread Lifecycle");
188    println!("\n");
189
190    println!("Typical thread lifecycle:");
191    println!("  1. Create thread (ThreadRequestBuilder)");
192    println!("  2. Add messages to thread");
193    println!("  3. Create runs to process messages");
194    println!("  4. Retrieve assistant responses");
195    println!("  5. Continue conversation");
196    println!("  6. Thread persists until deleted");
197
198    // Example 5: Thread use cases
199    println!("\n");
200    println!(" Example 5: Common Thread Use Cases");
201    println!("\n");
202
203    println!(" Customer Support:");
204    println!("  • Create thread per customer session");
205    println!("  • Metadata: customer_id, ticket_id");
206    println!("  • Maintain conversation history");
207    println!("  • Allow agents to review past interactions\n");
208
209    println!(" Chatbot Conversations:");
210    println!("  • One thread per user session");
211    println!("  • Metadata: user_id, session_start");
212    println!("  • Preserve context across messages");
213    println!("  • Support multi-turn conversations\n");
214
215    println!(" Document Q&A:");
216    println!("  • Thread per document discussion");
217    println!("  • Metadata: document_id, user_id");
218    println!("  • Allow follow-up questions");
219    println!("  • Maintain question history\n");
220
221    println!(" Tutoring/Education:");
222    println!("  • Thread per learning session");
223    println!("  • Metadata: student_id, subject, lesson");
224    println!("  • Track learning progression");
225    println!("  • Review past explanations");
226
227    // Example 6: Thread metadata strategies
228    println!("\n");
229    println!(" Example 6: Metadata Strategies");
230    println!("\n");
231
232    println!("Recommended metadata fields:\n");
233
234    println!(" Identification:");
235    println!("  user_id: Identify the user");
236    println!("  session_id: Track specific sessions");
237    println!("  organization_id: Multi-tenant applications\n");
238
239    println!(" Classification:");
240    println!("  category: customer_support, sales, etc.");
241    println!("  priority: low, medium, high, urgent");
242    println!("  language: en, es, fr, etc.\n");
243
244    println!("⏰ Temporal:");
245    println!("  session_start: When conversation began");
246    println!("  last_active: Last interaction time");
247    println!("  expires_at: When to auto-cleanup\n");
248
249    println!(" Business Context:");
250    println!("  product_id: Related product");
251    println!("  ticket_id: Support ticket number");
252    println!("  campaign_id: Marketing campaign");
253
254    // Example 7: Thread best practices
255    println!("\n");
256    println!(" Example 7: Best Practices");
257    println!("\n");
258
259    println!(" Do:");
260    println!("  • Create one thread per conversation");
261    println!("  • Add meaningful metadata for filtering");
262    println!("  • Reuse threads for ongoing conversations");
263    println!("  • Clean up old/expired threads");
264    println!("  • Use metadata for analytics\n");
265
266    println!(" Don't:");
267    println!("  • Create new threads for each message");
268    println!("  • Store sensitive data in metadata");
269    println!("  • Let threads accumulate indefinitely");
270    println!("  • Use threads for one-off requests");
271    println!("  • Mix different conversations in one thread");
272
273    // Summary
274    println!("\n");
275    println!(" Summary");
276    println!("\n");
277
278    println!(" Threads API examples completed!");
279    println!("\n Key Takeaways:");
280    println!("  • Threads maintain conversation state");
281    println!("  • Metadata enables organization and filtering");
282    println!("  • One thread per conversation is recommended");
283    println!("  • Threads persist until explicitly deleted");
284    println!("  • Perfect for multi-turn conversations");
285
286    println!("\n Integration Pattern:");
287    println!("  1. Create thread at conversation start");
288    println!("  2. Store thread ID in your database");
289    println!("  3. Add messages as user interacts");
290    println!("  4. Create runs to get assistant responses");
291    println!("  5. Retrieve messages to display conversation");
292    println!("  6. Reuse thread for entire conversation");
293
294    println!("\n Related APIs:");
295    println!("  • Messages API: Add/retrieve messages in threads");
296    println!("  • Runs API: Process messages with assistants");
297    println!("  • Assistants API: Create AI assistants");
298    println!("  • Vector Stores: Add knowledge to assistants");
299
300    println!("\n Example completed successfully!");
301
302    Ok(())
303}