Aller au contenu principal

Tool Search : outils dynamiques

Tool Search : outils dynamiques

Quand vous avez des dizaines ou des centaines de fonctions, les declarer toutes dans chaque appel devient contre-productif : le modele perd en precision et les couts explosent. Tool Search resout ce probleme en permettant au modele de chercher l’outil adapte dans un catalogue indexe.

Le probleme des catalogues d’outils larges

Avec le function calling classique, chaque fonction declaree consomme des tokens dans le contexte :

# 5 fonctions = ~500 tokens de contexte
# 50 fonctions = ~5000 tokens de contexte
# 200 fonctions = impossible a gerer efficacement

# Le modele perd en precision quand il y a trop de fonctions
# Il choisit parfois la mauvaise fonction ou hallucine des parametres

Tool Search indexe vos definitions de fonctions et ne presente au modele que les plus pertinentes :

from openai import OpenAI

client = OpenAI()

# Declarer un grand nombre de fonctions
toutes_les_fonctions = [
    {
        "type": "function",
        "name": "creer_facture",
        "description": "Creer une nouvelle facture pour un client",
        "parameters": {"type": "object", "properties": {"client_id": {"type": "string"}}, "required": ["client_id"]}
    },
    {
        "type": "function",
        "name": "annuler_facture",
        "description": "Annuler une facture existante",
        "parameters": {"type": "object", "properties": {"facture_id": {"type": "string"}}, "required": ["facture_id"]}
    },
    # ... des dizaines d'autres fonctions
]

# Utiliser Tool Search pour laisser le modele trouver la bonne fonction
response = client.responses.create(
    model="gpt-5.3",
    input="Annule la facture FAC-2026-0042",
    tools=[{
        "type": "tool_search",
        "tool_search": {
            "tools": toutes_les_fonctions
        }
    }]
)

Le modele ne recoit dans son contexte que les fonctions pertinentes pour la requete, pas la totalite du catalogue.

Organiser le catalogue de fonctions

Pour que Tool Search soit efficace, structurez vos fonctions avec des descriptions claires :

catalogue_crm = [
    {
        "type": "function",
        "name": "crm_rechercher_client",
        "description": "Rechercher un client dans le CRM par nom, email ou identifiant. "
                       "Utiliser pour trouver les informations d'un client existant.",
        "parameters": {
            "type": "object",
            "properties": {
                "terme": {"type": "string", "description": "Terme de recherche"},
                "champ": {"type": "string", "enum": ["nom", "email", "id"]}
            },
            "required": ["terme"],
            "additionalProperties": false
        },
        "strict": true
    },
    {
        "type": "function",
        "name": "crm_creer_client",
        "description": "Creer un nouveau client dans le CRM. "
                       "Utiliser quand un client n'existe pas encore.",
        "parameters": {
            "type": "object",
            "properties": {
                "nom": {"type": "string"},
                "email": {"type": "string"},
                "entreprise": {"type": "string"}
            },
            "required": ["nom", "email", "entreprise"],
            "additionalProperties": false
        },
        "strict": true
    }
]

catalogue_facturation = [
    {
        "type": "function",
        "name": "fact_creer_facture",
        "description": "Creer une facture. Necessite un client existant.",
        "parameters": {
            "type": "object",
            "properties": {
                "client_id": {"type": "string"},
                "lignes": {"type": "array", "items": {"type": "object", "properties": {
                    "description": {"type": "string"},
                    "montant": {"type": "number"}
                }}}
            },
            "required": ["client_id", "lignes"],
            "additionalProperties": false
        },
        "strict": true
    }
]

# Fusionner tous les catalogues
catalogue_complet = catalogue_crm + catalogue_facturation

Bonnes pratiques pour les descriptions

La qualite du Tool Search depend des descriptions. Le moteur de recherche vectoriel indexe ces textes :

# Mauvais : trop generique
{"name": "get_data", "description": "Recuperer des donnees"}

# Bon : specifique avec contexte d'usage
{
    "name": "rh_consulter_solde_conges",
    "description": "Consulter le solde de conges (CP, RTT, maladie) d'un salarie. "
                   "Retourne les jours restants par type de conge. "
                   "Utiliser quand un salarie demande combien de jours il lui reste."
}

# Bon : avec des synonymes pour ameliorer la recherche
{
    "name": "compta_rapprocher_banque",
    "description": "Rapprochement bancaire : comparer les ecritures comptables "
                   "avec les mouvements bancaires. Reconciliation des comptes. "
                   "Utiliser pour verifier la coherence entre la comptabilite "
                   "et les releves de banque."
}

Combiner Tool Search avec des outils fixes

Vous pouvez melanger des outils toujours disponibles avec un catalogue dynamique :

response = client.responses.create(
    model="gpt-5.3",
    input="Cherche les ventes du mois sur le web et cree la facture correspondante",
    tools=[
        # Outils toujours disponibles
        {"type": "web_search_preview"},
        {"type": "code_interpreter"},
        # Catalogue dynamique
        {
            "type": "tool_search",
            "tool_search": {
                "tools": catalogue_complet  # 200+ fonctions
            }
        }
    ]
)

Pattern : systeme multi-domaines

class SystemeMultiDomaines:
    def __init__(self):
        self.client = OpenAI()
        self.catalogues = {}

    def enregistrer_domaine(self, nom: str, fonctions: list[dict]):
        """Enregistre un catalogue de fonctions pour un domaine."""
        self.catalogues[nom] = fonctions

    def catalogue_complet(self) -> list[dict]:
        """Fusionne tous les catalogues."""
        result = []
        for fonctions in self.catalogues.values():
            result.extend(fonctions)
        return result

    def executer(self, requete: str) -> str:
        """Execute une requete avec Tool Search sur tous les domaines."""
        response = self.client.responses.create(
            model="gpt-5.3",
            input=requete,
            tools=[{
                "type": "tool_search",
                "tool_search": {
                    "tools": self.catalogue_complet()
                }
            }]
        )

        # Traiter les appels de fonction
        for item in response.output:
            if item.type == "function_call":
                resultat = self.dispatcher(item.name, item.arguments)
                # ... boucle de function calling

        return response.output_text

    def dispatcher(self, name: str, arguments: str):
        """Route l'appel vers le bon service."""
        # Votre logique de routage
        pass

# Utilisation
systeme = SystemeMultiDomaines()
systeme.enregistrer_domaine("crm", catalogue_crm)
systeme.enregistrer_domaine("facturation", catalogue_facturation)
systeme.enregistrer_domaine("rh", catalogue_rh)
systeme.enregistrer_domaine("support", catalogue_support)

# Le modele trouve automatiquement la bonne fonction
# parmi des centaines de possibilites
resultat = systeme.executer("Combien de jours de conges reste-t-il a Marie Dupont ?")

Points cles a retenir

  • Tool Search resout le probleme des catalogues de fonctions volumineux
  • Le modele ne recoit que les fonctions pertinentes dans son contexte
  • Des descriptions riches et specifiques sont essentielles pour la precision
  • Prefixez les noms de fonctions par domaine pour la lisibilite
  • Combinez Tool Search avec des outils built-in toujours disponibles