Support toolCall XML tags and XML child arguments in DetectToolCalls
This commit is contained in:
@@ -658,7 +658,10 @@ type ToolTagPair struct {
|
|||||||
var ToolTagPairs = []ToolTagPair{
|
var ToolTagPairs = []ToolTagPair{
|
||||||
{Start: "<tool_call>", End: "</tool_call>"},
|
{Start: "<tool_call>", End: "</tool_call>"},
|
||||||
{Start: "<tool_calls>", End: "</tool_calls>"},
|
{Start: "<tool_calls>", End: "</tool_calls>"},
|
||||||
|
{Start: "<toolCall>", End: "</toolCall>"},
|
||||||
|
{Start: "<toolCalls>", End: "</toolCalls>"},
|
||||||
{Start: "<function_call>", End: "</function_call>"},
|
{Start: "<function_call>", End: "</function_call>"},
|
||||||
|
{Start: "<functionCall>", End: "</functionCall>"},
|
||||||
{Start: "[TOOL_CALLS]", End: "[/TOOL_CALLS]"},
|
{Start: "[TOOL_CALLS]", End: "[/TOOL_CALLS]"},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -903,6 +906,36 @@ func parseXMLToolCall(block string) ([]ToolCall, bool) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if argsStr != "" && !json.Valid([]byte(argsStr)) {
|
||||||
|
reTagOpen := regexp.MustCompile(`<([a-zA-Z0-9_-]+)>`)
|
||||||
|
openMatches := reTagOpen.FindAllStringSubmatchIndex(argsStr, -1)
|
||||||
|
if len(openMatches) > 0 {
|
||||||
|
xmlMap := make(map[string]interface{})
|
||||||
|
for _, match := range openMatches {
|
||||||
|
tagName := argsStr[match[2]:match[3]]
|
||||||
|
closeTag := "</" + tagName + ">"
|
||||||
|
closeIdx := strings.Index(argsStr[match[1]:], closeTag)
|
||||||
|
if closeIdx != -1 {
|
||||||
|
v := strings.TrimSpace(argsStr[match[1] : match[1]+closeIdx])
|
||||||
|
if num, err := strconv.ParseFloat(v, 64); err == nil && !strings.HasPrefix(v, "0") {
|
||||||
|
xmlMap[tagName] = num
|
||||||
|
} else if v == "true" {
|
||||||
|
xmlMap[tagName] = true
|
||||||
|
} else if v == "false" {
|
||||||
|
xmlMap[tagName] = false
|
||||||
|
} else {
|
||||||
|
xmlMap[tagName] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(xmlMap) > 0 {
|
||||||
|
if b, err := json.Marshal(xmlMap); err == nil {
|
||||||
|
argsStr = string(b)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if fnName != "" {
|
if fnName != "" {
|
||||||
if argsStr == "" {
|
if argsStr == "" {
|
||||||
argsStr = "{}"
|
argsStr = "{}"
|
||||||
@@ -976,6 +1009,12 @@ func DetectToolCalls(content string) ([]ToolCall, string, bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(calls) > 0 {
|
if len(calls) > 0 {
|
||||||
|
remaining = strings.TrimSpace(remaining)
|
||||||
|
if remaining == "```xml" || remaining == "```" || remaining == "```json" {
|
||||||
|
remaining = ""
|
||||||
|
}
|
||||||
|
reEmptyFence := regexp.MustCompile("(?m)^```(?:xml|json)?\\s*\\n?\\s*```\\s*$")
|
||||||
|
remaining = strings.TrimSpace(reEmptyFence.ReplaceAllString(remaining, ""))
|
||||||
return calls, remaining, true
|
return calls, remaining, true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -670,6 +670,22 @@ Some postamble.`
|
|||||||
if rem4 != "" {
|
if rem4 != "" {
|
||||||
t.Errorf("expected empty remaining, got %q", rem4)
|
t.Errorf("expected empty remaining, got %q", rem4)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 5. XML toolCall with child tags
|
||||||
|
xmlChildTags := "```xml\n<toolCall>\n <name>get_weather</name>\n <arguments>\n <loc>Paris</loc>\n </arguments>\n</toolCall>\n```"
|
||||||
|
calls5, rem5, ok5 := DetectToolCalls(xmlChildTags)
|
||||||
|
if !ok5 || len(calls5) != 1 {
|
||||||
|
t.Fatalf("expected 1 call from xmlChildTags, got %d", len(calls5))
|
||||||
|
}
|
||||||
|
if calls5[0].Function.Name != "get_weather" {
|
||||||
|
t.Errorf("expected get_weather, got %q", calls5[0].Function.Name)
|
||||||
|
}
|
||||||
|
if !strings.Contains(calls5[0].Function.Arguments, `"Paris"`) {
|
||||||
|
t.Errorf("expected Paris in arguments, got %s", calls5[0].Function.Arguments)
|
||||||
|
}
|
||||||
|
if rem5 != "" {
|
||||||
|
t.Errorf("expected empty remaining, got %q", rem5)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestUniversalStreamToolCallFilterVariants(t *testing.T) {
|
func TestUniversalStreamToolCallFilterVariants(t *testing.T) {
|
||||||
|
|||||||
Reference in New Issue
Block a user