Hanah

Hanah

wow-agent-day02 手搓一个土得掉渣的Agent

Reference: DataWhale wow agent day02

準備段階#

  1. 仮想環境 agent を作成し、pip install openai python-dotenv を実行します。
  2. 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"
  1. 環境変数を読み込むコード:
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 変数#

  1. ChatGPT は、さまざまな良好にマークされた階層構造のコンテンツを認識できます。
  2. プロンプトの内容を構造化された方法で提示し、タイトルを設定することで、簡単に引用、修正、プロンプト内容を設定できます。段落のタイトルを使用して大きな内容を指し示すことも、ChatGPT に特定の内容を修正するように指示することもできます。これはプログラミングの変数に似ているため、このタイトルを変数として使用できます。
  3. Markdown の構文階層構造は非常に良好で、プロンプトを書くのに適しているため、LangGPT の変数は Markdown 構文に基づいています。実際には、Markdown 以外のさまざまなマークアップ機能を持つもの(JSON、YAML、さらには適切にフォーマットされたもの)も使用できます。

LangGPT テンプレート#

Role テンプレートを使用するには、テンプレートに従って対応する内容を記入するだけです。
変数やテンプレートの他に、LangGPT はコマンド、メモリ、条件文などの構文設定方法も提供しています。

構造化プロンプトの概念#

識別子:#, <> などの記号(-, [] も含む)、これらの 2 つの記号はそれぞれタイトル、変数、コンテンツの階層を制御するために使用され、階層構造を識別します。

属性語: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. スキルの説明 1
  2. スキルの説明 2

Skill-2

  1. スキルの説明 1
  2. スキルの説明 2

Rules

  1. どんな状況でもキャラクターを壊さないでください。
  2. 無駄話をせず、事実を作り上げないでください。

Workflow

  1. 最初に、xxx
  2. 次に、xxx
  3. 最後に、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 バージョンのプロンプトチェーンは、プログラミングと組み合わせることで、全体のプロセスをより自動化できます。

プロンプト設計方法論#

  1. データ準備。高品質のケースデータを収集し、後の分析の基礎とします。
  2. モデル選択。具体的な創作目的に応じて、適切な大規模言語モデルを選択します。
  3. プロンプト設計。ケースデータに基づいて初版のプロンプトを設計します。役割設定、背景説明、目標定義、制約条件などの要点に注意します。
  4. テストと反復。プロンプトを GPT に入力してテストし、結果を分析します。追求、深い交流、問題の指摘などを通じて GPT と交流し、最適化の提案を得ます。
  5. プロンプト修正。GPT からのフィードバックに基づいて、プロンプトの各部分を調整し、有効な要素を強化し、無効な要素を排除します。
  6. 再テスト。修正されたプロンプトを再度テストし、結果を比較し、GPT に追求し、プロンプトを調整します。
  7. 循環反復。上記のテスト - 交流 - 修正プロセスを繰り返し、結果が満足するまで続けます。
  8. まとめと抽出。プロンプト最適化プロセスで得られた貴重な経験を要約し、プロンプト設計のベストプラクティスを形成します。
  9. 応用拡張。習得した方法論を他の創造的コンテンツの設計に応用し、プロンプト設計のスキルを豊かにします。
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 のユーザー、どの操作を実行したいですか?

  1. ユーザー登録 - 新しいユーザーを登録したい場合はお知らせください。
  2. ユーザーデータの照会 - ユーザーデータを照会したい場合はお知らせください。
  3. ユーザーデータの削除 - ユーザーデータを削除したい場合はお知らせください。

ご要望に応じて、適切な操作を選択してください。私はそれに応じて作業者を呼び出します。
意図認識:わかりました、ID 1001 のユーザーデータを照会する必要があります。"query workers" という特別なトークンを送信して、ユーザーデータの照会を処理する作業者を呼び出します。少々お待ちください、結果をお知らせします。
switch to
Assistant: 設定したパスワードを提供してください。
意図認識:照会中ですので、少々お待ちください。(照会をシミュレート)

ユーザー ID 1001 の情報は以下の通りです:

照会が完了しました。

他に相談したいことはありますか?もしなければ、「customer service」と返信してタスクを終了してください。
switch to
Assistant: 照会中ですので、少々お待ちください。(照会をシミュレート)

ユーザー ID 1001 の情報は以下の通りです:

  • ユーザー名:張三
    ...
    他に相談したいことはありますか?もしなければ、「customer service」と返信してタスクを終了してください。
    意図認識:ユーザー ID とパスワードを提供しましたので、"query workers" という特別なトークンを送信してデータベースを照会します。少々お待ちください。
読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。