Logo Zéphyrnet

Explorer les options de synthèse pour les soins de santé avec Amazon SageMaker | Services Web Amazon

Date :

Dans le paysage des soins de santé en évolution rapide d'aujourd'hui, les médecins sont confrontés à de grandes quantités de données cliniques provenant de diverses sources, telles que des notes de soignant, des dossiers de santé électroniques et des rapports d'imagerie. Cette mine d'informations, bien qu'essentielle pour les soins aux patients, peut également être écrasante et fastidieuse pour les professionnels de la santé à passer au crible et à analyser. Résumer et extraire efficacement des informations à partir de ces données est crucial pour améliorer les soins aux patients et la prise de décision. Les informations résumées sur les patients peuvent être utiles pour un certain nombre de processus en aval tels que l'agrégation de données, le codage efficace des patients ou le regroupement de patients présentant des diagnostics similaires pour examen.

Les modèles d'intelligence artificielle (IA) et d'apprentissage automatique (ML) se sont révélés très prometteurs pour relever ces défis. Les modèles peuvent être formés pour analyser et interpréter de grands volumes de données textuelles, condensant efficacement les informations en résumés concis. En automatisant le processus de résumé, les médecins peuvent accéder rapidement aux informations pertinentes, ce qui leur permet de se concentrer sur les soins aux patients et de prendre des décisions plus éclairées. Voir ce qui suit un exemple pour en savoir plus sur un cas d'utilisation réel.

Amazon Sage Maker, un service de ML entièrement géré, fournit une plate-forme idéale pour héberger et mettre en œuvre divers modèles et approches de synthèse basés sur l'IA/ML. Dans cet article, nous explorons différentes options pour mettre en œuvre des techniques de résumé sur SageMaker, y compris l'utilisation Amazon SageMaker JumpStart modèles de base, affiner les modèles pré-formés de Hugging Face et créer des modèles de synthèse personnalisés. Nous discutons également des avantages et des inconvénients de chaque approche, permettant aux professionnels de la santé de choisir la solution la plus appropriée pour générer des résumés concis et précis de données cliniques complexes.

Deux termes importants à connaître avant de commencer : pré-formé ainsi que réglage fin. Un modèle pré-formé ou de base est un modèle qui a été construit et formé sur un grand corpus de données, généralement pour des connaissances linguistiques générales. Le réglage fin est le processus par lequel un modèle pré-formé reçoit un autre ensemble de données plus spécifique à un domaine afin d'améliorer ses performances sur une tâche spécifique. Dans un contexte de soins de santé, cela signifierait de donner au modèle des données, y compris des phrases et une terminologie se rapportant spécifiquement aux soins aux patients.

Créez des modèles de synthèse personnalisés sur SageMaker

Bien qu'il s'agisse de l'approche la plus exigeante, certaines organisations peuvent préférer créer des modèles de synthèse personnalisés sur SageMaker à partir de zéro. Cette approche nécessite une connaissance plus approfondie des modèles AI/ML et peut impliquer la création d'une architecture de modèle à partir de zéro ou l'adaptation de modèles existants pour répondre à des besoins spécifiques. La création de modèles personnalisés peut offrir une plus grande flexibilité et un meilleur contrôle sur le processus de synthèse, mais nécessite également plus de temps et de ressources par rapport aux approches qui partent de modèles pré-formés. Il est essentiel de bien peser les avantages et les inconvénients de cette option avant de poursuivre, car elle peut ne pas convenir à tous les cas d'utilisation.

Modèles de fondation SageMaker JumpStart

Une excellente option pour implémenter la synthèse sur SageMaker consiste à utiliser les modèles de base JumpStart. Ces modèles, développés par des organisations de recherche en IA de premier plan, offrent une gamme de modèles de langage pré-entraînés optimisés pour diverses tâches, y compris le résumé de texte. SageMaker JumpStart fournit deux types de modèles de base : les modèles propriétaires et les modèles open source. SageMaker JumpStart fournit également l'éligibilité HIPAA, ce qui le rend utile pour les charges de travail des soins de santé. Il appartient en dernier ressort au client d'assurer la conformité, alors assurez-vous de prendre les mesures appropriées. Voir Architecture pour la sécurité et la conformité HIPAA sur Amazon Web Services pour plus de détails.

Modèles de fondation propriétaires

