LiteLLMとLangGraphで構築したAIエージェントをFastAPI・Streamlit・Dockerでデプロイしてみる

LiteLLMとLangGraphで構築したAIエージェントをFastAPI・Streamlit・Dockerでデプロイしてみる

2026.05.20

はじめに

データ事業本部のkobayashiです。

これまで実装してきたLangGraphエージェントを実運用環境で公開する方法を試してみます。本記事ではFastAPI(REST API)、Streamlit(チャットUI)、Dockerでのコンテナ化、そしてLangGraph Platformへの言及をまとめます。

デプロイの選択肢

方法 特徴 適用
FastAPI + Uvicorn 軽量・自由度高 バックエンドAPI、社内ツール
Streamlit UIをコードで書ける プロトタイプ、社内ダッシュボード
LangGraph Platform LangChain純正、永続化・スケジューリング統合 本番運用、エンタープライズ
Cloud Run / ECS Fargate コンテナベースのマネージド実行 一般的なクラウド本番

環境

Python 3.13
litellm 1.83.14
langgraph 1.1.10
langchain 1.0.0
langchain-litellm 0.6.4
fastapi
uvicorn
streamlit

FastAPI で REST API として公開

fastapi_server.py
"""FastAPI で LangGraph エージェントを REST API として公開する。

エンドポイント:
- POST /chat: 1ターンの会話
- thread_id でセッションを継続
"""

from fastapi import FastAPI
from langchain.agents import create_agent
from langchain_core.tools import tool
from langchain_litellm import ChatLiteLLM
from langgraph.checkpoint.memory import InMemorySaver
from pydantic import BaseModel

@tool
def get_weather(city: str) -> str:
    """都市の天気を返します。"""
    return f"{city}: 晴れ、24°C"

llm = ChatLiteLLM(model="openai/gpt-5-mini")
checkpointer = InMemorySaver()
agent = create_agent(model=llm, tools=[get_weather], checkpointer=checkpointer)

app = FastAPI(title="LiteLLM × LangGraph Agent")

class ChatRequest(BaseModel):
    thread_id: str
    message: str

class ChatResponse(BaseModel):
    answer: str

@app.post("/chat", response_model=ChatResponse)
async def chat(req: ChatRequest) -> ChatResponse:
    config = {"configurable": {"thread_id": req.thread_id}}
    result = await agent.ainvoke(
        {"messages": [{"role": "user", "content": req.message}]}, config=config
    )
    return ChatResponse(answer=str(result["messages"][-1].content))

@app.get("/health")
def health() -> dict:
    return {"status": "ok"}

# 起動: uvicorn fastapi_server:app --host 0.0.0.0 --port 8000

thread_idをリクエストに含めることで、複数ユーザーのセッションを分離できます。CheckpointerをPostgresSaverに切り替えれば、複数のFastAPIインスタンスで状態を共有できます。

起動・テスト:

$ uvicorn fastapi_server:app --reload
INFO:     Started server process [...]
INFO:     Application startup complete.
INFO:     Uvicorn running on http://127.0.0.1:8000

# 別ターミナルで
$ curl -s http://localhost:8000/health
{"status":"ok"}

$ curl -s -X POST http://localhost:8000/chat \
       -H "Content-Type: application/json" \
       -d '{"thread_id":"demo-1","message":"東京の天気を教えて"}'
{"answer":"東京の天気は晴れ、気温は24°Cです。何か他に知りたいことはありますか?"}

POSTのレスポンスはエージェントが get_weather ツールを呼んだ結果を整形した1文応答です。同じ thread_id で続けて投げれば、Checkpointerが履歴を保持してくれるので「さっきの天気は?」のような追従質問が可能です。

Streamlit でチャットUI

社内ツールやプロトタイプには、Pythonだけでチャットインターフェースが組めるStreamlitが便利です。

streamlit_app.py
"""Streamlit で LangGraph エージェントのチャットUIを提供する。

起動: streamlit run streamlit_app.py
"""

import streamlit as st
from langchain.agents import create_agent
from langchain_core.tools import tool
from langchain_litellm import ChatLiteLLM
from langgraph.checkpoint.memory import InMemorySaver

@tool
def get_weather(city: str) -> str:
    """都市の天気を返します。"""
    return f"{city}: 晴れ、24°C"

@st.cache_resource
def get_agent():
    llm = ChatLiteLLM(model="openai/gpt-5-mini")
    checkpointer = InMemorySaver()
    return create_agent(model=llm, tools=[get_weather], checkpointer=checkpointer)

agent = get_agent()
st.title("LiteLLM × LangGraph Chat")

if "thread_id" not in st.session_state:
    import uuid

    st.session_state.thread_id = str(uuid.uuid4())

if "messages" not in st.session_state:
    st.session_state.messages = []

