Tài liệu

Tài liệu

bộ nhớ đệm prompt

Đánh dấu một lần tiền tố lời nhắc ổn định bằng cache_control — hoặc gọi một mô hình Claude theo định dạng OpenAI, vốn không có trường này, để Kunavo đặt các điểm ngắt thay bạn. Mọi lệnh gọi tiếp theo sử dụng lại tiền tố đó sẽ được tính phí chỉ bằng một phần giá đầu vào — 10% giá đầu vào trên hầu hết mô hình trò chuyện, thấp nhất là 2.5%. Lớp định tuyến của Kunavo giữ bộ nhớ đệm luôn nóng bằng cách ghim cuộc hội thoại của bạn vào cùng một khóa thượng nguồn.

Với system prompt 30K token và Claude Sonnet 5, một lần đọc bộ nhớ đệm có giá $0.14 / 1M thay vì $1.4 / 1M. Với một tác tử gửi lại cùng ngữ cảnh 50 lần trong một phiên, bộ nhớ đệm tiết kiệm ~90% hóa đơn đầu vào.

Kiểm tra truy cập bộ nhớ đệm thành công bằng hai yêu cầu

Gửi cùng một yêu cầu hai lần trong vòng năm phút. Phần usage của phản hồi đầu tiên ghi tiền tố đã đánh dấu vào cache_creation_input_tokens; phản hồi thứ hai ghi nó vào cache_read_input_tokens, phần được tính theo giá đọc bộ nhớ đệm hiển thị trên trang của mô hình.

check_cache.sh
# Send this twice within five minutes.
curl https://api.kunavo.com/v1/messages \
  -H "Authorization: Bearer $KUNAVO_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "Content-Type: application/json" \
  -d @request.json        # a system block with "cache_control": {"type": "ephemeral"}

# First response — the prefix is written:
#   "usage": {"input_tokens": 21, "cache_creation_input_tokens": 30412,
#             "cache_read_input_tokens": 0, "output_tokens": 180}
# Second response — the prefix is read back:
#   "usage": {"input_tokens": 21, "cache_creation_input_tokens": 0,
#             "cache_read_input_tokens": 30412, "output_tokens": 175}

Có ba điều khiến lượt đọc đó quay lại thành lượt ghi khi yêu cầu đi qua gateway, và không điều nào trả về lỗi:

  • Yêu cầu đã đến một nhà cung cấp thượng nguồn khác. Bộ nhớ đệm chỉ tồn tại ở nơi nó được ghi. Vì vậy Kunavo cố định tiền tố của một cuộc hội thoại vào một khóa thượng nguồn duy nhất (định tuyến affinity, bên dưới).
  • Có thứ đã thay đổi tiền tố. Một system message bị viết lại hay một danh sách công cụ bị đổi thứ tự là một tiền tố khác, và tiền tố khác thì không trúng bộ nhớ đệm.
  • Khoảng nghỉ dài hơn tuổi thọ của mục. Một mục hết hạn năm phút sau lần đọc cuối, nên một agent tạm dừng lâu hơn giữa các lượt sẽ phải dựng lại mỗi lần.

Bộ nhớ đệm prompt của Claude lần lượt phân tích cả ba trường hợp cùng các con số usage giúp phân biệt chúng.

Cách bật

Thêm một điểm ngắt cache_control: { type: "ephemeral" } vào bất kỳ khối hệ thống, thông điệp hoặc định nghĩa công cụ nào. Mô hình lưu vào bộ nhớ đệm đoạn nội dung đến điểm ngắt đó trong lần gọi đầu tiên; các lần gọi tiếp theo có cùng các byte tiền tố sẽ dùng dữ liệu từ bộ nhớ đệm.

cache_example.py
from openai import OpenAI

client = OpenAI(
    api_key="sk-kn-...",
    base_url="https://api.kunavo.com/v1",
)

