·

Khi thiết kế prompt cho AI agent, một trong những quyết định ảnh hưởng lớn nhất đến chi phí token lại thường bị xử lý theo cảm tính: "cứ thêm vài ví dụ (example) cho chắc". Few-shot prompting — kỹ thuật đưa vào prompt một số ví dụ input/output mẫu — có thể cải thiện độ chính xác đáng kể, nhưng mỗi ví dụ đều là token phải trả tiền trên từng request, mãi mãi, chứ không phải chi phí một lần. Bài này đi sâu vào bài toán kinh tế học của few-shot so với zero-shot: khi nào ví dụ đáng tiền, khi nào chúng chỉ là rác token, và làm sao xây dựng hệ thống chọn ví dụ động để agent chỉ trả tiền cho ví dụ khi thực sự cần.

Understanding the Token Cost of Examples

Điều đầu tiên cần nắm rõ: few-shot examples không phải là "training" theo nghĩa fine-tuning. Fine-tuning là chi phí một lần (one-time cost) — bạn huấn luyện model một lần, sau đó mọi inference đều rẻ vì model đã "học" pattern vào trong weights. Few-shot examples thì ngược lại: chúng phải được nhồi vào context window của mỗi request, nghĩa là bạn trả tiền cho cùng một kiến thức lặp đi lặp lại, vô hạn lần.

Hãy làm một bài toán cụ thể. Giả sử bạn có một agent phân loại ticket hỗ trợ khách hàng vào các category (billing, bug report, feature request, spam...). Mỗi ví dụ few-shot bao gồm:

  • Input mẫu (nội dung ticket): trung bình 80 token
  • Output mẫu (category + giải thích ngắn): trung bình 25 token
  • Định dạng bao quanh (labels như "Input:", "Output:", dấu phân cách): 10 token

→ Mỗi ví dụ tốn khoảng 115 token.

Nếu bạn dùng 5 ví dụ few-shot cho mỗi request: 5 × 115 = 575 token chỉ để "dạy" model cách làm — chưa tính prompt hệ thống, instruction, hay input thực tế cần xử lý.

Giờ nhân với tần suất sử dụng thực tế:

Số request/ngày Token ví dụ/ngày Token ví dụ/tháng Chi phí/tháng (giả định $3/1M input token)
1.000 575.000 ~17,25 triệu ~$51,75
50.000 28,75 triệu ~862,5 triệu ~$2.587,5
500.000 287,5 triệu ~8,6 tỷ ~$25.875

Đây là chi phí chỉ riêng cho ví dụ, lặp lại mỗi request, không hề giảm theo thời gian — trái với fine-tuning, nơi bạn trả chi phí train một lần rồi inference gần như không tốn thêm gì cho "kiến thức" đó.

So sánh ba mô hình chi phí:

  1. Zero-shot: 0 token ví dụ. Chi phí = chi phí instruction + input. Rẻ nhất mỗi request, nhưng rủi ro độ chính xác thấp hơn nếu task phức tạp hoặc mơ hồ.
  2. Few-shot (static): chi phí ví dụ cố định × mọi request, vô hạn. Chi phí tăng tuyến tính theo volume, không bao giờ khấu hao.
  3. Fine-tuning: chi phí train một lần (có thể vài chục đến vài trăm đô cho dataset nhỏ), sau đó inference gần như bằng zero-shot về độ dài prompt. Hoà vốn (break-even) khi volume đủ lớn để chi phí ví dụ lặp lại vượt chi phí train.

Điểm hoà vốn giữa few-shot và fine-tuning là con số bạn nên tính trước khi quyết định kiến trúc. Nếu agent của bạn xử lý dưới vài nghìn request/tháng, few-shot vẫn rẻ hơn train. Nhưng ở quy mô production (hàng trăm nghìn đến hàng triệu request/tháng), few-shot tĩnh có thể âm thầm trở thành dòng chi phí lớn nhất trong hệ thống — lớn hơn cả input thực tế của user.

Mẹo: Trước khi thêm ví dụ vào prompt, hãy tính nhanh "chi phí ví dụ/tháng" = (số token ví dụ) × (số request/tháng) × (giá token). Nếu con số này vượt quá 20-30% tổng chi phí LLM của agent, đó là dấu hiệu cần xem xét fine-tuning hoặc dynamic selection thay vì few-shot tĩnh.

When Zero-Shot Works — and Why It's Usually Your First Choice

