DEV Community

Cover image for วิธีใช้ Function Calling กับ DeepSeek V4 Pro API
Thanawat Wongchai
Thanawat Wongchai

Posted on Originally published at apidog.com

วิธีใช้ Function Calling กับ DeepSeek V4 Pro API

DeepSeek นำ V4 Pro ออกจากการแสดงตัวอย่างเมื่อวันที่ 12 สิงหาคม 2026 และรายงานการเปิดตัวเน้นเวิร์กโฟลว์เอเจนต์ เช่น การเขียนโค้ด การใช้เครื่องมือ และงานหลายขั้นตอนที่ต้องรักษาเป้าหมายต่อเนื่อง ความสามารถ API ที่สำคัญจึงไม่ใช่แค่การสร้างข้อความแชท แต่คือการเรียกใช้ฟังก์ชัน (function calling)

ลองใช้ Apidog วันนี้

บทความนี้จะพาคุณสร้าง agent loop ที่เรียกใช้เครื่องมือจริงด้วย Python และ SDK openai ตั้งแต่กำหนด JSON Schema, รับ tool_calls, ส่งผลลัพธ์กลับด้วยข้อความ tool ไปจนถึงทดสอบ request/response ใน Apidog ก่อนนำไปใช้งานจริง หากยังไม่มี API key ให้เริ่มจากคู่มือวิธีการใช้ DeepSeek V4 API

สรุป

  • deepseek-v4-pro (GA build DeepSeek-V4-Pro-0813) รองรับ function calling แบบ OpenAI: ส่ง tools, รับ tool_calls และส่งผลลัพธ์กลับด้วยข้อความ tool
  • ใช้ SDK openai มาตรฐานได้โดยตั้ง base_url เป็น https://api.deepseek.com
  • agent loop ที่ใช้งานได้จริงประกอบด้วย: เรียกโมเดล → รันเครื่องมือ → เพิ่มผลลัพธ์ → ทำซ้ำจนได้คำตอบสุดท้าย
  • คุณภาพการเรียกใช้เครื่องมือขึ้นอยู่กับคำอธิบายและ JSON Schema ของเครื่องมือ จึงควรทดสอบกับสกีมาจริงของระบบคุณ
  • การแคชคำนำหน้าช่วยลดต้นทุนอินพุตที่ถูกแคชจาก $0.435/M เหลือ $0.003625/M โทเค็น

เหตุใด function calling จึงเหมาะกับ V4 Pro

V4 Pro ถูกวางตำแหน่งสำหรับงานเอเจนต์ โดยมีสเปกที่เหมาะกับลูปหลายขั้นตอน:

สเปก DeepSeek V4 Pro
สถาปัตยกรรม Sparse MoE: พารามิเตอร์รวม 1.6 ล้านล้าน, 49 พันล้านที่ทำงานต่อโทเค็น
หน้าต่างบริบท 1M โทเค็น
เอาต์พุตสูงสุด 384K โทเค็น
ราคาอินพุต $0.435/M โทเค็น (แคชพลาด), $0.003625/M (แคชสำเร็จ)
ราคาเอาต์พุต $0.87/M โทเค็น
Function calling tools แบบ OpenAI และการตอบกลับ tool_calls
อินเทอร์เฟซอื่น Anthropic Messages format, DeepSeek Responses API

หน้าต่างบริบทขนาดใหญ่ช่วยเก็บประวัติการเรียกเครื่องมือและผลลัพธ์หลายรอบได้ ขณะที่การแคชคำนำหน้าช่วยลดต้นทุนของการส่งประวัติเดิมซ้ำในทุกเทิร์น

สำหรับการเปรียบเทียบผู้ให้บริการ โมเดลนี้ระบุใน OpenRouter เป็น deepseek-v4-pro-0813

ข้อควรระวัง: นักพัฒนาในการสนทนาบน Hacker Newsรายงานว่าผลลัพธ์การเรียกใช้เครื่องมือไวต่อโครงสร้างของ prompt, framework และ schema มาก อย่าใช้ benchmark เป็นคำตอบสุดท้าย ให้ทดสอบกับสกีมาและสถานการณ์จริงของคุณ

วิธีทำงานของ DeepSeek function calling

โมเดลไม่ได้รันฟังก์ชันแทนคุณ แต่ส่งคำขอที่มีโครงสร้างกลับมา เช่น:

{
  "name": "get_order",
  "arguments": "{\"order_id\": \"ORD-10442\"}"
}
Enter fullscreen mode Exit fullscreen mode

