RFT 평가 - Amazon SageMaker AI

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

RFT 평가

참고

자체 AWS 환경에서 원격 보상 함수를 통한 평가는 Nova Forge 고객인 경우에만 사용할 수 있습니다.

중요

rl_env 구성 필드는 교육이 아닌 평가에만 사용됩니다. 훈련 중에 reward_lambda_arn (한 번 회전) 또는 BYOO 인프라와 rollout.delegate: true (다중 회전)를 사용하여 보상 함수를 구성합니다.

RFT 평가란 무엇입니까?

RFT 평가를 사용하면 강화 학습 훈련 전, 중 또는 후에 사용자 지정 보상 함수를 사용하여 모델의 성능을 평가할 수 있습니다. 미리 정의된 지표를 사용하는 표준 평가와 달리 RFT 평가를 사용하면 특정 요구 사항에 따라 모델 출력을 채점하는 Lambda 함수를 통해 고유한 성공 기준을 정의할 수 있습니다.

RFT로 평가하는 이유는 무엇입니까?

RL 미세 조정 프로세스에 다음이 있는지 확인하려면 평가가 중요합니다.

  • 특정 사용 사례 및 인적 값에 맞게 모델 조정 개선

  • 주요 작업에 대한 모델 기능을 유지 관리하거나 개선했습니다.

  • 사실성 감소, 세부 정보 증가 또는 다른 작업의 성능 저하와 같은 의도하지 않은 부작용 방지

  • 보상 함수에서 정의한 사용자 지정 성공 기준 충족

RFT 평가를 사용해야 하는 경우

다음 시나리오에서 RFT 평가를 사용합니다.

  • RFT 훈련 전: 평가 데이터 세트에 대한 기준 지표 설정

  • RFT 훈련 중: 중간 체크포인트를 사용하여 훈련 진행 상황 모니터링

  • RFT 훈련 후: 최종 모델이 요구 사항을 충족하는지 확인

  • 모델 비교: 일관된 보상 기준을 사용하여 여러 모델 버전 평가

참고

사용자 지정 도메인별 지표가 필요한 경우 RFT 평가를 사용합니다. 범용 평가(정확성, 복잡성, BLEU)의 경우 표준 평가 방법을 사용합니다.

데이터 형식 요구 사항

입력 데이터 구조

RFT 평가 입력 데이터는 OpenAI 강화 미세 조정 형식을 따라야 합니다. 각 예제는 다음을 포함하는 JSON 객체입니다.

  • messages: systemuser 역할과의 대화 전환 배열

  • 기타 선택적 메타데이터, 예: reference_answer

데이터 형식 예제

다음 예제에서는 필수 형식을 보여줍니다.

{ "messages": [ { "role": "user", "content": [ { "type": "text", "text": "Solve for x. Return only JSON like {\"x\": <number>}. Equation: 2x + 5 = 13" } ] } ], "reference_answer": { "x": 4 } }
현재 제한 사항

RFT 평가에 적용되는 제한 사항은 다음과 같습니다.

  • 텍스트만 해당: 멀티모달 입력(이미지, 오디오, 비디오)은 지원되지 않습니다.

  • 단일 턴 대화: 단일 사용자 메시지만 지원(다중 턴 대화 없음)

  • JSON 형식: 입력 데이터는 JSONL 형식이어야 합니다(행당 JSON 객체 1개).

  • 모델 출력: 지정된 모델에서 생성된 완료 시 평가가 수행됩니다.

평가 레시피 준비

샘플 레시피 구성

다음 예제에서는 전체 RFT 평가 레시피를 보여줍니다.

run: name: nova-lite-rft-eval-job model_type: amazon.nova-lite-v1:0:300k model_name_or_path: s3://escrow_bucket/model_location # [MODIFIABLE] S3 path to your model or model identifier replicas: 1 # [MODIFIABLE] For SageMaker Training jobs only; fixed for HyperPod jobs data_s3_path: "" # [REQUIRED FOR HYPERPOD] Leave empty for SageMaker Training jobs output_s3_path: "" # [REQUIRED] Output artifact S3 path for evaluation results evaluation: task: rft_eval # [FIXED] Do not modify strategy: rft_eval # [FIXED] Do not modify metric: all # [FIXED] Do not modify # Inference Configuration inference: max_new_tokens: 8196 # [MODIFIABLE] Maximum tokens to generate top_k: -1 # [MODIFIABLE] Top-k sampling parameter top_p: 1.0 # [MODIFIABLE] Nucleus sampling parameter temperature: 0 # [MODIFIABLE] Sampling temperature (0 = deterministic) top_logprobs: 0 # Evaluation Environment Configuration (NOT used in training) rl_env: reward_lambda_arn: arn:aws:lambda:<region>:<account_id>:function:<reward-function-name>

보상 함수 사전 설정

오픈 소스 verl 라이브러리에서 사용할 RFT lambda와 쉽게 번들링할 수 있는 lambda 계층으로 2개의 사전 설정된 보상 함수(prime_code, prime_math)를 사용할 수 있도록 했습니다.

개요

이러한 사전 설정 함수는 다음에 대한 out-of-the-box 평가 기능을 제공합니다.

  • prime_code: 코드 생성 및 정확성 평가

  • prime_math: 수학적 추론 및 문제 해결 평가

빠른 설정

사전 설정된 보상 함수를 사용하려면:

  1. nova-custom-eval-sdk 릴리스에서 Lambda 계층 다운로드

  2. AWS CLI를 사용하여 Lambda 계층 게시:

    aws lambda publish-layer-version \ --layer-name preset-function-layer \ --description "Preset reward function layer with dependencies" \ --zip-file fileb://universal_reward_layer.zip \ --compatible-runtimes python3.9 python3.10 python3.11 python3.12 \ --compatible-architectures x86_64 arm64
  3. AWS 콘솔에서 Lambda 함수에 계층 추가(사용자 지정 preset-function-layer 계층을 선택하고 AWSSDKPandas-Python312를 추가하여 종속성을 축소)

  4. Lambda 코드에서 가져오기 및 사용:

    from prime_code import compute_score # For code evaluation from prime_math import compute_score # For math evaluation
prime_code 함수

용도: 테스트 사례에 대해 코드를 실행하고 정확성을 측정하여 Python 코드 생성 작업을 평가합니다.

평가의 입력 데이터 세트 형식 예:

{"messages":[{"role":"user","content":"Write a function that returns the sum of two numbers."}],"reference_answer":{"inputs":["3\n5","10\n-2","0\n0"],"outputs":["8","8","0"]}} {"messages":[{"role":"user","content":"Write a function to check if a number is even."}],"reference_answer":{"inputs":["4","7","0","-2"],"outputs":["True","False","True","True"]}}

주요 기능:

  • 마크다운 코드 블록에서 자동 코드 추출

  • 함수 감지 및 호출 기반 테스트

  • 제한 시간 보호를 사용하여 사례 실행 테스트

  • 구문 검증 및 컴파일 검사

  • 트레이스백을 사용한 세부 오류 보고

prime_math 함수

용도: 심볼 수학 지원을 통해 수학 추론 및 문제 해결 기능을 평가합니다.

입력 형식:

{"messages":[{"role":"user","content":"What is the derivative of x^2 + 3x?."}],"reference_answer":"2*x + 3"}

주요 기능:

  • SymPy를 사용한 심볼 수학 평가

  • 여러 응답 형식(LaTeX, 일반 텍스트, 심볼)

  • 수학적 동등성 검사

  • 표현식 정규화 및 간소화

모범 사례

사전 설정된 보상 함수를 사용할 때는 다음 모범 사례를 따르세요.

  • 테스트 사례에 적절한 데이터 형식 사용(통합자 대 문자열, 부울 대 "True")

  • 코드 문제에 명확한 함수 서명 제공

  • 테스트 입력에 엣지 케이스 포함(0, 음수, 빈 입력)

  • 참조 답변에서 수학 표현식의 형식을 일관되게 지정

  • 배포 전에 샘플 데이터로 보상 함수 테스트

보상 함수 생성

Lambda ARN

Lambda ARN에 대해 다음 형식을 참조해야 합니다.

"arn:aws:lambda:*:*:function:*SageMaker*"

Lambda에이 이름 지정 체계가 없는 경우이 오류와 함께 작업이 실패합니다.

[ERROR] Unexpected error: lambda_arn must contain one of: ['SageMaker', 'sagemaker', 'Sagemaker'] when running on SMHP platform (Key: lambda_arn)
Lambda 함수 구조

Lambda 함수는 모델 출력 배치를 수신하고 보상 점수를 반환합니다. 다음은 샘플 구현입니다.

from typing import List, Any import json import re from dataclasses import asdict, dataclass @dataclass class MetricResult: """Individual metric result.""" name: str value: float type: str @dataclass class RewardOutput: """Reward service output.""" id: str aggregate_reward_score: float metrics_list: List[MetricResult] def lambda_handler(event, context): """ Main lambda handler """ return lambda_grader(event) def lambda_grader(samples: list[dict]) -> list[dict]: """ Core grader function """ scores: List[RewardOutput] = [] for sample in samples: print("Sample: ", json.dumps(sample, indent=2)) # Extract components idx = sample.get("id", "no id") if not idx or idx == "no id": print(f"ID is None/empty for sample: {sample}") ground_truth = sample.get("reference_answer") if "messages" not in sample: print(f"Messages is None/empty for id: {idx}") continue if ground_truth is None: print(f"No answer found in ground truth for id: {idx}") continue # Get model's response (last turn is assistant turn) last_message = sample["messages"][-1] if last_message["role"] != "nova_assistant": print(f"Last message is not from assistant for id: {idx}") continue if "content" not in last_message: print(f"Completion text is empty for id: {idx}") continue model_text = last_message["content"] # --- Actual scoring logic (lexical overlap) --- ground_truth_text = _extract_ground_truth_text(ground_truth) # Calculate main score and individual metrics overlap_score = _lexical_overlap_score(model_text, ground_truth_text) # Create two separate metrics as in the first implementation accuracy_score = overlap_score # Use overlap as accuracy fluency_score = _calculate_fluency(model_text) # New function for fluency # Create individual metrics metrics_list = [ MetricResult(name="accuracy", value=accuracy_score, type="Metric"), MetricResult(name="fluency", value=fluency_score, type="Reward") ] ro = RewardOutput( id=idx, aggregate_reward_score=overlap_score, metrics_list=metrics_list ) print(f"Response for id: {idx} is {ro}") scores.append(ro) # Convert to dict format result = [] for score in scores: result.append({ "id": score.id, "aggregate_reward_score": score.aggregate_reward_score, "metrics_list": [asdict(metric) for metric in score.metrics_list] }) return result def _extract_ground_truth_text(ground_truth: Any) -> str: """ Turn the `ground_truth` field into a plain string. """ if isinstance(ground_truth, str): return ground_truth if isinstance(ground_truth, dict): # Common patterns: { "explanation": "...", "answer": "..." } if "explanation" in ground_truth and isinstance(ground_truth["explanation"], str): return ground_truth["explanation"] if "answer" in ground_truth and isinstance(ground_truth["answer"], str): return ground_truth["answer"] # Fallback: stringify the whole dict return json.dumps(ground_truth, ensure_ascii=False) # Fallback: stringify anything else return str(ground_truth) def _tokenize(text: str) -> List[str]: # Very simple tokenizer: lowercase + alphanumeric word chunks return re.findall(r"\w+", text.lower()) def _lexical_overlap_score(model_text: str, ground_truth_text: str) -> float: """ Simple lexical overlap score in [0, 1]: score = |tokens(model) ∩ tokens(gt)| / |tokens(gt)| """ gt_tokens = _tokenize(ground_truth_text) model_tokens = _tokenize(model_text) if not gt_tokens: return 0.0 gt_set = set(gt_tokens) model_set = set(model_tokens) common = gt_set & model_set return len(common) / len(gt_set) def _calculate_fluency(text: str) -> float: """ Calculate a simple fluency score based on: - Average word length - Text length - Sentence structure Returns a score between 0 and 1. """ # Simple implementation - could be enhanced with more sophisticated NLP words = _tokenize(text) if not words: return 0.0 # Average word length normalized to [0,1] range # Assumption: average English word is ~5 chars, so normalize around that avg_word_len = sum(len(word) for word in words) / len(words) word_len_score = min(avg_word_len / 10, 1.0) # Text length score - favor reasonable length responses ideal_length = 100 # words length_score = min(len(words) / ideal_length, 1.0) # Simple sentence structure check (periods, question marks, etc.) sentence_count = len(re.findall(r'[.!?]+', text)) + 1 sentence_ratio = min(sentence_count / (len(words) / 15), 1.0) # Combine scores fluency_score = (word_len_score + length_score + sentence_ratio) / 3 return fluency_score
Lambda 요청 형식

Lambda 함수는 다음 형식으로 데이터를 수신합니다.

[ { "id": "sample-001", "messages": [ { "role": "user", "content": [ { "type": "text", "text": "Do you have a dedicated security team?" } ] }, { "role": "nova_assistant", "content": [ { "type": "text", "text": "As an AI developed by Company, I don't have a dedicated security team in the traditional sense. However, the development and deployment of AI systems like me involve extensive security measures, including data encryption, user privacy protection, and other safeguards to ensure safe and responsible use." } ] } ], "reference_answer": { "compliant": "No", "explanation": "As an AI developed by Company, I do not have a traditional security team. However, the deployment involves stringent safety measures, such as encryption and privacy safeguards." } } ]
참고

메시지 구조에는 입력 데이터 형식과 일치하는 중첩 content 배열이 포함됩니다. 역할이 있는 마지막 메시지에는 모델의 생성된 응답이 nova_assistant 포함됩니다.

