Passer au contenu principal
En utilisant asyncio et le client AsyncOpenAI, vous pouvez envoyer plusieurs requêtes simultanément, réduisant considérablement le temps d’attente et améliorant le temps de réponse pour les opérations en lot.
Efficacité et ÉvolutivitéLes requêtes asynchrones permettent des opérations non-bloquantes, rendant votre application plus efficace et évolutive, surtout lors de multiples appels API simultanés.

Prérequis

  • Assurez-vous d’avoir la bibliothèque openai installée avec support pour les opérations asynchrones.
  • Une clé API stockée de manière sécurisée, de préférence dans une variable d’environnement PARADIGM_API_KEY.

Programmation Asynchrone avec asyncio

asyncio est une bibliothèque Python qui fournit un framework pour écrire du code concurrent en utilisant la syntaxe async et await. Elle est particulièrement utile pour le code réseau structuré de haut niveau et les opérations liées aux E/S. Vous pouvez trouver plus d’informations sur Asyncio ici.

Configuration du Client AsyncOpenAI

Pour utiliser les fonctionnalités asynchrones, utilisez AsyncOpenAI au lieu de OpenAI. Initialisez le client avec votre clé API et l’endpoint approprié.
from openai import AsyncOpenAI
import os

# Initialiser le client de manière asynchrone
# si vous avez un déploiement Paradigm privé,
# remplacez l'argument base_url par le vôtre
async_client = AsyncOpenAI(api_key=os.getenv("PARADIGM_API_KEY"), base_url=os.getenv("PARADIGM_BASE_URL", "https://paradigm.lighton.ai/api/v2"))

names = ["Alice", "Bob", "Charlie", "David", "Emma", "Frank", "Grace", "Hannah", "Ian", "Jessica", "Kevin", "Linda", "Michael", "Nancy", "Olivia", "Peter", "Quincy", "Rachel", "Samuel", "Tiffany"]

# comme exemple nous utiliserons ce lot de messages
messages_batch = [[{"role": "user", "content": f"Dis bonjour au nouvel utilisateur sur Paradigm ! Donne un accueil court d'une phrase hautement personnalisé à : {name}"}] for name in names]

Appels API Asynchrones

Voici comment implémenter des appels API asynchrones :

1. Définir une Fonction Asynchrone pour Envoyer des Messages

Créez une fonction async qui envoie un message à l’API et attend la réponse.
async def send_message(messages, *args, **kwargs):
    response = await client.chat.completions.create(messages=messages, *args, **kwargs)
    return response

2. Envoyer des Requêtes de Manière Concurrente

Utilisez asyncio.gather pour envoyer plusieurs requêtes simultanément. Cette fonction attend que tous les futures (opérations asynchrones) se terminent.
async def main():
    start_time = time.time()
    tasks = [send_message(messages, model="alfred-40b-1123", temperature=0.4) for messages in messages_batch]
    responses = await asyncio.gather(*tasks)
    duration = time.time() - start_time
    print(f"L'exécution asynchrone a pris {duration} secondes.")
    for response in responses:
      print(response.choices[0].message.content)
    return responses

3. Exécuter la Fonction Main Asynchrone

Utilisez asyncio.run() pour exécuter la fonction main, qui gère toutes les opérations asynchrones.
if __name__ == "__main__":
    asyncio.run(main())

Comparaison avec l’Exécution Synchrone

Lors de la comparaison de l’exécution asynchrone avec l’exécution synchrone traditionnelle (séquentielle), les opérations asynchrones se terminent généralement en beaucoup moins de temps—jusqu’à 3 fois plus rapide dans cet exemple, avec un potentiel d’amélioration encore plus grand selon la longueur des différentes requêtes. Cela est particulièrement vrai pour les tâches liées aux E/S comme les requêtes API. Les gains d’efficacité de l’exécution asynchrone proviennent de sa nature non-bloquante, qui permet à d’autres tâches de continuer sans attendre que les opérations d’E/S se terminent.
Bonnes Pratiques
  • Utilisez toujours await avec les fonctions async pour éviter les erreurs d’exécution.
  • Utilisez AsyncOpenAI pour les opérations asynchrones afin d’assurer des appels non-bloquants.
  • Pour les notebooks Jupyter, exécutez le code asynchrone via un script Python séparé en utilisant la commande magique !python file_to_execute.py dans une cellule pour éviter les problèmes de boucle d’événements.
