tool_parser_glm4_moe.rs 5.45 KB
Newer Older
1
2
//! GLM-4 MoE Parser Integration Tests

3
4
5
6
use sglang_router_rs::tool_parser::{Glm4MoeParser, ToolParser};

mod common;
use common::create_test_tools;
7
8
9
10
11
12
13
14
15
16
17
18
19
20

#[tokio::test]
async fn test_glm4_complete_parsing() {
    let parser = Glm4MoeParser::new();

    let input = r#"Let me search for that.
<tool_call>get_weather
<arg_key>city</arg_key>
<arg_value>Beijing</arg_value>
<arg_key>date</arg_key>
<arg_value>2024-12-25</arg_value>
</tool_call>
The weather will be..."#;

21
    let (normal_text, tools) = parser.parse_complete(input).await.unwrap();
22
    assert_eq!(tools.len(), 1);
23
    assert_eq!(normal_text, "Let me search for that.\n");
24
    assert_eq!(tools[0].function.name, "get_weather");
25

26
    let args: serde_json::Value = serde_json::from_str(&tools[0].function.arguments).unwrap();
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
    assert_eq!(args["city"], "Beijing");
    assert_eq!(args["date"], "2024-12-25");
}

#[tokio::test]
async fn test_glm4_multiple_tools() {
    let parser = Glm4MoeParser::new();

    let input = r#"<tool_call>search
<arg_key>query</arg_key>
<arg_value>rust tutorials</arg_value>
</tool_call>
<tool_call>translate
<arg_key>text</arg_key>
<arg_value>Hello World</arg_value>
<arg_key>target_lang</arg_key>
<arg_value>zh</arg_value>
</tool_call>"#;

46
    let (normal_text, tools) = parser.parse_complete(input).await.unwrap();
47
    assert_eq!(tools.len(), 2);
48
    assert_eq!(normal_text, "");
49
50
    assert_eq!(tools[0].function.name, "search");
    assert_eq!(tools[1].function.name, "translate");
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
}

#[tokio::test]
async fn test_glm4_type_conversion() {
    let parser = Glm4MoeParser::new();

    let input = r#"<tool_call>process
<arg_key>count</arg_key>
<arg_value>42</arg_value>
<arg_key>rate</arg_key>
<arg_value>1.5</arg_value>
<arg_key>enabled</arg_key>
<arg_value>true</arg_value>
<arg_key>data</arg_key>
<arg_value>null</arg_value>
<arg_key>text</arg_key>
<arg_value>string value</arg_value>
</tool_call>"#;

70
    let (normal_text, tools) = parser.parse_complete(input).await.unwrap();
71
    assert_eq!(tools.len(), 1);
72
    assert_eq!(normal_text, "");
73

74
    let args: serde_json::Value = serde_json::from_str(&tools[0].function.arguments).unwrap();
75
76
77
78
79
80
81
82
83
    assert_eq!(args["count"], 42);
    assert_eq!(args["rate"], 1.5);
    assert_eq!(args["enabled"], true);
    assert_eq!(args["data"], serde_json::Value::Null);
    assert_eq!(args["text"], "string value");
}

#[tokio::test]
async fn test_glm4_streaming() {
84
85
86
    let mut parser = Glm4MoeParser::new();

    let tools = create_test_tools();
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101

    // Simulate streaming chunks
    let chunks = vec![
        "<tool_call>",
        "get_weather\n",
        "<arg_key>city</arg_key>\n",
        "<arg_value>Shanghai</arg_value>\n",
        "<arg_key>units</arg_key>\n",
        "<arg_value>celsius</arg_value>\n",
        "</tool_call>",
    ];

    let mut found_name = false;

    for chunk in chunks {
102
        let result = parser.parse_incremental(chunk, &tools).await.unwrap();
103

104
105
        for call in result.calls {
            if let Some(name) = call.name {
106
107
108
109
110
111
                assert_eq!(name, "get_weather");
                found_name = true;
            }
        }
    }

112
    assert!(found_name, "Should have found tool name during streaming");
113
114
115
116
117
118
119
}

#[test]
fn test_glm4_format_detection() {
    let parser = Glm4MoeParser::new();

    // Should detect GLM-4 format
120
121
    assert!(parser.has_tool_markers("<tool_call>"));
    assert!(parser.has_tool_markers("text with <tool_call> marker"));
122
123

    // Should not detect other formats
124
125
126
    assert!(!parser.has_tool_markers("[TOOL_CALLS]"));
    assert!(!parser.has_tool_markers("<|tool▁calls▁begin|>"));
    assert!(!parser.has_tool_markers("plain text"));
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
}

#[tokio::test]
async fn test_glm4_python_literal_values() {
    let parser = Glm4MoeParser::new();

    let input = r#"<tool_call>config
<arg_key>debug</arg_key>
<arg_value>True</arg_value>
<arg_key>verbose</arg_key>
<arg_value>False</arg_value>
<arg_key>optional</arg_key>
<arg_value>None</arg_value>
</tool_call>"#;

142
143
    let (_normal_text, tools) = parser.parse_complete(input).await.unwrap();
    assert_eq!(tools.len(), 1);
144

145
    let args: serde_json::Value = serde_json::from_str(&tools[0].function.arguments).unwrap();
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
    assert_eq!(args["debug"], true);
    assert_eq!(args["verbose"], false);
    assert_eq!(args["optional"], serde_json::Value::Null);
}

#[tokio::test]
async fn test_python_literals() {
    let parser = Glm4MoeParser::new();

    let input = r#"<tool_call>test_func
<arg_key>bool_true</arg_key>
<arg_value>True</arg_value>
<arg_key>bool_false</arg_key>
<arg_value>False</arg_value>
<arg_key>none_val</arg_key>
<arg_value>None</arg_value>
</tool_call>"#;

164
165
166
    let (_normal_text, tools) = parser.parse_complete(input).await.unwrap();
    assert_eq!(tools.len(), 1);
    assert_eq!(tools[0].function.name, "test_func");
167

168
    let args: serde_json::Value = serde_json::from_str(&tools[0].function.arguments).unwrap();
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
    assert_eq!(args["bool_true"], true);
    assert_eq!(args["bool_false"], false);
    assert_eq!(args["none_val"], serde_json::Value::Null);
}

#[tokio::test]
async fn test_nested_values() {
    let parser = Glm4MoeParser::new();

    let input = r#"<tool_call>process
<arg_key>data</arg_key>
<arg_value>{"nested": {"key": "value"}}</arg_value>
<arg_key>list</arg_key>
<arg_value>[1, 2, 3]</arg_value>
</tool_call>"#;

185
186
    let (_normal_text, tools) = parser.parse_complete(input).await.unwrap();
    assert_eq!(tools.len(), 1);
187

188
    let args: serde_json::Value = serde_json::from_str(&tools[0].function.arguments).unwrap();
189
190
191
    assert!(args["data"].is_object());
    assert!(args["list"].is_array());
}