

Terjemahan disediakan oleh mesin penerjemah. Jika konten terjemahan yang diberikan bertentangan dengan versi bahasa Inggris aslinya, utamakan versi bahasa Inggris.

# Menerapkan fungsi hadiah
<a name="nova-implementing-reward-functions"></a>

## Ikhtisar
<a name="nova-reward-overview"></a>

Fungsi hadiah (juga disebut pencetak gol atau grader) adalah komponen inti yang mengevaluasi respons model dan memberikan sinyal umpan balik untuk pelatihan. Ini harus diimplementasikan sebagai fungsi Lambda yang menerima respons model dan mengembalikan skor hadiah.

## Format antarmuka
<a name="nova-reward-interface"></a>

Fungsi reward Anda harus menerima dan mengembalikan data dalam format berikut:

**Sampel sampel masukan untuk pelatihan**

```
{  
    "messages": [  
        {  
            "role": "user",  
            "content": "Do you have a dedicated security team?"  
        }  
    ],              
   "reference_answer": {  
       "compliant": "No",  
       "explanation": "As an AI developed by Company, I do not have a traditional security team..."  
    }  
}
```

**Contoh payload untuk hadiah lambda**

Kontainer secara otomatis mengubah data Anda sebelum mengirimnya ke fungsi Lambda Anda dengan:

1. Menghasilkan respons model untuk setiap prompt

1. Menambahkan giliran asisten (respons yang dihasilkan) ke array pesan

1. Menambahkan `id` bidang unik untuk melacak

Fungsi Lambda Anda akan menerima data dalam format yang diubah ini:

```
{    
   "id": "123",  
    "messages": [  
        {  
            "role": "user",  
            "content": "Do you have a dedicated security team?"  
        },  
        {  
            "role": "assistant",  
            "content": "As an AI developed by Amazon, I don not have a dedicated security team..."  
        }  
    ],              
    # Following section will be same as your training dataset sample  
    "reference_answer": {  
        "compliant": "No",  
        "explanation": "As an AI developed by Company, I do not have a traditional security team..."  
    }  
}
```

**Hadiah kontrak Lambda**

```
def lambda_handler(event, context):  
   return lambda_grader(event)  
  
def lambda_grader(samples: list[dict]) -> list[dict]:  
    """  
    Args:  
        samples: List of dictionaries in OpenAI format  
          
        Example input:  
        {     
            "id": "123",  
            "messages": [  
                {  
                    "role": "user",  
                    "content": "Do you have a dedicated security team?"  
                },  
                {  
                    "role": "assistant",  
                    "content": "As an AI developed by Company, I don nott have a dedicated security team..."  
                }  
            ],              
            # This section will be same as your training dataset  
            "reference_answer": {  
                "compliant": "No",  
                "explanation": "As an AI developed by Company, I do not have a traditional security team..."  
            }  
        }  
      
    Returns:  
        List of dictionaries with reward scores:  
        {  
            "id": str,                              # Same id as input sample  
            "aggregate_reward_score": float,        # Overall score for the sample  
            "metrics_list": [                       # OPTIONAL: Component scores  
                {  
                    "name": str,                    # Name of the component score  
                    "value": float,                 # Value of the component score  
                    "type": str                     # "Reward" or "Metric"  
                }  
            ]  
        }  
    """
```

## Bidang input dan output
<a name="nova-reward-fields"></a>

### Bidang input
<a name="nova-reward-input-fields"></a>


| Bidang | Deskripsi | Catatan tambahan | 
| --- | --- | --- | 
| id | Pengidentifikasi unik untuk sampel | Bergema kembali dalam output. Format string | 
| pesan | Riwayat obrolan yang dipesan dalam format OpenAI | Array objek pesan | 
| pesan [] .role | Pembicara pesan | Nilai umum: “pengguna”, “asisten”, “sistem” | 
| pesan [] .content | Konten teks pesan | Tali polos | 
| \*\*metadata | Informasi bentuk bebas untuk membantu penilaian | Objek; bidang opsional yang dilewatkan dari data pelatihan | 

