Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
OpenDAS
dynamo
Commits
b6a3b0c6
Unverified
Commit
b6a3b0c6
authored
Apr 01, 2026
by
ishandhanani
Committed by
GitHub
Apr 01, 2026
Browse files
refactor(2/3): rename dynamo-async-openai to dynamo-protocols (#7565)
parent
c84c0934
Changes
155
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
182 additions
and
192 deletions
+182
-192
lib/llm/src/protocols/openai/tools.rs
lib/llm/src/protocols/openai/tools.rs
+6
-8
lib/llm/src/protocols/openai/validate.rs
lib/llm/src/protocols/openai/validate.rs
+15
-15
lib/llm/src/protocols/unified.rs
lib/llm/src/protocols/unified.rs
+5
-7
lib/llm/tests/aggregators.rs
lib/llm/tests/aggregators.rs
+4
-4
lib/llm/tests/http-service.rs
lib/llm/tests/http-service.rs
+50
-56
lib/llm/tests/http_metrics.rs
lib/llm/tests/http_metrics.rs
+8
-8
lib/llm/tests/kserve_service.rs
lib/llm/tests/kserve_service.rs
+1
-1
lib/llm/tests/logprob_analysis_integration.rs
lib/llm/tests/logprob_analysis_integration.rs
+3
-3
lib/llm/tests/openai_completions.rs
lib/llm/tests/openai_completions.rs
+4
-4
lib/llm/tests/parallel_tool_call_integration.rs
lib/llm/tests/parallel_tool_call_integration.rs
+15
-15
lib/llm/tests/postprocessor_parsing_stream.rs
lib/llm/tests/postprocessor_parsing_stream.rs
+5
-5
lib/llm/tests/preprocessor.rs
lib/llm/tests/preprocessor.rs
+14
-14
lib/llm/tests/test_common_ext.rs
lib/llm/tests/test_common_ext.rs
+4
-4
lib/llm/tests/test_jail.rs
lib/llm/tests/test_jail.rs
+13
-13
lib/llm/tests/test_reasoning_parser.rs
lib/llm/tests/test_reasoning_parser.rs
+4
-4
lib/llm/tests/test_streaming_tool_parsers.rs
lib/llm/tests/test_streaming_tool_parsers.rs
+2
-2
lib/llm/tests/test_streaming_usage.rs
lib/llm/tests/test_streaming_usage.rs
+10
-10
lib/llm/tests/tool_choice.rs
lib/llm/tests/tool_choice.rs
+7
-7
lib/llm/tests/tool_choice_finish_reasons.rs
lib/llm/tests/tool_choice_finish_reasons.rs
+11
-11
lib/parsers/Cargo.toml
lib/parsers/Cargo.toml
+1
-1
No files found.
lib/llm/src/protocols/openai/tools.rs
View file @
b6a3b0c6
...
...
@@ -3,9 +3,7 @@
use
std
::
collections
::
BTreeMap
;
use
dynamo_async_openai
::
types
::{
ChatCompletionTool
,
ChatCompletionToolChoiceOption
,
FunctionObject
,
};
use
dynamo_protocols
::
types
::{
ChatCompletionTool
,
ChatCompletionToolChoiceOption
,
FunctionObject
};
use
serde_json
::{
Value
,
json
};
use
thiserror
::
Error
;
...
...
@@ -267,7 +265,7 @@ fn merge_defs(
#[cfg(test)]
mod
tests
{
use
super
::
*
;
use
dynamo_
async_openai
::
types
::{
ChatCompletionToolChoiceOption
,
ChatCompletionToolType
};
use
dynamo_
protocols
::
types
::{
ChatCompletionToolChoiceOption
,
ChatCompletionToolType
};
fn
sample_tools
()
->
Vec
<
ChatCompletionTool
>
{
vec!
[
...
...
@@ -310,9 +308,9 @@ mod tests {
fn
named_choice_returns_parameters
()
{
let
tools
=
sample_tools
();
let
tool_choice
=
ChatCompletionToolChoiceOption
::
Named
(
dynamo_
async_openai
::
types
::
ChatCompletionNamedToolChoice
{
dynamo_
protocols
::
types
::
ChatCompletionNamedToolChoice
{
r
#
type
:
ChatCompletionToolType
::
Function
,
function
:
dynamo_
async_openai
::
types
::
FunctionName
{
function
:
dynamo_
protocols
::
types
::
FunctionName
{
name
:
"get_weather"
.to_string
(),
},
},
...
...
@@ -358,9 +356,9 @@ mod tests {
fn
missing_tool_errors
()
{
let
tools
=
sample_tools
();
let
tool_choice
=
ChatCompletionToolChoiceOption
::
Named
(
dynamo_
async_openai
::
types
::
ChatCompletionNamedToolChoice
{
dynamo_
protocols
::
types
::
ChatCompletionNamedToolChoice
{
r
#
type
:
ChatCompletionToolType
::
Function
,
function
:
dynamo_
async_openai
::
types
::
FunctionName
{
function
:
dynamo_
protocols
::
types
::
FunctionName
{
name
:
"unknown"
.to_string
(),
},
},
...
...
lib/llm/src/protocols/openai/validate.rs
View file @
b6a3b0c6
...
...
@@ -119,9 +119,9 @@ pub fn validate_no_unsupported_fields(
///
/// `{"type":"text"}` is accepted and means no structured constraint.
pub
fn
validate_response_format
(
response_format
:
&
Option
<
dynamo_
async_openai
::
types
::
ResponseFormat
>
,
response_format
:
&
Option
<
dynamo_
protocols
::
types
::
ResponseFormat
>
,
)
->
Result
<
(),
anyhow
::
Error
>
{
use
dynamo_
async_openai
::
types
::
ResponseFormat
;
use
dynamo_
protocols
::
types
::
ResponseFormat
;
let
Some
(
fmt
)
=
response_format
else
{
return
Ok
(());
...
...
@@ -355,15 +355,15 @@ pub fn validate_user(user: Option<&str>) -> Result<(), anyhow::Error> {
}
/// Validates stop sequences
pub
fn
validate_stop
(
stop
:
&
Option
<
dynamo_
async_openai
::
types
::
Stop
>
)
->
Result
<
(),
anyhow
::
Error
>
{
pub
fn
validate_stop
(
stop
:
&
Option
<
dynamo_
protocols
::
types
::
Stop
>
)
->
Result
<
(),
anyhow
::
Error
>
{
if
let
Some
(
stop_value
)
=
stop
{
match
stop_value
{
dynamo_
async_openai
::
types
::
Stop
::
String
(
s
)
=>
{
dynamo_
protocols
::
types
::
Stop
::
String
(
s
)
=>
{
if
s
.is_empty
()
{
anyhow
::
bail!
(
"Stop sequence cannot be empty"
);
}
}
dynamo_
async_openai
::
types
::
Stop
::
StringArray
(
sequences
)
=>
{
dynamo_
protocols
::
types
::
Stop
::
StringArray
(
sequences
)
=>
{
if
sequences
.is_empty
()
{
anyhow
::
bail!
(
"Stop sequences array cannot be empty"
);
}
...
...
@@ -391,7 +391,7 @@ pub fn validate_stop(stop: &Option<dynamo_async_openai::types::Stop>) -> Result<
/// Validates messages array
pub
fn
validate_messages
(
messages
:
&
[
dynamo_
async_openai
::
types
::
ChatCompletionRequestMessage
],
messages
:
&
[
dynamo_
protocols
::
types
::
ChatCompletionRequestMessage
],
)
->
Result
<
(),
anyhow
::
Error
>
{
if
messages
.is_empty
()
{
anyhow
::
bail!
(
"Messages array cannot be empty"
);
...
...
@@ -415,7 +415,7 @@ pub fn validate_top_logprobs(top_logprobs: Option<u8>) -> Result<(), anyhow::Err
/// Validates tools array
pub
fn
validate_tools
(
tools
:
&
Option
<&
[
dynamo_
async_openai
::
types
::
ChatCompletionTool
]
>
,
tools
:
&
Option
<&
[
dynamo_
protocols
::
types
::
ChatCompletionTool
]
>
,
)
->
Result
<
(),
anyhow
::
Error
>
{
let
tools
=
match
tools
{
Some
(
val
)
=>
val
,
...
...
@@ -448,7 +448,7 @@ pub fn validate_tools(
/// Validates reasoning effort parameter
pub
fn
validate_reasoning_effort
(
_
reasoning_effort
:
&
Option
<
dynamo_
async_openai
::
types
::
ReasoningEffort
>
,
_
reasoning_effort
:
&
Option
<
dynamo_
protocols
::
types
::
ReasoningEffort
>
,
)
->
Result
<
(),
anyhow
::
Error
>
{
// TODO ADD HERE
// ReasoningEffort is an enum, so if it exists, it's valid by definition
...
...
@@ -458,7 +458,7 @@ pub fn validate_reasoning_effort(
/// Validates service tier parameter
pub
fn
validate_service_tier
(
_
service_tier
:
&
Option
<
dynamo_
async_openai
::
types
::
ServiceTier
>
,
_
service_tier
:
&
Option
<
dynamo_
protocols
::
types
::
ServiceTier
>
,
)
->
Result
<
(),
anyhow
::
Error
>
{
// TODO ADD HERE
// ServiceTier is an enum, so if it exists, it's valid by definition
...
...
@@ -471,14 +471,14 @@ pub fn validate_service_tier(
//
/// Validates prompt
pub
fn
validate_prompt
(
prompt
:
&
dynamo_
async_openai
::
types
::
Prompt
)
->
Result
<
(),
anyhow
::
Error
>
{
pub
fn
validate_prompt
(
prompt
:
&
dynamo_
protocols
::
types
::
Prompt
)
->
Result
<
(),
anyhow
::
Error
>
{
match
prompt
{
dynamo_
async_openai
::
types
::
Prompt
::
String
(
s
)
=>
{
dynamo_
protocols
::
types
::
Prompt
::
String
(
s
)
=>
{
if
s
.is_empty
()
{
anyhow
::
bail!
(
"Prompt string cannot be empty"
);
}
}
dynamo_
async_openai
::
types
::
Prompt
::
StringArray
(
arr
)
=>
{
dynamo_
protocols
::
types
::
Prompt
::
StringArray
(
arr
)
=>
{
if
arr
.is_empty
()
{
anyhow
::
bail!
(
"Prompt string array cannot be empty"
);
}
...
...
@@ -488,12 +488,12 @@ pub fn validate_prompt(prompt: &dynamo_async_openai::types::Prompt) -> Result<()
}
}
}
dynamo_
async_openai
::
types
::
Prompt
::
IntegerArray
(
arr
)
=>
{
dynamo_
protocols
::
types
::
Prompt
::
IntegerArray
(
arr
)
=>
{
if
arr
.is_empty
()
{
anyhow
::
bail!
(
"Prompt integer array cannot be empty"
);
}
}
dynamo_
async_openai
::
types
::
Prompt
::
ArrayOfIntegerArray
(
arr
)
=>
{
dynamo_
protocols
::
types
::
Prompt
::
ArrayOfIntegerArray
(
arr
)
=>
{
if
arr
.is_empty
()
{
anyhow
::
bail!
(
"Prompt array of integer arrays cannot be empty"
);
}
...
...
@@ -516,7 +516,7 @@ pub fn validate_prompt(prompt: &dynamo_async_openai::types::Prompt) -> Result<()
///
/// Format for prompt_embeds: PyTorch tensor serialized with torch.save() and base64-encoded
pub
fn
validate_prompt_or_embeds
(
prompt
:
Option
<&
dynamo_
async_openai
::
types
::
Prompt
>
,
prompt
:
Option
<&
dynamo_
protocols
::
types
::
Prompt
>
,
prompt_embeds
:
Option
<&
str
>
,
)
->
Result
<
(),
anyhow
::
Error
>
{
// Check that at least one is provided
...
...
lib/llm/src/protocols/unified.rs
View file @
b6a3b0c6
...
...
@@ -46,7 +46,7 @@ use crate::protocols::openai::{
OpenAIOutputOptionsProvider
,
OpenAISamplingOptionsProvider
,
OpenAIStopConditionsProvider
,
};
use
dynamo_
async_openai
::
types
::
responses
::{
IncludeEnum
,
Reasoning
,
Truncation
};
use
dynamo_
protocols
::
types
::
responses
::{
IncludeEnum
,
Reasoning
,
Truncation
};
use
super
::
anthropic
::
types
::{
AnthropicCreateMessageRequest
,
ThinkingConfig
};
use
super
::
openai
::
responses
::
NvCreateResponse
;
...
...
@@ -417,8 +417,8 @@ impl OpenAIStopConditionsProvider for UnifiedRequest {
fn
get_stop
(
&
self
)
->
Option
<
Vec
<
String
>>
{
self
.inner.inner.stop
.as_ref
()
.map
(|
stop
|
match
stop
{
dynamo_
async_openai
::
types
::
Stop
::
String
(
s
)
=>
vec!
[
s
.clone
()],
dynamo_
async_openai
::
types
::
Stop
::
StringArray
(
arr
)
=>
arr
.clone
(),
dynamo_
protocols
::
types
::
Stop
::
String
(
s
)
=>
vec!
[
s
.clone
()],
dynamo_
protocols
::
types
::
Stop
::
StringArray
(
arr
)
=>
arr
.clone
(),
})
}
...
...
@@ -466,9 +466,7 @@ impl OAIChatLikeRequest for UnifiedRequest {
minijinja
::
value
::
Value
::
from_serialize
(
&
messages_json
)
}
fn
typed_messages
(
&
self
,
)
->
Option
<&
[
dynamo_async_openai
::
types
::
ChatCompletionRequestMessage
]
>
{
fn
typed_messages
(
&
self
)
->
Option
<&
[
dynamo_protocols
::
types
::
ChatCompletionRequestMessage
]
>
{
Some
(
self
.inner.inner.messages
.as_slice
())
}
...
...
@@ -535,7 +533,7 @@ mod tests {
#[test]
fn
test_chat_completions_roundtrip
()
{
let
req
=
NvCreateChatCompletionRequest
{
inner
:
dynamo_
async_openai
::
types
::
CreateChatCompletionRequest
{
inner
:
dynamo_
protocols
::
types
::
CreateChatCompletionRequest
{
model
:
"test-model"
.to_string
(),
messages
:
vec!
[],
..
Default
::
default
()
...
...
lib/llm/tests/aggregators.rs
View file @
b6a3b0c6
// SPDX-FileCopyrightText: Copyright (c) 2024-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
use
dynamo_async_openai
::
types
::{
ChatChoiceStream
,
ChatCompletionMessageContent
,
ChatCompletionStreamResponseDelta
,
CreateChatCompletionStreamResponse
,
Role
,
};
use
dynamo_llm
::
protocols
::{
Annotated
,
ContentProvider
,
DataStream
,
codec
::{
Message
,
SseCodecError
,
create_message_stream
},
...
...
@@ -17,6 +13,10 @@ use dynamo_llm::protocols::{
completions
::
NvCreateCompletionResponse
,
},
};
use
dynamo_protocols
::
types
::{
ChatChoiceStream
,
ChatCompletionMessageContent
,
ChatCompletionStreamResponseDelta
,
CreateChatCompletionStreamResponse
,
Role
,
};
use
futures
::
StreamExt
;
fn
get_text
(
content
:
&
ChatCompletionMessageContent
)
->
&
str
{
...
...
lib/llm/tests/http-service.rs
View file @
b6a3b0c6
...
...
@@ -3,7 +3,6 @@
use
anyhow
::
Error
;
use
async_stream
::
stream
;
use
dynamo_async_openai
::
config
::
OpenAIConfig
;
use
dynamo_llm
::
protocols
::{
Annotated
,
codec
::
SseLineCodec
,
...
...
@@ -28,6 +27,7 @@ use dynamo_llm::{
},
model_card
::
ModelDeploymentCard
,
};
use
dynamo_protocols
::
config
::
OpenAIConfig
;
use
dynamo_runtime
::
metrics
::
prometheus_names
::{
frontend_service
,
name_prefix
};
use
dynamo_runtime
::{
CancellationToken
,
...
...
@@ -318,16 +318,16 @@ async fn test_http_service() {
let
client
=
reqwest
::
Client
::
new
();
let
message
=
dynamo_
async_openai
::
types
::
ChatCompletionRequestMessage
::
User
(
dynamo_
async_openai
::
types
::
ChatCompletionRequestUserMessage
{
content
:
dynamo_
async_openai
::
types
::
ChatCompletionRequestUserMessageContent
::
Text
(
let
message
=
dynamo_
protocols
::
types
::
ChatCompletionRequestMessage
::
User
(
dynamo_
protocols
::
types
::
ChatCompletionRequestUserMessage
{
content
:
dynamo_
protocols
::
types
::
ChatCompletionRequestUserMessageContent
::
Text
(
"hi"
.to_string
(),
),
name
:
None
,
},
);
let
mut
request
=
dynamo_
async_openai
::
types
::
CreateChatCompletionRequestArgs
::
default
()
let
mut
request
=
dynamo_
protocols
::
types
::
CreateChatCompletionRequestArgs
::
default
()
.model
(
"foo"
)
.messages
(
vec!
[
message
])
.build
()
...
...
@@ -493,7 +493,7 @@ async fn test_http_service() {
// ==== ChatCompletions / Unary / Error ====
// ==== Completions / Unary / Error ====
let
mut
request
=
dynamo_
async_openai
::
types
::
CreateCompletionRequestArgs
::
default
()
let
mut
request
=
dynamo_
protocols
::
types
::
CreateCompletionRequestArgs
::
default
()
.model
(
"bar"
)
.prompt
(
"hi"
)
.build
()
...
...
@@ -649,15 +649,14 @@ async fn test_pure_openai_client() {
wait_for_service_ready
(
port
)
.await
;
// Test successful streaming request
let
request
=
dynamo_
async_openai
::
types
::
CreateChatCompletionRequestArgs
::
default
()
let
request
=
dynamo_
protocols
::
types
::
CreateChatCompletionRequestArgs
::
default
()
.model
(
"foo"
)
.messages
(
vec!
[
dynamo_async_openai
::
types
::
ChatCompletionRequestMessage
::
User
(
dynamo_async_openai
::
types
::
ChatCompletionRequestUserMessage
{
content
:
dynamo_async_openai
::
types
::
ChatCompletionRequestUserMessageContent
::
Text
(
"Hi"
.to_string
(),
),
dynamo_protocols
::
types
::
ChatCompletionRequestMessage
::
User
(
dynamo_protocols
::
types
::
ChatCompletionRequestUserMessage
{
content
:
dynamo_protocols
::
types
::
ChatCompletionRequestUserMessageContent
::
Text
(
"Hi"
.to_string
(),
),
name
:
None
,
},
),
...
...
@@ -682,15 +681,14 @@ async fn test_pure_openai_client() {
assert
!
(
count
>
0
,
"Should receive at least one response"
);
// Test error case with invalid model
let
request
=
dynamo_
async_openai
::
types
::
CreateChatCompletionRequestArgs
::
default
()
let
request
=
dynamo_
protocols
::
types
::
CreateChatCompletionRequestArgs
::
default
()
.model
(
"bar"
)
// This model will fail
.messages
(
vec!
[
dynamo_async_openai
::
types
::
ChatCompletionRequestMessage
::
User
(
dynamo_async_openai
::
types
::
ChatCompletionRequestUserMessage
{
content
:
dynamo_async_openai
::
types
::
ChatCompletionRequestUserMessageContent
::
Text
(
"Hi"
.to_string
(),
),
dynamo_protocols
::
types
::
ChatCompletionRequestMessage
::
User
(
dynamo_protocols
::
types
::
ChatCompletionRequestUserMessage
{
content
:
dynamo_protocols
::
types
::
ChatCompletionRequestUserMessageContent
::
Text
(
"Hi"
.to_string
(),
),
name
:
None
,
},
),
...
...
@@ -716,15 +714,14 @@ async fn test_pure_openai_client() {
// Test context management
let
ctx
=
HttpRequestContext
::
new
();
let
request
=
dynamo_
async_openai
::
types
::
CreateChatCompletionRequestArgs
::
default
()
let
request
=
dynamo_
protocols
::
types
::
CreateChatCompletionRequestArgs
::
default
()
.model
(
"foo"
)
.messages
(
vec!
[
dynamo_async_openai
::
types
::
ChatCompletionRequestMessage
::
User
(
dynamo_async_openai
::
types
::
ChatCompletionRequestUserMessage
{
content
:
dynamo_async_openai
::
types
::
ChatCompletionRequestUserMessageContent
::
Text
(
"Hi"
.to_string
(),
),
dynamo_protocols
::
types
::
ChatCompletionRequestMessage
::
User
(
dynamo_protocols
::
types
::
ChatCompletionRequestUserMessage
{
content
:
dynamo_protocols
::
types
::
ChatCompletionRequestUserMessageContent
::
Text
(
"Hi"
.to_string
(),
),
name
:
None
,
},
),
...
...
@@ -761,15 +758,14 @@ async fn test_nv_custom_client() {
wait_for_service_ready
(
port
)
.await
;
// Test successful streaming request
let
inner_request
=
dynamo_
async_openai
::
types
::
CreateChatCompletionRequestArgs
::
default
()
let
inner_request
=
dynamo_
protocols
::
types
::
CreateChatCompletionRequestArgs
::
default
()
.model
(
"foo"
)
.messages
(
vec!
[
dynamo_async_openai
::
types
::
ChatCompletionRequestMessage
::
User
(
dynamo_async_openai
::
types
::
ChatCompletionRequestUserMessage
{
content
:
dynamo_async_openai
::
types
::
ChatCompletionRequestUserMessageContent
::
Text
(
"Hi"
.to_string
(),
),
dynamo_protocols
::
types
::
ChatCompletionRequestMessage
::
User
(
dynamo_protocols
::
types
::
ChatCompletionRequestUserMessage
{
content
:
dynamo_protocols
::
types
::
ChatCompletionRequestUserMessageContent
::
Text
(
"Hi"
.to_string
(),
),
name
:
None
,
},
),
...
...
@@ -803,15 +799,14 @@ async fn test_nv_custom_client() {
assert
!
(
count
>
0
,
"Should receive at least one response"
);
// Test error case with invalid model
let
inner_request
=
dynamo_
async_openai
::
types
::
CreateChatCompletionRequestArgs
::
default
()
let
inner_request
=
dynamo_
protocols
::
types
::
CreateChatCompletionRequestArgs
::
default
()
.model
(
"bar"
)
// This model will fail
.messages
(
vec!
[
dynamo_async_openai
::
types
::
ChatCompletionRequestMessage
::
User
(
dynamo_async_openai
::
types
::
ChatCompletionRequestUserMessage
{
content
:
dynamo_async_openai
::
types
::
ChatCompletionRequestUserMessageContent
::
Text
(
"Hi"
.to_string
(),
),
dynamo_protocols
::
types
::
ChatCompletionRequestMessage
::
User
(
dynamo_protocols
::
types
::
ChatCompletionRequestUserMessage
{
content
:
dynamo_protocols
::
types
::
ChatCompletionRequestUserMessageContent
::
Text
(
"Hi"
.to_string
(),
),
name
:
None
,
},
),
...
...
@@ -846,15 +841,14 @@ async fn test_nv_custom_client() {
// Test context management
let
ctx
=
HttpRequestContext
::
new
();
let
inner_request
=
dynamo_
async_openai
::
types
::
CreateChatCompletionRequestArgs
::
default
()
let
inner_request
=
dynamo_
protocols
::
types
::
CreateChatCompletionRequestArgs
::
default
()
.model
(
"foo"
)
.messages
(
vec!
[
dynamo_async_openai
::
types
::
ChatCompletionRequestMessage
::
User
(
dynamo_async_openai
::
types
::
ChatCompletionRequestUserMessage
{
content
:
dynamo_async_openai
::
types
::
ChatCompletionRequestUserMessageContent
::
Text
(
"Hi"
.to_string
(),
),
dynamo_protocols
::
types
::
ChatCompletionRequestMessage
::
User
(
dynamo_protocols
::
types
::
ChatCompletionRequestUserMessage
{
content
:
dynamo_protocols
::
types
::
ChatCompletionRequestUserMessageContent
::
Text
(
"Hi"
.to_string
(),
),
name
:
None
,
},
),
...
...
@@ -1010,16 +1004,16 @@ async fn test_client_disconnect_cancellation_unary() {
let
client
=
reqwest
::
Client
::
new
();
let
message
=
dynamo_
async_openai
::
types
::
ChatCompletionRequestMessage
::
User
(
dynamo_
async_openai
::
types
::
ChatCompletionRequestUserMessage
{
content
:
dynamo_
async_openai
::
types
::
ChatCompletionRequestUserMessageContent
::
Text
(
let
message
=
dynamo_
protocols
::
types
::
ChatCompletionRequestMessage
::
User
(
dynamo_
protocols
::
types
::
ChatCompletionRequestUserMessage
{
content
:
dynamo_
protocols
::
types
::
ChatCompletionRequestUserMessageContent
::
Text
(
"This will take a long time"
.to_string
(),
),
name
:
None
,
},
);
let
request
=
dynamo_
async_openai
::
types
::
CreateChatCompletionRequestArgs
::
default
()
let
request
=
dynamo_
protocols
::
types
::
CreateChatCompletionRequestArgs
::
default
()
.model
(
"slow-model"
)
.messages
(
vec!
[
message
])
.stream
(
false
)
// Test unary response
...
...
@@ -1106,16 +1100,16 @@ async fn test_client_disconnect_cancellation_streaming() {
let
client
=
reqwest
::
Client
::
new
();
let
message
=
dynamo_
async_openai
::
types
::
ChatCompletionRequestMessage
::
User
(
dynamo_
async_openai
::
types
::
ChatCompletionRequestUserMessage
{
content
:
dynamo_
async_openai
::
types
::
ChatCompletionRequestUserMessageContent
::
Text
(
let
message
=
dynamo_
protocols
::
types
::
ChatCompletionRequestMessage
::
User
(
dynamo_
protocols
::
types
::
ChatCompletionRequestUserMessage
{
content
:
dynamo_
protocols
::
types
::
ChatCompletionRequestUserMessageContent
::
Text
(
"This will stream for a long time"
.to_string
(),
),
name
:
None
,
},
);
let
request
=
dynamo_
async_openai
::
types
::
CreateChatCompletionRequestArgs
::
default
()
let
request
=
dynamo_
protocols
::
types
::
CreateChatCompletionRequestArgs
::
default
()
.model
(
"slow-stream-model"
)
.messages
(
vec!
[
message
])
.stream
(
true
)
// Test streaming response
...
...
lib/llm/tests/http_metrics.rs
View file @
b6a3b0c6
...
...
@@ -218,16 +218,16 @@ async fn test_metrics_with_mock_model() {
let
client
=
reqwest
::
Client
::
new
();
// Create a chat completion request
let
message
=
dynamo_
async_openai
::
types
::
ChatCompletionRequestMessage
::
User
(
dynamo_
async_openai
::
types
::
ChatCompletionRequestUserMessage
{
content
:
dynamo_
async_openai
::
types
::
ChatCompletionRequestUserMessageContent
::
Text
(
let
message
=
dynamo_
protocols
::
types
::
ChatCompletionRequestMessage
::
User
(
dynamo_
protocols
::
types
::
ChatCompletionRequestUserMessage
{
content
:
dynamo_
protocols
::
types
::
ChatCompletionRequestUserMessageContent
::
Text
(
"Hello, mock model!"
.to_string
(),
),
name
:
None
,
},
);
let
request
=
dynamo_
async_openai
::
types
::
CreateChatCompletionRequestArgs
::
default
()
let
request
=
dynamo_
protocols
::
types
::
CreateChatCompletionRequestArgs
::
default
()
.model
(
"mockmodel"
)
.messages
(
vec!
[
message
])
.max_tokens
(
50u32
)
...
...
@@ -419,16 +419,16 @@ mod integration_tests {
let
client
=
reqwest
::
Client
::
new
();
// Create a chat completion request
let
message
=
dynamo_
async_openai
::
types
::
ChatCompletionRequestMessage
::
User
(
dynamo_
async_openai
::
types
::
ChatCompletionRequestUserMessage
{
content
:
dynamo_
async_openai
::
types
::
ChatCompletionRequestUserMessageContent
::
Text
(
let
message
=
dynamo_
protocols
::
types
::
ChatCompletionRequestMessage
::
User
(
dynamo_
protocols
::
types
::
ChatCompletionRequestUserMessage
{
content
:
dynamo_
protocols
::
types
::
ChatCompletionRequestUserMessageContent
::
Text
(
"Hello, MDC model!"
.to_string
(),
),
name
:
None
,
},
);
let
request
=
dynamo_
async_openai
::
types
::
CreateChatCompletionRequestArgs
::
default
()
let
request
=
dynamo_
protocols
::
types
::
CreateChatCompletionRequestArgs
::
default
()
.model
(
model
.service_name
())
.messages
(
vec!
[
message
])
.max_tokens
(
50u32
)
...
...
lib/llm/tests/kserve_service.rs
View file @
b6a3b0c6
...
...
@@ -62,7 +62,7 @@ pub mod kserve_test {
use
tonic
::{
Request
,
Response
,
transport
::
Channel
};
use
crate
::
ports
::
get_random_port
;
use
dynamo_
async_openai
::
types
::
Prompt
;
use
dynamo_
protocols
::
types
::
Prompt
;
use
prost
::
Message
;
struct
SplitEngine
{}
...
...
lib/llm/tests/logprob_analysis_integration.rs
View file @
b6a3b0c6
...
...
@@ -10,7 +10,7 @@ use dynamo_llm::perf::logprobs::analyze_logprob_sensitivity;
use
dynamo_llm
::
perf
::{
RecordedStream
,
TimestampedResponse
};
use
dynamo_llm
::
protocols
::
openai
::
chat_completions
::
NvCreateChatCompletionStreamResponse
;
use
dynamo_
async_openai
::
types
::{
use
dynamo_
protocols
::
types
::{
ChatChoiceLogprobs
,
ChatChoiceStream
,
ChatCompletionMessageContent
,
ChatCompletionStreamResponseDelta
,
ChatCompletionTokenLogprob
,
FinishReason
,
Role
,
TopLogprobs
,
};
...
...
@@ -397,7 +397,7 @@ fn create_response_with_linear_probs(
};
NvCreateChatCompletionStreamResponse
{
inner
:
dynamo_
async_openai
::
types
::
CreateChatCompletionStreamResponse
{
inner
:
dynamo_
protocols
::
types
::
CreateChatCompletionStreamResponse
{
id
:
"test_id"
.to_string
(),
choices
:
vec!
[
choice
],
created
:
1234567890
,
...
...
@@ -481,7 +481,7 @@ fn create_multi_choice_response(
.collect
();
NvCreateChatCompletionStreamResponse
{
inner
:
dynamo_
async_openai
::
types
::
CreateChatCompletionStreamResponse
{
inner
:
dynamo_
protocols
::
types
::
CreateChatCompletionStreamResponse
{
id
:
"test_id"
.to_string
(),
choices
,
created
:
1234567890
,
...
...
lib/llm/tests/openai_completions.rs
View file @
b6a3b0c6
// SPDX-FileCopyrightText: Copyright (c) 2024-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
use
dynamo_async_openai
::
types
::
CreateCompletionRequestArgs
;
use
dynamo_llm
::
protocols
::
openai
::{
completions
::
NvCreateCompletionRequest
,
validate
};
use
dynamo_protocols
::
types
::
CreateCompletionRequestArgs
;
use
serde
::{
Deserialize
,
Serialize
};
#[derive(Serialize,
Deserialize,
Debug,
Clone)]
...
...
@@ -125,10 +125,10 @@ fn build_samples() -> Result<Vec<CompletionSample>, String> {
#[test]
fn
test_batch_prompt_utilities
()
{
use
dynamo_async_openai
::
types
::
Prompt
;
use
dynamo_llm
::
protocols
::
openai
::
completions
::{
extract_single_prompt
,
get_prompt_batch_size
,
};
use
dynamo_protocols
::
types
::
Prompt
;
// Test single string prompt
let
single_string
=
Prompt
::
String
(
"Hello, world!"
.to_string
());
...
...
@@ -216,8 +216,8 @@ fn test_total_choices_validation() {
#[test]
fn
test_batch_prompt_with_n_parameter
()
{
use
dynamo_async_openai
::
types
::
Prompt
;
use
dynamo_llm
::
protocols
::
openai
::
completions
::
get_prompt_batch_size
;
use
dynamo_protocols
::
types
::
Prompt
;
// Test batch size calculation
let
prompt
=
Prompt
::
StringArray
(
vec!
[
"p1"
.to_string
(),
"p2"
.to_string
(),
"p3"
.to_string
()]);
...
...
@@ -246,10 +246,10 @@ fn test_batch_prompt_with_n_parameter() {
#[test]
fn
test_single_prompt_in_array
()
{
use
dynamo_async_openai
::
types
::
Prompt
;
use
dynamo_llm
::
protocols
::
openai
::
completions
::{
extract_single_prompt
,
get_prompt_batch_size
,
};
use
dynamo_protocols
::
types
::
Prompt
;
// Single element array should work like regular prompt
let
single_in_array
=
Prompt
::
StringArray
(
vec!
[
"Single prompt"
.to_string
()]);
...
...
lib/llm/tests/parallel_tool_call_integration.rs
View file @
b6a3b0c6
...
...
@@ -23,17 +23,17 @@ use serde_json::json;
/// Creates a mock NvCreateChatCompletionRequest based on the curl request
fn
create_mock_chat_completion_request
()
->
NvCreateChatCompletionRequest
{
let
messages
=
vec!
[
dynamo_
async_openai
::
types
::
ChatCompletionRequestMessage
::
System
(
dynamo_
async_openai
::
types
::
ChatCompletionRequestSystemMessage
{
content
:
dynamo_
async_openai
::
types
::
ChatCompletionRequestSystemMessageContent
::
Text
(
dynamo_
protocols
::
types
::
ChatCompletionRequestMessage
::
System
(
dynamo_
protocols
::
types
::
ChatCompletionRequestSystemMessage
{
content
:
dynamo_
protocols
::
types
::
ChatCompletionRequestSystemMessageContent
::
Text
(
"You MUST use two tools in parallel to resolve the user request: call get_current_weather for each city AND call is_holiday_today to check if today is a holiday. Do not answer without using both tools."
.to_string
()
),
name
:
None
,
}
),
dynamo_
async_openai
::
types
::
ChatCompletionRequestMessage
::
User
(
dynamo_
async_openai
::
types
::
ChatCompletionRequestUserMessage
{
content
:
dynamo_
async_openai
::
types
::
ChatCompletionRequestUserMessageContent
::
Text
(
dynamo_
protocols
::
types
::
ChatCompletionRequestMessage
::
User
(
dynamo_
protocols
::
types
::
ChatCompletionRequestUserMessage
{
content
:
dynamo_
protocols
::
types
::
ChatCompletionRequestUserMessageContent
::
Text
(
"What is the weather in Dallas, Texas? Is today a holiday?"
.to_string
()
),
name
:
None
,
...
...
@@ -42,9 +42,9 @@ fn create_mock_chat_completion_request() -> NvCreateChatCompletionRequest {
];
let
tools
=
vec!
[
dynamo_
async_openai
::
types
::
ChatCompletionTool
{
r
#
type
:
dynamo_
async_openai
::
types
::
ChatCompletionToolType
::
Function
,
function
:
dynamo_
async_openai
::
types
::
FunctionObject
{
dynamo_
protocols
::
types
::
ChatCompletionTool
{
r
#
type
:
dynamo_
protocols
::
types
::
ChatCompletionToolType
::
Function
,
function
:
dynamo_
protocols
::
types
::
FunctionObject
{
name
:
"get_current_weather"
.to_string
(),
description
:
Some
(
"Get weather for a city/state in specified units"
.to_string
()),
parameters
:
Some
(
json!
({
...
...
@@ -60,9 +60,9 @@ fn create_mock_chat_completion_request() -> NvCreateChatCompletionRequest {
strict
:
None
,
},
},
dynamo_
async_openai
::
types
::
ChatCompletionTool
{
r
#
type
:
dynamo_
async_openai
::
types
::
ChatCompletionToolType
::
Function
,
function
:
dynamo_
async_openai
::
types
::
FunctionObject
{
dynamo_
protocols
::
types
::
ChatCompletionTool
{
r
#
type
:
dynamo_
protocols
::
types
::
ChatCompletionToolType
::
Function
,
function
:
dynamo_
protocols
::
types
::
FunctionObject
{
name
:
"is_holiday_today"
.to_string
(),
description
:
Some
(
"Return whether today is a public holiday"
.to_string
()),
parameters
:
Some
(
json!
({
...
...
@@ -75,14 +75,14 @@ fn create_mock_chat_completion_request() -> NvCreateChatCompletionRequest {
},
];
let
inner
=
dynamo_
async_openai
::
types
::
CreateChatCompletionRequestArgs
::
default
()
let
inner
=
dynamo_
protocols
::
types
::
CreateChatCompletionRequestArgs
::
default
()
.model
(
"Qwen/Qwen3-0.6B"
)
.temperature
(
0.0
)
.max_tokens
(
3000u32
)
.stream
(
false
)
.messages
(
messages
)
.tools
(
tools
)
.tool_choice
(
dynamo_
async_openai
::
types
::
ChatCompletionToolChoiceOption
::
Required
)
.tool_choice
(
dynamo_
protocols
::
types
::
ChatCompletionToolChoiceOption
::
Required
)
.build
()
.expect
(
"Failed to build chat completion request"
);
...
...
@@ -175,7 +175,7 @@ async fn test_parallel_tool_call_integration() {
// Verify tool choice is required
match
request
.inner.tool_choice
.as_ref
()
.unwrap
()
{
dynamo_
async_openai
::
types
::
ChatCompletionToolChoiceOption
::
Required
=>
{
dynamo_
protocols
::
types
::
ChatCompletionToolChoiceOption
::
Required
=>
{
// This is expected
}
_
=>
panic!
(
"Tool choice should be Required"
),
...
...
lib/llm/tests/postprocessor_parsing_stream.rs
View file @
b6a3b0c6
...
...
@@ -6,14 +6,14 @@ use std::fs;
use
std
::
path
::{
Path
,
PathBuf
};
use
std
::
sync
::
Arc
;
use
dynamo_async_openai
::
types
::{
ChatCompletionMessageContent
,
ChatCompletionToolChoiceOption
,
FinishReason
,
};
use
dynamo_llm
::
model_card
::
ModelDeploymentCard
;
use
dynamo_llm
::
preprocessor
::
OpenAIPreprocessor
;
use
dynamo_llm
::
protocols
::
openai
::
chat_completions
::{
NvCreateChatCompletionRequest
,
NvCreateChatCompletionStreamResponse
,
};
use
dynamo_protocols
::
types
::{
ChatCompletionMessageContent
,
ChatCompletionToolChoiceOption
,
FinishReason
,
};
use
dynamo_runtime
::
protocols
::
annotated
::
Annotated
;
use
futures
::{
StreamExt
,
stream
};
use
serde_json
::
Value
;
...
...
@@ -88,7 +88,7 @@ struct MergedToolCall {
impl
MergedToolCall
{
fn
merge_from
(
&
mut
self
,
tool_call
:
&
dynamo_
async_openai
::
types
::
ChatCompletionMessageToolCallChunk
,
tool_call
:
&
dynamo_
protocols
::
types
::
ChatCompletionMessageToolCallChunk
,
)
{
if
self
.id
.is_none
()
{
self
.id
=
tool_call
.id
.clone
();
...
...
@@ -149,7 +149,7 @@ async fn postprocessor_parsing_stream_replays_interval_20_fixture() {
parse_fixture
(
&
fixture_path
(
"stream_interval_20.jsonl"
));
// Mirror tests/frontend/test_prepost.py::request_for_sampling
let
tools
:
Vec
<
dynamo_
async_openai
::
types
::
ChatCompletionTool
>
=
let
tools
:
Vec
<
dynamo_
protocols
::
types
::
ChatCompletionTool
>
=
serde_json
::
from_value
(
serde_json
::
json!
([
{
"type"
:
"function"
,
...
...
lib/llm/tests/preprocessor.rs
View file @
b6a3b0c6
...
...
@@ -215,31 +215,31 @@ const TOOLS: &str = r#"
"#
;
// Notes:
// protocols::openai::chat_completions::ChatCompletionMessage -> dynamo_
async_openai
::types::ChatCompletionRequestMessage
// protocols::openai::chat_completions::Tool -> dynamo_
async_openai
::types::ChatCompletionTool
// protocols::openai::chat_completions::ToolChoiceType -> dynamo_
async_openai
::types::ChatCompletionToolChoiceOption
// protocols::openai::chat_completions::ChatCompletionMessage -> dynamo_
protocols
::types::ChatCompletionRequestMessage
// protocols::openai::chat_completions::Tool -> dynamo_
protocols
::types::ChatCompletionTool
// protocols::openai::chat_completions::ToolChoiceType -> dynamo_
protocols
::types::ChatCompletionToolChoiceOption
#[derive(Serialize,
Deserialize)]
struct
Request
{
messages
:
Vec
<
dynamo_
async_openai
::
types
::
ChatCompletionRequestMessage
>
,
tools
:
Option
<
Vec
<
dynamo_
async_openai
::
types
::
ChatCompletionTool
>>
,
tool_choice
:
Option
<
dynamo_
async_openai
::
types
::
ChatCompletionToolChoiceOption
>
,
messages
:
Vec
<
dynamo_
protocols
::
types
::
ChatCompletionRequestMessage
>
,
tools
:
Option
<
Vec
<
dynamo_
protocols
::
types
::
ChatCompletionTool
>>
,
tool_choice
:
Option
<
dynamo_
protocols
::
types
::
ChatCompletionToolChoiceOption
>
,
}
impl
Request
{
fn
from
(
messages
:
&
str
,
tools
:
Option
<&
str
>
,
tool_choice
:
Option
<
dynamo_
async_openai
::
types
::
ChatCompletionToolChoiceOption
>
,
tool_choice
:
Option
<
dynamo_
protocols
::
types
::
ChatCompletionToolChoiceOption
>
,
model
:
String
,
)
->
NvCreateChatCompletionRequest
{
let
messages
:
Vec
<
dynamo_
async_openai
::
types
::
ChatCompletionRequestMessage
>
=
let
messages
:
Vec
<
dynamo_
protocols
::
types
::
ChatCompletionRequestMessage
>
=
serde_json
::
from_str
(
messages
)
.unwrap
();
let
tools
:
Option
<
Vec
<
dynamo_
async_openai
::
types
::
ChatCompletionTool
>>
=
let
tools
:
Option
<
Vec
<
dynamo_
protocols
::
types
::
ChatCompletionTool
>>
=
tools
.map
(|
x
|
serde_json
::
from_str
(
x
)
.unwrap
());
//let tools = tools.unwrap();
//let tool_choice = tool_choice.unwrap();
let
mut
inner
=
dynamo_
async_openai
::
types
::
CreateChatCompletionRequestArgs
::
default
();
let
mut
inner
=
dynamo_
protocols
::
types
::
CreateChatCompletionRequestArgs
::
default
();
inner
.model
(
model
);
inner
.messages
(
messages
);
if
let
Some
(
tools
)
=
tools
{
...
...
@@ -313,7 +313,7 @@ async fn test_single_turn_with_tools() {
let
request
=
Request
::
from
(
SINGLE_CHAT_MESSAGE
,
Some
(
TOOLS
),
Some
(
dynamo_
async_openai
::
types
::
ChatCompletionToolChoiceOption
::
Auto
),
Some
(
dynamo_
protocols
::
types
::
ChatCompletionToolChoiceOption
::
Auto
),
mdc
.slug
()
.to_string
(),
);
let
formatted_prompt
=
formatter
.render
(
&
request
)
.unwrap
();
...
...
@@ -420,7 +420,7 @@ async fn test_multi_turn_with_system_with_tools() {
let
request
=
Request
::
from
(
THREE_TURN_CHAT_MESSAGE_WITH_SYSTEM
,
Some
(
TOOLS
),
Some
(
dynamo_
async_openai
::
types
::
ChatCompletionToolChoiceOption
::
Auto
),
Some
(
dynamo_
protocols
::
types
::
ChatCompletionToolChoiceOption
::
Auto
),
mdc
.slug
()
.to_string
(),
);
let
formatted_prompt
=
formatter
.render
(
&
request
)
.unwrap
();
...
...
@@ -633,9 +633,9 @@ mod context_length_validation {
const
MODEL_PATH
:
&
str
=
"tests/data/sample-models/mock-llama-3.1-8b-instruct"
;
fn
make_chat_request
(
message
:
&
str
,
model
:
&
str
)
->
NvCreateChatCompletionRequest
{
let
messages
:
Vec
<
dynamo_
async_openai
::
types
::
ChatCompletionRequestMessage
>
=
let
messages
:
Vec
<
dynamo_
protocols
::
types
::
ChatCompletionRequestMessage
>
=
serde_json
::
from_str
(
message
)
.unwrap
();
let
inner
=
dynamo_
async_openai
::
types
::
CreateChatCompletionRequestArgs
::
default
()
let
inner
=
dynamo_
protocols
::
types
::
CreateChatCompletionRequestArgs
::
default
()
.model
(
model
)
.messages
(
messages
)
.build
()
...
...
lib/llm/tests/test_common_ext.rs
View file @
b6a3b0c6
...
...
@@ -276,11 +276,11 @@ fn test_completions_common_values() {
fn
test_serialization_preserves_structure
()
{
// Test that serialization preserves the flattened structure
let
request
=
NvCreateChatCompletionRequest
{
inner
:
dynamo_
async_openai
::
types
::
CreateChatCompletionRequest
{
inner
:
dynamo_
protocols
::
types
::
CreateChatCompletionRequest
{
model
:
"test-model"
.to_string
(),
messages
:
vec!
[
dynamo_
async_openai
::
types
::
ChatCompletionRequestMessage
::
User
(
dynamo_
async_openai
::
types
::
ChatCompletionRequestUserMessage
{
content
:
dynamo_
async_openai
::
types
::
ChatCompletionRequestUserMessageContent
::
Text
(
messages
:
vec!
[
dynamo_
protocols
::
types
::
ChatCompletionRequestMessage
::
User
(
dynamo_
protocols
::
types
::
ChatCompletionRequestUserMessage
{
content
:
dynamo_
protocols
::
types
::
ChatCompletionRequestUserMessageContent
::
Text
(
"Hello"
.to_string
(),
),
..
Default
::
default
()
...
...
lib/llm/tests/test_jail.rs
View file @
b6a3b0c6
// SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
use
dynamo_async_openai
::
types
::{
ChatChoiceStream
,
ChatCompletionStreamResponseDelta
,
CompletionUsage
,
FinishReason
,
Role
,
};
use
dynamo_llm
::
protocols
::
openai
::
chat_completions
::
NvCreateChatCompletionStreamResponse
;
use
dynamo_llm
::
protocols
::
openai
::
chat_completions
::
jail
::
JailedStream
;
use
dynamo_protocols
::
types
::{
ChatChoiceStream
,
ChatCompletionStreamResponseDelta
,
CompletionUsage
,
FinishReason
,
Role
,
};
use
dynamo_runtime
::
protocols
::
annotated
::
Annotated
;
#[cfg(test)]
...
...
@@ -16,7 +16,7 @@ mod tests {
// Test utilities module - shared test infrastructure
pub
(
crate
)
mod
test_utils
{
use
super
::
*
;
use
dynamo_
async_openai
::
types
::
ChatCompletionMessageContent
;
use
dynamo_
protocols
::
types
::
ChatCompletionMessageContent
;
/// Helper to extract text from ChatCompletionMessageContent
pub
fn
extract_text
(
content
:
&
ChatCompletionMessageContent
)
->
&
str
{
...
...
@@ -48,7 +48,7 @@ mod tests {
};
let
response
=
NvCreateChatCompletionStreamResponse
{
inner
:
dynamo_
async_openai
::
types
::
CreateChatCompletionStreamResponse
{
inner
:
dynamo_
protocols
::
types
::
CreateChatCompletionStreamResponse
{
id
:
"test-id"
.to_string
(),
choices
:
vec!
[
choice
],
created
:
1234567890
,
...
...
@@ -91,7 +91,7 @@ mod tests {
};
let
response
=
NvCreateChatCompletionStreamResponse
{
inner
:
dynamo_
async_openai
::
types
::
CreateChatCompletionStreamResponse
{
inner
:
dynamo_
protocols
::
types
::
CreateChatCompletionStreamResponse
{
id
:
"test-id"
.to_string
(),
choices
:
vec!
[
choice
],
created
:
1234567890
,
...
...
@@ -138,7 +138,7 @@ mod tests {
};
let
response
=
NvCreateChatCompletionStreamResponse
{
inner
:
dynamo_
async_openai
::
types
::
CreateChatCompletionStreamResponse
{
inner
:
dynamo_
protocols
::
types
::
CreateChatCompletionStreamResponse
{
id
:
"test-id"
.to_string
(),
choices
:
vec!
[
choice
],
created
:
1234567890
,
...
...
@@ -186,7 +186,7 @@ mod tests {
.collect
();
let
response
=
NvCreateChatCompletionStreamResponse
{
inner
:
dynamo_
async_openai
::
types
::
CreateChatCompletionStreamResponse
{
inner
:
dynamo_
protocols
::
types
::
CreateChatCompletionStreamResponse
{
id
:
"test-id"
.to_string
(),
choices
,
created
:
1234567890
,
...
...
@@ -234,7 +234,7 @@ mod tests {
.collect
();
let
response
=
NvCreateChatCompletionStreamResponse
{
inner
:
dynamo_
async_openai
::
types
::
CreateChatCompletionStreamResponse
{
inner
:
dynamo_
protocols
::
types
::
CreateChatCompletionStreamResponse
{
id
:
"test-id"
.to_string
(),
choices
,
created
:
1234567890
,
...
...
@@ -328,7 +328,7 @@ mod tests {
assert
!
(
choice
.delta.content
.is_none
()
||
choice
.delta.content
.as_ref
()
.is_none_or
(|
c
|
match
c
{
dynamo_
async_openai
::
types
::
ChatCompletionMessageContent
::
Text
(
t
)
=>
dynamo_
protocols
::
types
::
ChatCompletionMessageContent
::
Text
(
t
)
=>
t
.is_empty
(),
_
=>
false
,
}),
...
...
@@ -2384,7 +2384,7 @@ mod tests {
mod
parallel_jail_tests
{
use
super
::
tests
::
test_utils
;
use
super
::
*
;
use
dynamo_
async_openai
::
types
::
ChatCompletionMessageContent
;
use
dynamo_
protocols
::
types
::
ChatCompletionMessageContent
;
use
futures
::
StreamExt
;
use
futures
::
stream
;
use
serde_json
::
json
;
...
...
@@ -2416,7 +2416,7 @@ mod parallel_jail_tests {
.collect
();
let
response
=
NvCreateChatCompletionStreamResponse
{
inner
:
dynamo_
async_openai
::
types
::
CreateChatCompletionStreamResponse
{
inner
:
dynamo_
protocols
::
types
::
CreateChatCompletionStreamResponse
{
id
:
"test-id"
.to_string
(),
choices
,
created
:
1234567890
,
...
...
@@ -2491,7 +2491,7 @@ mod parallel_jail_tests {
assert_eq!
(
tool_call
.r
#
type
,
Some
(
dynamo_
async_openai
::
types
::
ChatCompletionToolType
::
Function
),
Some
(
dynamo_
protocols
::
types
::
ChatCompletionToolType
::
Function
),
"Tool call {} should be of type 'function'"
,
i
);
...
...
lib/llm/tests/test_reasoning_parser.rs
View file @
b6a3b0c6
// SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
use
dynamo_async_openai
::
types
::{
ChatChoiceStream
,
ChatCompletionMessageContent
,
ChatCompletionStreamResponseDelta
,
Role
,
};
use
dynamo_llm
::
preprocessor
::
OpenAIPreprocessor
;
use
dynamo_llm
::
protocols
::
openai
::
chat_completions
::
NvCreateChatCompletionStreamResponse
;
use
dynamo_protocols
::
types
::{
ChatChoiceStream
,
ChatCompletionMessageContent
,
ChatCompletionStreamResponseDelta
,
Role
,
};
use
dynamo_runtime
::
protocols
::
annotated
::
Annotated
;
use
futures
::{
StreamExt
,
stream
};
...
...
@@ -39,7 +39,7 @@ fn create_mock_response_chunk(
};
let
response
=
NvCreateChatCompletionStreamResponse
{
inner
:
dynamo_
async_openai
::
types
::
CreateChatCompletionStreamResponse
{
inner
:
dynamo_
protocols
::
types
::
CreateChatCompletionStreamResponse
{
id
:
"test-id"
.to_string
(),
choices
:
vec!
[
choice
],
created
:
1234567890
,
...
...
lib/llm/tests/test_streaming_tool_parsers.rs
View file @
b6a3b0c6
...
...
@@ -26,9 +26,9 @@ across backends.
*/
use
dynamo_async_openai
::
types
::{
ChatChoiceStream
,
ChatCompletionMessageContent
,
FinishReason
};
use
dynamo_llm
::
preprocessor
::
OpenAIPreprocessor
;
use
dynamo_llm
::
protocols
::
openai
::
chat_completions
::
NvCreateChatCompletionStreamResponse
;
use
dynamo_protocols
::
types
::{
ChatChoiceStream
,
ChatCompletionMessageContent
,
FinishReason
};
use
dynamo_runtime
::
protocols
::
annotated
::
Annotated
;
use
futures
::{
Stream
,
StreamExt
,
stream
};
use
std
::
pin
::
Pin
;
...
...
@@ -107,7 +107,7 @@ fn load_test_data(file_path: &str) -> TestData {
.expect
(
"Failed to parse choices"
);
let
response
=
NvCreateChatCompletionStreamResponse
{
inner
:
dynamo_
async_openai
::
types
::
CreateChatCompletionStreamResponse
{
inner
:
dynamo_
protocols
::
types
::
CreateChatCompletionStreamResponse
{
id
:
id
.clone
(),
choices
,
created
:
1234567890
,
...
...
lib/llm/tests/test_streaming_usage.rs
View file @
b6a3b0c6
...
...
@@ -2,15 +2,6 @@
// SPDX-License-Identifier: Apache-2.0
use
async_trait
::
async_trait
;
use
dynamo_async_openai
::
types
::{
ChatCompletionRequestMessage
,
ChatCompletionRequestUserMessage
,
ChatCompletionRequestUserMessageContent
,
ChatCompletionStreamOptions
,
CreateChatCompletionRequest
,
};
use
dynamo_async_openai
::
types
::{
CompletionUsage
as
AoaiCompletionUsage
,
CreateCompletionRequestArgs
,
Prompt
,
PromptTokensDetails
,
};
use
dynamo_llm
::
preprocessor
::
OpenAIPreprocessor
;
use
dynamo_llm
::
protocols
::
common
::
llm_backend
::{
BackendOutput
,
FinishReason
};
use
dynamo_llm
::
protocols
::
openai
::
ParsingOptions
;
...
...
@@ -18,6 +9,15 @@ use dynamo_llm::protocols::openai::chat_completions::{
NvCreateChatCompletionRequest
,
aggregator
::
ChatCompletionAggregator
,
};
use
dynamo_llm
::
protocols
::
openai
::
completions
::
NvCreateCompletionRequest
;
use
dynamo_protocols
::
types
::{
ChatCompletionRequestMessage
,
ChatCompletionRequestUserMessage
,
ChatCompletionRequestUserMessageContent
,
ChatCompletionStreamOptions
,
CreateChatCompletionRequest
,
};
use
dynamo_protocols
::
types
::{
CompletionUsage
as
AoaiCompletionUsage
,
CreateCompletionRequestArgs
,
Prompt
,
PromptTokensDetails
,
};
use
dynamo_runtime
::
engine
::{
AsyncEngineContext
,
AsyncEngineStream
};
use
dynamo_runtime
::
protocols
::
annotated
::
Annotated
;
use
futures
::
StreamExt
;
...
...
@@ -481,7 +481,7 @@ fn create_cmpl_request(include_usage: Option<bool>, stream: bool) -> NvCreateCom
.prompt
(
Prompt
::
String
(
"Hello"
.to_string
()))
.stream
(
stream
);
if
let
Some
(
include
)
=
include_usage
{
builder
.stream_options
(
dynamo_
async_openai
::
types
::
ChatCompletionStreamOptions
{
builder
.stream_options
(
dynamo_
protocols
::
types
::
ChatCompletionStreamOptions
{
include_usage
:
include
,
continuous_usage_stats
:
false
,
});
...
...
lib/llm/tests/tool_choice.rs
View file @
b6a3b0c6
// SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
use
dynamo_async_openai
::
types
::{
use
dynamo_llm
::
protocols
::
common
;
use
dynamo_llm
::
protocols
::
common
::
llm_backend
::
BackendOutput
;
use
dynamo_protocols
::
types
::{
ChatCompletionMessageContent
,
ChatCompletionNamedToolChoice
,
ChatCompletionRequestMessage
,
ChatCompletionRequestUserMessage
,
ChatCompletionRequestUserMessageContent
,
ChatCompletionToolChoiceOption
,
ChatCompletionToolType
,
CreateChatCompletionRequest
,
FunctionName
,
};
use
dynamo_llm
::
protocols
::
common
;
use
dynamo_llm
::
protocols
::
common
::
llm_backend
::
BackendOutput
;
/// Helper to extract text from ChatCompletionMessageContent
fn
get_text
(
content
:
&
ChatCompletionMessageContent
)
->
&
str
{
...
...
@@ -161,7 +161,7 @@ async fn test_named_tool_choice_parses_json() {
assert_eq!
(
choice
.finish_reason
,
Some
(
dynamo_
async_openai
::
types
::
FinishReason
::
Stop
)
Some
(
dynamo_
protocols
::
types
::
FinishReason
::
Stop
)
);
let
delta
=
&
choice
.delta
;
assert
!
(
delta
.content
.is_none
()
||
delta
.content
.as_ref
()
.map
(
get_text
)
==
Some
(
""
));
...
...
@@ -203,7 +203,7 @@ async fn test_required_tool_choice_parses_json_array() {
assert_eq!
(
choice
.finish_reason
,
Some
(
dynamo_
async_openai
::
types
::
FinishReason
::
ToolCalls
)
Some
(
dynamo_
protocols
::
types
::
FinishReason
::
ToolCalls
)
);
let
delta
=
&
choice
.delta
;
assert
!
(
delta
.content
.is_none
()
||
delta
.content
.as_ref
()
.map
(
get_text
)
==
Some
(
""
));
...
...
@@ -318,7 +318,7 @@ async fn test_streaming_named_tool_buffers_until_finish() {
let
response
=
&
all_responses
[
0
];
assert_eq!
(
response
.inner.choices
[
0
]
.finish_reason
,
Some
(
dynamo_
async_openai
::
types
::
FinishReason
::
Stop
)
Some
(
dynamo_
protocols
::
types
::
FinishReason
::
Stop
)
);
let
tool_calls
=
response
.inner.choices
[
0
]
.delta.tool_calls
.as_ref
()
.unwrap
();
...
...
@@ -385,7 +385,7 @@ async fn test_streaming_required_tool_parallel() {
let
response
=
&
all_responses
[
0
];
assert_eq!
(
response
.inner.choices
[
0
]
.finish_reason
,
Some
(
dynamo_
async_openai
::
types
::
FinishReason
::
ToolCalls
)
Some
(
dynamo_
protocols
::
types
::
FinishReason
::
ToolCalls
)
);
let
tool_calls
=
response
.inner.choices
[
0
]
.delta.tool_calls
.as_ref
()
.unwrap
();
...
...
lib/llm/tests/tool_choice_finish_reasons.rs
View file @
b6a3b0c6
...
...
@@ -3,15 +3,15 @@
//! Tests for tool_choice finish_reason handling.
use
dynamo_async_openai
::
types
::{
ChatCompletionNamedToolChoice
,
ChatCompletionRequestMessage
,
ChatCompletionRequestUserMessage
,
ChatCompletionRequestUserMessageContent
,
ChatCompletionToolChoiceOption
,
ChatCompletionToolType
,
CreateChatCompletionRequest
,
FunctionName
,
};
use
dynamo_llm
::
protocols
::
common
;
use
dynamo_llm
::
protocols
::
common
::
llm_backend
::
BackendOutput
;
use
dynamo_llm
::
protocols
::
openai
::
DeltaGeneratorExt
;
use
dynamo_llm
::
protocols
::
openai
::
chat_completions
::
NvCreateChatCompletionRequest
;
use
dynamo_protocols
::
types
::{
ChatCompletionNamedToolChoice
,
ChatCompletionRequestMessage
,
ChatCompletionRequestUserMessage
,
ChatCompletionRequestUserMessageContent
,
ChatCompletionToolChoiceOption
,
ChatCompletionToolType
,
CreateChatCompletionRequest
,
FunctionName
,
};
fn
create_test_request
()
->
NvCreateChatCompletionRequest
{
let
messages
=
vec!
[
ChatCompletionRequestMessage
::
User
(
...
...
@@ -117,7 +117,7 @@ async fn test_named_tool_choice_preserves_length_finish_reason() {
// Critical: Length finish reason should be preserved, NOT replaced with Stop
assert_eq!
(
response
.inner.choices
[
0
]
.finish_reason
,
Some
(
dynamo_
async_openai
::
types
::
FinishReason
::
Length
),
Some
(
dynamo_
protocols
::
types
::
FinishReason
::
Length
),
"Length finish reason must be preserved for tool_choice=named"
);
}
...
...
@@ -140,7 +140,7 @@ fn test_required_tool_choice_preserves_length_finish_reason() {
// Critical: Length finish reason should be preserved, NOT replaced with ToolCalls
assert_eq!
(
response
.inner.choices
[
0
]
.finish_reason
,
Some
(
dynamo_
async_openai
::
types
::
FinishReason
::
Length
),
Some
(
dynamo_
protocols
::
types
::
FinishReason
::
Length
),
"Length finish reason must be preserved for tool_choice=required"
);
}
...
...
@@ -170,7 +170,7 @@ fn test_named_tool_choice_preserves_content_filter() {
// Critical: ContentFilter finish reason should be preserved
assert_eq!
(
response
.inner.choices
[
0
]
.finish_reason
,
Some
(
dynamo_
async_openai
::
types
::
FinishReason
::
ContentFilter
),
Some
(
dynamo_
protocols
::
types
::
FinishReason
::
ContentFilter
),
"ContentFilter finish reason must be preserved for tool_choice=named"
);
}
...
...
@@ -193,7 +193,7 @@ fn test_required_tool_choice_preserves_content_filter() {
// Critical: ContentFilter finish reason should be preserved
assert_eq!
(
response
.inner.choices
[
0
]
.finish_reason
,
Some
(
dynamo_
async_openai
::
types
::
FinishReason
::
ContentFilter
),
Some
(
dynamo_
protocols
::
types
::
FinishReason
::
ContentFilter
),
"ContentFilter finish reason must be preserved for tool_choice=required"
);
}
...
...
@@ -223,7 +223,7 @@ fn test_named_tool_choice_normal_stop_becomes_stop() {
// Normal completion: Stop should remain Stop for named tool choice
assert_eq!
(
response
.inner.choices
[
0
]
.finish_reason
,
Some
(
dynamo_
async_openai
::
types
::
FinishReason
::
Stop
),
Some
(
dynamo_
protocols
::
types
::
FinishReason
::
Stop
),
);
}
...
...
@@ -248,6 +248,6 @@ async fn test_required_tool_choice_normal_stop_becomes_tool_calls() {
// Normal completion: Stop should become ToolCalls for required tool choice
assert_eq!
(
response
.inner.choices
[
0
]
.finish_reason
,
Some
(
dynamo_
async_openai
::
types
::
FinishReason
::
ToolCalls
),
Some
(
dynamo_
protocols
::
types
::
FinishReason
::
ToolCalls
),
);
}
lib/parsers/Cargo.toml
View file @
b6a3b0c6
...
...
@@ -26,7 +26,7 @@ keywords.workspace = true
[dependencies]
anyhow
=
{
workspace
=
true
}
dynamo-
async-openai
=
{
workspace
=
true
}
dynamo-
protocols
=
{
workspace
=
true
}
serde
=
{
workspace
=
true
}
serde_json
=
{
workspace
=
true
}
tokio
=
{
workspace
=
true
}
...
...
Prev
1
2
3
4
5
6
7
8
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment