[model-gateway] Fix logging module name, parse endpoint context, and tokenizer factory (#15782)

This commit is contained in:
Simo Lin
2025-12-24 13:54:48 -05:00
committed by GitHub
parent 186a56f6e2
commit 643aeefe6d
6 changed files with 23 additions and 45 deletions

View File

@@ -289,7 +289,7 @@ impl<B> MakeSpan<B> for RequestSpan {
status_code = Empty,
latency = Empty,
error = Empty,
module = "sglang::router_rs"
module = "sgl_model_gateway"
)
}
}

View File

@@ -35,14 +35,13 @@ use crate::{
completion::CompletionRequest,
embedding::EmbeddingRequest,
generate::GenerateRequest,
parser::{ParseFunctionCallRequest, SeparateReasoningRequest},
rerank::{RerankRequest, RerankResponse, RerankResult},
responses::{ResponsesGetParams, ResponsesRequest},
},
routers::{
error::{self, extract_error_code_from_response},
grpc::utils::{error_type_from_status, route_to_endpoint},
header_utils, parse, RouterTrait,
header_utils, RouterTrait,
},
};
@@ -54,7 +53,6 @@ pub struct Router {
dp_aware: bool,
enable_igw: bool,
retry_config: RetryConfig,
context: Option<Arc<AppContext>>,
}
impl std::fmt::Debug for Router {
@@ -66,7 +64,6 @@ impl std::fmt::Debug for Router {
.field("dp_aware", &self.dp_aware)
.field("enable_igw", &self.enable_igw)
.field("retry_config", &self.retry_config)
.field("context", &"<AppContext>")
.finish()
}
}
@@ -81,7 +78,6 @@ impl Router {
dp_aware: ctx.router_config.dp_aware,
enable_igw: ctx.router_config.enable_igw,
retry_config: ctx.router_config.effective_retry_config(),
context: Some(ctx.clone()),
})
}
@@ -817,14 +813,6 @@ impl RouterTrait for Router {
}
}
async fn parse_function_call(&self, req: &ParseFunctionCallRequest) -> Response {
parse::parse_function_call(self.context.as_ref(), req).await
}
async fn parse_reasoning(&self, req: &SeparateReasoningRequest) -> Response {
parse::parse_reasoning(self.context.as_ref(), req).await
}
fn router_type(&self) -> &'static str {
"regular"
}
@@ -859,7 +847,6 @@ mod tests {
client: Client::new(),
retry_config: RetryConfig::default(),
enable_igw: false,
context: None,
}
}

View File

@@ -16,7 +16,6 @@ use crate::protocols::{
completion::CompletionRequest,
embedding::EmbeddingRequest,
generate::GenerateRequest,
parser::{ParseFunctionCallRequest, SeparateReasoningRequest},
rerank::RerankRequest,
responses::{ResponsesGetParams, ResponsesRequest},
};
@@ -194,16 +193,6 @@ pub trait RouterTrait: Send + Sync + Debug {
(StatusCode::NOT_IMPLEMENTED, "Rerank not implemented").into_response()
}
/// Parse function calls from text
async fn parse_function_call(&self, req: &ParseFunctionCallRequest) -> Response {
parse::parse_function_call(None, req).await
}
/// Separate reasoning from normal text
async fn parse_reasoning(&self, req: &SeparateReasoningRequest) -> Response {
parse::parse_reasoning(None, req).await
}
/// Get router type name
fn router_type(&self) -> &'static str;

View File

@@ -28,13 +28,9 @@ fn error_response(status: StatusCode, message: &str) -> Response {
/// Parse function calls from model output text
pub async fn parse_function_call(
context: Option<&Arc<AppContext>>,
ctx: &Arc<AppContext>,
req: &ParseFunctionCallRequest,
) -> Response {
let Some(ctx) = context else {
return error_response(StatusCode::SERVICE_UNAVAILABLE, "Context not initialized");
};
let Some(factory) = &ctx.tool_parser_factory else {
return error_response(
StatusCode::SERVICE_UNAVAILABLE,
@@ -71,14 +67,7 @@ pub async fn parse_function_call(
}
/// Parse and separate reasoning from normal text
pub async fn parse_reasoning(
context: Option<&Arc<AppContext>>,
req: &SeparateReasoningRequest,
) -> Response {
let Some(ctx) = context else {
return error_response(StatusCode::SERVICE_UNAVAILABLE, "Context not initialized");
};
pub async fn parse_reasoning(ctx: &Arc<AppContext>, req: &SeparateReasoningRequest) -> Response {
let Some(factory) = &ctx.reasoning_parser_factory else {
return error_response(
StatusCode::SERVICE_UNAVAILABLE,

View File

@@ -50,7 +50,7 @@ use crate::{
validated::ValidatedJson,
worker_spec::{WorkerConfigRequest, WorkerUpdateRequest},
},
routers::{conversations, router_manager::RouterManager, tokenize, RouterTrait},
routers::{conversations, parse, router_manager::RouterManager, tokenize, RouterTrait},
service_discovery::{start_service_discovery, ServiceDiscoveryConfig},
wasm::route::{add_wasm_module, list_wasm_modules, remove_wasm_module},
workflow::{LoggingSubscriber, WorkflowEngine},
@@ -67,14 +67,14 @@ async fn parse_function_call(
State(state): State<Arc<AppState>>,
Json(req): Json<ParseFunctionCallRequest>,
) -> Response {
state.router.parse_function_call(&req).await
parse::parse_function_call(&state.context, &req).await
}
async fn parse_reasoning(
State(state): State<Arc<AppState>>,
Json(req): Json<SeparateReasoningRequest>,
) -> Response {
state.router.parse_reasoning(&req).await
parse::parse_reasoning(&state.context, &req).await
}
async fn sink_handler() -> Response {

View File

@@ -254,14 +254,27 @@ pub async fn create_tokenizer_async_with_chat_template(
}
// Check if it's a GPT model name that should use Tiktoken
if model_name_or_path.contains("gpt-")
// Only match specific OpenAI model patterns to avoid catching HuggingFace models like "openai/gpt-oss-20b"
if model_name_or_path.contains("gpt-4")
|| model_name_or_path.contains("gpt-3.5")
|| model_name_or_path.contains("gpt-3")
|| model_name_or_path.contains("turbo")
|| model_name_or_path.contains("davinci")
|| model_name_or_path.contains("curie")
|| model_name_or_path.contains("babbage")
|| model_name_or_path.contains("ada")
|| model_name_or_path.contains("codex")
{
let tokenizer = TiktokenTokenizer::from_model_name(model_name_or_path)?;
return Ok(Arc::new(tokenizer));
// Try tiktoken first, but fall back to HuggingFace if it fails
match TiktokenTokenizer::from_model_name(model_name_or_path) {
Ok(tokenizer) => return Ok(Arc::new(tokenizer)),
Err(e) => {
debug!(
"Tiktoken failed for '{}': {}, falling back to HuggingFace",
model_name_or_path, e
);
}
}
}
// Try to download tokenizer files from HuggingFace