### Bidang output
<a name="nova-reward-output-fields"></a>


| Bidang | Deskripsi | Catatan tambahan | 
| --- | --- | --- | 
| id | Pengidentifikasi yang sama dengan sampel input | Harus cocok dengan masukan | 
| aggregate\_reward\_score | Skor keseluruhan untuk sampel | Float (misalnya, 0,0—1,0 atau rentang yang ditentukan tugas) | 
| metrics\_list | Skor komponen yang membentuk agregat | Array objek metrik | 

## Kendala teknis
<a name="nova-reward-constraints"></a>
+ **Batas batas waktu** - 15 menit waktu eksekusi maksimum per pemanggilan Lambda
+ **Konkurensi** - Harus menangani permintaan `rollout_worker_replicas * 64` bersamaan
+ **Keandalan** - Harus menerapkan penanganan kesalahan yang tepat dan mengembalikan skor yang valid secara konsisten
+ **Kinerja** - Optimalkan untuk eksekusi cepat (detik, bukan menit) untuk memungkinkan pelatihan yang efisien

**Praktik terbaik**
+ Minimalkan panggilan API eksternal
+ Gunakan algoritma dan struktur data yang efisien
+ Menerapkan logika coba lagi untuk kegagalan sementara
+ Cache perhitungan yang dapat digunakan kembali
+ Uji secara menyeluruh sebelum pelatihan untuk memastikan eksekusi bebas bug

## Menggunakan fungsi hadiah khusus
<a name="nova-reward-using-custom"></a>

Menerapkan fungsi hadiah khusus ketika Anda memiliki kriteria evaluasi khusus tugas:
+ **Tentukan kriteria evaluasi** - Tentukan apa yang membuat respons yang baik untuk tugas Anda
+ **Menerapkan fungsi Lambda** - Buat fungsi Lambda mengikuti format antarmuka
+ **Uji secara lokal** - Validasi fungsi Anda mengembalikan skor yang benar untuk input sampel
+ **Terapkan ke AWS** — Menyebarkan Lambda Anda dan perhatikan ARN
+ **Konfigurasikan resep** — Tambahkan Lambda ARN ke bidang resep Anda `reward_lambda_arn`
+ **Uji dengan dataset kecil** — Jalankan RFT dengan data minimal untuk memverifikasi integrasi

## Izin IAM
<a name="nova-reward-iam"></a>

### Izin yang diperlukan
<a name="nova-reward-required-permissions"></a>

Peran SageMaker eksekusi Anda harus memiliki izin untuk menjalankan fungsi Lambda Anda. Tambahkan kebijakan ini ke peran SageMaker eksekusi Anda:

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

### Peran pelaksanaan Lambda
<a name="nova-reward-lambda-role"></a>

Peran eksekusi fungsi Lambda Anda memerlukan izin eksekusi Lambda dasar:

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

Izin tambahan: Jika fungsi Lambda Anda mengakses layanan AWS lain (misalnya, S3 untuk data referensi, DynamoDB untuk logging), tambahkan izin tersebut ke peran eksekusi Lambda.

## Contoh: LLM Sebagai fungsi hadiah Hakim
<a name="nova-reward-llm-judge-example"></a>

Contoh ini menunjukkan penggunaan model Amazon Bedrock sebagai juri untuk mengevaluasi respons model dengan membandingkannya dengan jawaban referensi. Template Lambda ini menyediakan kerangka kerja bagi pelanggan untuk mengimplementasikan panggilan ke Amazon Bedrock untuk permintaan inferensi guna memproses evaluasi penilaian. Fungsi Lambda mempertahankan input/output kontrak yang sama dengan fungsi hadiah lainnya.

### Implementasi
<a name="nova-reward-llm-judge-implementation"></a>