Les modèles propriétaires, tels que les modèles Jurassic d'AI21 et le modèle Cohere Generate de Cohere, peuvent être découverts via SageMaker JumpStart sur le Console de gestion AWS et sont actuellement en prévisualisation. L'utilisation de modèles propriétaires pour la synthèse est idéale lorsque vous n'avez pas besoin d'affiner votre modèle sur des données personnalisées. Il s'agit d'une solution prête à l'emploi et facile à utiliser qui peut répondre à vos besoins de synthèse avec une configuration minimale. En utilisant les fonctionnalités de ces modèles pré-formés, vous pouvez économiser du temps et des ressources qui seraient autrement consacrés à la formation et au réglage fin d'un modèle personnalisé. De plus, les modèles propriétaires sont généralement fournis avec des API et des SDK conviviaux, ce qui simplifie le processus d'intégration avec vos systèmes et applications existants. Si vos besoins de synthèse peuvent être satisfaits par des modèles propriétaires pré-formés sans nécessiter de personnalisation ou de réglage précis, ils offrent une solution pratique, économique et efficace pour vos tâches de synthèse de texte. Étant donné que ces modèles ne sont pas formés spécifiquement pour les cas d'utilisation dans le domaine de la santé, la qualité ne peut être garantie pour le langage médical prêt à l'emploi sans un réglage fin.

Jurassic-2 Grande Instruct est un grand modèle de langage (LLM) d'AI21 Labs, optimisé pour les instructions en langage naturel et applicable à diverses tâches linguistiques. Il offre une API et un SDK Python faciles à utiliser, équilibrant qualité et prix abordable. Les utilisations populaires incluent la génération de copie marketing, l'alimentation des chatbots et la synthèse de texte.

Sur la console SageMaker, accédez à SageMaker JumpStart, recherchez le modèle AI21 Jurassic-2 Grande Instruct et choisissez Essayez le modèle.

Si vous souhaitez déployer le modèle sur un point de terminaison SageMaker que vous gérez, vous pouvez suivre les étapes de cet exemple cahier, qui vous montre comment déployer Jurassic-2 Large à l'aide de SageMaker.

Modèles de fondation open source

Les modèles open source incluent les modèles FLAN T5, Bloom et GPT-2 qui peuvent être découverts via SageMaker JumpStart dans le Amazon SageMakerStudio UI, SageMaker JumpStart sur la console SageMaker et les API SageMaker JumpStart. Ces modèles peuvent être affinés et déployés sur des points de terminaison sous votre compte AWS, vous donnant la pleine propriété des pondérations de modèle et des codes de script.

Flan-T5 XL est un modèle puissant et polyvalent conçu pour un large éventail de tâches linguistiques. En affinant le modèle avec vos données spécifiques à votre domaine, vous pouvez optimiser ses performances pour votre cas d'utilisation particulier, comme la synthèse de texte ou toute autre tâche NLP. Pour plus de détails sur le réglage fin de Flan-T5 XL à l'aide de l'interface utilisateur de SageMaker Studio, reportez-vous à Réglage fin des instructions pour FLAN T5 XL avec Amazon SageMaker Jumpstart.

Affiner les modèles pré-formés avec Hugging Face sur SageMaker

L'une des options les plus populaires pour la mise en œuvre de la synthèse sur SageMaker consiste à affiner les modèles pré-formés à l'aide de Hugging Face. Transformateurs bibliothèque. Hugging Face propose une large gamme de modèles de transformateurs pré-formés spécialement conçus pour diverses tâches de traitement du langage naturel (TAL), y compris le résumé de texte. Avec la bibliothèque Hugging Face Transformers, vous pouvez facilement affiner ces modèles pré-formés sur vos données spécifiques à votre domaine à l'aide de SageMaker. Cette approche présente plusieurs avantages, tels que des temps de formation plus rapides, de meilleures performances sur des domaines spécifiques et un packaging et un déploiement de modèles plus faciles à l'aide des outils et services SageMaker intégrés. Si vous ne parvenez pas à trouver un modèle approprié dans SageMaker JumpStart, vous pouvez choisir n'importe quel modèle proposé par Hugging Face et l'affiner à l'aide de SageMaker.

