流式 Tool Call Chunk 兼容性对比

对比自定义 OpenAI-compatible 接口与 OpenRouter DeepSeek V4 Flash 的 streaming tool call 返回结构。生成时间:2026-07-09 14:32:07

结论
核心拼接路径兼容,但结束语义不完全一致。

两边都通过 SSE 返回 chat.completion.chunk,并把工具参数放在 choices[].delta.tool_calls[].function.arguments 中分块返回。客户端可以用同一套累计逻辑拼接参数。

主要差异:自定义接口工具调用结束时返回 finish_reason: "stop";OpenRouter DeepSeek 返回 finish_reason: "tool_calls"。如果要对齐 DeepSeek/OpenAI-compatible 工具调用语义,建议把工具调用结束 chunk 改成 tool_calls

实测数据源

接口JSONL 文件总 SSE JSON chunkTool argument chunk模型
自定义接口tmp/streaming_tool_chunks.jsonl317252qwen3.5-122b-int4
OpenRouter DeepSeektmp/openrouter-deepseek-v4-flash-streaming-tool-chunks.jsonl461434deepseek/deepseek-v4-flash-20260423

协议层对齐情况

检查项自定义接口OpenRouter DeepSeek判断
SSE chunk 对象object: chat.completion.chunkobject: chat.completion.chunk一致
工具参数路径choices[].delta.tool_calls[].function.argumentschoices[].delta.tool_calls[].function.arguments一致
参数是否分块252 个参数 chunk434 个参数 chunk一致,均为真实分块
工具调用终止原因stoptool_calls不一致
额外字段prompt_token_ids, token_ids, stop_reasonprovider, native_finish_reason, usage实现差异,可兼容忽略

关键 chunk 对比

自定义接口:第一个 tool chunk

{
  "tool_calls": [
    {
      "id": "chatcmpl-tool-8ec795451c9063ff",
      "type": "function",
      "index": 0,
      "function": {
        "name": "write_markdown_story",
        "arguments": "{"
      }
    }
  ]
}

OpenRouter DeepSeek:第一个 tool chunk

{
  "content": null,
  "role": "assistant",
  "tool_calls": [
    {
      "index": 0,
      "id": "call_db8531364ef5436b8eb2cb0a",
      "type": "function",
      "function": {
        "name": "write_markdown_story",
        "arguments": ""
      }
    }
  ]
}

自定义接口:最后一个 tool chunk

{
  "tool_calls": [
    {
      "index": 0,
      "function": {
        "arguments": ""
      }
    }
  ]
}

OpenRouter DeepSeek:最后一个 tool chunk

{
  "content": null,
  "role": "assistant",
  "tool_calls": [
    {
      "index": 0,
      "function": {
        "arguments": "}"
      }
    }
  ]
}

Finish chunk 对比

自定义接口

[
  {
    "index": 0,
    "delta": {
      "tool_calls": [
        {
          "index": 0,
          "function": {
            "arguments": ""
          }
        }
      ]
    },
    "logprobs": null,
    "finish_reason": "stop",
    "stop_reason": null,
    "token_ids": null
  }
]

OpenRouter DeepSeek

[
  {
    "index": 0,
    "delta": {
      "content": "",
      "role": "assistant",
      "reasoning": null
    },
    "finish_reason": "tool_calls",
    "native_finish_reason": "tool_calls"
  },
  {
    "index": 0,
    "delta": {
      "content": "",
      "role": "assistant"
    },
    "finish_reason": "tool_calls",
    "native_finish_reason": "tool_calls"
  }
]

字段分布

自定义接口 delta keys

{
  "role": 1,
  "content": 1,
  "reasoning": 64,
  "tool_calls": 252
}

OpenRouter DeepSeek delta keys

{
  "content": 461,
  "role": 461,
  "reasoning": 26,
  "reasoning_details": 25,
  "tool_calls": 434
}

建议

参考规范

DeepSeek Chat Completion 文档说明:stream=true 时会以 data-only SSE 发送 partial deltas,并用 data: [DONE] 结束;工具定义通过 toolstool_choice 提供;finish_reason 包含 tool_calls,用于表示模型调用了工具。

DeepSeek Create Chat Completion API