GoalChain は、人間と LLM および LLM と LLM の対話のための目標指向の会話フローを可能にする、シンプルですが効果的なフレームワークです。
pip install goalchain
会話フローの基礎となるField
、 ValidationError
、 Goal
、およびGoalChain
クラスをインポートしましょう。
from goalchain import Field , ValidationError , Goal , GoalChain
この例では、顧客から希望の製品注文に関する情報を収集することを目的とする AI アシスタントを作成します。 Goal
の子であるProductOrderGoal
内のField
オブジェクトを使用して、収集される情報を定義します。
また、数量のバリデーターも定義します (int への型キャスト後)。 ValidationError
エラー メッセージを会話に戻すために使用されます。これらのメッセージは人間が読める形式である必要があります。
format_hint
LLM の JSON モード出力の自然言語型ヒントです。
def quantity_validator ( value ):
try :
value = int ( value )
except ( ValueError , TypeError ):
raise ValidationError ( "Quantity must be a valid number" )
if value <= 0 :
raise ValidationError ( "Quantity cannot be less than one" )
if value > 100 :
raise ValidationError ( "Quantity cannot be greater than 100" )
return value
class ProductOrderGoal ( Goal ):
product_name = Field ( "product to be ordered" , format_hint = "a string" )
customer_email = Field ( "customer email" , format_hint = "a string" )
quantity = Field ( "quantity of product" , format_hint = "an integer" , validator = quantity_validator )
顧客の気が変わった場合に備えて、 OrderCancelGoal
という別のGoal
子クラスを作成しましょう。進行中の注文をお客様がキャンセルする場合、当社は任意の理由を要求します。説明でフィールドが「(オプション)」であると指定することで、LLM は目標を達成する必要がないことを認識します。
class OrderCancelGoal ( Goal ):
reason = Field ( "reason for order cancellation (optional)" , format_hint = "a string" )
product_name
などのフィールド オブジェクト名は LLM プロンプトに直接渡されるため、他のすべての文字列と同様にプロンプト エンジニアリング タスクの一部であることに注意してください。
基本的に、私たちが定義したクラスは顧客が記入するフォームのようなものですが、説明がありません。クラスをオブジェクトとしてインスタンス化して、これらを追加しましょう。
product_order_goal = ProductOrderGoal (
label = "product_order" ,
goal = "to obtain information on an order to be made" ,
opener = "I see you are trying to order a product, how can I help you?" ,
out_of_scope = "Ask the user to contact sales team at [email protected]"
)
order_cancel_goal = OrderCancelGoal (
label = "cancel_current_order" ,
goal = "to obtain the reason for the cancellation" ,
opener = "I see you are trying to cancel the current order, how can I help you?" ,
out_of_scope = "Ask the user to contact the support team at [email protected]" ,
confirm = False
)
私たちは定義します
opener
- 事前の入力がない場合に AI アシスタントが使用するもの、 confirm
フラグは、 Field
オブジェクトを使用して定義された必要な情報がすべて揃ったら、AI アシスタントが確認を求めるかどうかを決定します。デフォルトではTrue
です。注文キャンセル目標の確認は、それ自体がすでに一種の確認であるため、必要ありません。
次に、目標を結び付ける必要があります。
product_order_goal . connect ( goal = order_cancel_goal ,
user_goal = "to cancel the current order" ,
hand_over = True ,
keep_messages = True )
user_goal
別の「to ...」ステートメントです。 hand_over=True
指定しないと、AI エージェントはopener
で応答します。 True
に設定すると、会話がスムーズに進みます。定型応答が必要な場合もあれば、そうでない場合もあります。
keep_messages=True
、 order_cancel_goal
product_order_goal
との会話の完全な履歴を受け取ることを意味します。それ以外の場合は消去されます。繰り返しになりますが、さまざまな AI パーソナリティをシミュレートする場合など、会話履歴の消去が必要になる場合があります。
本当に決断力のない顧客の可能性も考えてみましょう。 「キャンセルを取り消す」という選択肢も与えるべきです。
order_cancel_goal . connect ( goal = product_order_goal ,
user_goal = "to continue with the order anyway" ,
hand_over = True ,
keep_messages = True )
ある時点で、 Field
オブジェクトなしでゴールを作成できるかどうか疑問に思ったことがあるかもしれません。あなたはできる!このような目標は、その目標が持つ接続のみで定義されるルーティング目標です。これは、ボイスメール メニュー システムなどで役立ちます。
また、目標をそれ自体に結びつけることができるかどうかも知りたいかもしれません。あなたはできる!これは、たとえば、 Goal
継承オブジェクトでconfirm=False
使用し、何らかの種類の連続したユーザー入力が必要な場合に便利です。
また、 goal.connect(...).connect(...).connect(...)
のように、チェーン接続することもできます。
最後に、 GoalChain
使用して初期目標を設定し、AI セールス アシスタントをテストしてみましょう。
goal_chain = GoalChain ( product_order_goal )
各目標は、LiteLLM によって有効にされた個別の LLM API を使用でき、必要な環境変数が設定されている場合は、サポートされているモデル プロバイダーの任意のモデルを使用できることに注意してください。
デフォルトのモデルは"gpt-4-1106-preview"
です。つまり、次のようになります。
product_order_goal = ProductOrderGoal (...
model = "gpt-4-1106-preview" ,
json_model = "gpt-4-1106-preview"
)
次のように、 params
使用して LiteLLM 共通パラメータを渡すこともできます。
product_order_goal = ProductOrderGoal (...
model = "gpt-4-1106-preview" ,
json_model = "gpt-4-1106-preview" ,
params = { "temperature" : 1.5 , "max_tokens" : 10 }
)
params
使用して、VLLM を使用してローカル モデルを呼び出すこともできます。
デフォルトの"gpt-4-1106-preview"
モデルを使用する場合は、必ずOPENAI_API_KEY
環境変数を設定してください。
import os
os . environ [ "OPENAI_API_KEY" ] = "sk-ABC..."
注: これまでのコードは要点として入手できます。これを Jupyter ノートブックに貼り付け、その前に!pip install goalchain
付けて、以下の実際の例を開始します。
通常、最初に AI エージェントにプロンプトを表示するのはユーザーですが、そうでない場合は、引数なしでget_response
を呼び出すか、引数としてNone
使用します。
goal_chain . get_response ()
{'type': 'message',
'content': 'Great choice! Could you please provide me with your email address to proceed with the order?',
'goal': <__main__.ProductOrderGoal at 0x7f8c8b687110>}
GoalChain は、応答のタイプ ( message
またはdata
)、応答の内容 (現時点では定型応答のみ)、および現在のGoal
継承オブジェクトを含むdict
返します。
AI アシスタントに購入の可能性を問い合わせてみましょう。
goal_chain . get_response ( "Hi, I'd like to buy a vacuum cleaner" )
{'type': 'message',
'content': 'Great! Could you please provide your email address so we can send the confirmation of your order?',
'goal': <__main__.ProductOrderGoal at 0x7ff0fb283090>}
AI アシスタントは現在の目標の達成に向けて取り組み、注文に必要な情報を収集しています。
goal_chain . get_response ( "Sure, it is [email protected]" )
{'type': 'message',
'content': 'Thank you, John. Which model of vacuum cleaner would you like to order?',
'goal': <__main__.ProductOrderGoal at 0x7ff0fb283090>}
goal_chain . get_response ( "The 2000XL model" )
{'type': 'message',
'content': 'How many of the 2000XL model would you like to order?',
'goal': <__main__.ProductOrderGoal at 0x7ff0fb283090>}
AI アシスタントが現在の注文のキャンセルを処理できるかどうかをテストしてみましょう。
goal_chain . get_response ( "Actually I changed my mind, cancel this order" )
{'type': 'message',
'content': 'Of course, I can assist with that. Could you please tell me the reason for the cancellation?',
'goal': <__main__.OrderCancelGoal at 0x7ff0fb275650>}
うまくいきました。返される目標のタイプはOrderCancelGoal
になっていることに注意してください。目標を切り替えました。また、元に戻すことができるかどうかもテストしてみましょう。
goal_chain . get_response ( "Actually, yeah, I would like to buy the vacuum cleaner" )
{'type': 'message',
'content': 'Understood. How many of the 2000XL model would you like to order?',
'goal': <__main__.ProductOrderGoal at 0x7ff0fb283090>}
ProductOrderGoal
に戻ります。
goal_chain . get_response ( "1 please" )
{'type': 'message',
'content': 'To confirm, you would like to order one 2000XL vacuum cleaner and the order will be sent to [email protected], is that correct?',
'goal': <__main__.ProductOrderGoal at 0x7ff0fb283090>}
AIアシスタントが注文を確認します。この動作が気に入らない場合は、 confirm=False
使用します。
アシスタントが範囲外のクエリにどのように応答するかを見てみましょう。
goal_chain . get_response ( "Is it a good vacuum cleaner? What do you think?" )
{'type': 'message',
'content': "For product reviews and additional information, I recommend contacting our sales team at [email protected]. They can help with your inquiries. Meanwhile, can you please confirm if you'd like to proceed with the order for one 2000XL vacuum cleaner to [email protected]?",
'goal': <__main__.ProductOrderGoal at 0x7ff0fb283090>}
AI アシスタントは、前に定義したように営業チームの受信箱にリダイレクトし、確認を繰り返します。
でも、変化球を投げてみましょう...
goal_chain . get_response ( "Ok, I'd actually like to make that an order of 500" )
{'type': 'message',
'content': "Just to clarify, you'd like to order 500 units of the 2000XL vacuum cleaner, with the order confirmation sent to [email protected]. Is that correct?",
'goal': <__main__.ProductOrderGoal at 0x7ff0fb283090>}
goal_chain . get_response ( "Yes" )
{'type': 'message',
'content': 'I’m sorry, but I need to inform you that the quantity cannot be greater than 100 for an order. If you would like to proceed with an order within this limit, please let me know.',
'goal': <__main__.ProductOrderGoal at 0x7ff0fb283090>}
私たちが使用するバリデーターは、 ValidationError
メッセージを通じて、この数量を処理できない理由を正当化するのに十分な情報を AI アシスタントに提供しています。
GoalChain は、トークンの効率性とパフォーマンス上の理由から、 Goal
が完了した後にのみ入力を検証することに注意してください。入力を途中で検証したい場合は、次の 2 つのオプションがあります。
Field
1 つだけ指定してGoal
使用し、 confirm=False
設定します。単一のGoal
で複数のフィールドを使用するのではなく、これらの目標を連鎖させます。
ソフトプロンプトを使用します (例: quantity = Field("quantity of product (no more than 100)", format_hint="an integer")
。このアプローチは確実ではないため、バリデーターを使用することをお勧めします。ただし、ユーザーはすぐにフィードバックを受け取ります。
注文を完了しましょう。
goal_chain . get_response ( "Alright, I'll guess I'll just go with 1" )
{'type': 'message',
'content': 'To confirm, you would like to order one 2000XL vacuum cleaner and the order will be sent to [email protected], is that correct?',
'goal': <__main__.ProductOrderGoal at 0x7ff0fb283090>}
goal_chain . get_response ( "That's right" )
{'type': 'data',
'content': {'customer_email': '[email protected]',
'product_name': '2000XL',
'quantity': 1},
'goal': <__main__.ProductOrderGoal at 0x7ff0fb283090>}
返されるコンテンツは、LLM の JSON モードの出力から解析された辞書です。キーはフィールド インスタンス名です。このデータを使用して、仮想の 2000XL 掃除機の注文を処理するなど、何らかのアクションを実行できるようになりました。
実際には、このようなシステムを構築する場合は、任意のまたは意味のない製品名を許可しないように、専用の製品検索目標を作成する必要があることに注意してください。
注文が処理されたことの確認をsimulate_response
経由で送信しましょう。また、 rephrase = True
使用して出力を言い換えます。これにより、顧客が頻繁に目標を操作する場合に、より自然に表示されます。
goal_chain . simulate_response ( f"Thank you for ordering from Acme. Your order will be dispatched in the next 1-3 business days." , rephrase = True )
{'type': 'message',
'content': 'We appreciate your purchase with Acme! Rest assured, your order will be on its way within the next 1 to 3 business days.',
'goal': <__main__.ProductOrderGoal at 0x7ff0fb283090>}
この時点で、セッションを終了するか、さらなる入力のためにメニューまたはルーティング目標に接続し直すことができます。
GoalChain のカスタマイズやそれに貢献したい場合、あるいは問題を報告したい場合は、GitHub ページにアクセスしてください。