LangChainをLocalのDockerで動かしてみる

こんにちは、エンジニアリングマネージャーの渡辺(@mochi_neko_7)です。

最近常に話題になっているChatGPTを始めとするLLM(Large Language Model)ですが、APIを利用して単にChat(正確にはChat Completion)をする以外に少し凝ったことをしたいというケースも多いでしょう。

そのような場合に便利なLangChainというPythonライブラリがあります。

github.com

概要はこちらの記事などでも紹介されています。

note.com

今回はタイトルにもあるように、このLangChainをLocalのDocker環境で動くようにしてみたいと思います。

モチベーション

Dockerを使うメリットは改めてここで語るまでもないと思いますが、個人的にはPythonのパッケージ毎のPythonバージョンの互換性で何度か大変な思いをしたこともあり、Pythonを使うときは可能ならDockerを使いたいと思っていました。

普段からPythonを触っているというわけでもないので、正直あまり詳しいわけではないです。

今回初めて触ったPoetryというパッケージマネージャーにはPython環境の仮想化の機能もあるみたいなので、考えすぎかもしれません。

最終的にどこかのクラウド環境にホスティングすることを考えるとDockerで環境構築しておいた方が移植しやすいので無駄ではないでしょう。

環境

  • macOS 13.3.1, ARM64(M2)
  • LangChain 0.0.135
  • Docker Desktop 4.13.0
  • Python 3.9
  • Poetry 1.4.2

前提

前提、というか自分の知識レベルは下記になります。

  • Pythonは触れる
  • OpenAIのChatGPTのAPIは触れる
  • Dockerでのローカル環境構築は分かる
  • Poetry、LangChainは触ったことない

全て詳細に説明するのは流石に大変なので、Docker、Poetry、LangChainの最低限のセットアップをメインに解説していきます。

Docker環境のセットアップ

セットアップの手順を順番に説明していきます。

ソースはこちらに置いています。

github.com

もしこれをそのまま触る場合は、ご自身のOpenAIのAPI Keyを発行して、.envの環境変数ファイルに書いて配置する必要があることに注意してください。

フォルダ構成

ここではフォルダ構成を次のようにします。

.
├── compose.yaml
└── langchain
    ├── Dockerfile
    ├── .env
    ├── (poetry.lock)
    ├── (pyproject.toml)
    └── src
        └── main.py

poetry.lockpyproject.tomlのファイルは後でPoetryのプロジェクトを作成して生成するため、初めから置いておく必要はありません。

compose.yaml

先日の弊社テックブログの記事に倣って、compose.yamlを作成します。

services:
  langchain:
    build:
      context: ./langchain
      dockerfile: Dockerfile
    tty: true
    ports:
      - 8000:8000
    volumes:
      - ./langchain:/app
    env_file:
      - ./langchain/.env

今回はLnagChainだけのシンプルな構成なので特に迷うところはありませんが、ポイントはenv_fileで環境変数を指定しているところでしょうか。

OpenAIのAPIを利用するために必要なOPENAI_API_KEYはこの環境変数ファイル.envに置いておき、このファイルは.gitignoreに登録しておき、GitHubに上げても他の人に自分のAPI Keyを利用されないようにしておきます。

OPENAI_API_KEY=sk-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Dockerfile

FROM --platform=arm64 python:3.9

RUN apt-get -y update

WORKDIR /app

RUN pip install poetry

## COPY pyproject.toml poetry.lock ./

## RUN poetry install --no-root

COPY . .

今回はCLIで触るだけなのでPythonの公式ImageにPoetryを追加するだけの最低限のセットアップのみで、##でコメントアウトしてあるところはPoetryプロジェクト作成後に使用するものです。

先頭の--platform=arm64は自分がmacOSのARM64版を使用しているための事故防止です。

Pythonのバージョンは深く考えていませんがとりあえず3.9では問題なく動いています。

上記のセットアップをした後、通常通りDockerでbuild&upし、exceコマンドでbashを立ち上げます。

$ docker compose up -d --build 
$ docker compose exec langchain bash

Poetryプロジェクトのセットアップ

今回はPoetryを使用してLangChainを触る環境を作成します。

