T-CREATOR

LangChain を Serverless へ配備:AWS Lambda/Fly.io/Railway の実装手順

LangChain を Serverless へ配備:AWS Lambda/Fly.io/Railway の実装手順

LangChain を使った AI アプリケーションを開発したあと、次のステップはデプロイですよね。サーバーレス環境への配備は、スケーラビリティとコスト効率の両面で優れた選択肢となります。

本記事では、LangChain アプリケーションを AWS Lambda、Fly.io、Railway という 3 つの人気プラットフォームへ配備する具体的な手順をご紹介します。それぞれのプラットフォームには異なる特徴があり、用途に応じて最適な選択ができるでしょう。

背景

LangChain とサーバーレスの組み合わせ

LangChain は、大規模言語モデル(LLM)を活用したアプリケーション開発を容易にするフレームワークです。ChatGPT や Claude などの LLM を使った複雑なワークフローを、シンプルなコードで実装できます。

サーバーレスアーキテクチャは、インフラ管理の負担を大幅に削減し、使用した分だけ課金される従量課金モデルを提供します。LangChain アプリケーションは、リクエストごとに処理を行うため、サーバーレス環境との相性が抜群なんです。

以下の図は、LangChain アプリケーションがサーバーレス環境でどのように動作するかを示しています。

mermaidflowchart LR
    client["クライアント"] -->|リクエスト| serverless["サーバーレス<br/>環境"]
    serverless -->|プロンプト送信| langchain["LangChain<br/>処理"]
    langchain -->|API コール| llm["LLM<br/>(OpenAI/Claude)"]
    llm -->|レスポンス| langchain
    langchain -->|結果| serverless
    serverless -->|レスポンス| client

各プラットフォームの特徴比較

3 つのプラットフォームはそれぞれ異なる強みを持っています。

#プラットフォーム特徴料金モデル起動時間
1AWS LambdaAWS エコスystem との統合実行時間+リクエスト数コールドスタート有
2Fly.ioグローバル展開が容易常時稼働型高速起動
3Railwayシンプルなデプロイ体験使用リソース課金中程度

AWS Lambda は既存の AWS サービスと連携したい場合に最適で、Fly.io は低レイテンシが求められるグローバルアプリケーションに向いています。Railway は開発者体験を重視し、素早くプロトタイプを公開したい場合におすすめですね。

課題

サーバーレス環境特有の制約

LangChain をサーバーレス環境に配備する際、いくつかの技術的課題に直面します。

実行時間制限が最も大きな課題でしょう。AWS Lambda では最大 15 分、他のプラットフォームでも一定の制限があります。LangChain の処理、特に複数の LLM 呼び出しを含むチェーンは、時間がかかることがあるんです。

コールドスタート問題も無視できません。サーバーレス関数は、しばらく使われていないと停止し、次回起動時に初期化時間がかかります。LangChain のライブラリは比較的大きいため、この初期化に数秒かかることもあります。

依存関係のサイズ制限も考慮が必要です。AWS Lambda では、デプロイパッケージのサイズに制限があるため、必要最小限の依存関係のみをインストールする工夫が求められますね。

以下の図は、サーバーレス環境で LangChain を実行する際の課題を整理したものです。

mermaidflowchart TD
    deploy["LangChain<br/>デプロイ"] --> challenge1["実行時間制限"]
    deploy --> challenge2["コールドスタート"]
    deploy --> challenge3["パッケージサイズ"]

    challenge1 --> sol1["タイムアウト<br/>エラー対策"]
    challenge2 --> sol2["ウォームアップ<br/>戦略"]
    challenge3 --> sol3["依存関係<br/>最適化"]

    sol1 --> impl["実装での<br/>解決策"]
    sol2 --> impl
    sol3 --> impl

環境変数と秘匿情報の管理

API キーなどの秘匿情報を安全に管理することも重要な課題です。OpenAI や Anthropic の API キーは、コードに直接記述せず、環境変数として管理する必要があります。各プラットフォームで環境変数の設定方法が異なるため、それぞれの手順を理解しておかなければなりません。

解決策

基本的な実装アプローチ

LangChain アプリケーションをサーバーレス環境に配備するには、以下の 3 つの基本戦略を採用します。

