Quay lại blog

AI cho người mớiHướng dẫn

Vì sao một cuộc chat AI dài tốn kém hơn: API gửi lại lịch sử

Mỗi tin nhắn mới trong một cuộc chat AI gửi lại toàn bộ lịch sử, nên đầu vào tăng mỗi lượt. Xem phép tính và 3 cách để giữ chi phí thấp.

Bởi CheapTokens TeamĐã xuất bản Đã cập nhật 7 phút đọc

Ảnh bìa: “Vì sao một cuộc chat dài tốn kém hơn với mỗi tin nhắn” — API gửi lại toàn bộ lịch sử mỗi lượt
Trên trang này
  1. Câu trả lời ngắn gọn
  2. Một ví dụ minh họa với các con số giả định
  3. Chi phí theo giá hiện hành
  4. Ba cách để giữ chi phí thấp
  5. 1. Bắt đầu cuộc chat mới khi chủ đề thay đổi
  6. 2. Cắt bớt lịch sử
  7. 3. Thay các lượt cũ bằng một bản tóm tắt
  8. Xem nó trong chính mã của bạn
  9. Nơi chạy các cuộc chat dài

Những tin nhắn đầu tiên của một cuộc trò chuyện thì rẻ. Tin nhắn thứ năm mươi tốn kém hơn đáng kể so với tin nhắn thứ mười, dù bạn gõ cùng một lượng chữ. Không có gì hỏng cả: đây là cách các API chat hoạt động.

Câu trả lời ngắn gọn#

Một mô hình không ghi nhớ các yêu cầu trước đó của bạn. Tài liệu của OpenAI nói thẳng: "mỗi yêu cầu sinh văn bản là độc lập và không lưu trạng thái", và với một cuộc hội thoại nhiều lượt, bạn đưa các tin nhắn trước đó cùng câu trả lời trước của mô hình vào yêu cầu tiếp theo. Messages API của Anthropic mô tả cùng một mẫu: hội thoại nhiều lượt không lưu trạng thái, trong đó các lượt trước được truyền vào tham số messages.

Vậy nên cửa sổ chat bạn thấy trong một ứng dụng là một ảo ảnh do ứng dụng dựng nên. Phía sau nó, mỗi tin nhắn mới là một yêu cầu mới mang theo toàn bộ cuộc hội thoại cho đến lúc đó. Bạn trả tiền cho token đầu vào ở mỗi yêu cầu, và lịch sử là một phần của đầu vào đó. Nếu bạn mới làm quen với các thuật ngữ này, hãy đọc What is a token và Input vs output tokens trước.

OpenAI nêu rõ khía cạnh tính phí cho các chuỗi phản hồi của mình: tất cả token đầu vào trước đó trong chuỗi đều được tính phí như token đầu vào. Nguyên tắc tương tự đúng với bất kỳ API nào mà bạn tự gửi lịch sử: những gì bạn gửi là những gì được tính.

Một ví dụ minh họa với các con số giả định#

Các con số dưới đây là ví dụ để giảng giải, không phải phép đo thực tế. Giả sử mỗi tin nhắn của bạn khoảng 200 token và mỗi câu trả lời khoảng 300 token. Một lượt trao đổi hoàn chỉnh thêm 500 token vào lịch sử.

Lượt Lịch sử trước đó được gửi lại Tin nhắn mới Đầu vào của yêu cầu này Đầu ra
1 0 200 200 300
5 500 × 4 = 2.000 200 2.200 300
10 500 × 9 = 4.500 200 4.700 300
20 500 × 19 = 9.500 200 9.700 300

Câu trả lời vẫn giữ nguyên độ dài, nhưng đầu vào của lượt 20 gần gấp năm mươi lần đầu vào của lượt 1. Đầu ra không tăng; đầu vào thì tăng.

Giờ là tổng cho một cuộc chat 20 lượt. Lịch sử được gửi lại 0, 1, 2 ... 19 lần tương ứng với số lượt trao đổi, đây là một phép cộng đơn giản:

  • Các lượt trao đổi cũ được gửi lại: 500 × 190 = 95.000 token (190 là 0 + 1 + 2 + ... + 19).
  • Tin nhắn mới: 200 × 20 = 4.000 token.
  • Tổng đầu vào cho cuộc chat: 95.000 + 4.000 = 99.000 token.
  • Tổng đầu ra: 300 × 20 = 6.000 token.

Nếu mô hình ghi nhớ mọi thứ miễn phí, đầu vào sẽ chỉ là 200 × 20 = 4.000 token. Phần còn lại là lịch sử được gửi lại. Tăng gấp đôi số lượt không làm chi phí lịch sử tăng gấp đôi, mà gần như tăng gấp bốn, vì tổng tăng theo bình phương số lượt.

Chi phí theo giá hiện hành#

Đây là cùng cuộc chat 20 lượt đó (99.000 đầu vào, 6.000 đầu ra) theo giá hiện tại. Bảng này là trực tiếp và cập nhật khi biểu giá thay đổi; cột cuối là giá tham chiếu của OpenRouter để so sánh.

Mô hình Chi phí OpenRouter
GLM-5.3-Flash $0.0022 $0.0045
DeepSeek-V4-Flash $0.0021 $0.0056
MiniMax-M2.7 $0.0059 $0.0369

Tổng cộng 99.000 token đầu vào và 6.000 token đầu ra. 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.

