chat_completions.rs 6.27 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// SPDX-FileCopyrightText: Copyright (c) 2024-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

Paul Hendricks's avatar
Paul Hendricks committed
16
17
18
19
use super::nvext::NvExt;
use super::nvext::NvExtProvider;
use super::OpenAISamplingOptionsProvider;
use super::OpenAIStopConditionsProvider;
Neelay Shah's avatar
Neelay Shah committed
20
use dynamo_runtime::protocols::annotated::AnnotationsProvider;
21
22
23
24
25
26
use serde::{Deserialize, Serialize};
use validator::Validate;

mod aggregator;
mod delta;

Paul Hendricks's avatar
Paul Hendricks committed
27
pub use aggregator::DeltaAggregator;
28
29
pub use delta::DeltaGenerator;

30
31
32
33
34
35
36
/// A request structure for creating a chat completion, extending OpenAI's
/// `CreateChatCompletionRequest` with [`NvExt`] extensions.
///
/// # Fields
/// - `inner`: The base OpenAI chat completion request, embedded using `serde(flatten)`.
/// - `nvext`: The optional NVIDIA extension field. See [`NvExt`] for
///   more details.
Paul Hendricks's avatar
Paul Hendricks committed
37
#[derive(Serialize, Deserialize, Validate, Debug, Clone)]
38
pub struct NvCreateChatCompletionRequest {
Paul Hendricks's avatar
Paul Hendricks committed
39
40
    #[serde(flatten)]
    pub inner: async_openai::types::CreateChatCompletionRequest,
41
42

    #[serde(skip_serializing_if = "Option::is_none")]
43
44
45
    pub nvext: Option<NvExt>,
}

46
47
48
49
50
51
/// A response structure for unary chat completion responses, embedding OpenAI's
/// `CreateChatCompletionResponse`.
///
/// # Fields
/// - `inner`: The base OpenAI unary chat completion response, embedded
///   using `serde(flatten)`.
Paul Hendricks's avatar
Paul Hendricks committed
52
#[derive(Serialize, Deserialize, Validate, Debug, Clone)]
53
pub struct NvCreateChatCompletionResponse {
Paul Hendricks's avatar
Paul Hendricks committed
54
55
    #[serde(flatten)]
    pub inner: async_openai::types::CreateChatCompletionResponse,
56
57
}

58
59
60
61
62
63
/// A response structure for streamed chat completions, embedding OpenAI's
/// `CreateChatCompletionStreamResponse`.
///
/// # Fields
/// - `inner`: The base OpenAI streaming chat completion response, embedded
///   using `serde(flatten)`.
Paul Hendricks's avatar
Paul Hendricks committed
64
#[derive(Serialize, Deserialize, Validate, Debug, Clone)]
65
pub struct NvCreateChatCompletionStreamResponse {
Paul Hendricks's avatar
Paul Hendricks committed
66
67
    #[serde(flatten)]
    pub inner: async_openai::types::CreateChatCompletionStreamResponse,
68
69
}

70
71
/// Implements `NvExtProvider` for `NvCreateChatCompletionRequest`,
/// providing access to NVIDIA-specific extensions.
72
impl NvExtProvider for NvCreateChatCompletionRequest {
73
    /// Returns a reference to the optional `NvExt` extension, if available.
74
75
76
77
    fn nvext(&self) -> Option<&NvExt> {
        self.nvext.as_ref()
    }

78
    /// Returns `None`, as raw prompt extraction is not implemented.
79
80
81
82
83
    fn raw_prompt(&self) -> Option<String> {
        None
    }
}

