Trung cấpHướng dẫnClaude APINguồn: Anthropic

Tạo test data tự động với Claude — Synthetic Test Generation

Nghe bài viết
00:00

Điểm nổi bật

Nhấn để đến mục tương ứng

  1. 1 Bước đầu tiên bạn nên làm: Mới bắt đầu dự án, chưa có real-world data Cần test edge cases khó kiếm trong thực tế tiếng địa phương, lỗi chính tả cố. Áp dụng đúng cách sẽ thấy kết quả rõ rệt từ tuần đầu tiên.
  2. 2 Một điều ít người đề cập: Đầu tiên, ta phân tích prompt template để hiểu cần generate data gì: import anthropic import json import re client =. Hiểu rõ bối cảnh áp dụng sẽ quyết định 80% thành công khi triển khai.
  3. 3 Điểm nhấn quan trọng: Cần validate: def validateexampleexample: dict, originalprompt: str -> dict: """ Validate một synthetic example bằng. Đây là phần mang lại giá trị thực tiễn cao nhất trong toàn bài viết.
  4. 4 Thực hành được liền: Sau validation, ta có thể cải thiện dataset bằng cách phân tích failures: def analyzefailuresandregenerateneedsreview:. Quy trình từng bước trong phần này giúp bạn bắt đầu ngay mà không cần kinh nghiệm chuyên sâu.
  5. 5 Thành thật mà nói: TASKTEMPLATES = { "sentiment": { "description": "Phân loại cảm xúc text POSITIVE/NEGATIVE/NEUTRAL", "classes":. Phương pháp này hiệu quả trong hầu hết trường hợp, nhưng bạn cần điều chỉnh cho phù hợp ngữ cảnh riêng.
an abstract image of a network of dots

Xây dựng eval system cần test data đa dạng và chất lượng cao. Viết tay hàng trăm test cases tốn nhiều thời gian và thường thiếu đa dạng. Synthetic data generation dùng chính Claude để tạo test data — nhanh hơn 10x và đa dạng hơn khi được hướng dẫn đúng cách.

Bài toán: Khi nào cần synthetic test data?

  • Mới bắt đầu dự án, chưa có real-world data
  • Cần test edge cases khó kiếm trong thực tế (tiếng địa phương, lỗi chính tả cố ý, v.v.)
  • Cần nhanh chóng mở rộng từ 20 lên 200 test cases
  • Cần data với golden answers sẵn có để đánh giá tự động

Bước 1: Phân tích prompt template để extract variables

Đầu tiên, ta phân tích prompt template để hiểu cần generate data gì:

import anthropic
import json
import re

client = anthropic.Anthropic()

def extract_template_variables(prompt_template: str) -> list:
    """Extract các biến từ prompt template."""
    # Tìm các placeholder dạng {variable_name}
    variables = re.findall(r"{(w+)}", prompt_template)
    return list(set(variables))

# Ví dụ prompt template
SENTIMENT_PROMPT = """Phân loại cảm xúc của review sản phẩm sau:

Review: {review_text}

Phân loại: POSITIVE, NEGATIVE, hay NEUTRAL?
Chỉ trả lời một từ."""

variables = extract_template_variables(SENTIMENT_PROMPT)
print(f"Variables cần generate: {variables}")
# Output: ['review_text']

Bước 2: Tạo synthetic examples với Claude

GENERATOR_PROMPT = """Tạo {n} ví dụ test đa dạng cho bài toán: {task_description}

Yêu cầu:
- Đa dạng về độ dài (ngắn, trung bình, dài)
- Đa dạng về style (formal, informal, mixed)
- Bao gồm edge cases: tiếng lóng, lỗi chính tả, câu mơ hồ
- Mỗi ví dụ phải có golden answer chính xác
- Phân bổ đều: ~40% POSITIVE, ~35% NEGATIVE, ~25% NEUTRAL

Trả về JSON array với format:
[
  {{
    "id": "ex_001",
    "input": "{{review_text}}",
    "golden": "POSITIVE|NEGATIVE|NEUTRAL",
    "difficulty": "easy|medium|hard",
    "notes": "mô tả ngắn tại sao đây là ví dụ thú vị"
  }}
]

