BabyAGI の LangChain 実装版を試してみた(ver. GPT-3.5)

FacebooktwitterredditpinterestlinkedinmailFacebooktwitterredditpinterestlinkedinmail

前回の関連:https://ict-worker.com/ai/autogpt-langchain.html

アジとかサバとか、IT 系は青魚がお好き。さて、 AGI とはなんぞやとか、LLMが AGI か否かとかそういう話は魚を焼くにも火力が強すぎるお話になりがちなので、放っておくとして。

yohei nakajima 氏の BabyAGI が LangChain でも実装されているので、それをいじってみます。

BabyAGI ってなーんだ

https://twitter.com/yoheinakajima/status/1640934493489070080?s=20

同じく Nakajima 氏による論文の、Task -Driven Autonomous Agent (タスク駆動型自律式エージェント)を短縮したバージョンだそうです。詳しくは Tweet の図を見ると分かりやすいのですが、タスクを実行する LLM Agent の他に、 Task を作成する Agent, それから Task の優先順位を作成する Agent の3つエージェントによって複雑なタスクを分解し処理するアプローチです。

一つのvector store によるメモリをタスク生成 agent と実行 agent で共有する点は、AutoGPT と共通していますね。ただ、 Task Queue に対し、実行優先順位も決定する agent がいるというのが面白いなと思いました。会社組織だったら絶対喧嘩する奴ですね。

LangChain で実行するとどんないいことがあるの?

オリジナルの BabyAGI もオープンソースで、 Python による実装が GitHub で公開されており、実行環境があれば自由に実験することができます。

しかし、敢えて LangChain に取りこまれたバージョンを使う動機がいくつもあります。

  1. GitHub Clone とかしなくていい
    公開リポジトリとかなんか怖いし……pip install だけで動くので気楽
  2. LLM や vector store の実装を自由に選べる
    LLM の選択肢は現状少ないですが、 vector store についてはオリジナルのBabyAGIではpineconeで実装されています。そのため、API キーが必要ですが(無料で試用は可能)、これを好きなVector Store に出来る
  3. LangChain で実装されている(これから実装される)Tools との組み合わせが容易
    オリジナルの BabyAGI でも自分で実装すれば組み合わせられると思いますが、慣れたインターフェースで豊富なツールが容易されているのは便利です

主に「楽だから」ですが、 LangChain 経由で実装するとこれらのメリットを享受できます。もちろん、学習のために BabyAGI そのものを触って見るというのもありだと思います。

とはいえ、AutoGPT のような他の手法と気軽に比較できるメリットが現状では大きいと思います(来月にはまた全然違ったタスク解決への応用が出てこないとも言い切れません)。

LangChain から BabyAGI を実行してみる

参考:https://python.langchain.com/en/latest/use_cases/autonomous_agents/baby_agi.html

まずは import とか

BabyAGI をimport する以外はほぼ前回と一緒です(それだけ、タスクに分解し、vector storeに格納して実行させるという手法が有効なのでしょう)。

from typing import Optional

from langchain.chat_models import ChatOpenAI
from langchain.embeddings import OpenAIEmbeddings
from langchain.experimental import BabyAGI

from langchain.vectorstores import FAISS
import faiss
from langchain.docstore import InMemoryDocstore

import os, key

Embedding の準備とか

# Embedding model の準備
embeddings_model = OpenAIEmbeddings()
# 空のvector storeを作成
embedding_size = 1536
index = faiss.IndexFlatL2(embedding_size)
vectorstore = FAISS(embeddings_model.embed_query, index, InMemoryDocstore({}), {})

# GPT-3.5-turbo モデルの準備
llm = ChatOpenAI(temperature=0)

LangChain のサンプルページでは、 LLM に OpenAI を使っていて、model も GPT-3 davinci を利用しています。が、特にメリットを感じられなかったので、ここでは ChatOpenAI を利用しています(OpenAIでも model_name を指定することで利用するモデルを GPT-3.5-turbo に切り替えられますが、 warning が出ます)。

BabyAGI の設定と起動

# Logging of LLMChains
verbose = False
# 設定しないと無限ループに突入する
max_iterations: Optional[int] = 3
baby_agi = BabyAGI.from_llm(
    llm=llm, vectorstore=vectorstore, verbose=verbose, max_iterations=max_iterations
)
OBJECTIVE = "Write a weather report for SF today"
baby_agi({"objective": OBJECTIVE})

