Aller au contenu principal

Background mode

Exécuter des tâches en arrière-plan

Le background mode de la Responses API permet de lancer une requête et de récupérer le résultat plus tard, sans maintenir de connexion ouverte. C’est un intermédiaire entre l’appel synchrone (réponse immédiate) et la Batch API (traitement en lot) : vous envoyez une requête individuelle, vous recevez un identifiant, et vous interrogez l’API quand vous voulez pour récupérer le résultat.

Fonctionnement du background mode

Lancer une requête en arrière-plan

import openai

client = openai.OpenAI()

# Lancer la requête en background
response = client.responses.create(
    model="o3-pro",  # Idéal pour les modèles lents (raisonnement)
    input="Analysez les implications économiques de la régulation "
          "européenne sur l'IA pour les PME françaises. "
          "Proposez un plan d'action en 10 points.",
    background=True,  # Mode arrière-plan
)

print(f"ID de la réponse : {response.id}")
print(f"Statut : {response.status}")  # "queued" ou "in_progress"

Récupérer le résultat

import time

def attendre_reponse(response_id: str, intervalle: int = 5) -> str:
    """Attend qu'une réponse en background soit terminée."""
    while True:
        response = client.responses.retrieve(response_id)

        match response.status:
            case "completed":
                return response.output_text
            case "failed":
                raise RuntimeError(
                    f"La requête a échoué : {response.error}"
                )
            case "cancelled":
                raise RuntimeError("La requête a été annulée.")
            case _:
                print(f"Statut : {response.status}...")
                time.sleep(intervalle)

Cas d’usage du background mode

Tâches de raisonnement long

Les modèles comme o3-pro peuvent prendre 30 secondes à 2 minutes pour réfléchir. Le background mode évite les timeouts :

async def analyse_approfondie(document: str) -> str:
    """Lance une analyse avec o3-pro sans bloquer."""
    response = client.responses.create(
        model="o3-pro",
        input=f"Effectuez une analyse juridique approfondie de ce contrat. "
              f"Identifiez tous les risques potentiels, les clauses "
              f"problématiques et proposez des modifications.\n\n{document}",
        background=True,
    )
    return response.id

# Lancer plusieurs analyses en parallèle
ids_taches = []
for doc in documents:
    tache_id = await analyse_approfondie(doc)
    ids_taches.append(tache_id)

# Récupérer les résultats plus tard
resultats = {}
for tache_id in ids_taches:
    resultats[tache_id] = attendre_reponse(tache_id)

Pattern fire-and-forget avec webhook

from fastapi import FastAPI, BackgroundTasks
import httpx

app = FastAPI()

@app.post("/api/analyse-longue")
async def lancer_analyse(requete: dict, background_tasks: BackgroundTasks):
    """Lance une analyse et notifie par webhook quand c'est fini."""
    response = client.responses.create(
        model="o3-pro",
        input=requete["prompt"],
        background=True,
    )

    # Surveiller en arrière-plan
    background_tasks.add_task(
        surveiller_et_notifier,
        response_id=response.id,
        webhook_url=requete["webhook_url"],
    )

    return {"response_id": response.id, "statut": "lancé"}

async def surveiller_et_notifier(response_id: str, webhook_url: str):
    """Surveille une requête background et notifie par webhook."""
    resultat = attendre_reponse(response_id)

    async with httpx.AsyncClient() as http:
        await http.post(webhook_url, json={
            "response_id": response_id,
            "resultat": resultat,
        })

Background mode vs Batch API

Choisissez selon votre besoin :

  • Background mode : une requête à la fois, résultat en minutes, prix standard
  • Batch API : milliers de requêtes, résultat en heures, -50 % du prix
  • Synchrone : une requête, résultat immédiat, prix standard
def choisir_mode(
    nb_requetes: int,
    urgence: str,
    budget: str,
) -> str:
    """Recommande le mode d'exécution optimal."""
    if nb_requetes > 100 and urgence != "immediat":
        return "batch"
    elif urgence == "immediat":
        return "synchrone"
    else:
        return "background"

Annuler une requête en cours

def annuler_si_trop_long(response_id: str, timeout: int = 120):
    """Annule une requête si elle dépasse le timeout."""
    debut = time.time()

    while time.time() - debut < timeout:
        response = client.responses.retrieve(response_id)
        if response.status == "completed":
            return response.output_text
        time.sleep(5)

    # Timeout dépassé — annuler
    client.responses.cancel(response_id)
    raise TimeoutError(
        f"Requête {response_id} annulée après {timeout}s."
    )

Points clés à retenir

  • Le background mode lance des requêtes sans maintenir de connexion ouverte
  • Idéal pour les modèles de raisonnement lents (o3-pro) et les tâches longues
  • Combinez-le avec un webhook pour une architecture événementielle
  • Pour du traitement en masse à bas coût, préférez la Batch API