Có một sai lầm phổ biến khi làm prompt engineering: mặc định rằng model cần ví dụ mới hiểu được yêu cầu. Điều này đúng với các model thế hệ cũ, nhưng các LLM hiện đại (GPT-4 class, Claude, Gemini...) có khả năng instruction-following rất mạnh — chúng thường chỉ cần instruction rõ ràng, không cần ví dụ minh họa.

Zero-shot nên là điểm khởi đầu mặc định, không phải phương án dự phòng. Lý do:

  1. Chi phí thấp nhất có thể: không tốn token cho ví dụ, nghĩa là latency thấp hơn, chi phí thấp hơn, và context window còn nhiều chỗ cho input thực tế (quan trọng với task cần input dài như phân tích document).
  2. Không bị "đóng khung" bởi ví dụ: few-shot examples có tác dụng phụ là khiến model có xu hướng bám sát pattern của ví dụ, đôi khi làm giảm khả năng tổng quát hóa cho case ngoài phạm vi ví dụ đã cho (overfitting theo ví dụ).
  3. Dễ maintain: instruction rõ ràng dễ đọc, dễ review, dễ update hơn một bộ ví dụ phải curate và giữ đồng bộ.

Heuristic quyết định thực tế — hãy tự hỏi theo thứ tự:

  • Bước 1: Viết instruction rõ ràng nhất có thể (định nghĩa task, ràng buộc, format output mong muốn, ví dụ edge case bằng lời chứ chưa phải ví dụ đầy đủ). Test với zero-shot.
  • Bước 2: Đo độ chính xác trên một tập test đại diện (ít nhất 30-50 case, càng nhiều càng đáng tin). Nếu độ chính xác đạt ngưỡng chấp nhận được (ví dụ ≥ 90% cho task phân loại không critical), dừng ở đây. Đừng thêm ví dụ "cho chắc".
  • Bước 3: Chỉ khi zero-shot thất bại có hệ thống ở một số pattern cụ thể (không phải lỗi ngẫu nhiên), hãy phân tích: model sai vì không hiểu format mong muốn, hay sai vì không nắm được nhận định/ngữ nghĩa tinh vi của task? Câu trả lời quyết định bạn cần schema/template (rẻ) hay few-shot thật (đắt hơn) — chi tiết ở phần cuối bài.

Ví dụ cụ thể: task "trích xuất tên công ty và số tiền hóa đơn từ email" thường zero-shot xử lý tốt nếu instruction nêu rõ format JSON mong muốn kèm tên field. Nhưng task "đánh giá mức độ khẩn cấp của ticket dựa trên tone và ngữ cảnh ngầm" thường cần vài ví dụ vì đây là judgment call mang tính chủ quan, khó diễn đạt hết bằng instruction.

Prompt zero-shot mẫu cho task phân loại ticket (không ví dụ):

You are a support ticket classifier. Classify the ticket below into exactly one category:
billing, bug_report, feature_request, or spam.

Rules:
- billing: payment, invoice, subscription, refund issues
- bug_report: something is broken or not working as expected
- feature_request: user is asking for new functionality
- spam: promotional content, irrelevant links, or gibberish

Output only the category name, nothing else.

Ticket: "{ticket_text}"
Category:

Instruction này nêu rõ ràng buộc, định nghĩa từng category, và format output — không cần ví dụ minh họa vẫn đủ để model hoạt động tốt với đa số ticket rõ ràng.

Mẹo: Luôn benchmark zero-shot trước khi viết bất kỳ ví dụ nào. Ghi lại accuracy zero-shot làm baseline — nếu sau này ai đó đề xuất thêm few-shot, bạn có số liệu để so sánh gain thực tế so với chi phí token thêm vào, tránh thêm ví dụ theo cảm tính.

The Diminishing Returns of Additional Examples

Giả sử zero-shot không đủ và bạn cần few-shot. Câu hỏi tiếp theo: bao nhiêu ví dụ là đủ? Đây là chỗ nhiều team lãng phí token nhất — tâm lý "thêm ví dụ luôn tốt hơn" dẫn đến prompt phình to với 10-15 ví dụ trong khi phần lớn giá trị đã đạt được từ 3 ví dụ đầu.

Quy luật quan sát được trong thực tế (và được nhiều nghiên cứu về in-context learning xác nhận) là đường cong lợi ích của few-shot có dạng logarithmic, không phải linear: mỗi ví dụ thêm vào mang lại cải thiện độ chính xác nhỏ hơn ví dụ trước, và sau một điểm ngưỡng (thường 2-5 ví dụ với task không quá phức tạp), việc thêm ví dụ mới gần như không đổi được gì, đôi khi còn làm giảm chất lượng do "loãng" tín hiệu quan trọng trong context.