基本的に Agent と使い方が一緒なのは AutoGPT と同様です(ここでは Tools を使っていない分コードが短いですが)。

特記事項としては、max_iterations (最大繰り返し)が設定できる点です。コメントにもあるとおり、これを設定しないと LLM 同士(Agent 同士)で無限に対話を繰り返してしまうことがこれまでもありました。これを設定してどこまで解を正確に出せるか? はともかくとして、 いつInterrupt しようか考えながらToken が溶けていく Console を見つめるよりはマシでしょう。

また、baby_agi の場合、ユーザーからの入力は objective: 目的と表現するようです。

実行してみる

検索用 Tool が設定されていないのでどう頑張っても幻視された結果しか出てこない点はともかくとして、天気予報をするというタスクについても、1回目のタスク生成の段階で6つのタスクに分解している点が興味深いです。

  1. 現在の天候データの取得
  2. 現在の気温、湿度、風の情報などを分析する
  3. 現在の気象警報などの情報を集める
  4. 正確で分かりやすいように校正する(データを? 文章を?)
  5. サンフランシスコの天気予報を詳しく書く。現在の状況や潜在的な天候の危険性を含む。
  6. 指定された場所や人に公開する

確かにプロフェッショナルの天気予報士のタスクのように見えます。とはいえ……

1を実行した時点で限界繰り返し数に到達し(最初のTask list Noneの状態からカウントされると思われる)、最終出力となっています。

サンフランシスコの現在の気象データを取得した後、同市の現在の気象警報や注意報について調査し、情報を収集しました。現在のところ、サンフランシスコには気象警報や注意報は発令されていません。天候は概ね晴れ、最高気温は68°F、最低気温は54°Fと予想されています。夕方には気温が下がるかもしれないので、軽いジャケットやセーターを持ち歩くことをお勧めします。サンフランシスコで素敵な一日をお過ごしください!

この結果が妥当かどうかは……ちょっと分かりません(当然検索結果も含まれていないはずなので、正解していても偶然でしょう)。

ちなみに、日本語にすると……

タスクリストを生成したところで終わってしまいました……。

BabyAGI を LangChain の Tool と一緒に使う

参考:https://python.langchain.com/en/latest/use_cases/autonomous_agents/baby_agi_with_agent.html

import から 基本的な初期化

前節と同じ辺りまで

from typing import Optional

from langchain.chat_models import ChatOpenAI
from langchain.embeddings import OpenAIEmbeddings
from langchain.experimental import BabyAGI

from langchain.vectorstores import FAISS
import faiss
from langchain.docstore import InMemoryDocstore

from langchain.agents import ZeroShotAgent, Tool, AgentExecutor
from langchain import LLMChain, PromptTemplate
from langchain.utilities import GoogleSearchAPIWrapper

import os, key
os.environ["OPENAI_API_KEY"] = key.OPEN_API_KEY
os.environ["GOOGLE_CSE_ID"] = key.GOOGLE_CSE_ID
os.environ["GOOGLE_API_KEY"] = key.GOOGLE_API_KEY

embeddings_model = OpenAIEmbeddings()
embedding_size = 1536
index = faiss.IndexFlatL2(embedding_size)
vectorstore = FAISS(embeddings_model.embed_query, index, InMemoryDocstore({}), {})

llm = ChatOpenAI(temperature=0)

以降のコードもそうなのですが、import でも AutoGPT より追加分が多いです。というのも、 AutoGPT は Agent として単体で実装されているのですが、 BabyAGI の方が LLM の関係が複雑なようで、使用するツールを入れ換えるためには Chain, Agent の作り直しが必要なようです。

Tools の定義

todo_prompt = PromptTemplate.from_template(
    "You are a planner who is an expert at coming up with a todo list for a given objective. Come up with a todo list for this objective: {objective}"
    # あなたは、とある目的のためにTodoリストを考えるのが得意なプランナーです。この目的のためにTodoリストを考えてください:{objective}
)
todo_chain = LLMChain(llm=llm, prompt=todo_prompt)
search = GoogleSearchAPIWrapper()
tools = [
    Tool(
        name="Search",
        func=search.run,
        description="useful for when you need to answer questions about current events",
    ),
    Tool(
        name="TODO",
        func=todo_chain.run,
        description="useful for when you need to come up with todo lists. Input: an objective to create a todo list for. Output: a todo list for that objective. Please be very clear what the objective is!",
    ),
]

