Skip to main content
Glama
civilian7

korean-people-persona

by civilian7

korean-people-persona

HuggingFace nvidia/Nemotron-Personas-Korea 데이터셋(약 100만 행, 9개 parquet 파일)을 SQLite로 변환·검색하기 위한 도구 모음.

개요

  • 출처: NVIDIA, Nemotron-Personas-Korea — https://huggingface.co/datasets/nvidia/Nemotron-Personas-Korea

  • 라이선스: 원 데이터셋 페이지의 라이선스 조항을 따름

  • DB 파일: database/persona.db

  • 원본 parquet: data/train-*-of-*.parquet

  • 테이블: persona (메인) + persona_fts (FTS5 외부 콘텐츠 인덱스)

  • 타깃 SQLite: 3.37+ (FTS5, STRICT 테이블, JSON1 사용)

  • Python: 3.10 이상 (3.11+ 권장)

  • 의존성: pyarrow >= 15.0, huggingface_hub >= 0.24 (requirements.txt 참조)

  • 디스크 여유: 약 13 GB (parquet ~2GB + DB 실측 ~10.7GB)

변경 이력은 CHANGELOG.md 참조.

Related MCP server: Legal Search MCP

데이터 출처

항목

값

저장소

nvidia/Nemotron-Personas-Korea

파일

train-0000{0..8}-of-00009.parquet (9개)

파일당 행 수

약 111,112

총 행 수

1,000,000

결측치

모든 컬럼에서 0 (NOT NULL 보장)

country

모두 대한민국 단일값

*_list

파이썬 repr 형식의 문자열 → JSON 배열로 정규화

폴더 구조

korean-people-persona/
├── data/                  # 원본 parquet (gitignore — 약 2GB)
│   └── train-*-of-*.parquet
├── database/              # 생성된 SQLite (gitignore — 약 10.7GB)
│   └── persona.db
├── src/
│   ├── convert/                # parquet → SQLite 변환기
│   └── mcp_server/             # MCP 서버 (도구 5종, stdio)
├── examples/              # 활용 데모 스크립트 (아래 '활용 데모' 참조)
│   ├── common.py               # 데모 공용 헬퍼
│   ├── synthetic_survey.py     # 사례 1 — 합성 설문
│   ├── user_simulator.py       # 사례 2 — 챗봇 평가용 유저 시뮬레이터
│   ├── synthetic_reviews.py    # 사례 3 — 합성 리뷰 데이터 생성
│   ├── copy_ab_test.py         # 사례 4A — 카피 A/B 테스트
│   ├── npc_casting.py          # 사례 4B — NPC/캐릭터 캐스팅
│   ├── test_demos.py           # 단위 테스트 (pytest)
│   └── requirements.txt        # 데모 전용 의존성 (mcp, anthropic)
├── docs/
│   └── use-cases.md            # LLM 에이전트 활용 사례 4종 + 프롬프트 레시피
├── build.sh / build.bat / build.ps1
├── requirements.txt
├── CHANGELOG.md
└── README.md

data/와 database/는 용량이 크므로 .gitignore로 폴더째 제외됩니다.

데이터셋 다운로드

세 가지 방법 중 하나를 선택. 결과 파일은 data/ 폴더에 train-*-of-*.parquet 형태로 위치해야 함.

1) 변환 스크립트 옵션 (권장)

src/convert 패키지가 누락 시 자동으로 가져옴:

pip install huggingface_hub pyarrow
PYTHONPATH=src python -m convert --download              # 없을 때만 받음
PYTHONPATH=src python -m convert --download --force-download   # 항상 재다운로드

2) huggingface-cli 직접 사용

pip install huggingface_hub
huggingface-cli download nvidia/Nemotron-Personas-Korea \
    --repo-type dataset \
    --include "train-*-of-*.parquet" \
    --local-dir ./data

3) git lfs 클론

git lfs install
git clone https://huggingface.co/datasets/nvidia/Nemotron-Personas-Korea
mv Nemotron-Personas-Korea/train-*.parquet ./data/

인증: 비공개 또는 게이트 모델의 경우 huggingface-cli login 또는 HF_TOKEN 환경변수 필요. 본 데이터셋(공개 시점 기준)은 비인증으로도 다운로드 가능.

