Bỏ qua, tới nội dung chính
← Tất cả bài viết
Hướng dẫn

Tích hợp OpenAI SDK trong 5 phút

Đọc 4 phút

Gateway nói đúng wire format của OpenAI — cùng endpoint, cùng cấu trúc request, cùng khung SSE. Code của bạn đang chạy với api.openai.com thì chạy được với CLF AI Gateway sau hai thay đổi: base URL và key. Dưới đây là cấu hình chạy được cho hai SDK chính thức, LangChain và Vercel AI SDK, kèm streaming và những lỗi thực tế bạn sẽ gặp.

Chuẩn bị

  • Tạo key tại app.clfaigateway.dev. Key có prefix sk-gw- và chỉ hiện đúng một lần — lưu ngay khi thấy.
  • Base URL: https://api.clfaigateway.dev/v1
  • ID model: deepseek-v4-flashdeepseek-v4-pro (context 1M), kimi-k2.6, kimi-k2.7-code, glm-5.2 (262K) và glm-4.7-flash (131K) — danh sách đầy đủ kèm giá ở /models.

Python — SDK openai chính thức

Chạy với openai ≥ 1.0 (pip install openai):

python
import os
from openai import OpenAI

client = OpenAI(
    base_url="https://api.clfaigateway.dev/v1",
    api_key=os.environ["CLF_API_KEY"],  # sk-gw-...
)

resp = client.chat.completions.create(
    model="kimi-k2.6",
    messages=[{"role": "user", "content": "Say hello in five words."}],
    max_tokens=256,
)
print(resp.choices[0].message.content)

max_tokens không bắt buộc nhưng nên thành thói quen: nó kiêm luôn vai trò trần chi tiêu cứng cho mỗi request.

Node / TypeScript — SDK openai chính thức

npm install openai:

typescript
import OpenAI from 'openai';

const client = new OpenAI({
  baseURL: 'https://api.clfaigateway.dev/v1',
  apiKey: process.env.CLF_API_KEY, // sk-gw-...
});

const resp = await client.chat.completions.create({
  model: 'kimi-k2.6',
  messages: [{ role: 'user', content: 'Say hello in five words.' }],
  max_tokens: 256,
});
console.log(resp.choices[0].message.content);

Streaming

Streaming là SSE tiêu chuẩn qua SDK. Ba điểm riêng của gateway cần biết: truyền stream_options: {"include_usage": true} để chunk cuối mang số token chính thức (đúng số dùng để tính tiền); bắt finish_reason: "error" — thượng nguồn đứt giữa stream thì lỗi đi trong thân stream, vì HTTP status đã gửi 200 từ trước; và Kimi/GLM là model reasoning nên reasoning_content stream về trước phần content nhìn thấy được.

python
stream = client.chat.completions.create(
    model="glm-5.2",
    messages=[{"role": "user", "content": "Explain SSE in one sentence."}],
    stream=True,
    stream_options={"include_usage": True},
)

usage = None
for chunk in stream:
    if chunk.usage is not None:
        usage = chunk.usage  # chunk cuối = số token bạn bị tính tiền
    for choice in chunk.choices:
        thinking = getattr(choice.delta, "reasoning_content", None)
        if thinking:
            print(thinking, end="")
        if choice.delta.content:
            print(choice.delta.content, end="")
        if choice.finish_reason == "error":
            raise RuntimeError("stream đứt giữa chừng; chỉ token đã nhận mới bị tính")

print(usage)

LangChain

langchain-openai nhận thẳng base URL tùy chỉnh (pip install langchain-openai):

python
from langchain_openai import ChatOpenAI

llm = ChatOpenAI(
    model="glm-4.7-flash",
    base_url="https://api.clfaigateway.dev/v1",
    api_key="sk-gw-...",
)

print(llm.invoke("Summarize SSE in one sentence.").content)

Từ đây ChatOpenAI hoạt động bình thường trong chain, agent và .stream() — với LangChain, gateway chỉ là thêm một endpoint hình dạng OpenAI.

Vercel AI SDK

Dùng provider OpenAI-compatible (npm install ai @ai-sdk/openai-compatible):

typescript
import { createOpenAICompatible } from '@ai-sdk/openai-compatible';
import { streamText } from 'ai';

const clf = createOpenAICompatible({
  name: 'clf-ai-gateway',
  baseURL: 'https://api.clfaigateway.dev/v1',
  apiKey: process.env.CLF_API_KEY,
});

const result = streamText({
  model: clf('kimi-k2.6'),
  prompt: 'Write a two-line haiku about prepaid credits.',
});

for await (const text of result.textStream) {
  process.stdout.write(text);
}

generateText, streamText và bộ hook UI useChat chạy nguyên vẹn không đổi gì.

Hai lỗi thực tế bạn sẽ gặp

401 invalid_api_key

Key thiếu, gõ sai, hoặc đã bị revoke. Kiểm tra header Authorization: Bearer sk-gw-... và chắc rằng bạn đã copy trọn key lúc nó hiện ra. SDK báo lỗi này bằng class authentication error tiêu chuẩn của nó.

402 insufficient_credits

Số dư trả trước không đủ cho khoản tạm giữ ước lượng của request. Body nói rõ bạn thiếu bao nhiêu:

json
{
  "error": {
    "type": "insufficient_credits",
    "code": "insufficient_credits",
    "message": "Insufficient credits. Available: $0.0041. This request requires an estimated hold of $0.0269. Top up at https://app.clfaigateway.dev/billing/topup",
    "metadata": {
      "available_nano": 4100000,
      "required_estimate_nano": 26927600,
      "topup_url": "https://app.clfaigateway.dev/billing/topup"
    }
  }
}

Nạp thêm (VietQR tự xác nhận sau khoảng 15 giây; thẻ quốc tế cũng dùng được) rồi gọi lại — không cần code gì thêm ngoài việc hiện message cho người dùng. Cũng nên biết: 404 model_not_found nghĩa là ID model không nằm trong danh sách model đang mở (xem trang models), còn 429 rpm_exceeded đi kèm header retry-after mà các SDK chính thức đã tự tôn trọng bằng backoff.

Mấy mặc định giúp tiết kiệm tiền

  • Đặt max_tokens cho mọi lời gọi production — ngắt kết nối giữa stream không hủy được token đã sinh.
  • Để phần ổn định (system prompt, tools, ví dụ few-shot) lên đầu hội thoại: prefix lặp lại tính theo giá cached input, rẻ hơn khoảng 6 lần trên các model Kimi.
  • Lời gọi lặp lại tất định thì thêm "cache": {"mode": "on"} cùng temperature: 0 — trúng trọn vẹn chỉ tính 10% giá thường.
  • Đọc usage trên mọi response. Phần toán đằng sau nó nằm ở Billing theo token — bạn tự kiểm lại được từng con số.