

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.

# Utilisation des fonctions Lambda de pré-annotation et post-annotation
<a name="sms-custom-templates-step3-lambda-requirements"></a>

Utilisez ces rubriques pour en savoir plus sur la syntaxe des requêtes envoyées aux fonctions Lambda pré-annotation et post-annotation, ainsi que sur la syntaxe de réponse requise que Ground Truth utilise dans des flux de travail d’étiquetage personnalisés.

**Topics**
+ [Lambda de pré-annotation](#sms-custom-templates-step3-prelambda)
+ [Lambda de post-annotation](#sms-custom-templates-step3-postlambda)

## Lambda de pré-annotation
<a name="sms-custom-templates-step3-prelambda"></a>

Avant qu’une tâche d’étiquetage ne soit envoyée à l’employé, une fonction Lambda de pré-annotation facultative peut être invoquée.

Ground Truth envoie à votre fonction Lambda une requête au format JSON pour fournir des détails sur la tâche d’étiquetage et l’objet de données.

Les exemples suivants sont deux exemples de requêtes au format JSON.

------
#### [ Data object identified with "source-ref" ]

```
{
    "version": "2018-10-16",
    "labelingJobArn": <labelingJobArn>
    "dataObject" : {
        "source-ref": <s3Uri>
    }
}
```

------
#### [ Data object identified with "source" ]

```
{
    "version": "2018-10-16",
    "labelingJobArn": <labelingJobArn>
    "dataObject" : {
        "source": <string>
    }
}
```

------

 La liste suivante contient les schémas de requête de pré-annotation. Chaque paramètre est décrit ci-dessous.
+ `version` (chaîne) : il s’agit d’un numéro de version utilisé en interne par Ground Truth.
+ `labelingJobArn` (chaîne) : il s’agit du Amazon Resource Name, ou ARN, de votre tâche d’étiquetage. Cet ARN peut être utilisé pour référencer la tâche d’étiquetage lors de l’utilisation d’opérations d’API Ground Truth telles que `DescribeLabelingJob`.
+ La propriété `dataObject` (objet JSON) : la clé contient une seule ligne JSON, provenant de votre fichier manifeste source ou envoyée par Amazon SNS. Les objets de ligne JSON de votre manifeste peuvent comporter jusqu’à 100 kilo-octets de taille et contenir une grande variété de données. Pour une tâche très basique d’annotation d’image, la propriété `dataObject` JSON peut simplement contenir une clé `source-ref`, identifiant l’image à annoter. Si l’objet de données (par exemple, une ligne de texte) est inclus directement dans le fichier manifeste source, l’objet de données est identifié par `source`. Si vous créez une tâche de vérification ou d’ajustement, cette ligne peut contenir des données d’étiquettes et des métadonnées provenant de la tâche d’étiquetage précédente.

Les onglets d’exemples suivants présentent des exemples de requête de pré-annotation. Chaque paramètre de ces exemples de requêtes est expliqué sous le tableau à onglets.

------
#### [ Data object identified with "source-ref" ]

```
{
    "version": "2018-10-16",
    "labelingJobArn": "arn:aws:sagemaker:us-west-2:111122223333:labeling-job/<labeling_job_name>"
    "dataObject" : {
        "source-ref": "s3://input-data-bucket/data-object-file-name"
    }
}
```

------
#### [ Data object identified with "source" ]

```
{
    "version": "2018-10-16",
    "labelingJobArn": "arn:aws:sagemaker:<aws_region>:111122223333:labeling-job/<labeling_job_name>"
    "dataObject" : {
        "source": "Sue purchased 10 shares of the stock on April 10th, 2020"
    }
}
```

------

En retour, Ground Truth nécessite une réponse formatée comme suit :

**Example de données de retour attendues**  

```
{
    "taskInput": <json object>,
    "isHumanAnnotationRequired": <boolean> # Optional
}
```

Dans l’exemple précédent, `<json object>` doit contenir *toutes* les données dont votre modèle de tâche d’employé a besoin. Si vous accomplissez une tâche de cadre de délimitation où les instructions restent toujours les mêmes, il peut s’agir simplement de la ressource HTTP(S) ou Amazon S3 de votre fichier image. S’il s’agit d’une tâche d’analyse de ressenti et que différents objets peuvent comporter des choix différents, la référence de l’objet est une chaîne de caractères et les choix sont un tableau de chaînes de caractères.

**Implications de `isHumanAnnotationRequired`**  
Cette valeur est facultative, car elle prend par défaut la valeur `true`. Vous paramétrez cette valeur de manière explicite principalement lorsque vous souhaitez empêcher cet objet de données d’être étiquetés par des employés humains. 

Si vous avez un mélange d’objets dans votre manifeste, certains d’entre eux nécessitant une annotation humaine et d’autres pas, vous pouvez inclure une valeur `isHumanAnnotationRequired` dans chaque objet de données. Vous pouvez ajouter une logique à votre pré-annotation Lambda pour déterminer dynamiquement si un objet nécessite une annotation, et définir cette valeur booléenne en conséquence.

### Exemples de fonctions Lambda de pré-annotation
<a name="sms-custom-templates-step3-prelambda-example"></a>

La fonction Lambda de pré-annotation de base suivante accède à l’objet JSON dans `dataObject` à partir de la requête initiale, et le renvoie dans le paramètre `taskInput`.

```
import json

def lambda_handler(event, context):
    return {
        "taskInput":  event['dataObject']
    }
```

En supposant que le fichier manifeste source utilise `"source-ref"` pour identifier les objets de données, le modèle de tâche d’employé utilisé dans la même tâche d’étiquetage que cette pré-annotation Lambda doit inclure un élément Liquid comme le suivant pour intégrer (les données) `dataObject` :

```
{{ task.input.source-ref | grant_read_access }}
```

Si le fichier manifeste source a utilisé `source` pour identifier l’objet de données, le modèle de tâche employé peut intégrer (les données) `dataObject` avec les éléments suivants :

```
{{ task.input.source }}
```

L’exemple Lambda de pré-annotation suivant inclut une logique pour identifier la clé utilisée dans `dataObject`, et pour pointer vers cet objet de données en utilisant `taskObject` dans la déclaration de retour de Lambda.

```
import json

def lambda_handler(event, context):

    # Event received
    print("Received event: " + json.dumps(event, indent=2))

    # Get source if specified
    source = event['dataObject']['source'] if "source" in event['dataObject'] else None

    # Get source-ref if specified
    source_ref = event['dataObject']['source-ref'] if "source-ref" in event['dataObject'] else None

    # if source field present, take that otherwise take source-ref
    task_object = source if source is not None else source_ref

    # Build response object
    output = {
        "taskInput": {
            "taskObject": task_object
        },
        "humanAnnotationRequired": "true"
    }

    print(output)
    # If neither source nor source-ref specified, mark the annotation failed
    if task_object is None:
        print(" Failed to pre-process {} !".format(event["labelingJobArn"]))
        output["humanAnnotationRequired"] = "false"

    return output
```

## Lambda de post-annotation
<a name="sms-custom-templates-step3-postlambda"></a>

Lorsque tous les employés ont annoté l’objet de données ou lorsque [https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_HumanLoopConfig.html#SageMaker-Type-HumanLoopConfig-TaskAvailabilityLifetimeInSeconds](https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_HumanLoopConfig.html#SageMaker-Type-HumanLoopConfig-TaskAvailabilityLifetimeInSeconds) a été atteint, selon la première éventualité, Ground Truth envoie ces annotations à votre fonction Lambda de post-annotation. Cette fonction Lambda est généralement utilisée pour [Consolidation d’annotation](sms-annotation-consolidation.md).

**Note**  
Pour voir un exemple de fonction Lambda post-consolidation, [consultez](https://github.com/aws-samples/aws-sagemaker-ground-truth-recipe/blob/master/aws_sagemaker_ground_truth_sample_lambda/annotation_consolidation_lambda.py) le fichier annotation\$1consolidation\$1lambda.py dans [aws-sagemaker-ground-truthle](https://github.com/aws-samples/aws-sagemaker-ground-truth-recipe) GitHub référentiel -recipe.

Le bloc de code suivant contient le schéma de requête de post-annotation. Chaque paramètre est décrit dans la liste à puces suivante.

```
{
    "version": "2018-10-16",
    "labelingJobArn": <string>,
    "labelCategories": [<string>],
    "labelAttributeName": <string>,
    "roleArn" : <string>,
    "payload": {
        "s3Uri": <string>
    }
 }
```
+ `version` (chaîne) : un numéro de version utilisé en interne par Ground Truth.
+ `labelingJobArn` (chaîne) : l’Amazon Resource Name, ou ARN, de votre tâche d’étiquetage. Cet ARN peut être utilisé pour référencer la tâche d'étiquetage lors de l'utilisation d'opérations d'API Ground Truth telles que `DescribeLabelingJob`.
+ `labelCategories` (liste des chaînes) : inclut les catégories d’étiquettes et les autres attributs que vous avez spécifiés dans la console ou que vous incluez dans le fichier de configuration des catégories d’étiquettes.
+ `labelAttributeName` (chaîne) : soit le nom de votre tâche d’étiquetage, soit le nom de l’attribut d’étiquette que vous spécifiez lorsque vous créez la tâche d’étiquetage.
+ `roleArn` (chaîne) : Amazon Resource Name (ARN) du rôle d’exécution IAM que vous spécifiez lorsque vous créez la tâche d’étiquetage. 
+ `payload` (objet JSON) : un JSON qui inclut une clé `s3Uri`, identifiant l’emplacement des données d’annotation pour cet objet de données dans Amazon S3. Le deuxième bloc de code ci-dessous présente un exemple de ce fichier d’annotation.

Le bloc de code suivant contient un exemple de requête de post-annotation. Chaque paramètre de cet exemple de requête est expliqué sous le bloc de code.

**Example d’une requête Lambda de post-annotation**  

```
{
    "version": "2018-10-16",
    "labelingJobArn": "arn:aws:sagemaker:us-west-2:111122223333:labeling-job/labeling-job-name",
    "labelCategories": ["Ex Category1","Ex Category2", "Ex Category3"],
    "labelAttributeName": "labeling-job-attribute-name",
    "roleArn" : "arn:aws:iam::111122223333:role/role-name",
    "payload": {
        "s3Uri": "s3://amzn-s3-demo-bucket/annotations.json"
    }
 }
```

**Note**  
Si aucun employé n’utilise l’objet de données et que `TaskAvailabilityLifetimeInSeconds` a été atteint, l’objet de données est marqué comme ayant échoué et n’est pas inclus dans l’invocation Lambda de post-annotation.

Le bloc de code suivant contient le schéma de charge utile. Il s’agit du fichier qui est indiqué par le paramètre `s3Uri` dans l’objet JSON `payload` de requête Lambda de post-annotation. Par exemple, si le bloc de code précédent est la requête Lambda post-annotation, le fichier d’annotation suivant se trouve dans `s3://amzn-s3-demo-bucket/annotations.json`.

Chaque paramètre est décrit dans la liste à puces suivante.

**Example d’un fichier d’annotation**  

```
[
    {
        "datasetObjectId": <string>,
        "dataObject": {
            "s3Uri": <string>,
            "content": <string>
        },
        "annotations": [{
            "workerId": <string>,
            "annotationData": {
                "content": <string>,
                "s3Uri": <string>
            }
       }]
    }
]
```
+ `datasetObjectId` (chaîne) : identifie un ID unique que Ground Truth attribue à chaque objet de données que vous envoyez à la tâche d’étiquetage.
+ `dataObject` (objet JSON) : l’objet de données étiqueté. Si l’objet de données est inclus dans le fichier manifeste source et est identifié à l’aide de la clé `source` (par exemple, une chaîne), `dataObject` inclut une clé `content`, qui identifie l’objet de données. Sinon, l’emplacement de l’objet de données (par exemple, un lien ou un URI S3) est identifié par `s3Uri`.
+ `annotations` (liste des objets JSON) : cette liste contient un objet JSON unique pour chaque annotation soumise par les employés pour ce `dataObject`. Un seul objet JSON contient un `workerId` qui peut être utilisé pour identifier l’employé qui a soumis cette annotation. La clé `annotationData` contient l’un des éléments suivants :
  + `content` (string) : contient les données d’annotation. 
  + `s3Uri` (chaîne) : contient un URI S3 qui identifie l’emplacement des données d’annotation.

Le tableau suivant contient des exemples de contenu que vous pouvez trouver dans les données utiles pour différents types d’annotations.

------
#### [ Named Entity Recognition Payload ]

```
[
    {
      "datasetObjectId": "1",
      "dataObject": {
        "content": "Sift 3 cups of flour into the bowl."
      },
      "annotations": [
        {
          "workerId": "private.us-west-2.ef7294f850a3d9d1",
          "annotationData": {
            "content": "{\"crowd-entity-annotation\":{\"entities\":[{\"endOffset\":4,\"label\":\"verb\",\"startOffset\":0},{\"endOffset\":6,\"label\":\"number\",\"startOffset\":5},{\"endOffset\":20,\"label\":\"object\",\"startOffset\":15},{\"endOffset\":34,\"label\":\"object\",\"startOffset\":30}]}}"
          }
        }
      ]
    }
]
```

------
#### [ Semantic Segmentation Payload ]

```
[
    {
      "datasetObjectId": "2",
      "dataObject": {
        "s3Uri": "s3://amzn-s3-demo-bucket/gt-input-data/images/bird3.jpg"
      },
      "annotations": [
        {
          "workerId": "private.us-west-2.ab1234c5678a919d0",
          "annotationData": {
            "content": "{\"crowd-semantic-segmentation\":{\"inputImageProperties\":{\"height\":2000,\"width\":3020},\"labelMappings\":{\"Bird\":{\"color\":\"#2ca02c\"}},\"labeledImage\":{\"pngImageData\":\"iVBOR...\"}}}"
          }
        }
      ]
    }
  ]
```

------
#### [ Bounding Box Payload ]

```
[
    {
      "datasetObjectId": "0",
      "dataObject": {
        "s3Uri": "s3://amzn-s3-demo-bucket/gt-input-data/images/bird1.jpg"
      },
      "annotations": [
        {
          "workerId": "private.us-west-2.ab1234c5678a919d0",
          "annotationData": {
            "content": "{\"boundingBox\":{\"boundingBoxes\":[{\"height\":2052,\"label\":\"Bird\",\"left\":583,\"top\":302,\"width\":1375}],\"inputImageProperties\":{\"height\":2497,\"width\":3745}}}"
          }
        }
      ]
    }
 ]
```

------

Votre fonction Lambda de post-annotation peut contenir une logique similaire à la suivante pour parcourir et accéder à toutes les annotations contenues dans la requête. Pour un exemple complet, consultez le [fichier annotation\$1consolidation\$1lambda.py](https://github.com/aws-samples/aws-sagemaker-ground-truth-recipe/blob/master/aws_sagemaker_ground_truth_sample_lambda/annotation_consolidation_lambda.py) dans le GitHub référentiel [aws-sagemaker-ground-truth-recipe](https://github.com/aws-samples/aws-sagemaker-ground-truth-recipe). Dans cet GitHub exemple, vous devez ajouter votre propre logique de consolidation des annotations. 

```
for i in range(len(annotations)):
    worker_id = annotations[i]["workerId"]
    annotation_content = annotations[i]['annotationData'].get('content')
    annotation_s3_uri = annotations[i]['annotationData'].get('s3uri')
    annotation = annotation_content if annotation_s3_uri is None else s3_client.get_object_from_s3(
        annotation_s3_uri)
    annotation_from_single_worker = json.loads(annotation)

    print("{} Received Annotations from worker [{}] is [{}]"
            .format(log_prefix, worker_id, annotation_from_single_worker))
```

**Astuce**  
Lorsque vous exécutez des algorithmes de consolidation sur les données, vous pouvez utiliser un service de base de données AWS pour stocker les résultats, ou vous pouvez renvoyer les résultats traités à Ground Truth. Les données que vous renvoyez à Ground Truth sont stockées dans des manifestes d’annotation consolidés dans le compartiment S3 spécifié pour la sortie lors de la configuration de la tâche d’étiquetage.

En retour, Ground Truth nécessite une réponse formatée comme suit :

**Example de données de retour attendues**  

```
[
   {        
        "datasetObjectId": <string>,
        "consolidatedAnnotation": {
            "content": {
                "<labelattributename>": {
                    # ... label content
                }
            }
        }
    },
   {        
        "datasetObjectId": <string>,
        "consolidatedAnnotation": {
            "content": {
                "<labelattributename>": {
                    # ... label content
                }
            }
        }
    }
    .
    .
    .
]
```
À ce stade, toutes les données que vous envoyez à votre compartiment S3, autres que `datasetObjectId`, sont dans l’objet `content`.

Lorsque vous retournez des annotations dans `content`, cela génère une entrée dans le manifeste de sortie de votre tâche, comme suit :

**Example de format d’étiquette dans le manifeste de sortie**  

```
{  "source-ref"/"source" : "<s3uri or content>", 
   "<labelAttributeName>": {
        # ... label content from you
    },   
   "<labelAttributeName>-metadata": { # This will be added by Ground Truth
        "job_name": <labelingJobName>,
        "type": "groundTruth/custom",
        "human-annotated": "yes", 
        "creation_date": <date> # Timestamp of when received from Post-labeling Lambda
    }
}
```

En raison de la nature potentiellement complexe d’un modèle personnalisé et des données qu’il collecte, Ground Truth n’offre pas de traitement ou d’analyse des données.