🌊

OpenAI APIとLangChainエージェントでFunction Calling機能を使用する

2023/06/21に公開

はじめに

この記事では最近注目を集めているOpenAI APIのFunction Calling機能をLangChainで実装するという内容になります。
なお、本記事の内容とソースコードは以下のnpakaさんによる記事の内容とソースコードを参考に作成しました。
https://note.com/npaka/n/n917463f55b8a

また、本記事で実装するソースコードではpytestを使用して実行結果の出力内容を確認しています。

LangChainで使用するモデルのセットアップ

まずはLangChainで使用するエージェントの設定を行います。

from langchain.chat_models import ChatOpenAI
import openai

class TestChatFunctionCalling:
    def setup(self):
        openai_api_key = os.getenv('OPENAI_API_KEY')
        openai.api_key = openai_api_key # APIキーの認証
	# 使用するモデルを定義
        self.model = ChatOpenAI(model='gpt-3.5-turbo-0613', temperature=0)

OpenAI Functionの定義

次に、LangChainで使用する具体的な機能を定義します。
ここでは、「現在の天気を取得する」という機能を作成しています。

from langchain.agents.tools import BaseTool
from pydantic import Field, BaseModel
from typing import Optional, Type
from enum import Enum
import json

# 温度の単位を表すEnumクラスを定義します
class WeatherUnit(str, Enum):
    celsius = 'celsius'
    fahrenheit = 'fahrenheit'

# 天気情報を取得するための入力パラメータを定義するモデルを作成します
class GetCurrentWeatherCheckInput(BaseModel):
    location: str = Field(..., description='city_and_state')
    unit: WeatherUnit

# 天気情報を取得する機能を定義
class GetCurrentWeatherTool(BaseTool):
    name = 'get_current_weather'
    description = 'Acquire current weather at a specified location.'

    # _runメソッドに具体的な機能の実装を記述
    def _run(self, location: str, unit: str = 'fahrenheit'):
  
        # 実際は外部の天気API等から情報を取得
        weather_info = {
            "location": location,
            "temperature": "72",
            "unit": unit,
            "forecast": ["sunny", "windy"],
        }
        return json.dumps(weather_info)

    def _arun(self, location: str, unit: str):
        raise NotImplementedError("This tool does not support async")

    # 入力パラメータのスキーマを定義
    args_schema: Optional[Type[BaseModel]] = GetCurrentWeatherCheckInput

上記では_runメソッドにダミーとして天気情報を返すようにしていますが、実際は外部の天気API等から情報を取得する必要があります。

エージェントの初期化とOpenAI Functionの呼び出し

ここでは、Function Callingをテストするメソッドを定義しています。

from langchain.agents import AgentType, initialize_agent
import logging

def test_get_current_weather_function(self, request='東京の天気を教えてくれますか?'):
    # 使用するツールをリストとして定義
    tools = [GetCurrentWeatherTool()]
    # エージェントを初期化
    agent = initialize_agent(tools=tools, llm=self.model, agent=AgentType.OPENAI_FUNCTIONS, verbose=True)
    # 自然言語のリクエストを実行し、結果を出力
    response = agent.run(request)
    logging.debug(response)

pytest.iniファイルの設定

pytest上でログを出力させるには、pytest.iniファイルを作成して、
ログ出力の設定を行う必要があるみたいです。

[pytest]
addopts = -p no:warnings
log_cli=true
log_level=DEBUG
log_format = %(asctime)s %(levelname)s: %(message)s

pytestの実行

pytestを実行して出力内容を確認します。

pytest -s

出力結果

> Finished chain.
17:25:54 DEBUG: 東京の天気は晴れで、気温は摂氏72度です。また、風も強いようです。

まとめ

今回の記事では、LangChainのエージェントとOpenAIのFunction Callingを組み合わせて、自然言語のリクエストから関数を実行するという内容でした。

ちょっと前まではLangChainを使用することでChatGPTが苦手とする最新情報の取得やプログラムの実行といったことを実現するためのライブラリで、Function Callingの登場によりLangChainはもう必要ない説が出てきているような気がしますが、むしろ他のエージェントタイプと組み合わせたり、データベースとの連携をLangChainを用いて行うことでより強力なアプリケーションが作れるような気がしました。

Discussion