DEV Community

Cover image for DeepSeek V4 Function Calling: Structured Output Without the Pain
TokenPAPA
TokenPAPA

Posted on • Originally published at doc.tokenpapa.ai

DeepSeek V4 Function Calling: Structured Output Without the Pain

DeepSeek V4 Function Calling: Structured Output Without the Pain

Function calling is how LLMs stop chatting and start working — parsing input, calling tools, returning structured JSON. And with DeepSeek V4, it's also cheap enough to run at scale.

Here's how to build reliable tool-use flows with DeepSeek V4, with real code.


Why Function Calling Matters

Raw chat output is a string. Production systems need structure. Function calling gives you:

  • Structured JSON — no regex parsing of prose
  • Tool orchestration — the model decides what to call
  • Agent loops — multi-step workflows with state

DeepSeek V4 supports the OpenAI tool-calling format, so everything below works with the standard openai SDK — just point base_url at https://tokenpapa.ai/v1.


Step 1 — Define Your Tools

from openai import OpenAI

client = OpenAI(base_url="https://tokenpapa.ai/v1", api_key="your-key")

tools = [{
    "type": "function",
    "function": {
        "name": "get_weather",
        "description": "Get current weather for a city",
        "parameters": {
            "type": "object",
            "properties": {
                "city": {"type": "string", "description": "City name"},
                "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}
            },
            "required": ["city"]
        }
    }
}]
Enter fullscreen mode Exit fullscreen mode

Step 2 — Call and Handle the Tool

resp = client.chat.completions.create(
    model="deepseek-v4-flash",
    messages=[{"role": "user", "content": "What's the weather in Shanghai?"}],
    tools=tools,
    tool_choice="auto",
)

msg = resp.choices[0].message

if msg.tool_calls:                     # model wants to call a tool
    call = msg.tool_calls[0].function
    print("calling:", call.name, call.arguments)   # arguments = valid JSON
    result = get_weather(**json.loads(call.arguments))

    # feed result back and continue
    resp2 = client.chat.completions.create(
        model="deepseek-v4-flash",
        messages=[
            {"role": "user", "content": "What's the weather in Shanghai?"},
            msg,
            {"role": "tool", "tool_call_id": call.id, "content": json.dumps(result)},
        ],
        tools=tools,
    )
    print(resp2.choices[0].message.content)
else:
    print(msg.content)
Enter fullscreen mode Exit fullscreen mode

Step 3 — Reliable JSON Without Tools (JSON Mode)

For simple structured output you can also force JSON with a prompt contract:

resp = client.chat.completions.create(
    model="deepseek-v4-flash",
    messages=[
        {"role": "system", "content": "Output ONLY valid JSON with keys: title, summary, tags."},
        {"role": "user", "content": "Summarize this article."},
    ],
    response_format={"type": "json_object"},   # OpenAI-compatible
)
data = json.loads(resp.choices[0].message.content)
Enter fullscreen mode Exit fullscreen mode

Cost Control for Agent Loops

Cost lever How much it saves
DeepSeek V4 Flash base price $0.14/1M in — already 100x cheaper than frontier
Context caching Repeat tool definitions cached — up to ~90% off repeat input
Shorten tool descriptions Trim schema docs; fewer tokens every loop
Cap max_tokens A runaway tool response costs 20x a normal one
Batch tool calls Ask for multiple calls in one turn where possible

A typical 5-turn agent session on DeepSeek V4 Flash costs well under $0.01 — cheap enough for interactive products.


Common Pitfalls

  1. Forgetting the tool result round-trip — the model needs the role: "tool" message or it loses context.
  2. Huge tool schemas — every token in the schema is paid on every call. Keep descriptions tight.
  3. No fallback for parse failures — wrap json.loads in try/except; retry with a clearer prompt.
  4. Ignoring cache hits — repeated identical tool definitions are cached automatically; don't vary them per request.

FAQ

Q: Does DeepSeek V4 support function calling?
A: Yes — OpenAI-style tool calling, reliable structured JSON for agents.

Q: How do I get structured JSON from DeepSeek V4?
A: Use the tools parameter or response_format: {"type": "json_object"} — OpenAI-compatible, works via TokenPAPA's endpoint.

Q: Is function calling expensive?
A: No — $0.14/1M in, $0.42/1M out. Even multi-turn agent loops stay under $0.01.

Q: Can I build agents with DeepSeek V4?
A: Yes — 82.7 on Terminal Bench 2.1 makes it a strong budget agent backbone.


Get Started

  1. Sign up at tokenpapa.ai — get $1 free credit
  2. Create your API key — OpenAI-compatible
  3. Build your first tool call — code above, live
from openai import OpenAI
client = OpenAI(base_url="https://tokenpapa.ai/v1", api_key="your-key")

resp = client.chat.completions.create(
    model="deepseek-v4-flash",
    messages=[{"role": "user", "content": "Extract the city from: I live in Beijing."}],
    tools=tools,
)
print(resp.choices[0].message.tool_calls[0].function.arguments)
Enter fullscreen mode Exit fullscreen mode

Originally published at https://doc.tokenpapa.ai/en/docs/blog/deepseek-v4-function-calling.

Top comments (0)