Pour commencer à travailler avec un modèle pour en savoir plus sur les fonctionnalités de ML, il vous suffit d'ouvrir SageMaker Studio, de trouver un modèle pré-formé que vous souhaitez utiliser dans le Hub de modèle de visage étreignant, et choisissez SageMaker comme méthode de déploiement. Hugging Face vous donnera le code à copier, coller et exécuter dans votre cahier. C'est aussi simple que ça! Aucune expérience en ingénierie ML requise.

La bibliothèque Hugging Face Transformers permet aux constructeurs d'opérer sur les modèles pré-formés et d'effectuer des tâches avancées comme le réglage fin, que nous explorons dans les sections suivantes.

Provisionner les ressources

Avant de pouvoir commencer, nous devons provisionner un notebook. Pour obtenir des instructions, reportez-vous aux étapes 1 et 2 de Construire et former un modèle d'apprentissage automatique localement. Pour cet exemple, nous avons utilisé les paramètres indiqués dans la capture d'écran suivante.

Nous devons également créer un Service de stockage simple Amazon (Amazon S3) pour stocker les données de formation et les artefacts de formation. Pour obtenir des instructions, reportez-vous à Créer un bucket.

Préparer le jeu de données

Pour affiner notre modèle afin d'avoir une meilleure connaissance du domaine, nous devons obtenir des données adaptées à la tâche. Lors de la formation pour un cas d'utilisation d'entreprise, vous devrez effectuer un certain nombre de tâches d'ingénierie de données pour préparer vos propres données afin qu'elles soient prêtes pour la formation. Ces tâches sortent du cadre de ce poste. Pour cet exemple, nous avons généré des données synthétiques pour émuler les notes de soins infirmiers et les avons stockées dans Amazon S3. Le stockage de nos données dans Amazon S3 nous permet de concevoir nos charges de travail pour la conformité HIPAA. Nous commençons par récupérer ces notes et les chargeons sur l'instance sur laquelle notre notebook s'exécute :

from datasets import load_dataset
dataset = load_dataset("csv", data_files={
    "train": "s3://" + bucket_name + train_data_path,
    "validation": "s3://" + bucket_name + test_data_path
})

Les notes sont composées d'une colonne contenant l'entrée complète, la note, et une colonne contenant une version abrégée illustrant ce que devrait être notre sortie souhaitée, résumé. Le but de l'utilisation de cet ensemble de données est d'améliorer le vocabulaire biologique et médical de notre modèle afin qu'il soit plus adapté à la synthèse dans un contexte de soins de santé, appelé réglage fin du domaine, et montrez à notre modèle comment structurer sa sortie résumée. Dans certains cas de résumé, nous pouvons souhaiter créer un résumé à partir d'un article ou un résumé d'une ligne d'une critique, mais dans ce cas, nous essayons de faire en sorte que notre modèle produise une version abrégée des symptômes et des actions prises. pour un patient jusqu'à présent.

Charger le modèle

Le modèle que nous utilisons comme base est une version de Pegasus de Google, disponible dans le Hugging Face Hub, appelé pégase-xsum. Il est déjà pré-formé pour la synthèse, de sorte que notre processus de réglage fin peut se concentrer sur l'extension de sa connaissance du domaine. La modification de la tâche que notre modèle exécute est un autre type de réglage fin non couvert dans cet article. La bibliothèque Transformer nous fournit une classe pour charger la définition du modèle à partir de notre model_checkpoint: google/pegasus-xsum. Cela chargera le modèle à partir du hub et l'instanciera dans notre cahier afin que nous puissions l'utiliser plus tard. Parce que pegasus-xsum est un modèle séquence à séquence, nous voulons utiliser le type Seq2Seq du AutoModèle classe:

from transformers import AutoModelForSeq2SeqLM
model = AutoModelForSeq2SeqLM.from_pretrained(model_checkpoint)

Maintenant que nous avons notre modèle, il est temps de porter notre attention sur les autres composants qui nous permettront d'exécuter notre boucle d'entraînement.

Créer un tokenizer

Le premier de ces composants est le tokenizer. tokenization est le processus par lequel les mots des données d'entrée sont transformés en représentations numériques que notre modèle peut comprendre. Encore une fois, la bibliothèque Transformer nous fournit une classe pour charger une définition de tokenizer à partir du même point de contrôle que nous avons utilisé pour instancier le modèle :

from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained(model_checkpoint)

