[router][tool parser] Modify tool parser to return both normal text and tool calls (non-stream) (#10995)
This commit is contained in:
@@ -15,11 +15,11 @@ async fn test_json_with_xml_style_wrapper() {
|
||||
let input =
|
||||
r#"Some text before <tool>{"name": "test", "arguments": {"x": 1}}</tool> and after"#;
|
||||
|
||||
let result = parser.parse_complete(input).await.unwrap();
|
||||
assert_eq!(result.len(), 1);
|
||||
assert_eq!(result[0].function.name, "test");
|
||||
let (_normal_text, tools) = parser.parse_complete(input).await.unwrap();
|
||||
assert_eq!(tools.len(), 1);
|
||||
assert_eq!(tools[0].function.name, "test");
|
||||
|
||||
let args: serde_json::Value = serde_json::from_str(&result[0].function.arguments).unwrap();
|
||||
let args: serde_json::Value = serde_json::from_str(&tools[0].function.arguments).unwrap();
|
||||
assert_eq!(args["x"], 1);
|
||||
}
|
||||
|
||||
@@ -32,14 +32,14 @@ async fn test_json_with_multiple_wrapper_pairs() {
|
||||
});
|
||||
|
||||
let input1 = r#"<tool>{"name": "tool1", "arguments": {}}</tool>"#;
|
||||
let result1 = parser.parse_complete(input1).await.unwrap();
|
||||
assert_eq!(result1.len(), 1);
|
||||
assert_eq!(result1[0].function.name, "tool1");
|
||||
let (_normal_text, tools1) = parser.parse_complete(input1).await.unwrap();
|
||||
assert_eq!(tools1.len(), 1);
|
||||
assert_eq!(tools1[0].function.name, "tool1");
|
||||
|
||||
let input2 = r#"<<TOOL>>{"name": "tool2", "arguments": {}}<</TOOL>>"#;
|
||||
let result2 = parser.parse_complete(input2).await.unwrap();
|
||||
assert_eq!(result2.len(), 1);
|
||||
assert_eq!(result2[0].function.name, "tool2");
|
||||
let (_normal_text, tools2) = parser.parse_complete(input2).await.unwrap();
|
||||
assert_eq!(tools2.len(), 1);
|
||||
assert_eq!(tools2[0].function.name, "tool2");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
@@ -52,9 +52,9 @@ async fn test_json_with_only_start_token() {
|
||||
|
||||
let input = r#"Some preamble >>>FUNCTION:{"name": "execute", "arguments": {"cmd": "ls"}}"#;
|
||||
|
||||
let result = parser.parse_complete(input).await.unwrap();
|
||||
assert_eq!(result.len(), 1);
|
||||
assert_eq!(result[0].function.name, "execute");
|
||||
let (_normal_text, tools) = parser.parse_complete(input).await.unwrap();
|
||||
assert_eq!(tools.len(), 1);
|
||||
assert_eq!(tools[0].function.name, "execute");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
@@ -68,9 +68,9 @@ async fn test_json_with_custom_separator() {
|
||||
// Though we're not testing multiple tools here, the separator is configured
|
||||
let input = r#"[FUNC]{"name": "test", "arguments": {}}[/FUNC]"#;
|
||||
|
||||
let result = parser.parse_complete(input).await.unwrap();
|
||||
assert_eq!(result.len(), 1);
|
||||
assert_eq!(result[0].function.name, "test");
|
||||
let (_normal_text, tools) = parser.parse_complete(input).await.unwrap();
|
||||
assert_eq!(tools.len(), 1);
|
||||
assert_eq!(tools[0].function.name, "test");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
@@ -88,21 +88,21 @@ async fn test_json_with_nested_wrapper_tokens_in_content() {
|
||||
let input =
|
||||
r#"<call>{"name": "echo", "arguments": {"text": "Use <call> and </call> tags"}}</call>"#;
|
||||
|
||||
let result = parser.parse_complete(input).await.unwrap();
|
||||
let (_normal_text, tools) = parser.parse_complete(input).await.unwrap();
|
||||
|
||||
// This is a known limitation - the parser may fail when end tokens appear in content
|
||||
// For now, we accept this behavior
|
||||
if result.is_empty() {
|
||||
if tools.is_empty() {
|
||||
// Parser failed due to nested tokens - this is expected
|
||||
assert_eq!(
|
||||
result.len(),
|
||||
tools.len(),
|
||||
0,
|
||||
"Known limitation: nested wrapper tokens in content"
|
||||
);
|
||||
} else {
|
||||
// If it does parse, verify it's correct
|
||||
assert_eq!(result[0].function.name, "echo");
|
||||
let args: serde_json::Value = serde_json::from_str(&result[0].function.arguments).unwrap();
|
||||
assert_eq!(tools[0].function.name, "echo");
|
||||
let args: serde_json::Value = serde_json::from_str(&tools[0].function.arguments).unwrap();
|
||||
assert_eq!(args["text"], "Use <call> and </call> tags");
|
||||
}
|
||||
}
|
||||
@@ -118,9 +118,9 @@ async fn test_json_extraction_without_wrapper_tokens() {
|
||||
And here is some text after.
|
||||
"#;
|
||||
|
||||
let result = parser.parse_complete(input).await.unwrap();
|
||||
assert_eq!(result.len(), 1);
|
||||
assert_eq!(result[0].function.name, "search");
|
||||
let (_normal_text, tools) = parser.parse_complete(input).await.unwrap();
|
||||
assert_eq!(tools.len(), 1);
|
||||
assert_eq!(tools[0].function.name, "search");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
@@ -143,9 +143,9 @@ async fn test_json_with_multiline_wrapper_content() {
|
||||
```
|
||||
Done!"#;
|
||||
|
||||
let result = parser.parse_complete(input).await.unwrap();
|
||||
assert_eq!(result.len(), 1);
|
||||
assert_eq!(result[0].function.name, "format_code");
|
||||
let (_normal_text, tools) = parser.parse_complete(input).await.unwrap();
|
||||
assert_eq!(tools.len(), 1);
|
||||
assert_eq!(tools[0].function.name, "format_code");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
@@ -158,11 +158,11 @@ async fn test_json_with_special_chars_in_tokens() {
|
||||
|
||||
let input = r#"{{FUNC[[{"name": "test", "arguments": {"special": "[]{}"}}]]FUNC}}"#;
|
||||
|
||||
let result = parser.parse_complete(input).await.unwrap();
|
||||
assert_eq!(result.len(), 1);
|
||||
assert_eq!(result[0].function.name, "test");
|
||||
let (_normal_text, tools) = parser.parse_complete(input).await.unwrap();
|
||||
assert_eq!(tools.len(), 1);
|
||||
assert_eq!(tools[0].function.name, "test");
|
||||
|
||||
let args: serde_json::Value = serde_json::from_str(&result[0].function.arguments).unwrap();
|
||||
let args: serde_json::Value = serde_json::from_str(&tools[0].function.arguments).unwrap();
|
||||
assert_eq!(args["special"], "[]{}");
|
||||
}
|
||||
|
||||
@@ -183,9 +183,9 @@ async fn test_json_multiple_tools_with_wrapper() {
|
||||
|
||||
// Current implementation might handle this as separate calls
|
||||
// Let's test that at least the first one is parsed
|
||||
let result = parser.parse_complete(input).await.unwrap();
|
||||
assert!(!result.is_empty(), "Should parse at least one tool");
|
||||
assert_eq!(result[0].function.name, "tool1");
|
||||
let (_normal_text, tools) = parser.parse_complete(input).await.unwrap();
|
||||
assert!(!tools.is_empty(), "Should parse at least one tool");
|
||||
assert_eq!(tools[0].function.name, "tool1");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
@@ -201,10 +201,10 @@ async fn test_json_wrapper_with_array() {
|
||||
{"name": "func2", "arguments": {"param": "value"}}
|
||||
]</tools>"#;
|
||||
|
||||
let result = parser.parse_complete(input).await.unwrap();
|
||||
assert_eq!(result.len(), 2);
|
||||
assert_eq!(result[0].function.name, "func1");
|
||||
assert_eq!(result[1].function.name, "func2");
|
||||
let (_normal_text, tools) = parser.parse_complete(input).await.unwrap();
|
||||
assert_eq!(tools.len(), 2);
|
||||
assert_eq!(tools[0].function.name, "func1");
|
||||
assert_eq!(tools[1].function.name, "func2");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
@@ -217,13 +217,13 @@ async fn test_json_incomplete_wrapper_tokens() {
|
||||
|
||||
// Missing end token
|
||||
let input = r#"<tool>{"name": "test", "arguments": {}}"#;
|
||||
let result = parser.parse_complete(input).await.unwrap();
|
||||
assert_eq!(result.len(), 0, "Should not parse without closing token");
|
||||
let (_normal_text, tools) = parser.parse_complete(input).await.unwrap();
|
||||
assert_eq!(tools.len(), 0, "Should not parse without closing token");
|
||||
|
||||
// Missing start token
|
||||
let input = r#"{"name": "test", "arguments": {}}</tool>"#;
|
||||
let result = parser.parse_complete(input).await.unwrap();
|
||||
assert_eq!(result.len(), 0, "Should not parse without opening token");
|
||||
let (_normal_text, tools) = parser.parse_complete(input).await.unwrap();
|
||||
assert_eq!(tools.len(), 0, "Should not parse without opening token");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
@@ -236,7 +236,7 @@ async fn test_json_empty_wrapper_tokens() {
|
||||
|
||||
let input = r#"{"name": "test", "arguments": {"key": "value"}}"#;
|
||||
|
||||
let result = parser.parse_complete(input).await.unwrap();
|
||||
assert_eq!(result.len(), 1);
|
||||
assert_eq!(result[0].function.name, "test");
|
||||
let (_normal_text, tools) = parser.parse_complete(input).await.unwrap();
|
||||
assert_eq!(tools.len(), 1);
|
||||
assert_eq!(tools[0].function.name, "test");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user