Skip to content

qwen3_coder bare <function=...> (no <tool_call>) is a call in non-streaming and plain text in streaming #90

Open

Description

@gdevenyi

When the model skips the <tool_call> wrapper, non-streaming returns a tool call and also leaves the raw <function=...> markup in content. The streaming detector only looks for <tool_call> in idle mode, so it emits the whole block as content and executes no call. The fix parses the bare form as a call in both modes. It requires a declared tool name followed by <parameter= or </function>, so a literal <function= in prose or code stays text.

tools = [{"type": "function", "function": {"name": "edit", "parameters": {"type": "object", "properties": {"path": {"type": "string"}}}}}]
bare = ["Doing it.\n", "<", "function", "=", "edit", ">\n", "<parameter=path>\n", "a.py\n", "</parameter>\n", "</function>"]
p = FunctionCallParser(tools, "qwen3_coder"); print([p.parse_stream_chunk(c) for c in bare])   # all text, no call
r = FunctionCallParser(tools, "qwen3_coder").parse_non_stream("".join(bare)); print(repr(r.normal_text), r.calls)  # markup in text AND a call

Fixed on 5080deploy by fdf372c (merged in 1542d52); stream/non-stream parity tests are in tests/server/test_streaming_model_matrix.py.

Activity

  1. gdevenyi commented on Oct 16, 2026

    @gdevenyi
    OwnerAuthor

    Upstream: FlashML-org#714

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions