개요

NVIDIA OpenCodeReasoning은 경쟁 프로그래밍을 위한 현재까지 가장 큰 추론 기반 합성 데이터셋입니다. 735,255개 샘플28,319개 고유 문제로 구성되어 있으며, Python 언어에 특화되어 지도 학습(SFT)용으로 설계되었습니다.

이 데이터셋은 R1 모델에 의해 생성된 고품질 추론 기반 응답을 포함하며, CodeForces, LeetCode, CodeChef10개 주요 경쟁 프로그래밍 플랫폼의 문제들을 통합했습니다. 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 모델의 추론 특성:

  1. 단계별 사고 과정 명시
  2. 문제 분석과 해결 전략 설명
  3. 코드 구현과 검증 과정 포함
  4. 엣지 케이스 고려 및 최적화

추론 응답 구조 예시

# 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)}")

성능 벤치마킹

평가 메트릭

  1. 코드 정확성: 테스트 케이스 통과율
  2. 추론 품질: 설명의 논리적 일관성
  3. 실행 효율성: 시간/공간 복잡도 최적화
  4. 가독성: 코드 스타일 및 주석 품질

벤치마크 결과 예시

# 성능 평가 프레임워크
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")

향후 발전 방향

데이터셋 확장 계획

  1. 다국어 지원
    • Python 외 Java, C++, JavaScript 추가
    • 언어별 특성을 고려한 추론 생성
    • 언어간 코드 변환 기능
  2. 실시간 업데이트
    • 새로운 경쟁 프로그래밍 문제 추가
    • 트렌드 반영한 최신 알고리즘 포함
    • 커뮤니티 기여 시스템 구축
  3. 고급 추론 방법론
    • 다단계 추론 과정 강화
    • 대안적 솔루션 제시
    • 최적화 과정 상세 설명

모델 성능 개선

  1. 더 강력한 생성 모델
    • R1 후속 모델 적용
    • 특화된 코드 생성 모델 활용
    • 인간 피드백 학습 통합
  2. 품질 보증 시스템
    • 자동화된 코드 검증
    • 추론 일관성 검사
    • 커뮤니티 리뷰 시스템

결론

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}, 
}

참고 자료