Lambda 응답 형식

Lambda 함수는 다음 형식으로 데이터를 반환해야 합니다.

[ { "id": "sample-001", "aggregate_reward_score": 0.75, "metrics_list": [ { "name": "accuracy", "value": 0.85, "type": "Metric" }, { "name": "fluency", "value": 0.90, "type": "Reward" } ] } ]

응답 필드:

  • id: 입력 샘플 ID와 일치해야 합니다.

  • aggregate_reward_score: 전체 점수(일반적으로 0.0~1.0)

  • metrics_list: 다음을 사용한 개별 지표 배열:

    • name: 지표 식별자(예: "정확성", "유창성")

    • value: 지표 점수(일반적으로 0.0~1.0)

    • type: "Metric"(보고용) 또는 "Reward"(교육에 사용됨)

IAM 권한

필수 권한

SageMaker AI 실행 역할에는 Lambda 함수를 호출할 수 있는 권한이 있어야 합니다. SageMaker AI 실행 역할에이 정책을 추가합니다.

{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "lambda:InvokeFunction" ], "Resource": "arn:aws:lambda:region:account-id:function:function-name" } ] }
Lambda 실행 역할

Lambda 함수의 실행 역할에는 기본 Lambda 실행 권한이 필요합니다.

{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents" ], "Resource": "arn:aws:logs:*:*:*" } ] }

추가 권한: Lambda 함수가 다른 AWS 서비스(예: 참조 데이터를 위한 Amazon S3, 로깅을 위한 DynamoDB)에 액세스하는 경우 해당 권한을 Lambda 실행 역할에 추가합니다.

평가 작업 실행

  1. 데이터 준비

    • 데이터 형식 요구 사항에 따라 평가 데이터 형식 지정

    • Amazon S3에 JSONL 파일을 업로드합니다. s3://your-bucket/eval-data/eval_data.jsonl

  2. 레시피 구성

    구성으로 샘플 레시피를 업데이트합니다.

    • 모델 위치로 model_name_or_path 설정

    • 보상 함수 ARNlambda_arn으로 설정

    • 원하는 출력 위치로 output_s3_path 설정

    • 필요에 따라 inference 파라미터 조정

    레시피를 로 저장 rft_eval_recipe.yaml

  3. 평가 실행

    제공된 노트북: Nova 모델 평가 노트북을 사용하여 평가 작업 실행

  4. 진행 상황 모니터링

    다음을 통해 평가 작업을 모니터링합니다.

    • SageMaker AI 콘솔: 작업 상태 및 로그 확인

    • CloudWatch Logs: 세부 실행 로그 보기

    • Lambda 로그: 보상 함수 문제 디버깅

평가 결과 이해

출력 형식

평가 작업은 결과를 지정된 Amazon S3 위치에 JSONL 형식으로 출력합니다. 각 줄에는 하나의 샘플에 대한 평가 결과가 포함됩니다.

{ "id": "sample-001", "aggregate_reward_score": 0.75, "metrics_list": [ { "name": "accuracy", "value": 0.85, "type": "Metric" }, { "name": "fluency", "value": 0.90, "type": "Reward" } ] }
참고

RFT 평가 작업 출력은 Lambda 응답 형식과 동일합니다. 평가 서비스는 Lambda 함수의 응답을 수정 없이 전달하여 보상 계산과 최종 결과 간의 일관성을 보장합니다.

결과 해석

보상 점수 집계:

  • 범위: 일반적으로 0.0(최악)~1.0(가장 좋음)이지만 구현에 따라 다름

  • 용도: 전체 성능을 요약하는 단일 숫자

  • 사용: 모델 비교, 훈련 대비 개선 사항 추적

개별 지표:

  • 지표 유형: 분석을 위한 정보 지표

  • 보상 유형: RFT 훈련 중에 사용되는 지표

  • 해석: 값이 높을수록 일반적으로 더 나은 성능을 나타냅니다(반대 지표를 설계하지 않는 한).

성능 벤치마크

"좋은" 성능을 구성하는 요소는 사용 사례에 따라 달라집니다.

점수 범위

해석

작업

0.8~1.0

우수

배포 준비된 모델

0.6~0.8

양호

사소한 개선이 유용할 수 있음

0.4~0.6

공정

상당한 개선 필요

0.0~0.4

나쁨

훈련 데이터 및 보상 함수 검토

중요

다음은 일반적인 지침입니다. 비즈니스 요구 사항, 기준 모델 성능, 도메인별 제약 조건, 추가 교육의 비용 편익 분석을 기반으로 자체 임계값을 정의합니다.