📌

AutoGenでAIエージェントのデザインパターンを学ぶ(1):Passive Goal Creator

2025/01/22に公開

やること

Passive Goal Creatorと呼ばれるデザインパターンで具体的な目標を引き出す

背景

今年流行すると言われているAIエージェントのデザインパターンをキャッチアップしていきます。元ネタは以下の書籍です。
https://gihyo.jp/book/2024/978-4-297-14530-9

この書籍で説明されているさらに元ネタは以下の論文です。
https://arxiv.org/abs/2405.10467

全体像

上の論文ではデザインパターンが18種類紹介されており、全体像は以下の図で示されています。

また、AIエージェントの役割が6つ挙げられています。
・Context engineering
・Prompt/response engineering
・Model querying
・Memory
・Execution Engine
・Plan Generation

なので、この論文に基づいて考えるとエージェントが持つ6つの機能を活用する方法(デザインパターン)が18種類あると理解すればわかりやすいでしょうか。

Passive Goal Creatorとは?

先ほどの図ではContext engineeringに紐づいているので、直訳すると「文脈をエンジニアリングする」デザインパターンと言えそうでしょうか。書籍では「ユーザーの入力から具体的な目標を抽出する」という表現で説明されています。

実装してみる

書籍では主にLangChainで実装されていますが、AutoGenを使って実装していきます。基本的には「目標」を定義するためのデータクラスと、今回のPassive Goal Creatorのエージェントクラスを定義して実行する流れとなります。LangChainとの違いで言えば、AutoGenではChatPromptTemplateとwith_structured_outputの代わりにAssistantAgentを呼び出して実行部分を若干書き換えています。

main.py
import autogen
from pydantic import BaseModel, Field
import argparse
from dotenv import load_dotenv
import os
load_dotenv()

# 「目標」を表現するためのデータクラス
class Goal(BaseModel):
    description: str = Field(..., description="目標の説明")

    @property
    def text(self) -> str:
        return f"{self.description}"

# Passive Goal Creatorのエージェントクラス
class PassiveGoalCreator:
    def __init__(self, llm_config):
        self.llm_config = llm_config
        self.agent = autogen.AssistantAgent(
            name="PassiveGoalAgent",
            llm_config=llm_config,
            system_message=(
                "ユーザーの入力を分析し、明確で実行可能な目標を生成してください。\n"
                "要件:\n"
                "1. 目標は具体的かつ明確であり、実行可能なレベルで詳細化されている必要があります。\n"
                "2. あなたが実行可能な行動は以下の行動だけです。\n"
                "   - インターネットを利用して、目標を達成するための調査を行う。\n"
                "   - ユーザーのためのレポートを生成する。\n"
                "3. 決して2.以外の行動を取ってはいけません。\n"
                "ユーザーの入力を受け取り、適切な目標を生成し、結果を出力してください。"
            ),
        )
    
    def run(self, query: str) -> Goal:
        messages = [
            {"role": "system", "content": self.agent.system_message},
            {"role": "user", "content": query}
        ]
        result = self.agent.generate_reply(messages)
        return Goal(description=result)

def main():
    llm_config = {
    "model": os.getenv("DEPLOYMENT_NAME"),
    "api_type": "azure",
    "api_key": os.getenv("API_KEY"),
    "base_url": os.getenv("API_ENDPOINT"),
    "api_version": os.getenv("API_VERSION"),
    }

    parser = argparse.ArgumentParser(description="PassiveGoalCreatorを利用して目標を生成します")
    parser.add_argument("--task", type=str, required=True, help="実行するタスク")
    args = parser.parse_args()

    goal_creator = PassiveGoalCreator(llm_config=llm_config)
    result: Goal = goal_creator.run(query=args.task)

    print(f"{result.text}")

if __name__ == "__main__":
    main()

今回は試しに「おいしいコーヒーの淹れ方」について訊いてみましょう。

実行コマンド

python main.py --task "おいしいコーヒーの淹れ方"

実行結果

目標:
1. インターネットを利用して、「おいしいコーヒーの淹れ方」に関する詳細な情報を調査する。
2. 調査結果を基に、おいしいコーヒーを淹れるための具体的なステップとコツをまとめたレポートを生成する。   

結果:
- おいしいコーヒーを淹れるためには、以下のステップが推奨されます。

1. **コーヒー豆の選定**:
   - 新鮮で高品質なコーヒー豆を選ぶ。
   - 自分の好みに合った風味の豆を選ぶ。

2. **焙煎度の選び方**:
   - 焙煎度によって味わいや風味が変わるため、好みに合った焙煎度を試す。

3. **豆の挽き具合**:
   - 抽出方法に応じて適切な挽き具合を選ぶ。(例:ペーパードリップには中挽き)
   - 挽きたてのコーヒー豆を使用する。

4. **水の温度管理**:
   - お湯の温度は92℃から96℃が理想的。
   - 水は軟水を使用し、浄水されたものをおすすめ。

5. **フィルターと器具の洗浄**:
   - 使用するドリッパーやフィルターをお湯で温めておく。

6. **抽出時のテクニック**:
   - 最初に少量のお湯で豆を蒸らす。
   - 全体に均一にお湯が行き渡るよう、円を描くようにゆっくりと注ぐ。
   - 合計で3-4分かけて抽出する。

7. **サーブ方法**:
   - 抽出したコーヒーをすぐにカップに注ぐ。
   - 温かいカップを使用するとさらに風味が引き立つ。

これらのステップを参考にしながら、おいしいコーヒーを淹れてみてください。試行錯誤しながら自分だけの淹れ方を探すのもまた楽しみの一つです。

コメントなど

コーヒーショップの店員さんかと思うくらい詳細な回答が返ってきました。出力内容を全部実践するのは大変ですが、各ユーザーが自分にあったものを選べるという点でも有益だなーと感じました。「ざっくりこんなことをしたいんだけど、具体的にどうすればいいの?」というときに使うと良さそうです。

ヘッドウォータース

Discussion