- Prompt evaluation = đo chất lượng prompt bằng dataset + grader thay vì cảm tính; vòng lặp 5 bước draft → dataset → run → score → cải tiến.
- Graders: code grader cho tiêu chí cứng, model grader cho tiêu chí mềm — thay score gán tay bằng grader thật.
- 4 kỹ thuật prompt: being clear & direct, being specific, XML tags, multi-shot examples — dùng điểm eval làm thước đo cải tiến.
TL;DR — Viết prompt xong phải đo: dựng evaluation pipeline (test dataset → run → grader → score) rồi cải tiến prompt bằng 4 kỹ thuật chuẩn Anthropic, lấy điểm eval làm thước thay cảm tính.
Phần 2/7 của ghi chú khoá Building with the Claude API — đề thi thử 589 câu (chấm điểm + giải thích) nằm ở tab "Đề thi thử" trên trang tổng quan.
Prompt engineering vs prompt evaluation — 3 ngả sau khi viết prompt
TL;DR mini. Viết được một prompt mới mới chỉ là điểm bắt đầu. Có hai khái niệm bổ trợ nhau: prompt engineering = bộ kỹ thuật viết prompt tốt hơn (multishot, XML tags…); prompt evaluation = đo prompt chạy tốt tới đâu bằng test tự động. Sau khi draft một prompt, có 3 ngả: (1) test 1 lần rồi cho qua, (2) test vài lần + vá dăm ca lẻ, (3) chạy qua evaluation pipeline chấm điểm rồi lặp cải tiến. Chỉ ngả 3 cho độ tin cậy thật ở production.
Để xây ứng dụng AI đáng tin, cần hiểu hai khái niệm — chúng giải hai bài toán khác nhau, không thay thế nhau:
| Prompt engineering | Prompt evaluation | |
|---|---|---|
| Trả lời câu hỏi | Viết prompt thế nào cho tốt? | Prompt đang chạy tốt tới đâu? |
| Bản chất | Bộ best-practice để Claude hiểu đúng ý + trả lời đúng dạng | Đo hiệu quả bằng automated testing |
| Ví dụ | Multishot prompting · structuring với XML tags · và nhiều kỹ thuật khác | Test với expected answer · so sánh nhiều version của cùng prompt · soi output tìm lỗi |
3 ngả sau khi draft một prompt
Viết xong một prompt, hầu như ai cũng đứng trước 3 lựa chọn:
| Ngả | Làm gì | Cái giá |
|---|---|---|
| 1 | Test một lần, thấy ổn là cho qua | Rủi ro cao — vỡ ở production khi user nhập thứ bạn không lường. |
| 2 | Test vài lần + tweak để chặn một hai ca lẻ | Khá hơn ngả 1, nhưng user thực tế vẫn cho ra vô số input bạn chưa nghĩ tới. |
| 3 | Chạy prompt qua evaluation pipeline để chấm điểm, rồi lặp cải tiến theo chỉ số khách quan | Tốn công + tốn tiền hơn, đổi lại tự tin hơn hẳn về độ tin cậy. |
Vì sao kỹ sư hay sa vào bẫy ngả 1 & 2
Ngả 1 và 2 là cái bẫy chung — kỹ sư nào cũng từng dính (tác giả khoá tự nhận luôn). Rất tự nhiên khi ta viết một prompt cho ứng dụng nghiêm túc rồi test không đủ kỹ, vì ta luôn đánh giá thấp số lượng edge case mà user thật sẽ tạo ra.
Sự thật phũ: khi prompt lên production, user sẽ tương tác theo những cách bạn chưa từng tưởng tượng. Một prompt trông "chắc cú" trong vài lần test có thể sụp rất nhanh trước đủ loại input đời thực.
Vì sao nên đi ngả 3 (evaluation-first)
Cho prompt chạy qua evaluation pipeline cho bạn số liệu khách quan trên một dải test case rộng hơn nhiều. Cách tiếp cận data-driven này giúp:
- Phát hiện điểm yếu trước khi nó thành sự cố production.
- So sánh các version prompt một cách khách quan (không cãi nhau bằng cảm tính).
- Lặp cải tiến với sự tự tin, dựa trên cải thiện đo được.
- Xây ứng dụng AI đáng tin và bền hơn.
Đổi lại là đầu tư trước vào thời gian + hạ tầng test — nhưng nó trả cổ tức bằng độ tin cậy của sản phẩm cuối. Mục tiêu: bắt lỗi lúc đang phát triển, đừng để user bắt hộ.
Góc Delivery Manager. "Test một lần thấy ổn" chính là rủi ro đội lốt sự xong việc — thứ tôi phải gỡ nhiều nhất khi review. Đặt ngược lại theo ngôn ngữ delivery: ngả 1–2 đẩy chi phí lỗi sang sau khi release (đắt nhất, lộ trước mặt khách); ngả 3 kéo chi phí đó về lúc dev (rẻ nhất). Với team mình, "prompt eval" được đối xử đúng như một test suite: nằm trong repo, chạy trong CI, là cổng trước khi đổi prompt lên prod — không phải việc làm thêm cho vui. Nó cũng là chỗ ăn khớp với hai núm phía trước: eval chỉ đáng tin khi output không nhảy lung tung (→
temperaturethấp cho task cần kiểm chứng) và khi prompt/systemđược version-control để A/B test. Lưu ý chi phí có thật: pipeline tốn tiền API → cân coverage ↔ ngân sách, đừng eval mù toàn bộ mà ưu tiên các đường người dùng + ca rủi ro cao.
Evaluation workflow — 5 bước (vòng lặp đo & cải tiến)
TL;DR mini. Ngả 3 ở trên ("evaluation pipeline") khi mổ ra gồm 5 bước lặp đi lặp lại: Draft a prompt → Create an eval dataset → Feed through Claude → Feed through a grader → Change prompt & repeat. Mục tiêu: thay câu "tôi thấy prompt ổn" bằng "tôi đo được prompt ổn N điểm" → so sánh version bằng số, không bằng cảm tính.
| # | Bước | Chuyện gì xảy ra |
|---|---|---|
| 1 | Draft a Prompt | Viết prompt khởi đầu làm baseline. Ví dụ tối giản: "Please answer the user's question: {question}". |
| 2 | Create an Eval Dataset | Tập sample input đại diện cho dữ liệu production, sẽ được nội suy vào prompt template. Vài ca → hàng nghìn ca. Tạo tay hoặc nhờ Claude sinh (xem mục dưới). |
| 3 | Feed Through Claude | Ghép từng input với template → gửi cho Claude → thu response cho từng ca. |
| 4 | Feed Through a Grader | Grader chấm chất lượng response (nhìn cả câu hỏi lẫn câu trả lời), cho điểm khách quan — thường thang 1–10 (10 = perfect). Lấy average trên cả dataset. |
| 5 | Change Prompt & Repeat | Sửa prompt → chạy lại toàn bộ → so điểm mới vs baseline. Cao hơn ⇒ cải thiện thật. |
Ví dụ chấm điểm: 3 ca được grader cho 10, 4, 9 → average (10+4+9)/3 = 7.66 (baseline). Thêm chỉ thị "Answer with ample detail" vào prompt → chạy lại → average lên 8.7. Con số tăng = bằng chứng câu sửa là cải tiến, không phải "chỉ khác đi".
Lợi ích lõi (prompt scoring): so version bằng số, chọn version điểm cao nhất, lặp để tìm cách tốt hơn — removes guesswork khỏi prompt engineering, cho anh tự tin rằng thay đổi là cải thiện chứ không phải biến thể khác.
Generating test datasets — để Claude tự sinh dữ liệu test
TL;DR mini. Phóng to Bước 2 ở trên. Thay vì gõ tay từng ca, nhờ chính Claude sinh eval dataset bằng một meta-prompt. Kỹ thuật parse không có gì mới — tái dùng đúng combo prefilling + stop_sequences ở phần structured data. Dùng model rẻ/nhanh (Haiku) vì sinh data không cần model mạnh nhất.
Bối cảnh ví dụ khoá: một prompt giúp user viết output cho tác vụ AWS, ra 3 dạng: Python · JSON · Regex — yêu cầu output sạch, không lời giải thích/header/footer. Prompt v1 tối giản: "Please provide a solution to the following task: {task}".
Cấu trúc dataset: một array các JSON object, mỗi object có property "task" (mô tả việc cần làm — chính là input nội suy vào prompt).
[
{ "task": "Description of task" },
...additional
]
Hàm sinh dataset — viết một meta-prompt bảo Claude sinh ra mảng task, rồi parse:
def generate_dataset():
prompt = """
Generate an evaluation dataset ... tasks that require Python, JSON, or a Regex ...
* Focus on tasks solvable by a single Python function, a single JSON object, or a single regex
* Focus on tasks that do not require writing much code
Please generate 3 objects.
"""
messages = []
add_user_message(messages, prompt)
add_assistant_message(messages, "```json") # PREFILL: mồi mở code block
text = chat(messages, stop_sequences=["```"]) # STOP: gặp ``` là dừng
return json.loads(text) # parse mảng JSON sạch
Lưu lại để load khi eval:
with open('dataset.json', 'w') as f:
json.dump(dataset, f, indent=2) # ghi RA file (khác json.loads = nạp VÀO)
⚠️ Mấy chỗ dễ nhầm. (1) Sinh data → temperature CAO (đa dạng ca test, helper default
1.0); còn task cần kiểm chứng + grader → temperature THẤP (ổn định, lặp lại được) — cùng pipeline, 2 chỗ chỉnh núm ngược nhau. (2) Dùng Haiku ở bước sinh data vì rẻ/nhanh, không cần model mạnh nhất. (3) Dataset là array of objects mỗi object có key"task"— không phải mảng string trần. (4)json.dump= đổ ra file ·json.load(s)= nạp vào — đừng lẫn. (5) Ràng buộc "single function / single JSON / single regex, not much code" để mỗi ca test nhỏ-gọn-dễ chấm.
Góc Delivery Manager. Để LLM tự sinh test data là đòn scale dataset gần như miễn phí — nhưng nó là con dao hai lưỡi: data Claude sinh ra mang sẵn bias của chính model (nó nghĩ ra những ca nó vốn giỏi), nên dễ cho điểm eval đẹp giả. Với team mình, data tự sinh là để khởi động nhanh (seed), sau đó bổ sung ca tay từ lỗi production thật + ca biên hiểm — chỗ user thật làm vỡ prompt. Và luôn nhớ mắt xích chốt: grader (nhất là LLM-as-judge) phải được calibrate với người chấm trước khi tin cho production, nếu không cả cái thước đã cong.
Running the eval — bộ khung pipeline (3 hàm)
TL;DR mini. Phóng to Bước 3 (Feed through Claude). Có dataset rồi thì dựng pipeline lõi = 3 hàm lồng nhau:
run_prompt(chạy 1 prompt) →run_test_case(chạy + chấm 1 ca) →run_eval(lặp cả dataset). Grader chưa làm — tạm hardcodescore = 10để test khung chạy thông trước. "Dựng xong cái này là anh đã làm phần lớn việc của một eval pipeline."
| Hàm | Trách nhiệm |
|---|---|
run_prompt(test_case) |
Ghép test_case["task"] vào prompt template → chat(messages) → trả output thô. Prompt còn rất đơn giản (chưa có format instruction) nên output verbose. |
run_test_case(test_case) |
Gọi run_prompt → chấm (giờ score = 10 hardcode, grading = # TODO) → trả dict {output, test_case, score}. |
run_eval(dataset) |
Lặp từng case → gọi run_test_case → gom vào list results. |
def run_prompt(test_case):
"""Ghép prompt + input của test case, trả output"""
prompt = f"""
Please solve the following task:
{test_case["task"]}
"""
messages = []
add_user_message(messages, prompt)
return chat(messages)
def run_test_case(test_case):
"""Gọi run_prompt rồi chấm"""
output = run_prompt(test_case)
score = 10 # TODO — grader thật ở bài sau
return {"output": output, "test_case": test_case, "score": score}
def run_eval(dataset):
"""Chạy từng case trong dataset, gom results"""
results = []
for test_case in dataset:
results.append(run_test_case(test_case))
return results
Chạy & soi kết quả:
with open("dataset.json", "r") as f:
dataset = json.load(f) # đọc TỪ FILE (khác json.loads = parse string)
results = run_eval(dataset)
print(json.dumps(results, indent=2)) # đổi object THÀNH STRING để in
Mỗi result giữ 3 thứ: output (response đầy đủ của Claude), test_case (đề gốc — để grader & truy vết), score (điểm, giờ là placeholder).
⚠️ Mấy chỗ dễ nhầm. (1) Họ hàng
json:load(f)đọc từ file ·loads(s)parse từ string ·dump(obj,f)ghi ra file ·dumps(obj)đổi thành string. Mẹo: cós= string, khôngs= file. (2)score = 10là scaffold để test khung trước khi có grader — không phải logic chấm. (3) Vòng lặp tuần tự → ~30s kể cả Haiku → tối ưu bằng concurrency ở bài sau. (4) Output verbose là do prompt thiếu format instruction (Bước 5 iterate sẽ vá), không phải bug. (5) Result giữ cảtest_case, không chỉ điểm.
Góc Delivery Manager. Bài này là minh hoạ sạch của nguyên tắc "skeleton trước, grader sau" — dựng đường ống chạy thông end-to-end với điểm giả, rồi mới lắp bộ phận khó. Lợi ích delivery: anh tách rủi ro ra hai pha — khung pipeline (dễ, làm trước) và grading logic (khó, đáng đầu tư). Cái
# TODOở đây là nợ kỹ thuật cố ý và hữu hình — khác hẳn nợ ẩn: nó nằm chình ình trong code, không ai quên. Cònscore = 10cho mọi ca là lời nhắc đừng tin pipeline xanh vội: pipeline "chạy được" không nghĩa là nó "đo đúng" — value thật nằm ở grader, đúng chỗ phức tạp nhất.
Graders — thay score = 10 bằng grader thật (model + code)
TL;DR mini. Bộ phận khó nhất của pipeline = grader: nhận output, trả tín hiệu đo được 1–10. Có 3 loại (code · model · human). Với prompt sinh code, ta ghép 2 grader: code grader lo Format + Valid Syntax, model grader lo Task Following. Điểm cuối = trung bình hai cái.
3 loại grader
| Loại | Cách chấm | Giỏi đánh giá |
|---|---|---|
| Code grader | code tự viết (programmatic) | length · có/không chứa từ · syntax validation (JSON/Python/regex) · readability |
| Model grader | gọi một AI khác chấm | response quality · instruction following · completeness · helpfulness · safety |
| Human grader | người chấm tay | quality · comprehensiveness · depth · conciseness · relevance — linh hoạt nhất nhưng chậm/cực |
Định nghĩa criteria TRƯỚC — và map đúng grader
Với prompt sinh code, 3 tiêu chí, mỗi cái hợp một loại grader:
| Criteria | Mô tả | Grader hợp |
|---|---|---|
| Format | chỉ trả Python/JSON/Regex, không lời giải thích | code |
| Valid Syntax | code parse được đúng ngôn ngữ | code |
| Task Following | giải đúng việc được giao, code chính xác | model (cần linh hoạt) |
Model grader — grade_by_model
def grade_by_model(test_case, output):
eval_prompt = """
You are an expert code reviewer. Evaluate this AI-generated solution.
Task: {task}
Solution: {solution}
Provide your evaluation as a structured JSON object with:
- "strengths": An array of 1-3 key strengths
- "weaknesses": An array of 1-3 key areas for improvement
- "reasoning": A concise explanation of your assessment
- "score": A number between 1-10
"""
messages = []
add_user_message(messages, eval_prompt)
add_assistant_message(messages, "```json") # tái dùng prefill + stop
eval_text = chat(messages, stop_sequences=["```"])
return json.loads(eval_text)
⭐ Insight quan trọng nhất. Bắt model nêu
strengths·weaknesses·reasoningcùng vớiscore. Thiếu phần lý luận này, model dồn về điểm lưng chừng ~6 (chấm lười). Bắt nó lý luận trước = một dạng chain-of-thought → điểm sát thực. (Đúng nguyên lýreasoning-rồi-mới-scoretrongJUDGE_SCHEMAở bài thực hành 9.)
Code grader — validate syntax (10 / 0)
def validate_json(text):
try:
json.loads(text.strip()); return 10
except json.JSONDecodeError:
return 0
def validate_python(text):
try:
ast.parse(text.strip()); return 10 # import ast
except SyntaxError:
return 0
def validate_regex(text):
try:
re.compile(text.strip()); return 10 # import re
except re.error:
return 0
Mỗi hàm parse được → 10, lỗi → 0 (nhị phân, không trải đều). Để biết gọi validator nào, dataset thêm field "format":
{ "task": "Create a Python function to validate an AWS IAM username", "format": "python" }
(Cập nhật meta-prompt sinh dataset để tự thêm field này.) Đồng thời làm prompt rõ hơn để output sạch: "Respond only with Python, JSON, or a plain Regex" + "Do not add any comments or commentary or explanation"; có thể prefill generic ```code để Claude tự chọn loại.
Trộn điểm & lấy average
model_grade = grade_by_model(test_case, output)
model_score = model_grade["score"]
syntax_score = grade_syntax(output, test_case)
score = (model_score + syntax_score) / 2 # đều trọng số — chỉnh được theo use case
from statistics import mean
def run_eval(dataset):
results = [run_test_case(tc) for tc in dataset]
average_score = mean([r["score"] for r in results])
print(f"Average score: {average_score}")
return results
⚠️ Mấy chỗ dễ nhầm. (1) Format + Valid Syntax → code grader; Task Following → model grader — cặp map kinh điển. (2) Code grader trả 10/0 nhị phân, model grader mới cho 1–10 mượt. (3) 3 cặp hàm–exception:
json.loads/json.JSONDecodeError·ast.parse/SyntaxError·re.compile/re.error. (4) Thiếu reasoning → điểm dồn về ~6. (5) Điểm tuyệt đối không = tốt/xấu; giá trị là cải thiện tương đối khi iterate prompt.
Góc Delivery Manager. Kiến trúc 2-grader này là một quyết định altitude đẹp: việc nào máy kiểm được rẻ và tất định (syntax, format) thì đừng phí tiền cho LLM — đẩy hết sang code grader; chỉ để model grader (đắt, đỏng đảnh) lo phần phán đoán nội dung mà code không làm nổi. Cộng điểm 50/50 chỉ là mặc định — ở production tôi sẽ chỉnh trọng số theo rủi ro: API trả JSON sai cú pháp = vỡ ngay (syntax nặng đô hơn), còn câu trả lời "hơi chưa tối ưu" thì nhẹ hơn. Và nhớ: model grader capricious → đây là lý do bài thực hành 9 nhấn calibrate với người chấm trước khi tin con số cho prod.
Prompt engineering — vòng lặp cải tiến (eval làm thước)
TL;DR mini. Hết phần đo (prompt evaluation), giờ sang phần cải tiến (prompt engineering): lấy prompt đã viết rồi nâng dần cho output đáng tin/chất lượng hơn theo vòng lặp 5 bước, với eval pipeline làm cái thước xác nhận mỗi lần sửa có thật sự tốt lên.
Vòng lặp 5 bước (iterative refinement):
- Set a goal — prompt cần đạt gì.
- Write an initial prompt — bản nháp đầu (thường cố tình ngây ngô để lấy baseline).
- Evaluate the prompt — chạy eval, chấm điểm.
- Apply a prompt engineering technique — áp một kỹ thuật cụ thể.
- Re-evaluate — xác nhận điểm thật sự tăng.
→ Lặp bước 4–5 đến khi hài lòng; mỗi vòng phải cho measurable improvement.
⚠️ Đừng lẫn 2 danh sách "5 bước". Eval workflow (module trước): Draft prompt → Create dataset → Feed through Claude → Feed through grader → Change & repeat. Prompt engineering loop (đây): Set a goal → Write initial prompt → Evaluate → Apply technique → Re-evaluate. Loop engineering bọc eval vào bên trong (bước 3 & 5): eval = đo, engineering = cải tiến + lặp.
PromptEvaluator — pipeline đóng gói thành class
Bản "nâng cấp" của pipeline module trước (file 001_prompting.ipynb), gói cả dataset generation + grading:
evaluator = PromptEvaluator(max_concurrent_tasks=5) # concurrency; start LOW (~3) tránh rate limit
dataset = evaluator.generate_dataset(
task_description="Write a compact, concise 1 day meal plan for a single athlete",
prompt_inputs_spec={ # khai báo INPUT SCHEMA
"height": "Athlete's height in cm",
"weight": "Athlete's weight in kg",
"goal": "Goal of the athlete",
"restrictions": "Dietary restrictions of the athlete",
},
output_file="dataset.json",
num_cases=3, # thấp (2–3) lúc dev → iterate nhanh
)
results = evaluator.run_evaluation(
run_prompt_function=run_prompt,
dataset_file="dataset.json",
extra_criteria=""" # bơm yêu cầu RIÊNG cho grader
The output should include:
- Daily caloric total
- Macronutrient breakdown
- Meals with exact foods, portions, and timing
""",
)
max_concurrent_tasks = núm song song (đây là phần "tối ưu concurrency" đã hứa ở bài Running the eval) — bắt đầu thấp (~3) tránh rate limit error, tăng dần nếu quota cho phép. num_cases để ít (2–3) lúc dev, tăng khi validate cuối.
Baseline naive prompt & đọc report
Bắt đầu bằng prompt cố tình đơn giản để lấy mốc đo:
def run_prompt(prompt_inputs):
prompt = f"""
What should this person eat?
- Height: {prompt_inputs["height"]}
- Weight: {prompt_inputs["weight"]}
- Goal: {prompt_inputs["goal"]}
- Dietary restrictions: {prompt_inputs["restrictions"]}
"""
messages = []
add_user_message(messages, prompt)
return chat(messages)
Kết quả: điểm số + HTML report chi tiết từng ca kèm reasoning (vì sao điểm đó). Baseline 2.3/10 là bình thường cho lần đầu — đừng nản; giá trị nằm ở xu hướng đi lên qua từng vòng, không phải điểm tuyệt đối. Report chỉ ra prompt fail ở đâu → dẫn đường cho vòng sửa kế.
⚠️ Mấy chỗ dễ nhầm. (1) Lặp bước 4–5, không phải toàn bộ. (2) Điểm thấp ban đầu = bình thường, không phải làm sai. (3)
max_concurrent_tasksđể thấp tránh rate limit (không phải chạy nhanh hết cỡ). (4)num_casesít lúc dev, nhiều lúc validate. (5) ⭐ one change at a time — đổi nhiều thứ cùng lúc thì không biết cái nào có công.
Góc Delivery Manager. "One change at a time" chính là controlled experiment đội lốt prompt engineering — y hệt nguyên tắc đừng nhồi 5 thay đổi vào một release rồi mù tịt khi vỡ. Với team mình, giá trị lớn nhất của vòng lặp này không phải điểm cao, mà là attribution: biết kỹ thuật nào tạo ra bao nhiêu điểm → tái dùng được cho prompt khác, bỏ được cái vô dụng. Baseline cố tình dở cũng là một kỷ luật: nó buộc mọi tuyên bố "prompt này tốt" phải chứng minh bằng delta điểm, không phải bằng cảm giác. Đây là lúc prompt engineering thôi là nghề thủ công và thành quy trình đo được.
Kỹ thuật 1 — Being clear and direct
TL;DR mini. Kỹ thuật cải tiến đầu tiên áp vào vòng lặp. Xoáy vào first line (dòng đầu prompt — phần quan trọng nhất) với 2 nguyên tắc: Clear (rõ — cái gì) + Direct (thẳng — cách cấu trúc). Áp vào ca meal plan: baseline 2.32 → 3.92 chỉ nhờ viết lại dòng mở đầu.
| Nguyên tắc | Nghĩa | Trục |
|---|---|---|
| Clear | ngôn ngữ đơn giản · không mơ hồ · nói thẳng muốn gì · mở đầu bằng câu nêu task | trả lời CÁI GÌ |
| Direct | dùng instructions, không phải questions · bắt đầu bằng action verb (Write · Create · Generate · Identify) · nêu rõ constraints | trả lời CÁCH cấu trúc |
Ví dụ tương phản:
| Yếu | Tốt |
|---|---|
| "I need to know about those things people put on their roofs that use sun…" (vòng vo) | "Write three paragraphs about how solar panels work." |
| "…geothermal energy sounds neat. What countries use it?" (câu hỏi, mơ hồ) | "Identify three countries that use geothermal energy. Include generation stats for each." |
| "What should this person eat?" → 2.32 | "Generate a one-day meal plan for an athlete that meets their dietary restrictions." → 3.92 |
Câu tốt nói thẳng 3 thứ: action (generate) · what (meal plan) · constraints (one day · athlete · dietary restrictions).
⚠️ Mấy chỗ dễ nhầm. (1) Clear ≠ Direct: Clear = ngôn ngữ/nội dung; Direct = cấu trúc (mệnh lệnh + động từ). (2) Mệnh lệnh, KHÔNG câu hỏi ("Identify…" thay vì "What…?"). (3) Mở đầu bằng action verb, không phải bối cảnh lan man. (4) First line quan trọng nhất, không phải đoạn cuối. (5) Mental model: Claude là trợ lý giỏi cần chỉ dẫn rõ, không phải kẻ phải đoán ý.
Góc Delivery Manager. Đây là lần áp kỹ thuật đầu tiên trong vòng lặp — baseline 2.32 → 3.92 nhờ một thay đổi ở dòng mở đầu: bằng chứng sống của "one change → đo → điểm lên thật". Bài học delivery rộng hơn: cách mình viết một prompt cho LLM không khác cách viết một ticket/spec cho người — mơ hồ đầu vào thì rác đầu ra, dù người nhận là Claude hay là dev. "Treat it like a capable assistant who needs clear direction" đúng cho cả hai. Và lưu ý kỹ thuật này rẻ nhất, hiệu quả cao nhất → luôn là nước đi đầu tiên trước khi nghĩ tới multishot/XML phức tạp.
Kỹ thuật 2 — Being specific
TL;DR mini. Đưa guidelines (tiêu chí) hoặc steps (các bước) thay vì để Claude tự đoán. Prompt mơ hồ → vô số hướng (dài/ngắn, ít/nhiều nhân vật). Có 2 loại thường dùng chung: Output Quality Guidelines + Process Steps. Áp vào ca meal plan: 3.92 → 7.86 (hơn gấp đôi).
| Loại | Là gì | Kiểm soát | Dùng khi |
|---|---|---|---|
| Output Quality Guidelines | liệt kê phẩm chất output phải có | length · structure/format · elements to include · tone/style | Gần như MỌI prompt (lưới an toàn) |
| Process Steps | các bước Claude phải làm trước khi trả lời | bắt suy nghĩ hệ thống, xét nhiều góc | Chỉ bài PHỨC TẠP |
Output Guidelines — ca meal plan (đẩy 3.92 → 7.86):
1. Calorie/ngày chính xác 4. Chỉ dùng món hợp restriction
2. Lượng protein / fat / carb 5. Khẩu phần theo gram
3. Giờ ăn từng bữa 6. Tiết kiệm nếu được nhắc
Process Steps — ví dụ phân tích vì sao doanh số tụt: dắt Claude qua market metrics → thay đổi ngành → hiệu suất cá nhân → thay đổi tổ chức → phản hồi khách — thay vì để nó dồn vào một nguyên nhân.
Khi nào dùng cái nào:
- Output guidelines → LUÔN LUÔN — gần như mọi prompt, lưới an toàn cho kết quả nhất quán.
- Process steps → CHỈ khi bài khó — troubleshooting · decision-making · critical thinking · cần xét nhiều góc.
- Professional = ghép cả hai — steps đảm bảo nghĩ kỹ, guidelines đảm bảo output đúng dạng.
⚠️ Mấy chỗ dễ nhầm. (1) Output guidelines = output trông thế nào; Process steps = Claude nghĩ thế nào. (2) Khi nào: Output = gần như mọi prompt; Steps = chỉ bài phức tạp (không phải mọi prompt). (3) Process steps hợp khi cần xét nhiều góc (doanh số tụt có nhiều nguyên nhân), không phải để làm cho dài. (4) Pro ghép cả hai, không chọn một. (5) 7.86 = hơn gấp đôi 3.92, cộng dồn lên clear & direct.
Góc Delivery Manager. Hai loại này ánh xạ thẳng vào ngôn ngữ delivery của mình: Output guidelines = Definition of Done (sản phẩm cuối phải đủ những gì), Process steps = quy trình/checklist điều tra (làm theo trình tự, xét đủ góc trước khi kết luận). Đó là lý do "always use output guidelines" — y như mọi ticket đều phải có DoD; còn process steps chỉ bung ra cho ca phức tạp, đúng như mình không viết runbook 10 bước cho việc vặt. Mạch điểm 2.32 → 3.92 → 7.86 cũng dạy một điều quản lý: cải tiến cộng dồn, mỗi nước đo riêng — đừng gộp để rồi không biết nước nào tạo giá trị.
Kỹ thuật 3 — Structure with XML tags
TL;DR mini. Bọc nội dung trong thẻ kiểu
<sales_records>…</sales_records>để tạo ranh giới rõ ràng (delimiters), giúp Claude phân biệt đâu là chỉ dẫn, đâu là dữ liệu — đặc biệt khi prompt nhồi nhiều nội dung hoặc trộn nhiều loại (code + docs + data). Tên thẻ tự đặt, càng mô tả càng tốt.
Vì sao cần: nhồi 20 trang sales records lẫn câu lệnh → Claude khó biết đâu là việc cần làm, đâu là data. Ví dụ đắt nhất là debug code kèm tài liệu: trộn chung thì không rõ đâu là code đâu là docs → tách bằng <my_code> và <docs> là rõ ngay.
Tên thẻ — descriptive > generic (KHÔNG cần thẻ XML "chính thống"):
| Nên | Thay vì |
|---|---|
<sales_records> |
<data> |
<athlete_information> |
<info> |
<my_code> · <docs> |
gộp chung |
Ví dụ thực tế:
<athlete_information>
- Height: 6'2"
- Weight: 180 lbs
- Goal: Build muscle
- Dietary restrictions: Vegetarian
</athlete_information>
Generate a meal plan based on the athlete information above.
→ Rõ ràng height/weight/goal/restrictions là một cụm dữ liệu khách cần xét cùng nhau.
When to use: dữ liệu/ngữ cảnh lớn · trộn nhiều loại nội dung (code · docs · data) · cần ranh giới thật rõ · prompt phức tạp interpolate nhiều biến.
⚠️ Mấy chỗ dễ nhầm. (1) KHÔNG cần thẻ XML chính thống — tự đặt tên. (2) Tên thẻ càng mô tả càng tốt (
<sales_records>><data>). (3) Mục đích = ranh giới / phân tách, nhất là khi trộn nhiều loại nội dung. (4) Cần cặp mở + đóng<x>…</x>. (5) Prompt đơn giản có thể KHÔNG cải thiện rõ — giá trị tăng theo độ phức tạp; bài này không có điểm eval mới (mạch vẫn 2.32 → 3.92 → 7.86).
Góc Delivery Manager. XML tags là kỹ thuật về scale, không phải về câu chữ: nó giải đúng bài toán "prompt production phình to" — khi mình nhồi context động (hồ sơ khách, log lỗi, tài liệu) vào prompt, ranh giới mờ là nguồn của output lệch khó tái hiện. Đặt tên thẻ mô tả còn là lớp self-documentation cho prompt: người sau đọc
<athlete_information>hiểu ngay khúc đó là gì — y như đặt tên biến tử tế trong code. Và nhớ tính chất "chỉ đáng khi phức tạp": đừng nhét XML vào mọi prompt 1 dòng cho ra vẻ; dùng đúng chỗ nó cứu (đa biến, đa loại nội dung).
Kỹ thuật 4 — Providing examples (one-shot / multi-shot)
TL;DR mini. Đưa Claude cặp input/output mẫu để nó học theo = one-shot / multi-shot prompting. Một trong các kỹ thuật mạnh nhất, vì nó "show rather than tell" — chỉ ra thay vì tả. Đặc biệt cứu các ca biên (sarcasm, format phức tạp, input mơ hồ).
Ví dụ — phân loại cảm xúc tweet: khó ở sarcasm. Tweet "Ồ tuyệt, đúng thứ tôi cần — chuyến bay trễ tối nay!" nhìn khen nhưng thực ra negative. Giải bằng cách đưa ví dụ ca khó:
<sample_input>Great game tonight!</sample_input>
<ideal_output>Positive</ideal_output>
<sample_input>Oh yeah, I really needed a flight delay tonight! Excellent!</sample_input>
<ideal_output>Negative</ideal_output>
- một câu context giải thích vì sao phải cẩn thận với sarcasm. (Để ý ví dụ bọc trong XML tags — dùng lại kỹ thuật 3.)
| Số ví dụ | Dùng khi | |
|---|---|---|
| One-shot | 1 | thiết lập một pattern |
| Multi-shot | nhiều | phủ nhiều ca biên / nhiều dạng output hợp lệ |
Khi nào dùng: corner cases/edge scenarios · output format phức tạp (JSON cụ thể) · cho thấy đúng style/tone · xử lý input mơ hồ.
⭐ Lấy ví dụ TỪ eval: chọn các output điểm cao nhất (10) trong eval → dùng làm ví dụ → Claude hiểu "output hoàn hảo cho task này trông thế nào". Đây là chỗ vòng eval quay lại nuôi prompt.
Thêm lý do vào ví dụ (không chỉ cặp input/output):
<ideal_output>
[output mẫu]
</ideal_output>
This example is well-structured, provides detailed information
on food choices and quantities, and aligns with the athlete's
goals and restrictions.
→ giúp Claude hiểu cái lý đằng sau output tốt, không chỉ format.
Best practices: luôn dùng XML tags để bọc ví dụ · nói rõ "Here is an example input with an ideal response" · ưu tiên ví dụ cho failure case hay gặp · giải thích vì sao output đó ideal · giữ ví dụ relevant với task.
⚠️ Mấy chỗ dễ nhầm. (1) One-shot = 1 ví dụ · Multi-shot = nhiều ví dụ (phủ nhiều edge case). (2) Bọc ví dụ trong XML tags — kỹ thuật 4 xài lại kỹ thuật 3. (3) Nguồn ví dụ tốt nhất = output điểm cao trong eval (điểm 10). (4) Thêm lý do (why ideal), không chỉ cặp pair — hay bị bỏ sót. (5) "Show rather than tell" là mô hình tư duy lõi.
Góc Delivery Manager. Đây là kỹ thuật khép vòng tròn hệ thống đẹp nhất module: eval không chỉ chấm prompt — nó đẻ ra nguyên liệu (các output điểm 10) để vá chính prompt đó qua multi-shot. Với team mình nghĩa là: mỗi lần production gặp ca khó (một reply sarcasm bị chấm sai), ca đó sau khi sửa đúng trở thành ví dụ vàng nạp ngược vào prompt → hệ tự khá lên theo thời gian. "Show, don't tell" cũng là chân lý quản lý: đưa một mẫu chuẩn nhanh và đúng hơn mười dòng mô tả — đúng cho cả dạy Claude lẫn onboard người mới. Lưu ý chi phí: mỗi ví dụ tốn token đầu vào mỗi request → chọn ví dụ đắt giá nhất (đúng failure case), đừng nhồi cho nhiều.
Phần tiếp theo: Tool use với Claude API — JSON Schema, multi-block messages, conversation loop
Nguồn: Building with the Claude API (Anthropic Academy) — Copyright Anthropic. Phần đề thi thử cho khoá này nằm ở tab "Đề thi thử" trên trang tổng quan khoá.