# Mark the large, stable prefix once with cache_control.
# Every subsequent call that sends the same prefix reads it back
# from cache at 0.10× the input rate on Claude Sonnet 5.
# Per-model rates are in the pricing table below.
SYSTEM = [
    {
        "type": "text",
        "text": open("long_system_prompt.txt").read(),
        "cache_control": {"type": "ephemeral"},
    },
]

resp = client.chat.completions.create(
    model="claude-sonnet-5",
    messages=[
        {"role": "system", "content": SYSTEM},
        {"role": "user", "content": "Summarize the doc above in 3 bullets."},
    ],
)

u = resp.usage
# OpenAI-compat fields populated by Kunavo:
# - prompt_tokens_details.cached_tokens — read from cache
# - cache_creation_input_tokens          — written to cache this call
print(u.prompt_tokens_details.cached_tokens,
      getattr(u, "cache_creation_input_tokens", 0))

Định dạng truyền tải giống hệt trên Messages API gốc — cache_control được chuyển tiếp đến Claude mà không cần dịch:

messages_api.sh
# Native Anthropic Messages API — cache_control passes through untranslated.
curl https://api.kunavo.com/v1/messages \
  -H "Authorization: Bearer $KUNAVO_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-sonnet-5",
    "system": [
      {
        "type": "text",
        "text": "<your large stable system prompt>",
        "cache_control": { "type": "ephemeral" }
      }
    ],
    "messages": [
      { "role": "user", "content": "Summarize the doc above in 3 bullets." }
    ],
    "max_tokens": 1024
  }'
Các byte phải ổn định. Khóa bộ nhớ đệm được xác định theo nội dung. Chỉ cần một ký tự ở bất kỳ vị trí nào trong tiền tố khác đi là bộ nhớ đệm của đoạn đó bị vô hiệu. Đặt nội dung động (dấu thời gian, tên người dùng, ID theo từng lệnh gọi) sau khối được lưu vào bộ nhớ đệm, không đặt bên trong khối đó.

Tự động chèn điểm ngắt trên các endpoint định dạng OpenAI

Các định dạng OpenAI Chat Completions và Responses hoàn toàn không có trường cache_control — OpenAI tự động lưu bộ nhớ đệm trên máy chủ của mình. Claude thì không: Claude chỉ lưu những nội dung được đánh dấu bằng điểm ngắt. Vì vậy, ứng dụng giao tiếp theo giao thức OpenAI không có cách yêu cầu lưu bộ nhớ đệm; nếu chỉ dịch nguyên trạng yêu cầu, Claude sẽ nhận được yêu cầu không có điểm ngắt nào — và mỗi lượt trong cuộc trò chuyện dài sẽ tính phí lại toàn bộ lịch sử theo mức giá đầu vào đầy đủ.

Vì vậy, khi bạn gọi một mô hình Claude qua /v1/chat/completions hoặc /v1/responses, Kunavo sẽ đặt các điểm ngắt mà giao thức không thể truyền tải. Bạn không cần bật gì cả. Cách này chỉ áp dụng cho các mô hình Claude — mọi họ mô hình khác đều được phục vụ qua giao thức mà nhà cung cấp tự động lưu bộ nhớ đệm, không cần đặt điểm ngắt.

no_cache_control.py
# Plain OpenAI Chat Completions — no cache_control anywhere in the body.
# The format has no field for one; Kunavo inserts the breakpoints instead.
resp = client.chat.completions.create(
    model="claude-sonnet-5",
    messages=[
        {"role": "system", "content": LONG_SYSTEM_PROMPT},
        {"role": "user", "content": "first question"},
        {"role": "assistant", "content": "...previous answer..."},
        {"role": "user", "content": "follow-up"},
    ],
)

