Chatterstack は、ChatGPT API で使用される「会話」変数を処理する極めてシンプルで直感的な方法であると同時に、高度な機能も提供します。
pip からパッケージをインストールします。
pip install chatterstack
Chatterstack には 2 つのオプションがあります。 Base ライブラリと、Base を拡張する Advanced Library。
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 )
このアプローチは、いくつかの異なる値を使用して 1 回だけ呼び出しを行う場合に最適です。
ただし、会話全体に異なる値が必要であることがわかっている場合は、ファイルの先頭でそれらを大文字で定義し、次のようにglobals()
dict を使用して 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 )
この関数に正の値を渡すと、システム メッセージがインデックスにロックされます。メッセージが追加、削除、または並べ替えられるたびに、システム メッセージがその位置 (または可能な限りその近く) に留まるようにします。
負の値を渡すと、システム メッセージが会話の終わりから数えてインデックスにロックされます (上記の例では、常に会話の最後から 2 番目のメッセージになります)。
注: 現在、これらのメソッドは、システム メッセージが 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 時にゴミを出すようにリマインドして」または「1 時間後にゴミを出すようにリマインドして」と指示できるようになりました。
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 )
現在、Chatterstack の Javascript バージョンがありますが、私は Javascript についても詳しくなく、その信頼性にもあまり自信がないため、まだ利用可能にしていません。 Javascript に詳しい方で、助けていただける方は、ぜひお知らせください。