Chatterstack 是一種非常簡單且直覺的方法來處理 ChatGPT API 使用的「對話」變量,同時也為您提供進階功能。
從 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 ()
ChatGPT API 使用「對話」變數來追蹤您與機器人的互動。這是一個字典列表,每個字典代表對話中的一個回合。
這會讓你的程式充斥著這樣的東西:
# 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" )
chatterstack“send_to_bot”方法是一個標準的 OpenAI API 呼叫,但它使用起來更簡單,並且在後台為您做一些方便的事情。像這樣稱呼它:
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 )
當您只想使用一些不同的值進行一次呼叫時,這種方法非常有用。
但是,如果您知道整個對話需要不同的值,您可以在檔案頂部的大寫字母中定義它們,並使用globals()
字典初始化chatterstack,如下所示:
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 調用,您仍然可以這樣做!只需將 Chatterstack 的 .list 屬性傳遞給它,它是字典的原始列表:
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 = "}}"
您也可以直接從聊天介面自呼叫 chatterstack 類別本身的任何方法(或設定任何屬性):
# 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 )
您需要做的最後一件事是透過將觸發詞或短語添加到 ChatterstackAdvanced 類別的init方法中來為您的命令分配觸發詞或短語。
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 )
目前有一個 Javascript 版本的 Chatterstack,但我還沒有提供它,因為我也不了解 Javascript,對其可靠性不太有信心。如果您了解 Javascript,並且願意提供協助,請告訴我!