async_openai/
chat.rs

1use serde::Serialize;
2
3use crate::{
4    config::Config,
5    error::OpenAIError,
6    types::chat::{
7        ChatCompletionDeleted, ChatCompletionList, ChatCompletionMessageList,
8        ChatCompletionResponseStream, CreateChatCompletionRequest, CreateChatCompletionResponse,
9        UpdateChatCompletionRequest,
10    },
11    Client,
12};
13
14/// Given a list of messages comprising a conversation, the model will return a response.
15///
16/// Related guide: [Chat Completions](https://platform.openai.com/docs/guides/text-generation)
17pub struct Chat<'c, C: Config> {
18    client: &'c Client<C>,
19}
20
21impl<'c, C: Config> Chat<'c, C> {
22    pub fn new(client: &'c Client<C>) -> Self {
23        Self { client }
24    }
25
26    /// Creates a model response for the given chat conversation.
27    ///
28    /// Returns a [chat completion](https://platform.openai.com/docs/api-reference/chat/object) object, or a streamed sequence of [chat completion chunk](https://platform.openai.com/docs/api-reference/chat/streaming) objects if the request is streamed.
29    ///
30    /// Learn more in the [text generation](https://platform.openai.com/docs/guides/text-generation), [vision](https://platform.openai.com/docs/guides/vision), and [audio](https://platform.openai.com/docs/guides/audio) guides.
31    ///
32    /// Parameter support can differ depending on the model used to generate the response, particularly for newer reasoning models. Parameters that are only supported for reasoning models are noted below. For the current state of unsupported parameters in reasoning models, [refer to the reasoning guide](https://platform.openai.com/docs/guides/reasoning).
33    ///
34    /// byot: You must ensure "stream: false" in serialized `request`
35    #[crate::byot(
36        T0 = serde::Serialize,
37        R = serde::de::DeserializeOwned
38    )]
39    pub async fn create(
40        &self,
41        request: CreateChatCompletionRequest,
42    ) -> Result<CreateChatCompletionResponse, OpenAIError> {
43        #[cfg(not(feature = "byot"))]
44        {
45            if request.stream.is_some() && request.stream.unwrap() {
46                return Err(OpenAIError::InvalidArgument(
47                    "When stream is true, use Chat::create_stream".into(),
48                ));
49            }
50        }
51        self.client.post("/chat/completions", request).await
52    }
53
54    /// Creates a completion for the chat message.
55    ///
56    /// If set to true, the model response data will be streamed to the client as it is generated using [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format).
57    ///
58    /// See the [Streaming section](https://platform.openai.com/docs/api-reference/chat/streaming) for more information, along with the [streaming responses](https://platform.openai.com/docs/guides/streaming-responses) guide for more information on how to handle the streaming events.
59    ///
60    /// [ChatCompletionResponseStream] is a parsed SSE stream until a \[DONE\] is received from server.
61    ///
62    /// byot: You must ensure "stream: true" in serialized `request`
63    #[crate::byot(
64        T0 = serde::Serialize,
65        R = serde::de::DeserializeOwned,
66        stream = "true",
67        where_clause = "R: std::marker::Send + 'static"
68    )]
69    #[allow(unused_mut)]
70    pub async fn create_stream(
71        &self,
72        mut request: CreateChatCompletionRequest,
73    ) -> Result<ChatCompletionResponseStream, OpenAIError> {
74        #[cfg(not(feature = "byot"))]
75        {
76            if request.stream.is_some() && !request.stream.unwrap() {
77                return Err(OpenAIError::InvalidArgument(
78                    "When stream is false, use Chat::create".into(),
79                ));
80            }
81
82            request.stream = Some(true);
83        }
84        Ok(self.client.post_stream("/chat/completions", request).await)
85    }
86
87    /// List stored Chat Completions. Only Chat Completions that have been stored
88    /// with the `store` parameter set to `true` will be returned.
89    #[crate::byot(T0 = serde::Serialize, R = serde::de::DeserializeOwned)]
90    pub async fn list<Q>(&self, query: &Q) -> Result<ChatCompletionList, OpenAIError>
91    where
92        Q: Serialize + ?Sized,
93    {
94        self.client
95            .get_with_query("/chat/completions", &query)
96            .await
97    }
98
99    /// Get a stored chat completion. Only Chat Completions that have been created
100    /// with the `store` parameter set to `true` will be returned.
101    #[crate::byot(T0 = std::fmt::Display, R = serde::de::DeserializeOwned)]
102    pub async fn retrieve(
103        &self,
104        completion_id: &str,
105    ) -> Result<CreateChatCompletionResponse, OpenAIError> {
106        self.client
107            .get(&format!("/chat/completions/{completion_id}"))
108            .await
109    }
110
111    /// Modify a stored chat completion. Only Chat Completions that have been
112    /// created with the `store` parameter set to `true` can be modified. Currently,
113    /// the only supported modification is to update the `metadata` field.
114    #[crate::byot(
115        T0 = std::fmt::Display,
116        T1 = serde::Serialize,
117        R = serde::de::DeserializeOwned
118    )]
119    pub async fn update(
120        &self,
121        completion_id: &str,
122        request: UpdateChatCompletionRequest,
123    ) -> Result<CreateChatCompletionResponse, OpenAIError> {
124        self.client
125            .post(&format!("/chat/completions/{completion_id}"), request)
126            .await
127    }
128
129    /// Delete a stored chat completion. Only Chat Completions that have been
130    /// created with the `store` parameter set to `true` can be deleted.
131    #[crate::byot(T0 = std::fmt::Display, R = serde::de::DeserializeOwned)]
132    pub async fn delete(&self, completion_id: &str) -> Result<ChatCompletionDeleted, OpenAIError> {
133        self.client
134            .delete(&format!("/chat/completions/{completion_id}"))
135            .await
136    }
137
138    /// Get a list of messages for the specified chat completion.
139    #[crate::byot(T0 = std::fmt::Display, T1 = serde::Serialize, R = serde::de::DeserializeOwned)]
140    pub async fn messages<Q>(
141        &self,
142        completion_id: &str,
143        query: &Q,
144    ) -> Result<ChatCompletionMessageList, OpenAIError>
145    where
146        Q: Serialize + ?Sized,
147    {
148        self.client
149            .get_with_query(
150                &format!("/chat/completions/{completion_id}/messages"),
151                &query,
152            )
153            .await
154    }
155}