0

Hiểu ba giao thức API trước khi cấu hình DeepSeek Harness

Vấn đề

Khi thêm một mô hình bên ngoài vào DeepSeek Harness, hai ô đầu tiên được điền rất nhanh. Bạn dán địa chỉ API, dán khóa API, bấm lấy danh sách mô hình, và mọi thứ hiện ra trong vài giây.

Rồi đến ô thứ ba: API protocol, với ba lựa chọn — OpenAI Chat Completions, OpenAI Responses, Anthropic Messages. Không có dòng chú thích nào nói ba mục này khác nhau ở đâu, và nếu chọn sai thì thông báo lỗi cũng không cho biết đã sai ở chỗ nào.

Bài viết này đi theo thứ tự ngược với thói quen thông thường: giải thích khái niệm trước, rồi mới cấu hình. Nếu bạn đã quen với API, có thể bỏ qua phần thuật ngữ và đọc tiếp từ mục "Ba lựa chọn khác nhau ở đâu".

Menu chọn giao thức API trong phần cài đặt mô hình của DeepSeek Harness

Ảnh chụp giao diện tháng 10 năm 2026. Ô nhập khóa API nằm ngoài khung hình.

Giải thích thuật ngữ

Phần này dành cho người mới bắt đầu. Năm thuật ngữ dưới đây xuất hiện trong gần như mọi tài liệu về API, và hiểu chúng sẽ giúp bạn đọc thông báo lỗi mà không cần đoán.

API (Application Programming Interface) là cách một chương trình nói chuyện với một chương trình khác. Ở đây, DeepSeek Harness gửi yêu cầu đến một dịch vụ mô hình, và dịch vụ đó trả về câu trả lời.

Endpoint (điểm cuối) là một địa chỉ cụ thể mà yêu cầu được gửi tới. Địa chỉ gốc thường trông như https://api.example.com/v1, còn endpoint là phần đường dẫn nối thêm vào, ví dụ /chat/completions hoặc /messages. Cùng một dịch vụ có thể mở nhiều endpoint khác nhau.

Giao thức (protocol) là bộ quy tắc quy định cách viết yêu cầu: trường nào tên là gì, dữ liệu lồng nhau ra sao, thông tin xác thực đặt ở đâu. Ba lựa chọn trong menu chính là ba bộ quy tắc như vậy.

Header (tiêu đề yêu cầu) là phần thông tin phụ đi kèm mỗi yêu cầu, trong đó có thông tin xác thực. Đây là chỗ hay gây lỗi nhất, vì mỗi giao thức đặt khóa API ở một header khác nhau.

Một mẹo nhỏ khi đọc tài liệu: mỗi trang tài liệu API thường ghi rõ ba thứ — endpoint, header dùng để xác thực, và cấu trúc phần thân yêu cầu. Đó cũng chính là ba thứ khác nhau giữa các giao thức, nên đọc theo đúng thứ tự này sẽ nhanh hơn đọc từ đầu đến cuối.

Mã trạng thái (status code) là con số ba chữ số mà dịch vụ trả về. 200 nghĩa là thành công, 401 là chưa xác thực được, 404 là không tìm thấy đường dẫn, 400 là yêu cầu sai định dạng. Chỉ cần đọc đúng bốn con số này là đã loại được phần lớn nguyên nhân.

Hai khái niệm nữa cũng cần biết vì chúng xuất hiện trong phần so sánh bên dưới. Ngữ cảnh (context) là toàn bộ nội dung cuộc trò chuyện mà mô hình cần để trả lời. Gọi công cụ (tool call) là việc mô hình yêu cầu chương trình của bạn chạy một hàm nào đó rồi trả kết quả về.

Ba lựa chọn khác nhau ở đâu

