DEV Community

Cover image for Cách sử dụng Function Calling với DeepSeek V4 Pro API
Sebastian Petrus
Sebastian Petrus

Posted on Originally published at apidog.com

Cách sử dụng Function Calling với DeepSeek V4 Pro API

DeepSeek đã đưa V4 Pro ra khỏi giai đoạn xem trước vào ngày 12 tháng 8 năm 2026, và phạm vi đưa tin ra mắt tập trung vào các quy trình làm việc tự động (agentic workflows): lập trình, sử dụng công cụ và các tác vụ dài hạn liên kết hàng chục bước mà không làm mất đi mạch lạc. Định vị này khiến một tính năng API trở nên quan trọng hơn bất kỳ tính năng nào khác, đó là function calling, và đây là tính năng mà các hướng dẫn tuần ra mắt chưa đề cập. Mọi hướng dẫn cho đến nay đều dừng lại ở chat completions.

Dùng thử Apidog ngay hôm nay

Hướng dẫn này sẽ đi xa hơn: định nghĩa một tool schema, thực hiện lệnh gọi công cụ đầu tiên bằng SDK openai tiêu chuẩn của Python, xây dựng vòng lặp tác nhân hoàn chỉnh, sau đó kiểm tra toàn bộ quá trình trong Apidog trước khi triển khai tác nhân. Nếu chưa có khóa API DeepSeek, hãy thiết lập khóa theo hướng dẫn cách sử dụng API DeepSeek V4, sau đó quay lại đây.

Tóm gọn

  • deepseek-v4-pro (bản GA DeepSeek-V4-Pro-0813) hỗ trợ function calling theo kiểu OpenAI: gửi mảng tools, nhận tool_calls, rồi trả kết quả qua tin nhắn có role tool. SDK openai tiêu chuẩn hoạt động với https://api.deepseek.com.
  • Bạn có thể triển khai vòng lặp tác nhân đầy đủ trong khoảng 30 dòng Python: gọi mô hình, thực thi tool, thêm kết quả vào lịch sử, rồi lặp đến khi mô hình không còn yêu cầu tool. Lệnh gọi song song và đầu ra có cấu trúc được hỗ trợ; chế độ tư duy bổ sung reasoning_content.
  • Tính năng lưu trữ tiền tố tự động định giá đầu vào truy cập từ bộ nhớ đệm ở mức 0,003625 USD cho mỗi triệu token, rẻ hơn 120 lần so với khi bỏ lỡ bộ đệm. Đây là yếu tố giúp các vòng lặp tác nhân sâu trở nên khả thi về chi phí.
  • Chất lượng gọi tool phụ thuộc vào harness và schema. Hãy kiểm thử tool schema thực tế của bạn trực tiếp với mô hình, thay vì chỉ dựa vào benchmark.

Tại sao gọi tool là trường hợp sử dụng nổi bật của V4 Pro

DeepSeek xây dựng V4 Pro cho tác nhân, và bảng thông số kỹ thuật này gần như là checklist cho môi trường chạy tác nhân:

Thông số DeepSeek V4 Pro
Kiến trúc Sparse MoE: 1.6T tổng tham số, 49B hoạt động mỗi token
Cửa sổ ngữ cảnh 1M token
Đầu ra tối đa 384K token
Giá đầu vào 0,435 USD/M token (truy cập bộ đệm thất bại), 0,003625 USD/M (truy cập bộ đệm thành công)
Giá đầu ra 0,87 USD/M token
Gọi hàm Mảng tools và phản hồi tool_calls tương thích OpenAI
Các giao diện khác Định dạng tin nhắn Anthropic, API Phản hồi DeepSeek

Mỗi dòng đều giải quyết một vấn đề của tác nhân: cửa sổ ngữ cảnh 1 triệu token có thể chứa lịch sử kết quả tool dài, giới hạn đầu ra 384K token phù hợp với payload có cấu trúc lớn, còn lưu trữ tiền tố giữ chi phí vòng lặp ở mức thấp. Mô hình được liệt kê trên OpenRouter dưới tên deepseek-v4-pro-0813 để so sánh giữa các nhà cung cấp.

Tuy nhiên, hãy kiểm tra bằng harness của chính bạn. Trong cuộc thảo luận ra mắt trên Hacker News, các nhà phát triển báo cáo hiệu suất gọi tool rất nhạy cảm với framework, prompt và cách viết schema. Cùng một mô hình có thể hoạt động tốt hoặc kém tùy theo những yếu tố này. Benchmark không phản ánh chính xác cách mô hình xử lý tool schema thực tế của bạn.

Cách hoạt động của function calling trong DeepSeek

