use dynamo_mocker::sglang::{LogprobOptions, ResponseMetadata};
use dynamo_runtime::error::{DynamoError, ErrorType};
use serde::Deserialize;
use serde_json::{Value, json};
use crate::protocols::common::FinishReason;
use crate::protocols::common::llm_backend::{LLMEngineOutput, PreprocessedRequest};
const PAYLOAD_KEY: &str = "sglang_tito";
#[derive(Deserialize)]
struct NativeControls {
rid: Option<String>,
return_logprob: Option<bool>,
top_logprobs_num: Option<i64>,
logprob_start_len: Option<i64>,
}
pub(super) fn response_metadata(
request: &PreprocessedRequest,
fallback_request_id: &str,
) -> Result<Option<ResponseMetadata>, DynamoError> {
let Some(payload) = request
.extra_args
.as_ref()
.and_then(Value::as_object)
.and_then(|extra| extra.get(PAYLOAD_KEY))
else {
return Ok(None);
};
let controls = NativeControls::deserialize(payload)
.map_err(|error| invalid_argument(format!("invalid extra_args.{PAYLOAD_KEY}: {error}")))?;
let logprobs = LogprobOptions::new(
controls.return_logprob.unwrap_or(false),
controls.top_logprobs_num.unwrap_or(0),
controls.logprob_start_len.unwrap_or(-1),
)
.map_err(invalid_argument)?;
let request_id = controls
.rid
.unwrap_or_else(|| fallback_request_id.to_string());
Ok(Some(ResponseMetadata::new(
request_id,
&request.token_ids,
logprobs,
)))
}
pub(super) fn adapt(
metadata: &ResponseMetadata,
output: &mut LLMEngineOutput,
completion_tokens: usize,
) {
let response = metadata.response(
&output.token_ids,
completion_tokens,
output.finish_reason.as_ref().map(native_finish_reason),
);
output.engine_data = Some(json!({"sglang_response": response}));
}
fn native_finish_reason(reason: &FinishReason) -> Value {
match reason {
FinishReason::Length => json!({"type": "length"}),
FinishReason::EoS | FinishReason::Stop => json!({"type": "stop"}),
FinishReason::Cancelled => json!({
"type": "abort",
"message": "request was cancelled",
}),
FinishReason::Error(message) => json!({
"type": "abort",
"message": message,
}),
FinishReason::ContentFilter => json!({
"type": "abort",
"message": "generation stopped by content filter",
}),
}
}
fn invalid_argument(message: impl Into<String>) -> DynamoError {
DynamoError::builder()
.error_type(ErrorType::InvalidArgument)
.message(message.into())
.build()
}
#[cfg(test)]
mod tests {
use super::*;
use crate::protocols::common::{OutputOptions, SamplingOptions, StopConditions};
fn request(extra_args: Option<Value>) -> PreprocessedRequest {
PreprocessedRequest::builder()
.model("mock".to_string())
.token_ids(vec![11, 12, 13])
.stop_conditions(StopConditions {
max_tokens: Some(2),
..Default::default()
})
.sampling_options(SamplingOptions::default())
.output_options(OutputOptions::default())
.extra_args(extra_args)
.build()
.unwrap()
}
fn native_metadata(payload: Value) -> ResponseMetadata {
response_metadata(&request(Some(json!({"sglang_tito": payload}))), "fallback")
.unwrap()
.unwrap()
}
#[test]
fn only_requests_carrying_the_native_payload_are_adapted() {
assert!(
response_metadata(&request(None), "fallback")
.unwrap()
.is_none()
);
assert!(
response_metadata(&request(Some(json!({"other_engine": {}}))), "fallback")
.unwrap()
.is_none()
);
assert!(response_metadata(&request(Some(json!({"sglang_tito": 7}))), "fallback").is_err());
}
#[test]
fn resolves_the_request_id_and_ignores_unknown_controls() {
let metadata =
native_metadata(json!({"rid": "resolved-id", "future_field": {"opaque": true}}));
assert_eq!(metadata.request_id(), "resolved-id");
assert_eq!(native_metadata(json!({})).request_id(), "fallback");
}
#[test]
fn null_logprob_controls_use_sglang_defaults() {
let metadata = native_metadata(json!({
"return_logprob": null,
"top_logprobs_num": null,
"logprob_start_len": null,
}));
let response = metadata.response(&[107], 1, Some(json!({"type": "length"})));
assert!(response["meta_info"].get("output_token_logprobs").is_none());
let metadata = native_metadata(json!({
"return_logprob": true,
"top_logprobs_num": null,
"logprob_start_len": null,
}));
let response = metadata.response(&[107], 1, Some(json!({"type": "length"})));
let meta = &response["meta_info"];
assert!(meta.get("output_token_logprobs").is_some());
assert!(meta.get("output_top_logprobs").is_none());
assert!(meta.get("input_token_logprobs").is_none());
}
#[test]
fn maps_cancellation_and_errors_to_abort() {
let metadata = native_metadata(json!({"rid": "terminal"}));
for (mut output, expected_message) in [
(
LLMEngineOutput::error("backend failed".to_string()),
"backend failed",
),
(LLMEngineOutput::cancelled(), "request was cancelled"),
] {
adapt(&metadata, &mut output, 0);
let finish = &output.engine_data.as_ref().unwrap()["sglang_response"]["meta_info"]["finish_reason"];
assert_eq!(finish["type"], "abort");
assert_eq!(finish["message"], expected_message);
}
}
}