Hãy hình dung một bảng đo thực nghiệm (dạng bạn nên tự chạy trên tập test của mình):

Số ví dụ Accuracy Token ví dụ Gain accuracy so với bước trước Chi phí thêm/1K request
0 (zero-shot) 78% 0 $0
1 85% 115 +7% ~$0,35
2 89% 230 +4% ~$0,35
3 91% 345 +2% ~$0,35
5 92% 575 +1% (cho 2 ví dụ thêm) ~$0,69
10 92,3% 1.150 +0,3% (cho 5 ví dụ thêm) ~$1,73

Nhìn bảng này, quyết định rõ ràng: dừng ở 3 ví dụ (91%) là điểm hợp lý nhất — thêm từ 3 lên 10 ví dụ chỉ mang lại +1,3% accuracy nhưng tốn thêm gấp hơn 3 lần token ví dụ. Ví dụ thứ 6, thứ 10 gần như là "chi phí chìm" (sunk cost) không tương xứng với giá trị.

Cách xác định điểm dừng cho task của riêng bạn:

  1. Chuẩn bị tập test riêng biệt (không trùng với ví dụ dùng làm few-shot) — tối thiểu 50-100 case, gán nhãn đúng (ground truth) sẵn.
  2. Chạy benchmark tăng dần: 0, 1, 2, 3, 5, 8 ví dụ — đo accuracy (hoặc metric phù hợp với task: F1, exact match, human eval score...) ở mỗi mức.
  3. Vẽ đường cong mức tăng biên (marginal gain): tính (accuracy[n] - accuracy[n-1]) / (token thêm vào). Khi tỷ lệ này giảm xuống dưới một ngưỡng bạn tự đặt (ví dụ dưới 0,01% accuracy trên mỗi 100 token), đó là điểm dừng.
  4. Chọn số ví dụ tại điểm khuỷu tay (elbow point) của đường cong — không phải điểm accuracy cao nhất tuyệt đối, mà điểm mà thêm ví dụ không còn đáng "đồng tiền bát gạo".

Một lưu ý quan trọng: điểm dừng này phụ thuộc vào task. Task đơn giản, ít nhập nhằng (phân loại 3-4 category rõ ràng) thường bão hòa ở 2-3 ví dụ. Task phức tạp, nhiều edge case, hoặc cần few-shot để dạy reasoning pattern nhiều bước có thể cần 5-8 ví dụ mới bão hòa. Đừng áp dụng một con số "magic number" cho mọi task — luôn đo trên chính use case của bạn.

Mẹo: Đừng chỉ nhìn accuracy tổng — hãy xem ví dụ thứ N mới thêm có sửa được loại lỗi nào mà ví dụ cũ chưa cover không. Nếu ví dụ mới chỉ là biến thể gần giống ví dụ đã có (near-duplicate), nó không đóng góp thông tin mới — loại bỏ ngay, bất kể accuracy đo được có nhích lên chút do nhiễu thống kê.

Crafting High-Efficiency Examples

Không phải tất cả ví dụ few-shot có "mật độ thông tin" (information density) bằng nhau. Hai ví dụ cùng độ dài token có thể mang lại lợi ích rất khác nhau nếu một ví dụ được viết cẩn thận, còn ví dụ khác chứa nhiều boilerplate dư thừa. Mục tiêu ở đây là tối đa hóa "tín hiệu học được" trên mỗi token bỏ ra.

Các nguyên tắc cụ thể để viết ví dụ hiệu quả cao:

1. Cắt bỏ boilerplate không cần thiết. Nhiều người viết ví dụ theo dạng câu chuyện đầy đủ ("Xin chào, tôi tên là...") trong khi model chỉ cần phần nội dung cốt lõi. So sánh:

  • Kém hiệu quả (48 token): "Input: Hi there, I hope you're doing well. I'm writing because I noticed my invoice for last month seems to have an extra charge of $15 that I don't recognize, could you help me understand what this is for?"
  • Hiệu quả (18 token): "Input: Invoice has unrecognized $15 charge, need explanation."

Nếu task thực tế của bạn nhận input đầy đủ dạng câu (email thật), bạn phải giữ ví dụ input gần với thực tế input production — nhưng phần output/label thì luôn nên cắt ngắn tối đa. Đừng để model "học" cách viết văn hoa trong output khi task chỉ cần category hoặc JSON ngắn.

