Skip to content

[Enhancement]: SDK 层增加 tool_call 文本兜底解析,应对模型 function calling 退化 #437

@9Ashwin

Description

@9Ashwin

背景

跑 DeepSeek V4 Pro 的时候发现一个情况:模型偶尔不走 tool_calls[] 结构化字段,而是直接在 content 里吐出 XML 格式的工具调用,类似:

<tool_call id="call_00_xxx" name="some_tool">
{"param1": "value1"}
</tool_call>

然后这段 XML 就被当普通文本原样输出,工具没跑。不是每次复现,但出一次就挺尴尬的——用户看到的是没被执行的 XML 片段。

排查

过了一遍 Memoh agent 层和 twilight-ai SDK 的代码,两边都没写错——都是按 OpenAI function calling spec 来的。SDK 的 stream.goprocessToolCallDeltascompletions.gofinish_reasonFinishReasonToolCalls 的路由都没问题。

问题在模型侧:DeepSeek V4 Pro 在上下文较大、tool definitions 较多的时候,function calling 不太稳,会退化到用文字描述它想调的工具,而不是走标准 API 通道。

想法

在 SDK 的 provider/openai/completions/ 层加个兜底——内容输出给 agent 之前,扫一眼 TextPart 里的文本,正则匹配 <tool_call> XML 片段然后拆成 ToolCallPart。这样就算模型没走 tool_calls 字段,文本里的工具调用也能被识别和执行。

不改 Memoh 代码,在 Provider 层做一次 post-process 就行,所有下游 agent 都能受益。而且不只是 DeepSeek 的问题,其他 OpenAI-compatible 模型也可能有类似退化。

版本信息

  • Version: main 分支,2026-05-08
  • Model: DeepSeek-V4 Pro(走 openai-completions provider)
  • SDK: github.com/memohai/twilight-ai v1.1.0-0.20260503122618-0320ef707a97

来自 memohbot,跑 DeepSeek-V4 Pro 踩到的,排查完觉得 SDK 层加个兜底比较合理。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions