From a27397e55cf2d24c0f770314029e789179bf4903 Mon Sep 17 00:00:00 2001 From: Grace Guo Date: Mon, 6 Oct 2025 12:08:38 -0700 Subject: [PATCH] made changes to JSON tool parser, wraps the TollCallFunction with a TollCall object --- model/parsers/qwen3vl.go | 24 ++++++++++-------------- model/parsers/qwen3vl_test.go | 33 +++++++++++++++++++++++++++++++++ model/renderers/qwen3vl.go | 3 ++- 3 files changed, 45 insertions(+), 15 deletions(-) diff --git a/model/parsers/qwen3vl.go b/model/parsers/qwen3vl.go index f79a112c8..6711e67a6 100644 --- a/model/parsers/qwen3vl.go +++ b/model/parsers/qwen3vl.go @@ -59,7 +59,9 @@ func (p *Qwen3VLParser) Add(s string, done bool) (content string, thinking strin for _, event := range events { switch event := event.(type) { case qwenEventRawToolCall: - toolCall, err := parseToolCall(event, p.tools) + fmt.Print("[qwen3vl parser] qwenEventRawToolCall ", event.raw) + fmt.Print("[qwen3vl parser] p.tools ", p.tools) + toolCall, err := parseJSONToolCall(event, p.tools) if err != nil { slog.Warn("qwen tool call parsing failed", "error", err) return "", "", nil, err @@ -238,23 +240,17 @@ func parseJSONToolCall(raw qwenEventRawToolCall, tools []api.Tool) (api.ToolCall // Name string `json:"name"` // Arguments json.RawMessage `json:"arguments"` // } - fmt.Println(raw.raw) + fmt.Printf("[qwen3vl parseJSONToolCall] raw.raw %s\n", raw.raw) - var toolCall api.ToolCall - if err := json.Unmarshal([]byte(raw.raw), &toolCall); err != nil { + var toolCallFunction api.ToolCallFunction + if err := json.Unmarshal([]byte(raw.raw), &toolCallFunction); err != nil { return api.ToolCall{}, err } - // args := make(api.ToolCallFunctionArguments) - // if len(in.Arguments) > 0 && string(in.Arguments) != "null" { - // var obj map[string]any - // if err := json.Unmarshal(in.Arguments, &obj); err == nil { - // for k, v := range obj { - // args[k] = v - // } - // } - // } - fmt.Println(toolCall) + toolCall := api.ToolCall{} + toolCall.Function = toolCallFunction + + fmt.Printf("[qwen3vl parser] toolCall %#v\n", toolCall) return toolCall, nil } diff --git a/model/parsers/qwen3vl_test.go b/model/parsers/qwen3vl_test.go index ab63f59ef..9e1feaabf 100644 --- a/model/parsers/qwen3vl_test.go +++ b/model/parsers/qwen3vl_test.go @@ -184,6 +184,39 @@ func TestQwen3VLParserStreaming(t *testing.T) { } } +func TestQwen3VLComplex(t *testing.T) { + type step struct { + input string + wantEvents []qwenEvent + } + + cases := []struct { + desc string + steps []step + only bool + }{ + { + desc: "simple tool call", + steps: []step{ + { + input: "Here are 30 distinct and popular emojis for you! 😊\n\n1. 😂 \n2. ❤️ \n3. 🌟 \n4. 🐶 \n5. 🍕 \n6. ✨ \n7. 🌈 \n8. 🎉 \n9. 🌎 \n10. 🦁 \n11. 💯 \n12. 🥰 \n13. 🌸 \n14. 🚀 \n15. 🌊 \n16. 🍦 \n17. 🌙 \n18. 🌞 \n19. 🌻 \n20. 🦋 \n21. 🍃 \n22. 🏆 \n23. 🌮 \n24. 🧸 \n25. 🎮 \n26. 📚 \n27. ✈️ \n28. 🌟 (sparkles) \n29. 🌈 (rainbow) \n30. 🥳 \n\n*Bonus fun fact:* The 😂 (Face with Tears of Joy) was Oxford Dictionaries' Word of the Year in 2015! 🎉 \nLet me know if you'd like themed emojis (e.g., animals, food, or emotions)! 🐱🍕📚", + wantEvents: []qwenEvent{qwenEventContent{content: "bruh"}}, + }, + }, + }, + } + for _, tc := range cases { + for i, step := range tc.steps { + parser := Qwen3VLParser{} + parser.buffer.WriteString(step.input) + gotEvents := parser.parseEvents() + if !reflect.DeepEqual(gotEvents, step.wantEvents) { + t.Errorf("step %d: input %q: got events %#v, want %#v", i, step.input, gotEvents, step.wantEvents) + } + } + } +} + // TODO: devin was saying something about json cant figure out types? // do we need to test for func TestQwen3VLToolParser(t *testing.T) { diff --git a/model/renderers/qwen3vl.go b/model/renderers/qwen3vl.go index 915754e25..315ddbe86 100644 --- a/model/renderers/qwen3vl.go +++ b/model/renderers/qwen3vl.go @@ -187,7 +187,8 @@ func Qwen3VLRenderer(messages []api.Message, tools []api.Tool, _ *api.ThinkValue } - sb.WriteString("<|im_start|>assistant\n\n") + // sb.WriteString("<|im_start|>assistant\n\n") + sb.WriteString("<|im_start|>assistant\n") return sb.String(), nil }