Mettre en œuvre des fonctions de récompense - Amazon SageMaker AI

Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.

Mettre en œuvre des fonctions de récompense

Présentation de

La fonction de récompense (également appelée scorer ou grader) est l'élément central qui évalue les réponses du modèle et fournit des signaux de feedback pour l'entraînement. Elle doit être implémentée en tant que fonction Lambda qui accepte les réponses du modèle et renvoie des scores de récompense.

Format d'interface

Votre fonction de récompense doit accepter et renvoyer les données au format suivant :

Exemple d'échantillon d'entrée pour la formation

{ "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..." } }

Exemple de charge utile pour le Reward Lambda

Le conteneur transforme automatiquement vos données avant de les envoyer à votre fonction Lambda en :

  1. Génération d'un modèle de réponse pour chaque invite

  2. Ajouter le tour de l'assistant (réponse générée) au tableau des messages

  3. Ajouter un id champ unique pour le suivi

Votre fonction Lambda recevra les données dans ce format transformé :

{ "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..." } }

Contrat Reward 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" } ] } """

Champs d'entrée et de sortie

Champs de saisie

Champ Description Informations complémentaires
id Identifiant unique pour l'échantillon Retourné en écho dans la sortie. Format de chaîne
messages Historique des discussions ordonné au format OpenAI Tableau d'objets de message
messages [] .role Intervenant du message Valeurs communes : « utilisateur », « assistant », « système »
messages [] .content Contenu textuel du message Chaîne de texte brut
**métadonnées Informations sous forme libre pour faciliter le classement Objet ; champs facultatifs transmis à partir des données d'entraînement

Champs de sortie

Champ Description Informations complémentaires
id Identifiant identique à celui de l'échantillon d'entrée Doit correspondre à l'entrée
score de récompense agrégé Note globale pour l'échantillon Valeur flottante (par exemple, 0,0-1,0 ou plage définie par la tâche)
liste_métriques Scores des composants qui constituent l'agrégat Tableau d'objets métriques

Contraintes techniques

  • Limite de délai d'exécution : 15 minutes maximum par appel Lambda

  • Concurrence — Doit gérer les demandes rollout_worker_replicas * 64 simultanées

  • Fiabilité — Doit mettre en œuvre une gestion appropriée des erreurs et renvoyer des scores valides de manière cohérente

  • Performances — Optimisation pour une exécution rapide (quelques secondes, et non quelques minutes) afin de permettre un entraînement efficace

Bonnes pratiques

  • Minimiser les appels d'API externes

  • Utiliser des algorithmes et des structures de données efficaces

  • Implémenter une logique de nouvelle tentative pour les échecs transitoires

  • Mettre en cache les calculs réutilisables

  • Effectuez des tests approfondis avant l'entraînement pour garantir une exécution sans bogue

Utilisation de fonctions de récompense personnalisées

Implémentez des fonctions de récompense personnalisées lorsque vous avez des critères d'évaluation spécifiques à une tâche :

  • Définissez les critères d'évaluation — Déterminez ce qui constitue une bonne réponse à votre tâche

  • Implémenter la fonction Lambda — Créez une fonction Lambda selon le format de l'interface

  • Testez localement : validez que votre fonction renvoie des scores corrects pour les échantillons d'entrées

  • Déployer vers AWS : déployez votre Lambda et notez l'ARN

  • Configurer la recette — Ajoutez l'ARN Lambda au champ de votre recette reward_lambda_arn

  • Test avec un petit ensemble de données — Exécutez RFT avec un minimum de données pour vérifier l'intégration

Autorisations IAM

Autorisations requises

Votre rôle SageMaker d'exécution doit être autorisé à appeler votre fonction Lambda. Ajoutez cette politique à votre rôle SageMaker d'exécution :

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

Rôle d’exécution Lambda

Le rôle d'exécution de votre fonction Lambda nécessite des autorisations d'exécution Lambda de base :

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

Autorisations supplémentaires : si votre fonction Lambda accède à d'autres AWS services (par exemple, S3 pour les données de référence, DynamoDB pour la journalisation), ajoutez ces autorisations au rôle d'exécution Lambda.

Exemple : fonction de récompense LLM As a Judge

Cet exemple montre comment utiliser les modèles Amazon Bedrock comme juges pour évaluer les réponses des modèles en les comparant aux réponses de référence. Ce modèle Lambda fournit un cadre permettant aux clients de mettre en œuvre des appels à Amazon Bedrock pour des demandes d'inférence afin de traiter les évaluations des juges. La fonction Lambda maintient le même input/output contrat que les autres fonctions de récompense.

Mise en œuvre

Cette fonction Lambda met en œuvre un processus d'évaluation en deux étapes : elle lambda_handler extrait les réponses du modèle et les réponses de référence des échantillons entrants, puis la fonction lambda_graded appelle Amazon Bedrock pour évaluer la similitude sémantique entre elles. La mise en œuvre inclut une gestion robuste des erreurs avec des tentatives automatiques pour les échecs transitoires et prend en charge des formats de réponse de référence flexibles (formats de chaîne et de dictionnaire structuré).

Détails de mise en œuvre :

  • Logique de réessai : implémente un ralentissement exponentiel (1 s, 2, 4 s) pour limiter les exceptions afin de gérer les limites de débit de l'API Bedrock

  • Gestion des erreurs : renvoie un score de 0,0 en cas d'échec des évaluations plutôt que de déclencher des exceptions

  • Notation déterministe : utilise la température = 0,0 pour garantir des scores cohérents entre les évaluations

  • Format de référence flexible : gère automatiquement les réponses de référence sous forme de chaîne et de dictionnaire

  • Limitation des scores : garantit que tous les scores se situent dans une plage valide [0,0, 1,0]

  • Indépendant du modèle : modifiez JUDGE_MODEL_ID pour utiliser n'importe quel modèle Amazon Bedrock (Nova, Llama, Mistral, etc.)

""" 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 d'entrée

Le Lambda reçoit le même format de saisie que les autres fonctions de récompense :

{ "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 de sortie

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

Considérations relatives au déploiement

Vous devrez peut-être également ajuster le modèle d'invite et les paramètres d'inférence en fonction des capacités du modèle que vous avez choisi et du format d'API.

  • Autorisations IAM : le rôle d'exécution Lambda doit être autorisé pour le bedrock:InvokeModel modèle que vous avez choisi

  • Délai d'expiration : définissez le délai Lambda à au moins 60 secondes pour tenir compte de la latence de l'API Bedrock et des nouvelles tentatives

  • Région : Déployez dans une région où le modèle Bedrock que vous avez choisi est disponible

  • Coût : surveillez l'utilisation de l'API Bedrock car chaque évaluation effectue un appel d'API par échantillon

  • Débit : pour les évaluations à grande échelle, demandez des quotas Bedrock accrus pour éviter les ralentissements

Augmenter le débit du substrat rocheux

Si vous rencontrez un ralentissement pendant l'évaluation, augmentez les quotas de votre modèle Bedrock :

  • Accédez à la console AWS Service Quotas

  • Recherchez « Bedrock » et sélectionnez votre région

  • Trouvez le quota pour le modèle que vous avez choisi (par exemple, « Invocations par minute pour Claude 3.5 Sonnet »)

  • Cliquez sur « Demander une augmentation du quota » et spécifiez le débit souhaité

  • Justifiez l'augmentation (par exemple, « charge de travail d'évaluation RFT »)

La logique de relance intégrée au Lambda gère les ralentissements occasionnels, mais les évaluations soutenues de volumes élevés nécessitent des augmentations de quotas appropriées.

Politique IAM requise :

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