용량: parquet 9개 합계 약 1~2 GB.

메인 테이블 persona

CREATE TABLE persona (
  id                         INTEGER PRIMARY KEY,                                  -- rowid 별칭 (자동 증가)
  uuid                       TEXT    NOT NULL,                                     -- 원본 32자 hex 문자열 (대시 없음, 유니크 인덱스)
  -- 페르소나 서술 (긴 한국어 텍스트) ----------------------------------------------
  persona                    TEXT    NOT NULL,                                     -- 핵심 1~2문장 요약
  professional_persona       TEXT    NOT NULL,                                     -- 직업/업무 페르소나
  sports_persona             TEXT    NOT NULL,                                     -- 스포츠/운동 페르소나
  arts_persona               TEXT    NOT NULL,                                     -- 예술/문화 페르소나
  travel_persona             TEXT    NOT NULL,                                     -- 여행 페르소나
  culinary_persona           TEXT    NOT NULL,                                     -- 식문화/요리 페르소나
  family_persona             TEXT    NOT NULL,                                     -- 가족 관계 페르소나
  cultural_background        TEXT    NOT NULL,                                     -- 문화·성장 배경 서술
  skills_and_expertise       TEXT    NOT NULL,                                     -- 보유 기술/전문성 서술
  hobbies_and_interests      TEXT    NOT NULL,                                     -- 취미·관심사 서술
  career_goals_and_ambitions TEXT    NOT NULL,                                     -- 향후 목표/포부
  -- 리스트 (JSON 배열로 저장) -----------------------------------------------------
  skills_and_expertise_list  TEXT    NOT NULL CHECK(json_valid(skills_and_expertise_list)),   -- 스킬 키워드 JSON 배열
  hobbies_and_interests_list TEXT    NOT NULL CHECK(json_valid(hobbies_and_interests_list)),  -- 취미 키워드 JSON 배열
  -- 인구통계 ---------------------------------------------------------------------
  sex              TEXT    NOT NULL,                                               -- 성별: 남자 / 여자
  age              INTEGER NOT NULL CHECK(age >= 0),                               -- 나이 (정수)
  marital_status   TEXT    NOT NULL,                                               -- 결혼상태 (4종: 미혼/기혼/이혼/사별 등)
  military_status  TEXT    NOT NULL,                                               -- 병역상태 (군필/해당없음 등)
  family_type      TEXT    NOT NULL,                                               -- 가구 유형 (39종: 1인 가구, 배우자와 자녀 등)
  housing_type     TEXT    NOT NULL,                                               -- 주거 형태 (6종: 아파트, 단독주택 등)
  education_level  TEXT    NOT NULL,                                               -- 최종 학력 (7종: 초등학교 ~ 대학원)
  bachelors_field  TEXT    NOT NULL,                                               -- 학사 전공 분야
  occupation       TEXT    NOT NULL,                                               -- 직업 (자유 텍스트)
  district         TEXT    NOT NULL,                                               -- 시군구 (예: 강남-서초)
  province         TEXT    NOT NULL,                                               -- 시도 (17종)
  country          TEXT    NOT NULL DEFAULT '대한민국'                             -- 국가 (단일값: 대한민국)
) STRICT;

인덱스

이름

컬럼

용도

idx_persona_demo

(sex, age)

성/연령 분포 쿼리

idx_persona_region

(province, district)

지역 필터

idx_persona_edu_occ

(education_level, occupation)

학력/직업 분석

idx_persona_family

(family_type, marital_status)

가구/결혼 분석

idx_persona_prov_sex

(province, sex)

시도×성별 집계·층화 샘플링 커버링

idx_persona_uuid

(uuid) UNIQUE

uuid 단건 조회

컬럼 의미

컬럼

설명

예시

uuid

32자 hex 문자열 (대시 없음). 유니크

03b4f36a18e6469386d0286dddd513c8

persona

핵심 1~2문장 요약

"농촌 지역에서 평생 농업 일을 해온 70대 남성으로..."

*_persona

영역별 상세 페르소나 (수문장 길이)

직업/스포츠/예술/여행/식문화/가족

cultural_background

문화·성장 배경 서술

skills_and_expertise

보유 기술 서술

skills_and_expertise_list