En incorporant des requêtes asynchrones dans votre application, vous pouvez atteindre une plus grande efficacité et évolutivité, particulièrement lors de la gestion d’un grand nombre d’appels API.

Exemple Complet pour Comparaison

Pour comparer les appels API synchrones et asynchrones dans un scénario pratique, vous pouvez utiliser l’extrait suivant. Cet extrait créera un fichier Python, test.py, implémentant des requêtes API synchrones et asynchrones, respectivement. Vous pouvez ensuite exécuter ce script pour observer la différence de temps d’exécution, démontrant l’efficacité de la programmation asynchrone pour les requêtes en lot.
%%writefile speed_test.py
import os
import time
from openai import OpenAI, AsyncOpenAI
import asyncio

# Configuration du Client Synchrone
# si vous avez un déploiement Paradigm privé,
# remplacez l'argument base_url par le vôtre
sync_client = OpenAI(api_key=os.getenv("PARADIGM_API_KEY"), base_url=os.getenv("PARADIGM_BASE_URL", "https://paradigm.lighton.ai/api/v2"))

# Configuration du Client Asynchrone
# si vous avez un déploiement Paradigm privé,
# remplacez l'argument base_url par le vôtre
async_client = AsyncOpenAI(api_key=os.getenv("PARADIGM_API_KEY"), base_url=os.getenv("PARADIGM_BASE_URL", "https://paradigm.lighton.ai/api/v2"))

names = ["Alice", "Bob", "Charlie", "David", "Emma", "Frank", "Grace", "Hannah", "Ian", "Jessica", "Kevin", "Linda", "Michael", "Nancy", "Olivia", "Peter", "Quincy", "Rachel", "Samuel", "Tiffany"]

# Fonction synchrone pour envoyer des messages
def sync_send_message(name):
    messages = [{"role": "user", "content": f"Dis bonjour au nouvel utilisateur sur Paradigm ! Donne un accueil court d'une phrase hautement personnalisé à : {name}"}]
    response = sync_client.chat.completions.create(messages=messages, model="alfred-40b-1123", temperature=0.4)
    return response

# Fonction asynchrone pour envoyer des messages
async def async_send_message(messages, *args, **kwargs):
    response = await async_client.chat.completions.create(messages=messages, *args, **kwargs)
    return response

def sync_main():
    responses = []
    start_time = time.time()
    for name in names:
        response = sync_send_message(name)
        responses.append(response)
    duration = time.time() - start_time
    print(f"L'exécution synchrone a pris {duration} secondes.")

async def async_main():
    start_time = time.time()
    tasks = [async_send_message([{"role": "user", "content": f"Dis bonjour au nouvel utilisateur sur Paradigm ! Donne un accueil court d'une phrase hautement personnalisé à : {name}"}], model="alfred-40b-1123", temperature=0.4) for name in names]
    responses = await asyncio.gather(*tasks)
    duration = time.time() - start_time
    print(f"L'exécution asynchrone a pris {duration} secondes.")

if __name__ == "__main__":
    async_start_time = time.time()
    asyncio.run(async_main())
    async_times=time.time() - async_start_time

    sync_start_time = time.time()
    sync_main()
    sync_times=time.time() - sync_start_time

    improvement_factor = sync_times / async_times

    print(f"Facteur d'amélioration : {improvement_factor}")
Pour exécuter la comparaison :
  1. Exécutez l’extrait de code ci-dessus dans une cellule de notebook Jupyter pour créer speed_test.py.
  2. Exécutez le script dans le notebook Jupyter ou un terminal en utilisant la commande !python speed_test.py.
Ce script exécutera d’abord la version asynchrone, affichant le temps d’exécution total. Il exécutera ensuite la version synchrone, faisant de même. Comparer les deux temps d’exécution illustrera les gains d’efficacité réalisables avec les appels API asynchrones. Dans notre cas, nous avons obtenu la sortie suivante :
L'exécution asynchrone a pris 7.048963308334351 secondes.
L'exécution synchrone a pris 19.48901128768921 secondes.
Facteur d'amélioration : 2.7641254222771914

Conclusion

Exploiter les requêtes API asynchrones via le client AsyncOpenAI peut considérablement améliorer les performances et l’évolutivité des applications. Comme démontré, l’exécution asynchrone peut être presque 3 fois plus rapide que les méthodes synchrones, offrant des gains d’efficacité significatifs. Cette approche est essentielle pour gérer des interactions API à haut volume, garantissant l’efficacité des applications.
I