Chatterstack — это чрезвычайно простой и интуитивно понятный способ обработки переменных «разговора», используемых API ChatGPT, а также предоставляющий вам расширенные функциональные возможности.
Установить пакет из pip:
pip install chatterstack
Есть два варианта использования Chatterstack. Базовая библиотека и Расширенная библиотека, расширяющая базовую.
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 ()
API-интерфейсы ChatGPT используют переменные «разговора», чтобы отслеживать ваше взаимодействие с ботом. Это список словарей, каждый из которых представляет поворот в разговоре.
В результате ваша программа будет засорена такими вещами:
# 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" ])
Нелепый.
Если вы хотите сделать что-то более сложное, например «сохранить максимальную переменную разговора до 8 сообщений» или «сделать системное сообщение всегда самым последним сообщением в разговоре»… что ж, я оставлю вам фрагмент кода для те.
Поскольку многие аспекты этих словарей очень предсказуемы, и чаще всего мы выполняем с их помощью лишь несколько основных задач...
... это означает, что мы действительно можем абстрагировать большую часть этого беспорядка, сделав его более интуитивным в использовании, сохраняя при этом практически всю присущую ему гибкость! Это редкая вещь, которую можно сделать.
Это полнофункциональная программа-чат-бот, использующая 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 ()
Вот и все!
Вот как этот диалог будет выглядеть в терминале:
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]
Эта библиотека создана интуитивно понятной и гибкой , поэтому вы можете легко изменить ее поведение или внешний вид разными способами в соответствии с вашими потребностями. Вот несколько основных примеров, которые пока остаются в терминале:
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 )
Теперь ваш разговор ведется с GPT-4 и выглядит следующим образом (с количеством токенов):
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
Дополнительную информацию о текущих значениях по умолчанию и различных методах их изменения см. ниже в разделе об отправке сообщений в API.
Метод user_input()
аналогичен методу python input()
, за исключением того, что он также автоматически добавляет вводимые пользователем данные в виде правильно отформатированного слова в переменную вашего разговора.
convo . user_input ()
Как видно выше, этот метод по умолчанию запрашивает у пользователя «USER:», но вы можете изменить его на все, что захотите.
convo . user_input ( "Ask the bot: " )
Ask the bot:
Возможно, вы не используете терминал.
Или, может быть, вы хотите каким-то образом изменить ввод перед его добавлением.
Есть несколько способов взять любую строковую переменную и добавить ее в диалог как правильно отформатированный словарь:
# 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" )
Существует также .insert(), если вы хотите добавить сообщение по определенному индексу, а не добавлять его в конец разговора:
# Here's the format
convo . insert ( index , role , content )
# example
convo . insert ( 4 , "system" , "IMPORTANT: Remember to not apologize to the user so much" )
Метод «send_to_bot» в chatterstack — это стандартный вызов API OpenAI, но его проще использовать и он выполняет множество полезных действий в фоновом режиме. Назовите это так:
convo . send_to_bot ()
Вот и все!
Он позаботится о передаче всех значений по умолчанию, а также о добавлении ответа к вашему разговору. Он также сохраняет для вас счетчик токенов (а в продвинутом классе — гораздо больше).
По умолчанию Chatterstack использует следующие значения:
model = "gpt-3.5-turbo" ,
temperature = 0.8 ,
top_p = 1 ,
frequency_penalty = 0 ,
presence_penalty = 0 ,
max_tokens = 200
Есть несколько способов изменить их. Выбирайте то, что вам наиболее удобно.
Самый очевидный способ — просто передать их в качестве аргументов при вызове. Например, если вам нужны токены GPT-4 и максимум 800:
convo . send_to_bot ( model = "gpt-4" , max_tokens = 800 )
Этот подход хорош, когда вы хотите сделать только один вызов с разными значениями.
Но если вы знаете, что вам нужны разные значения для всего разговора, вы можете определить их заглавными буквами в верхней части файла и инициализировать Chatterstack с помощью слова globals()
, например:
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 ()
Наконец, если вы хотите просто использовать шаблонный вызов OpenAI, вы все равно можете это сделать! Просто передайте ему атрибут .list вашего Chatterstack, который представляет собой необработанный список словарей:
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 ,
)
Супер Просто:
# Print the "content" of the last message
convo . print_last_message ()
Или, если вы хотите сначала выполнить форматирование строки...
# 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 )
Ах, да. Мы отслеживаем токены.
# 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
Доступны различные методы управления порядком разговора, вот некоторые из них:
# 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 )
Но гораздо важнее — методы детального контроля над системным сообщением.
Системные сообщения обычно используются для инструкций, и часто бывает полезно, чтобы инструкции появлялись в разговоре «недавно». Это означает отслеживание и перемещение этого сообщения, не нарушая работу остальных.
# 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 )
И мой личный фаворит (по сути, именно поэтому я написал всю эту библиотеку)
convo . set_system_lock_index ( - 1 )
Передача положительного значения этой функции заблокирует системное сообщение в индексе. Каждый раз, когда сообщения добавляются, удаляются или переупорядочиваются, система следит за тем, чтобы системное сообщение оставалось в этой позиции (или как можно ближе к ней).
Если передать ему отрицательное значение, ваше системное сообщение будет привязано к индексу, отсчитываемому с конца разговора (в приведенном выше примере оно всегда будет предпоследним сообщением в разговоре).
ПРИМЕЧАНИЕ. В настоящее время эти методы предполагают, что у вас есть только одно системное сообщение.
Распечатайте отформатированную версию вашего разговора (отлично подходит для отладки).
convo . print_formatted_conversation
По умолчанию печатается так:
System: You are a helpful assistant.
User: hi!
Assistant: Hi! How can I help you?
увидеть общую статистику вашего разговора.
convo . summary ()
SUMMARY:
{'total_messages': 2, 'prompt_tokens': 200, 'assistant_tokens': 78, 'total_tokens': 278}
Класс Chatterstack Advanced расширяет базовый класс и имеет гораздо больше встроенных функций. Он также легко расширяется.
Предупреждение : недавние изменения в модели, похоже, нарушили эту функциональность. Это может сработать, а может и не сработать, когда вы попробуете. Вероятно, его придется переписать, чтобы снова использовать вызов функций для стабильной работы.
Теперь вы можете сказать боту: «Напомни мне вынести мусор в 8 вечера» или «Напомни мне вынести мусор через час».
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!
Бот может отслеживать столько напоминаний, сколько вы захотите отправить.
Выдавайте команды из пользовательского ввода:
# saves the conversation to a txt file
USER: [save]
# quit the program
USER: [quit]
По умолчанию команды выдаются с использованием [
и ]
в качестве разделителей. Но вы можете изменить их на все, что захотите:
convo.open_command = "{{"
convo.close_command = "}}"
вы также можете самостоятельно вызвать любой метод (или установить любой атрибут) самого класса болтовни прямо из интерфейса чата:
# 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)]
Итак, хотя первоначальный пример программы чата в начале этого репозитория на первый взгляд может показаться упрощенным, вы можете видеть, что это действительно все, что вам нужно, поскольку практически любую функциональность, которую вы хотите, можно вызвать изнутри самого чата.
Если вы хотите писать свои собственные команды, chatterstack предоставляет для этого простой класс интерфейса, называемый ICommand
.
class ICommand :
def execute ( self ):
pass
По сути, вы пишете свою команду как класс, который наследует от класса ICommand
и имеет метод «выполнить» (это то, что вы хотите, чтобы это происходило при вызове вашей команды).
Вот пример:
class ExampleCommand ( ICommand ):
def execute ( self ):
print ( "An example command that prints this statement right here." )
Если вашей команде нужны аргументы, вы также можете добавить метод __init__
и передать его *args
точно так:
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 )
Последнее, что вам нужно сделать, — это назначить команде триггерное слово или фразу, добавив их в метод init класса 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 )
В настоящее время существует версия Chatterstack для Javascript, но я еще не сделал ее доступной, поскольку я также не знаю Javascript и не уверен в ее надежности. Если вы знаете Javascript и хотите помочь, пожалуйста, дайте мне знать!