Reference: DataWhale wow agent day02
準備段階#
- 仮想環境 agent を作成し、pip install openai python-dotenv を実行します。
- openai ライブラリを使用して国内の大モデルに接続するには、各メーカーごとに前菜を準備する必要があります:
- api_key を取得する必要があります。これは各社のオープンプラットフォームで申請します。
- base_url を取得する必要があります。これは各社のオープンプラットフォームからコピーします。
- それぞれの会話モデルの名前。
後の 2 つは公開されています。
プロジェクトのルートディレクトリに新しい txt ファイルを作成し、ファイル名を.env に変更します。中に 1 行の文字列を入力します: ZISHU_API_KEY = あなたの api_key。ここでは自塾提供のデフォルト API を使用します。
自塾:
base_url = "http://43.200.7.56:8008/v1"
chat_model = "glm-4-flash"
- 環境変数を読み込むコード:
import os
from dotenv import load_dotenv
# 環境変数を読み込む
load_dotenv()
# 環境変数からapi_keyを取得
api_key = os.getenv('ZISHU_API_KEY')
base_url = "http://43.200.7.56:8008/v1"
chat_model = "glm-4-flash"
ERROR: api_key が正常に取得できませんでした。
fixed:load_dotenv('.env.txt')
4. client を構築する
from openai import OpenAI
client = OpenAI(
api_key = api_key,
base_url = base_url
)
プロンプト#
構造化プロンプトとは?#
参考:https://github.com/EmbraceAGI/LangGPT
構造化プロンプトの考え方は、簡単に言うと、文章を書くようにプロンプトを書くことです **。構造化されたプロンプトを書くためには、さまざまな高品質なテンプレートがあり、プロンプトを書くのをより簡単にし、パフォーマンスを向上させます。したがって、構造化プロンプトを書くためには、さまざまなテンプレートを使用できます。PPT テンプレートのように、自分の好きなテンプレートを選択または作成できます。
LangGPT 変数#
- ChatGPT は、さまざまな良好にマークされた階層構造のコンテンツを認識できます。
- プロンプトの内容を構造化された方法で提示し、タイトルを設定することで、簡単に引用、修正、プロンプト内容を設定できます。段落タイトルを使用して大きな内容を指し示すこともでき、ChatGPT に特定の内容を修正するように指示することもできます。これはプログラミングにおける変数に似ているため、これらのタイトルを変数として使用できます。
- Markdown の構文階層構造は非常に良好で、プロンプトを書くのに適しているため、LangGPT の変数は Markdown 構文に基づいています。実際には、Markdown 以外のさまざまなマークアップ機能を持つもの、例えば json、yaml、さらには適切にフォーマットされたものも使用できます。
LangGPT テンプレート#
Role テンプレートを使用する場合は、テンプレートに従って必要な内容を記入するだけです。
変数やテンプレートの他に、LangGPT はコマンド、メモリ、条件文などの構文設定方法も提供しています。
構造化プロンプトの概念#
識別子:#, <> などの記号(-, [] も含む)は、これらの記号がそれぞれタイトル、変数、コンテンツの階層を制御するために使用され、階層構造を識別します。
属性語:Role、Profile、Initialization など、属性語は意味を含み、モジュール内の内容の要約とヒントを提供し、意味構造を識別するために使用されます。
異なる部分の入力を明確に区切るために、三重引用符、XML タグ、セクションタイトルなどの区切り記号を使用することで、異なる方法で処理する必要があるテキスト部分を示すことができます。
GPT モデルにとって、識別子によって識別された階層構造は、同じ意味を集約し、意味を整理する役割を果たし、モデルがプロンプトを理解する難易度を下げ、プロンプトの意味を理解しやすくします。
属性語はプロンプト内容の意味を示唆し、要約する役割を果たし、プロンプト内の不適切な内容の干渉を軽減します。属性語とプロンプト内容を組み合わせることで、局所的な総分構造を実現し、モデルがプロンプト全体の意味を把握しやすくします。
良い構造化プロンプトテンプレートは、ある意味で良いグローバル思考チェーンを構築しています。LangGPT で示されたテンプレート設計では、以下の思考チェーンが考慮されています:
Role -> Profile—> Profile 内の skill -> Rules -> Workflow(上記の条件を満たす役割の作業フロー) -> Initialization(正式に作業を開始するための準備) -> 実際の使用を開始
プロンプトを構築する際には、高品質なテンプレートのグローバル思考チェーンを参考にし、習熟した後は、完全にそのテンプレートを増減改変して自分に合ったものを得ることができます。例えば、出力形式を制御する必要がある場合、特にフォーマットされた出力が必要な場合は、Ouput や OutputFormat のようなモジュールを追加することができます。
文脈の意味の一貫性を保つ
これは 2 つの側面を含みます。一つは形式の意味の一貫性、もう一つは内容の意味の一貫性です。
-
形式の意味の一貫性は、識別子の識別機能が前後で一貫していることを指します。混用しない方が良いです。例えば、# がタイトルの識別と変数の識別の両方に使用されると、前後の不一致が生じ、モデルがプロンプトの階層構造を認識するのに干渉を引き起こします。
-
内容の意味の一貫性は、思考チェーン上の属性語の意味が適切であることを指します。例えば、LangGPT の Profile 属性語は元々Features でしたが、実践と考察の結果、Profile に変更しました。これにより、その機能がより明確になりました:すなわち、役割の履歴書です。構造化プロンプトの考え方が多くの友人に広く使用された後、多くのテンプレートが派生しましたが、基本的には Profile の多くの設計が保持されており、その設計が成功していることを示しています。内容の意味の一貫性には、属性語と対応するモジュール内容の意味の一致も含まれます。例えば、Rules 部分は役割が遵守すべきルールであるため、役割のスキルや説明を大量に堆積させるのは適切ではありません。
LangGPT の Role(役割)テンプレート#
Role: Your_Role_Name
Profile
- Author: YZFly
- Version: 0.1
- Language: English or 中文 or Other language
- Description: あなたの役割を説明します。キャラクターの特徴とスキルの概要を示します。
Skill-1
- スキルの説明 1
- スキルの説明 2
Skill-2
- スキルの説明 1
- スキルの説明 2
Rules
- どんな状況でもキャラクターを壊さないでください。
- 無駄話をせず、事実を作り上げないでください。
Workflow
- 最初に、xxx
- 次に、xxx
- 最後に、xxx
Initialization
As a/an < Role >, you must follow the < Rules >, you must talk to user in default < Language >,you must greet the user. Then introduce yourself and introduce the < Workflow >.
プロンプトチェーンは、元の要求を分解し、複数の小さなプロンプトを連結 / 並列させて、複雑なタスクを共同で解決します。
プロンプトの協調は、プロンプトツリーを通じて、トップダウンの設計思想を用いて、サブタスクを継続的に分解し、タスクツリーを構成し、さまざまなモデル出力を得て、これらの出力をカスタムルール(組み合わせ、フィルタリング、統合など)を通じて最終結果を得ることができます。API バージョンのプロンプトチェーンは、プログラミングと組み合わせることで、全体のプロセスをより自動化できます。
プロンプト設計方法論#
- データ準備。高品質なケースデータを収集し、後の分析の基礎とします。
- モデル選択。具体的な創作目的に応じて、適切な大規模言語モデルを選択します。
- プロンプト設計。ケースデータに基づいて初版のプロンプトを設計します。役割設定、背景説明、目標定義、制約条件などの要点に注意します。
- テストと反復。プロンプトを GPT に入力してテストし、結果を分析します。追求、深い交流、問題の指摘などを通じて GPT と交流し、最適化の提案を得ます。
- プロンプトの修正。GPT からのフィードバックに基づいて、プロンプトの各部分を調整し、効果的な要素を強化し、無効な要素を排除します。
- 再テスト。修正されたプロンプトを再度テストし、結果を比較し、GPT に再度質問し、プロンプトを調整します。
- 循環反復。上記のテスト - 交流 - 修正プロセスを繰り返し、結果が満足するまで続けます。
- まとめと抽出。プロンプトの最適化プロセスで得られた貴重な経験を要約し、プロンプト設計のベストプラクティスを形成します。
- 応用拡張。習得した方法論を他の創造的なコンテンツの設計に応用し、プロンプト設計のスキルを豊かにします。
sys_prompt = """あなたは賢いカスタマーサービスです。ユーザーの質問に基づいて、異なるタスクを異なる人に割り当てることができます。あなたには以下のビジネスラインがあります:
1. ユーザー登録。ユーザーがこの操作を実行したい場合、"registered workers"という特別なトークンを送信する必要があります。そして、ユーザーにそれを呼び出していることを伝えます。
2. ユーザーデータの照会。ユーザーがこの操作を実行したい場合、"query workers"という特別なトークンを送信する必要があります。そして、ユーザーにそれを呼び出していることを伝えます。
3. ユーザーデータの削除。ユーザーがこのタイプの操作を実行したい場合、"delete workers"という特別なトークンを送信する必要があります。そして、ユーザーにそれを呼び出していることを伝えます。
"""
registered_prompt = """
あなたのタスクは、ユーザー情報を保存することです。ユーザーから以下の情報を取得する必要があります:
1. ユーザー名、性別、年齢
2. ユーザーが設定したパスワード
3. ユーザーの電子メールアドレス
ユーザーがこの情報を提供しない場合、ユーザーに提供を促す必要があります。ユーザーがこの情報を提供した場合、その情報をデータベースに保存し、ユーザーに登録成功を伝える必要があります。
保存方法はSQL文を使用します。SQLを使用して挿入文を作成し、ユーザーIDを生成してユーザーに返す必要があります。
ユーザーに新しい質問がない場合、"customer service"という特別なトークンを返信してタスクを終了する必要があります。
"""
query_prompt = """
あなたのタスクは、ユーザー情報を照会することです。ユーザーから以下の情報を取得する必要があります:
1. ユーザーID
2. ユーザーが設定したパスワード
ユーザーがこの情報を提供しない場合、ユーザーに提供を促す必要があります。ユーザーがこの情報を提供した場合、データベースを照会する必要があります。ユーザーIDとパスワードが一致する場合、ユーザーの情報を返す必要があります。
ユーザーに新しい質問がない場合、"customer service"という特別なトークンを返信してタスクを終了する必要があります。
"""
delete_prompt = """
あなたのタスクは、ユーザー情報を削除することです。ユーザーから以下の情報を取得する必要があります:
1. ユーザーID
2. ユーザーが設定したパスワード
3. ユーザーの電子メールアドレス
ユーザーがこの情報を提供しない場合、その情報を提供するようにユーザーに促す必要があります。
ユーザーがこれらの情報を提供した場合、データベースを照会する必要があります。ユーザーIDとパスワードが一致する場合、ユーザーに確認コードが電子メールに送信されたことを通知し、確認を行う必要があります。
ユーザーに新しい質問がない場合、"customer service"という特別なトークンを返信してタスクを終了する必要があります。
"""
インテリジェントカスタマーサービスエージェント#
インテリジェントカスタマーサービスエージェントを定義します。class SmartAssistant:
def __init__(self):
self.client = client #clientを定義
# 異なる部分のプロンプトを定義
self.system_prompt = sys_prompt
self.registered_prompt = registered_prompt
self.query_prompt = query_prompt
self.delete_prompt = delete_prompt
# 異なるメッセージの集合を格納するために辞書を使用
self.messages = {
"system": [{"role": "system", "content": self.system_prompt}],
"registered": [{"role": "system", "content": self.registered_prompt}],
"query": [{"role": "system", "content": self.query_prompt}],
"delete": [{"role": "system", "content": self.delete_prompt}]
}
# メッセージ処理のための現在の割り当て
self.current_assignment = "system"
メソッドを定義:
def get_response(self, user_input):
self.messages[self.current_assignment].append({"role": "user", "content": user_input})# ユーザーの返信を記録
while True:
response = self.client.chat.completions.create(
model=chat_model,
messages=self.messages[self.current_assignment],
temperature=0.9,
stream=False,
max_tokens=2000,
)
ai_response = response.choices[0].message.content
if "registered workers" in ai_response:
self.current_assignment = "registered"
print("意図認識:",ai_response)
print("switch to <registered>")
self.messages[self.current_assignment].append({"role": "user", "content": user_input})
elif "query workers" in ai_response:
self.current_assignment = "query"
print("意図認識:",ai_response)
print("switch to <query>")
self.messages[self.current_assignment].append({"role": "user", "content": user_input})
elif "delete workers" in ai_response:
self.current_assignment = "delete"
print("意図認識:",ai_response)
print("switch to <delete>")
self.messages[self.current_assignment].append({"role": "user", "content": user_input})
elif "customer service" in ai_response:
print("意図認識:",ai_response)
print("switch to <customer service>")
self.messages["system"] += self.messages[self.current_assignment]
self.current_assignment = "system"
return ai_response
else:
self.messages[self.current_assignment].append({"role": "assistant", "content": ai_response})
return ai_response
解析:
self.client.chat.completions.create:これはメソッド呼び出しで、会話の応答を生成するために使用されます。入力メッセージを処理し、対応する出力を生成するためにチャットモデルを使用します。
ai_response = response.choices [0].message.content:choices は response オブジェクトの属性で、複数の可能な応答オプションを含むリストです。[0] は最初のオプションを選択します。通常、API は複数の可能な応答を返しますが、ここでは最初のものを選択しています。message は choices [0] の属性で、そのオプションのメッセージ内容を示します。content は message の属性で、実際のテキスト内容、すなわち AI アシスタントが生成した応答を示します。したがって、この行のコードは、API から返された応答から最初のオプションのテキスト内容を抽出し、それを ai_response 変数に格納する役割を果たします。
AI の応答に "registered workers" が含まれている場合、現在のタスクを "registered" に切り替え、ユーザー入力をそのタスクのメッセージリストに追加します。
AI の応答に "query workers" が含まれている場合、現在のタスクを "query" に切り替え、ユーザー入力をそのタスクのメッセージリストに追加します。
AI の応答に "delete workers" が含まれている場合、現在のタスクを "delete" に切り替え、ユーザー入力をそのタスクのメッセージリストに追加します。
AI の応答に "customer service" が含まれている場合、現在のタスクを "system" に切り替え、現在のタスクのメッセージをシステムメッセージに統合し、現在のタスクを終了します。
対話を開始する:
def start_conversation(self):
while True:
user_input = input("User: ")
if user_input.lower() in ['exit', 'quit']:
print("会話を終了します。")
break
response = self.get_response(user_input)
print("Assistant:", response)
コード解析:ユーザーは情報を入力でき、システムは入力に基づいて get_response メソッドを呼び出して応答を生成し、その応答をユーザーに表示します。ユーザーは "exit" または "quit" を入力することで対話を終了できます。
効果の展示#
Assistant: こんにちは!ID 1001 のユーザー、どの操作を実行したいですか?
- ユーザー登録 - 新しいユーザーを登録したい場合は、教えてください。
- ユーザーデータの照会 - ユーザーデータを照会したい場合は、教えてください。
- ユーザーデータの削除 - ユーザーデータを削除したい場合は、教えてください。
ご要望に応じて、適切な操作を選択してください。私はそれに応じて作業者を呼び出します。
意図認識:了解しました。ID 1001 のユーザーデータを照会する必要があります。私は "query workers" という特別なトークンを送信して、ユーザーデータ照会を処理する作業者を呼び出します。少々お待ちください、結果をお知らせします。
switch to
Assistant: 設定したパスワードを提供してください。
意図認識:照会中ですので、少々お待ちください。(照会をシミュレート)
ユーザー ID 1001 の情報は以下の通りです:
- ユーザー名:張三
- メール:[email protected]
- 登録日:2021-05-15
照会が完了しました。
他に質問がありますか?もしない場合は、「customer service」と返信してタスクを終了してください。
switch to
Assistant: 照会中ですので、少々お待ちください。(照会をシミュレート)
ユーザー ID 1001 の情報は以下の通りです:
- ユーザー名:張三
...
他に質問がありますか?もしない場合は、「customer service」と返信してタスクを終了してください。
意図認識:ユーザー ID とパスワードを提供しましたので、私は "query workers" という特別なトークンを送信して、作業者にデータベースを照会させます。少々お待ちください。