Điểm dễ hiểu nhầm nhất: ba mục này không phải ba mức độ, kiểu bản cơ bản — bản nâng cao — bản chuyên nghiệp. Chúng là ba định dạng song song. Bốn thứ thay đổi khi bạn đổi lựa chọn:

  • Ai giữ ngữ cảnh. Chat Completions và Messages không giữ gì cả, bạn phải gửi lại toàn bộ cuộc trò chuyện mỗi lần. Responses có thể lưu ở phía máy chủ.
  • Chỗ đặt chỉ dẫn hệ thống. Phần tử đầu tiên của messages, trường instructions, hoặc trường system ở cấp cao nhất.
  • Cách gọi công cụ. tool_calls, function_call và tool_use nhìn qua thì giống nhau nhưng cấu trúc khác nhau.
  • Chỗ chứa văn bản trả lời. choices, output, hoặc content.

So sánh ba giao thức: khả năng ghi nhớ, khả năng tự hành động, và khi nào nên chọn

Một điểm nữa cần nói rõ, vì nó khiến nhiều người hiểu sai: chữ "OpenAI" trong tên mục là tên định dạng trao đổi dữ liệu, không phải tên hãng mô hình. Mô hình nào trả lời là do mã mô hình ở ô bên cạnh quyết định.

Hạng mục Chat Completions Responses Messages
Đường dẫn /chat/completions /responses /messages
Xác thực Authorization: Bearer Authorization: Bearer x-api-key và anthropic-version
Chỉ dẫn hệ thống phần tử đầu của messages trường instructions trường system cấp cao nhất
Văn bản trả lời choices output content
Ngữ cảnh không lưu, gửi lại mỗi lần có thể lưu phía máy chủ không lưu, gửi lại mỗi lần

Thực hành: ba bước kiểm tra

Đừng bắt đầu bằng việc trò chuyện. Hãy kiểm tra theo thứ tự: địa chỉ, rồi khóa, rồi đường dẫn, cuối cùng mới đến tên trường. Mỗi bước chỉ kiểm tra một thứ, nên khi có lỗi bạn biết ngay nó nằm ở đâu.

$base    = "https://api.crazyrouter.com/v1"   # ví dụ: Crazyrouter
$headers = @{ Authorization = "Bearer $env:CRAZYROUTER_API_KEY" }

# Bước 1: danh sách mô hình — chỉ kiểm tra địa chỉ và khóa
Invoke-RestMethod -Uri "$base/models" -Headers $headers |
  Select-Object -ExpandProperty data | Select-Object -First 5 -Property id

