NVIDIA OpenCodeReasoning: 경쟁 프로그래밍을 위한 최대 규모 추론 기반 코딩 데이터셋
개요
NVIDIA OpenCodeReasoning은 경쟁 프로그래밍을 위한 현재까지 가장 큰 추론 기반 합성 데이터셋입니다. 735,255개 샘플과 28,319개 고유 문제로 구성되어 있으며, Python 언어에 특화되어 지도 학습(SFT)용으로 설계되었습니다.
이 데이터셋은 R1 모델에 의해 생성된 고품질 추론 기반 응답을 포함하며, CodeForces, LeetCode, CodeChef 등 10개 주요 경쟁 프로그래밍 플랫폼의 문제들을 통합했습니다. CC BY 4.0 라이센스로 제공되어 상업적/비상업적 용도 모두에서 자유롭게 활용할 수 있습니다.
데이터셋 규모 및 구성
전체 통계
항목 | 수량 | 설명 |
---|---|---|
총 샘플 수 | 735,255개 | R1 모델이 생성한 추론 기반 솔루션 |
고유 문제 수 | 28,319개 | 경쟁 프로그래밍 문제 |
지원 언어 | Python | 단일 언어로 집중 |
데이터 분할 | 2개 스플릿 | split_0, split_1 |
파일 크기 | 100K-1M | 효율적인 Parquet 형식 |
플랫폼별 데이터 분포
소스 | 문제 수 | 샘플 수 | 비율 |
---|---|---|---|
CodeForces | 10,069 | 386,948 | 52.6% |
CodeChef | 3,796 | 72,925 | 9.9% |
AIZU | 2,123 | 62,476 | 8.5% |
HackerEarth | 2,269 | 59,181 | 8.0% |
AtCoder | 2,043 | 47,222 | 6.4% |
GeeksForGeeks | 2,667 | 37,602 | 5.1% |
Codewars | 2,493 | 34,326 | 4.7% |
Kattis | 1,187 | 13,095 | 1.8% |
HackerRank | 895 | 10,955 | 1.5% |
LeetCode | 777 | 10,525 | 1.4% |
데이터 소스 상세
원본 데이터셋 컬렉션:
제외사항:
- CodeContests와 open-r1/codeforces의 테스트 스플릿 제외
- 데이터 오염 방지를 위한 엄격한 분리
데이터 필드 구조
주요 필드 설명
{
"id": "문제별 고유 식별자",
"input": "경쟁 프로그래밍 문제 설명 (split_0만 해당)",
"output": "R1 모델의 완전한 추론 응답",
"solution": "R1 응답에서 추출한 코드 부분만",
"dataset": "원본 데이터셋명 (예: apps, taco, code_contests)",
"license": "데이터셋 라이센스 (예: mit, apache-2.0, cc-by-4.0)",
"split": "원본 데이터셋의 분할명 (예: train, valid, test)",
"source": "경쟁 프로그래밍 플랫폼명 (예: CodeForces, CodeChef)",
"difficulty": "문제 난이도 레이블",
"index": "APPS/TACO 데이터셋에서 문제 검색용 인덱스 (split_1만)"
}
스플릿 구조
Split_0 (567,850 샘플)
- 완전한 문제 설명 포함
- 즉시 사용 가능한 형태
- 직접적인 SFT 훈련 활용
Split_1 (167,405 샘플)
- 참조 기반 구조 (input = “-“)
- TACO/APPS 데이터셋에서 별도 로드 필요
- 저장 공간 효율성 최적화
사용 방법 및 실습
기본 데이터 로드
from datasets import load_dataset
from tqdm import tqdm
# Split_0 로드 (완전한 문제 포함)
ocr_split_0 = load_dataset("nvidia/OpenCodeReasoning", "split_0")
print(f"Split_0 샘플 수: {len(ocr_split_0['split_0'])}")
# Split_1 로드 (참조 기반)
ocr_split_1 = load_dataset("nvidia/OpenCodeReasoning", "split_1")
print(f"Split_1 샘플 수: {len(ocr_split_1['split_1'])}")
Split_1 문제 내용 복원
# 참조 데이터셋 로드
reference_datasets = {
"taco": load_dataset("BAAI/TACO"),
"apps": load_dataset("codeparrot/apps")
}
# Split_1 문제 내용 복원
def restore_split_1_problems(split_1_data):
restored_data = []
for item in tqdm(split_1_data["split_1"]):
# 입력이 "-"인지 확인
assert item["input"] == "-"
assert item["dataset"] in ["taco", "apps"]
# 원본 데이터셋에서 문제 내용 가져오기
original_dataset = reference_datasets[item["dataset"]]
question = original_dataset[item["split"]][int(item["index"])]["question"]
# 문제 내용 복원
restored_item = item.copy()
restored_item["input"] = question
restored_data.append(restored_item)
return restored_data
# 복원 실행
restored_split_1 = restore_split_1_problems(ocr_split_1)
플랫폼별 데이터 분석
# 플랫폼별 통계 분석
def analyze_platform_distribution(dataset):
platform_stats = {}
for item in dataset:
platform = item['source']
difficulty = item['difficulty']
if platform not in platform_stats:
platform_stats[platform] = {
'total': 0,
'difficulties': {}
}
platform_stats[platform]['total'] += 1
if difficulty not in platform_stats[platform]['difficulties']:
platform_stats[platform]['difficulties'][difficulty] = 0
platform_stats[platform]['difficulties'][difficulty] += 1
return platform_stats
# 분석 실행
stats = analyze_platform_distribution(ocr_split_0['split_0'])
# 결과 출력
for platform, data in stats.items():
print(f"\n{platform}: {data['total']} 샘플")
for diff, count in data['difficulties'].items():
print(f" - {diff}: {count} 개")
R1 모델 기반 추론 생성
추론 품질 특징
R1 모델의 추론 특성:
- 단계별 사고 과정 명시
- 문제 분석과 해결 전략 설명
- 코드 구현과 검증 과정 포함
- 엣지 케이스 고려 및 최적화
추론 응답 구조 예시
# R1 생성 응답 예시 구조
sample_output = """
문제 분석:
이 문제는 배열에서 최대 부분 배열의 합을 구하는 문제입니다.
카데인 알고리즘(Kadane's Algorithm)을 사용하여 O(n) 시간에 해결할 수 있습니다.
해결 전략:
1. 현재까지의 최대 합을 추적
2. 각 원소에서 새로 시작할지 이어갈지 결정
3. 전체 최대값 업데이트
코드 구현:
```python
def max_subarray_sum(arr):
if not arr:
return 0
max_sum = current_sum = arr[0]
for i in range(1, len(arr)):
# 새로 시작하거나 이어서 진행
current_sum = max(arr[i], current_sum + arr[i])
max_sum = max(max_sum, current_sum)
return max_sum
시간 복잡도: O(n) 공간 복잡도: O(1)
테스트 케이스 검증:
- 입력: [-2, 1, -3, 4, -1, 2, 1, -5, 4]
- 출력: 6 (부분 배열 [4, -1, 2, 1]) “””
## 데이터 품질 및 특성
### 품질 관리 과정
1. **원본 데이터 검증**
- 10개 주요 플랫폼에서 검증된 문제
- 중복 문제 제거 및 정규화
- 난이도별 균형 있는 분포
2. **R1 모델 생성 품질**
- 논리적 일관성 검증
- 코드 실행 가능성 확인
- 추론 과정의 명확성 평가
3. **라이센스 호환성**
- 각 플랫폼별 라이센스 확인
- 상업적 사용 가능성 검토
- 재배포 조건 명시
### 난이도 분포 분석
```python
# 난이도별 분포 시각화
def analyze_difficulty_distribution(dataset):
difficulty_counts = {}
for item in dataset:
difficulty = item['difficulty']
if difficulty not in difficulty_counts:
difficulty_counts[difficulty] = 0
difficulty_counts[difficulty] += 1
# 정렬된 결과 반환
return sorted(difficulty_counts.items(), key=lambda x: x[1], reverse=True)
# 실행 및 출력
diff_stats = analyze_difficulty_distribution(ocr_split_0['split_0'])
print("난이도별 분포:")
for difficulty, count in diff_stats:
percentage = (count / len(ocr_split_0['split_0'])) * 100
print(f"- {difficulty}: {count:,} 개 ({percentage:.1f}%)")
활용 사례 및 응용
SFT 모델 훈련
# SFT 훈련을 위한 데이터 전처리
def prepare_sft_data(dataset):
sft_samples = []
for item in dataset:
# 표준 프롬프트 형식으로 변환
prompt = f"다음 프로그래밍 문제를 해결하세요:\n\n{item['input']}"
response = item['output']
sft_sample = {
'prompt': prompt,
'response': response,
'metadata': {
'source': item['source'],
'difficulty': item['difficulty'],
'dataset': item['dataset']
}
}
sft_samples.append(sft_sample)
return sft_samples
# SFT 데이터 준비
sft_data = prepare_sft_data(ocr_split_0['split_0'])
print(f"SFT 훈련 샘플 준비 완료: {len(sft_data)} 개")
코드 생성 모델 평가
# 생성된 코드 품질 평가
def evaluate_code_quality(dataset, sample_size=100):
import ast
import random
samples = random.sample(list(dataset), sample_size)
quality_metrics = {
'syntactically_valid': 0,
'has_main_function': 0,
'handles_input': 0,
'has_comments': 0
}
for item in samples:
solution = item['solution']
try:
# 구문 유효성 검사
ast.parse(solution)
quality_metrics['syntactically_valid'] += 1
except SyntaxError:
continue
# 추가 품질 지표 검사
if 'def ' in solution:
quality_metrics['has_main_function'] += 1
if 'input()' in solution or 'sys.stdin' in solution:
quality_metrics['handles_input'] += 1
if '#' in solution:
quality_metrics['has_comments'] += 1
# 백분율로 변환
for metric in quality_metrics:
quality_metrics[metric] = (quality_metrics[metric] / sample_size) * 100
return quality_metrics
# 품질 평가 실행
quality_report = evaluate_code_quality(ocr_split_0['split_0'])
print("코드 품질 평가 결과:")
for metric, percentage in quality_report.items():
print(f"- {metric}: {percentage:.1f}%")
OpenCodeReasoning 모델 시리즈
사전 훈련된 모델
NVIDIA는 이 데이터셋을 기반으로 여러 모델을 공개했습니다:
모델 | 크기 | 주요 특징 |
---|---|---|
OpenCodeReasoning-Nemotron-7B | 7B | 효율적인 중급 크기 모델 |
OpenCodeReasoning-Nemotron-32B | 32B | 최고 성능 대형 모델 |
커뮤니티 파인 튜닝 모델
218개 이상의 파생 모델이 이 데이터셋으로 훈련되었습니다:
- SVECTOR-CORPORATION/Spec-Coder-4b-V1: 11.3K 다운로드
- Mungert/OpenCodeReasoning-Nemotron-32B-IOI-GGUF: GGUF 양자화 버전
- ertghiu256/qwen3-4b-code-reasoning: Qwen 기반 파인튜닝
기술적 세부사항
데이터 처리 파이프라인
# 데이터 전처리 파이프라인 예시
class OpenCodeReasoningProcessor:
def __init__(self):
self.platforms = [
'CodeForces', 'CodeChef', 'LeetCode', 'AtCoder',
'HackerRank', 'HackerEarth', 'AIZU', 'Kattis',
'Codewars', 'GeeksForGeeks'
]
def load_raw_problems(self):
"""원본 문제 데이터 로드"""
problems = {}
for platform in self.platforms:
problems[platform] = self.fetch_platform_problems(platform)
return problems
def generate_solutions_with_r1(self, problems):
"""R1 모델로 솔루션 생성"""
solutions = []
for platform, problem_list in problems.items():
for problem in problem_list:
solution = self.r1_generate_solution(problem)
solutions.append({
'problem': problem,
'solution': solution,
'platform': platform
})
return solutions
def quality_filter(self, solutions):
"""품질 필터링 적용"""
filtered = []
for item in solutions:
if self.validate_solution(item['solution']):
filtered.append(item)
return filtered
def export_to_parquet(self, data, filename):
"""Parquet 형식으로 내보내기"""
import pandas as pd
df = pd.DataFrame(data)
df.to_parquet(filename, compression='snappy')
# 사용 예시
processor = OpenCodeReasoningProcessor()
# raw_problems = processor.load_raw_problems()
# solutions = processor.generate_solutions_with_r1(raw_problems)
# filtered_solutions = processor.quality_filter(solutions)
# processor.export_to_parquet(filtered_solutions, 'opencode_reasoning.parquet')
저장 형식 및 최적화
- 형식: Parquet with Snappy 압축
- 스키마: Apache Arrow 호환
- 압축률: 약 60-70% 크기 절약
- 접근 성능: 컬럼형 저장으로 빠른 쿼리
라이센스 및 사용 조건
CC BY 4.0 라이센스
허용사항:
- ✅ 상업적 사용: 자유로운 상업적 활용
- ✅ 수정: 데이터 변경 및 가공 가능
- ✅ 배포: 원본 및 수정본 재배포 허용
- ✅ 사적 사용: 개인/조직 내부 사용
의무사항:
- 📝 저작자 표시: NVIDIA 개발자 명시 필요
- 📝 라이센스 고지: CC BY 4.0 라이센스 표시
- 📝 변경사항 표시: 수정 시 변경사항 명시
개별 데이터셋 라이센스 주의사항
중요: 각 원본 데이터셋의 라이센스도 확인해야 합니다:
# 라이센스 확인 코드
def check_dataset_licenses(dataset):
license_distribution = {}
for item in dataset:
license_type = item['license']
dataset_name = item['dataset']
if license_type not in license_distribution:
license_distribution[license_type] = []
if dataset_name not in license_distribution[license_type]:
license_distribution[license_type].append(dataset_name)
return license_distribution
# 라이센스 분포 확인
licenses = check_dataset_licenses(ocr_split_0['split_0'])
print("데이터셋별 라이센스 분포:")
for license_type, datasets in licenses.items():
print(f"- {license_type}: {', '.join(datasets)}")
성능 벤치마킹
평가 메트릭
- 코드 정확성: 테스트 케이스 통과율
- 추론 품질: 설명의 논리적 일관성
- 실행 효율성: 시간/공간 복잡도 최적화
- 가독성: 코드 스타일 및 주석 품질
벤치마크 결과 예시
# 성능 평가 프레임워크
class CodeReasoningEvaluator:
def __init__(self, dataset):
self.dataset = dataset
self.test_cases = self.prepare_test_cases()
def evaluate_correctness(self, model_output, expected_output):
"""코드 정확성 평가"""
try:
# 코드 실행 및 결과 비교
result = self.execute_code(model_output)
return result == expected_output
except Exception as e:
return False
def evaluate_reasoning_quality(self, reasoning_text):
"""추론 품질 평가"""
quality_score = 0
# 단계별 설명 존재 여부
if "단계" in reasoning_text or "Step" in reasoning_text:
quality_score += 25
# 복잡도 분석 포함 여부
if "복잡도" in reasoning_text or "complexity" in reasoning_text:
quality_score += 25
# 테스트 케이스 언급 여부
if "테스트" in reasoning_text or "test" in reasoning_text:
quality_score += 25
# 엣지 케이스 고려 여부
if "엣지" in reasoning_text or "edge case" in reasoning_text:
quality_score += 25
return quality_score
def run_evaluation(self, sample_size=1000):
"""전체 평가 실행"""
import random
samples = random.sample(list(self.dataset), sample_size)
results = {
'correctness': [],
'reasoning_quality': [],
'avg_solution_length': 0
}
total_length = 0
for item in samples:
# 정확성 평가 (여기서는 구문 유효성으로 대체)
try:
compile(item['solution'], '<string>', 'exec')
results['correctness'].append(1)
except:
results['correctness'].append(0)
# 추론 품질 평가
quality = self.evaluate_reasoning_quality(item['output'])
results['reasoning_quality'].append(quality)
# 솔루션 길이
total_length += len(item['solution'])
# 평균 계산
results['avg_correctness'] = sum(results['correctness']) / len(results['correctness'])
results['avg_reasoning_quality'] = sum(results['reasoning_quality']) / len(results['reasoning_quality'])
results['avg_solution_length'] = total_length / len(samples)
return results
# 평가 실행 예시
# evaluator = CodeReasoningEvaluator(ocr_split_0['split_0'])
# results = evaluator.run_evaluation()
# print(f"평균 정확성: {results['avg_correctness']:.2%}")
# print(f"평균 추론 품질: {results['avg_reasoning_quality']:.1f}/100")
향후 발전 방향
데이터셋 확장 계획
- 다국어 지원
- Python 외 Java, C++, JavaScript 추가
- 언어별 특성을 고려한 추론 생성
- 언어간 코드 변환 기능
- 실시간 업데이트
- 새로운 경쟁 프로그래밍 문제 추가
- 트렌드 반영한 최신 알고리즘 포함
- 커뮤니티 기여 시스템 구축
- 고급 추론 방법론
- 다단계 추론 과정 강화
- 대안적 솔루션 제시
- 최적화 과정 상세 설명
모델 성능 개선
- 더 강력한 생성 모델
- R1 후속 모델 적용
- 특화된 코드 생성 모델 활용
- 인간 피드백 학습 통합
- 품질 보증 시스템
- 자동화된 코드 검증
- 추론 일관성 검사
- 커뮤니티 리뷰 시스템
결론
NVIDIA OpenCodeReasoning은 경쟁 프로그래밍 분야에서 현재까지 가장 큰 규모의 추론 기반 합성 데이터셋입니다. 735,255개 샘플과 28,319개 고유 문제를 통해 10개 주요 플랫폼의 다양한 프로그래밍 도전을 포괄합니다.
R1 모델 기반의 고품질 추론과 체계적인 데이터 수집 방법론은 이 데이터셋을 코드 생성 AI 개발의 새로운 기준으로 만듭니다. CC BY 4.0 라이센스로 제공되어 교육, 연구, 상업적 활용 모든 분야에서 자유롭게 사용할 수 있습니다.
218개 이상의 파생 모델과 활발한 커뮤니티 활용은 이 데이터셋의 실용성과 품질을 입증합니다. 향후 다국어 지원과 실시간 업데이트를 통해 더욱 발전된 코드 추론 AI 개발의 기반이 될 것으로 기대됩니다.
인용 정보
@article{ahmad2025opencodereasoning,
title={OpenCodeReasoning: Advancing Data Distillation for Competitive Coding},
author={Wasi Uddin Ahmad, Sean Narenthiran, Somshubra Majumdar, Aleksander Ficek, Siddhartha Jain, Jocelyn Huang, Vahid Noroozi, Boris Ginsburg},
year={2025},
eprint={2504.01943},
archivePrefix={arXiv},
primaryClass={cs.CL},
url={https://arxiv.org/abs/2504.01943},
}