- En utilisant TensorZero comme proxy open source, l’auteur a intercepté et analysé le trafic entre Cursor et les fournisseurs de LLM (OpenAI, etc.), puis a partagé son expérience d’observation en temps réel des prompts, modèles et résultats d’inférence, ainsi que ses expérimentations d’optimisation
- Cursor permet de surcharger la Base URL et le nom du modèle lors des appels LLM, ce qui facilite l’intégration d’un proxy maison comme TensorZero
- En interne, Cursor appelle les LLM via ses propres serveurs ; pour une configuration proxy complète, il faut donc mettre en place Ngrok + un reverse proxy Nginx ainsi que les en-têtes CORS
- Le proxy permet d’observer jusqu’au system prompt, au user prompt et aux requêtes d’édition de code inline réellement envoyés par Cursor au LLM, et de basculer/expérimenter en temps réel avec différents LLM (tests A/B)
- L’analyse du system prompt de Cursor montre qu’un prompt d’environ 642 tokens seulement suffit au LLM pour comprendre et traiter la majorité des contextes de génie logiciel. L’édition de code est prise en charge par un « apply model » distinct, un modèle auxiliaire moins intelligent
- Avec une architecture proxy comme TensorZero, il devient possible de mener des expérimentations LLM personnalisées par utilisateur et une optimisation fondée sur le feedback ; cette approche est idéale pour l’évaluation de la qualité des assistants de code (tests A/B), l’optimisation des prompts et la supervision en conditions réelles
Introduction
- Présentation d’un retour d’expérience sur l’utilisation du framework open source TensorZero comme passerelle proxy entre Cursor et divers LLM (grands modèles de langage), ainsi que des observations, expérimentations et pistes d’optimisation qui en découlent
- TensorZero est un projet open source conçu pour améliorer la qualité des applications LLM en exploitant des signaux de feedback (indicateurs de production, comportements utilisateurs, etc.)
- En tant qu’utilisateur de Cursor, l’auteur a appliqué cette technique à l’IDE basé sur LLM qu’il utilise le plus, afin d’examiner les requêtes API réellement échangées et de tester lui-même différentes optimisations
Vue d’ensemble et objectif
- Cursor est un assistant de développement optimisé à l’échelle de l’ensemble de ses utilisateurs, mais il est presque impossible d’y mener des expérimentations d’optimisation personnalisées ou d’observer les données de manière fine au niveau individuel
- En plaçant TensorZero comme proxy, il devient possible d’observer en toute transparence l’ensemble des requêtes de Cursor, les réponses du LLM, les prompts, les modèles et le processus d’inférence, puis d’étendre cela à l’expérimentation et à l’optimisation
- Comme la plupart des méthodes d’optimisation, d’évaluation et d’expérimentation nécessitent des données d’inférence réelles, l’article présente concrètement des moyens de les collecter et de les automatiser
Intégration : mise en place de la passerelle LLM
- Cursor permet de personnaliser l’OpenAI base URL et le nom du modèle
- TensorZero fournit un endpoint d’inférence compatible OpenAI, ce qui permet de connecter Cursor à TensorZero à la place d’OpenAI
- En enregistrant une fonction
cursorzero dans TensorZero, il devient possible d’automatiser le stockage des données d’inférence et de feedback tout en menant des expérimentations sur différents modèles/prompts et sans dépendre d’un fournisseur unique
Premier obstacle : les serveurs propres à Cursor
- Cursor a tenté de se connecter directement à TensorZero local, mais cela a échoué
- Cursor envoie toujours d’abord les requêtes à ses propres serveurs, puis poursuit l’appel LLM après un traitement interne
- Cela signifie que les identifiants sont transmis aux serveurs de Cursor, lesquels peuvent ainsi collecter des données sur toutes les requêtes et l’ensemble de la base de code
- Comme solution de contournement, l’auteur a testé une connexion via OpenRouter afin de vérifier, dans certaines interactions de Cursor, la possibilité d’utiliser des modèles externes
- L’autocomplétion Tab de Cursor fonctionne avec son propre modèle propriétaire, tout en pouvant être combinée avec d’autres LLM
- La solution finale consiste à utiliser un reverse proxy et Ngrok pour faire transiter, via un endpoint public, les requêtes vers TensorZero en interne
- Nginx est placé en frontal pour ajouter une authentification, renforcer la sécurité et achever le routage LLM via une fonction TensorZero personnalisée
- Architecture finale :
- Cursor → Ngrok → Nginx (authentification) → TensorZero (local) → fournisseur LLM
Deuxième obstacle : CORS
- Lors de l’authentification, une requête CORS preflight (OPTIONS) atteint Nginx, ce qui empêche l’authentification initiale de se dérouler correctement
- Nginx a été configuré pour renvoyer les en-têtes CORS identiques à ceux de l’API OpenAI, afin de répondre aux exigences de l’IDE Cursor basé sur Electron
- Une fois les problèmes d’authentification et de CORS résolus, toutes les requêtes réelles passent par les serveurs de Cursor
- (Exemple de configuration Nginx inclus)
Résultat final : il devient possible d’inspecter Cursor
- Il devient possible d’observer en temps réel toutes les requêtes/réponses LLM, le system prompt, le user prompt, ainsi que le contenu du code et des fichiers joints
- L’exemple de system prompt précise même les instructions permettant d’activer un « apply model » distinct pour l’édition de code (structure en couches à deux modèles)
- Principales caractéristiques de la structure de prompt de Cursor :
- fourniture du contexte, comme les informations de session utilisateur, les fichiers et la position du curseur
- délimitation des sections au moyen de blocs de commentaires, etc.
- lors des demandes de modification de code, consignes pour générer un bloc de code en minimisant strictement les parties modifiées
- Le prompt engineering de Cursor
- un unique grand system prompt de 642 tokens suffit à automatiser la majorité des tâches de génie logiciel
- Un apply model moins intelligent, spécialisé dans les changements de code, existe séparément comme modèle auxiliaire et reçoit des consignes explicites sur la cible d’application et les règles à suivre
- cela confirme que des architectures en couches de LLM (séparation de l’intelligence et des fonctions) sont réellement implémentées dans le prompt lui-même
Conclusion et implications
- Cursor est capable de traiter le contexte du génie logiciel grâce aux connaissances natives des LLM récents et à des prompts concis
- Avec un proxy comme TensorZero, il est facile de mettre en place une architecture d’optimisation fondée sur le feedback utilisateur et les données d’usage réelles (tests A/B, ajustement de prompts/modèles)
- Les entreprises qui déploient des IA d’assistance au code ou des LLM dans leurs produits peuvent utiliser cette approche pour expérimenter rapidement la conception de prompts, l’amélioration des performances et l’optimisation par utilisateur
- Un prochain article abordera les expérimentations suivantes, notamment les méthodes de collecte de données en usage réel, Tree-sitter et l’utilisation de git hooks
1 commentaires
Avis Hacker News
Cursor est le seul produit, parmi les services que j’utilise depuis plus de 20 ans, dont j’ai annulé l’abonnement à cause de l’absence totale de support client
Pendant plusieurs semaines, j’ai envoyé plusieurs e-mails au sujet d’un problème de facturation, sans jamais recevoir la moindre réponse
Ce n’était pas une simple question liée à VS Code, mais un problème qui nécessitait absolument l’intervention de l’équipe Cursor
En revanche, les e-mails promotionnels, eux, arrivaient très bien
J’espère que la « valeur » de Cursor se diffusera vite à d’autres services
J’espère que la prochaine équipe répondra aux e-mails
Il manque beaucoup de choses dans ce prompt
L’absence de descripteurs d’appels d’outils est ce qui saute le plus aux yeux
On peut d’ailleurs le comparer directement à un prompt de jailbreaking d’il y a un an
Cela dit, d’autres éléments de configuration comme les cursor rules sont intéressants
À titre de référence, on peut voir des ressources liées aux prompts ici
Cursor utilise des prompts différents selon l’action effectuée par l’utilisateur
Pour l’instant, seul un échantillon a été fourni, mais l’objectif fondamental est de faire de l’A/B testing entre différents modèles et d’optimiser les prompts et les modèles
Du code a aussi été fourni pour permettre la reproduction, et on peut y consulter d’autres prompts
Le Gist que tu as partagé est lui aussi assez utile
Je me demande s’il n’y a pas une logique d’optimisation qui fait que seules les informations d’outils strictement nécessaires à la requête de l’utilisateur sont incluses dans le prompt
Ils ont peut-être une stratégie assez agressive consistant à supprimer les descripteurs d’outils inutiles pour économiser des tokens
Une référence utile à ce sujet se trouve ici
Donc... on ne peut plus utiliser wireshark maintenant ?
Il est précisé à la fin de l’article qu’il ne s’agit que d’un premier billet de survol avant de décider comment l’utiliser
À noter qu’aujourd’hui, mitmproxy est devenu excellent même pour simplement inspecter les paquets mitmproxy docs
wireshark peut être utilisé pour voir les requêtes qui partent de l’application desktop vers les serveurs de Cursor, donc en pratique celles envoyées au LLM
En revanche, si on veut voir comment la requête réelle part des serveurs de Cursor vers le LLM, il faut une configuration supplémentaire
Avec ce type de configuration, on pourrait aussi faire de l’A/B testing en modifiant les requêtes
Cursor et les différentes solutions de modalité IDE sont intéressants, mais c’est dommage qu’ils donnent l’habitude de traiter le contexte de façon approximative
Si l’on regarde un extrait du prompt de Cursor,
c’est du type : « À chaque fois que l’utilisateur envoie un message, nous pouvons automatiquement ajouter des informations supplémentaires comme l’état courant, l’historique des modifications de la session, les erreurs du linter, etc., et ces informations peuvent ou non être liées à la tâche de code. À toi d’en juger la pertinence. »
Ce type de « gonflement du contexte » limite fortement les performances des LLM quand il s’agit de résoudre de vrais problèmes difficiles
Le problème de
.envpris en exemple est d’un type simple, donc Cursor le gère bien, mais avec ce niveau de complexité on ne peut pas continuer à employer des ingénieurs logicielsPersonnellement, quand on travaille avec l’IA, je recommanderais d’abord de réfléchir à la manière de garder un contexte de conversation propre dans l’interface de chat
Sur des problèmes complexes, le contexte se retrouve imbriqué entre réunions, conversations Slack, documentation interne, contenus externes, code, etc.
J’ai créé des outils comme FileKitty(lien) et, plus récemment, slackprep(lien) pour filtrer uniquement les informations pertinentes à la résolution du problème et les utiliser de manière plus intentionnelle
Il fallait rédiger les consignes en incluant uniquement ce qui était effectivement joint, pas « ce qui pourrait être joint automatiquement »
Au lieu de dire « cela peut être pertinent ou non, à toi de voir », il est plus efficace d’avoir des instructions claires sur ce qu’il faut faire dans les cas où c’est pertinent et ceux où ça ne l’est pas
Ce n’est pas très problématique quand le contexte est court, mais sur des sujets longs et complexes, ce niveau de précision fait une grande différence
Cursor semble probablement garder des instructions aussi générales que possible pour profiter des avantages tarifaires des cached tokens
Beaucoup d’éléments restent encore au stade expérimental, et on verra sans doute encore beaucoup d’améliorations sur les prompts et les modèles
Une autre analyse des prompts de Cursor peut être consultée ici
Je me suis toujours demandé comment se faisait la sélection du contexte pertinent dans les longues conversations
Je me demande si quelqu’un a réellement fait du reverse engineering de cette logique pour comprendre comment l’historique des transformations est tronqué et comment l’état le plus récent des fichiers est représenté
Je vais continuer à examiner ce point, et poursuivre les expérimentations d’optimisation des modèles et des prompts avec TensorZero
Je suis en train d’analyser la même chose avec mitmproxy discussion associée
Maintenant qu’on connaît les informations de prompt, je me demande s’il serait possible de réimplémenter les serveurs de Cursor pour créer une version entièrement locale, ou une sorte de version crackée
Ou alors, il vaut mieux utiliser dès le départ des projets open source spécialisés dans le codage agentique, comme Cline ou Roo Code
C’est un peu surprenant d’avoir attendu uniquement la publication des prompts pour tenter cela
Le modèle apply de Cursor semble tourner côté serveur
Je me demande à quel point il serait difficile d’implémenter directement un modèle apply local
Sur un MacBook, ce serait peut-être même beaucoup plus rapide
C’est clairement possible