u = resp.usage
# Turn that writes the cache:
#   u.cache_creation_input_tokens            -> 18,000
#   u.prompt_tokens_details.cached_tokens    ->      0
# Next turn, same prefix, inside the 5-minute window:
#   u.cache_creation_input_tokens            ->    240   (only the new turn)
#   u.prompt_tokens_details.cached_tokens    -> 18,000
#
# Both stuck at 0 on a conversation well over the threshold? The prefix is
# changing between calls — a timestamp or request id inside the cached span.

Vị trí đặt điểm ngắt và thứ tự sử dụng hạn mức:

  • Một điểm ngắt luân phiên ở thông điệp cuối cùng — đặt trên khối nội dung cuối cùng của thông điệp cuối cùng để lưu toàn bộ nội dung trước đó vào bộ nhớ đệm; nếu yêu cầu kết thúc bằng một thông điệp hệ thống được giữ lại trong cuộc trò chuyện (xem bên dưới), điểm ngắt sẽ được đặt thay vào đó trên khối ngay trước thông điệp đó. Chỉ thêm điểm ngắt khi messages đã có một lượt trả lời của trợ lý: thao tác ghi vào bộ nhớ đệm tính phí 1.25× đầu vào, vì vậy đánh dấu một prompt mà không ai gửi lại sẽ tốn thêm một phần tư chi phí mà không tiết kiệm được gì. Lượt trả lời trước đó là dấu hiệu cho thấy chính xác tiền tố này sắp được gửi lại.
  • Một điểm ngắt trên system, một điểm trên tools — phần đầu ổn định của prompt. Đáng để đánh dấu ngay cả trong một lệnh gọi chỉ dùng một lần, vì ứng dụng gửi system prompt một lần hầu như luôn gửi lại cùng prompt đó trong lần gọi tiếp theo.
  • Trước một thông điệp hệ thống được giữ lại trong cuộc trò chuyện — phần hạn mức còn lại sau điểm ngắt luân phiên và các điểm ngắt trên system và tools được đặt trên khối ngay trước thông điệp loại này cuối cùng mà phía sau vẫn còn nội dung, rồi đến khối ngay trước thông điệp loại này liền trước đó. Được điền sau cùng, vì chỉ ứng dụng khách di chuyển thông điệp như vậy giữa các lượt mới cần đến; cuộc trò chuyện không có thông điệp nào như vậy, tức là gần như mọi cuộc trò chuyện, sẽ không có vị trí này.

Có hai giới hạn. Độ dài tối thiểu mà Anthropic cho phép lưu vào bộ nhớ đệm tùy theo mô hình, và Kunavo hoàn toàn không chèn gì khi prompt — gồm thông điệp, system và lược đồ công cụ — có ít ký tự hơn một nửa số token tối thiểu đó. Mức tối thiểu của Anthropic và ngưỡng của Kunavo là 512 token và 256 ký tự trên Opus 5.5, Opus 5, Sonnet 5.5, Fable 5.1 và Fable 5; 1.024 token và 512 ký tự trên Sonnet 5, Opus 4.8, Sonnet 4.6 và Sonnet 4.5; 2.048 token và 1.024 ký tự trên Opus 4.7; 4.096 token và 2.048 ký tự trên Opus 4.6 và Haiku 4.5. Ngưỡng này tính hai token cho mỗi ký tự, nhiều hơn số token mà văn bản tiếng Trung hay tiếng Nhật thực sự dùng cho mỗi ký tự, nên prompt dưới ngưỡng quá ngắn để lưu vào bộ nhớ đệm. Prompt trên ngưỡng vẫn có thể chưa đạt mức tối thiểu, vì trong tiếng Anh một token tương đương khoảng bốn ký tự: Anthropic âm thầm bỏ qua điểm ngắt trên tiền tố ngắn hơn mức tối thiểu và không tính phí ghi hay đọc. Ngoài ra, Anthropic chấp nhận tối đa 4 điểm ngắt cho mỗi yêu cầu — điểm ngắt thứ năm sẽ gây lỗi 400 chứ không bị âm thầm bỏ qua.