軽量化されたパッケージングでは、必要な依存関係のみをインストールし、デプロイサイズを最小限に抑えます。langchain-corelangchain-openai など、特定機能に絞ったパッケージを使用するのが効果的ですね。

適切なタイムアウト設定により、LLM の応答時間を考慮した余裕のある制限時間を設定します。一般的には 30 秒から 60 秒程度が適切でしょう。

環境変数による設定管理で、API キーやモデル名などをコードから分離し、デプロイ環境ごとに柔軟に変更できるようにします。

プラットフォーム選択のガイドライン

用途に応じて最適なプラットフォームを選択することが重要です。

#ユースケース推奨プラットフォーム理由
1AWS サービスと連携AWS LambdaDynamoDB、S3 等との統合が容易
2グローバル展開Fly.io複数リージョンへの自動展開
3素早いプロトタイプRailwayデプロイが最も簡単
4低コスト・低トラフィックAWS Lambda無料枠が充実
5常時稼働が必要Fly.io / Railwayコールドスタートなし

以下の図は、プラットフォーム選択のフローチャートです。

mermaidflowchart TD
    start["プラットフォーム<br/>選択"] --> q1{"AWS サービス<br/>連携が必要?"}
    q1 -->|はい| lambda["AWS Lambda"]
    q1 -->|いいえ| q2{"グローバル<br/>展開?"}
    q2 -->|はい| flyio["Fly.io"]
    q2 -->|いいえ| q3{"開発速度<br/>優先?"}
    q3 -->|はい| railway["Railway"]
    q3 -->|いいえ| q4{"トラフィック<br/>パターン?"}
    q4 -->|不定期| lambda
    q4 -->|常時| flyio_or_railway["Fly.io または<br/>Railway"]

具体例

共通:LangChain アプリケーションの準備

まず、すべてのプラットフォームで使用する基本的な LangChain アプリケーションを作成しましょう。

プロジェクトの初期化

新しいプロジェクトディレクトリを作成し、必要なパッケージをインストールします。

bashmkdir langchain-serverless
cd langchain-serverless
yarn init -y

依存関係のインストール

LangChain と OpenAI のパッケージをインストールします。軽量化のため、必要最小限のパッケージのみを選択しますね。

bashyarn add langchain-core langchain-openai
yarn add -D typescript @types/node

TypeScript の設定

tsconfig.json を作成し、TypeScript の設定を行います。

