Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 11 additions & 3 deletions lib/llm/src/grpc/service/kserve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,9 @@ impl GrpcTuningConfig {

use crate::grpc::service::dispatch_error_status;
use crate::grpc::service::openai::completion_response_stream;
use crate::grpc::service::tensor::{ExtendedNvCreateTensorResponse, tensor_response_stream};
use crate::grpc::service::tensor::{
ExtendedNvCreateTensorResponse, kserve_metadata_shape, tensor_response_stream,
};
use std::convert::{TryFrom, TryInto};
use tonic::{Request, Response, Status, transport::Server};

Expand Down Expand Up @@ -686,7 +688,10 @@ impl GrpcInferenceService for KserveService {
.and_then(|dt| dt.oip_name())
.unwrap_or("TYPE_INVALID")
.to_string(),
shape: input.dims.clone(),
shape: kserve_metadata_shape(
&input.dims,
model_config.max_batch_size,
),
})
.collect(),
outputs: model_config
Expand All @@ -700,7 +705,10 @@ impl GrpcInferenceService for KserveService {
.and_then(|dt| dt.oip_name())
.unwrap_or("TYPE_INVALID")
.to_string(),
shape: output.dims.clone(),
shape: kserve_metadata_shape(
&output.dims,
model_config.max_batch_size,
),
},
)
.collect(),
Expand Down
33 changes: 33 additions & 0 deletions lib/llm/src/grpc/service/tensor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -854,6 +854,20 @@ impl DataType {
}
}

/// KServe v2 `ModelMetadata` wire shape for a Triton tensor.
///
/// Triton's `ModelConfig` stores per-tensor `dims` without the batch dimension.
/// When `max_batch_size > 0`, native Triton's KServe adapter prepends `-1`
/// (variable batch) so clients can send batched inputs. Copying `dims`
/// verbatim drops that axis and KServe v2 clients reject the tensor.
pub fn kserve_metadata_shape(dims: &[i64], max_batch_size: i32) -> Vec<i64> {
if max_batch_size > 0 {
std::iter::once(-1).chain(dims.iter().copied()).collect()
} else {
dims.to_vec()
}
}

impl std::fmt::Display for tensor::DataType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match *self {
Expand Down Expand Up @@ -1222,3 +1236,22 @@ mod oip_datatype_tests {
}
}
}

#[cfg(test)]
mod kserve_metadata_shape_tests {
use super::kserve_metadata_shape;

#[test]
fn prepends_variable_batch_dim_when_batching_enabled() {
assert_eq!(kserve_metadata_shape(&[-1], 4), vec![-1, -1]);
assert_eq!(kserve_metadata_shape(&[768], 8), vec![-1, 768]);
assert_eq!(kserve_metadata_shape(&[], 1), vec![-1]);
}

#[test]
fn leaves_dims_unchanged_when_batching_disabled() {
assert_eq!(kserve_metadata_shape(&[-1], 0), vec![-1]);
assert_eq!(kserve_metadata_shape(&[3, 224, 224], 0), vec![3, 224, 224]);
assert_eq!(kserve_metadata_shape(&[], 0), Vec::<i64>::new());
}
}
Loading