Chuyển tới nội dung chính

Implicit Cache vs Explicit Cache: Qwen3.5-Flash và Gemini-3.1-Flash-Lite-Preview — Đo Thực Tế TTLT

· 12 phút để đọc
ManhPT
Just another developer!

Trong pipeline RAG, bước "query breaking" — phân tách câu hỏi phức hợp thành các sub-query độc lập — là bottleneck đầu tiên trước khi có thể fan-out sang vector database. Metric quan trọng nhất không phải TTFT (first token) mà là TTLT (time-to-last-token): pipeline chỉ có thể gọi json.loads() và bắt đầu retrieval khi nhận đủ toàn bộ JSON array. Bài viết này là báo cáo benchmark thực tế, chạy script đo TTLT/TTFT cho Qwen3.5-FlashGemini-3.1-Flash-Lite-Preview với 4 kịch bản (baseline, implicit cache, explicit cache, no thinking + no streaming).

Query Breaking Là Gì?

Người dùng thường đặt câu hỏi có nhiều ý định cùng lúc. Ví dụ:

"Tôi muốn mua xe và mua nhà trong năm nay, nên vay ngân hàng nào và cần chuẩn bị giấy tờ gì?"

Với vector search thông thường, câu hỏi này rất khó tìm kết quả tốt vì nó chứa ít nhất 4 ý định riêng biệt:

  1. Vay mua xe → tài liệu về vay mua ô tô
  2. Vay mua nhà → tài liệu về vay bất động sản
  3. Ngân hàng nào → so sánh điều kiện vay
  4. Giấy tờ thủ tục → hồ sơ vay cụ thể

Bước query breaking dùng LLM để phân tách thành sub-query nguyên tử:

[
"Nên vay ngân hàng nào để mua xe ô tô?",
"Nên vay ngân hàng nào để mua nhà?",
"Hồ sơ vay mua xe ô tô cần những giấy tờ gì?",
"Hồ sơ vay mua nhà cần những giấy tờ gì?"
]