Avec cet objet tokenizer, nous pouvons créer une fonction de prétraitement et la mapper sur notre ensemble de données pour nous donner des jetons prêts à être introduits dans le modèle. Enfin, nous formatons la sortie tokenisée et supprimons les colonnes contenant notre texte d'origine, car le modèle ne pourra pas les interpréter. Il nous reste maintenant une entrée tokenisée prête à être introduite dans le modèle. Voir le code suivant :

tokenized_datasets = dataset.map(preprocess_function, batched=True) tokenized_datasets.set_format("torch") tokenized_datasets = tokenized_datasets.remove_columns( dataset["train"].column_names
)

Créer un collecteur et un optimiseur de données

Avec nos données tokenisées et notre modèle instancié, nous sommes presque prêts à exécuter une boucle de formation. Les prochains composants que nous voulons créer sont le collecteur de données et l'optimiseur. Le collecteur de données est une autre classe fournie par Hugging Face via la bibliothèque Transformers, que nous utilisons pour créer des lots de nos données tokenisées pour la formation. Nous pouvons facilement le construire en utilisant le tokenizer et les objets de modèle que nous avons déjà en trouvant simplement le type de classe correspondant que nous avons utilisé précédemment pour notre modèle (Seq2Seq) pour la classe d'assemblage. La fonction de l'optimiseur est de maintenir l'état d'entraînement et de mettre à jour les paramètres en fonction de notre perte d'entraînement pendant que nous travaillons dans la boucle. Pour créer un optimiseur, nous pouvons importer le optimal package du module torche, où un certain nombre d'algorithmes d'optimisation sont disponibles. Certains des plus courants que vous avez peut-être rencontrés auparavant sont la descente de gradient stochastique et Adam, ce dernier étant appliqué dans notre exemple. Le constructeur d'Adam prend en compte les paramètres du modèle et le taux d'apprentissage paramétré pour l'exécution d'entraînement donnée. Voir le code suivant :

from transformers import DataCollatorForSeq2Seq
from torch.optim import Adam data_collator = DataCollatorForSeq2Seq(tokenizer, model=model)
optimizer = Adam(model.parameters(), lr=learning_rate)

Construire l'accélérateur et le planificateur

Les dernières étapes avant de pouvoir commencer la formation consistent à construire l'accélérateur et le planificateur de taux d'apprentissage. L'accélérateur provient d'une bibliothèque différente (nous avons principalement utilisé Transformers) produite par Hugging Face, bien nommée Accelerate, et fera abstraction de la logique requise pour gérer les appareils pendant la formation (en utilisant plusieurs GPU par exemple). Pour le dernier composant, nous revisitons la bibliothèque Transformers, toujours très utile, pour implémenter notre planificateur de taux d'apprentissage. En spécifiant le type de planificateur, le nombre total d'étapes d'entraînement dans notre boucle et l'optimiseur créé précédemment, le get_scheduler renvoie un objet qui nous permet d'ajuster notre taux d'apprentissage initial tout au long du processus d'apprentissage :

from accelerate import Accelerator
from transformers import get_scheduler accelerator = Accelerator()
model, optimizer = accelerator.prepare( model, optimizer
) lr_scheduler = get_scheduler( "linear", optimizer=optimizer, num_warmup_steps=0, num_training_steps=num_training_steps,
)

Configurer une tâche d'entraînement

Nous sommes maintenant prêts pour la formation ! Configurons une tâche d'entraînement, en commençant par instancier le formation_args en utilisant la bibliothèque Transformers et en choisissant les valeurs des paramètres. Nous pouvons les transmettre, ainsi que nos autres composants et ensembles de données préparés, directement au entraîneur et commencer la formation, comme indiqué dans le code suivant. Selon la taille de votre ensemble de données et les paramètres choisis, cela peut prendre un temps considérable.

from transformers import Seq2SeqTrainer
from transformers import Seq2SeqTrainingArguments training_args = Seq2SeqTrainingArguments( output_dir="output/", save_total_limit=1, num_train_epochs=num_train_epochs, per_device_train_batch_size=batch_size, per_device_eval_batch_size=batch_size, evaluation_strategy="epoch", logging_dir="output/", load_best_model_at_end=True, disable_tqdm=True, logging_first_step=True, logging_steps=1, save_strategy="epoch", predict_with_generate=True
) trainer = Seq2SeqTrainer( model=model, tokenizer=tokenizer, args=training_args, train_dataset=tokenized_datasets["train"], eval_dataset=tokenized_datasets["validation"], data_collator=data_collator, optimizers=(optimizer, lr_scheduler)
) trainer.train()

