학습 데이터셋
GenD 학습 데이터셋은 LLM/VLM 파인튜닝용 학습 데이터(이미지, 비디오, instruction JSONL, 이미지-텍스트 페어)를 데이터셋 단위로 저장·탐색·버전 관리하는 기능입니다. 원본은 S3, 행 데이터는 Iceberg 테이블에 저장되어 SQL 에디터에서도 조회할 수 있고, 버전은 Iceberg snapshot 으로 고정되어 "이 모델이 어느 데이터로 학습됐는지"를 재현 가능하게 만듭니다.
주요 기능
- 데이터셋 생성: modality(이미지 / 이미지-텍스트 / 텍스트 / 비디오 v1.2+) 선택 → Iceberg 행 테이블이 자동 생성됩니다 (
iceberg.ws_<슬러그>.ds_*— 워크스페이스 스키마) - HF imagefolder 호환 (v1.2+): zip 폴더 구조에서 split/label 자동 추론
(
train/cat/1.jpg→ split=train·label=cat,valid→validation정규화)- zip 내
metadata.jsonl(file_name키) 로 label·caption·임의 메타 지정. 업로드 요청에?split=·?label=기본값도 줄 수 있습니다
- zip 내
- 이미지 업로드: 다중 파일 또는 zip — 확장자 화이트리스트(PNG/JPG/JPEG/TIFF/BMP), 손상 이미지 자동 거부, content_hash 기반 중복 제거(dedup), 썸네일 자동 생성
- 비디오 업로드 (v1.2+): MP4/WebM 개별 파일 — 컨테이너 시그니처 검증(위장 파일 거부), content_hash dedup. 썸네일·재생시간은 생성하지 않습니다
- JSONL/Parquet 업로드: instruction 데이터 — messages(멀티턴 chat) / prompt-response / DPO(chosen·rejected)
서브포맷 자동 추론, dry-run 미리보기 후 적재. HF TRL 4형식을 키 변환 없이 받습니다 —
text/messages/prompt+completion(또는response) /chosen+rejected(v1.2+) - 데이터 뷰어: 갤러리/테이블 두 가지 보기(v1.2+ — 이미지·비디오는 갤러리가 기본), 행 브라우징(더 보기 커서), 이미지 썸네일 + 라이트박스, 비디오 인라인 플레이어(클릭 시에만 로드), chat 말풍선 렌더, DPO 나란히 비교, split 필터, 행 상세 패널
- 행 삭제: 오염 데이터·PII 삭제 요청 대응 (선택 삭제)
- 버전 고정: 업로드/적재 응답의 snapshot ID 로 버전을 생성 — 이후 데이터가 추가·삭제되어도 버전 조회는 그 시점 그대로 유지됩니다
사용 방법
-
사이드바 학습 데이터셋 → 데이터셋 만들기 — 이름과 modality 를 선택합니다.
-
상세 페이지 데이터 업로드 — 이미지(다중/zip)·비디오(MP4/WebM 개별 파일) 또는 JSONL 파일을 올립니다. JSONL 은 미리보기(dry run) 로 서브포맷·파싱 오류를 먼저 확인할 수 있습니다.

비디오 데이터셋에서는 업로드 다이얼로그에 비디오 탭이 표시됩니다 — 파일당 최대 100MB, ZIP 은 지원하지 않으며 100MB 초과 파일은 선택 단계에서 제외되고 파일명이 안내됩니다.
-
데이터 탭에서 행을 탐색합니다.
이미지·비디오 데이터셋은 갤러리 보기로 열립니다 (v1.2+). 각 카드 아래에는 라벨이 있으면 라벨을, 없으면 split 배지가 표시됩니다.

오른쪽 위 토글로 테이블 보기로 바꿀 수 있습니다. 테이블에서는 썸네일이 첫 컬럼이고, 행 선택·삭제는 테이블 보기에서만 가능합니다 (갤러리는 조회 전용).

텍스트 데이터셋은 갤러리가 의미 없으므로 토글 없이 테이블만 표시됩니다. 이미지 클릭 시 원본 라이트박스가, 비디오의 재생 버튼 클릭 시 인라인 플레이어가 열립니다 (목록 스크롤 중에는 원본을 내려받지 않습니다 — 클릭한 클립만 로드).

-
업로드 결과에 표시된 snapshot ID 로 버전 탭에서 버전을 생성합니다. 버전의 "이 버전 보기"로 고정 시점 데이터를 조회합니다.
CLI·Python 으로 자동화
외부 학습 서버나 스크립트에서 올리고 내려받으려면
학습 데이터셋 — CLI·Python 으로 올리고 내려받기
를 보세요 (키 발급 → gend dataset upload/download → Python 예제).
라벨·split 지정 우선순위 (v1.2+)
가장 구체적인 것이 이깁니다:
- zip 내
metadata.jsonl의 값 - zip 폴더 구조 추론 (
<split>/<label>/파일) - 업로드 요청 파라미터 (
?split=·?label=, CLI--split/--label) - 기본값 (
split=train, label 없음)
JSONL 은 레코드의 split 키가 항상 최우선이고, 요청 파라미터는 레코드에 값이 없을 때만 적용됩니다.
:::warning 같은 이미지를 다른 라벨로 다시 올려도 라벨은 바뀌지 않습니다
중복 판정이 이미지 바이트의 content_hash 기준이라, 이미 있는 이미지는 duplicates 로 건너뛰고
라벨/캡션이 갱신되지 않습니다. 라벨을 고치려면 해당 행을 지우고 다시 올리세요.
:::
워크스페이스 격리 · 거버넌스
- 데이터셋은 생성한 워크스페이스에 격리됩니다 (교차 워크스페이스 접근 차단).
- 쓰기에는 워크스페이스별 권한 발급이 필요합니다 (v1.2+): 데이터셋 생성·적재·행 삭제·
데이터셋 삭제는 해당 워크스페이스의 스키마(
iceberg.ws_<슬러그>)에 write 바인딩이 있어야 합니다. 없으면 403 이며 관리자가 발급해야 합니다. 업로드 중단(abort) 같은 정리 동작은 권한과 무관하게 동작합니다 — 정리를 막으면 미완료 업로드가 남기 때문입니다. 단 v1.2 현재 키 방식(개인 트래킹 키·M2M 서비스 클라이언트) 토큰에는 이 격리가 적용되지 않습니다 — #3040 에서 수정 중이며, 자세한 내용은 CLI·Python 가이드 참조. - 생성 시 해당 Iceberg 테이블의 table-scope 권한(DataGrant)이 생성자에게 자동 발급됩니다.
- 모든 요청은 감사 로그에 기록됩니다.
:::info 워크스페이스 멤버면 쿼리 엔진 권한이 함께 열립니다 (v1.2.1+)
데이터셋이 워크스페이스 스키마에 놓이면서, 워크스페이스 소속만으로 엔진(Trino) 쪽
쓰기 권한까지 따라옵니다. 종전에는 API 바인딩을 받아도 엔진이 따로 막아 적재가
502 로 실패했습니다 — 원인이 API 계층이 아니어서 화면의 안내만으로는 알 수 없었습니다.
권한을 새로 받았는데도 여전히 막힌다면 최대 2~3분 기다린 뒤 다시 시도하세요. 멤버십이 엔진에 반영되기까지 동기화 주기가 있습니다. 그 시간이 지나도 실패하면 관리자에게 문의하세요. :::
API 엔드포인트
| Method | Path | 설명 |
|---|---|---|
| POST | /api/v1/datasets | 데이터셋 생성 |
| GET | /api/v1/datasets / /{id} | 목록 / 상세 |
| DELETE | /api/v1/datasets/{id} | 삭제 (Iceberg 테이블 동기 DROP) |
| POST | /api/v1/datasets/{id}/files | 이미지·비디오 업로드 (multipart — zip 은 이미지 전용, 비디오는 개별 파일) |
| POST | /api/v1/datasets/{id}/jsonl?dry_run= | JSONL 업로드 (미리보기/적재) |
| GET | /api/v1/datasets/{id}/rows | 행 조회 (keyset 커서 after, split/label 필터) |
| DELETE | /api/v1/datasets/{id}/rows | 행 삭제 (record_id 목록) |
| GET | /api/v1/datasets/{id}/blob/{hash}?variant= | 이미지·비디오 바이트 (Range 206 지원 v1.2+ — 비디오 시킹) |
| GET | /api/v1/datasets/{id}/stats | 행 수 · split/라벨 분포 |
| POST | /api/v1/datasets/{id}/versions | 버전 고정 (snapshot ID 명시) |
| GET | /api/v1/datasets/{id}/versions / /{v}/rows | 버전 목록 / 버전 고정 조회 |
| POST | /api/v1/datasets/{id}/exports | 버전 고정 JSONL export (202 + 폴링) |
| GET | /api/v1/datasets/{id}/exports / /{export_id} | export 목록 / 상태 조회 |
| GET | /api/v1/datasets/{id}/exports/{export_id}/download | export 산출물 다운로드 (v1.2+) — S3 자격 불필요, gend dataset download 가 사용 |
| POST/PUT | /api/v1/datasets/{id}/uploads* | 100MB 초과 parquet 청크 업로드 (v1.2+) — gend dataset upload 가 자동 전환 |
snapshot ID 는 문자열로 다룹니다 — 값이 JavaScript Number 정밀도(2^53)를 초과하므로 API 경계에서 10진 문자열로 직렬화됩니다.
제한 사항
- 파일 1개 최대 100 MB, 요청 합산 200 MB, 요청당 1,000개 파일
- zip: 엔트리 2,000개 · 압축 해제 누적 500 MB 상한, 경로 이탈/심링크 엔트리 거부
- 이미지 형식: PNG/JPG/JPEG/TIFF/BMP (SVG·GIF·WebP 미지원 — 보안 정책)
- 비디오 형식 (v1.2+): MP4/WebM 개별 파일만 (ZIP 미지원) · 파일당 최대 100MB · 재생시간/해상도 메타데이터와 썸네일은 현재 생성하지 않습니다 (
duration_ms/width/height는 NULL) completion은response의 입력 별칭입니다 (TRL prompt-completion 정합, v1.2+) — 저장 컬럼은response하나입니다. 한 레코드에 둘 다 있으면response를 채택하고completion은meta에 보존합니다- Parquet: 문자열 컬럼만 지원 (HF chat 의
list<struct>messages 는 미지원 — JSONL 사용).mask_pii는 JSONL 경로 전용 - JSONL 적재 시
mask_pii=true로 텍스트 필드 PII 마스킹 가능 (5,000행 이하 — Presidio 호출 비용 가드) - 버전의
pii_masked는 서버가 적재 이력으로 판정합니다 — 해당 snapshot까지의 모든 행 추가 적재가 마스킹된 경우에만 true (요청의 자기신고 값은 무시) - export 응답의
dataset_version_uri를 학습 잡이 MLflow run taggend.dataset_version으로 기록하면 dataset→model 계보가 남습니다 - 버전이 고정한 snapshot 은 유지보수 만료 대상에서 제외됩니다 (ADR-0027) — 행 삭제 후에도 과거 버전 조회에는 데이터가 남는 점에 유의하세요