Fungsi Lambda ini mengimplementasikan proses evaluasi dua tahap: `lambda_handler` mengekstrak respons model dan jawaban referensi dari sampel yang masuk, kemudian fungsi tersebut `lambda_graded` memanggil Amazon Bedrock untuk menilai kesamaan semantik di antara mereka. Implementasinya mencakup penanganan kesalahan yang kuat dengan percobaan ulang otomatis untuk kegagalan sementara dan mendukung format jawaban referensi yang fleksibel (baik format string dan kamus terstruktur).

**Detail implementasi:**
+ **Coba Ulang Logika**: Menerapkan backoff eksponensial (1s, 2s, 4s) untuk pengecualian pembatasan guna menangani batas laju API Bedrock
+ **Penanganan Kesalahan**: Mengembalikan skor 0,0 untuk evaluasi yang gagal daripada menaikkan pengecualian
+ **Penilaian Deterministik**: Menggunakan suhu = 0,0 untuk memastikan skor yang konsisten di seluruh evaluasi
+ **Format Referensi Fleksibel**: Secara otomatis menangani jawaban referensi string dan kamus
+ **Penjepitan Skor**: Memastikan semua skor berada dalam kisaran [0,0, 1,0] yang valid
+ **Model Agnostik**: Ubah JUDGE\_MODEL\_ID untuk menggunakan model Amazon Bedrock apa pun (Nova, Llama, Mistral, dll.)

```
"""  
LLM Judge Lambda POC - Working implementation using Amazon Bedrock  
"""  
  
import json  
import time  
import boto3  
  
bedrock_runtime = boto3.client('bedrock-runtime', region_name='us-east-1')  
JUDGE_MODEL_ID = "anthropic.claude-3-5-sonnet-20240620-v1:0"  
SYSTEM_PROMPT = "You must output ONLY a number between 0.0 and 1.0. No explanations, no text, just the number."  
  
JUDGE_PROMPT_TEMPLATE = """Compare the following two responses and rate how similar they are on a scale of 0.0 to 1.0, where:  
- 1.0 means the responses are semantically equivalent (same meaning, even if worded differently)  
- 0.5 means the responses are partially similar  
- 0.0 means the responses are completely different or contradictory  
  
Response A: {response_a}  
  
Response B: {response_b}  
  
Output ONLY a number between 0.0 and 1.0. No explanations."""  
  
  
def lambda_graded(response_a: str, response_b: str, max_retries: int = 3) -> float:  
    """Call Bedrock to compare responses and return similarity score."""  
    prompt = JUDGE_PROMPT_TEMPLATE.format(response_a=response_a, response_b=response_b)  
      
    for attempt in range(max_retries):  
        try:  
            response = bedrock_runtime.converse(  
                modelId=JUDGE_MODEL_ID,  
                messages=[{"role": "user", "content": [{"text": prompt}]}],  
                system=[{"text": SYSTEM_PROMPT}],  
                inferenceConfig={"temperature": 0.0, "maxTokens": 10}  
            )  
            print(f"Bedrock call successful: {response}")  
            output = response['output']['message']['content'][0]['text'].strip()  
            score = float(output)  
            print(f"Score parsed: {score}")  
            return max(0.0, min(1.0, score))  
                  
        except Exception as e:  
            if "ThrottlingException" in str(e) and attempt < max_retries - 1:  
                time.sleep(2 ** attempt)  
            else:  
                print(f"Bedrock call failed: {e}")  
                return None  
    return None  
  
  
def lambda_handler(event, context):  
    """AWS Lambda handler - processes samples from RFTEvalInvoker."""  
    try:  
        samples = event if isinstance(event, list) else [event]  
        results = []  
          
        for sample in samples:  
            sample_id = sample.get("id", "unknown")  
            messages = sample.get("messages", [])  
              
            # Extract assistant response (response A)  
            response_a = ""  
            for msg in messages:  
                if msg.get("role") in ["assistant", "nova_assistant"]:  
                    response_a = msg.get("content", "")  
                    break  
              
            # Extract reference answer from root level (no longer in metadata)  
            reference_answer = sample.get("reference_answer", "")  
              
            # Handle both string and dict reference_answer formats  
            if isinstance(reference_answer, dict):  
                # If reference_answer is a dict, extract the explanation or compliant field  
                response_b = reference_answer.get("explanation", reference_answer.get("compliant", ""))  
            else:  
                response_b = reference_answer  
              
            if not response_a or not response_b:  
                results.append({  
                    "id": sample_id,  
                    "aggregate_reward_score": 0.0,  
                    "metrics_list": [{"name": "similarity_score", "value": 0.0, "type": "Metric"}]  
                })  
                continue  
              
            # Get similarity score  
            score = lambda_graded(response_a, response_b)  
              
            results.append({  
                "id": sample_id,  
                "aggregate_reward_score": score,  
                "metrics_list": [  
                    {  
                        "name": "similarity_score",  
                        "value": score,  
                        "type": "Metric"  
                    }  
                ]  
            })  
          
        return {"statusCode": 200, "body": json.dumps(results)}  
          
    except Exception as e:  
        print(f"Error: {e}")  
        return {"statusCode": 500, "body": json.dumps({"error": str(e)})}
```

