Exigences relatives à la fonction Lambda de pré-annotation et post-annotation - Amazon SageMaker

Exigences relatives à la fonction Lambda de pré-annotation et post-annotation

Utilisez cette section 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 par Ground Truth pour exécuter un flux d'étiquetage personnalisé.

Lambda de pré-annotation

Avant qu'une tâche d'étiquetage ne soit envoyée à l'employé, votre fonction Lambda de pré-annotation est appelé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. Le tableau suivant contient les schémas de requête de pré-annotation. Chaque paramètre est décrit ci-dessous.

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> } }
  • 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.

Le tableau suivant inclut des exemples de blocs de code d'une 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:<aws_region>:<aws_account_number>: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>:<aws_account_number>: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 :

Exemple 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 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 travailleurs 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

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 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

Lorsque tous les employés ont annoté l'objet de données ou lorsque 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 Consolider les annotations.

Astuce

Pour voir un exemple de fonction Lambda de post-annotation, veuillez consulter annotation_consolidation_lambda.py dans le répertoire GitHub aws-sagemaker-ground-truth-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.

Exemple 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://DOC-EXAMPLE-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'appel 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://DOC-EXAMPLE-BUCKET/annotations.json.

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

Exemple 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 un 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 la charge utile 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://DOC-EXAMPLE-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://DOC-EXAMPLE-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 obtenir un exemple complet, veuillez consulter annotation_consolidation_lambda.py dans le répertoire GitHubaws-sagemaker-ground-truth-recipe. Dans cet exemple GitHub, vous devez ajouter votre propre logique de consolidation d'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 :

Exemple 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 :

Exemple 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.