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 :
- Exécutez l’extrait de code ci-dessus dans une cellule de notebook Jupyter pour créer speed_test.py.
- 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.