Chỉ trả về JSON, không có text khác."""

def generate_synthetic_data(task_description: str, n: int = 20) -> list:
    prompt = GENERATOR_PROMPT.format(
        n=n,
        task_description=task_description
    )

    response = client.messages.create(
        model="claude-sonnet-4-5",  # Dùng model mạnh để tạo data chất lượng
        max_tokens=4000,
        messages=[{"role": "user", "content": prompt}],
        temperature=0.8,  # Cao hơn để tăng độ đa dạng
    )

    text = response.content[0].text.strip()

    # Parse JSON
    # Xử lý trường hợp Claude wrap trong code block
    if text.startswith("'''"):
        text = re.sub(r"^'''(?:json)?
?", "", text)
        text = re.sub(r"
?'''$", "", text)

    examples = json.loads(text)
    return examples

# Tạo test data cho sentiment analysis
examples = generate_synthetic_data(
    task_description="Phân loại cảm xúc review sản phẩm e-commerce Việt Nam (POSITIVE/NEGATIVE/NEUTRAL)",
    n=30
)

print(f"Đã tạo {len(examples)} examples")
for ex in examples[:3]:
    print(f"
[{ex['golden']}] ({ex['difficulty']}) {ex['input'][:80]}...")
    print(f"  Notes: {ex['notes']}")

Bước 3: Validate và filter synthetic data

Synthetic data đôi khi có lỗi — Claude tạo golden answer sai, hoặc example không tự nhiên. Cần validate:

def validate_example(example: dict, original_prompt: str) -> dict:
    """
    Validate một synthetic example bằng cách:
    1. Chạy qua actual model
    2. So sánh output với golden answer
    3. Flag nếu model không đồng ý với golden answer
    """
    # Inject input vào template
    full_prompt = original_prompt.replace(
        "{review_text}",
        example["input"]
    )

    response = client.messages.create(
        model="claude-haiku-4-5",
        max_tokens=20,
        messages=[{"role": "user", "content": full_prompt}],
        temperature=0.0,
    )

    model_output = response.content[0].text.strip().upper()
    golden = example["golden"].upper()

    # Model đồng ý với golden?
    agreement = golden in model_output

    return {
        **example,
        "model_output": model_output,
        "model_agrees": agreement,
        "validation_status": "valid" if agreement else "check_needed",
    }

def validate_dataset(examples: list, prompt_template: str) -> dict:
    """Validate toàn bộ dataset."""
    validated = []
    for ex in examples:
        result = validate_example(ex, prompt_template)
        validated.append(result)

    agreed = sum(1 for ex in validated if ex["model_agrees"])
    print(f"Model đồng ý với golden answer: {agreed}/{len(validated)} ({agreed/len(validated):.1%})")

    # Tách ra hai nhóm
    clean = [ex for ex in validated if ex["model_agrees"]]
    needs_review = [ex for ex in validated if not ex["model_agrees"]]

    print(f"Clean examples: {len(clean)}")
    print(f"Cần review: {len(needs_review)}")

    for ex in needs_review[:5]:
        print(f"
  MISMATCH: '{ex['input'][:60]}...'")
        print(f"  Golden: {ex['golden']} | Model: {ex['model_output']}")

    return {"clean": clean, "needs_review": needs_review}

results = validate_dataset(examples, SENTIMENT_PROMPT)

Bước 4: Iterative refinement

Sau validation, ta có thể cải thiện dataset bằng cách phân tích failures:

def analyze_failures_and_regenerate(needs_review: list, n_new: int = 10) -> list:
    """
    Phân tích các cases model không đồng ý, sau đó tạo thêm examples
    tương tự nhưng rõ ràng hơn.
    """
    if not needs_review:
        print("Không có failures để phân tích!")
        return []

    # Tạo summary của failures
    failure_summary = "
".join([
        f"- Input: '{ex['input'][:50]}...' | Golden: {ex['golden']} | Model nói: {ex['model_output']}"
        for ex in needs_review[:10]
    ])

    analysis_prompt = f"""Phân tích các ví dụ test data sau mà model AI phân loại sai:

{failure_summary}

Tại sao những ví dụ này gây nhầm lẫn? Sau đó tạo {n_new} ví dụ MỚI tương tự nhưng rõ ràng hơn,
với golden answer dứt khoát không mơ hồ.

