Aller au contenu principal
Leçon 6 sur 20 · Outils API : Search, Files et Code Interpreter

Configurer et contrôler les résultats web

Leçon 6 sur 20 Mis à jour le 2 novembre 2026 Développeur
Sur cette page
  1. Configurer et contrôler les résultats web
  2. Paramètre search_context_size
  3. Guider les requêtes de recherche par le prompt
  4. Extraire et structurer les citations
  5. Pattern : recherche avec validation croisée
  6. Gérer l’absence de résultats
  7. Web Search avec streaming
  8. Filtrer les domaines et lister les sources
  9. Points clés à retenir

Leçon corrigée le 2 novembre 2026 d’après la documentation d’OpenAI : l’outil Code Interpreter exige un paramètre container (ajouté à tous les exemples), les parties de texte de l’entrée sont de type input_text, et la recherche web utilise l’outil web_search (web_search_preview n’est plus qu’un outil hérité, sans filtres de domaines). Les fichiers générés se récupèrent avec les fonctions fichiers_generes et telecharger de la leçon 10. Sources : Code Interpreter · Web search.

Configurer et contrôler les résultats web

Activer Web Search prend une ligne ; en tirer des réponses fiables demande trois réglages que cette leçon détaille. Le premier décide de la quantité de web injectée dans le contexte, et il pèse directement sur votre facture. Le deuxième oriente les requêtes que le modèle formule lui-même — car c’est lui qui les écrit, pas vous. Le troisième concerne les citations, sans lesquelles une réponse sourcée n’est qu’une réponse affirmative.

Paramètre search_context_size

Le paramètre search_context_size contrôle la quantité de contenu web injecté dans le contexte du modèle. Il ne change ni le nombre de recherches ni leur qualité : il détermine combien de texte, une fois les pages trouvées, entre effectivement dans le prompt. C’est donc un arbitrage entre exhaustivité et coût, et il se règle par type de tâche, pas une fois pour toutes.

from openai import OpenAI

client = OpenAI()

# Contexte minimal : réponses rapides et concises
response = client.responses.create(
    model="gpt-5.6-terra",
    input="Quel est le PIB de la France en 2025 ?",
    tools=[{
        "type": "web_search",
        "search_context_size": "low"
    }]
)

# Contexte moyen : bon compromis (defaut)
response = client.responses.create(
    model="gpt-5.6-terra",
    input="Resume les tendances du marche IA en Europe",
    tools=[{
        "type": "web_search",
        "search_context_size": "medium"
    }]
)

# Contexte large : analyses approfondies
response = client.responses.create(
    model="gpt-5.6-terra",
    input="Compare les strategies IA de la France, l'Allemagne et les Pays-Bas",
    tools=[{
        "type": "web_search",
        "search_context_size": "high"
    }]
)

Impact sur les coûts et la latence

La règle empirique tient en une phrase : montez d’un cran seulement quand la réponse obtenue vous a concrètement déçu. Une date, un chiffre, une confirmation factuelle n’exigent rien de plus que low, et y consacrer high revient à payer un dossier complet pour lire une ligne.

TailleTokens contexteLatenceCoûtUsage
lowMinimalRapideFaibleFaits simples, chiffres
mediumModéréStandardMoyenSynthèses, comparaisons
highMaximalPlus lentÉlevéAnalyses approfondies

Guider les requêtes de recherche par le prompt

Voici le point que l’on découvre généralement trop tard : le modèle formule ses propres requêtes de recherche. Vous écrivez « quelles sont les évolutions réglementaires récentes ? » et il traduit cela en mots-clés que vous ne voyez pas. La qualité des résultats dépend donc d’une reformulation sur laquelle vous n’avez qu’une prise indirecte — le prompt système. Nommez-y les sources qui font autorité dans votre domaine et la période qui vous intéresse : c’est ce qui déplace le plus l’aiguille.

response = client.responses.create(
    model="gpt-5.6-terra",
    instructions=(
        "Tu es un analyste de marche spécialisé en technologie européenne. "
        "Quand tu fais des recherches web, privilegia les sources institutionnelles "
        "(Commission européenne, INSEE, Eurostat) et les médias spécialisés "
        "(Les Echos, La Tribune, TechCrunch). "
        "Ignore les blogs personnels et les forums."
    ),
    input="Quel est l'état du financement des startups IA en France ?",
    tools=[{
        "type": "web_search",
        "search_context_size": "high"
    }]
)

Extraire et structurer les citations

Les citations arrivent sous forme d’annotations attachées à la réponse, et non dans le texte lui-même. Cette séparation est une bonne nouvelle : elle vous permet d’afficher les sources comme vous l’entendez, de les vérifier, ou de refuser une réponse qui n’en comporte aucune. Dans toute application où la réponse engage — juridique, médical, financier —, traiter l’absence d’annotation comme une erreur est plus sûr que de faire confiance au texte.

