Documents field semantics, schema quirks, and survey-instrument design lessons for the nvidia/Nemotron-Personas-Korea dataset. Includes re-runnable inspection and persona-loading scripts.
How this skill is triggered — by the user, by Claude, or both
Slash command
/nemotron-personas-korea:datasetThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
`nvidia/Nemotron-Personas-Korea` is 1,000,000 synthetic Korean adults (ages 19–99), calibrated to KOSIS / Supreme Court / NHIS marginals, CC BY 4.0. Each row is one persona with demographics, a compact one-sentence summary, and ten richer narrative fields.
nvidia/Nemotron-Personas-Korea is 1,000,000 synthetic Korean adults (ages 19–99), calibrated to KOSIS / Supreme Court / NHIS marginals, CC BY 4.0. Each row is one persona with demographics, a compact one-sentence summary, and ten richer narrative fields.
The dataset materializes ~5.76 GB on disk (1.85 GB compressed parquet + 3.91 GB arrow cache for fast iteration). Cache location is governed by HF_HOME. Confirm with the user before running the bundled scripts/inspect_dataset.py or any code that calls load_dataset("nvidia/Nemotron-Personas-Korea", ...).
Check the current HF_HOME value. If it is unset, the cache lands at %USERPROFILE%\.cache\huggingface on Windows — i.e., the system drive, which is usually not what the user wants. Ask explicitly, e.g.:
"HF_HOME is currently
<value>(or unset → defaults to%USERPROFILE%\.cache\huggingface). The dataset will cache ~5.76 GB. Where should I put it — project-local./hf-cache, a dedicated drive, or the default?"
Don't run the load until the user has confirmed.
Identity — uuid.
Demographics — sex (남자 / 여자), age (int64, 19–99), province (17 distinct values, abbreviated — see quirks), district ({short-province}-{city/gu}, e.g. 서울-강서구), education_level, marital_status, family_type, housing_type, occupation, military_status, bachelors_field, country (constant).
Compact persona — persona. One sentence, ~50 words. The right field for closed-form survey answers; over-narrative makes the LLM pattern-match on hobbies and skews short answers.
6 narrative facets (~2–4 sentences each) — professional_persona, sports_persona, arts_persona, travel_persona, culinary_persona, family_persona. Right for interview-depth use cases.
4 supplementary narrative fields — cultural_background, skills_and_expertise, hobbies_and_interests, career_goals_and_ambitions.
2 list-form variants — skills_and_expertise_list, hobbies_and_interests_list (Python-list-as-string).
These bit during inspection on a real project; surface them up front when designing prompts or analyses.
province uses non-standard abbreviated naming, internally inconsistent. Values are 경기 (not 경기도), 서울, 부산, etc. — and the Jeolla pair is asymmetrically shortened: 전북 is doubly-shortened (전라북도 → 전북) while 전라남 is singly-shortened (전라남도 → 전라남). Comparing to KOSIS data needs a name-map; charts should use dataset values for fidelity.district already includes the short-province prefix. Format is {short-province}-{city/gu}, e.g. 경상북-문경시, 서울-강서구. A prompt that injects {province} {district} produces redundant double-counted location like 경상북 경상북-문경시. Use {district} alone, or {province} alone — never both.age is int64, not pre-binned. Bin manually if you need bands.military_status returns 비현역 for ineligible rows (older women, etc.) — not a clean indicator of actual military service.bachelors_field is 해당없음 for non-bachelor's-degree holders — filter before any field-of-study analysis.country is constant 대한민국 — drop entirely from any extension that uses this dataset.Decide per question, not by use mode. For each candidate narrative field, ask: does this field plausibly inform the answer?
persona field and the structured demographics block. Cheap, universally relevant.travel_persona. Food question → culinary_persona. Consumer adoption / brand / spending → professional_persona (income & role-derived priorities), hobbies_and_interests (consumption-category cues), career_goals_and_ambitions (forward-looking attitudes). Don't include sports_persona for a question about banking apps just because the field exists.*_persona + 4 supplementary). Multi-turn conversation needs the texture; selective inclusion makes responses feel generic.Hand-off to nemotron-personas-korea:persona-respondent: when dispatching to that sub-agent, your prompt IS the hand-off — there is no separate metadata channel. The agent's md file (agents/persona-respondent.md) reads the prompt under the assumption that you followed this guidance. Selecting fields well here directly shapes the agent's response quality on the receiving end.
The concurrency model lives in the global sources — not duplicated here (this section is what drifted stale). As of 2026-05-30: batched main-session Agent dispatch has no hard cap ≤24 (measured), is launch-rate-bound (~1.8 s/dispatch emit; wall ≈ N·1.8 s + W), and useful fan-out = Little's law L = W/1.8 s (≈25 for ~45 s tasks, ≈8 for a closed-form batch-of-10). Per-dispatch overhead is still type-dependent (persona-respondent ≈1.85 s, general-purpose ≈1.2 s), and at short W (~1–2 s) overhead dominates so batch first. The dynamic-workflow runtime is a separate path capped at min(16, cores−2) = 6. Re-measure the cap before relying on it — never quote from memory (it has moved 4× across versions). Full model + fan-out sizing: ~/.claude/rules/lessons/claude-code-agent-tool-parallelism.md and the agent-tool-throughput skill.
Below: only the nemotron-specific dispatch-mode choices and empirical distribution/fidelity findings.
persona-respondent) for:L≈25 is rarely reached at N≤10).persona-respondent for high-volume opinion work (plugin v0.1.2+)For opinion / value-projection questions where role-play depth matters more than throughput per dispatch, use file-read mode on persona-respondent directly:
### Persona i=NNN blocks + question + per-persona output format). Then dispatches PR with prompt READ_PERSONA_BATCH <absolute-path> (one line, no other content needed). PR fetches the file via Read and applies its native role-play scaffolding to each persona block.tools: [] and cannot invoke Read).general-purpose for closed-form factual high-volume workFor binary, Likert, multi-choice on factual questions (ground truth knowable from the persona's stated demographics — e.g., "are you currently married?"), ≥30 items:
general-purpose agent with persona-respondent's system instructions inlined into the user prompt, plus a multi-persona instruction.i=NN: <answer> one line per persona. Anchors structured output and minimizes blending.persona-respondent one-shot + 40 via batched-general-purpose, all matching ground truth.persona-respondent.~/.claude/skills/agent-tool-throughput/SKILL.md for the empirical model.For full empirical evidence on the parallelism model (concurrency cap, per-type overhead, decisive experiments), see ~/.claude/rules/lessons/claude-code-agent-tool-parallelism.md.
Empirical findings from a five-iteration ladder on this dataset (binary → Likert → debias → softened-extremes, N up to 200) for an "early adopter" attitudinal question. Surface these up front when designing any new closed-form instrument on this dataset.
Anchor wording strictness drives endorsement asymmetry. A scale that looks symmetric on paper produces asymmetric distributions because the LLM weights the extreme labels through cultural-acceptability and narrative-justifiability filters.
Always include a debias instruction in the question text: 솔직하게 대답해야 하며, 1부터 5까지 응답 모두를 활용해야 합니다. 1이나 5로 답하는 것을 주저하지 마세요. Recovers the negative tail much more reliably than the positive — observed +16% to cell 1 but only +0.5% to cell 5 — but is necessary for both directions.
Soften both extreme anchors symmetrically. Avoid absolutist language ("전혀 ~", "매우 ~", "무조건 ~", "절대 ~") at both cells 1 and 5. The replacement should be endorsable without sounding boastful or self-deprecating in Korean.
매우 그렇다, 무조건 X with 상당히 그렇다, 적극적으로 X — keeps directional commitment, loses bombast.전혀 아니다, X 할 때까지 안 한다 with 거의 아니다, 보통 X하지 않는다 — keeps direction without requiring near-pathological commitment.Validate by bin-level distribution comparison, not just mean. Compute χ² against a normative reference (Rogers' diffusion curve for adoption questions, NHIS/KOSIS marginals for demographics, etc.). Report cell-by-cell percentages, cumulative distributions, and variance separately. A "matching mean" with χ² rejection is the failure mode this caution is about.
Expect persistent residuals even with best practices: ~30% variance compression and 0.05-0.10 mean-shift relative to the normative reference. These are the central-tendency residual that survives debias + symmetric anchoring. Pre-register tolerances so you don't move the goalposts.
Subgroup-stratified analysis is more reliable than overall comparison. Within-cell distributions (e.g. 19-29 women) often match the normative reference more cleanly than the overall sample, because the dataset's narratives encode genuine demographic variation. Use overall χ² as a screening test, then look at subgroups for the actual signal.
A single run that returns a flat / clipped / suspicious distribution is ambiguous between two very different causes: (a) the persona narratives genuinely don't encode the trait you're asking about, or (b) the instrument's wording is filtering the signal out before it can be reported. From one run you cannot tell these apart — the symptom is identical.
The diagnostic move is a ladder of runs that change one element at a time, holding everything else constant. The early-adopter ladder above: the first three runs (binary → Likert → larger N Likert) all pointed toward "no early-adopter signal in this dataset" and would have been a wrong conclusion. Run 4 (debias instruction) recovered the laggard tail, demonstrating that the instrument was the problem, not the data. Run 5 (softened cell-5 anchor) recovered the innovator tail and confirmed the diagnosis.
Do not conclude anything from a single suspicious run. Plan to run at least 3–4 follow-ups, each changing exactly one element (anchor wording, debias instruction, scale type, framing, field selection). Treat the evolution across the ladder as the primary evidence.
When the analytical question conditions on a variable the dataset does NOT encode (e.g., first-marriage vs remarriage status: this dataset has marital_status ∈ {배우자있음, 미혼, 사별, 이혼} but no marriage-history field), you have to project the latent from narrative + demographic cues. The LLM has two failure modes when the latent is unobserved (validated 2026-05-10 on a 초혼-conditional husband-age-gap question, n=500):
Mitigation: give the LLM BOTH a marginal prior AND specific narrative cues.
자녀와만 거주, 손주와 거주 with no spouse mention). Without explicit cues, the LLM correlation-borrows from whatever observable correlates with the latent in its training prior — exactly the failure mode you wanted to avoid.Bracket prior-sensitive results across with-prior and without-prior runs.
When the latent isn't directly observable, a single point estimate can swing 3× depending on prior choice (we saw 5.8% ↔ 20% in the 초혼-conditional 12-year-gap question). Run both extremes (no prior, calibrated prior with cues) and report the result as a range with a probable midpoint, not a single number. The without-prior run captures correlation-only attribution; the with-prior run captures prior-anchored projection. The honest answer lies between.
When the latent IS in the data (e.g., filtering on marital_status == 미혼 or sex == 여자), none of the above applies — direct filter, no projection error, no prior to debate, no bracketing needed. Use the column.
scripts/inspect_dataset.py — a standalone inspection script. Pins the dataset SHA, dumps schema + dtypes, samples 3 random rows in full, computes text-field length comparisons (which identifies the compact persona vs. the long narrative fields), reports the province distribution, and computes sex × age-band marginals with proportional N=300 allocation. Re-run on first contact in a new project, or whenever the dataset SHA may have changed, to verify findings against the live dataset.scripts/load_persona.py — standalone loader (just datasets + pandas, no project-specific imports). Takes --uuid <id> or --filter "sex=여자,age>=30,province=서울" and emits all 21 persona-relevant fields in === <fieldname> === blocks suitable for piping into a prompt builder. Used by the persona-respondent agent and /persona-interviewee command for portable persona loading.references/inspection-snapshot.md — a SHA-pinned snapshot of the script's output. Treat as a frozen reference, not a live spec — re-run the script and diff if the SHA has moved.HF_HOME — HuggingFace's standard. Governs where load_dataset caches the ~5.76 GB dataset materialization. Set this BEFORE any load to keep the cache off the system drive (Windows default: %USERPROFILE%\.cache\huggingface).NEMOTRON_INTERVIEWS_DIR — used by /persona-interviewee --save for transcript output. Defaults to ./nemotron-interviews/ in the current working directory if unset.The script itself runs in a few minutes wall-clock once the dataset is cached. (For first-time cache placement, see "Before loading the dataset" above.)
npx claudepluginhub cjunekim/claude-plugins --plugin nemotron-personas-koreaGuides reception of code review feedback: verify before implementing, avoid performative agreement, push back with technical reasoning when needed.
Design banners for social media, ads, website heroes, and print with multiple art direction options and AI-generated visuals.