위 항목의 키워드 리스트 (JSON 배열)

["엑셀 활용","문서 작성"]

hobbies_and_interests

취미·관심사 서술

hobbies_and_interests_list

위 항목의 키워드 리스트 (JSON 배열)

["등산","낚시"]

career_goals_and_ambitions

향후 목표

sex

남자 / 여자

age

정수

marital_status

4종

미혼 / 기혼 / 이혼 / 사별 등

military_status

2종

군필 / 해당없음 등

family_type

39종

배우자와 자녀, 1인 가구 등

housing_type

6종

아파트, 단독주택 등

education_level

7종

초등학교 ~ 대학원

bachelors_field

학사 전공 분야

occupation

직업 (자유 텍스트)

district

시군구

강남-서초

province

시도

서울, 경기 등 17종

country

국가

대한민국 (단일값)

전문 검색 — persona_fts (FTS5)

긴 한국어 서술 컬럼 10개를 외부 콘텐츠 방식으로 인덱싱.

CREATE VIRTUAL TABLE persona_fts USING fts5(
  professional_persona,
  sports_persona,
  arts_persona,
  travel_persona,
  culinary_persona,
  family_persona,
  cultural_background,
  skills_and_expertise,
  hobbies_and_interests,
  career_goals_and_ambitions,
  content='persona',
  content_rowid='id',
  tokenize='trigram'
);

토크나이저: trigram — 연속 3글자를 토큰으로 사용하므로 형태소 분석 없이 부분 문자열 매칭이 된다.

  • 3글자 이상 검색어는 조사가 붙은 형태도 그대로 매칭됨 (등산과, 트로트) — prefix * 불필요

  • 2글자 이하는 매칭 불가 (캠핑 → 0건). 공백 포함 구절('"캠핑 "')이나 합성어 OR 조합('캠핑장 OR 캠핑카')으로 우회

  • 불린 연산(AND/OR/NOT)과 큰따옴표 구절 검색 지원

  • 더 정교한 한국어 처리가 필요하면 mecab-ko / kiwi 기반 커스텀 토크나이저로 교체

FTS 동기화: 데이터셋이 정적이므로 1회 INSERT INTO persona_fts(rowid, ...) SELECT ...로 빌드. 변경이 있으면 트리거를 추가.

AI 에이전트 활용 (MCP 서버)

본 저장소는 MCP(Model Context Protocol) 서버를 제공하므로 Claude Desktop, Cursor, Cline 등 MCP 호환 에이전트가 데이터를 직접 검색·샘플링할 수 있습니다.

실행

PYTHONPATH=src python -m mcp_server          # stdio 서버 시작

에이전트별 등록 방법

모든 예시는 저장소 절대경로 /abs/path/to/korean-people-persona 를 본인 환경에 맞춰 바꿔야 합니다. 가상환경(.venv)을 만든 경우 command를 venv 안 파이썬으로 지정하면 의존성 충돌이 없습니다. (예: macOS/Linux /abs/path/.venv/bin/python, Windows C:/abs/path/.venv/Scripts/python.exe)

Claude Desktop

설정 파일 위치:

OS

경로

macOS

~/Library/Application Support/Claude/claude_desktop_config.json

Windows

%APPDATA%\Claude\claude_desktop_config.json

Linux

~/.config/Claude/claude_desktop_config.json

또는 앱 내 Settings → Developer → Edit Config 메뉴.

{
  "mcpServers": {
    "korean-persona": {
      "command": "python",
      "args": ["-m", "mcp_server"],
      "env": {
        "PYTHONPATH": "/abs/path/to/korean-people-persona/src",
        "PYTHONIOENCODING": "utf-8"
      }
    }
  }
}

저장 후 Claude Desktop 재시작 → 채팅창 우하단 망치(🔨) 아이콘에서 5개 도구 노출 확인.

Claude Code (CLI)

CLI 명령으로 한 줄 등록:

claude mcp add korean-persona python -m mcp_server \
  -e PYTHONPATH=/abs/path/to/korean-people-persona/src \
  -e PYTHONIOENCODING=utf-8

또는 프로젝트 루트의 .mcp.json / 사용자 설정 ~/.claude/settings.json에 직접 작성:

{
  "mcpServers": {
    "korean-persona": {
      "command": "python",
      "args": ["-m", "mcp_server"],
      "env": { "PYTHONPATH": "/abs/path/to/korean-people-persona/src" }
    }
  }
}

확인: claude mcp list → 활성화 후 /mcp 슬래시 명령으로 도구 호출 가능.

Cursor

프로젝트별 .cursor/mcp.json 또는 사용자 전역 ~/.cursor/mcp.json:

{
  "mcpServers": {
    "korean-persona": {
      "command": "python",
      "args": ["-m", "mcp_server"],
      "env": { "PYTHONPATH": "/abs/path/to/korean-people-persona/src" }
    }
  }
}

또는 Settings → MCP → Add new MCP Server UI 사용. 커서 재시작 후 @korean-persona로 호출.

ChatGPT (Developer Mode / Connectors)

ChatGPT의 MCP 통합은 HTTP/SSE 트랜스포트 기반으로 동작합니다(원격 커넥터). 본 서버는 stdio 서버이므로 그대로는 등록할 수 없고, HTTP 어댑터로 감싸서 노출해야 합니다.

  1. mcp SDK의 HTTP 트랜스포트로 서버 실행:

    PYTHONPATH=src python -m mcp_server --transport sse --port 8765

    (현재 본 저장소 server.py는 stdio만 호출. HTTP/SSE 모드를 쓰려면 mcp.run(transport="sse", port=8765)로 분기 추가가 필요합니다.)

  2. ngrok / Cloudflare Tunnel 등으로 외부 노출:

    ngrok http 8765
  3. ChatGPT → Settings → Connectors → Developer mode → Add custom connector

    • URL: https://<ngrok>/sse

    • 인증: 필요 시 Bearer 토큰 헤더 추가 (MCP_AUTH_TOKEN)

  4. 새 채팅에서 Tools 메뉴에서 커넥터를 활성화하면 도구 호출 가능.

보안 주의: ChatGPT 커넥터는 모델 외부에 도구를 노출하므로 공개 URL은 반드시 인증으로 보호하세요. 로컬 전용이면 stdio 기반 Claude Desktop / Cursor 사용을 권장.

Gemini CLI

Google gemini-cli 사용자 설정 ~/.gemini/settings.json:

{
  "mcpServers": {
    "korean-persona": {
      "command": "python",
      "args": ["-m", "mcp_server"],
      "env": { "PYTHONPATH": "/abs/path/to/korean-people-persona/src" },
      "cwd": "/abs/path/to/korean-people-persona"
    }
  }
}

확인: gemini mcp list (또는 CLI 내 /mcp 명령) → 도구 자동 노출.

공통 트러블슈팅

증상

원인 / 해결

도구가 안 보임

앱 재시작 누락. Claude Desktop은 완전 종료 필요 (트레이 아이콘까지)

ModuleNotFoundError: mcp_server

PYTHONPATH가 src를 가리키는지 확인 (절대경로 권장)

한글 깨짐

env.PYTHONIOENCODING=utf-8 추가 (특히 Windows)

python 명령 못 찾음

command를 절대경로로 (예: /usr/bin/python3, C:/Python311/python.exe, venv의 python)

권한 오류

Windows에서 경로 공백 → 따옴표 또는 경로 변경

노출 도구

도구

설명

search_persona(query, fields, filters, limit, full)

FTS5 자유 텍스트 검색 + 인구통계 필터 결합 (BM25 정렬)

get_persona(uuid)

uuid로 단일 페르소나 전체 조회

sample_persona(filters, n, full)

조건부 무작위 샘플링

aggregate(group_by, filters, limit)

인구통계 GROUP BY COUNT

stats()

전체 데이터셋 통계·사용 가능 컬럼 안내

에이전트 활용 샘플

1) 마케팅 인터뷰 시뮬레이션

"60대 이상 여성 중 등산을 즐기는 분 10명을 샘플링해서, 새로 출시한 무릎 보호대 광고 카피에 대한 반응을 시뮬레이션해줘."

에이전트는 다음 흐름으로 작동:

  1. search_persona(query="등산을 OR 등산과", filters={"sex":"여자","age_min":60}, limit=10, full=True)

  2. 각 페르소나를 시스템 프롬프트로 주입 → 광고 카피 평가 응답 1인 1건씩 생성

  3. 응답 클러스터링 후 인사이트 요약