Function calling không có nghĩa mô hình tự thực thi mã. Thay vào đó, mô hình trả về yêu cầu có cấu trúc, ví dụ: gọi get_order với {"order_id": "ORD-10442"}. Runtime của bạn thực thi hàm, trả kết quả về cho mô hình, rồi mô hình tiếp tục với dữ liệu thực.

Chu trình gồm 5 bước:

  1. Gửi messages cùng mảng tools mô tả các hàm bằng JSON Schema.
  2. Mô hình quyết định cần tool và trả về tool_calls với finish_reason: "tool_calls".
  3. Mã của bạn phân tích đối số và chạy hàm thực tế.
  4. Thêm kết quả dưới dạng tin nhắn role: "tool", liên kết với ID của tool call.
  5. Mô hình yêu cầu tool tiếp theo hoặc tạo câu trả lời cuối cùng.

Nếu bạn từng dùng function calling của OpenAI, định dạng giao tiếp là tương tự. Phần lớn mã tác nhân có thể chuyển sang DeepSeek chỉ bằng cách đổi base URL và tên model. Tài liệu chính thức của DeepSeek cũng đề cập endpoint tin nhắn tương thích Anthropic và API Phản hồi, nhưng hướng dẫn này tập trung vào giao diện tương thích OpenAI.

Bước 1: Thiết lập client

Cài SDK và thiết lập biến môi trường:

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

Khởi tạo client với base URL của DeepSeek:

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

Các ví dụ bên dưới dùng model="deepseek-v4-pro", được phân giải thành bản dựng GA DeepSeek-V4-Pro-0813.

Bước 2: Định nghĩa tool schema

Ví dụ này xây dựng tác nhân hỗ trợ cho một cửa hàng trực tuyến. Tool đầu tiên tra cứu trạng thái đơn hàng.

Một tool definition cần ba thành phần:

  • Tên hàm.
  • Mô tả rõ khi nào mô hình nên dùng hàm.
  • JSON Schema cho tham số.
tools = [
    {
        "type": "function",
        "function": {
            "name": "get_order",
            "description": (
                "Tra cứu đơn hàng của khách hàng bằng ID. Trả về trạng thái đơn hàng, "
                "nhà vận chuyển, số theo dõi và ngày giao hàng ước tính. Dùng công cụ này "
                "khi người dùng hỏi đơn hàng đang ở đâu hoặc trạng thái đơn hàng."
            ),
            "parameters": {
                "type": "object",
                "properties": {
                    "order_id": {
                        "type": "string",
                        "description": "ID đơn hàng, định dạng như 'ORD-10442'.",
                    }
                },
                "required": ["order_id"],
            },
        },
    }
]
Enter fullscreen mode Exit fullscreen mode

Mô tả không chỉ để làm tài liệu. Mô hình sử dụng phần này để quyết định có gọi tool hay không. Mô tả mơ hồ là nguyên nhân phổ biến khiến mô hình bỏ qua tool hoặc chọn nhầm tool.

Tiếp theo, tạo hàm cục bộ. Trong production, hàm này thường gọi API hoặc truy vấn database thực:

def get_order(order_id: str) -> dict:
    """Stub thay cho dịch vụ đặt hàng thực tế."""
    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

Bước 3: Thực hiện lệnh gọi tool đầu tiên

Gửi câu hỏi mà mô hình không thể trả lời nếu không truy cập dữ liệu đơn hàng:

messages = [
    {
        "role": "system",
        "content": "Bạn là một tác nhân hỗ trợ cho một cửa hàng trực tuyến.",
    },
    {
        "role": "user",
        "content": "Đơn hàng ORD-10442 của tôi ở đâu?",
    },
]

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

Thay vì tự trả lời, mô hình yêu cầu runtime chạy get_order. Payload thô có dạng:

{
  "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

Có ba điểm cần xử lý trong code:

  • finish_reason: "tool_calls" nghĩa là mô hình đang chờ bạn thực thi tool.
  • Mỗi tool call có một id; bạn phải gửi lại ID này cùng kết quả.
  • arguments là chuỗi JSON, không phải object Python. Hãy luôn parse và validate trước khi gọi hàm.

Bước 4: Thực thi hàm và trả kết quả

Sau khi nhận tool call, hãy:

  1. Phân tích chuỗi JSON trong arguments.
  2. Chạy hàm.
  3. Thêm tin nhắn assistant chứa tool_calls vào lịch sử.
  4. Thêm tin nhắn tool tương ứng.
  5. Gọi lại mô hình để nhận câu trả lời cuối cùng.
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)
# Đơn hàng ORD-10442 của bạn đã được vận chuyển bằng DHL và dự kiến đến nơi
# vào ngày 15 tháng 8 năm 2026. Số theo dõi: 4281337005.
Enter fullscreen mode Exit fullscreen mode

