프롬프트 기반 생성, 디스틸레이션, Evol-Instruct, Self-Instruct 등 LLM을 활용한 합성 데이터 생성 기법의 원리와 실전 적용법을 다룹니다.
LLM 기반 합성 데이터 생성의 가장 기본적인 방식은 프롬프트 엔지니어링(Prompt Engineering)입니다. 적절히 설계된 프롬프트를 통해 LLM이 원하는 형식과 품질의 데이터를 출력하도록 유도합니다.
효과적인 데이터 생성 프롬프트는 다음 네 가지 요소를 포함해야 합니다.
SYSTEM_PROMPT = """당신은 한국어 NLP 학습 데이터를 생성하는 전문가입니다.
다음 규칙을 반드시 따르세요:
1. 한국어 자연어로 작성합니다.
2. 지시(instruction)는 명확하고 구체적이어야 합니다.
3. 응답(response)은 지시를 충실히 따라야 합니다.
4. 난이도는 [초급/중급/고급] 중 지정된 수준을 따릅니다.
5. 출력은 반드시 JSON 형식으로 합니다."""
USER_PROMPT_TEMPLATE = """다음 주제에 대해 {difficulty} 수준의 지시-응답 쌍 3개를 생성하세요.
주제: {topic}
도메인: {domain}
출력 형식:
[
{{
"instruction": "지시문",
"response": "응답문",
"difficulty": "난이도",
"domain": "도메인"
}}
]"""프롬프트에 Few-shot 예시를 포함하면 생성 품질이 크게 향상됩니다. 일반적으로 2~3개의 고품질 예시가 최적이며, 예시가 너무 많으면 오히려 다양성이 감소합니다.
생성 다양성을 제어하는 핵심 파라미터는 온도(Temperature)입니다.
| 온도 범위 | 특성 | 적합한 용도 |
|---|---|---|
| 0.0~0.3 | 결정적, 일관성 높음 | 정답이 명확한 데이터 (수학, 코드) |
| 0.4~0.7 | 균형 잡힌 다양성 | 일반 지시-응답 쌍 |
| 0.8~1.2 | 높은 다양성, 창의성 | 대화 데이터, 브레인스토밍 |
온도만으로는 다양성을 충분히 확보하기 어렵습니다. Top-p(nucleus sampling), Top-k 등의 샘플링 전략을 함께 조절하면 더 효과적입니다.
디스틸레이션(Distillation)은 대규모 "교사" 모델이 생성한 데이터로 소규모 "학생" 모델을 학습시키는 기법입니다. 합성 데이터 생성의 가장 실용적인 패턴 중 하나로, GPT-4 수준의 모델이 생성한 고품질 데이터로 7B~13B 규모의 효율적인 모델을 학습시킵니다.
응답 디스틸레이션(Response Distillation): Teacher 모델이 다양한 프롬프트에 대해 고품질 응답을 생성합니다. 가장 단순하면서도 효과적인 방식입니다.
import json
from pathlib import Path
from openai import OpenAI
client = OpenAI()
def distill_responses(
instructions: list[str],
teacher_model: str = "gpt-4o",
output_path: str = "distilled_data.jsonl",
) -> None:
"""Teacher 모델로 고품질 응답을 생성하여 저장합니다."""
output_file = Path(output_path)
with output_file.open("a", encoding="utf-8") as f:
for instruction in instructions:
response = client.chat.completions.create(
model=teacher_model,
messages=[
{"role": "user", "content": instruction},
],
temperature=0.7,
max_tokens=2048,
)
data = {
"instruction": instruction,
"response": response.choices[0].message.content,
"teacher_model": teacher_model,
}
f.write(json.dumps(data, ensure_ascii=False) + "\n")추론 과정 디스틸레이션(Reasoning Distillation): Teacher 모델의 추론 과정(Chain-of-Thought)까지 포함하여 디스틸레이션합니다. Student 모델의 추론 능력을 크게 향상시킬 수 있습니다.
디스틸레이션의 효과는 놀라울 정도입니다. Microsoft의 Orca 프로젝트는 GPT-4의 추론 과정을 디스틸레이션하여 13B 모델로도 GPT-3.5 수준의 성능을 달성했습니다. 핵심은 단순한 답변이 아니라 "왜 그런 답변을 했는지"까지 전달하는 것입니다.
Evol-Instruct는 Microsoft Research가 WizardLM 논문에서 제안한 방법으로, 기존 지시문을 LLM을 활용하여 체계적으로 진화시키는 기법입니다. 단순한 지시문에서 출발하여 점진적으로 복잡하고 다양한 지시문을 생성합니다.
1. 깊이 진화(In-Depth Evolving)
기존 지시문에 제약 조건, 추론 단계, 복잡성을 추가하여 더 어려운 버전을 만듭니다.
DEPTH_EVOLUTION_PROMPT = """다음 지시문을 더 복잡하고 어렵게 진화시키세요.
진화 방법 (하나를 선택):
1. 제약 조건 추가: 추가적인 조건이나 제한을 부여합니다.
2. 추론 단계 심화: 더 많은 추론 단계를 요구하도록 만듭니다.
3. 구체성 강화: 더 구체적이고 전문적인 내용을 요구합니다.
4. 동시 처리: 여러 작업을 동시에 수행하도록 요구합니다.
원본 지시문:
{instruction}
진화된 지시문:"""예시를 보겠습니다.
2. 너비 진화(In-Breadth Evolving)
기존 지시문에서 영감을 받되, 완전히 다른 주제나 관점의 새로운 지시문을 생성합니다.
BREADTH_EVOLUTION_PROMPT = """다음 지시문에서 영감을 받아,
같은 난이도이지만 완전히 다른 주제의 새로운 지시문을 생성하세요.
조건:
- 원본과 주제가 겹치지 않아야 합니다.
- 원본과 비슷한 구조와 복잡도를 가져야 합니다.
- 실용적이고 의미 있는 지시문이어야 합니다.
원본 지시문:
{instruction}
새로운 지시문:"""3. 제거 진화(Elimination Evolving)
진화 과정에서 생성된 저품질 지시문을 필터링합니다. LLM 자체를 판별기로 활용하여, 다음 기준에 해당하는 지시문을 제거합니다.
Evol-Instruct의 진화 깊이는 보통 3~5 단계가 적절합니다. 그 이상 진화시키면 지시문이 지나치게 인위적이거나 비현실적으로 변할 수 있습니다.
Self-Instruct는 Stanford의 연구에서 제안된 방법으로, 소수의 시드 태스크에서 출발하여 모델이 스스로 새로운 지시-응답 쌍을 생성하는 부트스트래핑(Bootstrapping) 기법입니다.
Self-Instruct의 핵심 단계는 다음과 같습니다.
1단계: 시드 태스크 준비
인간이 작성한 175개의 고품질 시드 태스크를 준비합니다. 이 시드는 다양한 도메인과 난이도를 포괄해야 합니다.
2단계: 지시문 생성
태스크 풀에서 랜덤으로 몇 개를 샘플링하여 Few-shot 프롬프트를 구성하고, 새로운 지시문을 생성합니다.
3단계: 필터링
ROUGE-L 유사도를 기준으로 기존 태스크와 너무 유사한 지시문을 제거합니다. 일반적으로 ROUGE-L > 0.7인 경우 중복으로 판단합니다.
4단계: 응답 생성
필터링을 통과한 지시문에 대해 모델이 응답을 생성합니다.
5단계: 반복
새로 생성된 지시-응답 쌍을 태스크 풀에 추가하고, 2단계부터 반복합니다.
import random
from rouge_score import rouge_scorer
scorer = rouge_scorer.RougeScorer(["rougeL"], use_stemmer=False)
def is_novel(
new_instruction: str,
existing_instructions: list[str],
threshold: float = 0.7,
) -> bool:
"""새로운 지시문이 기존과 충분히 다른지 판별합니다."""
for existing in existing_instructions:
scores = scorer.score(existing, new_instruction)
if scores["rougeL"].fmeasure > threshold:
return False
return True
def self_instruct_iteration(
task_pool: list[dict],
model_fn,
num_samples: int = 5,
num_generate: int = 3,
) -> list[dict]:
"""Self-Instruct 한 반복을 수행합니다."""
sampled = random.sample(task_pool, min(num_samples, len(task_pool)))
existing_instructions = [t["instruction"] for t in task_pool]
new_tasks = []
# Few-shot 프롬프트 구성
examples = "\n".join(
f"지시: {t['instruction']}\n응답: {t['response']}"
for t in sampled
)
prompt = (
f"다음 예시를 참고하여 새로운 지시-응답 쌍 "
f"{num_generate}개를 생성하세요.\n\n{examples}"
)
generated = model_fn(prompt)
for item in generated:
if is_novel(item["instruction"], existing_instructions):
new_tasks.append(item)
return new_tasks모든 합성 데이터 생성의 출발점은 시드 데이터(Seed Data)입니다. 시드의 품질과 다양성이 전체 합성 데이터의 상한선을 결정합니다.
SEED_TAXONOMY = {
"도메인": ["과학", "기술", "인문", "사회", "예술"],
"난이도": ["초급", "중급", "고급", "전문가"],
"형식": ["설명형", "비교형", "분석형", "절차형", "토론형"],
"길이": ["단답", "중간", "장문"],
}
def generate_seed_matrix(taxonomy: dict) -> list[dict]:
"""택소노미 조합으로 시드 매트릭스를 생성합니다."""
seeds = []
for domain in taxonomy["도메인"]:
for difficulty in taxonomy["난이도"]:
for format_type in taxonomy["형식"]:
seeds.append({
"domain": domain,
"difficulty": difficulty,
"format": format_type,
"instruction": None, # 인간이 채울 부분
})
return seeds시드 데이터 100개의 품질을 높이는 것이, 시드 데이터 1,000개를 대충 만드는 것보다 최종 합성 데이터의 품질에 더 큰 영향을 미칩니다. 시드에 투자하는 시간은 결코 낭비가 아닙니다.
합성 데이터의 가장 큰 약점은 다양성 부족입니다. 생성 모델은 본질적으로 "평균적인" 출력을 선호하므로, 의도적인 다양성 강화 전략이 필요합니다.
생성 시 다양한 페르소나를 부여하여 관점의 다양성을 확보합니다.
PERSONAS = [
"5년 경력의 백엔드 개발자",
"AI 스타트업 CTO",
"컴퓨터과학 대학원생",
"비전공 데이터 분석가",
"시니어 MLOps 엔지니어",
]
def generate_with_persona(instruction: str, persona: str, model_fn) -> str:
"""페르소나를 적용하여 응답을 생성합니다."""
prompt = (
f"당신은 {persona}입니다. "
f"이 관점에서 다음 질문에 답하세요.\n\n{instruction}"
)
return model_fn(prompt)도메인, 난이도, 형식 등의 조건을 체계적으로 조합하여 생성합니다. 앞서 다룬 시드 매트릭스와 결합하면 효과적입니다.
임베딩 공간에서 기존 데이터와 너무 가까운 새 데이터를 제거합니다. 이를 통해 데이터셋 전체의 다양성을 유지합니다.
배치마다 온도를 달리하여 일부는 정확하게, 일부는 창의적으로 생성합니다.
TEMPERATURE_SCHEDULE = [
(0.3, 0.2), # 20%는 낮은 온도 (정확성 우선)
(0.7, 0.5), # 50%는 중간 온도 (균형)
(1.0, 0.2), # 20%는 높은 온도 (다양성 우선)
(1.2, 0.1), # 10%는 매우 높은 온도 (탐색)
]이 장에서는 LLM 기반 합성 데이터 생성의 네 가지 핵심 기법을 살펴보았습니다.
다음 장에서는 이 기법들을 실제 텍스트 데이터 합성에 적용합니다. 지시-응답 쌍, 대화 데이터, 분류/NER 데이터, 다국어 데이터, 코드 데이터까지 구체적인 파이프라인을 구축해 봅니다.
이 글이 도움이 되셨나요?
지시-응답 쌍, 대화 데이터, 분류/NER 학습 데이터, 다국어 데이터, 코드 데이터의 합성 파이프라인을 실전 코드와 함께 구축합니다.
합성 데이터의 정의와 유형, 2026년 합성 데이터가 필수가 된 배경, 데이터 순환 문제와 생태계 전체 지도를 살펴봅니다.
테이블/CSV 합성, JSON/SQL 데이터 생성, 이미지-텍스트 페어 생성, NVIDIA Nemotron 등 멀티모달 합성 데이터 생성 기법을 다룹니다.