Thông điệp system hoặc developer được gửi sau câu trả lời đầu tiên của mô hình sẽ được giữ lại trong cuộc trò chuyện, trong chính lượt mà nó được gửi, thay vì bị đưa lên system: đưa lên như vậy sẽ thay đổi phần đầu của prompt ở lượt nó được thêm vào và ghi lại toàn bộ lịch sử vào bộ nhớ đệm. Claude nhận nó dưới dạng thông điệp hệ thống nếu phía thượng nguồn chấp nhận, nếu không thì dưới dạng văn bản trong lượt của người dùng đó, nằm giữa các thẻ <system-reminder>. Thông điệp hệ thống được gửi trước câu trả lời đầu tiên của mô hình, hoặc thông điệp có điểm ngắt riêng yêu cầu bộ nhớ đệm một giờ, vẫn được đưa vào system.

Các điểm ngắt của bạn không bao giờ bị di chuyển hoặc xóa. Chúng được tính vào cùng hạn mức 4 điểm, và Kunavo chỉ bổ sung vào những vị trí bạn để trống. Nếu bạn gửi bố cục có 4 điểm ngắt, hệ thống không thêm điểm nào; nếu bạn gửi 1 điểm, hệ thống có thể thêm tối đa 3 điểm xung quanh điểm đó. Khi hạn mức sắp hết, vị trí sâu nhất được điền trước — điểm ngắt đặt muộn trong prompt sẽ lưu mọi nội dung trước nó vào bộ nhớ đệm, vì vậy điểm ngắt luân phiên có giá trị nhất. Trên endpoint /v1/messages gốc, hệ thống không chèn điểm ngắt nào: nội dung body được chuyển tiếp nguyên trạng và mọi điểm ngắt trong đó đều do bạn đặt.
Điểm ngắt không đồng nghĩa với một lần truy cập bộ nhớ đệm thành công. Điểm ngắt đánh dấu tiền tố có thể được lưu vào bộ nhớ đệm; để truy cập thành công, các byte tiền tố giống hệt phải được gửi lại trong khoảng thời gian tạm thời của Anthropic — năm phút, được làm mới mỗi lần đọc — và phải được định tuyến đến cùng một khóa thượng nguồn, đó là mục đích của định tuyến affinity bên dưới. Lệnh gọi đầu tiên với tiền tố mới luôn là thao tác ghi, không bao giờ là thao tác đọc; prompt thay đổi ở mỗi lượt sẽ không thể truy cập dữ liệu trong bộ nhớ đệm, bất kể đặt điểm ngắt ở đâu.

Cách báo cáo không thay đổi: các trường cached_tokens và cache_creation_input_tokens như mô tả trong mục Các trường phản hồi đều được điền, dù điểm ngắt do bạn hay gateway chèn. Vì vậy, đối tượng usage là cách bạn kiểm tra xem điểm ngắt được chèn có thực sự giúp truy cập bộ nhớ đệm thành công hay không.

Giá

Mức giá bộ nhớ đệm được tính từ giá đầu vào của từng mô hình theo đúng tỷ lệ của nhà cung cấp — các bảng bên dưới là nguồn tham chiếu chính thức và mọi mức giá trong đó đều được tính từ giá đầu vào của mô hình, không nhập thủ công. Đọc bộ nhớ đệm được tính phí bằng 0.10× giá đầu vào như nhau trên Anthropic và OpenAI, với 2 ngoại lệ: 0.025× ở Claude Fable 5.1, 0.05× ở Claude Opus 5.5. Ghi bộ nhớ đệm được tính phí bằng 1.25× giá đầu vào trên mọi mô hình Claude và trên GPT-6 Astra, GPT-6 Sol, GPT-6 Luna, GPT-5.6 Sol và GPT-5.6 Terra. Kunavo tính phí thao tác ghi có TTL 1 giờ của Claude theo cùng mức 1.25×, thấp hơn mức 2× của Anthropic. Mọi mô hình khác không có giá ghi riêng: thao tác ghi được tính theo mức giá đầu vào thông thường. Dù theo cách nào, một tiền tố được dùng lại dù chỉ một lần cũng có chi phí lưu trong bộ nhớ đệm thấp hơn so với gửi mới. Mỗi nhóm giá áp dụng mức giảm giá riêng của mô hình, vì vậy giá bộ nhớ đệm có cùng mức chiết khấu so với giá niêm yết của nhà cung cấp như giá đầu vào và đầu ra.

