Skip to main content
Glama
civilian7

korean-people-persona

by civilian7

korean-people-persona

Eine Sammlung von Werkzeugen zur Konvertierung und Durchsuchung des HuggingFace-Datensatzes nvidia/Nemotron-Personas-Korea (ca. 1 Million Zeilen, 9 Parquet-Dateien) mittels SQLite.

Übersicht

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

  • Lizenz: Gemäß den Lizenzbedingungen der ursprünglichen Datensatzseite

  • DB-Datei: database/persona.db

  • Original-Parquet: data/train-*-of-*.parquet

  • Tabellen: persona (Haupttabelle) + persona_fts (FTS5-Index für externe Inhalte)

  • Ziel-SQLite: 3.37+ (unter Verwendung von FTS5, STRICT-Tabellen, JSON1)

  • Python: 3.10 oder höher (3.11+ empfohlen)

  • Abhängigkeiten: pyarrow >= 15.0, huggingface_hub >= 0.24 (siehe requirements.txt)

  • Freier Speicherplatz: ca. 5 GB (Parquet ~2 GB + DB ~3 GB)

Related MCP server: Legal Search MCP

Datenquelle

Element

Wert

Repository

nvidia/Nemotron-Personas-Korea

Dateien

train-0000{0..8}-of-00009.parquet (9 Stück)

Zeilen pro Datei

ca. 111.112

Gesamtzahl der Zeilen

1.000.000

Fehlende Werte

0 in allen Spalten (NOT NULL garantiert)

country

durchgehend 대한민국 (Südkorea)

*_list

Python repr-Format-Strings → normalisiert zu JSON-Arrays

Ordnerstruktur

korean-people-persona/
├── data/                  # 원본 parquet (gitignore — 약 2GB)
│   └── train-*-of-*.parquet
├── database/              # 생성된 SQLite (gitignore — 약 3GB)
│   └── persona.db
├── src/
│   ├── convert/                # parquet → SQLite 변환기
│   │   ├── __init__.py
│   │   └── __main__.py
│   └── mcp_server/             # (예정) MCP 서버
├── build.sh / build.bat / build.ps1
├── requirements.txt
└── README.md

data/ und database/ sind aufgrund ihrer Größe per .gitignore ausgeschlossen.

Datensatz herunterladen

Wählen Sie eine der drei Methoden. Die Ergebnisdateien müssen im Ordner data/ als train-*-of-*.parquet vorliegen.

1) Konvertierungsskript-Option (empfohlen)

Das src/convert-Paket lädt fehlende Dateien automatisch nach:

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

2) Direkte Verwendung von 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 clone

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

Authentifizierung: Für private oder gated Modelle sind huggingface-cli login oder die Umgebungsvariable HF_TOKEN erforderlich. Dieser Datensatz (zum Zeitpunkt der Veröffentlichung) kann auch ohne Authentifizierung heruntergeladen werden.

Größe: Die 9 Parquet-Dateien umfassen insgesamt ca. 1–2 GB.

Haupttabelle persona

CREATE TABLE persona (
  uuid                       TEXT    PRIMARY KEY,                                  -- 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;

Indizes

Name

Spalten

Zweck

idx_persona_demo

(sex, age)

Abfrage der Geschlechts-/Altersverteilung

idx_persona_region

(province, district)

Regionalfilter

idx_persona_edu_occ

(education_level, occupation)

Analyse von Bildung/Beruf

idx_persona_family

(family_type, marital_status)

Analyse von Haushalt/Familienstand

Spaltenbedeutung

Spalte

Beschreibung

Beispiel

uuid

32-stelliger Hex-String (ohne Bindestriche). PK

03b4f36a18e6469386d0286dddd513c8

persona

Kernzusammenfassung (1–2 Sätze)

"Ein 70-jähriger Mann, der sein Leben lang in der Landwirtschaft tätig war..."

*_persona

Detaillierte Persona nach Bereich (mehrere Sätze)

Beruf/Sport/Kunst/Reisen/Ernährung/Familie

cultural_background

Kultureller/biografischer Hintergrund

skills_and_expertise

Beschreibung der Fähigkeiten

skills_and_expertise_list

Keyword-Liste der oben genannten Punkte (JSON-Array)

["Excel-Nutzung","Dokumentenerstellung"]

hobbies_and_interests

Beschreibung der Hobbys/Interessen

hobbies_and_interests_list

Keyword-Liste der oben genannten Punkte (JSON-Array)

["Wandern","Angeln"]

career_goals_and_ambitions

Zukünftige Ziele

sex

남자 (männlich) / 여자 (weiblich)

age

Ganzzahl

marital_status

4 Typen

ledig / verheiratet / geschieden / verwitwet etc.

military_status

2 Typen

gedient / nicht zutreffend etc.

family_type

39 Typen

Ehepartner und Kinder, Einpersonenhaushalt etc.

housing_type

6 Typen

Wohnung, Einfamilienhaus etc.

education_level

7 Typen

Grundschule ~ Postgraduiert

bachelors_field

Studienfach

occupation

Beruf (Freitext)

district

Stadt/Bezirk

Gangnam-Seocho

province

Provinz/Stadt

Seoul, Gyeonggi etc. (17 Typen)

country

Land

대한민국 (Südkorea)

Volltextsuche — persona_fts (FTS5)

Indizierung von 10 langen koreanischen Textspalten mittels externer Inhaltsmethode.

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='rowid',
  tokenize='unicode61 remove_diacritics 2',
  prefix='2 3 4'
);

