Explorer ChatGPT par rapport aux modèles open source sur des tâches légèrement plus difficiles

May 13 2023
Les LLM open source comme Vicuna et MPT-7B-Chat apparaissent partout, ce qui a conduit à de nombreuses discussions sur la façon dont ces modèles se comparent aux LLM commerciaux (comme ChatGPT ou Bard). La majeure partie de la comparaison a porté sur les réponses à des questions/instructions simples à un tour.
Toutes les images ont été générées par Marco et Scott.

Les LLM open source comme Vicuna et MPT-7B-Chat apparaissent partout, ce qui a conduit à de nombreuses discussions sur la façon dont ces modèles se comparent aux LLM commerciaux (comme ChatGPT ou Bard).

La majeure partie de la comparaison a porté sur les réponses à des questions/instructions simples à un tour. Par exemple, les gens de LMSYSOrg ont fait une analyse intéressante (+1 pour être automatisé et reproductible) comparant Vicuna-13B à ChatGPT sur diverses questions courtes, ce qui est excellent pour comparer les modèles en tant que simples chatbots. Cependant, de nombreuses façons intéressantes d'utiliser les LLM nécessitent généralement des instructions complexes et/ou des conversations à plusieurs tours, et une ingénierie rapide. Nous pensons que dans le "monde réel", la plupart des gens voudront comparer différentes offres LLM sur leur problème, avec une variété d'invites différentes.

Ce billet de blog (écrit conjointement avec Scott Lundberg ) est un exemple de ce à quoi pourrait ressembler une telle exploration avec guidance, un projet open source qui aide les utilisateurs à contrôler les LLM. Nous comparons deux modèles open source (Vicuna-13B, MPT-7b-Chat) avec ChatGPT (3.5) sur des tâches de complexité variable.

Échauffement : résolution d'équations

En guise d'échauffement, commençons par la tâche jouet de résoudre des équations polynomiales simples, où nous pouvons vérifier l'exactitude de la sortie et ne devrait pas nécessiter beaucoup d'ingénierie rapide. Ce sera similaire à la catégorie Math ici , à la différence que nous évaluons les modèles comme corrects / incorrects sur la vérité terrain, plutôt que d'utiliser GPT-4 pour évaluer la sortie.

Digression rapide sur la syntaxe du chat : chacun de ces modèles a sa propre syntaxe de chat, avec des jetons spéciaux séparant les énoncés. Voici à quoi ressemblerait la même conversation dans Vicuna et MPT (où [generated response]est l'endroit où le modèle générerait sa sortie) :

Vigogne :

A chat between a curious user and an artificial intelligence assistant. The assistant gives helpful, detailed, and polite answers to the user's questions.  
USER: Can you please solve the following equation? x^2 + 2x + 1 = 0  
ASSISTANT: [generated response] </s>

<|im_start|>system
- You are a helpful assistant chatbot trained by MosaicML.  
- You answer questions.
- You are excited to be able to help the user, but will refuse to do anything that could be considered harmful to the user.
- You are more than just an information source, you are also able to write poetry, short stories, and make jokes.
<|im_end|>
<|im_start|>user Can you please solve the following equation? x^2 + 2x + 1 = 0<|im_end|>
<|im_start|>assistant [generated response]<|im_end|>

find_roots = guidance('''
{{#system~}}
{{llm.default_system_prompt}}
{{~/system}}

{{#user~}}
Please find the roots of the following equation: {{equation}}
Think step by step, find the roots, and then say:
ROOTS = [root1, root2...]
For example, if the roots are 1.3 and 2.2, say ROOTS = [1.3, 2.2].
Make sure to use real numbers, not fractions.
{{~/user}}

{{#assistant~}}
{{gen 'answer'}}
{{~/assistant~}}''')

import guidance

mpt = guidance.llms.transformers.MPTChat('mosaicml/mpt-7b-chat', device=1)
vicuna = guidance.llms.transformers.Vicuna('yourpath/vicuna-13b', device_map='auto')
chatgpt = guidance.llms.OpenAI("gpt-3.5-turbo")

equation = 'x^2 + 3.0x = 0'
roots = [0, -3]
answer_gpt = find_roots(llm=chatgpt, equation=equation)

      
                

answer_vicuna = find_roots(llm=vicuna, equation=equation)

      
                

answer_mpt = find_roots(llm=mpt, equation=equation)

      
                

Dans le cahier accompagnant cet article, nous écrivons une fonction pour générer des équations quadratiques aléatoires avec des racines entières entre -20 et 20, et exécutons l'invite 20 fois avec chaque modèle. Les résultats étaient les suivants :

╔═══════════╦══════════╦
║   Model   ║ Accuracy ║     
╠═══════════╬══════════╬
║ ChatGPT   ║   80%    ║
║ Vicuna    ║    0%    ║ 
║ MPT       ║    0%    ║
╚═══════════╩══════════╩

ChatGPT fait une erreur de calcul à la dernière étape, où (13 +- 25) /2devrait rapporter [19, -6]plutôt que [19.5, -6.5].
Maintenant, puisque Vicuna et MPT ont échoué sur les équations quadratiques, nous examinons des équations encore plus simples, telles que x - 10 = 0. Pour ces équations, nous obtenons ces nombres :

╔═══════════╦══════════╦
║   Model   ║ Accuracy ║     
╠═══════════╬══════════╬
║ ChatGPT   ║   100%   ║
║ Vicuna    ║    85%   ║ 
║ MPT       ║    30%   ║
╚═══════════╩══════════╩

Discussion

Il s'agissait d'une tâche très ludique, mais qui servait d'exemple pour comparer des modèles avec différentes syntaxes de chat à l'aide de la même invite. Pour cette combinaison tâche/invite particulière, ChatGPT surpasse de loin Vicuna et MPT en termes de précision (mesurée sur la vérité terrain).

Tâche : extraire des extraits + répondre aux questions sur les réunions

Passons maintenant à une tâche plus réaliste, où l'évaluation de la précision n'est pas aussi simple. Disons que nous voulons que notre LLM réponde aux questions (avec les segments de conversation pertinents pour la mise à la terre) sur les transcriptions des réunions.
Il s'agit d'une application où certains utilisateurs pourraient préférer utiliser des LLM open source plutôt que des LLM commerciaux, pour des raisons de confidentialité (par exemple, certaines entreprises pourraient ne pas vouloir envoyer leurs données de réunion à OpenAI).

Voici une transcription de réunion de jouets pour commencer :

Transcription de la réunion :
John
: D'accord, nous sommes donc tous ici pour discuter de l'offre que nous avons reçue de Microsoft pour acheter notre startup. Que pensez-vous de ceci?
Lucy : Eh bien, je pense que c'est une grande opportunité pour nous. Microsoft est une énorme entreprise avec beaucoup de ressources, et ils pourraient vraiment nous aider à faire passer notre produit au niveau supérieur.
Steven : Je suis d'accord avec Lucy. Microsoft a beaucoup d'expérience dans l'industrie technologique, et ils pourraient nous fournir le soutien dont nous avons besoin pour développer notre entreprise.
John : Je vois ce que tu veux dire, mais j'hésite un peu à vendre notre startup. Nous avons consacré beaucoup de temps et d'efforts à la construction de cette entreprise, et je ne sais pas si je suis prêt à laisser tomber tout de suite.
Lucie: Je comprends où tu veux en venir, John, mais nous devons penser à l'avenir de notre entreprise. Si nous vendons à Microsoft, nous aurons accès à leurs ressources et à leur expertise, ce qui pourrait nous aider à développer encore plus notre entreprise.
Steven : D'accord, et n'oublions pas les avantages financiers. Microsoft nous offre beaucoup d'argent pour notre startup, ce qui pourrait nous aider à investir dans de nouveaux projets et à agrandir notre équipe.
John : Je vois ce que vous voulez dire, mais j'ai encore quelques réserves. Et si Microsoft changeait notre produit ou notre culture d'entreprise ? Et si nous perdions le contrôle de notre propre entreprise ?
Steven : Tu sais quoi, je n'y avais pas pensé avant, mais peut-être que John a raison. Ce serait dommage que notre culture change.
Lucie: Ce sont des préoccupations valables, mais nous pouvons négocier les termes de l'accord pour nous assurer que nous conservons un certain contrôle sur notre entreprise. Et en ce qui concerne le produit et la culture, nous pouvons travailler avec Microsoft pour nous assurer que notre vision est toujours intacte.
John : Mais ne changerons-nous pas simplement en étant absorbés par une grande entreprise ? Je veux dire, nous sommes une petite startup avec une culture très spécifique. Microsoft est une énorme entreprise avec une culture très différente. Je ne sais pas si les deux peuvent coexister.
Steven : Mais John, n'avons-nous pas toujours prévu d'être acquis ? Cela ne sera-t-il pas un problème à chaque fois ?
Lucy : C'est vrai
John : Je ne veux pas perdre ce que nous avons construit ici.
Steven : Je partage aussi cette inquiétude

Commençons par essayer de faire en sorte que ChatGPT résolve la tâche pour nous. Nous testerons la question "Que pense Steven de la vente?". Voici une première tentative d'invite

qa_attempt1 = guidance('''{{#system~}}
{{llm.default_system_prompt}}
{{~/system}}

{{#user~}}
You will read a meeting transcript, then extract the relevant segments to answer the following question:
Question: {{query}}
Here is a meeting transcript:
----
{{transcript}}
----
Please answer the following question:
Question: {{query}}
Extract from the transcript the most relevant segments for the answer, and then answer the question.
{{/user}}

{{#assistant~}}
{{gen 'answer'}}
{{~/assistant~}}''')

      
                

qa_attempt3 = guidance('''{{#system~}}
{{llm.default_system_prompt}}
{{~/system}}

{{#user~}}
You will read a meeting transcript, then extract the relevant segments to answer the following question:
Question: {{query}}
Here is a meeting transcript:
----
{{transcript}}
----
Based on the above, please answer the following question:
Question: {{query}}
Please extract from the transcript whichever conversation segments are most relevant for the answer, and then answer the question.
Note that conversation segments can be of any length, e.g. including multiple conversation turns.
Please extract at most 3 segments. If you need less than three segments, you can leave the rest blank.

As an example of output format, here is a fictitious answer to a question about another meeting transcript.
CONVERSATION SEGMENTS:
Segment 1: Peter and John discuss the weather.
Peter: John, how is the weather today?
John: It's raining.
Segment 2: Peter insults John
Peter: John, you are a bad person.
Segment 3: Blank
ANSWER: Peter and John discussed the weather and Peter insulted John.
{{/user}}

{{#assistant~}}
{{gen 'answer'}}
{{~/assistant~}}''')

      
                

qa_attempt5 = guidance('''{{#system~}}
{{llm.default_system_prompt}}
{{~/system}}

{{#user~}}
You will read a meeting transcript, then extract the relevant segments to answer the following question:
Question: What were the main things that happened in the meeting?
Here is a meeting transcript:
----
Peter: Hey
John: Hey
Peter: John, how is the weather today?
John: It's raining.
Peter: That's too bad. I was hoping to go for a walk later.
John: Yeah, it's a shame.
Peter: John, you are a bad person.
----
Based on the above, please answer the following question:
Question: {{query}}
Please extract from the transcript whichever conversation segments are most relevant for the answer, and then answer the question.
Note that conversation segments can be of any length, e.g. including multiple conversation turns.
Please extract at most 3 segments. If you need less than three segments, you can leave the rest blank.
{{/user}}
{{#assistant~}}
CONVERSATION SEGMENTS:
Segment 1: Peter and John discuss the weather.
Peter: John, how is the weather today?
John: It's raining.
Segment 2: Peter insults John
Peter: John, you are a bad person.
Segment 3: Blank
ANSWER: Peter and John discussed the weather and Peter insulted John.
{{~/assistant~}}
{{#user~}}
You will read a meeting transcript, then extract the relevant segments to answer the following question:
Question: {{query}}
Here is a meeting transcript:
----
{{transcript}}
----
Based on the above, please answer the following question:
Question: {{query}}
Please extract from the transcript whichever conversation segments are most relevant for the answer, and then answer the question.
Note that conversation segments can be of any length, e.g. including multiple conversation turns.
Please extract at most 3 segments. If you need less than three segments, you can leave the rest blank.
{{~/user}}

{{#assistant~}}
{{gen 'answer'}}
{{~/assistant~}}''')
qa_attempt5(llm=chatgpt, transcript=meeting_transcript, query=query1)

      
                

qa_guided = guidance('''{{#system~}}
{{llm.default_system_prompt}}
{{~/system}}

{{#user~}}
You will read a meeting transcript, then extract the relevant segments to answer the following question:
Question: {{query}}
----
{{transcript}}
----
Based on the above, please answer the following question:
Question: {{query}}
Please extract the three segment from the transcript that are the most relevant for the answer, and then answer the question.
Note that conversation segments can be of any length, e.g. including multiple conversation turns. If you need less than three segments, you can leave the rest blank.

As an example of output format, here is a fictitious answer to a question about another meeting transcript:
CONVERSATION SEGMENTS:
Segment 1: Peter and John discuss the weather.
Peter: John, how is the weather today?
John: It's raining.
Segment 2: Peter insults John
Peter: John, you are a bad person.
Segment 3: Blank
ANSWER: Peter and John discussed the weather and Peter insulted John.
{{/user}}

{{#assistant~}}
CONVERSATION SEGMENTS:
Segment 1: {{gen 'segment1'}}
Segment 2: {{gen 'segment2'}}
Segment 3: {{gen 'segment3'}}
ANSWER: {{gen 'answer'}}
{{~/assistant~}}''')

Nous pouvons, bien sûr, exécuter la même invite avec MPT :

Alors que MPT suit le format, il ignore la question et prend des extraits de l'exemple de format plutôt que de la vraie transcription.
À partir de maintenant, nous comparerons simplement ChatGPT et Vicuna.

Essayons une autre question : "Qui veut vendre l'entreprise ?"

Voici ChatGPT :

Vigogne :

Les deux semblent très bien fonctionner. Passons à la transcription de la réunion pour les premières minutes d' une interview avec Elon Musk. La partie pertinente pour la question que nous allons poser est

Elon Musk : Alors je dis, monsieur, que vous ne savez pas de quoi vous parlez.
Intervieweur : Vraiment ?
Elon Musk : Oui. Parce que vous ne pouvez pas donner un seul exemple de contenu haineux. Pas même un tweet. Et pourtant, vous avez affirmé que le contenu haineux était élevé. C'est faux.
Interviewer : Non. Ce que j'ai prétendu-
Elon Musk : Vous venez de mentir.

Ensuite, nous posons la question suivante :
"Est-ce qu'Elon Musk insulte l'intervieweur ?"

ChatGPT :

Vigogne :

Vicuna, a le bon format et même les bons segments, mais il génère étonnamment une réponse complètement fausse, quand il dit "Elon Musk ne l'accuse pas de mentir ou ne l'insulte en aucune façon".

Nous avons essayé une variété d'autres questions et conversations, et la tendance générale était que Vicuna était comparable à ChatGPT sur la plupart des questions, mais a obtenu la mauvaise réponse plus souvent que ChatGPT.

Tâche : faire des choses avec bash

Maintenant, nous essayons de faire en sorte que ces LLM utilisent de manière itérative un shell bash pour résoudre des problèmes individuels. Chaque fois qu'ils émettent une commande, nous l'exécutons et réinsérons la sortie dans l'invite, jusqu'à ce que la tâche soit résolue.

Voici l'invite ChatGPT (remarque qui shell this.commandappelle une fonction définie par l'utilisateur avec this.commandcomme argument) :

terminal = guidance('''{{#system~}}
{{llm.default_system_prompt}}
{{~/system}}

{{#user~}}
Please complete the following task:
Task: list the files in the current directory
You can give me one bash command to run at a time, using the syntax:
COMMAND: command
I will run the commands on my terminal, and paste the output back to you. Once you are done with the task, please type DONE.
{{/user}}

{{#assistant~}}
COMMAND: ls
{{~/assistant~}}

{{#user~}}
Output: guidance project
{{/user}}

{{#assistant~}}
The files or folders in the current directory are:
- guidance
- project
DONE
{{~/assistant~}}

{{#user~}}
Please complete the following task:
Task: {{task}}
You can give me one bash command to run at a time, using the syntax:
COMMAND: command
I will run the commands on my terminal, and paste the output back to you. Once you are done with the task, please type DONE.
{{/user}}

{{#geneach 'commands' stop=False}}
{{#assistant~}}
{{gen 'this.command'}}
{{~/assistant~}}

{{~#user~}}
Output: {{shell this.command)}}
{{~/user~}}
{{/geneach}}''')

En effet, ChatGPT suit une séquence très naturelle, et résout la tâche. Il ne suit pas notre instruction de dire DONE, mais nous sommes en mesure d'arrêter l'itération automatiquement car il n'émet aucune COMMANDE.