Trả về JSON array với cùng format như trước. Chỉ JSON."""

    response = client.messages.create(
        model="claude-sonnet-4-5",
        max_tokens=3000,
        messages=[{"role": "user", "content": analysis_prompt}],
        temperature=0.5,
    )

    text = response.content[0].text.strip()
    if text.startswith("'''"):
        text = re.sub(r"^'''(?:json)?
?", "", text)
        text = re.sub(r"
?'''$", "", text)

    new_examples = json.loads(text)
    print(f"Đã tạo thêm {len(new_examples)} examples từ failure analysis")
    return new_examples

new_examples = analyze_failures_and_regenerate(results["needs_review"])

Bước 5: Tạo few-shot examples từ synthetic data

Synthetic data không chỉ dùng cho eval — ta còn dùng để tạo few-shot examples cải thiện prompt:

def create_few_shot_examples(clean_examples: list, n_per_class: int = 3) -> str:
    """Chọn best examples để làm few-shot examples trong prompt."""
    by_class = {}
    for ex in clean_examples:
        label = ex["golden"]
        if label not in by_class:
            by_class[label] = []
        by_class[label].append(ex)

    selected = []
    for label, exs in by_class.items():
        # Ưu tiên các examples dễ (clear signal) và đa dạng
        easy_ones = [ex for ex in exs if ex.get("difficulty") == "easy"]
        chosen = (easy_ones[:n_per_class] if len(easy_ones) >= n_per_class
                  else exs[:n_per_class])
        selected.extend(chosen)

    # Format thành few-shot text
    few_shot_text = "Dưới đây là một số ví dụ:

"
    for ex in selected:
        few_shot_text += f"Review: {ex['input']}
Phân loại: {ex['golden']}

"

    return few_shot_text

few_shots = create_few_shot_examples(results["clean"])
print(few_shots[:500])

Template Generator cho nhiều loại task

TASK_TEMPLATES = {
    "sentiment": {
        "description": "Phân loại cảm xúc text (POSITIVE/NEGATIVE/NEUTRAL)",
        "classes": ["POSITIVE", "NEGATIVE", "NEUTRAL"],
        "distribution": {"POSITIVE": 0.4, "NEGATIVE": 0.35, "NEUTRAL": 0.25},
    },
    "spam_detection": {
        "description": "Phát hiện spam email/comment (SPAM/HAM)",
        "classes": ["SPAM", "HAM"],
        "distribution": {"SPAM": 0.3, "HAM": 0.7},
    },
    "intent_classification": {
        "description": "Phân loại intent người dùng chatbot (BUY/SUPPORT/INFO/COMPLAINT)",
        "classes": ["BUY", "SUPPORT", "INFO", "COMPLAINT"],
        "distribution": {"BUY": 0.25, "SUPPORT": 0.3, "INFO": 0.3, "COMPLAINT": 0.15},
    },
}

def generate_for_task(task_type: str, n: int = 50) -> list:
    if task_type not in TASK_TEMPLATES:
        raise ValueError(f"Unknown task: {task_type}")

    template = TASK_TEMPLATES[task_type]
    dist_str = ", ".join(
        f"~{int(v*100)}% {k}"
        for k, v in template["distribution"].items()
    )

    return generate_synthetic_data(
        task_description=f"{template['description']}. Phân bổ: {dist_str}",
        n=n
    )

# Tạo data cho spam detection
spam_data = generate_for_task("spam_detection", n=40)
print(f"Generated {len(spam_data)} spam detection examples")

Lưu và tái sử dụng dataset

import json
from datetime import datetime

def save_dataset(examples: list, task_name: str):
    filename = f"synthetic_data_{task_name}_{datetime.now().strftime('%Y%m%d')}.json"
    with open(filename, "w", encoding="utf-8") as f:
        json.dump({
            "task": task_name,
            "created_at": datetime.now().isoformat(),
            "n_examples": len(examples),
            "examples": examples
        }, f, ensure_ascii=False, indent=2)
    print(f"Saved {len(examples)} examples to {filename}")

def load_dataset(filename: str) -> list:
    with open(filename, "r", encoding="utf-8") as f:
        data = json.load(f)
    return data["examples"]

save_dataset(results["clean"], "sentiment_vi")

Synthetic test generation thay đổi hoàn toàn quy trình phát triển AI: thay vì chờ đủ real data mới bắt đầu evaluate, bạn có thể tạo dataset chất lượng cao trong vài phút và bắt đầu iterate ngay. Kết hợp với Building Evals để tạo vòng lặp cải thiện liên tục.

Tính năng liên quan:Synthetic DataTestingPrompt EngineeringEvaluation

Bai viet co huu ich khong?

Bản quyền thuộc về tác giả. Vui lòng dẫn nguồn khi chia sẻ.

Bình luận (0)
Ảnh đại diện
Đăng nhập để bình luận...
Đăng nhập để bình luận
  • Đang tải bình luận...

Đăng ký nhận bản tin

Nhận bài viết hay nhất về sản phẩm và vận hành, gửi thẳng vào hộp thư của bạn.

Bảo mật thông tin. Hủy đăng ký bất cứ lúc nào. Chính sách bảo mật.