จากนั้น runtime ของคุณต้องรันฟังก์ชัน ส่งผลลัพธ์กลับไป และให้โมเดลตัดสินใจขั้นตอนถัดไป

ลำดับการทำงานมีดังนี้:

  1. ส่ง messages พร้อมอาร์เรย์ tools ที่อธิบายฟังก์ชันด้วย JSON Schema
  2. โมเดลตอบกลับด้วย tool_calls และ finish_reason: "tool_calls"
  3. โค้ดของคุณแยก JSON arguments แล้วเรียกฟังก์ชันจริง
  4. เพิ่มผลลัพธ์เป็นข้อความ role: "tool" พร้อม tool_call_id
  5. เรียกโมเดลอีกครั้งจนกว่าจะตอบข้อความสุดท้าย

หากเคยใช้OpenAI function callingคุณสามารถใช้รูปแบบเดียวกันได้เกือบทั้งหมด โดยเปลี่ยน base URL และชื่อโมเดลเท่านั้น ดูอินเทอร์เฟซอื่นเพิ่มเติมได้จากเอกสาร DeepSeek

ขั้นตอนที่ 1: ตั้งค่าไคลเอนต์

ติดตั้ง SDK และตั้งค่า API key:

pip install openai
export DEEPSEEK_API_KEY="sk-..."
Enter fullscreen mode Exit fullscreen mode

สร้างไคลเอนต์โดยชี้ไปที่ DeepSeek API:

import os
from openai import OpenAI

client = OpenAI(
    api_key=os.environ["DEEPSEEK_API_KEY"],
    base_url="https://api.deepseek.com",
)
Enter fullscreen mode Exit fullscreen mode

ตัวอย่างทั้งหมดด้านล่างใช้โมเดล deepseek-v4-pro ซึ่งแปลงเป็น GA build DeepSeek-V4-Pro-0813

ขั้นตอนที่ 2: กำหนดสกีมาเครื่องมือ

ตัวอย่างนี้สร้างเครื่องมือ get_order สำหรับค้นหาสถานะคำสั่งซื้อ

tools = [
    {
        "type": "function",
        "function": {
            "name": "get_order",
            "description": (
                "Look up a customer order by its ID. Returns the order status, "
                "carrier, tracking number, and estimated delivery date. Use this "
                "whenever the user asks where an order is or what state it's in."
            ),
            "parameters": {
                "type": "object",
                "properties": {
                    "order_id": {
                        "type": "string",
                        "description": "The order ID, formatted like 'ORD-10442'.",
                    }
                },
                "required": ["order_id"],
            },
        },
    }
]
Enter fullscreen mode Exit fullscreen mode

คำอธิบายของเครื่องมือมีผลโดยตรงต่อการตัดสินใจของโมเดล ควรระบุให้ชัดเจนว่า:

  • เครื่องมือนี้ใช้ทำอะไร
  • ควรเรียกใช้ในสถานการณ์ใด
  • ส่งคืนข้อมูลอะไร
  • พารามิเตอร์แต่ละตัวมีรูปแบบอย่างไร

สร้าง implementation แบบจำลองก่อนเชื่อมต่อบริการจริง:

def get_order(order_id: str) -> dict:
    """Stub for your real order service."""
    fake_db = {
        "ORD-10442": {
            "status": "shipped",
            "carrier": "DHL",
            "tracking_number": "4281337005",
            "estimated_delivery": "2026-08-15",
        },
        "ORD-10587": {
            "status": "processing",
            "estimated_ship_date": "2026-08-14",
        },
    }
    return fake_db.get(order_id, {"error": f"Unknown order ID: {order_id}"})
Enter fullscreen mode Exit fullscreen mode

ขั้นตอนที่ 3: เรียกใช้เครื่องมือครั้งแรก

ส่งคำถามที่ต้องใช้ข้อมูลจากระบบภายนอก:

messages = [
    {"role": "system", "content": "You are a support agent for an online store."},
    {"role": "user", "content": "Where is my order ORD-10442?"},
]

response = client.chat.completions.create(
    model="deepseek-v4-pro",
    messages=messages,
    tools=tools,
)

message = response.choices[0].message

print(message.tool_calls[0].function.name)
# get_order

print(message.tool_calls[0].function.arguments)
# {"order_id": "ORD-10442"}
Enter fullscreen mode Exit fullscreen mode

โมเดลจะไม่ตอบสถานะคำสั่งซื้อโดยตรง แต่ร้องขอให้ runtime ของคุณรัน get_order

