Đọc · 12 phút Cập nhật 30/04/2026 Cấp độ · Trung cấp

Gọi AI từ app của bạn

ZeniRouter là engine định tuyến AI thông minh — tự động chọn model rẻ nhất phù hợp với task, cache câu hỏi lặp lại, và failover khi nhà cung cấp gặp sự cố. Tài liệu này hướng dẫn ba cách gọi từ cơ bản đến nâng cao.

Xác thực — Bearer JWT

Mọi request đến API đều cần header Authorization: Bearer zeni_pat_xxx. Tham khảo Quickstart để lấy token.

httpPOST /api/v1/router/complete?ws=my_workspace
Host: zenicloud.io
Authorization: Bearer zeni_pat_3a8f9b2c1d...
Content-Type: application/json

Tham số ws (workspace) bắt buộc — dùng để phân tách dữ liệu giữa các môi trường (dev, staging, prod) hoặc giữa các app khác nhau trong cùng tài khoản.

Cách 1 — Direct REST với cURL

Đơn giản nhất, dùng được trong shell script và CI/CD pipeline:

bashcurl -X POST "https://zenicloud.io/api/v1/router/complete?ws=prod" \
  -H "Authorization: Bearer $ZENI_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "messages": [
      {"role": "system", "content": "Bạn là trợ lý của Zeni Cloud."},
      {"role": "user", "content": "Tóm tắt 50 chữ về Sài Gòn."}
    ],
    "task_type": "qa_simple",
    "max_tokens": 200
  }'

Ví dụ Python

pythonimport os, requests

ZENI = "https://zenicloud.io/api/v1"
TOKEN = os.environ["ZENI_TOKEN"]

def ai_complete(prompt, task="qa_simple"):
    r = requests.post(
        f"{ZENI}/router/complete?ws=my_ws",
        headers={"Authorization": f"Bearer {TOKEN}"},
        json={
            "messages": [{"role": "user", "content": prompt}],
            "task_type": task,
        },
        timeout=60,
    )
    r.raise_for_status()
    return r.json()

# Use case 1 — câu hỏi đơn giản, định tuyến tới Flash
print(ai_complete("Tóm tắt 100 chữ về Hà Nội"))
# routing.primary_model = gemini-3-1-flash, cost ~ 0.0001 USD

# Use case 2 — soạn hợp đồng, định tuyến tới Opus
print(ai_complete("Soạn hợp đồng lao động Việt Nam mẫu", task="legal_contract"))
# routing.primary_model = claude-opus-4-7, cost ~ 0.025 USD

# Use case 3 — phân loại text
print(ai_complete("Phân loại email: 'Anh ơi đơn hàng đến chưa?'", task="classify"))
# routing.primary_model = gemma-4, cost ~ 0.00013 USD

Ví dụ Node.js

javascriptconst ZENI = "https://zenicloud.io/api/v1";
const TOKEN = process.env.ZENI_TOKEN;