2) 지역 기반 캐릭터 캐스팅

"부산 영도구에 사는 50대 자영업자 페르소나를 찾아서, 단편소설 주인공으로 쓸 수 있게 정리해줘."

search_persona(
  filters={"province":"부산", "district_like":"%영도%",
           "age_min":50, "age_max":59,
           "occupation_like":"%경영%"},   # occupation에 '자영업' 문자열은 없음 — 실제 값은 '소규모 상점 경영자' 등
  limit=5, full=True
)

3) 정책 영향 분석

"초등학교 졸업이 최종 학력인 70대 이상 1인 가구가 어느 시도에 가장 많은지 분포 분석해줘."

aggregate(
  group_by=["province"],
  filters={"education_level":"초등학교", "age_min":70,
           "family_type_like":"%혼자%"},
  limit=20
)

4) 의미 기반 검색 + 인용

"농촌에서 자랐고 손주가 있는 페르소나를 찾아 cultural_background 인용과 함께 알려줘."

search_persona(
  query='농촌에서 AND 손주들',
  fields=["cultural_background", "family_persona"],
  limit=5, full=True
)

5) 합성 설문조사

"전국 인구 분포에 비례해서 100명을 층화 샘플링한 뒤, 각자에게 '주 4일제 도입에 찬성하느냐'고 물어봐줘."

  1. aggregate(group_by=["province","sex","age"]) → 분포 비율 계산

  2. 비율대로 sample_persona를 시도×성별×연령대별로 호출

  3. 각 페르소나로 LLM에 1:1 응답 요청

  4. 결과 집계 → 가중치 적용한 찬반 분포 산출

직접 사용 (코드)

MCP 없이 파이썬에서 바로 호출:

import sys; sys.path.insert(0, "src")
from mcp_server import tools

tools.stats()
tools.search_persona(query="용접공", filters={"sex":"남자"}, limit=5)
tools.sample_persona(filters={"province":"제주"}, n=3, full=True)

활용 데모 (examples/)

docs/use-cases.md의 활용 사례 4종에 대응하는 동작하는 데모 스크립트. 각 사례 문서에는 코드 없이 Claude Code 세션에 붙여넣어 재현하는 "▶ Claude Code에서 바로 해보기" 프롬프트 레시피도 포함되어 있다.

스크립트

사례

내용

산출물

synthetic_survey.py

1

인구 비례 층화 샘플링 합성 설문 (5점 척도 + 이유)

survey_result.json

user_simulator.py

2

가상 고객 ↔ 결함 내장 더미 상담봇 멀티턴 대화 + LLM judge 채점

simulator_result.json

synthetic_reviews.py

3

관심사 시드 상품 리뷰 생성 + 인구통계 라벨 + 표현 복사 검출

synthetic_reviews.jsonl

copy_ab_test.py

4A

관심사 세그먼트 카피 A/B 선호 평가 (제시 순서 무작위화)

ab_test_result.json

npc_casting.py

4B

배역 요구 → 후보 추출 → 캐릭터 시트 생성

npc_candidates.md

common.py는 다섯 스크립트가 공유하는 헬퍼(MCP 접속·층화 샘플링·LLM 호출·집계)다.

설치

pip install -r examples/requirements.txt    # mcp, anthropic

실행

모든 스크립트는 프로젝트 루트에서 실행하며, MCP 서버를 직접 띄울 필요 없이 스크립트가 stdio로 자체 기동한다 (database/persona.db 빌드 선행 필요).

# 1) dry-run — API 키 없이 MCP 파이프라인(샘플링/검색)만 검증
python examples/synthetic_survey.py --dry-run --n 10
python examples/user_simulator.py --dry-run --per-group 3
python examples/synthetic_reviews.py --dry-run --n 5
python examples/copy_ab_test.py --dry-run
python examples/npc_casting.py --dry-run