2. Chọn ví dụ cover edge case, không lặp lại case dễ. Một bộ 5 ví dụ đều là case "rõ ràng, dễ phân loại" không dạy được gì nhiều — model đã tự xử lý tốt case dễ ở zero-shot rồi. Giá trị thực của few-shot nằm ở việc minh họa case mơ hồ, biên giới (boundary case). Ví dụ với task phân loại ticket:

  • Ví dụ tốt: một ticket vừa có yếu tố billing vừa có yếu tố bug (khách phàn nàn bị charge sai do một lỗi hệ thống) → minh họa cách ưu tiên category nào khi có tranh chấp.
  • Ví dụ lãng phí: một ticket "Tôi muốn hủy subscription" → quá rõ ràng là billing, zero-shot đã xử lý đúng, không cần minh họa thêm.

3. Loại bỏ ví dụ gần trùng lặp (near-duplicate). Nếu 2 ví dụ trong bộ của bạn khác nhau chỉ ở tên riêng hoặc số liệu nhưng cấu trúc/pattern giống nhau, một trong hai là dư thừa. Hãy audit bộ ví dụ hiện có bằng cách tự hỏi: "Nếu xóa ví dụ này, model còn học được pattern nào bị mất không?" — nếu câu trả lời là "không", xóa.

4. Đưa reasoning ngắn vào output khi cần dạy judgment, không cần khi chỉ dạy format. Nếu mục tiêu là dạy model cách suy luận để ra quyết định (ví dụ: đánh giá mức độ ưu tiên ticket), thêm một câu giải thích ngắn trong output ví dụ giúp model "nắm được logic" chứ không chỉ copy pattern bề mặt:

Input: "URGENT: production database is down, losing customers every minute"
Reasoning: mentions production outage + active business impact + urgency keyword
Priority: P0

So với chỉ:

Input: "URGENT: production database is down, losing customers every minute"
Priority: P0

Câu reasoning tốn thêm ~15 token nhưng thường cải thiện khả năng tổng quát hóa sang case tương tự chưa gặp — trong khi nếu mục tiêu chỉ là format tuân thủ (structural), phần reasoning này là dư thừa, nên bỏ.

5. Chuẩn hóa cấu trúc ví dụ để giảm token "khung". Dùng delimiter ngắn, nhất quán (Input:/Output: hoặc dấu ###) thay vì câu văn dẫn dắt dài dòng như "Đây là một ví dụ để bạn tham khảo...". Token khung nhân với số ví dụ — càng nhiều ví dụ, càng đáng tối ưu phần này.

Mẹo: Sau khi viết bộ ví dụ, thử bài test "xóa từng ví dụ một, đo lại accuracy". Ví dụ nào khi xóa không làm giảm accuracy đáng kể chính là ví dụ đang tốn token mà không sinh giá trị — loại bỏ khỏi bộ chính thức.

Dynamic Few-Shot Selection: Paying Only When It Helps

Cách tiếp cận few-shot phổ biến nhất — và lãng phí nhất — là nhồi cứng (hardcode) một bộ ví dụ cố định vào system prompt, dùng cho mọi request bất kể input là gì. Vấn đề: một input dễ, rõ ràng không cần ví dụ nào cả (zero-shot đủ tốt), nhưng vẫn phải trả tiền cho toàn bộ ví dụ tĩnh đó. Ngược lại, một input khó, hiếm gặp có khi cần ví dụ mà bộ tĩnh của bạn không hề cover.

Giải pháp: dynamic few-shot selection — xây một "ngân hàng ví dụ" (example bank) lớn, rồi với mỗi request, chỉ retrieve (truy xuất) những ví dụ liên quan nhất dựa trên độ tương đồng ngữ nghĩa (semantic similarity), thường tính qua embedding. Nếu không có ví dụ nào đủ liên quan (dưới ngưỡng similarity), fallback về zero-shot — không tốn token ví dụ nào cả.

Kiến trúc hoạt động gồm 3 bước:

  1. Xây example bank: một tập ví dụ đa dạng, đã curate kỹ (theo nguyên tắc ở phần trước — không near-duplicate, cover đủ edge case), mỗi ví dụ được embed sẵn (offline, một lần) và lưu vào vector store.
  2. Tại runtime: embed input của request hiện tại, tính similarity với toàn bộ example bank, lấy top-K ví dụ có similarity cao nhất.
  3. Áp ngưỡng (threshold): nếu similarity cao nhất trong top-K vẫn dưới ngưỡng đã định, tức là không có ví dụ nào thực sự liên quan — chuyển sang zero-shot thay vì nhồi ví dụ không liên quan (ví dụ không liên quan có thể gây nhiễu, làm giảm chất lượng chứ không chỉ lãng phí token).

Pseudocode minh họa cụ thể (Python):

import numpy as np

SIMILARITY_THRESHOLD = 0.75  # tune this on your own validation set
MAX_EXAMPLES = 3

def embed(text: str) -> np.ndarray:
    # calls your embedding model, e.g. text-embedding-3-small
    ...

def cosine_similarity(a: np.ndarray, b: np.ndarray) -> float:
    return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))