Để kiểm tra nhanh bằng văn bản: trên MiniMax-M2.7, toàn bộ cuộc hội thoại này tốn $0.0059. Với một cuộc chat như thế này, nơi đầu vào chiếm ưu thế, giá đầu vào quan trọng nhất: trên MiniMax-M2.7 nó rẻ hơn giá tham chiếu của OpenRouter. Tính trên 1M token, MiniMax-M2.7 là $0.05 cho đầu vào và $0.15 cho đầu ra.

Ba cách để giữ chi phí thấp#

1. Bắt đầu cuộc chat mới khi chủ đề thay đổi#

Lịch sử rẻ nhất là lịch sử rỗng. Nếu bạn đã gỡ lỗi xong một hàm và giờ muốn một công thức nấu ăn, một cuộc chat mới gửi 200 token thay vì 9.700. Trong một ứng dụng đây là một nút bấm; trong mã nó là history = []. Hãy làm vậy mỗi khi ngữ cảnh trước đó không còn giúp ích cho câu hỏi tiếp theo.

2. Cắt bớt lịch sử#

Chỉ giữ vài tin nhắn cuối và bỏ phần còn lại. Giả sử bạn giữ ba lượt trao đổi cuối, nên lịch sử không bao giờ vượt quá 500 × 3 = 1.500 token:

  • Các lượt 1-3 tăng bình thường: 0 + 500 + 1.000 = 1.500 token lịch sử.
  • Các lượt 4-20 mỗi lượt mang theo mức trần 1.500: 1.500 × 17 = 25.500 token.
  • Tổng lịch sử: 1.500 + 25.500 = 27.000 token, cộng 4.000 token tin nhắn mới = 31.000 token đầu vào.

Đó là 31.000 thay vì 99.000 cho cùng 20 lượt, và trên MiniMax-M2.7 nó tốn $0.0025. Cái giá của việc cắt bớt là mô hình quên đi phần đầu cuộc chat, nên hãy giữ system prompt và mọi dữ kiện không được phép mất ở ngoài phần bị cắt.

3. Thay các lượt cũ bằng một bản tóm tắt#

Khi lịch sử trở nên dài, hãy yêu cầu mô hình tóm tắt nó một lần, rồi tiếp tục với bản tóm tắt thay vì toàn bộ văn bản. Trong ví dụ trên, chín lượt trao đổi là 4.500 token; một bản tóm tắt khoảng 300 token mang các ý chính về phía trước. Bạn trả tiền cho một yêu cầu thêm để viết bản tóm tắt, và mọi yêu cầu sau đó đều nhẹ hơn. Cách này giữ được nhiều ý nghĩa hơn việc cắt bớt đơn thuần, đổi lại mất đi một chút chi tiết.

Cửa sổ ngữ cảnh là một giới hạn riêng: nó giới hạn số token mà một yêu cầu có thể chứa, bao gồm cả câu trả lời. Lịch sử rồi sẽ chạm trần đó; Why does an AI answer stop mid-sentence? giải thích điều này.

Xem nó trong chính mã của bạn#

Phản hồi chứa một đối tượng usage, nên bạn có thể tự theo dõi sự tăng trưởng. Đây là một ví dụ: hãy thay khóa và lấy id mô hình từ tài liệu CheapTokens, vì id khác nhau giữa các nhà cung cấp.

python
from openai import OpenAI

client = OpenAI(base_url='https://api.cheaptokens.dev/v1', api_key='YOUR_KEY')

system = {'role': 'system', 'content': 'You are a helpful assistant.'}
history = []
KEEP = 7  # new message + last 3 exchanges (6 messages); None keeps everything

def ask(text):
    history.append({'role': 'user', 'content': text})
    r = client.chat.completions.create(
        model='MODEL_ID_FROM_DOCS',
        messages=[system] + (history[-KEEP:] if KEEP else history),
    )
    answer = r.choices[0].message.content
    history.append({'role': 'assistant', 'content': answer})
    print(r.usage.prompt_tokens, r.usage.completion_tokens)
    return answer

Gọi ask() nhiều lần liên tiếp và in prompt_tokens: với KEEP = None nó tăng mỗi lượt, với KEEP = 7 nó chững lại. Với các agent lặp qua nhiều bước, hiệu ứng tương tự áp dụng cho mỗi bước; How to estimate the cost of an AI agent chỉ cách lập ngân sách cho việc đó.

Nơi chạy các cuộc chat dài#

Các cuộc đối thoại dài và vòng lặp agent chính là những khối lượng công việc mà lưu lượng đầu vào chiếm ưu thế, nên cả cửa sổ ngữ cảnh lớn lẫn chỗ cho câu trả lời dài đều quan trọng:

  • MiniMax-M2.7: ngữ cảnh 180K, tối đa 8.192 token mỗi câu trả lời, cả đầu vào và đầu ra đều rẻ hơn giá tham chiếu của OpenRouter.
  • DeepSeek-V4-Flash: ngữ cảnh 380K, tối đa 32.768 token mỗi câu trả lời, đầu ra rẻ hơn giá tham chiếu của OpenRouter.

CheapTokens có một số dư cho tất cả các mô hình, giá cố định cho mỗi mô hình không có giờ cao điểm, và API tương thích với OpenAI Chat Completions và Anthropic Messages, nên đoạn mã trên hoạt động chỉ bằng cách đổi base URL. Hãy nạp số dư và gửi yêu cầu đầu tiên bằng cách làm theo Your first API request with CheapTokens.