Pour opérationnaliser ce code, nous pouvons le conditionner sous forme de fichier de point d'entrée et l'appeler via un Emploi de formation SageMaker. Cela nous permet de séparer la logique que nous venons de construire de l'appel de formation et permet à SageMaker d'exécuter la formation sur une instance distincte.

Empaqueter le modèle pour l'inférence

Une fois la formation exécutée, l'objet modèle est prêt à être utilisé pour l'inférence. Comme meilleure pratique, sauvegardons notre travail pour une utilisation future. Nous devons créer nos artefacts de modèle, les compresser ensemble et télécharger notre tarball sur Amazon S3 pour le stockage. Pour préparer notre modèle pour la compression, nous devons déballer le modèle maintenant affiné, puis enregistrer le fichier binaire du modèle et les fichiers de configuration associés. Nous devons également enregistrer notre tokenizer dans le même répertoire que celui dans lequel nous avons enregistré nos artefacts de modèle afin qu'il soit disponible lorsque nous utilisons le modèle pour l'inférence. Notre model_dir dossier devrait maintenant ressembler à quelque chose comme le code suivant :

config.json pytorch_model.bin	tokenizer_config.json
generation_config.json	special_tokens_map.json tokenizer.json

Il ne reste plus qu'à exécuter une commande tar pour compresser notre répertoire et télécharger le fichier tar.gz sur Amazon S3 :

unwrapped_model = accelerator.unwrap_model(trainer.model) unwrapped_model.save_pretrained('model_dir', save_function=accelerator.save) tokenizer.save_pretrained('model_dir') !cd model_dir/ && tar -czvf model.tar.gz *
!mv model_dir/model.tar.gz ./ with open("model.tar.gz", "rb") as f: s3.upload_fileobj(f, bucket_name, artifact_path + "model/model.tar.gz")

Notre nouveau modèle affiné est maintenant prêt et disponible pour être utilisé pour l'inférence.

Effectuer une inférence

Pour utiliser cet artefact de modèle pour l'inférence, ouvrez un nouveau fichier et utilisez le code suivant, en modifiant le model_data paramètre pour s'adapter à l'emplacement de sauvegarde de votre artefact dans Amazon S3. Le HuggingFaceModel constructeur reconstruira notre modèle à partir du point de contrôle que nous avons enregistré dans model.tar.gz, que nous pouvons ensuite déployer pour l'inférence à l'aide de la méthode de déploiement. Le déploiement du point de terminaison prendra quelques minutes.

from sagemaker.huggingface import HuggingFaceModel
from sagemaker import get_execution_role role = get_execution_role() huggingface_model = HuggingFaceModel( model_data=”s3://{bucket_name}/{artifact_path}/model/model.tar.gz”, role=role, transformers_version=”4.26”, pytorch_version=”1.13”, py_version=”py39”
) predictor = huggingface_model.deploy( initial_instance_count=1, instance_type=”ml.m5.xlarge”
)

Une fois le point de terminaison déployé, nous pouvons utiliser le prédicteur que nous avons créé pour le tester. Passe le predict méthode une charge utile de données et exécutez la cellule, et vous obtiendrez la réponse de votre modèle affiné :

data = { "inputs": "Text to summarize”
}
predictor.predict(data)

Résultats

Pour voir l'avantage d'affiner un modèle, faisons un test rapide. Le tableau suivant inclut une invite et les résultats de la transmission de cette invite au modèle avant et après le réglage précis.

Prompt Réponse sans réglage fin Réponse avec réglage fin
Résumez les symptômes que le patient éprouve. Le patient est un homme de 45 ans qui se plaint de douleurs thoraciques rétrosternales irradiant vers le bras gauche. La douleur est d'apparition soudaine alors qu'il effectuait des travaux de jardinage, associée à un léger essoufflement et à une transpiration. À l'arrivée, la fréquence cardiaque du patient était de 120, la fréquence respiratoire de 24, la tension artérielle de 170/95. Electrocardiogramme 12 dérivations réalisé à l'arrivée aux urgences et XNUMX nitroglycérines sublinguales administrées sans soulagement des douleurs thoraciques. L'électrocardiogramme montre une élévation du segment ST dans les dérivations antérieures démontrant un infarctus aigu du myocarde antérieur. Nous avons contacté le laboratoire de cathétérisme cardiaque et préparé le cathétérisme cardiaque par un cardiologue. Nous présentons un cas d'infarctus aigu du myocarde. Douleur thoracique, MI antérieur, PCI.

