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.
-
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 queDescribeLabelingJob
. -
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é parsource
. 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.
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.
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.
Pour voir un exemple de fonction Lambda de post-annotation, veuillez consulter annotation_consolidation_lambda.py
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 queDescribeLabelingJob
. -
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" } }
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 uncontent
, 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é pars3Uri
. -
annotations
(liste des objets JSON) : cette liste contient un objet JSON unique pour chaque annotation soumise par les employés pour cedataObject
. Un seul objet JSON contient unworkerId
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.
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
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))
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.