dynamo_async_openai/types/
message.rs

1// SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2// SPDX-License-Identifier: Apache-2.0
3//
4// Based on https://github.com/64bit/async-openai/ by Himanshu Neema
5// Original Copyright (c) 2022 Himanshu Neema
6// Licensed under MIT License (see ATTRIBUTIONS-Rust.md)
7//
8// Modifications Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES.
9// Licensed under Apache 2.0
10
11use std::collections::HashMap;
12
13use derive_builder::Builder;
14use serde::{Deserialize, Serialize};
15
16use crate::error::OpenAIError;
17
18use super::{ImageDetail, ImageUrl};
19
20#[derive(Clone, Serialize, Debug, Deserialize, PartialEq, Default)]
21#[serde(rename_all = "lowercase")]
22pub enum MessageRole {
23    #[default]
24    User,
25    Assistant,
26}
27
28#[derive(Clone, Serialize, Debug, Deserialize, PartialEq)]
29#[serde(rename_all = "snake_case")]
30pub enum MessageStatus {
31    InProgress,
32    Incomplete,
33    Completed,
34}
35
36#[derive(Clone, Serialize, Debug, Deserialize, PartialEq)]
37#[serde(rename_all = "snake_case")]
38pub enum MessageIncompleteDetailsType {
39    ContentFilter,
40    MaxTokens,
41    RunCancelled,
42    RunExpired,
43    RunFailed,
44}
45
46#[derive(Clone, Serialize, Debug, Deserialize, PartialEq)]
47pub struct MessageIncompleteDetails {
48    /// The reason the message is incomplete.
49    pub reason: MessageIncompleteDetailsType,
50}
51
52///  Represents a message within a [thread](https://platform.openai.com/docs/api-reference/threads).
53#[derive(Clone, Serialize, Debug, Deserialize, PartialEq)]
54pub struct MessageObject {
55    /// The identifier, which can be referenced in API endpoints.
56    pub id: String,
57    /// The object type, which is always `thread.message`.
58    pub object: String,
59    /// The Unix timestamp (in seconds) for when the message was created.
60    pub created_at: i32,
61    /// The [thread](https://platform.openai.com/docs/api-reference/threads) ID that this message belongs to.
62    pub thread_id: String,
63
64    /// The status of the message, which can be either `in_progress`, `incomplete`, or `completed`.
65    pub status: Option<MessageStatus>,
66
67    /// On an incomplete message, details about why the message is incomplete.
68    pub incomplete_details: Option<MessageIncompleteDetails>,
69
70    /// The Unix timestamp (in seconds) for when the message was completed.
71    pub completed_at: Option<u32>,
72
73    /// The Unix timestamp (in seconds) for when the message was marked as incomplete.
74    pub incomplete_at: Option<u32>,
75
76    /// The entity that produced the message. One of `user` or `assistant`.
77    pub role: MessageRole,
78
79    /// The content of the message in array of text and/or images.
80    pub content: Vec<MessageContent>,
81
82    /// If applicable, the ID of the [assistant](https://platform.openai.com/docs/api-reference/assistants) that authored this message.
83    pub assistant_id: Option<String>,
84
85    /// The ID of the [run](https://platform.openai.com/docs/api-reference/runs) associated with the creation of this message. Value is `null` when messages are created manually using the create message or create thread endpoints.
86    pub run_id: Option<String>,
87
88    /// A list of files attached to the message, and the tools they were added to.
89    pub attachments: Option<Vec<MessageAttachment>>,
90
91    pub metadata: Option<HashMap<String, serde_json::Value>>,
92}
93
94#[derive(Clone, Serialize, Debug, Deserialize, PartialEq)]
95pub struct MessageAttachment {
96    /// The ID of the file to attach to the message.
97    pub file_id: String,
98    /// The tools to add this file to.
99    pub tools: Vec<MessageAttachmentTool>,
100}
101
102#[derive(Clone, Serialize, Debug, Deserialize, PartialEq)]
103#[serde(tag = "type")]
104#[serde(rename_all = "snake_case")]
105pub enum MessageAttachmentTool {
106    CodeInterpreter,
107    FileSearch,
108}
109
110#[derive(Clone, Serialize, Debug, Deserialize, PartialEq)]
111#[serde(tag = "type")]
112#[serde(rename_all = "snake_case")]
113pub enum MessageContent {
114    Text(MessageContentTextObject),
115    ImageFile(MessageContentImageFileObject),
116    ImageUrl(MessageContentImageUrlObject),
117    Refusal(MessageContentRefusalObject),
118}
119
120#[derive(Clone, Serialize, Debug, Deserialize, PartialEq)]
121pub struct MessageContentRefusalObject {
122    pub refusal: String,
123}
124
125/// The text content that is part of a message.
126#[derive(Clone, Serialize, Debug, Deserialize, PartialEq)]
127pub struct MessageContentTextObject {
128    pub text: TextData,
129}
130
131#[derive(Clone, Serialize, Debug, Deserialize, PartialEq)]
132pub struct TextData {
133    /// The data that makes up the text.
134    pub value: String,
135    pub annotations: Vec<MessageContentTextAnnotations>,
136}
137
138#[derive(Clone, Serialize, Debug, Deserialize, PartialEq)]
139#[serde(tag = "type")]
140#[serde(rename_all = "snake_case")]
141pub enum MessageContentTextAnnotations {
142    /// A citation within the message that points to a specific quote from a specific File associated with the assistant or the message. Generated when the assistant uses the "retrieval" tool to search files.
143    FileCitation(MessageContentTextAnnotationsFileCitationObject),
144    /// A URL for the file that's generated when the assistant used the `code_interpreter` tool to generate a file.
145    FilePath(MessageContentTextAnnotationsFilePathObject),
146}
147
148/// A citation within the message that points to a specific quote from a specific File associated with the assistant or the message. Generated when the assistant uses the "file_search" tool to search files.
149#[derive(Clone, Serialize, Debug, Deserialize, PartialEq)]
150pub struct MessageContentTextAnnotationsFileCitationObject {
151    /// The text in the message content that needs to be replaced.
152    pub text: String,
153    pub file_citation: FileCitation,
154    pub start_index: u32,
155    pub end_index: u32,
156}
157
158#[derive(Clone, Serialize, Debug, Deserialize, PartialEq)]
159pub struct FileCitation {
160    /// The ID of the specific File the citation is from.
161    pub file_id: String,
162    /// The specific quote in the file.
163    pub quote: Option<String>,
164}
165
166#[derive(Clone, Serialize, Debug, Deserialize, PartialEq)]
167pub struct MessageContentTextAnnotationsFilePathObject {
168    /// The text in the message content that needs to be replaced.
169    pub text: String,
170    pub file_path: FilePath,
171    pub start_index: u32,
172    pub end_index: u32,
173}
174
175#[derive(Clone, Serialize, Debug, Deserialize, PartialEq)]
176pub struct FilePath {
177    /// The ID of the file that was generated.
178    pub file_id: String,
179}
180
181/// References an image [File](https://platform.openai.com/docs/api-reference/files) in the content of a message.
182#[derive(Clone, Serialize, Debug, Deserialize, PartialEq)]
183pub struct MessageContentImageFileObject {
184    pub image_file: ImageFile,
185}
186
187#[derive(Clone, Serialize, Debug, Deserialize, PartialEq)]
188pub struct ImageFile {
189    /// The [File](https://platform.openai.com/docs/api-reference/files) ID of the image in the message content. Set `purpose="vision"` when uploading the File if you need to later display the file content.
190    pub file_id: String,
191    /// Specifies the detail level of the image if specified by the user. `low` uses fewer tokens, you can opt in to high resolution using `high`.
192    pub detail: Option<ImageDetail>,
193}
194
195/// References an image URL in the content of a message.
196#[derive(Clone, Serialize, Debug, Deserialize, PartialEq)]
197pub struct MessageContentImageUrlObject {
198    pub image_url: ImageUrl,
199}
200
201#[derive(Clone, Serialize, Debug, Deserialize, PartialEq)]
202pub struct MessageRequestContentTextObject {
203    /// Text content to be sent to the model
204    pub text: String,
205}
206
207#[derive(Clone, Serialize, Debug, Deserialize, PartialEq)]
208#[serde(untagged)]
209pub enum CreateMessageRequestContent {
210    /// The text contents of the message.
211    Content(String),
212    /// An array of content parts with a defined type, each can be of type `text` or images can be passed with `image_url` or `image_file`. Image types are only supported on [Vision-compatible models](https://platform.openai.com/docs/models/overview).
213    ContentArray(Vec<MessageContentInput>),
214}
215
216#[derive(Clone, Serialize, Debug, Deserialize, PartialEq)]
217#[serde(tag = "type")]
218#[serde(rename_all = "snake_case")]
219pub enum MessageContentInput {
220    Text(MessageRequestContentTextObject),
221    ImageFile(MessageContentImageFileObject),
222    ImageUrl(MessageContentImageUrlObject),
223}
224#[derive(Clone, Serialize, Default, Debug, Deserialize, Builder, PartialEq)]
225#[builder(name = "CreateMessageRequestArgs")]
226#[builder(pattern = "mutable")]
227#[builder(setter(into, strip_option), default)]
228#[builder(derive(Debug))]
229#[builder(build_fn(error = "OpenAIError"))]
230pub struct CreateMessageRequest {
231    /// The role of the entity that is creating the message. Allowed values include:
232    /// - `user`: Indicates the message is sent by an actual user and should be used in most cases to represent user-generated messages.
233    /// - `assistant`: Indicates the message is generated by the assistant. Use this value to insert messages from the assistant into the conversation.
234    pub role: MessageRole,
235    /// The content of the message.
236    pub content: CreateMessageRequestContent,
237
238    /// A list of files attached to the message, and the tools they should be added to.
239    pub attachments: Option<Vec<MessageAttachment>>,
240
241    #[serde(skip_serializing_if = "Option::is_none")]
242    pub metadata: Option<HashMap<String, serde_json::Value>>,
243}
244
245#[derive(Clone, Serialize, Default, Debug, Deserialize, PartialEq)]
246pub struct ModifyMessageRequest {
247    #[serde(skip_serializing_if = "Option::is_none")]
248    pub metadata: Option<HashMap<String, serde_json::Value>>,
249}
250
251#[derive(Clone, Serialize, Default, Debug, Deserialize, PartialEq)]
252pub struct DeleteMessageResponse {
253    pub id: String,
254    pub deleted: bool,
255    pub object: String,
256}
257
258#[derive(Clone, Serialize, Default, Debug, Deserialize, PartialEq)]
259pub struct ListMessagesResponse {
260    pub object: String,
261    pub data: Vec<MessageObject>,
262    pub first_id: Option<String>,
263    pub last_id: Option<String>,
264    pub has_more: bool,
265}
266
267/// Represents a message delta i.e. any changed fields on a message during streaming.
268#[derive(Clone, Serialize, Debug, Deserialize, PartialEq)]
269pub struct MessageDeltaObject {
270    /// The identifier of the message, which can be referenced in API endpoints.
271    pub id: String,
272    /// The object type, which is always `thread.message.delta`.
273    pub object: String,
274    /// The delta containing the fields that have changed on the Message.
275    pub delta: MessageDelta,
276}
277
278#[derive(Clone, Serialize, Debug, Deserialize, PartialEq)]
279pub struct MessageDelta {
280    /// The entity that produced the message. One of `user` or `assistant`.
281    pub role: Option<MessageRole>,
282    ///  The content of the message in array of text and/or images.
283    pub content: Option<Vec<MessageDeltaContent>>,
284}
285
286#[derive(Clone, Serialize, Debug, Deserialize, PartialEq)]
287#[serde(tag = "type")]
288#[serde(rename_all = "snake_case")]
289pub enum MessageDeltaContent {
290    ImageFile(MessageDeltaContentImageFileObject),
291    ImageUrl(MessageDeltaContentImageUrlObject),
292    Text(MessageDeltaContentTextObject),
293    Refusal(MessageDeltaContentRefusalObject),
294}
295
296#[derive(Clone, Serialize, Debug, Deserialize, PartialEq)]
297pub struct MessageDeltaContentRefusalObject {
298    /// The index of the refusal part in the message.
299    pub index: i32,
300    pub refusal: Option<String>,
301}
302
303/// The text content that is part of a message.
304#[derive(Clone, Serialize, Debug, Deserialize, PartialEq)]
305pub struct MessageDeltaContentTextObject {
306    /// The index of the content part in the message.
307    pub index: u32,
308    pub text: Option<MessageDeltaContentText>,
309}
310
311#[derive(Clone, Serialize, Debug, Deserialize, PartialEq)]
312pub struct MessageDeltaContentText {
313    /// The data that makes up the text.
314    pub value: Option<String>,
315    pub annotations: Option<Vec<MessageDeltaContentTextAnnotations>>,
316}
317
318#[derive(Clone, Serialize, Debug, Deserialize, PartialEq)]
319#[serde(tag = "type")]
320#[serde(rename_all = "snake_case")]
321pub enum MessageDeltaContentTextAnnotations {
322    FileCitation(MessageDeltaContentTextAnnotationsFileCitationObject),
323    FilePath(MessageDeltaContentTextAnnotationsFilePathObject),
324}
325
326/// A citation within the message that points to a specific quote from a specific File associated with the assistant or the message. Generated when the assistant uses the "file_search" tool to search files.
327#[derive(Clone, Serialize, Debug, Deserialize, PartialEq)]
328pub struct MessageDeltaContentTextAnnotationsFileCitationObject {
329    /// The index of the annotation in the text content part.
330    pub index: u32,
331    /// The text in the message content that needs to be replaced.
332    pub text: Option<String>,
333    pub file_citation: Option<FileCitation>,
334    pub start_index: Option<u32>,
335    pub end_index: Option<u32>,
336}
337
338/// A URL for the file that's generated when the assistant used the `code_interpreter` tool to generate a file.
339#[derive(Clone, Serialize, Debug, Deserialize, PartialEq)]
340pub struct MessageDeltaContentTextAnnotationsFilePathObject {
341    /// The index of the annotation in the text content part.
342    pub index: u32,
343    /// The text in the message content that needs to be replaced.
344    pub text: Option<String>,
345    pub file_path: Option<FilePath>,
346    pub start_index: Option<u32>,
347    pub end_index: Option<u32>,
348}
349
350/// References an image [File](https://platform.openai.com/docs/api-reference/files) in the content of a message.
351#[derive(Clone, Serialize, Debug, Deserialize, PartialEq)]
352pub struct MessageDeltaContentImageFileObject {
353    /// The index of the content part in the message.
354    pub index: u32,
355
356    pub image_file: Option<ImageFile>,
357}
358
359#[derive(Clone, Serialize, Debug, Deserialize, PartialEq)]
360pub struct MessageDeltaContentImageUrlObject {
361    /// The index of the content part in the message.
362    pub index: u32,
363
364    pub image_url: Option<ImageUrl>,
365}