[router][grpc] Consolidate parser checks for chat completions (#11439)
This commit is contained in:
@@ -6,7 +6,7 @@ use tokio::sync::Mutex;
|
||||
|
||||
use crate::tool_parser::parsers::{
|
||||
DeepSeekParser, Glm4MoeParser, GptOssHarmonyParser, GptOssParser, JsonParser, KimiK2Parser,
|
||||
LlamaParser, MistralParser, PythonicParser, QwenParser, Step3Parser,
|
||||
LlamaParser, MistralParser, PassthroughParser, PythonicParser, QwenParser, Step3Parser,
|
||||
};
|
||||
use crate::tool_parser::traits::ToolParser;
|
||||
|
||||
@@ -36,7 +36,7 @@ impl ParserRegistry {
|
||||
creators: Arc::new(RwLock::new(HashMap::new())),
|
||||
pool: Arc::new(RwLock::new(HashMap::new())),
|
||||
model_mapping: Arc::new(RwLock::new(HashMap::new())),
|
||||
default_parser: Arc::new(RwLock::new("json".to_string())),
|
||||
default_parser: Arc::new(RwLock::new("passthrough".to_string())),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,10 +124,9 @@ impl ParserRegistry {
|
||||
}
|
||||
}
|
||||
|
||||
// Check if default parser exists
|
||||
let default = self.default_parser.read().unwrap().clone();
|
||||
let creators = self.creators.read().unwrap();
|
||||
creators.contains_key(&default)
|
||||
// Return false if no specific parser found for this model
|
||||
// (get_pooled will still fall back to default parser)
|
||||
false
|
||||
}
|
||||
|
||||
/// Create a fresh (non-pooled) parser instance for a specific model.
|
||||
@@ -228,6 +227,7 @@ impl ParserFactory {
|
||||
let registry = ParserRegistry::new();
|
||||
|
||||
// Register default parsers
|
||||
registry.register_parser("passthrough", || Box::new(PassthroughParser::new()));
|
||||
registry.register_parser("json", || Box::new(JsonParser::new()));
|
||||
registry.register_parser("mistral", || Box::new(MistralParser::new()));
|
||||
registry.register_parser("qwen", || Box::new(QwenParser::new()));
|
||||
@@ -311,15 +311,15 @@ impl ParserFactory {
|
||||
|
||||
/// Get a pooled parser for the given model ID.
|
||||
/// Returns a shared instance that can be used concurrently.
|
||||
/// Falls back to JSON parser if model is not recognized.
|
||||
/// Falls back to passthrough parser if model is not recognized.
|
||||
pub fn get_pooled(&self, model_id: &str) -> PooledParser {
|
||||
self.registry
|
||||
.get_pooled_for_model(model_id)
|
||||
.unwrap_or_else(|| {
|
||||
// Fallback to JSON parser
|
||||
// Fallback to passthrough parser (no-op, returns text unchanged)
|
||||
self.registry
|
||||
.get_pooled_parser("json")
|
||||
.expect("JSON parser should always be registered")
|
||||
.get_pooled_parser("passthrough")
|
||||
.expect("Passthrough parser should always be registered")
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ pub mod json_parser;
|
||||
pub mod kimik2_parser;
|
||||
pub mod llama_parser;
|
||||
pub mod mistral_parser;
|
||||
pub mod passthrough_parser;
|
||||
pub mod pythonic_parser;
|
||||
pub mod qwen_parser;
|
||||
pub mod step3_parser;
|
||||
@@ -27,6 +28,7 @@ pub use json_parser::JsonParser;
|
||||
pub use kimik2_parser::KimiK2Parser;
|
||||
pub use llama_parser::LlamaParser;
|
||||
pub use mistral_parser::MistralParser;
|
||||
pub use passthrough_parser::PassthroughParser;
|
||||
pub use pythonic_parser::PythonicParser;
|
||||
pub use qwen_parser::QwenParser;
|
||||
pub use step3_parser::Step3Parser;
|
||||
|
||||
50
sgl-router/src/tool_parser/parsers/passthrough_parser.rs
Normal file
50
sgl-router/src/tool_parser/parsers/passthrough_parser.rs
Normal file
@@ -0,0 +1,50 @@
|
||||
//! Passthrough parser that returns text unchanged
|
||||
//!
|
||||
//! This parser is used as a fallback for unknown models where no specific
|
||||
//! tool call parsing should be performed. It simply returns the input text
|
||||
//! with no tool calls detected.
|
||||
|
||||
use crate::protocols::spec::Tool;
|
||||
use crate::tool_parser::errors::ParserResult;
|
||||
use crate::tool_parser::traits::ToolParser;
|
||||
use crate::tool_parser::types::{StreamingParseResult, ToolCall, ToolCallItem};
|
||||
use async_trait::async_trait;
|
||||
|
||||
/// Passthrough parser that returns text unchanged with no tool calls
|
||||
#[derive(Default)]
|
||||
pub struct PassthroughParser;
|
||||
|
||||
impl PassthroughParser {
|
||||
pub fn new() -> Self {
|
||||
Self
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl ToolParser for PassthroughParser {
|
||||
async fn parse_complete(&self, output: &str) -> ParserResult<(String, Vec<ToolCall>)> {
|
||||
// Return text unchanged with no tool calls
|
||||
Ok((output.to_string(), vec![]))
|
||||
}
|
||||
|
||||
async fn parse_incremental(
|
||||
&mut self,
|
||||
chunk: &str,
|
||||
_tools: &[Tool],
|
||||
) -> ParserResult<StreamingParseResult> {
|
||||
// Return chunk unchanged with no tool calls
|
||||
Ok(StreamingParseResult {
|
||||
normal_text: chunk.to_string(),
|
||||
calls: vec![],
|
||||
})
|
||||
}
|
||||
|
||||
fn has_tool_markers(&self, _text: &str) -> bool {
|
||||
// Passthrough never detects tool calls
|
||||
false
|
||||
}
|
||||
|
||||
fn get_unstreamed_tool_args(&self) -> Option<Vec<ToolCallItem>> {
|
||||
None
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user