Jump to content

Connect Leeroopedia MCP: Equip your AI agents to search best practices, build plans, verify code, diagnose failures, and look up hyperparameter defaults.

Heuristic:HKUDS AI Trader DeepSeek Tool Args Workaround

From Leeroopedia




Knowledge Sources
Domains LLM_Agents, Debugging
Last Updated 2026-02-09 14:00 GMT

Overview

DeepSeek API compatibility workaround: use a custom DeepSeekChatOpenAI wrapper class to handle tool_calls.args being returned as JSON strings instead of parsed dicts.

Description

When using DeepSeek models through the OpenAI-compatible API, the tool_calls response format differs from standard OpenAI behavior. DeepSeek returns tool_calls.args as raw JSON strings rather than pre-parsed Python dicts. The AI-Trader codebase addresses this by subclassing ChatOpenAI into DeepSeekChatOpenAI, which overrides the message parsing methods to handle this format difference transparently.

Usage

This workaround is automatically activated when the model name contains "deepseek" (case-insensitive check). No manual configuration needed. Be aware of this pattern when adding support for new LLM providers that may have similar API format differences.

The Insight (Rule of Thumb)

  • Action: When "deepseek" in self.basemodel.lower(), use DeepSeekChatOpenAI instead of ChatOpenAI.
  • Value: Transparent compatibility; the rest of the agent code works identically.
  • Trade-off: Adds a provider-specific code path. If DeepSeek fixes their API format, this class becomes dead code.

Reasoning

Different LLM providers implement the OpenAI-compatible API with subtle differences. DeepSeek's tool_calls format returns arguments as serialized JSON strings, while LangChain's ChatOpenAI expects parsed dicts. Rather than post-processing every response, subclassing the model class encapsulates the fix at the appropriate abstraction layer.

Code Evidence

DeepSeek wrapper class from agent/base_agent/base_agent.py:39-48:

class DeepSeekChatOpenAI(ChatOpenAI):
    """
    Custom ChatOpenAI wrapper for DeepSeek API compatibility.
    Handles the case where DeepSeek returns tool_calls.args as JSON strings instead of dicts.
    """

    def _create_message_dicts(self, messages: list, stop: Optional[list] = None) -> list:
        """Override to handle response parsing"""
        message_dicts = super()._create_message_dicts(messages, stop)
        return message_dicts

Conditional model selection from agent/base_agent/base_agent.py:382-397:

# Create AI model - use custom DeepSeekChatOpenAI for DeepSeek models
# to handle tool_calls.args format differences (JSON string vs dict)
if "deepseek" in self.basemodel.lower():
    self.model = DeepSeekChatOpenAI(
        model=self.basemodel,
        base_url=self.openai_base_url,
        api_key=self.openai_api_key,
        max_retries=3,
        timeout=30,
    )
else:
    self.model = ChatOpenAI(
        model=self.basemodel,
        base_url=self.openai_base_url,
        api_key=self.openai_api_key,
        max_retries=3,
        timeout=30,
    )

Related Pages

Page Connections

Double-click a node to navigate. Hold to expand connections.
Principle
Implementation
Heuristic
Environment