# 既存メッセージを表示
for msg in st.session_state.messages:
    with st.chat_message(msg["role"]):
        st.markdown(msg["content"])

# 入力
if user_input := st.chat_input("メッセージを入力..."):
    st.session_state.messages.append({"role": "user", "content": user_input})
    with st.chat_message("user"):
        st.markdown(user_input)

    config = {"configurable": {"thread_id": st.session_state.thread_id}}
    with st.chat_message("assistant"):
        placeholder = st.empty()
        full_response = ""

        # ストリーミングで応答
        for event in agent.stream(
            {"messages": [{"role": "user", "content": user_input}]},
            config=config,
            stream_mode="updates",
        ):
            for _node_name, node_state in event.items():
                if "messages" in node_state:
                    last = node_state["messages"][-1]
                    if hasattr(last, "content") and isinstance(last.content, str):
                        full_response = last.content
                        placeholder.markdown(full_response)

    st.session_state.messages.append({"role": "assistant", "content": full_response})

@st.cache_resourceでエージェントをセッション間で再利用し、st.session_state.thread_id でユーザーごとの履歴を分離します。

起動:

$ streamlit run streamlit_app.py

  You can now view your Streamlit app in your browser.
  Local URL: http://localhost:8501
  Network URL: http://...:8501

ブラウザで http://localhost:8501 を開くと「LiteLLM × LangGraph Chat」というタイトルのチャット画面が表示され、メッセージ入力欄からエージェントと対話できます。@st.cache_resource のおかげでエージェントは1度だけ初期化され、st.session_state.thread_id の uuid でブラウザセッションごとに会話が分離されます。

スクリーンショット 2026-05-09 16.15.28

CIや headless 検証で動作確認だけ行いたい場合は --server.headless true を付けて起動すると、ブラウザを開かない状態でサーバーが立ち上がります。

Docker でコンテナ化

Dockerfile
FROM python:3.13-slim

WORKDIR /app

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

EXPOSE 8000

CMD ["uvicorn", "fastapi_server:app", "--host", "0.0.0.0", "--port", "8000"]

ビルド・実行:

$ docker build -t litellm-agent .
$ docker run -p 8000:8000 \
       -e ANTHROPIC_API_KEY=$ANTHROPIC_API_KEY \
       -e OPENAI_API_KEY=$OPENAI_API_KEY \
       litellm-agent

このコンテナはAWS ECS Fargate / Cloud Run / Cloud Run Jobs などにそのまま乗るので手軽のクラウド環境でLLMサービスを立ち上げることができます。

LangGraph Platform

LangChainチームが提供するマネージドサービス LangGraph Platform は、以下を一括で面倒見してくれます。

  • グラフのデプロイ(コンテナ化不要)
  • Checkpointer・Storeの管理
  • スケジューリング(cron風)
  • アシスタント機能(versioning含む)
  • LangSmithとの統合

langgraph deploy コマンドで langgraph.json の設定からデプロイできます。エンタープライズ要件で運用負荷を抑えたい場合に有力な選択肢です。

構成パターンの推奨

用途 推奨構成
社内プロトタイプ Streamlit + InMemorySaver
内製API FastAPI + SqliteSaver / PostgresSaver + Cloud Run
一般向けプロダクト FastAPI + Postgres + Redis + Fargate / GKE
エンタープライズ LangGraph Platform

LiteLLMでモデルを切り替えられる利点は、デプロイ後のモデル変更が再ビルド不要で行える点にもあります(環境変数や Configマップの差し替えで切替可能)。

まとめ

LangGraph エージェントの主要なデプロイパターンを、FastAPI(軽量バックエンドAPI)/ Streamlit(即席チャットUI)/ Docker(コンテナ化)/ LangGraph Platform(マネージド本番)の4種類で紹介しました。

FastAPI では /chat エンドポイントで thread_id 管理を行い、Streamlit では @st.cache_resource でエージェントを永続化、Docker ではコンテナ化して FastAPI サーバーを CMD 起動、本格運用では LangGraph Platform に乗せて永続化やスケジューリングをマネージドに任せる、というように 段階的にスケール できる構成になっています。本番運用では Checkpointer に必ず プロセス横断で共有可能なバックエンド(Postgres など)を選ぶこと、API キーは シークレットマネージャー 経由で渡すことが重要で、LiteLLM を介していればモデル切替を1行で完結できる利点もそのまま生きてきます。

最後まで読んでいただきありがとうございました。


生成AI活用はクラスメソッドにお任せ

過去に支援してきた生成AIの支援実績100+を元にホワイトペーパーを作成しました。御社が抱えている課題のうち、どれが解決できて、どのようなサービスが受けられるのか?4つのフェーズに分けてまとめています。どうぞお気軽にご覧ください。

生成AI資料イメージ

無料でダウンロードする

この記事をシェアする

関連記事