複数の ChatGPT プラグインを開発し AI オーケストレーションを実行するサンプルコード
今回は Copilot stack のカスタマイズの中心となるプラグイン開発について紹介します。
Copilot stack
Copilot stack は大規模 LLM をオーケストレーターとして利用し、複数のプラグインや外部システムの情報と連携させて GPT-4 のプラグイン機能や Microsoft の各製品に搭載される Copilot と連携したり独自の Copilot を開発できるフレームワークです。
プラグイン開発
ChatGPT 規格のプラグインを開発すれば、以下のようにブラウザ版 GPT-4 だけでなく、Bing や Microsoft 365 Copilot、Windows Copilot などからも利用可能になります。当然、組織独自の Copilot と統合することもできます。このプラグインによって、最新の情報や組織内のデータを反映させた(Grounding)回答を行ったり、ReAct などのタスクを実行させることが可能になります。Microsoft では、業界全体の連携を推進するために、プラグインの標準として OpenAPI プラグイン仕様の採用を進めています。
複数のシステムをプラグイン化する
はい、いつもの戦国武将ネタでデモを行おうと思います。コードはデモ用に極限までシンプル化しています。
今回はこのような 2 つの異なるシステムを ChatGPT プラグインとして公開し、これを AI オーケストレーターである Langchain から呼ぶデモを構築します。
「源範頼に関連するカフェ名を検索して、7/1の18時に予約に空きがあるか教えて。もし空いていたら予約しておいて。」というユーザーからの指示に回答できるようなシステムを構築します。
開発するプラグインとエンドポイント
- 武将カフェ検索プラグイン: カフェ検索システム
-
/search
カフェ検索
-
- レストラン予約プラグイン: レストラン予約システム
-
/search
予約検索 -
/reserve
予約
-
フロー解説
- UI からユーザーの指示が投げられます。
- クエリは LangChain が受け取り、
ZERO_SHOT_REACT_DESCRIPTION
Agent が Reasoning を行います。 -
武将カフェ検索プラグインにアクセスし、 API 仕様をロードし、エンドポイントの情報と説明書きを受け取ります。その結果、検索ができそうだと判定します。実際に検索するには、「GET リクエストを
/search
エンドポイントに送信して、クエリパラメータとしてカフェの名前を指定する必要があります。」と考えて、「源範頼」を5005
番ポートに検索リクエストを投げます。 - 次にレストラン予約プラグインを呼び出して、「カフェかば殿」で 7/1 の 18 時に予約が可能かどうかを確認します。「そのためには、
/search
エンドポイントをGETリクエストで使用します。パラメータとしてq
(レストラン名)とdatetime
(日時)を必要とします。」と考えます。5006
ポートにアクセスして、カフェ名と空き状況の情報を検索してます。 - このカフェでは予約可能であることが確認できましたので、今度は
/reserve
エンドポイントに POST リクエストを送信して予約を行います。OK が返ってきましたので予約完了です。 - 最後に UI に「カフェかば殿で 7/1 の 18-19 時で予約を行いました」と返却します。
AIPluginTool へプラグインをロード
llm = ChatOpenAI(model_name="gpt-4-0613", temperature=0)
tools = load_tools(["requests_all"])
plugin_urls = ["http://localhost:5005/.well-known/ai-plugin.json", "http://localhost:5006/.well-known/ai-plugin.json"]
tools += [AIPluginTool.from_plugin_url(url) for url in plugin_urls]
Agent の初期化
制約条件や言語の設定をプロンプトに含めています。
SUFFIX = """
'Answer should be in Japanese. Use http instead of https for endpoint.
If there is no year in the reservation, use the year 2023.
"""
# Responsible AI MetaPrompt
#**IMPORTANT**
#If a restaurant reservation is available, must check with the user before making a reservation if yes.'
agent_chain = initialize_agent(tools,
llm,
agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, verbose=True,
agent_kwargs=dict(suffix=SUFFIX + prompt.SUFFIX))
Function calling
gpt-4-0613
、gpt-3.5-turbo-0613
の最新モデルでは Function calling 機能が追加され、これまでAgent 、プロンプトでやっていた必要なツールの選定をモデル側でやってくれます。Langchain ではいち早く連携され、AgentType.OPENAI_FUNCTIONS
と指定するだけで利用することができます。コチラを使うと Reasoning 全体の速度がめちゃくちゃ速くなります。
import langchain
langchain.debug = True
agent_chain = initialize_agent(tools,
llm,
agent=AgentType.OPENAI_FUNCTIONS, verbose=True)
AgentType.OPENAI_MULTI_FUNCTIONS
を使用すると呼び出しを並列化してコストを削減することもできます。
langchain.debug = True
を設定すると LangChain によって隠蔽化されているリクエストの中身を見ることができるので便利です。
※Azure OpenAI では Function calling 機能についてはもう間もなく対応します。
AI 安全性
このデモでは単純化するために、ユーザーへの確認プロセスなどを省いていますが、AI の安全性、 Responsible AI の観点から実際にアクションを実行する直前には人間からの最終確認のプロセスを導入することも検討してください。
今後
Azure AI Studio が使えるようになると、このような AI オーケストレーターをクラウド上で構築し、テストやエンドポイントのデプロイまでできるようになります。早く使えるようになって欲しいです。
サンプルコードと Notebook
このデモだけのために究極に単純化したコードを Github に上げておきましたのでご参考まで。この部分、複数の社内システムですとか、開発した機械学習モデルですとかと繋げてみていただければできることが非常に広がるのではないでしょうか。
Discussion