Tokenizer: unicode61 + 2/3/4-Zeichen-Präfix-Index. Für die koreanische Partikelverarbeitung wird bei der Suche ein Präfix-Matching der Form 등산* (Wandern*) empfohlen. Falls eine morphologische Analyse erforderlich ist, kann ein benutzerdefinierter Tokenizer auf Basis von mecab-ko / kiwi verwendet werden.

FTS-Synchronisation: Da der Datensatz statisch ist, erfolgt der Aufbau einmalig per INSERT INTO persona_fts(rowid, ...) SELECT .... Bei Änderungen sollten Trigger hinzugefügt werden.

Nutzung durch KI-Agenten (MCP-Server)

Dieses Repository stellt einen MCP (Model Context Protocol) Server bereit, sodass MCP-kompatible Agenten wie Claude Desktop, Cursor oder Cline Daten direkt abfragen und sampeln können.

Ausführung

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

Registrierung pro Agent

Alle Beispiele müssen den absoluten Pfad zum Repository /abs/path/to/korean-people-persona an Ihre Umgebung anpassen. Wenn eine virtuelle Umgebung (.venv) erstellt wurde, sollte der command auf den Python-Interpreter innerhalb der venv zeigen, um Abhängigkeitskonflikte zu vermeiden. (z. B. macOS/Linux /abs/path/.venv/bin/python, Windows C:/abs/path/.venv/Scripts/python.exe)

Claude Desktop

Speicherort der Konfigurationsdatei:

OS

Pfad

macOS

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

Windows

%APPDATA%\Claude\claude_desktop_config.json

Linux

~/.config/Claude/claude_desktop_config.json

Oder über das Menü Settings → Developer → Edit Config in der App.

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

Nach dem Speichern Claude Desktop neu starten → Überprüfen Sie, ob die 5 Werkzeuge über das Hammer-Symbol (🔨) unten rechts im Chat verfügbar sind.

Claude Code (CLI)

Registrierung per CLI-Befehl in einer Zeile:

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

Oder direkt in .mcp.json im Projektstammverzeichnis / Benutzereinstellungen ~/.claude/settings.json eintragen:

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

Überprüfung: claude mcp list → Nach Aktivierung können Werkzeuge über den /mcp-Slash-Befehl aufgerufen werden.

Cursor

.cursor/mcp.json pro Projekt oder global unter ~/.cursor/mcp.json:

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

Oder über die UI: Settings → MCP → Add new MCP Server. Nach dem Neustart von Cursor über @korean-persona aufrufbar.

ChatGPT (Developer Mode / Connectors)

Die MCP-Integration von ChatGPT basiert auf dem HTTP/SSE-Transport (Remote-Connector). Da dieser Server ein stdio-Server ist, kann er nicht direkt registriert werden, sondern muss über einen HTTP-Adapter bereitgestellt werden.

  1. Server mit dem HTTP-Transport des mcp-SDK ausführen:

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

    (Derzeit unterstützt server.py nur stdio. Für den HTTP/SSE-Modus ist eine Verzweigung mit mcp.run(transport="sse", port=8765) erforderlich.)

  2. Exponierung über ngrok / Cloudflare Tunnel etc.:

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

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

    • Authentifizierung: Bei Bedarf Bearer-Token-Header hinzufügen (MCP_AUTH_TOKEN)

  4. In einem neuen Chat können die Werkzeuge über das Tools-Menü aktiviert werden.

Sicherheitshinweis: Da ChatGPT-Connectoren Werkzeuge außerhalb des Modells exponieren, schützen Sie die öffentliche URL unbedingt mit einer Authentifizierung. Für lokale Nutzung wird die stdio-basierte Variante (Claude Desktop / Cursor) empfohlen.

Gemini CLI

Benutzereinstellungen für Google gemini-cli unter ~/.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"
    }
  }
}

Überprüfung: gemini mcp list (oder /mcp-Befehl in der CLI) → Werkzeuge werden automatisch geladen.

Allgemeine Fehlerbehebung

Symptom

Ursache / Lösung

Werkzeuge nicht sichtbar

App-Neustart vergessen. Claude Desktop muss vollständig beendet werden (auch Tray-Icon)

ModuleNotFoundError: mcp_server

Prüfen, ob PYTHONPATH auf src zeigt (absoluter Pfad empfohlen)

Koreanische Zeichen fehlerhaft