class ExampleBank:
    def __init__(self, examples: list[dict]):
        # each example: {"input": str, "output": str, "embedding": np.ndarray}
        self.examples = examples

    def select(self, query: str, k: int = MAX_EXAMPLES) -> list[dict]:
        query_emb = embed(query)
        scored = [
            (cosine_similarity(query_emb, ex["embedding"]), ex)
            for ex in self.examples
        ]
        scored.sort(key=lambda pair: pair[0], reverse=True)

        top_k = scored[:k]

        # threshold-based fallback: if the BEST match isn't relevant enough,
        # no example is worth including — use zero-shot for this request.
        if not top_k or top_k[0][0] < SIMILARITY_THRESHOLD:
            return []  # signals caller to use zero-shot prompt

        # only keep examples that individually clear the bar,
        # not just because they're in the top-k
        return [ex for score, ex in top_k if score >= SIMILARITY_THRESHOLD]


def build_prompt(query: str, bank: ExampleBank) -> str:
    selected = bank.select(query)

    if not selected:
        # zero-shot path — no example tokens spent at all
        return f"""You are a support ticket classifier.
Classify the ticket into: billing, bug_report, feature_request, or spam.
Output only the category name.

Ticket: "{query}"
Category:"""

    # few-shot path — only pay for examples that are actually relevant
    examples_block = "\n\n".join(
        f'Input: "{ex["input"]}"\nOutput: {ex["output"]}'
        for ex in selected
    )
    return f"""You are a support ticket classifier.
Classify the ticket into: billing, bug_report, feature_request, or spam.

Examples:
{examples_block}

Ticket: "{query}"
Category:"""

Điểm mấu chốt trong đoạn code trên là logic if not top_k or top_k[0][0] < SIMILARITY_THRESHOLD: return [] — đây chính là cơ chế "chỉ trả tiền khi ví dụ thực sự giúp được gì". Với input dễ, phổ biến, similarity với ví dụ trong bank thường thấp (vì ví dụ trong bank thường là case khó, đặc thù được chọn lọc kỹ) hoặc không cần thiết — hệ thống tự động rơi về zero-shot, tiết kiệm toàn bộ token ví dụ cho request đó.

Hiệu quả thực tế: nếu 70% request của bạn là case "dễ" (rơi vào zero-shot) và chỉ 30% là case khó cần few-shot (trung bình 2 ví dụ, ~230 token), thì so với static few-shot 3 ví dụ (345 token) cho mọi request:

  • Static: 100% × 345 token = 345 token/request trung bình
  • Dynamic: 70% × 0 + 30% × 230 = 69 token/request trung bình

→ Giảm khoảng 80% token ví dụ trung bình trên toàn hệ thống, mà vẫn giữ nguyên (hoặc cải thiện) chất lượng cho case khó — vì ví dụ được chọn theo độ liên quan thay vì cố định.

Chi phí đánh đổi cần lưu ý: dynamic selection thêm một bước gọi embedding model cho mỗi request (thường rất rẻ, ví dụ text-embedding-3-small chỉ vài phần triệu đô cho mỗi 1K token) và cần latency cho vector search — với embedding cache và vector store nhỏ (vài trăm đến vài nghìn ví dụ), latency này thường dưới vài chục milliseconds, không đáng kể so với latency gọi LLM.

Mẹo: Tune SIMILARITY_THRESHOLD bằng cách chạy A/B trên tập validation: quét ngưỡng từ 0.6 đến 0.9, đo accuracy và token trung bình ở mỗi mức, chọn điểm mà accuracy không giảm so với static few-shot nhưng token trung bình giảm rõ rệt. Đừng đặt ngưỡng "cảm tính" — số liệu cụ thể trên chính distribution input của bạn mới đáng tin.