Todo リスト作成用の Prompt を定義して、LLM Chain にまとめて Tools に入れています。これが、冒頭に示した BabyAGI の Task Creation Agent に相当すると考えられます。もう一つの Tool が並列に存在しているので、論文の図では、 Task Execution がこの Tools を所有する関係になるでしょう。

ZeroShotAgent の作成

上述した通り、 Task Execution Agent に相当すると思います。

prefix = """You are an AI who performs one task based on the following objective: {objective}. Take into account these previously completed tasks: {context}."""
# あなたは、目的:{objective}に基づき1つのタスクを実行するAIです。
# 以前に完了したこれらのタスクを考慮に入れてください: {context}。
suffix = """Question: {task}
{agent_scratchpad}"""
prompt = ZeroShotAgent.create_prompt(
    tools,
    prefix=prefix,
    suffix=suffix,
    input_variables=["objective", "task", "context", "agent_scratchpad"],
)

llm_chain = LLMChain(llm=llm, prompt=prompt)
tool_names = [tool.name for tool in tools]
agent = ZeroShotAgent(llm_chain=llm_chain, allowed_tools=tool_names)
agent_executor = AgentExecutor.from_agent_and_tools(
    agent=agent, tools=tools, verbose=True
)

実行するタスクを1つに絞った prompt が与えられているところが、これまでの ZeroshotAgent の設計とは異なる部分ですね。あくまでも Task を一つ Execution するエージェントのようです。

先に作成しておいた Tools を利用して agent を作成します。さらに、 AgentExceutor のインスタンスとして、Tool とセットで実体化しておきます(すぐに実行させずにBabyAGIに渡す)。

BabyAGI の作成と実行

ここまでくれば、前半とほぼ一緒です。

# Logging of LLMChains
verbose = False
# 無限ループ防止
max_iterations: Optional[int] = 3
baby_agi = BabyAGI.from_llm(
    llm=llm, vectorstore=vectorstore, task_execution_chain=agent_executor, verbose=verbose, max_iterations=max_iterations
)

OBJECTIVE = "Write a weather report for SF today"
baby_agi({"objective": OBJECTIVE})

from_llm メソッドでインスタンスを作成しますが、LLM, Memory の他、Task Execution Chain として論文で言う Task Execution Agent を渡します。このインスタンス内部には Task Creation Agent が Tool として内包されていて、 Agent 自体は1度に1回のタスクを実行するよう制約を受けて、タスク作成の他様々な Tool(今回は検索エンジンラッパー)を保持しています。

これにより、 BabyAGI インスタンスから階層としてBabyAGI→TaskExcecutionAgent→TaskCreationAgentという構造になります(なので、BabyAGIインスタンスに直接入れられた LLM は  Task Prioritization Agentになると思います)。

実行結果:

なんかいきなりピクニックを計画し出しましたよ……。

*****TASK RESULT*****
The latest weather forecast for San Francisco predicts mostly cloudy skies tonight with a low around 53°F and partly sunny skies tomorrow with a high near 66°F. There is no expected precipitation and the wind speed is expected to be around 9-11 mph. Those planning to spend time outdoors should be prepared for cooler temperatures tomorrow compared to today.

とはいえ、結果はちゃんと出て来ました。かなり具体的でいいですね。

日本語の実行結果:

いや……検索すれば分かるのは知っているんですが……。

もう一度実行すると、

To determine if the weather will affect party plans, I need to check the weather forecast for the date of the party, determine if there are any weather warnings or advisories in effect, and consider alternative indoor locations for the party. Additionally, I should create a guest list, plan the menu, purchase necessary ingredients, decide on decorations, rent any necessary equipment, hire a caterer or bartender if needed, plan activities or entertainment, set up the party space, coordinate with any vendors or helpers, and finally, enjoy the party!

なんかパーティーすることになってます。

恐らく、タスク作成のプロセスに objective が正常に反映されていないのだと思われます(日本語だからではなく、先のサンフランシスコの例でもピクニック行くことになっていたので、GPT-3.5-turbo と相性がよくないpromptのようです)。

ただ、GPT-3.5 だから問題なのか、 Tools を導入した途端に不安定になったため、 Tools のdescription や prompt が問題なのかはちょっと判断が難しいです。

FacebooktwitterredditpinterestlinkedinmailFacebooktwitterredditpinterestlinkedinmail

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください

最新の記事