Anthropic

ModelInputCache readCache write
Claude Fable 5.1$7$0.175 0.025×$8.75 1.25×
Claude Fable 5$7$0.7 0.10×$8.75 1.25×
Claude Opus 5.5$2.8$0.14 0.050×$3.5 1.25×
Claude Opus 5$3.5$0.35 0.10×$4,375 1.25×
Claude Opus 4.8$3.5$0.35 0.10×$4,375 1.25×
Claude Opus 4.7$3.5$0.35 0.10×$4,375 1.25×
Claude Opus 4.6$3.5$0.35 0.10×$4,375 1.25×
Claude Sonnet 5$1.4$0.14 0.10×$1.75 1.25×
Claude Sonnet 4.6$2.1$0.21 0.10×$2,625 1.25×
Claude Haiku 4.5$0.7$0.07 0.10×$0.875 1.25×

OpenAI

ModelInputCache readCache write
GPT-6 Astra$4$0.4 0.10×$5 1.25×
GPT-6 Sol$0.8$0.08 0.10×$1 1.25×
GPT-6 Luna$0.04$0.004 0.10×$0.05 1.25×
GPT-5.6 Sol$2$0.2 0.10×$2.5 1.25×
GPT-5.6 Terra$0.7$0.07 0.10×$0.875 1.25×
GPT-5.5$2$0.2 0.10×$2 1×
Prompt dài được tính phí theo bậc ngữ cảnh dài của nhà cung cấp. Khi vượt ngưỡng, toàn bộ yêu cầu được tính phí theo bội số của giá đầu vào và đầu ra của mô hình, bao gồm cả thao tác đọc và ghi bộ nhớ đệm: trên 272K token đầu vào trên GPT-6 Astra, GPT-6 Sol, GPT-6 Luna, GPT-5.6 Sol, GPT-5.6 Terra và GPT-5.5 (đầu vào ×2, đầu ra ×1.5). Claude không tính phụ phí ngữ cảnh dài: ngữ cảnh 1M của Claude được tính theo mức giá tiêu chuẩn.
Mức giá sàn trong danh mục đã tính đến bộ nhớ đệm. Kunavo tính phí max(catalog_cost, upstream × markup) cho mỗi lệnh gọi — mức sàn được tính theo giá đầu vào từ bộ nhớ đệm, không phải giá gửi mới, vì vậy khoản tiết kiệm đến được với bạn thay vì bị triệt tiêu.
Các mức giá trên là giá trong danh mục. Hóa đơn thực tế cho mỗi lệnh gọi được tính từ số tín dụng thượng nguồn mà mô hình thực sự đã sử dụng (cộng biên lợi nhuận), sau đó áp dụng mức sàn bằng giá trong danh mục. Khi truy cập bộ nhớ đệm thành công, nhà cung cấp thượng nguồn tính phí ít tín dụng hơn — vì vậy nhánh tính phí theo chi phí thượng nguồn nhân với biên lợi nhuận thường thấp hơn giá trong danh mục, và nhánh giá trong danh mục sẽ được áp dụng. Tóm lại: giá trong danh mục là mức giá cao nhất bạn có thể phải trả; các lệnh gọi dùng bộ nhớ đệm có thể thấp hơn mức đó nhưng không bao giờ cao hơn.