# 2) 실제 실행 — LLM 롤플레이 포함 (ANTHROPIC_API_KEY 필요, 호출량만큼 과금)
#    Linux/macOS: export ANTHROPIC_API_KEY=sk-ant-...
#    PowerShell:  $env:ANTHROPIC_API_KEY = "sk-ant-..."
python examples/synthetic_survey.py --n 20 --question "주 4일제 도입에 찬성하십니까?"
python examples/user_simulator.py --per-group 5
python examples/synthetic_reviews.py --n 10
python examples/copy_ab_test.py --copy-a "카피 A 문구" --copy-b "카피 B 문구"
python examples/npc_casting.py --brief "서울 30대 미혼 직장인 조연"

공통 옵션: --dry-run(키 불필요), --model(기본 claude-sonnet-4-6), 표본 수(--n 등). 세부 옵션은 각 스크립트의 --help 참조. 산출물은 프로젝트 루트에 저장되며 gitignore 처리되어 있다.

테스트

python -m pytest examples/test_demos.py -v    # 순수 함수 + 더미봇 규칙 16개

SQL 직접 쿼리

-- 1) 등산을 좋아하고 트로트 관련 언급이 있는 60대 여성 (trigram — 3글자 이상, '*' 불필요)
SELECT p.uuid, p.age, p.province, p.occupation
FROM persona_fts f
JOIN persona p ON p.id = f.rowid
WHERE persona_fts MATCH '등산과 AND 트로트'
  AND p.sex = '여자' AND p.age BETWEEN 60 AND 79
ORDER BY bm25(persona_fts) LIMIT 20;

-- 2) 특정 컬럼 검색 + 스니펫
SELECT p.uuid, snippet(persona_fts, 7, '<b>', '</b>', '...', 10) AS hit
FROM persona_fts f JOIN persona p ON p.id = f.rowid
WHERE f.skills_and_expertise MATCH '용접공' LIMIT 10;

-- 3) JSON 리스트 펼치기
SELECT p.uuid, j.value AS hobby
FROM persona p, json_each(p.hobbies_and_interests_list) j
WHERE j.value LIKE '%낚시%' LIMIT 10;

-- 4) 인구통계 분포
SELECT province, sex, COUNT(*) cnt
FROM persona GROUP BY province, sex ORDER BY cnt DESC;

PRAGMA 설정 (적재/운영)

PRAGMA journal_mode = WAL;
PRAGMA synchronous  = NORMAL;
PRAGMA temp_store   = MEMORY;
PRAGMA cache_size   = -262144;   -- 256MB

빌드 절차

한 줄 빌드 (권장)

OS별 래퍼 스크립트가 가상환경 생성 → 의존성 설치 → 다운로드 → 변환까지 자동 수행.

플랫폼

명령

Linux / macOS

chmod +x build.sh && ./build.sh

Windows (cmd)

build.bat

Windows (PowerShell)

.\build.ps1

재다운로드 옵션은 모두 동일하게 전달:

./build.sh --force-download
build.bat --force-download
.\build.ps1 --force-download

PowerShell에서 실행 정책 오류가 나면: PowerShell -ExecutionPolicy Bypass -File .\build.ps1

수동 실행

python -m venv .venv
# Linux/macOS: source .venv/bin/activate
# Windows:     .venv\Scripts\activate
pip install -r requirements.txt
PYTHONPATH=src python -m convert [--download] [--force-download]

내부 처리:

  1. (옵션) --download 시 parquet 누락분을 HuggingFace에서 받음

  2. persona.db 신규 생성 (기존 파일 삭제)

  3. PRAGMA 설정 + 스키마/인덱스 생성

  4. 9개 parquet을 순차 읽어 행 단위 정규화 후 executemany 적재 (트랜잭션 단위: 파일 1개)

  5. *_list 컬럼은 ast.literal_eval → json.dumps(ensure_ascii=False) 변환

  6. FTS5 가상 테이블 생성 + INSERT ... SELECT 1회 빌드

  7. INSERT INTO persona_fts(persona_fts) VALUES('optimize') 후 ANALYZE

  8. WAL 체크포인트 후 종료

디스크 사용량 (실측)

  • persona.db 합계 약 10.7 GB (메인 테이블 + 인덱스 + FTS5 trigram)

  • 빌드 소요 시간 약 24분 (장비에 따라 상이)

  • trigram 토크나이저는 모든 3글자 조합을 인덱싱하므로 unicode61 대비 용량이 크다 — 부분 문자열 매칭의 대가

Related MCP Connectors

Related MCP Servers