Liên kết tool_call_id là bắt buộc. Mỗi phần tử trong tool_calls cần một tin nhắn tool tương ứng trước lượt phản hồi tiếp theo của mô hình. Nếu thiếu, yêu cầu sẽ thất bại.

Bước 5: Xây dựng vòng lặp tác nhân hoàn chỉnh

Tác nhân thực tế thường cần liên kết nhiều tool call: tra cứu đơn hàng, kiểm tra chính sách hoàn tiền, soạn email, rồi tạo phản hồi. Mẫu triển khai là tiếp tục gọi mô hình và thực thi các tool được yêu cầu cho đến khi nhận được câu trả lời thông thường.

import json

TOOLS_BY_NAME = {
    "get_order": get_order,
}

def run_agent(client, messages, tools, max_rounds=10):
    """Chạy mô hình cho đến khi có câu trả lời cuối cùng hoặc đạt giới hạn lượt."""
    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)

        # Không còn tool call: mô hình đã trả lời xong.
        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:
                # Trả lỗi về cho mô hình để nó có thể điều chỉnh lời gọi.
                result = {"error": str(exc)}

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

    raise RuntimeError(
        f"Tác nhân không hoàn thành trong vòng {max_rounds} lượt"
    )
Enter fullscreen mode Exit fullscreen mode

Framework và SDK tác nhân đều là phần mở rộng của vòng lặp này. Đặt max_rounds để biến trường hợp mô hình lặp lại một tool thất bại thành lỗi rõ ràng, thay vì tạo chi phí không giới hạn.

Các lệnh gọi tool song song

Với yêu cầu như “so sánh trạng thái của ORD-10442 và ORD-10587”, V4 Pro thường có thể gộp cả hai tra cứu trong một lượt:

"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

Hàm run_agent đã xử lý trường hợp này: vòng lặp bên trong phản hồi từng tool call bằng tool_call_id riêng. Nếu các tool độc lập, bạn có thể thực thi chúng đồng thời để giảm độ trễ.

Đây là triết lý khác với function calling có lập trình của GPT-5.6, nơi mô hình viết mã điều phối trong sandbox. Với DeepSeek, việc thực thi và ranh giới tin cậy vẫn nằm trong runtime của bạn.

Chế độ tư duy và tool calling

V4 Pro có ba chế độ tư duy. Bạn có thể tăng cường suy luận cho các lượt lập kế hoạch phức tạp và bỏ qua nó ở những tra cứu thông thường. Xem tài liệu chính thức để biết tên chế độ và cấu hình mặc định.

Khi bật chế độ tư duy, API trả về dấu vết của mô hình trong reasoning_content cùng với các tool call:

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)
# Dấu vết lập kế hoạch

print(message.tool_calls)
# Các lệnh gọi mà mô hình đã quyết định
Enter fullscreen mode Exit fullscreen mode

Dấu vết này có thể giúp xác định lý do mô hình chọn một tool, đặc biệt khi schema chưa tốt. Tuy nhiên, hãy loại bỏ reasoning_content trước khi thêm lượt assistant vào lịch sử. Chỉ dùng chế độ tư duy cho các lượt nặng về lập kế hoạch, vì token suy luận được tính là đầu ra ở mức 0,87 USD/M.

Xử lý lỗi khi mô hình gọi tool sai

Tool call sai định dạng có thể hiếm, nhưng vòng lặp tác nhân sẽ khuếch đại mọi chế độ lỗi. Quy tắc triển khai quan trọng: không làm sập tác nhân chỉ vì một tool call lỗi. Thay vào đó, trả lỗi như kết quả tool để mô hình có cơ hội thử lại.

Ví dụ dưới đây xử lý JSON không hợp lệ và dữ liệu không đạt JSON Schema:

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"Các đối số không hợp lệ: {exc}",
        "hint": (
            "Gọi lại get_order với một chuỗi order_id "
            "như 'ORD-10442'."
        ),
    }
Enter fullscreen mode Exit fullscreen mode

Trường hint rất hữu ích: một chỉ dẫn sửa lỗi cụ thể thường giúp mô hình tạo lời gọi đúng ở vòng tiếp theo.

Ngoài ra, hãy coi lỗi tool là sự kiện bảo mật. Một mô hình bị thuyết phục gọi delete_order bằng đối số do kẻ tấn công cung cấp chỉ nguy hiểm tương ứng với quyền của credential mà tool dùng. Vì vậy, hãy dùng khóa API với quyền hạn tối thiểu cho tác nhân AI và giới hạn phạm vi credential để một tool call sai không trở thành sự cố.

Kiểm tra và gỡ lỗi tool calling với Apidog trước khi triển khai