ตัวอย่าง response แบบดิบ:

{
  "id": "chatcmpl-8f3a1c",
  "object": "chat.completion",
  "model": "deepseek-v4-pro",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": "",
        "tool_calls": [
          {
            "id": "call_0_f1c29a44",
            "type": "function",
            "function": {
              "name": "get_order",
              "arguments": "{\"order_id\": \"ORD-10442\"}"
            }
          }
        ]
      },
      "finish_reason": "tool_calls"
    }
  ],
  "usage": {
    "prompt_tokens": 312,
    "completion_tokens": 24,
    "total_tokens": 336,
    "prompt_cache_hit_tokens": 0,
    "prompt_cache_miss_tokens": 312
  }
}
Enter fullscreen mode Exit fullscreen mode

จุดที่ต้องตรวจสอบ:

  • finish_reason เป็น "tool_calls" หมายถึงต้องประมวลผลเครื่องมือ
  • ทุก tool_call มี id เฉพาะ
  • arguments เป็น JSON string จึงต้องใช้ json.loads()

ขั้นตอนที่ 4: รันฟังก์ชันและส่งผลลัพธ์กลับ

เพิ่มทั้งข้อความ assistant ที่มี tool_calls และข้อความ tool ที่มีผลลัพธ์:

import json

tool_call = message.tool_calls[0]
args = json.loads(tool_call.function.arguments)

result = get_order(**args)

messages.append(message)

messages.append({
    "role": "tool",
    "tool_call_id": tool_call.id,
    "content": json.dumps(result),
})

final = client.chat.completions.create(
    model="deepseek-v4-pro",
    messages=messages,
    tools=tools,
)

print(final.choices[0].message.content)
Enter fullscreen mode Exit fullscreen mode

ตัวอย่างคำตอบสุดท้าย:

Your order ORD-10442 shipped with DHL and is estimated to arrive
by August 15, 2026. Tracking number: 4281337005.
Enter fullscreen mode Exit fullscreen mode

tool_call_id ต้องตรงกับ ID ที่โมเดลส่งมา ทุก tool_call ต้องมีข้อความ tool ที่จับคู่กันก่อนเรียกโมเดลในเทิร์นถัดไป

ขั้นตอนที่ 5: สร้าง agent loop แบบเต็ม

เอเจนต์จริงอาจเรียกใช้หลายเครื่องมือต่อเนื่องกัน เช่น ค้นหาคำสั่งซื้อ ตรวจสอบนโยบายคืนสินค้า แล้วร่างอีเมลตอบลูกค้า

ใช้ loop ที่เรียกโมเดลซ้ำจนกว่าจะไม่มี tool_calls:

import json

TOOLS_BY_NAME = {
    "get_order": get_order,
}

def run_agent(client, messages, tools, max_rounds=10):
    """Run the model until it produces a final answer or hits the cap."""
    for _ in range(max_rounds):
        response = client.chat.completions.create(
            model="deepseek-v4-pro",
            messages=messages,
            tools=tools,
        )

        message = response.choices[0].message
        messages.append(message)

        if not message.tool_calls:
            return message.content

        for tool_call in message.tool_calls:
            fn = TOOLS_BY_NAME.get(tool_call.function.name)

            try:
                if fn is None:
                    raise ValueError(
                        f"Unknown tool: {tool_call.function.name}"
                    )

                args = json.loads(tool_call.function.arguments)
                result = fn(**args)

            except Exception as exc:
                result = {"error": str(exc)}

            messages.append({
                "role": "tool",
                "tool_call_id": tool_call.id,
                "content": json.dumps(result),
            })

    raise RuntimeError(f"Agent did not finish within {max_rounds} rounds")
Enter fullscreen mode Exit fullscreen mode

ตั้ง max_rounds เสมอ เพื่อป้องกันลูปไม่สิ้นสุดเมื่อโมเดลเรียกเครื่องมือซ้ำหลังเกิดข้อผิดพลาด

การเรียกใช้เครื่องมือแบบขนาน

หากผู้ใช้ถามว่า:

เปรียบเทียบสถานะของ ORD-10442 และ ORD-10587

โมเดลอาจส่งคำขอสองรายการใน response เดียว:

"tool_calls": [
  {
    "id": "call_0_a7d1",
    "type": "function",
    "function": {
      "name": "get_order",
      "arguments": "{\"order_id\": \"ORD-10442\"}"
    }
  },
  {
    "id": "call_1_b3e9",
    "type": "function",
    "function": {
      "name": "get_order",
      "arguments": "{\"order_id\": \"ORD-10587\"}"
    }
  }
]
Enter fullscreen mode Exit fullscreen mode

