Unverified Commit c112bcc4 authored by Chang Su's avatar Chang Su Committed by GitHub
Browse files

[router] global tool parser registry (#9840)

parent 5e194b21
......@@ -64,6 +64,7 @@ prost-types = "0.13"
deadpool = { version = "0.12", features = ["managed", "rt_tokio_1"] }
backoff = { version = "0.4", features = ["tokio"] }
strum = { version = "0.26", features = ["derive"] }
once_cell = "1.21.3"
[build-dependencies]
tonic-build = "0.12"
......
......@@ -23,6 +23,8 @@ use crate::tool_parser::{
pub struct PythonicParser {
/// Regex to detect tool calls in Pythonic format
tool_call_regex: Regex,
/// Regex to parse function calls - cached for reuse
call_regex: Regex,
}
impl PythonicParser {
......@@ -33,7 +35,13 @@ impl PythonicParser {
let pattern = r"\[[a-zA-Z_]\w*\(";
let tool_call_regex = Regex::new(pattern).expect("Valid regex pattern");
Self { tool_call_regex }
// Compile the function call regex once
let call_regex = Regex::new(r"(?s)^([a-zA-Z_]\w*)\((.*)\)$").expect("Valid regex pattern");
Self {
tool_call_regex,
call_regex,
}
}
/// Extract tool calls using bracket counting (similar to MistralParser)
......@@ -120,10 +128,8 @@ impl PythonicParser {
/// Parse a single function call from Python syntax
fn parse_function_call(&self, call_str: &str) -> ToolParserResult<Option<ToolCall>> {
// Match function_name(args) - use (?s) to make . match newlines
let call_regex = Regex::new(r"(?s)^([a-zA-Z_]\w*)\((.*)\)$").unwrap();
if let Some(captures) = call_regex.captures(call_str.trim()) {
// Use cached regex instead of creating new one
if let Some(captures) = self.call_regex.captures(call_str.trim()) {
let function_name = captures.get(1).unwrap().as_str();
let args_str = captures.get(2).unwrap().as_str();
......
......@@ -3,9 +3,13 @@ use crate::tool_parser::parsers::{
MistralParser, PythonicParser, QwenParser, Step3Parser,
};
use crate::tool_parser::traits::ToolParser;
use once_cell::sync::Lazy;
use std::collections::HashMap;
use std::sync::Arc;
/// Global singleton registry instance - created once and reused
pub static GLOBAL_REGISTRY: Lazy<ParserRegistry> = Lazy::new(ParserRegistry::new_internal);
/// Registry for tool parsers and model mappings
pub struct ParserRegistry {
/// Map of parser name to parser instance
......@@ -17,8 +21,19 @@ pub struct ParserRegistry {
}
impl ParserRegistry {
/// Create a new parser registry with default mappings
pub fn new() -> Self {
/// Get the global singleton instance
pub fn new() -> &'static Self {
&GLOBAL_REGISTRY
}
/// Create a new instance for testing (not the singleton)
#[cfg(test)]
pub fn new_for_testing() -> Self {
Self::new_internal()
}
/// Internal constructor for creating the singleton instance
fn new_internal() -> Self {
let mut registry = Self {
parsers: HashMap::new(),
model_mapping: HashMap::new(),
......@@ -202,8 +217,8 @@ impl ParserRegistry {
}
}
impl Default for ParserRegistry {
impl Default for &'static ParserRegistry {
fn default() -> Self {
Self::new()
ParserRegistry::new()
}
}
......@@ -74,7 +74,7 @@ fn test_parser_registry() {
#[test]
fn test_parser_registry_pattern_matching() {
let mut registry = ParserRegistry::new();
let mut registry = ParserRegistry::new_for_testing();
// Test that model mappings work by checking the list
registry.map_model("test-model", "json");
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment