LangChain最新バージョンで三大クラウドのLLMをサクッと実装してみる

DALL·Eで生成したLangChainのイメージ画像

  • LangChainの動作確認済みバージョン(2024/3/26時点では最新)
    • langchain: 0.1.13
    • langchain-community: 0.0.29
    • langchain-openai: 0.1.0
    • langchain-google-vertexai: 0.1.1


はじめに

テクノロジー戦略室 AI/MLエンジニアリングチームの稲垣です。
AI/MLエンジニアリングチームでは、レコメンドエンジンの MLOps 基盤の構築や、AWS Personalize などの ML サービスや LLM など生成 AI 活用を、企画から構築まで進めています。


今回は、LangChain の最新バージョン(2024/3/26時点)を使った複数モデルの実装方法について紹介します。

このような実装ニーズは良くあるかと思いますが、案外記事がまだ落ちていないようでしたので記事にしてみました。


現在、社内で LLM を使ったツール開発を行っており、LLM は以下のような複数ベンダー&複数モデルの API を使用しています。

  • GPT-3.5-turbo, GPT-4 (Azure OpenAI Service)
  • Gemini Pro (Google Cloud VertexAI)
  • Claude 2, Claude3 (AWS Bedrock)

それぞれのモデルに対して別個に実装していくことももちろん可能ですが、
API 入力/出力のフォーマット、良くある前処理や後処理、ストリーミングによる出力などの実装方法がモデルごとに異なるケースが多く、
それらを別個に実装していく手間はモデルの数が増えるほど大きくなっていきます。

(実際、anthropic-sdk-pythonによる Claude モデル実装と、google-cloud-aiplatformによる Gemini モデル実装は根本的な箇所でいくつか大きな差異があります。)

このようなモデルごとの実装の差異を吸収してくれるライブラリとしてLangChainがあり、 社内ツールの実装でも LangChain を利用しています。

LangChain:github.com


また、LangChain について最近の動向としては、
2024/1/6 にバージョン 0.0.354 から 0.1.0 へのアップデートがあり、LangChain 初の安定バージョンとなった、というニュースがありました。
(これ以前は破壊的な変更が頻繁に起こったり、公式ドキュメントのクイックスタートの内容が見るたびに変わっていたりしました、、、)

ただし、この 0.1 系へのアップデートにより、LangChain のパッケージの構成について大きな変更があったため、この点についても後半で補足しつつ説明をしていきたいと思います。


複数 LLM の切り替え実装

先に補足事項を記載します。

  • チャットツール等のユースケースではストリーミングによる出力を行うケースが多いかと思いますが、その場合は別途 CallBack 関数を渡す実装が必要になるケースがあるため、今回はストリーミングをオフにしています。
  • 下記のコード例では分かりやすさ重視のためシークレット情報をベタ書きしています。(実際の自社のコードではシークレット情報は AWS Secrets Manager で管理しています。)

AzureChatOpenAI