Định tuyến affinity giữ bộ nhớ đệm luôn nóng

Bộ nhớ đệm prompt ở nhà cung cấp thượng nguồn được phân chia theo từng khóa API. Nếu mỗi yêu cầu được chuyển đến một khóa thượng nguồn ngẫu nhiên, tỷ lệ truy cập bộ nhớ đệm thành công là ~1/N. Kunavo tạo hàm băm ổn định từ system prompt + thông điệp người dùng đầu tiên, rồi định tuyến mọi lệnh gọi có cùng tiền tố đến cùng một khóa thượng nguồn duy nhất — sử dụng phép băm rendezvous có trọng số, nhờ đó chỉ ~1/N khóa được ánh xạ lại khi nhóm khóa thay đổi.

Bạn không cần cấu hình gì cả. Định tuyến affinity được áp dụng tự động cho mọi lệnh gọi chat. (Hình ảnh / video / TTS sử dụng định tuyến ngẫu nhiên — các phương thức đó không có bộ nhớ đệm theo từng khóa.)

Các chỉ số trên bảng điều khiển

Khi các lệnh gọi của bạn bắt đầu truy cập bộ nhớ đệm thành công, /app/usage hiển thị hai chỉ số tổng hợp cho khoảng thời gian được chọn:

  • Tỷ lệ truy cập bộ nhớ đệm — số token đầu vào lấy từ bộ nhớ đệm ÷ tổng số token đầu vào. Chỉ số chính xác, được tính từ số lượng token của từng lệnh gọi.
  • Khoản tiết kiệm — số USD tiết kiệm được trong khoảng thời gian này, tính theo từng mô hình dựa trên mức giá đọc bộ nhớ đệm thực tế (không dùng giá trung bình ước lượng). Đây là con số ước tính theo giá trong danh mục — vì hóa đơn thực tế có mức sàn bằng giá trong danh mục và các lệnh gọi dùng bộ nhớ đệm có thể thấp hơn mức sàn, con số này là cận trên sát nhất của khoản tiết kiệm thực tế. Với khối lượng sử dụng chat thông thường, hai con số chỉ chênh nhau vài phần trăm.

Trang chi tiết từng lệnh gọi (/app/usage/<id>) hiển thị số lượng token được đọc từ bộ nhớ đệm + token được ghi vào bộ nhớ đệm khi các giá trị này khác 0, cùng số tiền thực tế đã tính phí.

Các trường phản hồi

Kunavo hiển thị token bộ nhớ đệm ở cả hai dạng phản hồi. Trên endpoint tương thích OpenAI /v1/chat/completions:

TrườngÝ nghĩa
usage.prompt_tokensTổng số token đầu vào (bao gồm token được lưu vào bộ nhớ đệm + token ghi vào bộ nhớ đệm).
usage.prompt_tokens_details.cached_tokensPhần token đầu vào được cung cấp từ bộ nhớ đệm.
usage.cache_creation_input_tokensSố token được ghi vào bộ nhớ đệm trong lệnh gọi này (tính phí theo mức giá ghi bộ nhớ đệm của mô hình trong các bảng phía trên).

Trên Messages API gốc tại /v1/messages, các trường nguyên bản của Anthropic được chuyển tiếp:

TrườngÝ nghĩa
input_tokensĐầu vào mới (chưa được lưu vào bộ nhớ đệm).
cache_read_input_tokensĐược cung cấp từ bộ nhớ đệm, tính phí bằng 0.10× giá đầu vào (0.025× ở Claude Fable 5.1, 0.05× ở Claude Opus 5.5).
cache_creation_input_tokensĐược ghi vào bộ nhớ đệm trong lệnh gọi này (tính phí 1.25× giá đầu vào — cả thao tác ghi có TTL 1 giờ cũng có mức giá này, thấp hơn 2× của Anthropic).

Tiếp theo nên xem gì