View a markdown version of this page

Implementación de funciones de recompensas - Amazon Nova

Implementación de funciones de recompensas

Descripción general

La función de recompensas (también llamada puntuador o calificador) es el componente principal que evalúa las respuestas del modelo y proporciona señales de comentarios para el entrenamiento. Debe implementarse como una función de Lambda que acepte las respuestas del modelo y devuelva las puntuaciones de recompensas.

Formato de la interfaz

La función de recompensas debe aceptar y devolver datos en el formato siguiente:

Ejemplo de entrada para el entrenamiento

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

Ejemplo de carga útil para la función de Lambda de recompensas

El contenedor transforma automáticamente los datos antes de enviarlos a la función de Lambda de la siguiente manera:

  1. Genera una respuesta del modelo para cada petición.

  2. Anexa el turno del asistente (respuesta generada) a la matriz de mensajes.

  3. Agrega un campo id único para el seguimiento.

La función de Lambda recibirá datos en este formato transformado:

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

Contrato de Lambda de recompensas

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

Campos de entrada y salida

Campos de entrada

Campo Descripción Notas adicionales
id Identificador único para la muestra Se vuelve a reflejar en la salida. Formato de la cadena
Mensajes Historial de chat ordenado en formato OpenAI Matriz de objetos de mensaje
messages[].role Hablante del mensaje Valores comunes: “usuario”, “asistente”, “sistema”
messages[].content Contenido del texto del mensaje Cadena sin formato
**metadatos Información en formato libre para facilitar la calificación Objeto; campos opcionales transferidos de los datos de entrenamiento

Campos de salida

Campo Descripción Notas adicionales
id El mismo identificador que en la muestra de entrada Debe coincidir con la entrada
aggregate_reward_score Puntuación general de la muestra Flotante (por ejemplo, entre 0,0 y 1,0 o un rango definido por la tarea)
metrics_list Puntuaciones de los componentes que forman el agregado Matriz de objetos métricos

Restricciones técnicas

  • Límite de tiempo de espera: dispone de 15 minutos de tiempo máximo de ejecución por invocación a Lambda.

  • Simultaneidad: debe gestionar solicitudes simultáneas de rollout_worker_replicas * 64.

  • Fiabilidad: debe implementar una gestión de errores adecuada y devolver puntuaciones válidas de manera coherente.

  • Rendimiento: optimice para una ejecución rápida (segundos, no minutos) que permita un entrenamiento eficiente.

Prácticas recomendadas

  • Minimice las llamadas a la API externa.

  • Utilice algoritmos y estructuras de datos eficientes.

  • Implemente una lógica de reintento para los errores transitorios.

  • Almacene en la memoria caché los cálculos reutilizables.

  • Lleve a cabo pruebas exhaustivas antes del entrenamiento para garantizar una ejecución sin errores.

Uso de funciones de recompensas personalizadas

Implemente funciones de recompensas personalizadas cuando tenga criterios de evaluación específicos para cada tarea:

  • Defina los criterios de evaluación: determine qué es lo que constituye una buena respuesta para su tarea.

  • Implemente la función de Lambda: cree una función de Lambda según el formato de interfaz.

  • Pruebe localmente: valide que la función devuelva las puntuaciones correctas para las entradas de muestra.

  • Implemente en AWS: implemente la función de Lambda y anote el ARN.

  • Configure la fórmula: agregue el ARN de Lambda al campo de reward_lambda_arn de la fórmula

  • Lleve a cabo pruebas con un conjunto de datos pequeño: ejecute el RFT con un mínimo de datos para verificar la integración.

Permisos de IAM

Permisos necesarios

El rol de ejecución de SageMaker debe tener permisos para invocar la función de Lambda. Agregue esta política al rol de ejecución de SageMaker:

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

Rol de ejecución de Lambda

El rol de ejecución de una función de Lambda necesita permisos de ejecución de Lambda básicos:

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

Permisos adicionales: si la función de Lambda accede a otros servicios de AWS (por ejemplo, S3 para los datos de referencia o DynamoDB para el registro), agregue esos permisos al rol de ejecución de Lambda.

Ejemplo: función de recompensas de LLM como juez

En este ejemplo, se muestra el uso de los modelos de Amazon Bedrock como jueces para evaluar las respuestas de los modelos al compararlas con las respuestas de referencia. Esta plantilla de Lambda proporciona un marco para que los clientes implementen llamadas a Amazon Bedrock para solicitudes de inferencia a fin de procesar las evaluaciones de los jueces. La función de Lambda mantiene el mismo contrato de entrada/salida que otras funciones de recompensas.

Implementación

Esta función de Lambda implementa un proceso de evaluación en dos etapas: lambda_handler extrae las respuestas del modelo y las respuestas de referencia de las muestras entrantes y, a continuación, la función lambda_graded llama a Amazon Bedrock para puntuar la similitud semántica entre ellas. La implementación incluye una sólida gestión de errores con reintentos automáticos para los errores transitorios y admite formatos de respuesta de referencia flexibles (tanto en formato de cadena como en formato de diccionario estructurado).

Detalles de la implementación:

  • Lógica de reintento: implementa un retroceso exponencial (1, 2 o 4 segundos) para limitar las excepciones a fin de gestionar los límites de frecuencia de la API de Bedrock.

  • Gestión de errores: devuelve una puntuación de 0,0 para las evaluaciones fallidas, en lugar de generar excepciones.

  • Puntuación determinista: utiliza una temperatura igual a 0,0 para garantizar la coherencia de las puntuaciones en todas las evaluaciones.

  • Formato de referencia flexible: gestiona automáticamente las respuestas de cadena y de referencia del diccionario.

  • Acotación de puntuaciones: garantiza que todas las puntuaciones estén dentro de un rango válido [0,0, 1,0].

  • Independencia del modelo: cambie JUDGE_MODEL_ID para usar cualquier modelo de 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)})}

Formato de entrada

La función de Lambda recibe el mismo formato de entrada que otras funciones de recompensas:

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

Formato de salida

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

Consideraciones sobre la implementación

Es posible que también tenga que ajustar la plantilla de la petición y los parámetros de inferencia en función de las capacidades del modelo elegido y el formato de la API.

  • Permisos de IAM: el rol de ejecución de Lambda debe tener el permiso bedrock:InvokeModel para el modelo elegido.

  • Tiempo de espera: establezca el tiempo de espera de Lambda en al menos 60 segundos para adaptarse a la latencia y los reintentos de la API de Bedrock.

  • Región: implemente en una región en la que esté disponible el modelo de Bedrock que haya elegido.

  • Costo: supervise el uso de la API de Bedrock, ya que cada evaluación hace una llamada a la API por muestra.

  • Rendimiento: para las evaluaciones a gran escala, solicite un aumento de las cuotas de Bedrock para evitar la limitación.

Aumento del rendimiento de Bedrock

Si experimenta limitaciones durante la evaluación, aumente las cuotas del modelo de Bedrock:

  • Vaya a la consola de AWS Service Quotas.

  • Busque “Bedrock” y seleccione la región.

  • Busque la cuota para el modelo que haya elegido (por ejemplo, “Invocaciones por minuto para Claude 3.5 Sonnet”).

  • Haga clic en “Solicitar aumento de cuota” y especifique el rendimiento deseado.

  • Justifique el aumento (por ejemplo, “carga de trabajo de evaluación del RFT”).

La lógica de reintentos integrada de Lambda permite controlar las limitaciones ocasionales, pero las evaluaciones sostenidas de gran volumen requieren un aumento adecuado de las cuotas.

Política de IAM obligatoria:

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