async function aiComplete(prompt, task = "qa_simple") {
  const res = await fetch(`${ZENI}/router/complete?ws=my_ws`, {
    method: "POST",
    headers: {
      "Authorization": `Bearer ${TOKEN}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      messages: [{ role: "user", content: prompt }],
      task_type: task,
    }),
  });
  if (!res.ok) throw new Error(`Zeni ${res.status}`);
  return res.json();
}

// Sử dụng
const r = await aiComplete("Liệt kê 5 quận trung tâm Sài Gòn");
console.log(r.text);
console.log(`Model: ${r.routing.primary_model}, cost: $${r.routing.actual_cost_usd}`);

Ví dụ Go

gopackage main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "net/http"
    "os"
)

type Msg struct { Role, Content string }
type Req struct {
    Messages []Msg  `json:"messages"`
    TaskType string `json:"task_type"`
}

func aiComplete(prompt string) (string, error) {
    body, _ := json.Marshal(Req{
        Messages: []Msg{{Role: "user", Content: prompt}},
        TaskType: "qa_simple",
    })
    req, _ := http.NewRequest("POST",
        "https://zenicloud.io/api/v1/router/complete?ws=my_ws",
        bytes.NewReader(body))
    req.Header.Set("Authorization", "Bearer "+os.Getenv("ZENI_TOKEN"))
    req.Header.Set("Content-Type", "application/json")

    resp, err := http.DefaultClient.Do(req)
    if err != nil { return "", err }
    defer resp.Body.Close()

    var out map[string]interface{}
    json.NewDecoder(resp.Body).Decode(&out)
    return fmt.Sprint(out["text"]), nil
}

Cách 2 — Smart routing với task_type

Đặt task_type chính xác để ZeniRouter chọn model rẻ nhất phù hợp. Đây là cách khuyến nghị cho hầu hết ứng dụng.

task_typeModel định tuyếnChi phí ước tínhUse case
qa_simplegemini-3-1-flash$0.0001/reqHỏi đáp ngắn, FAQ, chatbot
classifygemma-4$0.00013/reqPhân loại email, tag content
summarizegemini-3-1-flash$0.0002/reqTóm tắt văn bản dưới 5K từ
code_genclaude-sonnet-4-7$0.003/reqSinh code, review PR
legal_contractclaude-opus-4-7$0.025/reqSoạn hợp đồng, phân tích pháp lý
creative_longclaude-opus-4-7$0.030/reqViết blog dài, kịch bản
visiongemini-3-1-pro$0.005/reqPhân tích ảnh, biểu đồ

Cách 3 — Explicit model selection

Khi bạn chắc chắn muốn dùng một model cụ thể (ví dụ test benchmark, hoặc có hợp đồng commit), thêm trường model:

json{
  "messages": [{"role": "user", "content": "Viết bài SEO 1500 chữ về cà phê Việt Nam"}],
  "model": "claude-opus-4-7",
  "max_tokens": 3000,
  "temperature": 0.7
}
Cảnh báo chi phí
Khi đặt model tường minh, ZeniRouter sẽ không downgrade sang model rẻ hơn dù task đơn giản. Hãy chắc chắn bạn cần đúng model đó.

Chiến lược 80/15/5 — Tối ưu chi phí

ZeniRouter hoạt động dựa trên giả định: phần lớn câu hỏi là đơn giản, chỉ một số ít cần model mạnh. Phân bổ mặc định:

80%
FAST tier · Flash
Hỏi đáp ngắn, classify, summarize. Latency 1-2s, cost ~$0.0001/req.
15%
BALANCED tier · Sonnet
Code gen, phân tích trung bình. Latency 2-5s, cost ~$0.003/req.
5%
DEEP tier · Opus
Hợp đồng, viết dài, reasoning sâu. Latency 5-15s, cost ~$0.025/req.

So với gọi trực tiếp Anthropic Opus cho mọi request, chiến lược 80/15/5 tiết kiệm khoảng 70 phần trăm chi phí mà chất lượng đầu ra không giảm rõ rệt với 95 phần trăm câu hỏi.

Cache settings

Mỗi request tự động được hash và lưu cache. Có hai loại cache:

json{
  "messages": [{"role": "user", "content": "Sài Gòn có gì hay?"}],
  "task_type": "qa_simple",
  "cache": {
    "mode": "semantic",
    "ttl_seconds": 86400,
    "similarity_threshold": 0.92
  }
}

Cache TTL mặc định 1 giờ. Khi hit, bạn nhận response gần như tức thì (dưới 100ms) với cache_hit: trueactual_cost_usd: 0.

Rate limit & quota

GóiReq/phútTokens/ngàyUSD/tháng
Free20200K0 (kèm $1 credit)
Starter1002M9
Pro50020M49
Enterprisetuỳ chỉnhtuỳ chỉnhliên hệ

Khi vượt quota, hệ thống trả 429 với header Retry-After. Tham khảo Cost Dashboard để theo dõi tiêu thụ realtime.

Failover behavior

Nếu nhà cung cấp chính (Google, Anthropic) gặp lỗi 5xx hoặc timeout >30s, ZeniRouter tự động:

  1. Retry lần 1 sau 500ms với cùng model
  2. Retry lần 2 sau 2s với cùng model
  3. Failover sang model backup cùng tier (ví dụ Opus → Sonnet)
  4. Trả về 503 cho client với routing.failover_attempts

Failover trong suốt với app — bạn chỉ thấy latency cao hơn bình thường trong trường hợp hiếm.

Production checklist
1. Set timeout client tối thiểu 60s, vì DEEP tier có thể mất 15s.
2. Log routing.primary_modelactual_cost_usd để theo dõi spend.
3. Bật cache với mọi endpoint công cộng — hiệu quả ngay lập tức.
4. Set quota alert tại 80 phần trăm để không bị 429 đột ngột.

Mã lỗi thường gặp

Ý nghĩaXử lý
401Token sai hoặc hết hạnTạo token mới trong dashboard
403Token không có scopeCấp lại scope ai:read,ai:write
429Vượt rate limitĐợi Retry-After giây hoặc upgrade gói
503Tất cả model failover đều failHiếm. Thử lại sau 30s, liên hệ support nếu lặp