ModelRelay là cổng API cho sinh văn bản và sinh ảnh, tương thích OpenAI. Bạn gọi theo nhóm năng lực — “nhanh”, “chất lượng”, “ảnh” — còn việc chọn mô hình, xoay vòng hạn mức và chuyển hướng khi một nơi quá tải là việc của gateway.
base_url là chạy với SDK OpenAIGọi AI trực tiếp thì mọi sự cố của nhà cung cấp là sự cố của bạn. Gateway đứng giữa và xử lý những việc lặp đi lặp lại đó.
Một mô hình quá tải hay hết hạn mức, request được thử tiếp ở mô hình khác cùng nhóm — trong giới hạn thời gian bạn đặt.
Chọn text-fast,
text-quality hay nhóm ảnh. Danh sách mô hình phía sau được cập nhật liên tục, code của bạn
không cần đổi.
API key, mật khẩu, khoá riêng lẫn trong prompt bị phát hiện và chặn trước khi gửi đi — không phải sau khi đã lộ.
Mỗi phản hồi cho biết mô hình nào trả lời, đã thử mấy lần và vì sao — lỗi trả về có lý do cho từng lần thử.
Dùng lại SDK và code sẵn có:
/v1/chat/completions, /v1/images/generations.
Mỗi key có trần request/phút, request đồng thời và token/ngày — vượt thì nhận 429 kèm thời điểm gọi lại, không bị treo.
Giai đoạn này ModelRelay mở cho dùng thử để giới thiệu và trao đổi kinh nghiệm — chưa bán gói trả phí.
Nhận key dùng thử, đổi base_url, giữ nguyên phần còn lại.
# Python — SDK OpenAI
from openai import OpenAI
client = OpenAI(base_url="https://llm.allin1site.com/v1", api_key="fla_prod_...")
r = client.chat.completions.create(
model="text-quality", # nhóm năng lực, không phải tên mô hình
messages=[{"role": "user", "content": "Viết hai câu thơ lục bát về mùa thu"}],
)
print(r.choices[0].message.content)
# curl
curl https://llm.allin1site.com/v1/chat/completions \
-H "Authorization: Bearer fla_prod_..." -H "Content-Type: application/json" \
-d '{"model":"text-fast","messages":[{"role":"user","content":"Xin chào"}]}'
Toàn bộ endpoint đang mở, cách gọi, tham số, dạng phản hồi và mã lỗi.
POST /v1/chat/completionsPOST /v1/generate/textPOST /v1/generate/imagePOST /v1/images/generationsPOST /v1/generate/codeGET /v1/models, GET /v1/models/{id}GET /v1/meGET /healthz, GET /version| Mục | Giá trị |
|---|---|
| Base URL | https://llm.allin1site.com (SDK OpenAI: base_url="https://llm.allin1site.com/v1") |
| Xác thực | Header Authorization: Bearer fla_prod_… — key nhận khi đăng ký dùng thử. Thiếu / sai / đã thu hồi ⇒ 401 unauthenticated |
| Định dạng | JSON, UTF-8. Gửi Content-Type: application/json |
| Streaming | Có ở POST /v1/chat/completions (stream: true, SSE chuẩn OpenAI). Các endpoint khác trả một lần, trọn vẹn |
| Mã truy vết | Mọi phản hồi có header X-FLA-Trace-Id — gửi kèm khi cần hỗ trợ |
| Thời gian chờ | Mặc định 30 giây (stream 90 giây, sinh code 60 giây); đặt dài hơn bằng X-FLA-Deadline-Ms, tối đa 90 000. Đặt timeout phía client ≥ deadline + 5 giây |
| Phương thức | Đường dẫn | Việc | Quyền key |
|---|---|---|---|
| POST | /v1/chat/completions | Chat — tương thích OpenAI | text:generate |
| POST | /v1/generate/text | Sinh văn bản, dạng gọn (prompt hoặc messages) | text:generate |
| POST | /v1/generate/image | Sinh ảnh, dạng gọn | image:generate |
| POST | /v1/images/generations | Sinh ảnh — tương thích OpenAI (b64_json) | image:generate |
| POST | /v1/generate/code | Sinh code dạng patch (unified diff) | code:generate — cấp riêng theo yêu cầu |
| GET | /v1/models | Nhóm + mô hình key của bạn được dùng | key bất kỳ |
| GET | /v1/models/{id} | Một nhóm / mô hình (khuôn OpenAI); không có ⇒ 404 model_not_found | key bất kỳ |
| GET | /v1/me | Key của bạn: nhóm, quyền, hạn mức đang áp, đã dùng hôm nay | key bất kỳ |
| GET | /healthz | Dịch vụ còn sống không | không cần key |
| GET | /version | Phiên bản đang chạy | không cần key |
Đường dẫn /v1/… khác (ví dụ /v1/tasks, /v1/workspaces) đang trong kế hoạch và trả
501 not_implemented — nghĩa là “chưa mở”, không phải “sai URL”.
Bạn gọi theo tên nhóm, không theo tên mô hình. Gateway chọn mô hình trong nhóm, tự chuyển sang mô hình
kế tiếp khi một mô hình lỗi hoặc hết hạn mức. Danh sách mô hình phía sau thay đổi theo thời gian — code của bạn
không cần đổi. Key dùng thử được cấp một số nhóm; GET /v1/models cho biết chính xác nhóm nào bạn dùng được.
| Nhóm | Dùng cho | Endpoint |
|---|---|---|
text-fast (mặc định) | Trả lời nhanh, việc thường ngày | chat, text |
text-quality | Văn bản dài, cần chất lượng (viết bài, thơ, tóm tắt kỹ). Chậm hơn — nên đặt X-FLA-Deadline-Ms: 90000 | chat, text |
review-fast | Phân loại / rà soát ngắn, trả JSON ngắn; mô hình không “suy nghĩ” dài | chat, text |
code-quality | Sinh code — chỉ gọi qua /v1/generate/code | code |
image-free (mặc định ảnh) | Sinh ảnh từ mô tả | image, images/generations |
Ghim một mô hình (không khuyến khích): gửi id mô hình lấy từ GET /v1/models (dạng có dấu /) vào
model (chat) hoặc pin_model (text, ảnh). Khi ghim, gateway không chuyển sang mô hình khác nếu mô hình đó lỗi
(header X-FLA-Warning: pinned_model_no_t1_failover).
/v1/chat/completionsTương thích OpenAI Chat Completions: dùng nguyên SDK OpenAI, chỉ đổi base_url và api_key.
| Trường | Kiểu | Ghi chú |
|---|---|---|
messages | mảng, bắt buộc | {"role": "system"|"developer"|"user"|"assistant"|"tool", "content": "…"} — developer được coi như system; content là chuỗi, hoặc mảng các phần {"type": "text", "text": "…"} (ghép lại bằng xuống dòng; phần ảnh / âm thanh / file bị từ chối 422) (tin assistant có tool_calls được để null; tin tool phải có tool_call_id). Tối đa 100 tin, tổng 100 000 ký tự — tính cả đối số và kết quả tool |
model | chuỗi | Tên nhóm (text-quality…). Bỏ trống ⇒ text-fast. Có dấu / ⇒ ghim mô hình |
max_tokens / max_completion_tokens | số ≥ 1 | Bị kẹp về tối đa 8192 (header X-FLA-Max-Tokens-Applied cho biết số thật dùng) |
temperature | 0 – 2 | |
top_p, stop (chuỗi hoặc mảng ≤ 4 phần tử), presence_penalty, frequency_penalty, seed, response_format | Chuyển tiếp nguyên văn như OpenAI | |
reasoning_effort | none | minimal | low | medium | high | Giảm phần “suy nghĩ” của mô hình ⇒ trả lời nhanh hơn. Mô hình không hỗ trợ thì bỏ qua (header X-FLA-Params-Dropped) |
n | chỉ 1 | n > 1 ⇒ 422 |
stream | true | false | true ⇒ trả SSE từng phần (xem ví dụ dưới) |
stream_options | {"include_usage": true} | Chunk cuối (trước [DONE]) có usage. usage.x_fla_estimated: true = mô hình không báo, hệ ước tính |
tools, tool_choice, parallel_tool_calls | khuôn OpenAI | Gọi hàm (function calling). Request có tools hoặc lịch sử tool chỉ đi tới mô hình đã kiểm chứng gọi được tool (hiện có ở cả text-fast, text-quality, review-fast, nhưng ít mô hình hơn request thường). Nhóm không có mô hình nào như vậy ⇒ 400 tools_not_supported. Trả message.tool_calls + finish_reason: "tool_calls" (stream: delta.tool_calls). Đối số và kết quả tool cũng qua bộ lọc bí mật |
Trường lạ bị bỏ qua (không lỗi).
curl https://llm.allin1site.com/v1/chat/completions \
-H "Authorization: Bearer fla_prod_..." \
-H "Content-Type: application/json" \
-H "X-FLA-Deadline-Ms: 90000" \
-d '{
"model": "text-quality",
"messages": [
{"role": "system", "content": "Bạn là nhà thơ."},
{"role": "user", "content": "Viết bốn câu lục bát về Hà Nội"}
],
"max_tokens": 1024,
"reasoning_effort": "low"
}'
# Phản hồi 200
{
"id": "chatcmpl-trc_9f2c…",
"object": "chat.completion",
"created": 1790000000,
"model": "<model-id>",
"choices": [
{"index": 0,
"message": {"role": "assistant", "content": "…"},
"finish_reason": "stop"}
],
"usage": {"prompt_tokens": 31, "completion_tokens": 120, "total_tokens": 151},
"x_fla": {"trace_id": "trc_9f2c…", "attempts": 1, "failover_depth": 0,
"provider": "<provider>", "model_group": "text-quality"}
}
# Python — SDK OpenAI (pip install openai)
from openai import OpenAI
client = OpenAI(base_url="https://llm.allin1site.com/v1", api_key="fla_prod_...",
timeout=95) # >= deadline + 5 s
r = client.chat.completions.create(
model="text-quality",
messages=[{"role": "user", "content": "Tóm tắt bài sau trong 3 ý: ..."}],
max_tokens=800,
extra_headers={"X-FLA-Deadline-Ms": "90000"},
)
print(r.choices[0].message.content)
# Stream — chữ hiện dần, chữ đầu thường sau 1–3 giây
for chunk in client.chat.completions.create(
model="text-quality", stream=True,
messages=[{"role": "user", "content": "Đếm từ 1 đến 5"}],
extra_headers={"X-FLA-Deadline-Ms": "90000"}):
if chunk.choices and chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="", flush=True)
Stream và chuyển mô hình: hệ vẫn tự thử mô hình / key khác cho tới khi có chữ đầu tiên; lỗi trước mốc đó trả mã HTTP như thường (503, 429…).
Sau chữ đầu tiên thì không đổi mô hình được nữa — nếu bên sinh ngắt giữa chừng, luồng kết thúc bằng
data: {"error": {"code": "upstream_failed_midstream", "tokens_emitted": …}} rồi data: [DONE] (SDK OpenAI báo lỗi APIError): câu trả lời chưa đủ, gửi lại request.
// Node.js — SDK OpenAI (npm i openai)
import OpenAI from "openai";
const client = new OpenAI({ baseURL: "https://llm.allin1site.com/v1",
apiKey: "fla_prod_...", timeout: 95_000 });
const r = await client.chat.completions.create(
{ model: "text-fast", messages: [{ role: "user", content: "Xin chào" }] },
{ headers: { "X-FLA-Deadline-Ms": "60000" } },
);
console.log(r.choices[0].message.content);
/v1/generate/textDạng gọn của ModelRelay: gửi một prompt hoặc một mảng messages (đúng một trong hai), nhận về text.
| Trường | Kiểu | Ghi chú |
|---|---|---|
prompt | chuỗi | Tương đương một tin user |
messages | mảng | Như chat. Gửi cả hai hoặc không gửi gì ⇒ 422 |
model_group | chuỗi | Bỏ trống ⇒ text-fast |
pin_model | chuỗi | Ghim mô hình (xem phần nhóm) |
max_tokens, temperature, top_p, stop, seed, response_format, reasoning_effort… | Như chat |
curl https://llm.allin1site.com/v1/generate/text \
-H "Authorization: Bearer fla_prod_..." -H "Content-Type: application/json" \
-d '{"model_group": "review-fast", "temperature": 0,
"prompt": "Phân loại tiêu đề sau vào một trong: the-thao, kinh-te, giai-tri. Chỉ trả JSON {\"loai\": ...}. Tiêu đề: ..."}'
# Phản hồi 200
{
"text": "{\"loai\": \"the-thao\"}",
"model": "<model-id>",
"provider": "<provider>",
"usage": {"prompt_tokens": 52, "completion_tokens": 9, "total_tokens": 61},
"trace_id": "trc_1a7b…",
"attempts": 1,
"finish_reason": "stop"
}
finish_reason: "length" nghĩa là câu trả lời bị cắt vì chạm max_tokens — tăng max_tokens hoặc chia nhỏ yêu cầu.
/v1/generate/imageSinh ảnh từ mô tả. Mặc định 1 ảnh; ảnh trả về dạng base64 (máy chủ không lưu ảnh, nên không có URL).
| Trường | Kiểu | Ghi chú |
|---|---|---|
prompt | chuỗi, bắt buộc | Tối đa 2000 ký tự. Mô tả bằng tiếng Anh thường cho kết quả tốt hơn |
n | 1 – 4 | Mặc định 1 |
model_group | chuỗi | Bỏ trống ⇒ image-free |
pin_model | chuỗi | Ghim mô hình ảnh (id từ GET /v1/models → image_groups) |
seed | 0 – 2147483647 | Cùng seed + cùng prompt ⇒ ảnh gần giống nhau |
curl https://llm.allin1site.com/v1/generate/image \
-H "Authorization: Bearer fla_prod_..." -H "Content-Type: application/json" \
-H "X-FLA-Deadline-Ms: 90000" \
-d '{"prompt": "a cozy coffee shop in Hanoi old quarter, rainy evening, watercolor", "n": 1}'
# Phản hồi 200
{
"images": [{"b64": "iVBORw0KGgo…", "mime": "image/png", "model": "<model-id>"}],
"trace_id": "trc_77d0…",
"attempts": 1,
"model_group": "image-free",
"requested": 1,
"returned": 1,
"missing": 0,
"cost_usd": "0.000000"
}
Xin nhiều ảnh mà chỉ sinh được một phần ⇒ vẫn 200, returned < requested và header X-FLA-Partial: 1/3.
Mô tả bị bên sinh ảnh chặn vì nội dung ⇒ 451 content_filtered — sửa mô tả, đừng gửi lại y nguyên.
# Python — lưu ảnh ra file
import base64, requests
r = requests.post("https://llm.allin1site.com/v1/generate/image",
headers={"Authorization": "Bearer fla_prod_...", "X-FLA-Deadline-Ms": "90000"},
json={"prompt": "a red lotus on a calm pond, morning light"}, timeout=95)
r.raise_for_status()
for i, img in enumerate(r.json()["images"]):
open(f"anh_{i}.png", "wb").write(base64.b64decode(img["b64"]))
/v1/images/generationsCùng chức năng với /v1/generate/image, theo dạng OpenAI Images API. Nhận prompt, n, model
(tên nhóm, hoặc id có / để ghim), seed, response_format (chỉ b64_json; url ⇒ 422).
Trường khác của OpenAI (size, quality…) bị bỏ qua.
# Python — SDK OpenAI
import base64
from openai import OpenAI
client = OpenAI(base_url="https://llm.allin1site.com/v1", api_key="fla_prod_...", timeout=95)
r = client.images.generate(model="image-free", prompt="isometric tiny house, pastel colors",
response_format="b64_json")
open("anh.png", "wb").write(base64.b64decode(r.data[0].b64_json))
# Phản hồi 200
{
"created": 1790000000,
"data": [{"b64_json": "iVBORw0KGgo…"}],
"x_fla": {"trace_id": "trc_…", "attempts": 1, "model_group": "image-free",
"requested": 1, "returned": 1, "missing": 0, "cost_usd": "0.000000"}
}
/v1/generate/codeGửi mục tiêu + các file liên quan, nhận về patch (unified diff) kèm kết quả kiểm tra tự động. Cần quyền
code:generate — không có sẵn trong key dùng thử, liên hệ để được cấp.
| Trường | Kiểu | Ghi chú |
|---|---|---|
goal | chuỗi, bắt buộc | Việc cần làm, 1 – 4000 ký tự |
files | mảng, bắt buộc | [{"path": "src/a.py", "content": "…"}] — tối đa 5 file, đường dẫn tương đối |
keywords | mảng chuỗi | Tối đa 20 từ khoá gợi ý |
language | chuỗi | Ví dụ python |
constraints | object | max_files_changed (≤ 5), style_guide (≤ 64 ký tự) |
mode | "patch" | Giá trị duy nhất |
model_group | chuỗi | Bỏ trống ⇒ code-quality |
max_tokens, temperature, reasoning_effort | Mặc định max_tokens 8192 | |
workspace_id | null | Chưa hỗ trợ — luôn gửi files |
curl https://llm.allin1site.com/v1/generate/code \
-H "Authorization: Bearer fla_prod_..." -H "Content-Type: application/json" \
-d '{
"goal": "Hàm divide phải báo lỗi rõ ràng khi chia cho 0",
"language": "python",
"files": [{"path": "calc.py", "content": "def divide(a, b):\n return a / b\n"}]
}'
# Phản hồi 200
{
"status": "succeeded",
"mode": "patch",
"patch": "--- a/calc.py\n+++ b/calc.py\n@@ -1,2 +1,4 @@\n def divide(a, b):\n+ if b == 0:\n+ raise ValueError(\"b must not be 0\")\n return a / b\n",
"files_changed": ["calc.py"],
"explanation": "…",
"gates": {"patch_applies": true, "syntax_ok": true, "lint_ok": true, "tests": "not_run"},
"gate_details": {…},
"assumptions": [],
"flags": [],
"model": "<model-id>", "provider": "<provider>",
"usage": {…}, "attempts": 1, "trace_id": "trc_…"
}
status | Nghĩa |
|---|---|
succeeded | Patch áp được, cú pháp đúng, không thêm lỗi lint mới. tests: "not_run" — gateway không chạy test của bạn; hãy chạy trước khi dùng |
built_flagged | Có patch nhưng ít nhất một bước kiểm tra không đạt — xem gates, gate_details, flags |
needs_clarification | Mô hình cần thêm thông tin: đọc questions, bổ sung vào goal rồi gửi lại. Không có patch |
File chứa chuỗi giống bí mật (API key, mật khẩu, khoá riêng…) hoặc file nhạy cảm (.env, *.pem…) ⇒
422 redaction_blocked, không gửi đi đâu cả — gỡ bí mật rồi gửi lại.
/v1/modelsNhóm và mô hình mà key của bạn được dùng, ngay lúc này. Mô hình đang bị loại tạm thời nằm trong excluded kèm lý do.
curl https://llm.allin1site.com/v1/models -H "Authorization: Bearer fla_prod_..."
# Phản hồi 200 (rút gọn)
{
"object": "list",
"data": [
{"id": "text-fast", "object": "model", "created": 0, "owned_by": "fla", "x_fla_kind": "group",
"context_window": 131072, "capabilities": {"tools": true, "stream": true}},
{"id": "<model-id>", "object": "model", "created": 0, "owned_by": "<provider>",
"x_fla_kind": "model", "context_window": 1048576, "capabilities": {"tools": false, "stream": true}}
],
"groups": [
{"name": "text-fast", "default": true, "candidates": 6, "min_context": null,
"endpoints": ["/v1/chat/completions", "/v1/generate/text"], "max_input_chars": 100000,
"members": ["<model-id>", "…"],
"excluded": [{"model": "<model-id>", "reason": "…"}]}
],
"models": [
{"id": "<model-id>", "provider": "<provider>", "context_window": 1048576, "free_status": "verified_free"}
],
"image_groups": [
{"name": "image-free", "default": true, "paid": false, "candidates": 3,
"members": ["…"], "excluded": [], "max_n": 4}
]
}
candidates: 0 ⇒ nhóm đó hiện không có mô hình nào dùng được; gọi vào sẽ nhận 503.
data theo khuôn OpenAI (cho nút “Test kết nối” / danh sách model của client chuẩn): tên nhóm trước (nên dùng — có tự chuyển mô hình), rồi id mô hình lẻ (ghim).
Chỉ gồm thứ gọi được qua /v1/chat/completions — nhóm sinh code không có ở đây, xem groups[].endpoints.
max_input_chars: trần tổng ký tự nội dung — rút gọn trước khi gửi thay vì nhận 413.
capabilities chỉ khai điều đã đo: tools = mô hình gọi được tools (nhóm: có ít nhất một mô hình như vậy),
stream = stream=true ở /v1/chat/completions. Chưa đo thì không có trường (ví dụ chế độ JSON) — đừng coi vắng mặt là “không hỗ trợ”, chỉ là “chưa biết”.
context_window chỉ có khi danh mục biết; với nhóm là mức thấp nhất trong các mô hình của nhóm. created luôn 0 (không có nguồn).
GET /v1/models/{id}id là tên nhóm hoặc id mô hình (dạng có dấu /) lấy từ data[] ở trên. Trả một phần tử data[] (khuôn OpenAI).
Không có hoặc key không được dùng ⇒ 404 model_not_found.
/v1/meKey của bạn tự xem mình đang được dùng gì và còn bao nhiêu hạn mức — để client tự điều tiết thay vì đợi 429. Gọi /v1/me không tốn hạn mức.
curl https://llm.allin1site.com/v1/me -H "Authorization: Bearer fla_prod_..."
# Phản hồi 200 (rút gọn)
{
"object": "fla.tenant", "tenant": "ten-doi-tac", "scopes": ["text:generate"],
"model_groups": ["text-fast", "text-quality"], "image_groups": [],
"limits": {"rpm": 60, "dong_thoi": 5, "token_ngay": 2000000},
"usage": {"rpm": 3, "dong_thoi": 0, "token_ngay": 18250},
"reset": {"token_ngay_at": "2026-10-11T00:00:00Z", "token_ngay_in_seconds": 41120, "rpm_in_seconds": 27}
}
limits là hạn mức đang áp cho key này (mặc định hoặc mức riêng đã cấp). usage: request phút này / đang chạy cùng lúc / token hôm nay.
Không đọc được bộ đếm ⇒ vẫn 200, usage là null kèm usage_unavailable (lý do) — không phải lỗi của bạn.
Hạn mức token reset lúc 0 giờ UTC.
/healthz GET/versionKhông cần key. /healthz ⇒ {"status": "ok", "uptime_s": …} khi dịch vụ còn sống; /version ⇒ phiên bản đang chạy.
Dùng cho giám sát, không tính vào hạn mức key.
curl https://llm.allin1site.com/healthz
| Header | Ghi chú |
|---|---|
Authorization | Bearer fla_prod_… — bắt buộc với mọi /v1/… |
X-FLA-Deadline-Ms | Tổng thời gian gateway được phép dùng cho request (gồm cả các lần chuyển mô hình). 1 000 – 90 000 (sinh code: tối đa 60 000). Mặc định 30 000; sinh code 60 000; ảnh 90 000 |
X-FLA-Priority | interactive (mặc định) hoặc batch. Khi hệ thống quá tải nặng, request batch bị từ chối (503 shed) trước; interactive giữ nguyên. Việc chạy nền, hàng loạt nên gửi batch. Giá trị khác ⇒ 422. Không có hàng đợi |
X-FLA-Cache | Chat và text, không stream, không tools: câu trả lời giống hệt được dùng lại trong 1 giờ khi temperature = 0 — hoặc khi bạn gửi use (ép dùng cache với mọi temperature). bypass = không đọc, không ghi cache. Không bao giờ dùng chung giữa các tenant. Giá trị khác ⇒ 422 |
| Header | Ghi chú |
|---|---|
X-FLA-Trace-Id | Mã truy vết — luôn có, kể cả khi lỗi |
X-FLA-Model, X-FLA-Provider | Mô hình đã trả lời |
X-FLA-Attempts, X-FLA-Failover-Depth | Số lần thử; số lần đã chuyển sang mô hình / key khác |
X-FLA-Cache | hit = trả từ cache (không gọi mô hình, X-FLA-Attempts: 0, không trừ token; vẫn tính 1 request vào hạn mức phút) · miss · bypass. hit có thêm X-FLA-Cache-Age-S (tuổi của câu trả lời, giây) |
X-FLA-Priority | Mức ưu tiên đã áp (interactive | batch), kể cả khi lỗi |
X-FLA-Max-Tokens-Applied | max_tokens thực dùng (sau khi kẹp về 8192) |
X-FLA-Params-Dropped | Tham số bị bỏ: mô hình không nhận (ví dụ reasoning_effort) hoặc gateway không hỗ trợ (ví dụ logprobs, user) — liệt kê tên, tối đa 10 |
X-FLA-Params-Defaulted | Tham số gateway tự thêm cho mô hình này khi bạn không gửi |
X-FLA-Warning | pinned_model_no_t1_failover khi ghim mô hình |
X-FLA-Degraded | Hệ thống đang chạy chế độ suy giảm (tải cao) |
X-FLA-Partial, X-FLA-Cost-Usd | Ảnh: số ảnh trả được / số xin; chi phí (nhóm miễn phí luôn 0.000000) |
X-FLA-Code-Status | Sinh code: bằng trường status |
X-RateLimit-Limit-Requests, X-RateLimit-Remaining-Requests | Trần request / phút của key và số còn lại sau request này (chỉ ở phản hồi thành công — chat, text, ảnh, code) |
X-RateLimit-Limit-Tokens, X-RateLimit-Remaining-Tokens, X-RateLimit-Reset-Tokens | Trần token / ngày và số còn lại trước request này (token của request chỉ biết khi xong); thời gian tới 0 giờ UTC dạng 5h12m3s |
X-FLA-Quota | Khi 429: loại hạn mức đã chạm (phút / đồng thời / token ngày / code) |
Retry-After | Số giây nên chờ trước khi gọi lại (có khi lỗi tạm thời) |
| Giới hạn | Giá trị | Vượt thì |
|---|---|---|
| Tin nhắn mỗi request | 100 | 422 |
| Tổng nội dung mỗi request (text, chat, code) | 100 000 ký tự | 413 context_too_long_for_group |
max_tokens | kẹp về 8192 | không lỗi, xem header |
| Prompt ảnh / số ảnh | 2000 ký tự / 4 ảnh | 413 / 422 |
| File sinh code | 5 file mỗi request | 422 |
| Kích thước body | 1 MB (sinh code: 256 KB) | 413 |
| Hạn mức key mặc định | 60 request/phút · 5 request đồng thời · 2 000 000 token/ngày (UTC) | 429 tenant_rate_limited |
| Hạn mức sinh code (cộng thêm) | 10 request/phút · 2 đồng thời · 400 000 token/ngày | 429 tenant_rate_limited |
| Theo địa chỉ IP | 30 request/phút (sinh code: 6/phút), có chút dư cho đợt ngắn | 429 ip_rate_limited (JSON, có Retry-After) |
Hạn mức key dùng thử có thể khác mặc định — cấp theo nhu cầu bạn đăng ký. Token ngày tính cả vào lẫn ra, đặt lại lúc 0h UTC (7h sáng giờ Việt Nam).
Mọi lỗi có cùng dạng. Khi gateway đã thử gọi mô hình, attempts cho biết từng lần thử và vì sao chuyển tiếp.
{
"error": {
"code": "all_candidates_exhausted",
"message": "…",
"trace_id": "trc_…",
"retry_after_ms": 30000,
"attempts": [
{"n": 1, "provider": "<provider>", "model": "<model-id>", "key": "key_1a2b3c4d",
"error": "RATE_LIMITED", "http_status": 429, "latency_ms": 112, "reason": "…"},
{"n": 2, "provider": "<provider>", "model": "<model-id>", "key": null,
"error": "SKIP", "http_status": null, "latency_ms": 0, "reason": "…"}
]
}
}
| HTTP | code | Nghĩa | Nên làm |
|---|---|---|---|
| 400 | tools_not_supported | Có tools / lịch sử tool nhưng nhóm (hoặc mô hình ghim) không có mô hình gọi được tool | Đổi nhóm (xem bảng tham số chat) |
| 400 | unknown_model_group | Nhóm / mô hình không tồn tại hoặc key không được dùng | Xem GET /v1/models |
| 401 | unauthenticated | Thiếu / sai / hết hạn / đã thu hồi key, hoặc IP ngoài danh sách cho phép | Kiểm tra key; không gọi lại liên tục |
| 403 | scope_required | Key thiếu quyền cho endpoint này | Liên hệ để được cấp |
| 413 | context_too_long_for_group | Nội dung vượt giới hạn (thân lỗi có limit_chars) | Rút gọn / chia nhỏ |
| 422 | invalid_request | Sai schema, JSON hỏng, n>1, stream=true ngoài /v1/chat/completions… | Đọc message, sửa request |
| 422 | redaction_blocked | Nội dung có chuỗi giống bí mật — đã chặn, chưa gửi đi | Gỡ bí mật rồi gửi lại |
| 429 | tenant_rate_limited | Chạm hạn mức của key | Chờ retry_after_ms |
| 429 | ip_rate_limited | Quá nhiều request từ một địa chỉ IP trong thời gian ngắn | Chờ retry_after_ms (60 giây) |
| 429 | code_busy | Hệ thống đang chạy đủ số request sinh code cùng lúc | Chờ vài giây rồi thử lại |
| 451 | content_filtered | Nội dung bị bên sinh chặn | Sửa nội dung; gửi lại y nguyên vẫn bị chặn |
| 501 | not_implemented | Endpoint chưa mở | — |
| 503 | all_candidates_exhausted | Mọi mô hình trong nhóm đều lỗi / hết hạn mức | Chờ retry_after_ms rồi gọi lại một lần, hoặc đổi nhóm |
| 503 | deadline_exceeded | Hết thời gian cho phép trước khi có câu trả lời | Tăng X-FLA-Deadline-Ms, giảm max_tokens |
| 503 | shed | Hệ thống đang giảm tải | Không gọi lại ngay; chờ retry_after_ms |
| 503 | not_ready, quota_unavailable, redaction_unavailable, pool_saturated, cost_guard_tripped | Lỗi tạm thời phía gateway — được thiết kế để chặn thay vì đoán | Chờ rồi thử lại; kéo dài thì báo kèm trace_id |
Khuyến nghị gọi lại: chỉ thử lại với 429 / 503, chờ đúng retry_after_ms (hoặc header Retry-After), tối đa
1 – 2 lần. Không thử lại 400 / 401 / 403 / 413 / 422 / 451 — gửi lại y nguyên sẽ cho đúng lỗi đó.
Gateway đã tự chuyển mô hình bên trong; gọi lại dồn dập chỉ làm hạn mức cạn nhanh hơn.
SDK OpenAI: mặc định SDK tự thử lại 2 lần với 429 / 5xx — gặp 503 do quá tải, 2 lần đó chỉ nhân tải lên.
Hãy đặt max_retries từ 0 đến 1 (Python: OpenAI(max_retries=1); Node: new OpenAI({ maxRetries: 1 })).
Với các lỗi 503 shed, deadline_exceeded, all_candidates_exhausted, cost_guard_tripped
gateway gửi kèm header x-should-retry: false để SDK không tự thử lại; 429 tenant_rate_limited
và ip_rate_limited thì không, SDK chờ theo Retry-After là đúng.