def extraire_sources(response) -> list[dict]:
    """Extrait toutes les citations URL d'une réponse avec Web Search."""
    sources = []
    for item in response.output:
        if item.type == "message":
            for block in item.content:
                if hasattr(block, "annotations"):
                    for ann in block.annotations:
                        if ann.type == "url_citation":
                            sources.append({
                                "url": ann.url,
                                "titre": ann.title,
                                "extrait_debut": ann.start_index,
                                "extrait_fin": ann.end_index
                            })
    return sources

# Utilisation
response = client.responses.create(
    model="gpt-5.6-terra",
    input="Quelles sont les nouvelles règles RGPD pour l'IA en 2026 ?",
    tools=[{"type": "web_search"}]
)

sources = extraire_sources(response)
for s in sources:
    print(f"  {s['titre']}: {s['url']}")

Pattern : recherche avec validation croisée

Une source unique reste une source unique, même trouvée par un modèle. Sur une information qui engage une décision, demandez explicitement la confirmation par plusieurs sources indépendantes et faites signaler les divergences plutôt que de les laisser arbitrer en silence : un désaccord entre deux sources est en soi une information, souvent plus utile que la moyenne des deux.

def recherche_validee(question: str, min_sources: int = 3) -> dict:
    """Recherche web avec exigence de sources multiples."""
    response = client.responses.create(
        model="gpt-5.6-terra",
        instructions=(
            f"Pour répondre a cette question, tu dois trouver au moins "
            f"{min_sources} sources independantes qui confirment l'information. "
            "Si les sources se contredisent, signale les divergences. "
            "Cite chaque source explicitement."
        ),
        input=question,
        tools=[{
            "type": "web_search",
            "search_context_size": "high"
        }]
    )

    sources = extraire_sources(response)
    return {
        "reponse": response.output_text,
        "sources": sources,
        "fiabilite": "haute" if len(sources) >= min_sources else "a_verifier"
    }

Gérer l’absence de résultats

Reste le cas que l’on oublie de traiter : la recherche ne donne rien. Le risque n’est pas l’absence de réponse — c’est qu’à défaut de résultats, le modèle réponde depuis ses connaissances internes sans le signaler, et vous rende une information plausible mais périmée. Demandez-lui de le dire explicitement, et prévoyez la reformulation.

def recherche_avec_fallback(question: str) -> dict:
    """Recherche web avec detection d'échec et reformulation."""
    # Premiere tentative
    response = client.responses.create(
        model="gpt-5.6-terra",
        input=question,
        tools=[{"type": "web_search"}]
    )

    sources = extraire_sources(response)

    if len(sources) == 0:
        # Reformulation automatique
        response = client.responses.create(
            model="gpt-5.6-terra",
            input=f"Reformule cette question pour une recherche web plus efficace, "
                  f"puis cherche : {question}",
            tools=[{"type": "web_search", "search_context_size": "high"}]
        )
        sources = extraire_sources(response)

    return {
        "reponse": response.output_text,
        "sources": sources
    }

Web Search avec streaming

Une recherche web prend quelques secondes, parfois plus si le modèle enchaîne plusieurs requêtes. En streaming, l’utilisateur voit la réponse se construire au lieu de fixer un indicateur de chargement — et sur ce type de latence, la différence de perception est considérable pour un coût d’implémentation quasi nul.

stream = client.responses.create(
    model="gpt-5.6-terra",
    input="Quelles sont les actualités tech de la semaine ?",
    tools=[{"type": "web_search"}],
    stream=True
)

for event in stream:
    if event.type == "response.output_text.delta":
        print(event.delta, end="", flush=True)
    elif event.type == "response.completed":
        # Extraire les sources a la fin
        sources = extraire_sources(event.response)
        print(f"\n\n--- {len(sources)} sources consultees ---")

Filtrer les domaines et lister les sources

L’outil web_search accepte un paramètre filters qui restreint la recherche à une liste de domaines autorisés (jusqu’à 100) ou en exclut une liste (jusqu’à 100 également). Écrivez les domaines sans http:// ni https://. Le filtrage n’existe qu’avec web_search dans l’API Responses : l’ancien outil web_search_preview l’ignore.

response = client.responses.create(
    model="gpt-5.6-terra",
    tools=[{
        "type": "web_search",
        "filters": {"allowed_domains": ["service-public.fr", "legifrance.gouv.fr"]},
    }],
    include=["web_search_call.action.sources"],
    input="Quelles sont les obligations d'affichage des prix pour un commerce en France ?",
)
print(response.output_text)

L’option include=["web_search_call.action.sources"] renvoie la liste complète des URL consultées, souvent plus longue que celle des citations. Les citations, elles, arrivent sous forme d’annotations url_citation (URL, titre, position dans le texte) : la documentation d’OpenAI demande de les afficher de façon visible et cliquable dans votre interface.

Points clés à retenir

  • search_context_size contrôle le volume de données web injecté
  • filters restreint ou exclut des domaines (100 au plus), include liste toutes les sources consultées
  • Le prompt système guide le modèle vers les bonnes sources
  • Extrayez les annotations url_citation pour tracer les sources
  • Implémentez une validation croisée pour les informations critiques
  • Gérez l’absence de résultats avec reformulation automatique