Quay lại blog

Bắt đầuHướng dẫn

Yêu cầu đầu tiên đến CheapTokens bằng Python với requests, không cần SDK

Một script Python 20 dòng chỉ với requests: một chat completion, timeout, xử lý lỗi HTTP, và in ra câu trả lời, finish_reason và usage.

Bởi CheapTokens TeamĐã xuất bản 5 phút đọc

Script Python gọi endpoint chat completions của CheapTokens với requests
Trên trang này
  1. Toàn bộ script
  2. Mỗi dòng đang làm gì
  3. Đọc phản hồi
  4. Khi nó không hoạt động
  5. Một lệnh gọi tốn bao nhiêu
  6. Tiếp theo nên làm gì

Bạn không cần gói openai để giao tiếp với API tương thích OpenAI. Một lệnh gọi requests.post, một khóa Bearer và một body JSON là đủ, và bạn sẽ thấy chính xác những gì được truyền đi. Hướng dẫn này xây dựng script đó cho CheapTokens (https://api.cheaptokens.dev/v1/chat/completions) và kết thúc bằng việc in ra câu trả lời, finish_reason và lượng token đã dùng.

Nó phù hợp nếu bạn đang dùng một máy bị hạn chế chỉ cài requests, nếu một cron job nhỏ không nên kéo theo SDK, hoặc nếu bạn chỉ đơn giản muốn hiểu SDK làm gì cho bạn. Hướng dẫn yêu cầu đầu tiên bao gồm SDK, curl và Node; đây là phiên bản Python thuần.

Toàn bộ script#

Đặt khóa của bạn vào một biến môi trường trước (xem cách lưu trữ khóa API an toàn), sau đó lưu đoạn này thành ask.py:

python
import os
import requests

url = "https://api.cheaptokens.dev/v1/chat/completions"
headers = {"Authorization": f"Bearer {os.environ['CHEAPTOKENS_API_KEY']}"}
payload = {
    "model": "deepseek-ai/DeepSeek-V4-Flash-0731",
    "messages": [
        {"role": "user", "content": "Explain what a token is in two sentences."}
    ],
    "max_tokens": 200,
}

try:
    r = requests.post(url, headers=headers, json=payload, timeout=30)
    r.raise_for_status()
except requests.exceptions.Timeout:
    raise SystemExit("No reply within 30 seconds - try again or raise the timeout")
except requests.exceptions.HTTPError as e:
    raise SystemExit(f"HTTP {e.response.status_code}: {e.response.text}")

data = r.json()
choice = data["choices"][0]
print(choice["message"]["content"])
print("finish_reason:", choice["finish_reason"])
print("usage:", data["usage"])

Chạy python ask.py. ID model là ID gateway đầy đủ, deepseek-ai/DeepSeek-V4-Flash-0731; nếu bạn không chắc nên đặt gì ở đó, liệt kê các model với GET /v1/models. Để thử model khác, thay bằng zai-org/GLM-5.3-Flash và không thay đổi gì khác: một số dư bao trùm tất cả các model.

Đường đi của một yêu cầu: key, POST, raise_for_status, choices, usage
Một yêu cầu từ script của bạn đến câu trả lời được in ra

Mỗi dòng đang làm gì#

Dưới đây là năm ý tưởng mà script dựa vào. Quickstart của requests (tài liệu sống, kiểm tra ngày 2 tháng 11 năm 2026) giải thích hầu hết chúng, và tài liệu tham khảo Chat Completions của OpenAI định nghĩa các trường trong phản hồi.

Thẻ ghi nhớ

Năm điều trong script

Gạch đầu dòng thứ ba là cái mọi người bỏ qua. Một script treo mãi mãi trong cron job tệ hơn nhiều so với một script thất bại ầm ĩ sau 30 giây.

Đọc phản hồi#

Một phản hồi thành công là JSON. Những phần bạn quan tâm, theo tài liệu tham khảo Chat Completions:

  • choices[0].message.content là văn bản. Nó có thể là null, vì vậy đừng gọi các phương thức chuỗi trên nó một cách mù quáng.
  • choices[0].finish_reason cho biết lý do model dừng: stop (nó đã hoàn thành), length (giới hạn max_tokens đã cắt nó), tool_calls, content_filter.
  • usage.prompt_tokens, usage.completion_tokens và usage.total_tokens là những gì bạn bị tính phí: đầu vào, đầu ra và tổng của chúng.

Phản hồi có dạng này (các con số là giữ chỗ):

json
{
  "choices": [
    {
      "message": {"role": "assistant", "content": "A token is a small piece of text..."},
      "finish_reason": "stop"
    }
  ],
  "usage": {"prompt_tokens": 18, "completion_tokens": 52, "total_tokens": 70}
}
Tự mình thử xemThử xem: đặt max_tokens thành 5 và chạy lại script. finish_reason nói gì?Hiện đáp án

Nó nói length: model bị dừng bởi giới hạn max_tokens của bạn, vì vậy câu trả lời kết thúc giữa câu. Tăng giới hạn lên và bạn lại nhận được stop. Toàn bộ câu chuyện có trong Câu trả lời AI bị cắt? Sửa finish_reason "length".

Khi nó không hoạt động#

Script biến hầu hết các lỗi thành một dòng đầu ra. Đây là ý nghĩa thông thường của từng lỗi:

Ghép cặp

Ghép từng thông báo với nguyên nhân thông thường của nó

  • HTTP 401Khóa bị thiếu, gõ sai hoặc không phải khóa bạn định gửi
  • HTTP 404Đường dẫn URL hoặc ID model bị sai
  • requests.exceptions.TimeoutKhông có byte nào đến trong thời gian chờ
  • KeyError: 'CHEAPTOKENS_API_KEY'Biến môi trường chưa được đặt trong terminal này

Để xem body lỗi thực tế và kiểm tra từng bước khóa, base URL và ID model, hãy dùng Lỗi API 401 hoặc 404: sai khóa, base URL hoặc ID model. Hai lưu ý nhỏ hơn: nếu bạn thấy KeyError: 'choices', bạn đã phân tích một body lỗi như thành công, nghĩa là raise_for_status() đã bị bỏ qua. Và nếu máy của bạn có tệp ~/.netrc, requests có thể dùng thông tin đăng nhập của nó thay vì header Authorization bạn đã đặt.

Một lệnh gọi tốn bao nhiêu#

Với các con số giữ chỗ từ phản hồi ở trên (khoảng 18 token vào, 52 ra), một lệnh gọi đến DeepSeek-V4-Flash tốn $0.0000055. Đó là con số bạn không thể cảm nhận được, vì vậy hãy nhân nó lên. Giả sử script của bạn tóm tắt 1.000 phiếu hỗ trợ mỗi ngày, khoảng 800 token vào và 300 ra mỗi phiếu:

Mô hình Mỗi yêu cầu 1.000 yêu cầu OpenRouter, 1.000 yêu cầu
GLM-5.3-Flash $0.000028 $0.028 $0.0517
DeepSeek-V4-Flash $0.000042 $0.042 $0.098
MiniMax-M2.7 $0.000085 $0.085 $1.02

800 token đầu vào và 300 token đầu ra mỗi yêu cầu. Giá trên 1 triệu token là giá hiện hành và thay đổi cùng với biểu phí của chúng tôi; cột OpenRouter hiển thị giá tham chiếu cho cùng khối lượng công việc.

Giá được cố định theo từng model, không có giờ cao điểm, vì vậy cùng một script tốn cùng một chi phí lúc 3 giờ sáng và lúc giữa trưa. Giá hiện tại theo từng model có trên trang giá, và tài liệu liệt kê các endpoint.

Tiếp theo nên làm gì#

Khi điều này hoạt động, các bước tiếp theo thông thường là một vòng lặp qua nhiều đầu vào, thử lại khi gặp 429 (xem 429 Too Many Requests: thử lại với backoff), hoặc cùng lệnh gọi đó với streaming. Nếu bạn không muốn tự quản lý HTTP, con đường SDK chỉ cách một thay đổi base_url.