Pour les modèles open source, nous écrivons une invite plus simple (guidée) où il y a une séquence de sortie de commande :

guided_terminal = guidance('''{{#system~}}
{{llm.default_system_prompt}}
{{~/system}}

{{#user~}}
Please complete the following task:
Task: list the files in the current directory
You can run bash commands using the syntax:
COMMAND: command
OUTPUT: output
Once you are done with the task, use the COMMAND: DONE.
{{/user}}

{{#assistant~}}
COMMAND: ls
OUTPUT: guidance project
COMMAND: DONE 
{{~/assistant~}}

{{#user~}}
Please complete the following task:
Task: {{task}}
You can run bash commands using the syntax:
COMMAND: command
OUTPUT: output
Once you are done with the task, use the COMMAND: DONE.
{{~/user}}

{{#assistant~}}
{{#geneach 'commands' stop=False ~}}
COMMAND: {{gen 'this.command' stop='\\n'}}
OUTPUT: {{shell this.command)}}{{~/geneach}}
{{~/assistant~}}''')

Voici MPT :

Dans une tournure des événements intéressante, Vicuna est incapable de résoudre la tâche, mais MPT réussit. Outre la confidentialité (nous n'envoyons pas la transcription de la session à OpenAI), les modèles open source ont ici un avantage significatif : l'ensemble de l'invite est une seule exécution LLM (et nous l'accélérons même en ne lui faisant pas générer les jetons de structure de sortie comme COMMAND:) .
En revanche, nous devons effectuer un nouvel appel à ChatGPT pour chaque commande, ce qui est plus lent et plus coûteux.

