3行で経緯
- 久しぶりにPythonを触ることになったら、
- いつの間にかパッケージ管理に便利そうなもの(Poetry)が登場していたので
- 今時らしい題材(FastAPI + LangServe)で開発環境を構築してみる
前提
sysctl -n machdep.cpu.brand_string
# => Apple M1 Pro
python3 --version
# => Python 3.12.4
この記事で扱う技術セットの概要
Poetryとは
Pythonのパッケージマネージャー。より簡単に依存関係の管理や追跡、パッケージのビルド・配布を行えるのが強みで、Pythonの仮想環境のセットアップまで容易にしてくれる。pyproject.tomlを使用して依存パッケージやプロジェクト設定を一元管理する。
筆者は普段Node.js界隈中心に活動しているので、Node.js界隈にすぐ伝わる言い方をするなら、pyproject.tomlはpackage.jsonに相当。ちなみにpackage-lock.jsonに相当するものもあって、poetry.lockというファイルがそれに該当する。
LangServeとは
LangChainをREST APIとして簡単にデプロイするためのツール。LangChain公式が開発しており、LangChainテンプレートもこのLangServeで公開されている。FastAPIと統合されており、少ないコードでSwaggerUI付きの分かりやすいREST APIをすぐに実装できる。
LangChainとは
LLM(大規模言語モデル)を利用したアプリケーション開発のためのフレームワーク。各社の言語モデルを統合してくれていたり、様々なデータソースからモデルに情報を渡すことができたり、過去の会話を記録するメモリ機能があったりと、LLM開発において何かと手間のかかる部分をフレームワークとして容易かつ効率よく実装できるようになっている。
FastAPIとは
シンプルなコードで迅速にHTTP APIを開発可能なPythonのWebフレームワーク。FastAPIの公式ドキュメントは自身のことを次のように説明している。
FastAPI は、Pythonの標準である型ヒントに基づいてPython 以降でAPI を構築するための、モダンで、高速(高パフォーマンス)な、Web フレームワークです。
主な特徴:
- 高速: NodeJS や Go 並みのとても高いパフォーマンス (Starlette と Pydantic のおかげです)。 最も高速な Python フレームワークの一つです.
- 高速なコーディング: 開発速度を約 200%~300%向上させます。 *
- 少ないバグ: 開発者起因のヒューマンエラーを約 40%削減します。 *
- 直感的: 素晴らしいエディタのサポートや オートコンプリート。 デバッグ時間を削減します。
- 簡単: 簡単に利用、習得できるようにデザインされています。ドキュメントを読む時間を削減します。
- 短い: コードの重複を最小限にしています。各パラメータからの複数の機能。少ないバグ。
- 堅牢性: 自動対話ドキュメントを使用して、本番環境で使用できるコードを取得します。
- Standards-based: API のオープンスタンダードに基づいており、完全に互換性があります
Amazon Bedrockとは
AWSで生成AIアプリケーションを開発するならこれ。各社の生成AIモデルを提供してくれている。AWSなので権限制御はIAMで可能。プロダクトのその他のリソースと合わせて権限管理するならIAM制御可能なのは便利。
Poetryのインストールと設定
筆者はMacを使用しているので、次のようにインストールしました。
curl -sSL https://install.python-poetry.org | python3 -
パスを通すべく .zshrc
に下記を追加。
export PATH="$HOME/.local/bin:$PATH"
ターミナルを開き直すと無事にpoetryのバージョンを確認できました。
poetry --version
# => Poetry (version 1.8.3)
タブ補完を有効にして、
mkdir ~/.zfunc
poetry completions zsh > ~/.zfunc/_poetry
あとはパッケージ依存関係の管理をプロジェクト内に閉ざすべく、Pythonの仮想環境 .venv
をプロジェクトディレクトリごとに作成するよう下記を設定すれば完了!
poetry config virtualenvs.in-project true
Poetry + FastAPIで開発できるようにする
まずはPoetryで新しいプロジェクトを作成。
poetry new poetry-fastapi-langserve-sample
# $ tree poetry-fastapi-langserve-sample/
# poetry-fastapi-langserve-sample/
# ├── README.md
# ├── poetry_fastapi_langserve_sample
# │ └── __init__.py
# ├── pyproject.toml
# └── tests
# └── __init__.py
Pythonの仮想環境に入って、
cd poetry-fastapi-langserve-sample
poetry shell
# ※ちなみに仮想環境から出る時は `exit` コマンドを実行すればOK
必要なパッケージ2つを追加。
poetry add fastapi uvicorn
最小限のエントリーポイントを書いて、
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
return {"Hello": "World"}
FastAPIを起動。
uvicorn main:app --reload
リクエストを投げるとちゃんと応答が返ってくる。
curl http://localhost:8000
# => {"Hello":"World"}
これでFastAPIが動作していることが確認できた。
FastAPIにLangServe + Amazon Bedrockを組み込んでみる
まずはLangServeを導入。
poetry add 'langserve[server]'
LangServeはadd_routesにRunnableを継承したクラスを渡すと自動でルートを定義できる。今回はAmazon Bedrock経由で生成AIモデルを使いたいので、langchain-awsパッケージを導入する。
poetry add langchain-aws
このlangchain-awsパッケージにはBedrockをLangChainに統合可能な「ChatBedrock」が含まれている。このChatBedrock自体が前述のRunnableを継承したクラスなので、これさえあればすぐにBedrockのAPIルートを作成できる。モデルは今回、Claude 3.5 Sonnetを指定。
from fastapi import FastAPI
from langchain_aws.chat_models.bedrock import ChatBedrock
from langserve import add_routes
app = FastAPI()
add_routes(app, ChatBedrock(
model_id="anthropic.claude-3-5-sonnet-20240620-v1:0",
region_name="us-east-1"),
path="/bedrock")
実装はこれだけ! あとは動かすのみ。
ChatBedrockコンポーネントはAWS SDK for Python (Boto3) を介してBedrockにリクエストを投げるので、動かすためにはAWSのクレデンシャルが必要。環境変数でAWSプロファイルを指定するなら、次のようにする(もちろん他のやり方でもOK)
export AWS_PROFILE=自分のプロファイル名
AWSのクレデンシャルを指定できたなら、あとは起動して動作確認するだけ。
uvicorn main:app --reload
FastAPIが http://localhost:8000/docs
にSwaggerUIを表示してくれるので、アクセスしてみよう。
一通りのAPIルートが作成されている! 試しに動かしてみると、ちゃんとBedrock経由で生成AIモデルのAPIを動かせた。
これで、PoetryでのFastAPI + LangServe + Bedrockの環境構築ができた。
単にBedrock経由で生成AIのモデルを利用可能なREST APIを用意したいだけなら、これだけでも便利だし、何かプロダクトとしてLangChainで作ったカスタムチェーンを実行可能なREST APIにしたいなら、これを起点に開発していけばいいですね。
まとめ
PoetryでFastAPI + LangServe + Bedrockの環境構築とmain.py実装までを一気通貫するなら、こう。
# Poetry自体のインストールと設定までは割愛
poetry new poetry-fastapi-langserve-sample
cd poetry-fastapi-langserve-sample
poetry shell
poetry add fastapi uvicorn 'langserve[server]' langchain-aws
from fastapi import FastAPI
from langchain_aws.chat_models.bedrock import ChatBedrock
from langserve import add_routes
app = FastAPI()
add_routes(app, ChatBedrock(
model_id="anthropic.claude-3-5-sonnet-20240620-v1:0",
region_name="us-east-1"),
path="/bedrock")
# AWSクレデンシャルの指定とFastAPIの起動
export AWS_PROFILE=自分のプロファイル名
uvicorn main:app --reload
これで完了! この手数の少なさはプロダクトの中核を開発するまでの道のりが短くていいですね。
次回はLangChainでカスタムチェーンを実装し、LangServeで実際にREST API化するところまで記事にします。
参考: 最終的なディレクトリ構造やpyproject.tomlの状態など
最終的には、今回のプロジェクトは次のようなディレクトリ構造になっています。
.
├── README.md
├── __pycache__
│ ├── main.cpython-312.pyc
│ └── main.cpython-39.pyc
├── main.py
├── poetry.lock
├── poetry_fastapi_langserve_sample
│ └── __init__.py
├── pyproject.toml
└── tests
└── __init__.py
そしてpyproject.tomlの中身は次のようになっています。
[tool.poetry]
name = "poetry-fastapi-langserve-sample"
version = "0.1.0"
description = ""
authors = ["shigeru.hyodo <41170561+gel1123@users.noreply.github.com>"]
readme = "README.md"
[tool.poetry.dependencies]
python = "^3.12"
fastapi = "^0.115.0"
uvicorn = "^0.31.0"
langchain-aws = "^0.2.1"
langserve = {extras = ["server"], version = "^0.3.0"}
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
おまけ: LangServeのPlayground機能
LangServeにはadd_routesに渡したrunnableのPlaygroundを提供してくれる機能がある。
実際にFastAPIを起動してPlaygroundにアクセスしてみると、こんな感じ。ちょっとした動作確認をしたいときに便利そう。
本番環境で使う時など、PlaygroundをOFFにしたい場合は、次のようにdisabled_endpointsオプションを指定してやればOK。
add_routes(app, ChatBedrock(
model_id="anthropic.claude-3-5-sonnet-20240620-v1:0",
region_name="us-east-1"),
+ disabled_endpoints=["playground"],
path="/bedrock")
LangChainでカスタムチェーンを作った時の動作確認としても、あると便利そうですね!