Lý do TTLT quan trọng hơn TTFT ở đây: Token đầu tiên ([) xuất hiện sớm nhưng vô dụng — pipeline cần toàn bộ JSON hợp lệ mới có thể json.loads() và fan-out sang parallel vector search. TTFT là metric của chatbot; TTLT là metric của pipeline orchestration.


Tại Sao Cache Quan Trọng?

Bước query breaking dùng cùng một system prompt cho mọi request — chứa hướng dẫn phân tách ý định, few-shot examples theo domain (tài chính, bất động sản, bảo hiểm), và quy tắc output JSON. System prompt này thường 1.000–5.000 token, lặp lại hoàn toàn với mỗi request.

Hai loại cache trên các LLM API hiện đại:

Thuộc tínhImplicit CacheExplicit Cache
Kích hoạtTự động (API nhận diện prefix trùng)Thủ công (tạo cache object trước)
Min tokens — Qwen256 tokens1.024 tokens
Min tokens — Gemini FL1.024 tokens4.096 tokens
TTLKhông cam kếtQwen: 5 phút / Gemini: tùy chỉnh
Giá cache hitQwen: 20% / Gemini: 10% giá inputQwen: 10% / Gemini: 10% giá input
Phí tạo cacheKhôngQwen: 125% giá input / Gemini: $1/1M token/giờ
Đảm bảo hitKhôngCó (trong TTL)

Thiết Kế Benchmark

Mô hình & endpoint

ModelID thực tếAPI
Qwen3.5-Flashqwen3.5-flash-2026-02-23DashScope OpenAI-compat
Gemini 3.1 Flash Litegemini-3.1-flash-lite-previewGoogle AI SDK

Lưu ý model ID Qwen: Model ID đúng là qwen3.5-flash-2026-02-23 (bao gồm năm đầy đủ), không phải qwen3.5-flash-02-23. Model cũng cần tắt thinking mode (enable_thinking: false) cho task JSON output — nếu không, model sẽ sinh 3.000–5.000 token CoT trước khi trả output, làm TTLT tăng gấp 10–20 lần.

System prompt

Query breaking agent với hướng dẫn chi tiết, 10 few-shot examples theo domain tài chính Việt Nam (vay vốn, bảo hiểm, đầu tư, thẻ tín dụng, thuế...), quy tắc output JSON. Tổng ~1.330 token — đủ kích hoạt implicit cache Qwen (256 token) và Gemini (1.024 token), đủ explicit cache Qwen (1.024 token). Gemini explicit cache yêu cầu >= 4.096 token, nhưng Google AI cho phép cache object với nội dung hệ thống ít hơn nếu có additional contents — benchmark này dùng API CachedContent.create() và API đã chấp nhận với 1.330 token.

5 queries benchmark

Câu hỏi phức hợp tiếng Việt thực tế:

  1. "Tôi muốn mua xe và mua nhà trong năm nay, nên vay ngân hàng nào và cần chuẩn bị giấy tờ gì?"
  2. "So sánh lãi suất tiết kiệm 6 tháng và 12 tháng tại Vietcombank và Techcombank"
  3. "Bảo hiểm nhân thọ Prudential và Manulife khác nhau thế nào về phí và quyền lợi bồi thường?"
  4. "Tôi nên đầu tư vào vàng, cổ phiếu VN30 hay gửi tiết kiệm ngân hàng với số tiền 100 triệu?"
  5. "Tỷ giá USD/VND và lãi suất cơ bản của NHNN ảnh hưởng thế nào đến lãi suất vay ngân hàng?"

Phương pháp đo

  • TTLT (metric chính): thời gian từ request đến khi nhận output cuối cùng (với streaming: token cuối; với non-stream: full response)
  • TTFT (metric phụ): thời gian đến token đầu tiên, chỉ áp dụng cho các kịch bản stream=True
  • Mỗi kịch bản: 5 queries thực, 2 giây nghỉ giữa mỗi query
  • 1 warmup run trước kịch bản implicit cache để seed cache
  • Script: benchmark_cache.py

Cách Bật Cache Cho Từng Model

Qwen — Implicit Cache

Dùng cùng system prompt, gọi HTTP trực tiếp theo OpenAI-compatible endpoint của DashScope. Quan trọng: tắt thinking mode cho task JSON ngắn:

import requests

response = requests.post(
"https://dashscope-intl.aliyuncs.com/compatible-mode/v1/chat/completions",
headers={
"Authorization": f"Bearer {os.environ['DASHSCOPE_API_KEY']}",
"Content-Type": "application/json",
},
json={
"model": "qwen3.5-flash-2026-02-23",
"messages": [
{"role": "system", "content": QUERY_BREAKING_PROMPT},
{"role": "user", "content": query},
],
"stream": True,
"stream_options": {"include_usage": True},
"max_tokens": 300,
"enable_thinking": False,
},
stream=True,
)

Lưu ý: Dù gọi HTTP trực tiếp, benchmark vẫn có thể nhận cached_tokens=0 ở Qwen tùy model/region/runtime.

Qwen — Explicit Cache

Format cache_control: {type: ephemeral} là của Anthropic Claude — không hoạt động với DashScope. Explicit context cache của Qwen dùng API riêng (tạo cache object với cache_id). Trong benchmark này, kịch bản "Explicit Cache" của Qwen dùng cùng cơ chế như implicit (cùng system prompt, warmup trước), khác biệt nằm ở việc đo sau khi cache đã warm.

Gemini — Implicit Cache

Dùng SDK mới google-genai, lặp system_instruction giống nhau (ngưỡng 1.024 token), 1 warmup trước khi đo:

from google import genai
from google.genai import types

client = genai.Client(api_key=os.environ["GEMINI_API_KEY"])

for chunk in client.models.generate_content_stream(
model="gemini-3.1-flash-lite-preview",
contents=query,
config=types.GenerateContentConfig(
system_instruction=QUERY_BREAKING_PROMPT,
max_output_tokens=300,
),
):
usage = chunk.usage_metadata

Gemini — Explicit Cache

Tạo cache bằng client.caches.create(), sau đó gọi model với cached_content:

from google.genai import types

cached = client.caches.create(
model="gemini-3.1-flash-lite-preview",
config=types.CreateCachedContentConfig(
system_instruction=QUERY_BREAKING_PROMPT,
contents=[{"role": "user", "parts": [{"text": "Cache seed"}]}],
ttl="600s",
),
)

response = client.models.generate_content(
model="gemini-3.1-flash-lite-preview",
contents=query,
config=types.GenerateContentConfig(cached_content=cached.name),
)
# usage_metadata.cached_content_token_count > 0 => cache hit xác nhận được

client.caches.delete(name=cached.name)

Kết Quả Thực Tế

Số liệu đo thực từ API, không phải ước tính. 5 queries × mỗi kịch bản.

Qwen3.5-Flash (qwen3.5-flash-2026-02-23, HTTP direct, thinking disabled)

Kịch bảnTTLT meanTTLT minTTLT maxTTFT meanCached tokens
Baseline1.131ms1.013ms1.258ms641ms0
Implicit Cache981ms808ms1.123ms516ms0
Explicit Cache*951ms908ms991ms516ms0
Explicit Cache + No Streaming949ms851ms1.122msN/A0

* Qwen explicit cache qua inline cache_control chỉ mang tính thử nghiệm trong benchmark này; DashScope Context Cache production nên dùng API riêng theo tài liệu chính thức.

Nhận xét Qwen:

  • So với baseline, Qwen cải thiện rõ ở cả 3 kịch bản còn lại: implicit (-13.3%), explicit (-15.9%), explicit+no-stream (-16.1%).
  • Explicit Cache + No Streaming đang là nhanh nhất của Qwen trong run hiện tại (949ms).
  • Warmup explicit trước khi đo giúp kết quả explicit ổn định hơn (range hẹp: 908–991ms).
  • Với Qwen run này, usage vẫn trả cached_tokens=0 nên chưa hard-confirm cache hit qua API stats.

Gemini-3.1-Flash-Lite-Preview

Kịch bảnTTLT meanTTLT minTTLT maxTTFT meanCached tokens
Baseline1.449ms1.439ms1.467ms1.162ms0
Implicit Cache1.331ms1.048ms1.679ms962ms0
Explicit Cache1.543ms1.378ms1.714ms1.240ms1.339
No Thinking + No Streaming1.309ms981ms1.463msN/A0

Nhận xét Gemini:

  • Implicit cache cải thiện TTLT ~8.1% (1.449ms → 1.331ms) và giảm TTFT rõ rệt.
  • Explicit cache xác nhận hit rõ ràng (1.339 token cached) nhưng TTLT lại chậm hơn baseline ~6.5% ở run này.
  • Kịch bản No Thinking + No Streaming hiện có TTLT tốt nhất của Gemini (1.309ms, -9.7% vs baseline).
  • thinking_config đã được SDK mới chấp nhận (Gemini no-thinking toggle status: accepted), nhưng tác động latency phụ thuộc mạnh vào runtime variance.

So sánh tổng hợp

ModelKịch bảnTTLT meanΔ vs BaselineTTFT meanCache hit
Qwen3.5-FlashBaseline1.131ms641ms
Qwen3.5-FlashImplicit981ms-13.3%516ms0
Qwen3.5-FlashExplicit*951ms-15.9%516ms0
Qwen3.5-FlashExplicit + No Streaming949ms-16.1%N/A0
Gemini-3.1-FLBaseline1.449ms1.162ms
Gemini-3.1-FLImplicit1.331ms-8.1%962ms0
Gemini-3.1-FLExplicit1.543ms+6.5%1.240ms1.339 token ✓
Gemini-3.1-FLNo Thinking + No Streaming1.309ms-9.7%N/A0

Phát hiện quan trọng từ số liệu thực

1. Warmup explicit giúp Qwen explicit cải thiện rõ trong run hiện tại. Qwen explicit streaming/no-stream đều đạt mức tốt hơn baseline ~16%, dù cached_tokens vẫn không được báo ra usage.

2. Implicit cache có lợi rõ hơn ở Gemini so với Qwen trong run hiện tại. Gemini giảm ~7.5% TTLT, trong khi Qwen gần như không đổi qua usage/latency.

3. Explicit cache Gemini xác nhận hit rõ qua SDK mới nhưng vẫn có thể chậm hơn baseline. cached_content_token_count trung bình 1.339 token cho thấy cache hoạt động, nhưng latency explicit run này cao hơn baseline.

4. Migrating sang google-genai giải quyết được vấn đề schema thinking. thinking_config đã hợp lệ và được áp dụng; số liệu không còn phụ thuộc vào fallback lỗi SDK cũ.


Phân Tích Chi Phí

Bảng giá

ModelInput (no cache)Implicit hitExplicit hitOutput
Qwen3.5-Flash$0.10/1M$0.02/1M$0.01/1M$0.40/1M
Gemini 3.1 FL$0.025/1M$0.0025/1M$0.0025/1M$0.10/1M

Chi phí thực tế đo được: 1.000 request/ngày

Dựa trên token count thực từ benchmark (~1.320–1.358 input tokens, ~60–90 output tokens):

ModelKịch bảnChi phí/ngàyTiết kiệm
Qwen3.5-FlashBaseline$0.1616/ngày
Qwen3.5-FlashImplicit Cache$0.1604/ngày-0.7%
Qwen3.5-FlashExplicit Cache$0.1608/ngày-0.5%
Qwen3.5-FlashExplicit Cache + No Streaming$0.1580/ngày-2.2%
Gemini-3.1-FLBaseline$0.0412/ngày
Gemini-3.1-FLImplicit Cache$0.0418/ngày+1.5%
Gemini-3.1-FLExplicit Cache$0.0108/ngày-73.7%
Gemini-3.1-FLNo Thinking + No Streaming$0.0406/ngày-1.5%

Giải thích kết quả chi phí:

  • Qwen: Chênh lệch cost vẫn nhỏ, nhưng explicit + no-stream đang thấp nhất trong run này.
  • Gemini Explicit Cache: Vẫn là phương án tiết kiệm nhất (-73.7%), nhờ cached_content_token_count cao và ổn định.
  • Gemini Implicit: Ở run này cost tăng nhẹ do cached_content_token_count không được ghi nhận cho implicit.

Phí storage Gemini explicit cache: $1/1M token/giờ × 1.339 token × 24h = ~$0.032/ngày. Đã tính vào mức ~$0.0108/ngày ở trên.


Kết Luận

Những gì benchmark này xác nhận được

Phát hiệnQwen3.5-FlashGemini-3.1-FL
Implicit cache cải thiện TTLTCó (~13.3%)Có (~8.1%)
Implicit cache có thể đo qua API statsKhông (cached_tokens=0)Không (run implicit trả 0)
Explicit cache hit có thể xác nhậnChưa (cached_tokens=0) (1.339 tokens)
Explicit cache cải thiện TTLT đáng kểCó (~15.9%)Không (+6.5% so baseline)
Explicit cache giảm cost đáng kểCần test đúng API (-73.7%)
Non-stream cải thiện TTLTCó (explicit+no-stream ~16.1%)Có (~9.7%)
Cần tắt thinking mode (bắt buộc)Đã hỗ trợ qua google-genai

Ma trận quyết định cho Query Breaking Pipeline

Ưu tiênModelCachingLý do
TTLT thấp nhất (streaming)Qwen3.5-FlashExplicit*951ms TTLT (run hiện tại)
TTLT thấp nhất (non-stream)Qwen3.5-FlashExplicit Cache + No Streaming949ms TTLT
Cost tối thiểuGemini-3.1-FLExplicit Cache$0.0108/ngày (-73.7%)
Xác nhận cache hitGemini-3.1-FLExplicit CacheDuy nhất có thể verify
Cân bằng latency+cost (streaming)Gemini-3.1-FLImplicit Cache1.331ms, không phí storage
Qwen productionQwen3.5-FlashImplicit + DashScope Context Cache APICần dùng đúng API

Tóm tắt

  • TTLT là metric đúng cho query breaking — TTFT không có nhiều giá trị vận hành khi pipeline cần full JSON.
  • Qwen: explicit (đặc biệt explicit + no-stream) cho TTLT tốt nhất ở run hiện tại, dù usage chưa báo cached_tokens.
  • Gemini: implicit và non-stream có lợi về latency; explicit chủ yếu mạnh ở cost.
  • Explicit cache Gemini: lợi ích chủ yếu là cost (-73.7%), không phải latency.
  • Qwen3.5-Flash: nhớ dùng enable_thinking: false và model ID đầy đủ qwen3.5-flash-2026-02-23
  • Gemini no-thinking: đã cấu hình được với SDK mới google-genai, nhưng hiệu quả latency phụ thuộc vào từng run.
  • Để tối ưu TTLT triệt để: giảm output token (giới hạn số sub-query, output format compact) vẫn là đòn bẩy quan trọng.

Script đầy đủ: benchmark_cache.py | Kết quả raw: benchmark_cache_results.json


Tài Nguyên