C.W.K.
Stream
Lesson 04 of 07 · published

Synthetic Test Data Generation

~22 min · datasets, synthetic, scale

Level 0Guesser
0 XP0/55 lessons0/10 achievements
0/150 XP to next level150 XP to go0% complete

LLMs as their own dataset factories

Real data is the gold standard. Synthetic data is what gets you from 50 cases to 500 cases over lunch. Used correctly, it covers blind spots your production logs do not yet contain — rare combinations, adversarial inputs, multi-language coverage.

What synthetic data is good for

  • Coverage gaps — generating examples in languages, domains, or formats your real users have not yet exercised.
  • Adversarial tests — variants of jailbreak prompts, prompt injection attempts, edge-case formats.
  • Stress tests — extra-long inputs, deeply nested JSON, mixed-language documents.
  • Privacy-safe development — synthetic versions of sensitive data so engineers can iterate without touching real records.

What synthetic data is bad for

  • Distribution matching — generated inputs feel "model-shaped." They are smoother and more polite than real users.
  • Surfacing unknown unknowns — the LLM cannot generate a failure mode that nobody knows exists yet.
  • Final go/no-go decisions — never ship purely on synthetic eval results. Mix real and synthetic; weight real higher.
Principle: Synthetic data fills coverage gaps; real data discovers new failure modes. Use both. Never substitute one for the other.

Generation patterns that actually work

Seed-and-vary. Take 20 real cases, ask the model to generate 5 variants of each (paraphrases, longer versions, different languages). Now you have 100 cases preserving real distribution shape.

Persona-driven. Generate cases from the perspective of N user personas. Captures intent diversity better than ad-hoc prompts.

Failure-mode-driven. List the failure modes you fear; have the model generate inputs likely to trigger each one.

Code

Seed-and-vary generator with provenance tags·python
def generate_variants(seed_case, model, n=5):
    """Take one real case, produce N variants preserving meaning."""
    prompt = f"""
Given this real user query:
  {seed_case['input']}

Generate {n} variants that ask the SAME thing in different ways:
- Different phrasings
- One shorter, one longer
- One in a different language (Spanish or French)
- One with a typo or grammar mistake

Return JSON array of strings.
"""
    variants = json.loads(model.complete(prompt))
    return [
        {
            "id": f"{seed_case['id']}.var{i}",
            "input": v,
            "reference": seed_case["reference"],
            "tags": seed_case["tags"] + ["synthetic", "variant"],
            "source": "synthetic",
            "seed_id": seed_case["id"],
        }
        for i, v in enumerate(variants)
    ]
Failure-mode-driven adversarial generation·python
FAILURE_MODES = [
    "prompt injection — the user tries to override the system instruction",
    "PII extraction — the user tries to get the model to reveal training data",
    "jailbreak via roleplay — the user wraps a harmful request in a story",
    "format break — the user asks for output that breaks the JSON schema",
    "refusal probe — the user pushes the model to either refuse incorrectly or comply incorrectly",
]

def adversarial_set(model, per_mode=5):
    out = []
    for mode in FAILURE_MODES:
        prompt = (f"Generate {per_mode} adversarial user inputs that try to trigger this failure mode: {mode}. "
                  "Return JSON array of strings only.")
        cases = json.loads(model.complete(prompt))
        for c in cases:
            out.append({"input": c, "tags": ["adversarial", mode.split(' — ')[0].replace(' ', '-')]})
    return out

External links

Exercise

Take 5 real cases from your regression dataset and generate 5 variants of each using the seed-and-vary pattern. Tag them as synthetic. Run your eval on the combined set and check whether synthetic and real cases score similarly — large gaps signal distribution drift.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.