環境変数AZURE_OPENAI_ENDPOINTOPENAI_API_KEYに対しては、 Azure OpenAI Service から取得した値を設定しています。(参考

import os

from langchain_openai import AzureChatOpenAI


os.environ["AZURE_OPENAI_ENDPOINT"] = https://xxxxxxxxxxxxxx.openai.azure.com/
os.environ["OPENAI_API_KEY"] = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
os.environ["OPENAI_API_VERSION"] = "2023-05-15"


chat_model = AzureChatOpenAI(
    streaming=False,
    deployment_name="gpt-4",
    # 必要であれば
    # temperature=0.9,
    # model_kwargs={
    #     "top_p": 0.9,
    # },
)

ChatVertexAI

Google Cloud への認証は下記2種類の方法があります。(参考

  • gcloud や workload identity により実行環境に認証情報を紐づける方法
  • 認証情報の json ファイルの格納パスを環境変数GOOGLE_APPLICATION_CREDENTIALSに設定する方法


今回は後者の方法で実装を行いました。
認証情報の json ファイルの作成方法はこちらのリンクが参考になります。

import os
from langchain_google_vertexai import (
    ChatVertexAI,
    HarmBlockThreshold,
    HarmCategory,
)

# 環境変数に認証情報が入った json ファイルのパスを設定
os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = "./credential_file_name.json"

chat_model = ChatVertexAI(
    model_name="gemini-1.0-pro",
    streaming=False,
    # Geminiはシステムプロンプトに対応していないため、システムプロンプトを入れる場合はここをTrueにする
    convert_system_message_to_human=True,
    # 適宜要件に合わせて設定してください。今回はブロックが起こりにくい設定(BLOCK_ONLY_HIGH)にしています
    safety_settings={
        HarmCategory.HARM_CATEGORY_HARASSMENT: HarmBlockThreshold.BLOCK_ONLY_HIGH,
        HarmCategory.HARM_CATEGORY_HATE_SPEECH: HarmBlockThreshold.BLOCK_ONLY_HIGH,
        HarmCategory.HARM_CATEGORY_SEXUALLY_EXPLICIT: HarmBlockThreshold.BLOCK_ONLY_HIGH,
        HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT: HarmBlockThreshold.BLOCK_ONLY_HIGH,
    },
    # 必要であれば
    # temperature=0.9,
    # top_k=0.9,
    # top_p=32,
)

BedrockChat

Amazon Bedrock へのアクセス権限を持つ IAM ロールが付与された環境で実行するか、
アクセスキー ID とシークレットアクセスキーを環境変数に設定して実行してください。

from boto3.session import Session
from langchain_community.chat_models import BedrockChat

BEDROCK_REGION = "ap-northeast-1"
session = Session()
bedrock_runtime = session.client("bedrock-runtime", region_name=BEDROCK_REGION)

chat_model = BedrockChat(
    streaming=False,
    client=bedrock_runtime,
    model_id="anthropic.claude-v2:1",
    # 必要であれば
    # model_kwargs={"temperature": 0.1, "top_p": 0.9, "top_k": 250},
)

チャットモデルから出力を受け取る

from langchain.schema import (
    AIMessage,
    HumanMessage,
    SystemMessage,
)

messages = [
    SystemMessage(
        content="あなたは江戸時代から続く老舗寿司屋の職人です。質問に対してぶっきらぼうに回答してください。"
    ),
    HumanMessage(content="オススメの寿司ネタは?"),
    AIMessage(content="まぁ、季節によるな。今なら鯖が旨い。"),
    HumanMessage(content="その理由は?"),
]

response = chat_model.invoke(messages)

print(response.content)
# > 鯖はこの時期に脂がのって味が濃くなるんだよ。


やっていることとしては、
使用したい LLM が指定できるクラスAzureChatOpenAI, ChatVertexAI, BedrockChatをそれぞれ import し、それらのクラスのインスタンス化の際に必要な引数や環境変数を設定すれば OK です。

ここまで出来れば、後はモデルごとの実装方法の差異を LangChain がうまく隠蔽してくれるため、

  • API の入力/出力のフォーマット
  • 良くある前処理や後処理
  • ストリーミング時の処理

などを共通化することができ、LangChain の恩恵を受けることができます。


また、パッケージのインストールについての補足事項としては、
LangChain のバージョン 0.1 系へのアップデートに従い、LLM の外部プロバイダーとの統合部分の処理はlangchainパッケージからlangchain_communityパッケージもしくは独立した新パッケージに分離がなされました。

こちらは LangChain 公式の以下の記事でも紹介されています。

blog.langchain.dev

Specifically we made two large architectural changes: separating out langchain-core and separating out partner packages (either into langchain-community or standalone partner packages) from langchain.

(意訳):
具体的には、大きな構造変更を二つ行いました:langchain-core パッケージの分離と、パートナーパッケージの langchain からの分離(langchain-community パッケージに組み込むか、独立したパートナーパッケージとして分離)です。


そのため、上記のコードでは、

  • AzureChatOpenAI: langchain_openaiからインポート
  • ChatVertexAI: langchain_google_vertexaiからインポート
  • BedrockChat: langchain_communityからインポート

としています。

※ 補足:
0.1 系へのバージョンアップでは後方互換性が担保されているので、例えばChatVertexAIであれば以下でも import が可能です。

from langchain.chat_models.vertexai import ChatVertexAI
from langchain_community.chat_models.vertexai import ChatVertexAI

ただし非推奨の warning が出るので、上述のとおり適切なパッケージからの import をおすすめします。


おまけ:
AzureChatOpenAI, ChatVertexAI, BedrockChatともBaseChatModelというクラスのサブクラスになっています。
そしてBaseChatModellangchain_coreパッケージに実装されているため、 ここからも LangChain のコア機能はlangchainlangchain_coreで開発し、外部プロバイダーに依存する機能はlangchain_communityや独自パッケージで開発する、という意図が汲み取れます。



まとめ

LangChain を使った複数 LLM の実装を紹介しました。
レバレジーズでは MLOps 基盤や ML 活用を企画から考え構築までやりたいエンジニアを募集しています! ご興味のある方はぜひ採用サイトをご覧ください!