env.PYTHONIOENCODING=utf-8 hinzufügen (insb. unter Windows)

python-Befehl nicht gefunden

command als absoluten Pfad angeben (z. B. /usr/bin/python3, C:/Python311/python.exe, venv-Python)

Berechtigungsfehler

Pfade mit Leerzeichen unter Windows → in Anführungszeichen setzen oder Pfad ändern

Verfügbare Werkzeuge

Werkzeug

Beschreibung

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

FTS5-Freitextsuche + demografische Filter (BM25-Sortierung)

get_persona(uuid)

Vollständige Abfrage einer einzelnen Persona per UUID

sample_persona(filters, n, full)

Bedingte Zufallsstichprobe

aggregate(group_by, filters, limit)

Demografische GROUP BY COUNT-Analyse

stats()

Statistiken zum gesamten Datensatz und verfügbare Spalten

Anwendungsbeispiele für Agenten

1) Marketing-Interview-Simulation

"Wähle 10 Frauen über 60 aus, die gerne wandern, und simuliere ihre Reaktion auf den Werbetext für eine neue Kniebandage."

Der Agent arbeitet in folgenden Schritten:

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

  2. Jede Persona als System-Prompt injizieren → Bewertung des Werbetextes pro Person generieren

  3. Clustering der Antworten und Zusammenfassung der Erkenntnisse

2) Regionales Charakter-Casting

"Finde eine Persona eines 50-jährigen Selbstständigen aus Yeongdo-gu, Busan, und bereite sie als Protagonisten für einen Kurzroman auf."

search_persona(
  filters={"province":"부산", "district_like":"%영도%",
           "age_min":50, "age_max":59,
           "occupation_like":"%자영%"},
  limit=5, full=True
)

3) Analyse von politischen Auswirkungen

"Analysiere, in welcher Provinz Einpersonenhaushalte über 70 mit Grundschulabschluss am häufigsten vorkommen."

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

4) Semantische Suche + Zitat

"Finde eine Persona, die auf dem Land aufgewachsen ist und Enkelkinder hat, und gib sie zusammen mit einem Zitat aus cultural_background aus."

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

5) Synthetische Umfrage

"Erstelle eine geschichtete Stichprobe von 100 Personen proportional zur nationalen Bevölkerungsverteilung und frage jeden nach seiner Meinung zur Einführung der 4-Tage-Woche."

  1. aggregate(group_by=["province","sex","age"]) → Verteilungsquoten berechnen

  2. sample_persona gemäß den Quoten für Provinz × Geschlecht × Altersgruppe aufrufen

  3. LLM um 1:1-Antwort für jede Persona bitten

  4. Ergebnisse aggregieren → gewichtete Verteilung der Zustimmung/Ablehnung berechnen

Direkte Verwendung (Code)

Aufruf direkt aus Python ohne 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)

SQL-Direktabfrage

-- 1) 등산을 좋아하고 트로트 관련 언급이 있는 60대 여성
SELECT p.uuid, p.age, p.province, p.occupation
FROM persona_fts f
JOIN persona p ON p.rowid = 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.rowid = 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-Einstellungen (Laden/Betrieb)

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

Build-Prozess

Ein-Zeilen-Build (empfohlen)

OS-spezifische Wrapper-Skripte erstellen automatisch die virtuelle Umgebung, installieren Abhängigkeiten, laden Daten herunter und konvertieren sie.

Plattform

Befehl

Linux / macOS

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

Windows (cmd)

build.bat

Windows (PowerShell)

.\build.ps1

Optionen für erneuten Download werden einheitlich übergeben:

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

Falls unter PowerShell ein Fehler zur Ausführungsrichtlinie auftritt: PowerShell -ExecutionPolicy Bypass -File .\build.ps1

Manuelle Ausführung

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]

Interne Verarbeitung:

  1. (Optional) Bei --download werden fehlende Parquet-Dateien von HuggingFace geladen

  2. persona.db neu erstellen (vorhandene Datei löschen)

  3. PRAGMA-Einstellungen + Schema/Indizes erstellen

  4. 9 Parquet-Dateien sequenziell lesen, zeilenweise normalisieren und per executemany laden (Transaktionseinheit: 1 Datei)

  5. *_list-Spalten werden von ast.literal_eval → json.dumps(ensure_ascii=False) konvertiert

  6. FTS5-virtuelle Tabelle erstellen + einmaliger INSERT ... SELECT-Build

  7. INSERT INTO persona_fts(persona_fts) VALUES('optimize') gefolgt von ANALYZE

  8. WAL-Checkpoint und Beenden

Speicherplatzschätzung

  • Haupttabelle + Indizes: ca. 1,5 ~ 2,5 GB

  • FTS5 inklusive Präfixe: zusätzlich 1 ~ 3 GB

  • Gesamt ca. 3 ~ 5 GB erwartet (Aktualisierung nach tatsächlichem Laden).

Related MCP Connectors

Related MCP Servers