ลูปก่อนหน้านี้รองรับรูปแบบนี้อยู่แล้ว เพราะวนผ่าน message.tool_calls และส่งผลลัพธ์กลับตาม tool_call_id ของแต่ละรายการ

หากเครื่องมือของคุณเป็น I/O-bound เช่น HTTP request หรือ database query คุณสามารถเปลี่ยนส่วนนี้ให้ใช้ asyncio.gather() เพื่อรันคำขอพร้อมกันได้

แนวทางนี้ต่างจากการเรียกใช้เครื่องมือแบบโปรแกรมของ GPT-5.6ซึ่งโมเดลเขียนโค้ดเพื่อจัดการเครื่องมือใน sandbox ขณะที่ DeepSeek ให้ runtime ของคุณเป็นผู้ควบคุมการประมวลผลและขอบเขตความน่าเชื่อถือ

โหมดการคิดพร้อมเครื่องมือ

V4 Pro มีโหมดการคิดหลายแบบเพื่อเพิ่มความพยายามในการวางแผนสำหรับงานซับซ้อน ดูชื่อโหมดและค่าเริ่มต้นจากเอกสารทางการ

เมื่อเปิดใช้งาน API จะส่ง reasoning_content พร้อม tool_calls:

response = client.chat.completions.create(
    model="deepseek-v4-pro",
    messages=messages,
    tools=tools,
    extra_body={"thinking": {"type": "enabled"}},
)

message = response.choices[0].message

print(message.reasoning_content)
print(message.tool_calls)
Enter fullscreen mode Exit fullscreen mode

ใช้ reasoning_content เพื่อดีบักการเลือกเครื่องมือและสกีมา แต่ไม่ควรเพิ่มฟิลด์นี้กลับเข้าสู่ประวัติข้อความ ควรเปิดโหมดคิดเฉพาะเทิร์นที่ต้องวางแผนมาก เพราะ reasoning มีค่าใช้จ่ายตามราคาเอาต์พุต $0.87/M โทเค็น

จัดการข้อผิดพลาดของ arguments

อย่าปล่อยให้ agent ล้มเหลวทันทีเมื่อโมเดลส่ง JSON ผิดรูปแบบหรือค่าที่ไม่ผ่านกฎธุรกิจ ให้ส่งข้อผิดพลาดกลับเป็นผลลัพธ์ของเครื่องมือเพื่อให้โมเดลแก้ไขการเรียกครั้งถัดไป

import json
from jsonschema import ValidationError, validate

schema = tools[0]["function"]["parameters"]

try:
    args = json.loads(tool_call.function.arguments)
    validate(instance=args, schema=schema)
    result = get_order(**args)

except (json.JSONDecodeError, ValidationError) as exc:
    result = {
        "error": f"Invalid arguments: {exc}",
        "hint": (
            "Call get_order again with an order_id string "
            "like 'ORD-10442'."
        ),
    }
Enter fullscreen mode Exit fullscreen mode

hint ที่ชัดเจนช่วยให้โมเดลแก้ไขคำขอได้ในรอบถัดไป

นอกจากนี้ ให้ถือว่าการเรียกเครื่องมือเป็นขอบเขตด้านความปลอดภัยด้วย หากโมเดลถูกชักจูงให้เรียกเครื่องมือทำลายข้อมูล เช่น delete_order ความเสียหายขึ้นอยู่กับสิทธิ์ของ credential ที่ runtime ใช้ ควรใช้API key ที่มีสิทธิ์น้อยที่สุดสำหรับ AI agentsและแยกสิทธิ์ read/write ออกจากกัน

ทดสอบและดีบัก tool calling ด้วย Apidog

เครื่องมือของเอเจนต์มักเป็น wrapper รอบ API ภายในหรือ API ภายนอก ดังนั้นคุณควรทดสอบทั้ง API และ payload ที่ส่งให้โมเดล