# Bước 2: gõ vào ba endpoint, chỉ đọc mã trạng thái
foreach ($p in @("/chat/completions", "/responses", "/messages")) {
  $r = Invoke-WebRequest -Uri "$base$p" -Method Post -Headers $headers `
       -ContentType "application/json" -Body "{}" -SkipHttpErrorCheck
  Write-Output ("{0,-20} {1}" -f $p, $r.StatusCode)
}

# Bước 3: yêu cầu nhỏ nhất (đến đây tên trường mới thành vấn đề)
$body = @{
  model    = "deepseek-v4-pro"
  messages = @(@{ role = "user"; content = "Chỉ trả lời OK" })
} | ConvertTo-Json -Depth 5

Invoke-RestMethod -Uri "$base/chat/completions" -Method Post `
  -Headers $headers -ContentType "application/json" -Body $body |
  Select-Object -ExpandProperty choices

Bước 2 có thể chạy không cần khóa: bỏ $headers và gửi phần thân rỗng. Trả về 401 nghĩa là đường dẫn tồn tại; 404 nghĩa là đường dẫn đó không tồn tại. Đây là cách rẻ nhất để biết dịch vụ bạn dùng thực sự mở những endpoint nào.

Kết quả đo ngày 20/10/2026

Tôi chạy đúng ba bước trên với một dịch vụ, dùng cùng một khóa cho mọi lần gọi. Kết quả tóm gọn như sau.

Không có khóa, cả bốn đường dẫn thật đều trả 401, còn một đường dẫn tự đặt trả 404. Nội dung của 401 là 未提供令牌 (chưa cung cấp token), của 404 là Invalid endpoint path. Nghĩa là dịch vụ kiểm tra đường dẫn trước khi kiểm tra khóa.

Có khóa, cả ba endpoint đều trả 200, nhưng văn bản trả lời nằm ở ba chỗ khác nhau: choices, output và content. Thời gian phản hồi từ hai đến bốn giây.

Ba phát hiện đáng chú ý:

Thứ nhất, mã 404 có hai nghĩa. Nếu sai đường dẫn, nội dung là Invalid endpoint path. Nếu sai mã mô hình, nội dung là model_not_found kèm tên mô hình. Cùng một mã, cách xử lý khác nhau, nên luôn phải đọc phần nội dung.

Thứ hai, dịch vụ này dễ tính hơn đặc tả chính thức. Theo tài liệu Anthropic, trường max_tokens là bắt buộc; ở đây bỏ đi vẫn nhận 200. Nó cũng chấp nhận cả x-api-key lẫn Authorization: Bearer. Ngược lại, endpoint kiểu OpenAI chỉ nhận Bearer, đặt khóa vào x-api-key là 401 ngay.

Thứ ba, mã 200 không đồng nghĩa với việc cấu hình đã có tác dụng. Khi gửi chỉ dẫn hệ thống theo kiểu Anthropic vào endpoint Chat Completions, dịch vụ vẫn trả 200, nhưng chỉ dẫn đó bị bỏ qua. Tương tự, store và previous_response_id được chấp nhận và trả về nguyên vẹn, nhưng qua hai bước kiểm tra thì mô hình không hề nhớ nội dung trước đó.

Một điểm nữa đáng ghi lại: cả ba giao thức đều gọi được công cụ, nhưng cú pháp hoàn toàn khác nhau. Chat Completions đặt tham số trong tools[].function.parameters, Messages dùng tools[].input_schema, còn Responses dùng tools[].type=function. Sao chép nguyên xi từ tài liệu của giao thức này sang giao thức khác là cách chắc chắn nhất để gặp lỗi.

Ba bước tách vấn đề đường dẫn khỏi vấn đề tên trường

Khi nào chọn cái nào

  • Không chắc thì chọn OpenAI Chat Completions. Đây là định dạng được nhiều dịch vụ triển khai nhất, và hầu như mọi thông báo lỗi bạn gặp đều đã có người gặp và hỏi trước đó.
  • Chọn Anthropic Messages khi dịch vụ chỉ cung cấp /v1/messages, hoặc khi bạn nối vào một công cụ vốn được viết cho Claude.
  • Responses chỉ nên chọn khi bạn thực sự cần lưu ngữ cảnh phía máy chủ hoặc dùng công cụ có sẵn, và đã tự kiểm tra rằng hai tính năng đó hoạt động.

Có thể tóm lại bằng ba câu hỏi: dịch vụ đứng sau địa chỉ đó là ai; tài liệu của nó ghi những endpoint nào; và lần này bạn chỉ cần trò chuyện hay cần cả ghi nhớ ngữ cảnh lẫn công cụ. Câu trả lời cho câu hỏi thứ hai thường đã đủ để kết thúc việc lựa chọn.

Tổng kết

Điều hữu ích nhất không phải đáp án "chọn cái nào", mà là thứ tự đặt câu hỏi: địa chỉ, rồi khóa, rồi đường dẫn, cuối cùng là tên trường. Menu chọn giao thức chỉ hỏi về hai bước cuối, nên khi mọi thứ đổ vỡ, mã trạng thái mới là thứ cho biết bạn đang đứng ở bước nào.

Để kiểm tra những việc như trên, tôi dùng Crazyrouter: một khóa dùng cho mô hình của nhiều nhà cung cấp, với cổng vào riêng cho định dạng tương thích OpenAI và tương thích Anthropic, nên ba bước ở trên có thể chạy trên cùng một tài khoản.

Nguồn


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí