Doubao API do Volcano Ark cung cấp, hình thức giao diện gần với OpenAI nhưng ngữ nghĩa lỗi có đặc điểm riêng. Điển hình nhất là 404: dịch vụ không sập, vấn đề thường nằm ở ID điểm vào suy luận, tên mô hình, khu vực hoặc đường dẫn. 429 cũng hay bị chẩn đoán nhầm: có thể là giới hạn tốc độ, đồng thời, hạn mức, nợ phí hoặc hết gói tài nguyên, cách xử lý hoàn toàn khác nhau.

Thứ tự điều tra nên cố định năm bước: xem mã trạng thái HTTP, đọc code và message trong phần thân phản hồi, lấy request ID, dùng yêu cầu tối thiểu để tái hiện, cuối cùng mới sửa tham số hoặc đổi mô hình. Bài viết triển khai theo 401, 404, 400, 429, quá thời gian và 5xx, kèm mã xử lý lỗi và danh sách nhật ký. Mô hình và cách tính phí căn cứ theo giá mô hình.

Lưu ý: Doubao, Volcano Ark và Volcano Engine là nhãn hiệu của ByteDance. Bài viết chỉ nhằm mục đích kỹ thuật, không có quan hệ liên kết, đại lý hay hợp tác với ByteDance. Mã lỗi, quy tắc giới hạn tốc độ và hành vi giao diện có thể điều chỉnh theo phiên bản; cuối cùng căn cứ theo tài liệu chính thức và phản hồi thực tế.

1. Phân biệt hai tầng lỗi trước

Mã trạng thái HTTP cho biết kết quả tầng giao thức; code, type, message trong phần thân cho biết nguyên nhân cụ thể. Cùng là 401, có thể do không mang Key, Key viết sai, hết hiệu lực hoặc dự án không có quyền; cùng là 429, có thể do gửi quá nhanh, đồng thời quá cao, hết hạn mức hoặc nợ phí. Chỉ ghi mã trạng thái thì khi điều tra chỉ có thể đoán.

HTTP Ý nghĩa thường gặp Tình huống Doubao Có thử lại
401 Xác thực thất bại Thiếu Key, sai định dạng, hết hiệu lực hoặc không khớp khu vực Không, sửa thông tin xác thực trước
403 Không có quyền Key không có quyền với mô hình hoặc điểm vào đó Không, kiểm tra cấp quyền
404 Tài nguyên không tồn tại Sai ID điểm vào, tên mô hình, đường dẫn hoặc khu vực Không, đối chiếu trước
400 Tham số sai Ngữ cảnh quá dài, max_tokens không hợp lệ, định dạng ảnh không hỗ trợ Không, sửa yêu cầu
429 Giới hạn tốc độ hoặc hạn mức Vượt RPM, TPM, đồng thời; nợ phí hoặc hết gói tài nguyên Tùy nguyên nhân
500/502/503 Lỗi phía máy chủ Thượng nguồn bất thường, cổng chập chờn, tạm thời không khả dụng Có, lùi rồi thử lại
Quá thời gian Quá thời gian kết nối hoặc đọc Mạng, xếp hàng, đầu vào quá dài, đầu ra quá dài Thử lại có giới hạn

Tên trường căn cứ theo phản hồi thực tế: có trường nằm trong error.code, có trường ở tầng trên; mã không nên giả định chỉ có một cấu trúc.

2. 401: bốn nguyên nhân xác thực thất bại

401 không liên quan đến năng lực mô hình hay số dư; kiểm tra chuỗi thông tin xác thực trước:

  • Header có phải Authorization: Bearer <key>, có một dấu cách sau dấu hai chấm.
  • Key có được nạp đúng từ biến môi trường, có dấu ngoặc, khoảng trắng hoặc xuống dòng thừa không.
  • Key đã bị xóa, luân chuyển hoặc quá thời hạn chưa.
  • Dự án, khu vực của Key và Base URL có khớp không.

Key sao chép từ cửa sổ chat dễ mang ký tự vô hình. Hãy gửi một yêu cầu tối thiểu chỉ trả về một từ để loại trừ phần lớn lỗi sơ đẳng. Khi cùng một Key dùng được trên bảng điều khiển nhưng mã báo 401, kiểm tra biến môi trường và reverse proxy có làm mất header xác thực không.

3. 404: ID điểm vào và tên mô hình dễ bị nhầm nhất

Volcano Ark có hai cách chỉ định mô hình phổ biến: điểm vào suy luận tạo trên bảng điều khiển, thường bắt đầu bằng ep-; và gọi trực tiếp ID mô hình mà một số mô hình hỗ trợ. Cả hai đều điền vào trường model, nhưng quyền, giới hạn tốc độ và phạm vi áp dụng có thể khác nhau. Trộn ID điểm vào với tên mô hình, hoặc sao chép điểm vào của dự án khác, đều nhận 404 hoặc lỗi "tài nguyên không tồn tại" tương tự.

Thứ tự điều tra:

  1. Xác nhận Base URL là địa chỉ khu vực như https://ark.cn-beijing.volces.com/api/v3, không thừa hoặc thiếu /api/v3.
  2. Trên bảng điều khiển, đối chiếu điểm vào có tồn tại, thuộc dự án hiện tại, đã bị ngừng chưa.
  3. Xác nhận cách gọi hiện tại yêu cầu ID điểm vào hay ID mô hình, đừng điền lẫn theo trí nhớ.
  4. Dùng curl gửi yêu cầu tối thiểu, loại trừ ảnh hưởng của SDK tự ghép đường dẫn và proxy viết lại.
  5. Xem kiểu nội dung phản hồi: nếu trả trang lỗi HTML, yêu cầu có thể chưa tới Ark mà bị cổng hoặc reverse proxy chặn.

404 kèm HTML thường là vấn đề đường dẫn hoặc proxy; kèm phần thân lỗi JSON mới giống vấn đề mô hình hoặc điểm vào.

4. 400: ngữ cảnh quá dài và lỗi tham số

400 có phạm vi rất rộng, phổ biến nhất là ngữ cảnh quá dài. Cửa sổ ngữ cảnh thường tính bằng token đầu vào cộng token đầu ra; max_tokens quá lớn sẽ khiến yêu cầu lẽ ra chạy được vượt giới hạn. Ảnh, định nghĩa công cụ và tin nhắn lịch sử cũng chiếm token.

Cách xử lý không phải tăng giới hạn mà là để dư cho đầu vào:

  • Nén hoặc chia đoạn system prompt, xóa quy tắc lặp.
  • Tóm tắt lịch sử hội thoại, chỉ giữ vài lượt gần nhất và sự kiện then chốt.
  • Tài liệu dài nên truy xuất trước rồi ghép, đừng nhét cả bài.
  • Nén ảnh trước, xác nhận định dạng và kích thước trong phạm vi hỗ trợ.
  • Kiểm tra temperature, top_p có vượt khoảng không, vai trò tin nhắn có hợp lệ không.

Đếm token là giá trị ước lượng; khi gần giới hạn, để dư 10% đến 20% sẽ ổn định hơn.

5. 429: giới hạn tốc độ, đồng thời và hạn mức phải xử lý riêng

429 có bốn nhóm nguyên nhân:

  • Giới hạn tốc độ: số yêu cầu hoặc token mỗi phút vượt trần gói, lùi rồi thường hồi phục.
  • Giới hạn đồng thời: quá nhiều yêu cầu đang bay, cần giảm đồng thời hoặc xếp hàng; chỉ thử lại sẽ làm nghẽn nặng hơn.
  • Hết hạn mức hoặc gói tài nguyên: hạn mức dùng hết, thử lại vô nghĩa, cần nạp tiền hoặc điều chỉnh gói.
  • Trạng thái tài khoản bất thường: nợ phí, chưa xác thực danh tính hoặc thay đổi quyền, xử lý theo hướng dẫn bảng điều khiển.

Khi phản hồi có Retry-After thì chờ theo giá trị đó; nếu không có thì lùi cấp số nhân kèm nhiễu ngẫu nhiên. 429 do hạn mức và nợ phí không nên thử lại, chỉ kéo dài thời gian sự cố.

429 truyền phát có thể xảy ra lúc thiết lập kết nối, cũng có thể xuất hiện dưới dạng sự kiện lỗi trong luồng. Máy khách phải xử lý đồng thời mã trạng thái và lỗi trong luồng, không chỉ nhìn đoạn dữ liệu đầu tiên.

6. Quá thời gian và ngắt luồng: định vị theo ba đoạn

Quá thời gian chia thành ba đoạn:

  • Quá thời gian kết nối: DNS, TLS, proxy đường ra hoặc mạng không tới được, thường thất bại trong vài giây.
  • Quá thời gian token đầu: yêu cầu đã tới thượng nguồn nhưng đang xếp hàng hoặc xử lý đầu vào dài, biểu hiện là lâu không có đoạn đầu tiên.
  • Quá thời gian đọc: khoảng cách giữa hai đoạn quá lâu, có thể do đầu ra quá dài, suy luận lâu hoặc kết nối bị thiết bị trung gian cắt.

Ba đoạn cần cấu hình quá thời gian khác nhau. Tổng thời gian quá lớn khiến yêu cầu lỗi chiếm dụng nhóm kết nối lâu; quá nhỏ lại giết nhầm đầu ra dài bình thường. Nên đặt kết nối khoảng 5 giây, thời gian đọc theo P95 nghiệp vụ, tầng ứng dụng đặt thêm ngân sách tổng.

Tình huống truyền phát còn phải kiểm tra bộ đệm reverse proxy. Bộ đệm làm đoạn dữ liệu xuống chậm, trông như "treo". Sau khi đứt luồng, đừng đưa nửa nội dung vào cơ sở dữ liệu như kết quả hoàn chỉnh.

7. Request ID và nhật ký: bằng chứng điều tra

Phản hồi của Volcano Ark thường mang định danh yêu cầu, trường phổ biến gồm X-Request-Id; một số giao diện còn có thể trả ID nhật ký như X-Tt-Logid. Tên trường căn cứ theo phản hồi thực tế; nên giữ nguyên toàn bộ header thay vì chỉ chọn một trường.

Máy khách cũng nên tạo trace_id riêng, giữ nguyên qua mọi lần thử lại của cùng một yêu cầu nghiệp vụ. Nhật ký tối thiểu ghi thời gian, trace_id, Base URL, mô hình hoặc điểm vào, mã trạng thái, code và message lỗi, thời gian xử lý, số lần thử lại, có truyền phát không và mức dùng token.

Key chỉ ghi vài ký tự đầu hoặc giá trị băm; nội dung gốc người dùng và phản hồi đầy đủ không nên ghi cả đoạn xuống đĩa. Phần thân phản hồi lỗi chỉ cần giữ 500 ký tự đầu.

8. Thử lại và lùi: một đoạn mã dùng được

Đoạn mã dưới đây tắt tự động thử lại của SDK, đánh giá theo mã trạng thái và nội dung lỗi, tôn trọng Retry-After và tạo trace_id cho mỗi yêu cầu logic:

import os
import random
import time
import uuid

import httpx
from openai import OpenAI, APIConnectionError, APIStatusError, APITimeoutError

client = OpenAI(
    api_key=os.environ["ARK_API_KEY"],
    base_url=os.environ.get(
        "ARK_BASE_URL", "https://ark.cn-beijing.volces.com/api/v3"
    ),
    timeout=httpx.Timeout(connect=5.0, read=180.0, write=30.0, pool=10.0),
    max_retries=0,  # Tắt tự động thử lại của SDK, giao cho logic bên dưới
)

def parse_error(exc: APIStatusError) -> tuple[str, str]:
    try:
        body = exc.response.json()
    except Exception:
        return "", exc.response.text[:200]
    err = body.get("error", body)
    return str(err.get("code") or err.get("type") or ""), str(err.get("message") or "")

def is_retryable(exc: Exception) -> bool:
    if isinstance(exc, (APITimeoutError, APIConnectionError)):
        return True
    if not isinstance(exc, APIStatusError):
        return False
    if exc.status_code >= 500:
        return True
    if exc.status_code != 429:
        return False
    code, message = parse_error(exc)
    text = f"{code} {message}".lower()
    # 429 do hạn mức, nợ phí, quyền không có ý nghĩa thử lại; bổ sung từ khóa theo văn bản thực tế
    return not any(k in text for k in ("quota", "arrears", "balance", "permission"))

def ask(prompt: str, max_attempts: int = 4) -> str:
    trace_id = uuid.uuid4().hex[:12]
    for attempt in range(1, max_attempts + 1):
        try:
            resp = client.chat.completions.create(
                model=os.environ["ARK_MODEL"],  # ID điểm vào hoặc ID mô hình
                messages=[{"role": "user", "content": prompt}],
                max_tokens=1024,
            )
            return resp.choices[0].message.content
        except Exception as exc:
            status = getattr(exc, "status_code", "")
            code, message = parse_error(exc) if isinstance(exc, APIStatusError) else ("", "")
            print(
                f"trace={trace_id} attempt={attempt} status={status} "
                f"code={code} message={message[:200]}"
            )
            if attempt == max_attempts or not is_retryable(exc):
                raise
            retry_after = getattr(
                getattr(exc, "response", None), "headers", {}
            ).get("retry-after")
            try:
                wait = float(retry_after) if retry_after else min(2 ** (attempt - 1), 20)
            except ValueError:
                wait = min(2 ** (attempt - 1), 20)
            time.sleep(wait + random.uniform(0, 1))
    raise RuntimeError("Đã dùng hết số lần thử lại")

Bổ sung ba quy tắc: yêu cầu có tác dụng phụ phải dùng khóa idempotent xác nhận trạng thái trước; ngân sách thử lại kiểm soát toàn cục; giám sát tỷ lệ 429 và độ trễ P95, khi tăng đột biến thì giảm đồng thời trước.

9. Danh sách trước khi liên hệ hỗ trợ

  1. Thời điểm sự cố và múi giờ, là liên tục hay chập chờn.
  2. Base URL, đường dẫn đầy đủ, tên mô hình hoặc ID điểm vào.
  3. Mã trạng thái HTTP, code lỗi, message và request ID.
  4. Một yêu cầu curl tối thiểu có thể tái hiện, Key đã khử nhận dạng.
  5. Có truyền phát, ngữ cảnh dài, ảnh hay gọi công cụ không.
  6. Gần đây có đổi Key, điểm vào, hạn mức hoặc proxy không.
  7. Phạm vi ảnh hưởng: một Key, một dự án, một khu vực hay toàn bộ dịch vụ.

Chuẩn bị đủ những thông tin này, đội hỗ trợ mới đối chiếu trực tiếp được với nhật ký thượng nguồn. Sau mỗi sự cố, bổ sung một mục giám sát hoặc cảnh báo.

10. Câu hỏi thường gặp (FAQ)

1. 404 có chắc chắn là mô hình đã ngừng cung cấp không?

Không nhất thiết. Phổ biến hơn là sai ID điểm vào hoặc tên mô hình, điểm vào đã bị xóa, không khớp khu vực, hoặc đường dẫn thiếu /api/v3. Hãy xem phản hồi là JSON hay trang lỗi HTML rồi đối chiếu từng mục.

2. 429 nên thử lại mấy lần?

Với giới hạn tốc độ và nghẽn tạm thời, thử lại 2 đến 3 lần kèm lùi cấp số nhân. 429 do hết hạn mức, nợ phí hoặc thiếu quyền không nên thử lại; xử lý tài khoản hoặc gói trước. Tôn trọng Retry-After.

3. Độ dài ngữ cảnh rốt cuộc tính thế nào?

Thường tính bằng token đầu vào cộng token đầu ra; max_tokens cũng chiếm tổng hạn mức. Ảnh, định nghĩa công cụ và tin nhắn lịch sử đều tính vào đầu vào; khi gần giới hạn phải để dư.

4. Quá thời gian cho yêu cầu truyền phát nên đặt thế nào?

Thời gian đọc thường giới hạn khoảng cách giữa hai đoạn, không phải tổng thời lượng. Thời gian kết nối đặt riêng, tầng ứng dụng đặt thêm ngân sách tổng và thời gian nhàn rỗi. Bộ đệm proxy làm đoạn dữ liệu xuống chậm.

5. Sau khi qua cổng, lỗi nhiều hơn thì làm sao?

Trước hết xác nhận lỗi do cổng hay thượng nguồn trả về: xem định dạng phần thân, mã trạng thái và request ID. Giữ trace ID, lần lượt dùng kết nối trực tiếp và cổng gửi yêu cầu tối thiểu để so sánh. Phần lớn vấn đề nằm ở ghép đường dẫn, chuyển tiếp header xác thực hoặc quá thời gian.

Bước tiếp theo

Trước hết tạo Key kiểm thử tại ZSQH AI Gateway, diễn tập lần lượt 401, 404, 429 và quá thời gian, rồi kết nối giám sát sản xuất. Mô hình khả dụng và cách tính phí xem tại giá mô hình.

Bài viết liên quan