84
85
/// Implements `AnnotationsProvider` for `NvCreateChatCompletionRequest`,
/// enabling retrieval and management of request annotations.
86
impl AnnotationsProvider for NvCreateChatCompletionRequest {
87
    /// Retrieves the list of annotations from `NvExt`, if present.
Biswa Panda's avatar
Biswa Panda committed
88
89
90
91
92
93
    fn annotations(&self) -> Option<Vec<String>> {
        self.nvext
            .as_ref()
            .and_then(|nvext| nvext.annotations.clone())
    }

94
95
96
97
98
99
100
    /// Checks whether a specific annotation exists in the request.
    ///
    /// # Arguments
    /// * `annotation` - A string slice representing the annotation to check.
    ///
    /// # Returns
    /// `true` if the annotation exists, `false` otherwise.
Biswa Panda's avatar
Biswa Panda committed
101
102
103
104
105
106
107
108
    fn has_annotation(&self, annotation: &str) -> bool {
        self.nvext
            .as_ref()
            .and_then(|nvext| nvext.annotations.as_ref())
            .map(|annotations| annotations.contains(&annotation.to_string()))
            .unwrap_or(false)
    }
}
109

110
111
/// Implements `OpenAISamplingOptionsProvider` for `NvCreateChatCompletionRequest`,
/// exposing OpenAI's sampling parameters for chat completion.
112
impl OpenAISamplingOptionsProvider for NvCreateChatCompletionRequest {
113
    /// Retrieves the temperature parameter for sampling, if set.
114
    fn get_temperature(&self) -> Option<f32> {
Paul Hendricks's avatar
Paul Hendricks committed
115
        self.inner.temperature
116
117
    }

118
    /// Retrieves the top-p (nucleus sampling) parameter, if set.
119
    fn get_top_p(&self) -> Option<f32> {
Paul Hendricks's avatar
Paul Hendricks committed
120
        self.inner.top_p
121
122
    }

123
    /// Retrieves the frequency penalty parameter, if set.
124
    fn get_frequency_penalty(&self) -> Option<f32> {
Paul Hendricks's avatar
Paul Hendricks committed
125
        self.inner.frequency_penalty
126
127
    }

128
    /// Retrieves the presence penalty parameter, if set.
129
    fn get_presence_penalty(&self) -> Option<f32> {
Paul Hendricks's avatar
Paul Hendricks committed
130
        self.inner.presence_penalty
131
132
    }

133
    /// Returns a reference to the optional `NvExt` extension, if available.
134
135
136
137
138
    fn nvext(&self) -> Option<&NvExt> {
        self.nvext.as_ref()
    }
}

139
140
/// Implements `OpenAIStopConditionsProvider` for `NvCreateChatCompletionRequest`,
/// providing access to stop conditions that control chat completion behavior.
141
impl OpenAIStopConditionsProvider for NvCreateChatCompletionRequest {
142
    /// Retrieves the maximum number of tokens allowed in the response.
143
    #[allow(deprecated)]
Paul Hendricks's avatar
Paul Hendricks committed
144
    fn get_max_tokens(&self) -> Option<u32> {
145
        self.inner.max_completion_tokens.or(self.inner.max_tokens)
146
147
    }

148
149
150
151
152
    /// Retrieves the minimum number of tokens required in the response.
    ///
    /// # Note
    /// This method is currently a placeholder and always returns `None`
    /// since `min_tokens` is not an OpenAI-supported parameter.
Paul Hendricks's avatar
Paul Hendricks committed
153
154
    fn get_min_tokens(&self) -> Option<u32> {
        None
155
156
    }

157
158
159
160
161
162
163
    /// Retrieves the stop conditions that terminate the chat completion response.
    ///
    /// Converts OpenAI's `Stop` enum to a `Vec<String>`, normalizing the representation.
    ///
    /// # Returns
    /// * `Some(Vec<String>)` if stop conditions are set.
    /// * `None` if no stop conditions are defined.
164
    fn get_stop(&self) -> Option<Vec<String>> {
165
166
167
168
        self.inner.stop.as_ref().map(|stop| match stop {
            async_openai::types::Stop::String(s) => vec![s.clone()],
            async_openai::types::Stop::StringArray(arr) => arr.clone(),
        })
169
170
    }

171
    /// Returns a reference to the optional `NvExt` extension, if available.
172
173
174
175
    fn nvext(&self) -> Option<&NvExt> {
        self.nvext.as_ref()
    }
}