Implementação de funções de recompensa
Visão geral
A função de recompensa (também chamada de pontuador ou avaliador) é o componente principal que avalia as respostas do modelo e fornece sinais de feedback para o treinamento. Ela deve ser implementada como uma função do Lambda que aceita respostas do modelo e retorna pontuações de recompensa.
Formato da interface
A sua função de recompensa deve aceitar e retornar dados no seguinte formato:
Exemplo de entrada para treinamento
{ "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..." } }
Exemplo de carga útil para a recompensa do Lambda
O contêiner transforma automaticamente seus dados antes de enviá-los para sua função do Lambda ao:
-
Gerar uma resposta de modelo para cada prompt
-
Anexar o turno do assistente (resposta gerada) à matriz de mensagens
-
Adicionar um campo de
idúnico de rastreamento
Sua função do Lambda receberá dados neste 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 recompensa do 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" } ] } """
Campos de entrada e saída
Campos de entrada
| Campo | Descrição | Notas adicionais |
|---|---|---|
| id | Identificador único do exemplo | Ecoou de volta na saída. Formato de string |
| mensagens | Histórico sequencial do chat no formato OpenAI | Matriz de objetos de mensagem |
| messages[].role | Quem fala a mensagem | Valores comuns: “user”, “assistant”, “system” |
| messages[].content | O conteúdo do texto da mensagem | String simples |
| **metadados | Informações de formato livre para auxiliar na classificação | Objeto; campos opcionais dos dados de treinamento |
Campos de saída
| Campo | Descrição | Notas adicionais |
|---|---|---|
| id | Mesmo identificador do exemplo de entrada | Deve corresponder à entrada |
| aggregate_reward_score | Pontuação geral do exemplo | Flutuante (por exemplo, 0,0 a 1,0, ou intervalo definido pela tarefa) |
| metrics_list | Pontuações de componentes que compõem o agregado | Matriz de objetos de métricas |
Restrições técnicas
-
Limite de tempo: 15 minutos de tempo máximo de execução por invocação do Lambda
-
Simultaneidade: deve lidar com solicitações
rollout_worker_replicas * 64simultâneas -
Confiabilidade: deve implementar o tratamento adequado de erros e retornar pontuações válidas de forma consistente
-
Desempenho: otimiza para uma execução rápida (segundos, não minutos) para permitir um treinamento eficiente
Práticas recomendadas
-
Minimize as chamadas de API externas
-
Use algoritmos e estruturas de dados eficientes
-
Implementar a lógica de novas tentativas para falhas transitórias
-
Armazenar em cache cálculos reutilizáveis
-
Testar minuciosamente antes do treinamento para garantir uma execução sem erros
Uso de funções de recompensa personalizadas
Implemente funções de recompensa personalizadas quando você tiver critérios de avaliação específicos da tarefa:
-
Definir critérios de avaliação: determine o que constitui uma boa resposta para sua tarefa
-
Implementar a função do Lambda: crie uma função do Lambda seguindo o formato da interface
-
Testar localmente: valide se sua função retorna as pontuações corretas para as entradas do exemplo
-
Implantar na AWS: implante seu Lambda e anote o ARN
-
Configurar fórmula: adicione o ARN do Lambda ao campo
reward_lambda_arnda sua fórmula -
Testar com um pequeno conjunto de dados: execute o RFT com o mínimo de dados para verificar a integração
permissões do IAM
Permissões obrigatórias
O seu perfil de execução do SageMaker precisa ter as permissões para invocar sua função do Lambda. Adicione esta política ao seu perfil de execução do SageMaker:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "lambda:InvokeFunction" ], "Resource": "arn:aws:lambda:region:account-id:function:function-name" } ] }
Função de execução do Lambda
O perfil de execução de uma função do Lambda precisa de permissões básicas de execução do Lambda:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents" ], "Resource": "arn:aws:logs:*:*:*" } ] }
Permissões adicionais: se a função do Lambda acessar outros serviços da AWS (por exemplo, S3 para dados de referência, DynamoDB para registro em log), adicione essas permissões ao perfil de execução do Lambda.
Exemplo: função de recompensa para LLM como avaliador
Este exemplo demonstra o uso de modelos do Amazon Bedrock como avaliadores para analisar as respostas do modelo comparando-as com as respostas de referência. Esse modelo do Lambda fornece um framework para os clientes implementarem chamadas no Amazon Bedrock de solicitações de inferência para processar as análises dos avaliadores. A função do Lambda mantém o mesmo contrato de entrada/saída que outras funções de recompensa.
Implementação
Essa função do Lambda implementa um processo de avaliação em duas etapas: o lambda_handler extrai as respostas do modelo e as respostas de referência das amostras recebidas e, em seguida, a função lambda_graded chama o Amazon Bedrock para pontuar a semelhança semântica entre elas. A implementação inclui tratamento robusto de erros com novas tentativas automáticas para falhas transitórias e é compatível com formatos flexíveis de resposta de referência (formatos de string e dicionário estruturado).
Detalhes da implantação:
-
Repetir a lógica: implementa o recuo exponencial (1s, 2s, 4s) para controlar a utilização de exceções para lidar com os limites de taxa da API do Bedrock
-
Tratamento de erros: retorna a pontuação de 0,0 para avaliações com falha, em vez de gerar exceções
-
Pontuação determinística: usa temperature = 0,0 para garantir pontuações consistentes em todas as avaliações
-
Formato de referência flexível: processa automaticamente as respostas de referência de texto e dicionário
-
Limitadores de pontuação: garante que todas as pontuações estejam no intervalo válido [0,0, 1,0]
-
Modelo agnóstico: altera JUDGE_MODEL_ID para usar qualquer modelo do 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
O Lambda recebe o mesmo formato de entrada que outras funções de recompensa:
{ "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 saída
{ "id": "sample-001", "aggregate_reward_score": 0.85, "metrics_list": [ { "name": "similarity_score", "value": 0.85, "type": "Metric" } ] }
Considerações de implantação
Talvez você também precise ajustar o modelo do prompt e os parâmetros de inferência com base nos recursos do modelo escolhido e no formato da API.
-
Permissões do IAM: o perfil de execução do Lambda deve ter a permissão
bedrock:InvokeModelpara o modelo escolhido -
Tempo limite: defina o tempo limite do Lambda para pelo menos 60 segundos para acomodar a latência e as novas tentativas da API do Bedrock
-
Região: implante em uma região onde o modelo escolhido do Bedrock esteja disponível
-
Custo: monitore o uso da API do Bedrock à medida que cada avaliação faz uma chamada de API por exemplo
-
Throughput: para avaliações em grande escala, solicite maiores cotas do Bedrock para evitar o controle de utilização
Aumento do throughput do Bedrock
Se você observar controle de utilização durante a avaliação, aumente suas cotas do modelo Bedrock:
-
Navegue até o console do AWS Service Quotas
-
Pesquise por “Bedrock” e selecione sua região
-
Encontre a cota para o modelo escolhido (por exemplo, “Invocações por minuto para o Claude 3.5 Sonnet”)
-
Clique em “Solicitar aumento de cota” e especifique o throughput desejado
-
Forneça uma justificativa para o aumento (por exemplo, “workload de avaliação de RFT”)
A lógica de repetição integrada do Lambda lida com o controle de utilização ocasional, mas as avaliações sustentadas de alto volume exigem aumentos de cota apropriados.
Política do IAM necessária:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "bedrock:InvokeModel" ], "Resource": "arn:aws:bedrock:*::foundation-model/*" } ] }