Chatterstack est un moyen simple et intuitif de gérer les variables de « conversation » utilisées par l'API ChatGPT, tout en vous offrant des fonctionnalités avancées.
Installer le package à partir de pip :
pip install chatterstack
Il existe deux options pour Chatterstack. La bibliothèque de base et la bibliothèque avancée, qui étend la base.
import chatterstack
# The base library if you are only really concerned about mananging
# the conversation variable, it's order, and maybe tracking tokens.
convo = chatterstack . Chatterstack ()
# The advanced library allows you issuing commands from the chat input,
# gives the bot the ability to reach out to you with reminders, etc
convo = chatterstack . ChatterstackAdvanced ()
Les API ChatGPT utilisent des variables de « conversation » pour suivre vos interactions avec le bot. Il s'agit d'une liste de dictionnaires, chaque dictionnaire représentant un tournant dans la conversation.
Cela laisse votre programme encombré de choses comme ceci :
# append the bot's response to your conversation
conversation . append ({ 'role' : response . choices [ 0 ]. message . role , 'content' : response . choices [ 0 ]. message . content })
# to print the last message
print ( conversation [ - 1 ][ "content" ])
Ridicule.
Si vous souhaitez faire quelque chose de plus avancé, comme "conserver la variable de conversation à 8 messages maximum", ou "faire en sorte que le message système soit toujours le message le plus récent de la conversation"... eh bien, je vous épargne l'extrait de code pour ceux.
Étant donné que de nombreux aspects de ces dictionnaires sont hautement prévisibles et que nous n'effectuons le plus souvent qu'une poignée de tâches de base avec eux...
... cela signifie que nous pouvons réellement éliminer une grande partie de ce désordre, d'une manière qui le rend beaucoup plus intuitif à utiliser - tout en conservant pratiquement toute la flexibilité inhérente ! C'est une chose rare à pouvoir faire.
Il s'agit d'un programme de chatbot entièrement fonctionnel utilisant Chatterstack :
import chatterstack
import os
os . environ [ 'OPENAI_API_KEY' ] = 'your_api_key_here'
convo = chatterstack . Chatterstack ()
while True :
convo . user_input ()
convo . send_to_bot ()
convo . print_last_message ()
C'est tout !
Voici à quoi ressemblerait cette conversation dans le terminal :
USER: hey, can you help me with something?
ASSISTANT: Sure! What would you like help with?
USER: I need to know if France has a President or a Prime Minister
ASSISTANT: France has both a President and a Prime Minister, which [... bot goes on]
Cette bibliothèque est conçue pour être intuitive et flexible , afin que vous puissiez facilement modifier le comportement ou l'apparence, de plusieurs manières, en fonction de vos besoins. Voici quelques exemples de base, restant dans le terminal pour l'instant :
while True :
# Change the user's display name
convo . user_input ( prefix = "ME: " )
# change any of the API arguments
convo . send_to_bot ( model = "gpt-4" , temperature = 1 , max_tokens = 40 )
# change the line spacing of the convo
convo . print_last_message ( prefix = "GPT: " , lines_before = 0 , lines_after = 2 )
# and let's have it print the total tokens after each turn
print ( convo . tokens_total_all )
Votre conversation se déroule désormais avec GPT-4, et la conversation ressemble à ceci, avec le nombre de jetons :
ME: hey, can you help me with something?
GPT: Of course! I'm here to help. Please let me know what you need assistance with, and I'll do my best to help you.
28
ME: I need to know if France has a President or a Prime Minister
GPT: France has both a President and a Prime Minister. The President of France is [...bot goes on]
87
Vous trouverez plus d'informations sur les valeurs par défaut actuelles et les différentes méthodes pour les modifier ci-dessous dans la section sur l'envoi de messages à l'API.
La méthode user_input()
est la même que la méthode python input()
, sauf qu'elle ajoute également automatiquement l'entrée de l'utilisateur sous forme de dict correctement formaté à votre variable de conversation.
convo . user_input ()
Comme vu ci-dessus, cette méthode demande par défaut à l'utilisateur "USER:", mais vous pouvez la remplacer par ce que vous souhaitez.
convo . user_input ( "Ask the bot: " )
Ask the bot:
Peut-être que vous n'utilisez pas le terminal.
Ou peut-être souhaitez-vous modifier l'entrée d'une manière ou d'une autre avant de l'ajouter.
Il existe plusieurs façons de prendre n'importe quelle variable de chaîne et de l'ajouter à la conversation sous forme de dict correctement formaté :
# Use the .add() method. Pass it the role, then the content
convo . add ( "user" , message_string )
# or, use the role-specific methods & just pass the content
convo . add_user ( message_string )
convo . add_assistant ( "I'm a manually added assistant response" )
convo . add_system ( "SYSTEM INSTRUCTIONS - you are a helpful assistant who responds only in JSON" )
Il existe également .insert() si vous souhaitez ajouter un message à un index spécifique, au lieu de l'ajouter à la fin de la conversation :
# Here's the format
convo . insert ( index , role , content )
# example
convo . insert ( 4 , "system" , "IMPORTANT: Remember to not apologize to the user so much" )
La méthode chatterstack "send_to_bot" est un appel API OpenAI standard, mais elle est plus simple à utiliser et fait un tas de choses pratiques pour vous en arrière-plan. Appelez-le comme ceci :
convo . send_to_bot ()
C'est ça!
Il se chargera de transmettre toutes les valeurs par défaut pour vous, ainsi que d'ajouter la réponse à votre conversation. Il conserve également le nombre de jetons pour vous (et bien plus encore dans la classe avancée).
Par défaut, chatterstack utilise ces valeurs :
model = "gpt-3.5-turbo" ,
temperature = 0.8 ,
top_p = 1 ,
frequency_penalty = 0 ,
presence_penalty = 0 ,
max_tokens = 200
Il existe plusieurs façons de les modifier. Choisissez ce qui vous convient le mieux.
Le moyen le plus évident consiste simplement à les transmettre comme arguments lorsque vous effectuez l'appel. Par exemple, si vous vouliez des jetons GPT-4 et 800 maximum :
convo . send_to_bot ( model = "gpt-4" , max_tokens = 800 )
Cette approche est idéale lorsque vous souhaitez effectuer un seul appel avec des valeurs différentes.
Mais si vous savez que vous voulez des valeurs différentes pour l'ensemble de la conversation, vous pouvez les définir en majuscules en haut de votre fichier et initialiser chatterstack à l'aide du dict globals()
, comme ceci :
MODEL = "gpt-4"
TEMPERATURE = 0.6
FREQUENCY_PENALTY = 1.25
MAX_TOKENS = 500
# initialize with 'globals()'
convo = chatterstack . Chatterstack ( user_defaults = globals ())
# and now you can just call it like this again
convo . send_to_bot ()
Enfin, si vous souhaitez simplement utiliser l’appel standard OpenAI, vous pouvez toujours le faire ! Passez-lui simplement l'attribut .list de votre Chatterstack, qui est la liste brute des dictionnaires :
response = openai . ChatCompletion . create (
model = "gpt-3.5-turbo" ,
messages = convo . list , # <--- right here
temperature = 0.9 ,
top_p = 1 ,
frequency_penalty = 0 ,
presence_penalty = 0 ,
max_tokens = 200 ,
)
Super simple :
# Print the "content" of the last message
convo . print_last_message ()
Ou, si vous vouliez d'abord formater la chaîne...
# This represents/is the content string of the last message
convo . last_message
# So you can do stuff like this:
message_in_caps = convo . last_message . upper ()
# print the message in all upper case
print ( message_in_caps )
oh ouais. Nous gardons une trace des jetons.
# See the tokens used on the last API call
self . last_call_prompt_tokens
self . last_call_full_context_prompt_tokens
self . last_call_completion_tokens
self . last_call_tokens_all
# At any time, check the totals for the whole conversation so far
self . prompt_tokens_total
self . assistant_tokens_total
self . tokens_total_all
Différentes méthodes sont disponibles pour manipuler l'ordre de la conversation, en voici quelques-unes :
# Insert message at a specified index
convo . insert ( index , role , content )
# Remove N messages from the end of the list
convo . remove_from_end ( count )
# Remove N messages from the start of the list
convo . remove_from_start ( count )
Mais plus important encore, des méthodes permettant un contrôle précis du message système.
Les messages système sont généralement utilisés pour les instructions, et il peut souvent être utile que les instructions apparaissent plus « récemment » dans la conversation. Ce qui signifie suivre et déplacer ce message, sans perturber les autres.
# move your system message to be the most recent message in convo
convo . move_system_to_end ()
# or second to last, etc
convo . move_system_to_end ( minus = 1 )
Et mon préféré - essentiellement la raison pour laquelle j'ai écrit toute cette bibliothèque -
convo . set_system_lock_index ( - 1 )
Lui transmettre une valeur positive à cette fonction verrouillera le message système sur l'index. Chaque fois que des messages sont ajoutés, supprimés ou réorganisés, cela garantira que le message système reste à cette position (ou aussi près que possible).
En lui transmettant une valeur négative, votre message système sera verrouillé sur l'index à partir de la fin de la conversation (dans l'exemple ci-dessus, il s'agirait toujours de l'avant-dernier message de la conversation).
REMARQUE : actuellement, ces méthodes supposent que vous n'avez qu'un seul message système
Imprimez une version formatée de votre conversation (idéal pour le débogage)
convo . print_formatted_conversation
Par défaut, s'imprime comme ceci :
System: You are a helpful assistant.
User: hi!
Assistant: Hi! How can I help you?
voir les statistiques globales de votre conversation.
convo . summary ()
SUMMARY:
{'total_messages': 2, 'prompt_tokens': 200, 'assistant_tokens': 78, 'total_tokens': 278}
La classe Chatterstack Advanced étend la classe de base et intègre beaucoup plus de fonctionnalités. Il est également facilement extensible.
Attention : les modifications récentes apportées au modèle semblent avoir cassé cette fonctionnalité. Cela peut fonctionner ou non lorsque vous l'essayez. Il devra probablement être réécrit pour utiliser les appels de fonctions afin de fonctionner à nouveau de manière cohérente.
Vous pouvez maintenant dire au bot "rappelle-moi de sortir les poubelles à 20h", ou "rappelle-moi de sortir les poubelles dans une heure".
USER: hey, can you remind me to take the garbage out in an hour
ASSISTANT: Sure! I'll send you a reminder in an hour.
USER:
{...time passes...}
ASSISTANT: Hey! Just a quick reminder to take the garbage out!
Le bot peut suivre autant de rappels que vous souhaitez émettre.
Émettez des commandes à partir de l'entrée de l'utilisateur :
# saves the conversation to a txt file
USER: [save]
# quit the program
USER: [quit]
Par défaut, vous émettez des commandes en utilisant [
et ]
comme délimiteurs. Mais vous pouvez les modifier comme vous le souhaitez :
convo.open_command = "{{"
convo.close_command = "}}"
vous pouvez également appeler automatiquement n'importe quelle méthode (ou définir n'importe quel attribut) de la classe chatterstack elle-même, directement depuis l'interface de discussion :
# if you want to see what is currently in the conversation history
USER: [print_formatted_conversation]
# or how many tokens you have used so far
USER: [print_total_tokens]
# you can even pass arguments to commands
USER: [set_system_lock_index(-2)]
Ainsi, même si l'exemple de programme de chat initial au début de ce référentiel peut sembler simpliste au début, vous pouvez voir que c'est vraiment tout ce dont vous avez besoin, car presque toutes les fonctionnalités que vous souhaitez peuvent en fait être appelées depuis le chat lui-même.
Si vous souhaitez écrire vos propres commandes, chatterstack fournit une classe d'interface simple pour le faire, appelée ICommand
.
class ICommand :
def execute ( self ):
pass
Fondamentalement, vous écrivez votre commande en tant que classe, qui hérite de la classe ICommand
et possède une méthode "execute" (c'est ce que vous voulez réellement se produire lorsque votre commande est appelée.)
Voici un exemple :
class ExampleCommand ( ICommand ):
def execute ( self ):
print ( "An example command that prints this statement right here." )
Si votre commande a besoin d'arguments, vous pouvez également ajouter une méthode __init__
et lui transmettre *args
exactement comme ceci :
class ExampleCommand ( ICommand ):
def __init__ ( self , * args ):
self . args = args
def execute ( self ):
print ( "Example command that print this statement with this extra stuff:" , self . args )
La dernière chose que vous devez faire est d'attribuer à votre commande un mot ou une phrase déclencheur en l'ajoutant à la méthode init de la classe ChatterstackAdvanced.
class ChatterstackAdvanced ( Chatterstack ):
def __init__ ( self , ...)
# ...Lots of other code here...
# This command is already in the class:
self . command_handler . register_command ( 'save' , SaveConversationCommand ( self ))
# Add your new command
self . command_handler . register_command ( "example" , ExampleCommand )
Il existe actuellement une version Javascript de Chatterstack, mais je ne l'ai pas encore rendue disponible car je ne connais pas non plus Javascript et je ne suis pas aussi sûr de sa fiabilité. Si vous connaissez Javascript et que vous souhaitez aider, faites-le-moi savoir !