Poetryプロジェクトの作成

PoetryのインストールはDockefileに記述しているため操作は不要ですが、ちゃんとインストールされてPathが通っていることを確認します。

$ poetry --version

Poetryのプロジェクトの作成方法はこちらなどをご覧ください。

qiita.com

自分は最低限のファイルだけinitコマンドで作成しました。

$ poetry init

完了するとpyproject.tomlというTOML形式のプロジェクトファイルが作成されます。

[tool.poetry]
name = "langchain-docker"
version = "0.1.0"
description = ""
authors = ["Mochineko"]
license = "MIT"
readme = "README.md"
packages = [{include = "langchain_docker"}]

[tool.poetry.dependencies]
python = "^3.9"


[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"

その後、次のコマンドでプロジェクトの初期化を行い、poetry.lockファイルが作成されます。

$ poetry install --no-root

--no-rootのコマンドはpyproject.tomlpackages = [{include = "langchain_docker"}]のオプションで自身のPackageを追加しようとしてエラーが出るのを回避するためですが、自分もPoetryに慣れていないのであまり詳しくありません。

必要なPackageの追加

上記のpyproject.tomlにはまだ何もPackageの依存関係がないため、LangChainを動かすために最低限必要な次の2つのPackageの依存関係を追加します。

  • langchain
  • openai

コマンドはpoetry addを使用します。

$ poetry add langchain
$ poetry add openai

実行後、pyproject.tomlに依存関係が追加されていることを確認してください。

[tool.poetry.dependencies]
python = "^3.9"
langchain = "^0.0.135"
openai = "^0.27.4"

これで最低限のPoetryプロジェクトのセットアップは完了です。

動作確認

Dockerfile##のコメントアウトを外して、再度Dockerのビルドをしてbashを開きます。

Docker内のCLIで、まずPoetryのCLIを立ち上げます。

$ poetry shell

すると仮想環境で先ほどセットアップしたPoetryプロジェクトが使用できるようになるようです。

クイックスタートの記事を参考に、LLMをシンプルに動かす適当なPythonスクリプトを作成します。

from langchain.llms import OpenAI

# LLMの準備
llm = OpenAI(temperature=0.9)

# LLMの呼び出し
print(llm("コンピュータゲームを作る日本語の新会社名をを1つ提案してください"))

このファイル名をmain.pyとして、srcのディレクトリに移動してからこれを実行してみます。

$ python main.py

するとLLMに渡した"コンピュータゲームを作る日本語の新会社名をを1つ提案してください"に対する回答がprint関数によってCLIに表示されると思います。

正しく結果が表示されれば、LangChainが動いていることが確認できたことになります。

ちなみに、LangChainの色々な機能を触っていると追加でPackageが必要になることもあると思いますが、その場合もpoetry addで必要な依存関係を追加していくだけ問題ないです。

まとめ

上記で紹介した手順で、LocalのDocker環境でLangChainを実際に動かすことができました。

それほど凝ったことはしていませんが、いくつか注意すべきポイントを挙げておきます。

  • OpenAIのAPI Keyはcompose.yamlで外から環境変数ファイルとして設定しておき、ハードコーディングしない
  • Poetryのinitコマンドで自身のプロジェクトを読み込むのに失敗していたら--no-rootオプションで解決できるかもしれない
  • PoetryでPythonスクリプトを実行する前に一度poetry shellで仮想環境を立ち上げる

おわりに

ここまでおおよそ2時間くらいでLangChainをLocalのDockerで動かすためのセットアップができました。

その後はドキュメントを読んでずっと気になっていたKnowledge Graph MemoryやIndexなども少し触ってみましたが、自分で実装するにはそれなりに大変そうな機能がサクッと利用できるようになっていてとても便利ですね。

LangChainと似たようなコンセプトでMicrosoftもSemantic Kernelを公開していますし、こういったLLMのミドルウェア的なものは増えていくのではないでしょうか。

今回はLangChainを動かすところまでに留めましたが、今後はFastAPIを使ってLangChainAPI Server化して他のアプリケーションからLangChainの機能を利用することなども試してみたいなと思っています。