Maintenant, nous essayons une commande différente : "Trouvez tous les fichiers de bloc-notes jupyter dans ~/work/guidance qui ne sont actuellement pas suivis par git".

Voici ChatGPT :

Une fois de plus, nous rencontrons un problème avec ChatGPT qui ne suit pas notre structure de sortie spécifiée (et nous empêche ainsi de l'utiliser à l'intérieur d'un programme, sans un humain dans la boucle). Notre programme vient d'exécuter des commandes et s'est donc arrêté après le dernier message ChatGPT ci-dessus.

Nous soupçonnions que la sortie vide avait désactivé ChatGPT, et nous avons donc résolu ce problème particulier en modifiant le message lorsqu'il n'y a pas de sortie. Cependant, nous ne pouvons pas résoudre le problème général de ne pas pouvoir forcer ChatGPT à suivre notre structure de sortie spécifiée.

ChatGPT a pu résoudre le problème après cette petite modification. Voyons comment fait Vicuna :

Vicuna suit notre structure de sortie, mais exécute malheureusement la mauvaise commande pour effectuer la tâche. MPT (non illustré) appelle git status à plusieurs reprises, il échoue donc également.

Nous avons exécuté ces programmes pour diverses autres instructions et avons constaté que ChatGPT produisait presque toujours la séquence correcte de commandes, tout en ne suivant parfois pas le format spécifié (et nécessitant donc une intervention humaine). Les modèles open source ne fonctionnaient pas si bien (nous pouvons probablement les améliorer avec une ingénierie plus rapide, mais ils ont échoué sur les instructions les plus difficiles).

Plats à emporter

En plus des exemples ci-dessus, nous avons essayé diverses entrées pour les deux tâches (question answering et bash). Nous avons également essayé une variété d'autres tâches impliquant la synthèse, la réponse aux questions, la génération "créative" et les tâches de manipulation de chaînes de jouets où nous pouvons évaluer automatiquement la précision.
Voici un résumé de nos découvertes :

  • Qualité sur tâche : Pour chaque tâche que nous avons essayée, ChatGPT (3.5) est toujours plus fort que Vicuna sur la tâche elle-même. MPT a mal performé sur presque toutes les tâches (peut-être que nous l'utilisons mal ?), tandis que Vicuna était souvent proche de ChatGPT (parfois très proche, parfois bien pire que dans le dernier exemple de tâche ci-dessus).
  • Facilité d'utilisation : Il est beaucoup plus pénible de faire en sorte que ChatGPT suive un format de sortie spécifié, et il est donc plus difficile de l'utiliser à l'intérieur d'un programme (sans un humain dans la boucle). De plus, nous devons toujours écrire des analyseurs regex pour la sortie (par opposition à Vicuna, où l'analyse d'une invite avec une syntaxe claire est triviale).
    Nous sommes généralement en mesure de résoudre le problème de structure en ajoutant plus d'exemples à quelques prises de vue, mais il est fastidieux de les écrire, et parfois ChatGPT sort de toute façon du script. Nous nous retrouvons également avec des invites plus longues, plus maladroites et plus laides, ce qui n'est pas satisfaisant.
    Pouvoir spécifier la structure de sortie est un avantage important des modèles open source, au point qu'on pourrait parfois préférer Vicuna à ChatGPT même quand c'est un peu moins bon sur la tâche elle-même.
  • Efficacité : avoir le modèle localement signifie que nous pouvons résoudre des tâches en une seule exécution LLM ( guidancemaintient l'état LLM pendant l'exécution du programme), ce qui est plus rapide et moins cher. Cela est particulièrement vrai lorsque des sous-étapes impliquent l'appel d'autres API ou fonctions (par exemple, recherche, terminal, etc.), ce qui nécessite toujours un nouvel appel à l'API OpenAI. guidanceaccélère également la génération en ne laissant pas le modèle générer les jetons de structure de sortie, ce qui fait parfois une grande différence.

Nous devons reconnaître que nous sommes biaisés en ayant beaucoup utilisé les modèles OpenAI au cours des dernières années, en ayant écrit divers articles qui dépendent de GPT-3 (par exemple ici , ici ), et un article qui dit essentiellement "GPT-4 est génial , voici un tas d'exemples sympas ».
En parlant de cela, bien que Vicuna soit quelque peu comparable à ChatGPT (3.5), nous pensons que GPT-4 est un modèle beaucoup plus puissant et sommes ravis de voir si les modèles open source peuvent s'en approcher . Bien qu'il guidancefonctionne assez bien avec les modèles OpenAI, il brille vraiment lorsque vous pouvez spécifier la structure de sortie et accélérer la génération.

Encore une fois, nous sommes clairement biaisés, mais nous pensons que guidancec'est une excellente façon d'utiliser ces modèles, que ce soit avec des API (OpenAI, Azure) ou localement (huggingface). Voici un lien vers le cahier jupyter avec le code pour tous les exemples ci-dessus (et plus).

Avertissement : ce billet a été écrit conjointement par Marco Tulio Ribeiro et Scott Lundberg. Il représente strictement nos opinions personnelles, et non celles de notre employeur (Microsoft).

Remerciements : Nous sommes vraiment reconnaissants à Harsha Nori pour ses commentaires perspicaces sur ce post