json{
  "compilerOptions": {
    "target": "ES2020",
    "module": "commonjs",
    "lib": ["ES2020"],
    "outDir": "./dist",
    "rootDir": "./src",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "resolveJsonModule": true
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules"]
}

基本的な LangChain ハンドラーの実装

src​/​handler.ts を作成し、LangChain を使った簡単なチャットボットを実装します。このコードは、ユーザーからの質問に対して OpenAI の GPT モデルで応答を生成するものです。

typescript// 環境変数から OpenAI API キーを読み込み
import { ChatOpenAI } from "langchain-openai";
import { HumanMessage, SystemMessage } from "langchain-core/messages";

// LangChain のチャットモデルを初期化
const initializeChatModel = () => {
  return new ChatOpenAI({
    modelName: process.env.OPENAI_MODEL || "gpt-3.5-turbo",
    temperature: 0.7,
    openAIApiKey: process.env.OPENAI_API_KEY,
  });
};

上記のコードでは、環境変数から API キーとモデル名を取得しています。これにより、デプロイ環境ごとに異なる設定を柔軟に適用できるんです。

メッセージ処理ロジック

次に、実際のメッセージ処理ロジックを実装します。

typescript// ユーザーの質問を処理する関数
export const processQuestion = async (question: string): Promise<string> => {
  try {
    const model = initializeChatModel();

    // システムメッセージとユーザーメッセージを準備
    const messages = [
      new SystemMessage("あなたは親切で知識豊富なアシスタントです。"),
      new HumanMessage(question),
    ];

    // LLM を呼び出して応答を取得
    const response = await model.invoke(messages);

    return response.content.toString();
  } catch (error) {
    console.error("Error processing question:", error);
    throw new Error("質問の処理中にエラーが発生しました");
  }
};

このコードでは、try-catch ブロックでエラーハンドリングを行い、問題が発生した際にも適切なエラーメッセージを返すようにしています。

AWS Lambda への配備

AWS Lambda は、AWS のサーバーレスコンピューティングサービスです。イベント駆動型のアーキテクチャに最適で、他の AWS サービスとシームレスに連携できます。

Lambda ハンドラーの実装

AWS Lambda 用のハンドラーを src​/​lambda.ts として作成します。Lambda は特定の形式のハンドラー関数を要求するため、それに合わせた実装が必要です。

typescript// AWS Lambda のイベントと型定義をインポート
import { APIGatewayProxyEvent, APIGatewayProxyResult } from "aws-lambda";
import { processQuestion } from "./handler";

// Lambda ハンドラー関数
export const handler = async (
  event: APIGatewayProxyEvent
): Promise<APIGatewayProxyResult> => {
  // CORS ヘッダーの設定
  const headers = {
    "Content-Type": "application/json",
    "Access-Control-Allow-Origin": "*",
    "Access-Control-Allow-Headers": "Content-Type",
  };

CORS ヘッダーを設定することで、ブラウザからの API 呼び出しを許可しています。本番環境では、Access-Control-Allow-Origin を特定のドメインに制限することをおすすめしますね。

リクエストボディの解析とレスポンス生成

typescript  try {
    // リクエストボディから質問を取得
    const body = JSON.parse(event.body || "{}");
    const question = body.question;

    // 質問が空の場合はエラーを返す
    if (!question) {
      return {
        statusCode: 400,
        headers,
        body: JSON.stringify({ error: "質問が指定されていません" }),
      };
    }

    // LangChain で質問を処理
    const answer = await processQuestion(question);

バリデーションを追加することで、不正なリクエストを早期に検出し、適切なエラーレスポンスを返せます。

エラーハンドリングとレスポンス

typescript    // 成功レスポンスを返す
    return {
      statusCode: 200,
      headers,
      body: JSON.stringify({ answer }),
    };
  } catch (error) {
    console.error("Lambda handler error:", error);
    return {
      statusCode: 500,
      headers,
      body: JSON.stringify({
        error: "内部サーバーエラーが発生しました",
        message: error instanceof Error ? error.message : "不明なエラー"
      }),
    };
  }
};

Lambda 用の依存関係追加

Lambda デプロイに必要な型定義をインストールします。

bashyarn add -D @types/aws-lambda

ビルドスクリプトの設定

package.json にビルドスクリプトを追加しましょう。

json{
  "scripts": {
    "build": "tsc",
    "build:lambda": "tsc && cd dist && zip -r ../lambda.zip .",
    "clean": "rm -rf dist lambda.zip"
  }
}

build:lambda スクリプトは、TypeScript をコンパイルした後、dist ディレクトリを ZIP ファイルにパッケージ化します。

AWS Lambda 関数の作成

AWS CLI を使用して Lambda 関数を作成します。事前に AWS CLI のインストールと設定が必要ですね。

bash# Lambda 関数を作成
aws lambda create-function \
  --function-name langchain-chatbot \
  --runtime nodejs20.x \
  --handler lambda.handler \
  --role arn:aws:iam::YOUR_ACCOUNT_ID:role/lambda-execution-role \
  --zip-file fileb://lambda.zip \
  --timeout 60 \
  --memory-size 512

--timeout オプションで 60 秒を指定し、LLM の応答時間を考慮した余裕のある制限を設定しています。--memory-size も 512MB に設定し、十分なリソースを確保しましょう。

環境変数の設定

OpenAI API キーを環境変数として設定します。

bashaws lambda update-function-configuration \
  --function-name langchain-chatbot \
  --environment Variables={OPENAI_API_KEY=your-api-key-here,OPENAI_MODEL=gpt-3.5-turbo}

API キーは絶対にコードにハードコーディングせず、環境変数として管理することが重要です。

API Gateway の設定

Lambda 関数を HTTP エンドポイントとして公開するため、API Gateway を設定します。

bash# REST API を作成
aws apigateway create-rest-api \
  --name langchain-api \
  --description "LangChain Chatbot API"

# リソースとメソッドを作成(API ID は上記コマンドの出力から取得)
aws apigateway create-resource \
  --rest-api-id YOUR_API_ID \
  --parent-id ROOT_RESOURCE_ID \
  --path-part chat

Lambda のデプロイと更新

コードを更新した場合、以下のコマンドで再デプロイできます。

bash# ビルドとパッケージング
yarn build:lambda

# Lambda 関数の更新
aws lambda update-function-code \
  --function-name langchain-chatbot \
  --zip-file fileb://lambda.zip

Lambda のエラー対処

AWS Lambda で発生しやすいエラーと対処法をご紹介します。

エラーコード: Task timed out after 3.00 seconds

このエラーは、Lambda のデフォルトタイムアウト(3 秒)を超えた場合に発生します。

bash# タイムアウトを 60 秒に延長
aws lambda update-function-configuration \
  --function-name langchain-chatbot \
  --timeout 60

エラーコード: Cannot find module 'langchain-openai'

依存関係が正しくパッケージングされていない場合のエラーです。

発生条件:

  • node_modules が ZIP に含まれていない
  • Lambda レイヤーの設定ミス

解決方法:

  1. ビルド前に依存関係をインストール:yarn install --production
  2. ZIP に node_modules を含める:cd dist && zip -r ..​/​lambda.zip . ..​/​node_modules
  3. または Lambda レイヤーとして依存関係を分離する

Fly.io への配備

Fly.io は、アプリケーションをグローバルに展開できるプラットフォームです。Docker コンテナをベースとし、世界中のエッジロケーションで実行できるのが特徴ですね。

Fly.io CLI のインストール

まず、Fly.io の CLI ツールをインストールします。

bash# macOS の場合
curl -L https://fly.io/install.sh | sh

# インストール後、ログイン
flyctl auth login

Express サーバーの実装

Fly.io では常時稼働するサーバーとしてデプロイするため、Express を使った HTTP サーバーを実装します。

bash# Express と関連パッケージをインストール
yarn add express
yarn add -D @types/express

サーバーコードの作成

src​/​server.ts を作成し、Express サーバーを実装しましょう。

typescriptimport express, { Request, Response } from "express";
import { processQuestion } from "./handler";

// Express アプリケーションの初期化
const app = express();
const port = process.env.PORT || 3000;

// JSON ボディパーサーを有効化
app.use(express.json());

Express の基本設定を行い、JSON リクエストを処理できるようにしています。

ヘルスチェックエンドポイント

Fly.io はヘルスチェックでアプリケーションの状態を監視します。そのためのエンドポイントを追加しましょう。

typescript// ヘルスチェック用エンドポイント
app.get("/health", (req: Request, res: Response) => {
  res.status(200).json({ status: "healthy" });
});

// ルートエンドポイント
app.get("/", (req: Request, res: Response) => {
  res.json({ message: "LangChain Chatbot API" });
});

チャットエンドポイントの実装

実際の LangChain 処理を行うエンドポイントを作成します。

typescript// チャットエンドポイント
app.post("/chat", async (req: Request, res: Response) => {
  try {
    const { question } = req.body;

    // バリデーション
    if (!question || typeof question !== "string") {
      return res.status(400).json({
        error: "質問が指定されていません"
      });
    }

    // LangChain で処理
    const answer = await processQuestion(question);

    res.json({ answer });
  } catch (error) {
    console.error("Chat endpoint error:", error);
    res.status(500).json({
      error: "質問の処理中にエラーが発生しました",
      message: error instanceof Error ? error.message : "不明なエラー"
    });
  }
});

サーバーの起動

typescript// サーバーを起動
app.listen(port, () => {
  console.log(`Server is running on port ${port}`);
});

package.json の更新

サーバー起動用のスクリプトを追加します。

json{
  "scripts": {
    "build": "tsc",
    "start": "node dist/server.js",
    "dev": "ts-node src/server.ts"
  }
}

Dockerfile の作成

Fly.io では Docker コンテナを使用してデプロイします。プロジェクトルートに Dockerfile を作成しましょう。

dockerfile# Node.js の公式イメージを使用
FROM node:20-slim

# 作業ディレクトリを設定
WORKDIR /app

# package.json と yarn.lock をコピー
COPY package.json yarn.lock ./

ベースイメージには軽量な slim バージョンを使用し、イメージサイズを最小限に抑えています。

依存関係のインストールとビルド

dockerfile# 依存関係をインストール(本番用のみ)
RUN yarn install --production=false

# ソースコードをコピー
COPY . .

# TypeScript をビルド
RUN yarn build

# 開発用の依存関係を削除
RUN yarn install --production

マルチステージではなく、開発依存関係を後から削除する方法でイメージを最適化しています。

コンテナの起動設定

dockerfile# ポートを公開
EXPOSE 3000

# アプリケーションを起動
CMD ["yarn", "start"]

.dockerignore の作成

不要なファイルをイメージに含めないよう、.dockerignore を作成します。

bashnode_modules
dist
.git
.env
*.md
.gitignore

Fly.io アプリケーションの初期化

Fly.io プロジェクトを初期化します。対話形式で設定を行いますね。

bashflyctl launch

このコマンドを実行すると、アプリケーション名やリージョンを選択するプロンプトが表示されます。

fly.toml の設定

fly.toml ファイルが自動生成されますが、以下のように調整することをおすすめします。

tomlapp = "langchain-chatbot"
primary_region = "nrt"

[build]

[http_service]
  internal_port = 3000
  force_https = true
  auto_stop_machines = false
  auto_start_machines = true
  min_machines_running = 1

[[vm]]
  cpu_kind = "shared"
  cpus = 1
  memory_mb = 512

auto_stop_machines = false により、コールドスタートを防ぎ、常に 1 台以上のマシンを稼働させます。

環境変数の設定

Fly.io に環境変数を設定します。

bashflyctl secrets set OPENAI_API_KEY=your-api-key-here
flyctl secrets set OPENAI_MODEL=gpt-3.5-turbo

secrets コマンドを使用することで、環境変数が暗号化されて保存されます。

デプロイの実行

準備ができたら、デプロイを実行しましょう。

bashflyctl deploy

デプロイが完了すると、URL が表示されます。この URL にアクセスして動作を確認できますね。

デプロイの確認とログ確認

bash# アプリケーションの状態を確認
flyctl status

# ログを確認
flyctl logs

Fly.io のエラー対処

エラーコード: Error: connect ECONNREFUSED

アプリケーションが正しいポートでリッスンしていない場合のエラーです。

発生条件:

  • process.env.PORT を使用していない
  • fly.toml の internal_port と実際のポートが一致しない

解決方法:

  1. サーバーコードで process.env.PORT を使用する
  2. fly.toml の internal_port を確認(デフォルトは 3000)
typescriptconst port = process.env.PORT || 3000;
app.listen(port);

エラーコード: Health check failed

ヘルスチェックエンドポイントが応答していない場合のエラーです。

解決方法:

  1. ​/​health エンドポイントを実装
  2. fly.toml にヘルスチェック設定を追加
toml[http_service.checks]
  [http_service.checks.health]
    grace_period = "10s"
    interval = "30s"
    method = "GET"
    path = "/health"
    timeout = "5s"

Railway への配備

Railway は、Git リポジトリと連携した自動デプロイが特徴のプラットフォームです。GitHub リポジトリにプッシュするだけでデプロイが完了するため、開発体験が非常にスムーズなんです。

Railway プロジェクトの準備

まず、Railway のアカウントを作成し、プロジェクトを準備します。Railway は Web UI から簡単に操作できますね。

  1. Railway にアクセスしてサインアップ
  2. GitHub アカウントで認証
  3. 新しいプロジェクトを作成

Express サーバーの実装(Fly.io と共通)

Railway でも Express サーバーを使用します。Fly.io のセクションで作成した src​/​server.ts をそのまま使用できます。

package.json の start スクリプト確認

Railway は yarn start コマンドでアプリケーションを起動するため、package.json を確認しましょう。

json{
  "scripts": {
    "build": "tsc",
    "start": "node dist/server.js",
    "railway:build": "yarn install && yarn build"
  }
}

railway:build スクリプトを追加することで、ビルド手順を明示的に指定できます。

Railway 設定ファイルの作成

railway.json を作成し、ビルドとデプロイの設定を記述します。

json{
  "$schema": "https://railway.app/railway.schema.json",
  "build": {
    "builder": "NIXPACKS",
    "buildCommand": "yarn railway:build"
  },
  "deploy": {
    "startCommand": "yarn start",
    "restartPolicyType": "ON_FAILURE",
    "restartPolicyMaxRetries": 10
  }
}

この設定により、ビルドとデプロイのプロセスが自動化されます。

.gitignore の確認

Git リポジトリにコミットする前に、.gitignore を確認しましょう。

bashnode_modules
dist
.env
*.log
.DS_Store

環境変数ファイルや node_modules を除外することで、リポジトリサイズを小さく保てます。

Git リポジトリの初期化とプッシュ

コードを Git リポジトリにプッシュします。

bash# Git の初期化
git init
git add .
git commit -m "Initial commit: LangChain serverless app"

# GitHub にリポジトリを作成し、リモートを追加
git remote add origin https://github.com/YOUR_USERNAME/langchain-serverless.git
git branch -M main
git push -u origin main

Railway プロジェクトの作成

Railway の Web UI から、GitHub リポジトリをデプロイします。

手順:

  1. Railway ダッシュボードで「New Project」をクリック
  2. 「Deploy from GitHub repo」を選択
  3. デプロイしたいリポジトリを選択
  4. Railway が自動的にビルドとデプロイを開始

Railway は package.json を検出し、自動的に Node.js 環境を構築してくれるんです。

環境変数の設定

Railway の Web UI から環境変数を設定します。

手順:

  1. プロジェクトの「Variables」タブを開く
  2. 「New Variable」をクリック
  3. 以下の環境変数を追加
#変数名
1OPENAI_API_KEYyour-api-key-here
2OPENAI_MODELgpt-3.5-turbo
3PORT3000

環境変数を追加すると、Railway が自動的にアプリケーションを再デプロイします。

カスタムドメインの設定(オプション)

Railway は自動的に URL を生成しますが、カスタムドメインも設定できます。

手順:

  1. 「Settings」タブを開く
  2. 「Domains」セクションで「Add Domain」をクリック
  3. ドメイン名を入力(例:chatbot.yourdomain.com
  4. DNS レコードを設定(Railway が指示を表示)

デプロイログの確認

Railway の「Deployments」タブから、リアルタイムでビルドログを確認できます。

bash# ログの例
Building...
Installing dependencies...
Running build command: yarn railway:build
Build completed successfully
Starting application: yarn start
Server is running on port 3000

自動デプロイの設定

Railway では、GitHub の main ブランチにプッシュすると自動的にデプロイされます。この機能は設定不要で、デフォルトで有効になっているんです。

コードを更新して GitHub にプッシュするだけで、新しいバージョンがデプロイされます。

bash# コードを更新
git add .
git commit -m "Update chatbot logic"
git push origin main

# Railway が自動的に新しいデプロイを開始

Railway のエラー対処

エラーコード: Error: Cannot find module '.​/​dist​/​server.js'

TypeScript のビルドが失敗している、またはビルド成果物が正しくデプロイされていない場合のエラーです。

発生条件:

  • ビルドコマンドが実行されていない
  • tsconfig.json の outDir 設定が間違っている

解決方法:

  1. railway.json に正しいビルドコマンドを指定
  2. package.json の build スクリプトを確認
  3. Railway のビルドログでエラーを確認
json{
  "build": {
    "buildCommand": "yarn install && yarn build"
  }
}

エラーコード: Application failed to respond

アプリケーションが起動していない、または正しいポートでリッスンしていない場合のエラーです。

解決方法:

  1. process.env.PORT を使用しているか確認
  2. Railway の環境変数に PORT を設定(通常は自動設定)
  3. ログで起動エラーを確認

各プラットフォームの比較と選択基準

3 つのプラットフォームへの実装を見てきましたが、それぞれの実装方法と特性をまとめてみましょう。

#項目AWS LambdaFly.ioRailway
1デプロイ方法ZIP アップロードDocker コンテナGit プッシュ
2実行モデルイベント駆動常時稼働常時稼働
3コールドスタートあり(数秒)ほぼなしほぼなし
4スケーリング自動・無制限手動設定自動
5セットアップ難易度
6AWS 連携優れている不可不可
7料金モデル従量課金月額+従量月額+従量

以下は、各プラットフォームのデプロイフローを比較した図です。

mermaidflowchart TD
    subgraph Lambda["AWS Lambda フロー"]
        L1["コードを<br/>ビルド"] --> L2["ZIP に<br/>パッケージング"]
        L2 --> L3["AWS CLI で<br/>アップロード"]
        L3 --> L4["API Gateway<br/>設定"]
    end

    subgraph Flyio["Fly.io フロー"]
        F1["Dockerfile<br/>作成"] --> F2["flyctl<br/>コマンド実行"]
        F2 --> F3["自動的に<br/>デプロイ"]
    end

    subgraph Rail["Railway フロー"]
        R1["Git に<br/>プッシュ"] --> R2["自動的に<br/>ビルド"]
        R2 --> R3["自動的に<br/>デプロイ"]
    end

パフォーマンス最適化のポイント

どのプラットフォームでも、以下の最適化手法が有効です。

依存関係の最小化

LangChain は多くのサブパッケージを持っています。必要な機能だけをインストールすることで、デプロイサイズとコールドスタート時間を削減できますね。

bash# 全部入りではなく、必要なパッケージのみ
yarn add langchain-core langchain-openai

# 不要なパッケージは追加しない
# yarn add langchain  ← これは避ける

ストリーミングレスポンスの実装

長い応答を待つ代わりに、ストリーミングで段階的にレスポンスを返すことができます。

typescriptimport { ChatOpenAI } from "langchain-openai";

export const streamResponse = async (
  question: string,
  onToken: (token: string) => void
) => {
  const model = new ChatOpenAI({
    streaming: true,
    callbacks: [
      {
        handleLLMNewToken(token: string) {
          onToken(token);
        },
      },
    ],
  });

  await model.invoke([new HumanMessage(question)]);
};

このストリーミング機能により、ユーザーは応答が生成されている様子をリアルタイムで確認でき、体感速度が向上します。

キャッシング戦略

頻繁に使用されるプロンプトや応答をキャッシュすることで、LLM への API 呼び出しを削減できます。

typescript// シンプルなインメモリキャッシュ
const cache = new Map<string, string>();

export const processQuestionWithCache = async (
  question: string
): Promise<string> => {
  // キャッシュをチェック
  if (cache.has(question)) {
    console.log("Cache hit");
    return cache.get(question)!;
  }

  // LLM を呼び出し
  const answer = await processQuestion(question);

  // キャッシュに保存(最大 100 件)
  if (cache.size >= 100) {
    const firstKey = cache.keys().next().value;
    cache.delete(firstKey);
  }
  cache.set(question, answer);

  return answer;
};

まとめ

LangChain アプリケーションをサーバーレス環境に配備する方法について、AWS Lambda、Fly.io、Railway の 3 つのプラットフォームで具体的な実装手順をご紹介しました。

AWS Lambda は、AWS エコシステムとの統合が必要な場合や、トラフィックが不定期なアプリケーションに最適です。完全な従量課金モデルにより、使用していない時間はコストがかかりません。ただし、コールドスタートやデプロイの複雑さは考慮が必要ですね。

Fly.io は、グローバルに展開したいアプリケーションや、低レイテンシが求められる場合に優れた選択肢となります。Docker ベースのデプロイは柔軟性が高く、複数のリージョンへの展開も容易です。常時稼働モデルのため、コールドスタートの心配がありません。

Railway は、素早くプロトタイプを公開したい場合や、開発体験を重視する場合に最適でしょう。Git プッシュだけでデプロイが完了する仕組みは、開発フローを大幅に効率化します。初心者にも扱いやすく、学習コストが低いのが魅力ですね。

どのプラットフォームを選択するかは、プロジェクトの要件、チームのスキルセット、予算などによって変わってきます。本記事で紹介した実装パターンを参考に、最適なプラットフォームを選択してください。

LangChain の軽量化、適切なタイムアウト設定、環境変数の管理など、共通する最適化手法も忘れずに適用しましょう。これらの工夫により、安定した高性能な AI アプリケーションを提供できるはずです。

関連リンク

各プラットフォームの公式ドキュメントや参考資料です。

;