Comme vous pouvez le voir, notre modèle affiné utilise différemment la terminologie de la santé, et nous avons pu modifier la structure de la réponse pour l'adapter à nos objectifs. Notez que les résultats dépendent de votre ensemble de données et des choix de conception effectués lors de la formation. Votre version du modèle pourrait offrir des résultats très différents.

Nettoyer

Lorsque vous avez terminé avec votre bloc-notes SageMaker, assurez-vous de l'arrêter pour éviter les coûts liés aux ressources de longue durée. Notez que l'arrêt de l'instance vous fera perdre toutes les données stockées dans la mémoire éphémère de l'instance, vous devez donc enregistrer tout votre travail dans un stockage persistant avant le nettoyage. Vous devrez également vous rendre au Endpoints sur la console SageMaker et supprimez tous les terminaux déployés pour l'inférence. Pour supprimer tous les artefacts, vous devez également accéder à la console Amazon S3 pour supprimer les fichiers chargés dans votre compartiment.

Conclusion

Dans cet article, nous avons exploré diverses options pour mettre en œuvre des techniques de résumé de texte sur SageMaker afin d'aider les professionnels de la santé à traiter et extraire efficacement des informations à partir de grandes quantités de données cliniques. Nous avons discuté de l'utilisation des modèles de base SageMaker Jumpstart, de l'ajustement des modèles pré-formés de Hugging Face et de la création de modèles de synthèse personnalisés. Chaque approche a ses propres avantages et inconvénients, répondant à des besoins et des exigences différents.

La création de modèles de résumé personnalisés sur SageMaker offre beaucoup de flexibilité et de contrôle, mais nécessite plus de temps et de ressources que l'utilisation de modèles pré-formés. Les modèles de base SageMaker Jumpstart offrent une solution facile à utiliser et rentable pour les organisations qui ne nécessitent pas de personnalisation ou de réglage précis, ainsi que certaines options pour un réglage fin simplifié. Le réglage fin des modèles pré-formés de Hugging Face offre des temps de formation plus rapides, de meilleures performances spécifiques au domaine et une intégration transparente avec les outils et services SageMaker sur un large catalogue de modèles, mais cela nécessite un certain effort de mise en œuvre. Au moment de la rédaction de cet article, Amazon a annoncé une autre option, Socle amazonien, qui offrira des fonctionnalités de synthèse dans un environnement encore mieux géré.

En comprenant les avantages et les inconvénients de chaque approche, les professionnels de la santé et les organisations peuvent prendre des décisions éclairées sur la solution la plus appropriée pour générer des résumés concis et précis de données cliniques complexes. En fin de compte, l'utilisation de modèles de synthèse basés sur l'IA/ML sur SageMaker peut considérablement améliorer les soins aux patients et la prise de décision en permettant aux professionnels de la santé d'accéder rapidement aux informations pertinentes et de se concentrer sur la fourniture de soins de qualité.

Ressources

Pour le script complet discuté dans cet article et quelques exemples de données, reportez-vous au GitHub repo. Pour plus d'informations sur l'exécution des charges de travail ML sur AWS, consultez les ressources suivantes :


À propos des auteurs

Cody Collins est un architecte de solutions basé à New York chez Amazon Web Services. Il travaille avec des clients ISV pour créer des solutions de pointe dans le cloud. Il a réalisé avec succès des projets complexes pour diverses industries, optimisant l'efficacité et l'évolutivité. Dans ses temps libres, il aime lire, voyager et s'entraîner au jiu jitsu.

Ameer Hakmé est un architecte de solutions AWS résidant en Pennsylvanie. Son objectif professionnel consiste à collaborer avec des éditeurs de logiciels indépendants dans tout le Nord-Est, en les guidant dans la conception et la construction de plates-formes évolutives à la pointe de la technologie sur le cloud AWS.

spot_img

Dernières informations

spot_img