Mỗi tool thực tế là một lớp bọc mỏng quanh API, và mô hình trở thành một consumer của API đó. Nếu endpoint không rõ ràng hoặc phản hồi không ổn định, tác nhân sẽ kế thừa toàn bộ vấn đề này.

Bạn có thể dùng Apidog trong quy trình kiểm thử theo các bước sau:

  1. Thiết kế API hỗ trợ trước. Định nghĩa GET /orders/{order_id} trong trình thiết kế trực quan của Apidog. Tool schema nên phản ánh trực tiếp API spec để tránh schema và API lệch nhau.
  2. Mô phỏng trước khi backend hoàn thiện. Tính năng mock thông minh của Apidog cung cấp phản hồi từ schema, cho phép bạn chạy vòng lặp tác nhân với get_order trong khi dịch vụ thực vẫn đang được xây dựng.
  3. Kiểm tra payload thô. Gửi cùng nội dung messagestools đến https://api.deepseek.com từ Apidog, rồi xem trực tiếp JSON tool_calls. Các lỗi như properties lồng sai hoặc đối số bị mã hóa hai lần sẽ dễ thấy hơn.
  4. Chuyển hội thoại thành test scenario. Xác nhận finish_reason, tên tool và hình dạng đối số. Chạy bộ test này sau mỗi thay đổi schema. Với độ nhạy theo harness được báo cáo trên Hacker News, regression suite trên schema thực tế là benchmark hữu ích nhất cho production.

Xem cách tích hợp tác nhân AI vào harness kiểm thử Apidog để tham khảo mẫu triển khai sâu hơn.

Tải Apidog miễn phí để làm theo; máy chủ mock và các kịch bản kiểm thử được bao gồm trong gói miễn phí.

Chi phí của vòng lặp tác nhân và vai trò của lưu trữ tiền tố

Vòng lặp tác nhân gửi lại toàn bộ hội thoại ở mỗi lượt. Đến lượt thứ mười, system prompt, tool schema và kết quả của chín lượt trước đều tiếp tục xuất hiện trong input.

Tính năng lưu trữ tiền tố tự động của V4 Pro thay đổi chi phí này. Input của mỗi lượt thường là input lượt trước cộng thêm một phần nhỏ, nên phần lớn tiền tố có thể được tính ở mức 0,003625 USD/M thay vì 0,435 USD/M.

Ví dụ, đọc lại hội thoại 100K token tốn khoảng:

  • 0,0435 USD nếu không có cache.
  • 0,0004 USD nếu dùng cache.

Theo dõi prompt_cache_hit_tokens trong khối usage để xem tỷ lệ cache hit thực tế.

Để giữ tỷ lệ này cao:

  • Không thay đổi các tin nhắn trước đó giữa các lượt.
  • Giữ mảng tools ổn định ở cấp độ byte qua các lượt.
  • Tránh tái tạo schema với thứ tự key hoặc mô tả thay đổi không cần thiết.

Bài viết prompt caching là gì giải thích thêm cơ chế này.

Nếu deepseek-v4-flash với giá 0,14 USD/0,28 USD có vẻ hấp dẫn, nó phù hợp hơn cho định tuyến tool một lần. Với các vòng lặp liên kết hơn 10 lệnh gọi, lỗi và retry có thể làm mất lợi ích chi phí; Pro là lựa chọn mặc định an toàn hơn cho tác nhân.

Câu hỏi thường gặp

Các định nghĩa tool có tốn token không?

Có. Mảng tools là input trong mọi request. Giữ nó ổn định để nó trở thành một phần của tiền tố được lưu trữ sau lượt đầu tiên và được tính theo giá cache hit ở các lượt sau.

Có thể kết hợp function calling với đầu ra có cấu trúc không?

Có. Một mẫu phổ biến là dùng tool để lấy dữ liệu trung gian, sau đó dùng output schema để định dạng câu trả lời cuối cùng. Nhờ vậy, mã hạ nguồn không cần phân tích văn xuôi.

Tổng kết

Triển khai function calling trên DeepSeek V4 Pro tương đối trực tiếp: schema tương thích OpenAI, mảng tool_calls và tin nhắn tool mang đúng ID. Vòng lặp ở Bước 5 là nền tảng của toàn bộ kiến trúc tác nhân.

Điểm cần đầu tư không chỉ là model mà còn là tool schema, API hỗ trợ, xử lý lỗi và regression test. Hãy thiết kế API rõ ràng, mô phỏng sớm, kiểm tra payload thô và duy trì bộ test cho các kịch bản gọi tool trong Apidog. Cách này giúp thay đổi schema không âm thầm làm hỏng tác nhân khi lên production.

Top comments (0)