ใช้ Apidog ในขั้นตอนดังนี้:

  1. ออกแบบ API ที่รองรับก่อน

    กำหนด GET /orders/{order_id} ใน visual designer แล้วใช้สเปกเดียวกันเป็นต้นทางของ JSON Schema สำหรับเครื่องมือ

  2. Mock ก่อนสร้าง backend เสร็จ

    สร้าง response จำลองจากสกีมา เพื่อพัฒนา agent loop ได้ก่อนบริการจริงพร้อมใช้งาน

  3. ตรวจสอบ payload ดิบของ DeepSeek

    ส่ง request body เดียวกับที่ใช้ในโค้ด ได้แก่ messages และ tools ไปยัง https://api.deepseek.com แล้วตรวจดู tool_calls โดยตรง

  4. สร้าง regression test สำหรับสกีมา

    ตรวจสอบ finish_reason, ชื่อเครื่องมือ และรูปแบบ arguments ทุกครั้งที่เปลี่ยน schema ดูแนวทางเพิ่มเติมในบทความการเชื่อมต่อ AI agent เข้ากับ Apidog test harness

ดาวน์โหลด Apidogเพื่อเริ่มสร้าง mock server และสถานการณ์ทดสอบ

ค่าใช้จ่ายของ agent loop และการแคช

agent loop จะส่งประวัติการสนทนาเดิมซ้ำในทุกเทิร์น รอบที่ 10 จะรวม system prompt, คำจำกัดความเครื่องมือ และผลลัพธ์จากเก้ารอบก่อนหน้า

การแคชคำนำหน้าอัตโนมัติของ V4 Pro ทำให้ส่วนที่ซ้ำกันถูกคิดค่าบริการที่ $0.003625/M แทน $0.435/M โทเค็น

ตัวอย่างการอ่านประวัติ 100K โทเค็นซ้ำ:

  • ไม่ถูกแคช: ประมาณ $0.0435
  • ถูกแคช: ประมาณ $0.0004

ตรวจสอบอัตราการใช้งานจริงจากฟิลด์ต่อไปนี้:

{
  "prompt_cache_hit_tokens": 0,
  "prompt_cache_miss_tokens": 312
}
Enter fullscreen mode Exit fullscreen mode

เพื่อรักษา cache hit rate:

  • อย่าแก้ไขข้อความก่อนหน้าโดยไม่จำเป็น
  • รักษาลำดับและเนื้อหาของ tools ให้คงที่ระหว่างรอบ
  • เพิ่มข้อความใหม่ต่อท้ายประวัติ แทนการเขียนทับข้อความเดิม

อ่านหลักการเพิ่มเติมได้ในบทความการแคชพร้อมต์

แม้ deepseek-v4-flash ที่ราคา $0.14/$0.28 อาจเหมาะกับการส่งต่อเครื่องมือเพียงครั้งเดียว แต่ในลูปที่มี 10+ รอบ การลองใหม่และการส่งบริบทซ้ำอาจลดข้อได้เปรียบด้านต้นทุนได้ ดังนั้น DeepSeek Pro จึงเป็นค่าเริ่มต้นที่ปลอดภัยกว่าสำหรับเอเจนต์หลายขั้นตอน

คำถามที่พบบ่อย

คำจำกัดความของเครื่องมือมีค่าใช้จ่ายเป็นโทเค็นหรือไม่?

มี อาร์เรย์ tools เป็นส่วนหนึ่งของ input ทุก request อย่างไรก็ตาม หากรักษาไว้ให้คงที่ ระบบสามารถนำไปใช้กับ prefix cache หลังรอบแรกได้

ฉันสามารถรวม function calling กับเอาต์พุตที่มีโครงสร้างได้หรือไม่?

ได้ รูปแบบทั่วไปคือให้เครื่องมือดึงข้อมูลกลาง แล้วใช้สกีมาเอาต์พุตที่มีโครงสร้างจัดรูปแบบคำตอบสุดท้าย วิธีนี้ช่วยให้ระบบปลายน้ำไม่ต้องแยกวิเคราะห์ข้อความธรรมดา

สรุป

Function calling ของ DeepSeek V4 Pro ใช้รูปแบบที่คุ้นเคยสำหรับผู้ใช้ OpenAI-compatible API: กำหนด tools, รับ tool_calls, รันฟังก์ชันใน runtime ของคุณ และส่งผลลัพธ์กลับด้วยข้อความ tool

ส่วนสำคัญที่สุดไม่ใช่ loop เพียงอย่างเดียว แต่คือคุณภาพของ tool schema, การตรวจสอบ arguments, การจำกัดสิทธิ์ของเครื่องมือ และ regression test ที่ครอบคลุมสถานการณ์จริง ออกแบบ API ให้ชัดเจน สร้าง mock ล่วงหน้า และเก็บชุดทดสอบ tool-calling ไว้ใน Apidog เพื่อป้องกันการเปลี่ยนสกีมาที่ทำให้เอเจนต์ทำงานผิดพลาดโดยไม่รู้ตัว

Top comments (0)