Accueil / Articles

ToolCallingAgent contre CodeAgent sur les modèles locaux Qwen2.5 de 14 milliards de paramètres.

ToolCallingAgent contre CodeAgent dans smolagents sur un Mac M4 : vitesse et précision de routage avec les modèles locaux Qwen2.5 14B instruct et coder à plusieurs températures.

Éditeur : REACTAPP.TOP4 min de lecture848 mots

Sources: ToolCallingAgent vs. CodeAgent: Which Performs Better on a Local LLM?

Les configurations d’agents locaux révèlent rapidement des points faibles. La machine utilisée était un Mac Apple M4 de base doté de 16 Go de mémoire unifiée, sans capacité d’inférence en cloud ni de VRAM supplémentaire à disposition, de sorte qu’une fenêtre de contexte même modérée peut déclencher le swap. Deux styles d’agents provenant de smolagents, ToolCallingAgent et CodeAgent, ont été testés chacun sur deux modèles exécutés localement : qwen2.5-coder:14b et qwen2.5:14b-instruct. Ces deux modèles partagent une taille de 14 milliards de paramètres et une architecture de base, et tous deux ont été exécutés sur la même machine.

  • Qwen2.5:14b-instruct est le modèle polyvalent de la série de 14 milliards de paramètres, ajusté à partir de données d’instructions et de dialogues divers afin de bien suivre les commandes.
  • qwen2.5-coder:14b utilise la même architecture de base mais a bénéficié d’un préentraînement supplémentaire sur de grandes quantités de code, ainsi que d’un affinage ciblé sur ce type de données.

Avec un budget matériel aussi restreint, on ne s’attendait pas à ce que l’une ou l’autre configuration soit exceptionnelle. La question plus intéressante était de savoir où chacune d’elles rencontrait des limites, et si le choix d’un type d’agent différent pourrait atténuer ces contraintes.

La configuration

Une variation de température à 0, 0,1, 0,3 et 0,6 a été testée sur les deux types d’agents pour une seule tâche : trouver les cinq meilleurs restaurants de pizza à Seattle, vérifier le temps d’attente dans chacun d’eux et ne recommander que ceux correspondant au seuil fixé par le client. Les fonctions qui calculent les temps d’attente et les comparent au seuil sont déterministes.

@tool
def get_wait_time(restaurant_name: str) -> int:
    """Current wait in minutes for a restaurant. Deterministic, not a live lookup."""

@tool
def restaurants_in_wait_limit(wait_time: int, wait_threshold: int) -> bool:
    """True if the wait is within the customer's threshold."""

La conception déterministe est intentionnelle. Une recherche en temps réel permettrait à un modèle d’estimer un temps d’attente plausible et de continuer. Une appel de fonction forcé vérifie ce qui est important ici : si l’agent se fie à l’outil plutôt que d’inventer une valeur, et si cela reste vrai lorsque la température ou le type d’agent change.

Trois éléments ont été suivis : la latence, le fait qu’une exécution soit terminée, et la précision du routage, définie comme la proportion de l’ensemble de la chaîne d’outils exécutée correctement à chaque appel. Considérez ces chiffres comme une mesure indicative, car il ne s’agit pas d’un benchmark formel.

En quoi les deux agents diffèrent

Avec ToolCallingAgent, chaque étape génère un seul appel d’outil en JSON. Le modèle fournit les arguments, le framework exécute l’outil, puis la étape suivante commence. Cinq restaurants et deux fonctions donnent un total de dix appels distincts, et chacun représente une nouvelle occasion de fausser la sortie structurée.

CodeAgent emprunte une autre approche et génère un extrait de Python qui s’exécute en une seule étape. Une seule boucle peut couvrir tous les restaurants et appeler les deux fonctions à l’intérieur d’elle. Une boucle correcte fonctionne correctement pour tous eux lors de cette exécution, ce qui signifie que la décision est prise une seule fois plutôt que dix fois.

Résultats

Avec Qwen2.5:14b-instruct

Les deux agents se sont bien comportés. CodeAgent a maintenu une précision de routage de 1,00 à toutes les températures, tandis que ToolCallingAgent est resté entre 0,95 et 1,00. Aucune différence significative n’a été observée en termes de correction.

La vitesse raconte une histoire différente. ToolCallingAgent fonctionne environ deux fois plus lentement, avec environ cinq minutes par exécution contre environ deux minutes et demie pour CodeAgent. La cause est structurelle : ToolCallingAgent doit effectuer une nouvelle requête vers le modèle à chaque étape, en réenvoyant le contexte de la conversation et en générant du contenu à partir de zéro à chaque fois. CodeAgent, quant à lui, ne le fait qu’une seule fois. Sur une machine locale où chaque génération est déjà lente, ce surcoût ne peut être ignoré.

Au sujet de Qwen2.5-coder:14b

Ici, les deux agents ont montré des différences marquées. ToolCallingAgent n’a jamais atteint 50 % de précision dans le routage, quel que soit le paramètre de température, restant entre 0,40 et 0,50. Il fonctionnait plus rapidement que sur le modèle d’instructions, mais ce n’était pas un bon signe. Il était rapide parce qu’il abandonnait. Dès que le fil de discussion était perdu, il cessait d’envoyer des requêtes et terminait plus tôt, ayant accompli moins de travail.

CodeAgent a remporté la victoire haut la main avec une précision de routage de 1,00, égalant les meilleurs scores obtenus. C’est attendu, car il demande au modèle de codage de générer du Python et jamais du JSON structuré.

Que retenir de cela

L’avantage de la boucle chez CodeAgent est réel. Sur le modèle instruct, où les deux agents ont obtenu 1,00 en termes de routage, le regroupement des tâches a permis à CodeAgent d’être deux fois plus rapide que ToolCallingAgent.

Qwen2.5:14b-instruct se révèle être un généraliste fiable, à l’aise tant avec les appels JSON structurés que avec du code simple. Qwen2.5-coder:14b convient mieux aux tâches de codage exigeantes, car il peut être peu fiable pour générer du JSON structuré et le maintenir de manière cohérente au fil d’une série d’appels.

Une question en suspens

Une question reste en suspens. Deux éléments distinguent ces agents : CodeAgent regroupe son travail en un seul programme et écrit en Python plutôt qu’en JSON structuré. L’expérience suivante pourrait les comparer en faisant en sorte que CodeAgent émette des appels d’outils structurés tout en continuant à fonctionner en mode batch. Le résultat indiquerait si l’avantage provient principalement des boucles, ou du fait que les modèles trouvent plus facile de générer du code qu’une longue série d’appels JSON.