### Format input
<a name="nova-reward-llm-judge-input"></a>

Lambda menerima format input yang sama dengan fungsi reward lainnya:

```
{  
    "id": "sample-001",  
    "messages": [  
        {  
            "role": "user",  
            "content": "Do you have a dedicated security team?"  
        },  
        {  
            "role": "assistant",  
            "content": "As an AI developed by Amazon, I don't have a dedicated security team..."  
        }  
    ],  
    "reference_answer": {  
        "compliant": "No",  
        "explanation": "As an AI developed by Company, I do not have a traditional security team..."  
    },  
    "my_custom_field": "custom_value"  
}
```

### Format output
<a name="nova-reward-llm-judge-output"></a>

```
{  
    "id": "sample-001",  
    "aggregate_reward_score": 0.85,  
    "metrics_list": [  
        {  
            "name": "similarity_score",  
            "value": 0.85,  
            "type": "Metric"  
        }  
    ]  
}
```

### Pertimbangan deployment
<a name="nova-reward-llm-judge-deployment"></a>

Anda mungkin juga perlu menyesuaikan template prompt dan parameter inferensi berdasarkan kemampuan model dan format API yang Anda pilih.
+ **Izin IAM: Peran** eksekusi Lambda harus memiliki `bedrock:InvokeModel` izin untuk model yang Anda pilih
+ **Timeout**: Setel batas waktu Lambda setidaknya 60 detik untuk mengakomodasi latensi API Bedrock dan percobaan ulang
+ **Wilayah**: Terapkan di wilayah tempat model Bedrock pilihan Anda tersedia
+ **Biaya**: Pantau penggunaan API Bedrock karena setiap evaluasi membuat satu panggilan API per sampel
+ **Throughput**: Untuk evaluasi skala besar, mintalah peningkatan kuota Bedrock untuk menghindari pembatasan

**Meningkatkan Throughput Batuan Dasar**

Jika Anda mengalami pelambatan selama evaluasi, tingkatkan kuota model Bedrock Anda:
+ Arahkan ke konsol AWS Service Quotas
+ Cari “Bedrock” dan pilih wilayah Anda
+ Temukan kuota untuk model yang Anda pilih (misalnya, “Doa per menit untuk Claude 3.5 Soneta”)
+ Klik “Minta peningkatan kuota” dan tentukan throughput yang Anda inginkan
+ Berikan pembenaran untuk kenaikan (misalnya, “beban kerja evaluasi RFT”)

Logika coba ulang bawaan Lambda menangani pelambatan sesekali, tetapi evaluasi volume tinggi yang berkelanjutan memerlukan peningkatan kuota yang sesuai.

**Kebijakan IAM yang Diperlukan:**

```
{  
    "Version": "2012-10-17",		 	 	   
    "Statement": [  
        {  
            "Effect": "Allow",  
            "Action": [  
                "bedrock:InvokeModel"  
            ],  
            "Resource": "arn:aws:bedrock:*::foundation-model/*"  
        }  
    ]  
}
```