Few-Shot for Format Adherence vs. Semantic Learning

Câu hỏi quan trọng nhất bị bỏ qua khi quyết định dùng few-shot: bạn đang dùng ví dụ để dạy điều gì? Có hai mục đích hoàn toàn khác nhau, và chỉ một trong hai thực sự "đáng" chi phí token của few-shot.

Mục đích 1 — Format adherence (tuân thủ định dạng). Đây là khi bạn dùng ví dụ chỉ để chỉ cho model biết output nên có cấu trúc gì: JSON với field nào, thứ tự nào, độ dài nào, có dùng markdown hay không... Đây là loại "kiến thức" có thể thay thế hoàn toàn bằng cách khác rẻ hơn: JSON schema, function calling / structured output mode, hoặc template rõ ràng trong instruction. Ví dụ, nếu bạn dùng few-shot chỉ để dạy model trả về:

{"category": "billing", "confidence": 0.92, "reason": "..."}

...thì đây hoàn toàn có thể thay bằng structured output (buộc output tuân theo schema định trước) — nhiều LLM API hiện hỗ trợ ép output tuân theo JSON schema định trước, loại bỏ nhu cầu ví dụ hoàn toàn, với chi phí token gần bằng 0 (chỉ cần định nghĩa schema một lần, không lặp lại nội dung ví dụ mỗi request).

Mục đích 2 — Semantic learning (học nhận định/ngữ nghĩa). Đây là khi ví dụ dạy model một judgment call khó diễn đạt hết bằng luật lệ: mức độ nghiêm trọng của một bug report dựa trên tone và ngữ cảnh, việc phân biệt sarcasm (mỉa mai) với phản hồi tích cực thật, đánh giá độ rủi ro của một đoạn code dựa trên pattern tinh vi... Loại kiến thức này khó thay thế bằng schema vì nó không phải là vấn đề cấu trúc mà là vấn đề "cảm nhận" ngữ nghĩa — và đây là nơi few-shot thực sự đáng đồng tiền bát gạo, vì ví dụ minh họa là cách duy nhất (hoặc cách rẻ nhất) để truyền tải nhận định đó vào context.

Cách phân biệt hai trường hợp trong thực tế — hãy tự hỏi: "Nếu tôi viết ra một bộ luật (rule) rõ ràng, không mơ hồ, liệu model có làm đúng mà không cần ví dụ không?"

  • Nếu câu trả lời là → đây là format adherence, đừng dùng few-shot, dùng schema/template.
  • Nếu câu trả lời là không, vì luật lệ sẽ dài vô hạn hoặc vẫn mơ hồ → đây là semantic learning, few-shot đáng chi phí.

Bảng đối chiếu cụ thể:

Tình huống Loại Giải pháp rẻ hơn few-shot?
Output phải là JSON với field cố định Format Có — JSON schema / structured output
Output phải bắt đầu bằng emoji cảm xúc tương ứng Format Có — instruction + có thể 1 ví dụ duy nhất để chốt style
Phân loại mức độ ưu tiên dựa trên "cảm giác cấp bách" trong văn phong Semantic Khó — cần vài ví dụ minh họa cấp độ khác nhau
Phát hiện code review comment nào là "blocking" vs "nice-to-have" Semantic Khó — ranh giới mơ hồ, phụ thuộc ngữ cảnh dự án
Viết tóm tắt theo đúng số ký tự tối đa Format Có — instruction rõ ràng + validation ở tầng code
Đánh giá tín hiệu churn risk từ tone email khách hàng Semantic Khó — cần ví dụ để calibrate "mức độ" nhận định

Một hệ quả thực tế quan trọng: rất nhiều team dùng few-shot cho cả hai mục đích trộn lẫn trong cùng một bộ ví dụ, khiến việc audit và tối ưu trở nên khó khăn. Hãy tách riêng: dùng schema/template cho phần format, chỉ giữ few-shot (và áp dụng dynamic selection ở phần trước) cho phần semantic thực sự cần nhận định. Kết quả thường là giảm được 40-60% số ví dụ cần thiết, vì một nửa trong số đó vốn chỉ đang làm công việc mà schema làm tốt hơn và rẻ hơn.

Mẹo: Với mỗi ví dụ trong bộ few-shot hiện có, gắn nhãn nội bộ "format" hoặc "semantic". Với mọi ví dụ gắn nhãn "format", thử thay bằng structured output/schema và đo lại — nếu chất lượng không đổi, xóa ví dụ đó khỏi prompt vĩnh viễn.