RAGAS × FastAPI × Next.js × Docker で学ぶ「動かして理解する」Web アプリ開発入門

AIエンジニア

はじめに

この記事では、RAG(検索拡張生成) の評価ツール「RAGAS」を、FastAPI(バックエンド)と Next.js(フロントエンド)で使い、Docker で動かすまでの一連の流れを、初学者向けにコードの意味から丁寧に解説します。

「RAGAS って何?」「FastAPI や Next.js を触ったことがない」「Docker は聞いたことはあるが使ったことがない」という方でも、この記事を読みながら実際に手を動かせば、以下のことを身につけられます。

技術学べること
FastAPIREST API を設計・実装する流れ
Next.jsフロントエンドから API を呼び出し、結果を表示する流れ
Dockerバックエンドをコンテナ化し、同じ環境を再現する方法
RAGASRAG パイプラインの評価の基本

各章で「なぜそう書くか」を意識しながら、主要なコードを丁寧に説明していきます。


第 1 章:全体像と「何が起きているか」

1.1 このプロジェクトでやること

このプロジェクトでは、次のような「評価用 Web アプリ」を作成します。

① ユーザーがブラウザで入力
   └─ 質問 / RAGが取得したコンテキスト / RAGが生成した回答 / 正解(reference)

② フロントエンド(Next.js)→ バックエンド(FastAPI)へ送信

③ バックエンドが RAGAS で評価
   └─ Faithfulness / Context Recall / Factual Correctness などを計算

④ 評価スコアがフロントエンドへ返り、画面に表示

つまり、「RAG の入出力サンプル」を送ると「RAGAS の評価スコア」が返ってくる API と、その API を呼ぶ UI を用意します。

1.2 ディレクトリ構成

ragas_fast_api/
├── backend/                  # FastAPI(Python)
│   ├── app/
│   │   ├── api/              # ルート(URL と処理の対応)
│   │   ├── services/         # RAGAS 評価ロジック
│   │   ├── config.py         # 設定
│   │   ├── main.py           # アプリの入口
│   │   └── schemas.py        # リクエスト・レスポンスの型
│   ├── Dockerfile            # バックエンド用コンテナの設計図
│   ├── requirements.txt      # Python の依存パッケージ
│   └── .env.example          # 環境変数の例
├── frontend/                 # Next.js(TypeScript)
│   └── src/
│       ├── app/              # ページとレイアウト
│       └── lib/              # API 呼び出しなど共通ロジック
├── docker-compose.yml        # コンテナの起動設定
└── README.md
ディレクトリ役割
backend/サーバー側。「評価 API」の実装
frontend/ブラウザで動く画面。backend の API を呼ぶ
docker-compose.ymlポートや環境変数などの起動設定をまとめたファイル

次の章から、この中の主要なファイルを 1 つずつ開きながら説明していきます。


第 2 章:FastAPI の「入口」—— main.py

2.1 FastAPI とは

FastAPI は、Python で Web API(REST API) を書くためのフレームワークです。

  • パス(URL)と HTTP メソッド(GET / POST など)で「どの関数を実行するか」を決められる
  • リクエストの body やレスポンスを で定義すると、自動でバリデーションやドキュメント生成をしてくれる
  • 非同期(async)にも対応しており、I/O の多い API に適している

2.2 main.py の全体

# backend/app/main.py
import logging
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from app.api.routes import router
from app.config import get_settings

logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s [%(levelname)s] %(name)s: %(message)s",
)
logger = logging.getLogger(__name__)

app = FastAPI(
    title="RAGAS Evaluation API",
    description="RAG パイプラインを RAGAS で評価するための API。",
    version="1.0.0",
)

settings = get_settings()
app.add_middleware(
    CORSMiddleware,
    allow_origins=settings.cors_origins,
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

app.include_router(router)

@app.get("/")
def root() -> dict:
    return {
        "service": "RAGAS Evaluation API",
        "docs": "/docs",
        "health": "/api/health",
        "evaluate": "POST /api/evaluate",
    }

2.3 各部分の解説

ロギング設定

logging モジュールで、アプリの動作ログを標準出力に出します。本番環境ではファイルや JSON 形式に変えることもできます。

app = FastAPI(...)

FastAPI() で「API 」を 1 つ作成します。title / description / version は Swagger UI(/docs)に表示され、API の説明になります。

CORS ミドルウェア

ブラウザでは「別オリジン(別ドメイン・別ポート)へのリクエスト」が制限されています。フロントエンド(例:http://localhost:3000)からバックエンド(例:http://localhost:8001)へリクエストするには、バックエンド側で CORS(Cross-Origin Resource Sharing) を許可する必要があります。

CORSMiddleware で「どのオリジンを許可するか」「どの HTTP メソッド・ヘッダーを許可するか」を指定します。allow_origins=settings.cors_origins で、設定ファイル(または環境変数)で指定したオリジンのみ許可します。

app.include_router(router)

実際のエンドポイント(/api/healthPOST /api/evaluate)は別ファイル(app.api.routes)で定義されているため、その「ルーター」をアプリに取り込みます。これにより、各エンドポイントにアクセスできるようになります。

@app.get("/")root()

@app.get("/") は「パスが / で HTTP メソッドが GET のときにこの関数を実行する」という意味です。ブラウザで http://localhost:8001/ を開くと、戻り値の辞書が JSON として返ります。API の説明や他エンドポイントへの誘導に使えます。


第 3 章:設定の読み込み —— config.py

3.1 なぜ設定を別ファイルにするか

API キーや接続先などは、環境ごと(開発・本番)や開発者によって変えたいことが多いです。これらをコードに直接書くと、変更のたびに編集が必要になり、秘密情報がリポジトリに含まれるリスクもあります。そこで、環境変数.env ファイル から読み込み、1 か所(config.py)でまとめて管理します。

3.2 config.py の内容

# backend/app/config.py
from pydantic_settings import BaseSettings
from functools import lru_cache

class Settings(BaseSettings):
    app_name: str = "RAGAS Evaluation API"
    debug: bool = False
    openai_api_key: str = ""
    openai_model: str = "gpt-4o"
    cors_origins: list[str] = ["http://localhost:3000"]

    model_config = {"env_file": ".env", "extra": "ignore"}

@lru_cache
def get_settings() -> Settings:
    return Settings()

3.3 解説

Pydantic と BaseSettings

Pydantic は Python で「型付きのデータ」を扱うライブラリです。FastAPI も内部で Pydantic を使ってリクエスト・レスポンスを検証しています。BaseSettings は、環境変数や .env の値を読み込み、指定した型に変換してくれるクラスです。

フィールド用途
openai_api_keyRAGAS が評価時に OpenAI API を呼ぶためのキー
openai_model評価に使う OpenAI モデル名(例:gpt-4o
cors_originsCORS で許可するオリジンのリスト

model_config

  • "env_file": ".env" で、同じディレクトリの .env を読み込みます。Docker では docker-compose.ymlenvironment で渡した値も環境変数として読み込まれます。
  • "extra": "ignore" は、定義していない環境変数を無視するという意味です。

get_settings()@lru_cache

get_settings()Settings() を 1 回だけ生成し、2 回目以降は キャッシュ を返します(@lru_cache の効果)。設定の読み込みやバリデーションは起動時に 1 回で済むため、効率的です。

※「設定は環境変数と .env で渡し、コードでは Settings を通してのみ参照する」と決めておくと、後から本番用の設定に切り替えやすくなります。


第 4 章:API の「型」—— schemas.py

4.1 スキーマとは

スキーマ は、「リクエストやレスポンスの形(型)」を表す定義です。フロントエンドとバックエンドの間で事前にデータの形を決めておくことで、実装のずれを防げます。FastAPI では Pydantic の BaseModel でスキーマを定義すると、JSON との変換やバリデーションが自動で行われます。

4.2 評価用の 1 件分 —— EvaluationSample

# backend/app/schemas.py(抜粋)
from pydantic import BaseModel, Field

class EvaluationSample(BaseModel):
    user_input: str = Field(..., description="ユーザーの質問(クエリ)")
    retrieved_contexts: list[str] = Field(
        default_factory=list,
        description="RAG で取得したコンテキストのリスト",
    )
    response: str = Field(..., description="RAG システムが生成した回答")
    reference: str = Field(..., description="正解(グラウンドトゥルース)")
フィールド内容
user_inputユーザーが投げた質問(RAG の「クエリ」)
retrieved_contextsRAG が検索して得たドキュメントの断片のリスト
responseRAG が生成した回答そのもの
reference正解(グラウンドトゥルース)文字列

Field(..., ...)... は「この項目は必須」、default_factory=list は「省略時は空リストを使う」という意味です。

4.3 評価リクエスト全体 —— EvaluateRequest

class EvaluateRequest(BaseModel):
    samples: list[EvaluationSample] = Field(
        ...,
        min_length=1,
        description="評価するサンプルのリスト",
    )

min_length=1 で「最低 1 件は必要」としています。0 件では評価を実行できないためです。

4.4 評価結果の 1 項目 —— MetricScore

class MetricScore(BaseModel):
    name: str = Field(..., description="メトリクス名(例:faithfulness)")
    score: float = Field(..., description="スコア(0〜1)")
    description: str | None = Field(default=None, description="メトリクスの説明")

4.5 評価 API のレスポンス —— EvaluateResponse

class EvaluateResponse(BaseModel):
    success: bool = Field(..., description="評価が正常に完了したか")
    metrics: list[MetricScore] = Field(default_factory=list, description="各メトリクスのスコア一覧")
    error_message: str | None = Field(default=None, description="失敗時のエラーメッセージ")
フィールド成功時失敗時
successTrueFalse
metricsスコアのリスト空リスト
error_messageNoneエラー内容

送るデータ(Request)と返すデータ(Response)を型で明文化しておくことが、FastAPI で API を書くときの基本です。


第 5 章:エンドポイントの定義 —— api/routes.py

5.1 ルーターとは

FastAPI では、URL パスと HTTP メソッドごとに「どの関数を実行するか」を ルーター でまとめて登録します。main.pyapp.include_router(router) しているため、router に定義したパスがアプリに追加されます。

5.2 routes.py の構成

# backend/app/api/routes.py(抜粋)
from fastapi import APIRouter, Depends, HTTPException
from app.config import Settings, get_settings
from app.schemas import EvaluateRequest, EvaluateResponse, HealthResponse
from app.services.ragas_service import run_evaluation

router = APIRouter(prefix="/api", tags=["evaluation"])

APIRouter(prefix="/api", ...) で「このルーターのパスはすべて /api で始まる」と指定します。つまり、このファイルで @router.get("/health") と書くと、実際のパスは /api/health になります。

5.3 ヘルスチェック —— GET /api/health

@router.get("/health", response_model=HealthResponse)
def health_check() -> HealthResponse:
    return HealthResponse(status="ok", service="ragas-evaluation-api")

ヘルスチェック は「サーバーが起動しているか」を確認するためのエンドポイントです。Docker のヘルスチェックやロードバランサーの死活監視で活用します。この URL に GET でアクセスできれば「API は起動している」と判断できます。

5.4 評価実行 —— POST /api/evaluate

@router.post("/evaluate", response_model=EvaluateResponse)
def evaluate_rag(
    request: EvaluateRequest,
    settings: Settings = Depends(get_settings)
) -> EvaluateResponse:
    if not settings.openai_api_key:
        raise HTTPException(
            status_code=503,
            detail="OPENAI_API_KEY が設定されていません。",
        )
    try:
        metrics = run_evaluation(
            samples=request.samples,
            openai_api_key=settings.openai_api_key,
            model=settings.openai_model,
        )
        return EvaluateResponse(success=True, metrics=metrics)
    except ValueError as e:
        logger.warning("Validation error in evaluate: %s", e)
        raise HTTPException(status_code=400, detail=str(e))
    except Exception as e:
        logger.exception("Evaluation failed: %s", e)
        return EvaluateResponse(
            success=False,
            metrics=[],
            error_message=str(e),
        )

引数の役割

  • request: EvaluateRequest … リクエストボディが Pydantic によって自動でパース・検証され、EvaluateRequest のインスタンスとして渡されます
  • settings: Settings = Depends(get_settings)依存性注入(DI) です。FastAPI が get_settings() を呼び、その戻り値(設定)を settings に渡します。テスト時に設定を差し替えやすくなります

処理の流れ

1. OPENAI_API_KEY が未設定 → 503 を返して終了
2. run_evaluation(...) で RAGAS による評価を実行
3. 成功 → EvaluateResponse(success=True, metrics=metrics) を返す
4. ValueError(入力の不備)→ 400 エラー
5. その他の例外 → success=False と error_message を返す

「エンドポイントは薄く保ち、実際の処理は services/ に任せる」とすると、どこで何をしているかが明確になります。


第 6 章:RAGAS 評価の核 —— services/ragas_service.py

6.1 RAGAS とは

RAGAS は、RAG パイプラインや LLM の出力を 定量的に評価 するためのライブラリです。

メトリクス概要
Faithfulness回答がコンテキストに忠実かどうか
Context Recall正解に必要な情報がコンテキストに含まれていたか
Factual Correctness回答と正解の事実一致度

6.2 データセットの構築 —— _build_ragas_dataset

def _build_ragas_dataset(samples: list[EvaluationSample]) -> EvaluationDataset:
    raw_list: list[dict[str, Any]] = [
        {
            "user_input": s.user_input,
            "retrieved_contexts": s.retrieved_contexts,
            "response": s.response,
            "reference": s.reference,
        }
        for s in samples
    ]
    if hasattr(EvaluationDataset, "from_list"):
        return EvaluationDataset.from_list(raw_list)

    # from_list が存在しない旧バージョン向けのフォールバック
    from ragas import SingleTurnSample
    ragas_samples = [
        SingleTurnSample(
            user_input=s.user_input,
            retrieved_contexts=s.retrieved_contexts,
            response=s.response,
            reference=s.reference,
        )
        for s in samples
    ]
    return EvaluationDataset(samples=ragas_samples)

私たちの EvaluationSample を RAGAS が期待する形式に変換します。まず辞書のリスト(raw_list)に変換し、EvaluationDataset.from_list() で RAGAS 用データセットを作ります。from_list が存在しない古いバージョンでは、SingleTurnSample を 1 件ずつ作るフォールバックを使います。

6.3 評価の実行 —— run_evaluation

def run_evaluation(samples, *, openai_api_key, model="gpt-4o") -> list[MetricScore]:
    if not openai_api_key:
        raise ValueError("OPENAI_API_KEY が設定されていません")

    # Step 1: RAGAS 用データセットを構築
    eval_dataset = _build_ragas_dataset(samples)

    # Step 2: LLM を準備(RAGAS は内部で LLM を使う)
    llm = ChatOpenAI(model=model, api_key=openai_api_key)
    evaluator_llm = LangchainLLMWrapper(llm)

    # Step 3: メトリクスを指定して評価を実行
    metrics = [Faithfulness(), LLMContextRecall(), FactualCorrectness()]
    result = evaluate(
        dataset=eval_dataset,
        metrics=metrics,
        llm=evaluator_llm,
        show_progress=True,
    )

    # Step 4: result.scores を集計して MetricScore のリストに変換して返す
    ...
ステップ処理
Step 1_build_ragas_dataset() で RAGAS 用データセットを用意
Step 2LangChain の ChatOpenAI で LLM を作り、LangchainLLMWrapper でラップ
Step 33 つのメトリクスを指定して evaluate() を呼ぶ
Step 4result.scoreslist[dict])をメトリクス名ごとに平均をとり MetricScore のリストに変換

第 7 章:Docker でバックエンドを動かす

7.1 Docker とは

Docker は、アプリとその実行環境(OS・ランタイム・ライブラリ)をまとめた「イメージ」を作り、そのイメージから「コンテナ」という隔離されたプロセスを動かす技術です。

  • 「自分の PC では動くが、別の環境では動かない」という 環境差 を減らせる
  • Dockerfile に条件を書いておけば、どこでも同じ環境を再現できる
  • 本番に近い形でローカル開発できる

7.2 Dockerfile の解説

# backend/Dockerfile
FROM python:3.12-slim
WORKDIR /app

RUN apt-get update && apt-get install -y --no-install-recommends \
    curl \
    && rm -rf /var/lib/apt/lists/*

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

COPY app/ ./app/

RUN useradd -m appuser && chown -R appuser:appuser /app
USER appuser

HEALTHCHECK --interval=30s --timeout=5s --start-period=5s --retries=3 \
    CMD curl -f http://localhost:8000/api/health || exit 1

EXPOSE 8000
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
命令役割
FROM python:3.12-slimベースイメージを「Python 3.12 入りの軽量 Linux」に指定
WORKDIR /appコンテナ内の作業ディレクトリを /app に設定
RUN apt-get ...ヘルスチェック用に curl をインストール(イメージを小さく保つ工夫あり)
COPY requirements.txtRUN pip install依存関係を先にインストールして レイヤーキャッシュ を活用
COPY app/ ./app/アプリのソースをコピー
RUN useradd ... / USER appuserroot ではなく一般ユーザーで実行(セキュリティ向上)
HEALTHCHECK定期的に /api/health を確認し、異常時はコンテナを「不健全」とみなす
EXPOSE 8000コンテナが 8000 番ポートで待ち受けると宣言
CMD ["uvicorn", ...]コンテナ起動時に uvicorn で FastAPI を立ち上げる

--host 0.0.0.0 を指定することで、コンテナの外(ホストマシン)からもアクセスできるようになります。

7.3 docker-compose.yml の解説

# docker-compose.yml
services:
  backend:
    build:
      context: ./backend
      dockerfile: Dockerfile
    container_name: ragas-eval-api
    ports:
      - "8001:8000"
    environment:
      - OPENAI_API_KEY=${OPENAI_API_KEY}
      - OPENAI_MODEL=${OPENAI_MODEL}
      - CORS_ORIGINS=["http://localhost:3000","http://127.0.0.1:3000"]
    env_file:
      - ./backend/.env
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8000/api/health"]
      ...
設定項目内容
ports: "8001:8000"ホストの 8001 番をコンテナの 8000 番に接続。PC では http://localhost:8001 でアクセス
environmentコンテナに渡す環境変数。CORS_ORIGINS は JSON 配列の文字列で渡す(Pydantic が解釈)
env_file./backend/.env の内容を環境変数として読み込む
restart: unless-stoppedクラッシュ時に自動で再起動(手動で停止した場合は再起動しない)
healthcheckコンテナ内の http://localhost:8000/api/health を定期的に確認

第 8 章:Next.js と API クライアント —— lib/api.ts

8.1 Next.js とは

Next.js は、React ベースのフロントエンドフレームワークです。ここでは クライアント側 から FastAPI の API を fetch で呼び出し、得たデータを画面に表示する構成をとります。

8.2 ベース URL の決め方

// frontend/src/lib/api.ts
const getBaseUrl = () =>
  process.env.NEXT_PUBLIC_API_URL ?? "http://localhost:8001";

NEXT_PUBLIC_ で始まる環境変数は、Next.js のビルド時にクライアント用 JavaScript に埋め込まれ、ブラウザから参照できます。未設定時は http://localhost:8001(Docker でバックエンドを動かす想定のデフォルト値)を使います。

8.3 型定義(バックエンドとの契約)

export interface EvaluationSample {
  user_input: string;
  retrieved_contexts: string[];
  response: string;
  reference: string;
}

export interface EvaluateRequest {
  samples: EvaluationSample[];
}

export interface MetricScore {
  name: string;
  score: number;
  description?: string | null;
}

export interface EvaluateResponse {
  success: boolean;
  metrics: MetricScore[];
  error_message?: string | null;
}

バックエンドの Pydantic スキーマと 同じ形 にしておくことで、「送るデータ」「返ってくるデータ」を TypeScript 側でも型安全に扱えます。

8.4 ヘルスチェック —— fetchHealth

export async function fetchHealth(): Promise<HealthResponse> {
  const res = await fetch(`${getBaseUrl()}/api/health`, {
    method: "GET",
    headers: { "Content-Type": "application/json" },
  });
  if (!res.ok) throw new Error(`Health check failed: ${res.status}`);
  return res.json() as Promise<HealthResponse>;
}

8.5 評価実行 —— evaluateRag

export async function evaluateRag(
  request: EvaluateRequest
): Promise<EvaluateResponse> {
  const res = await fetch(`${getBaseUrl()}/api/evaluate`, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(request),
  });
  const data = (await res.json()) as EvaluateResponse;
  if (!res.ok) {
    throw new Error(data.error_message ?? `Request failed: ${res.status}`);
  }
  return data;
}

フロントとバックの型を関数で 1 か所に書いておくと、変更時に追いかけやすくなります。


第 9 章:画面の実装 —— app/page.tsx

9.1 役割

  • 評価サンプル(質問・コンテキスト・回答・正解)を 複数件 入力できるフォームを表示
  • 「API 接続確認」でヘルスチェック、「評価を実行」で評価 API を呼び出す
  • 返ってきたメトリクスをカード形式で表示

9.2 状態(useState)

const [samples, setSamples] = useState<EvaluationSample[]>(DEFAULT_SAMPLES);
const [apiStatus, setApiStatus] = useState<"idle" | "ok" | "error">("idle");
const [loading, setLoading] = useState(false);
const [result, setResult] = useState<{
  metrics: MetricScore[];
  error?: string;
} | null>(null);
状態変数用途
samples現在入力されている評価サンプルの配列
apiStatusヘルスチェックの結果(idle / ok / error
loading評価 API 呼び出し中かどうか(ボタンの無効化に使用)
result評価 API の戻り値。null のとき結果セクションは非表示

9.3 評価実行の流れ(handleEvaluate)

const handleEvaluate = useCallback(async () => {
  setLoading(true);
  setResult(null);
  try {
    const res = await evaluateRag({ samples });
    if (res.success) {
      setResult({ metrics: res.metrics });
    } else {
      setResult({
        metrics: [],
        error: res.error_message ?? "評価に失敗しました",
      });
    }
  } catch (e) {
    setResult({
      metrics: [],
      error: e instanceof Error ? e.message : "リクエスト中にエラーが発生しました",
    });
  } finally {
    setLoading(false);
  }
}, [samples]);

useCallbacksamples が変わったときだけ関数を再生成します。実行中は loadingtrue に、結果表示を一度クリアしてから evaluateRag を呼び出します。finally で必ず setLoading(false) を呼んでボタンを再度有効にします。

9.4 サンプルの操作

関数処理
addSample空の 1 件を samples の末尾に追加
updateSample指定インデックスのサンプルの指定フィールドを更新
updateContextretrieved_contexts の特定要素を更新
addContextコンテキストを 1 行追加

これらはすべて、状態を直接変更せず setSamples で新しい配列を渡して更新する という React の基本に従っています。

9.5 表示の構成

┌─────────────────────────────────────────┐
│ ヘッダー                                 │
│  └─ 「API 接続確認」ボタン + 接続状態表示  │
├─────────────────────────────────────────┤
│ 入力フォーム(samples を map して表示)    │
│  └─ user_input / contexts / response /  │
│     reference の入力欄 × 件数分          │
│  └─ 「サンプルを追加」ボタン              │
│  └─ 「評価を実行」ボタン                  │
├─────────────────────────────────────────┤
│ 評価結果(result が存在する場合のみ表示)  │
│  └─ エラーがあればエラーメッセージ        │
│  └─ メトリクスをカードで表示(% 表示等)  │
└─────────────────────────────────────────┘

第 10 章:動かす手順とトラブルシューティング

10.1 前提

  • Docker Desktop(または Docker Engine + docker compose)がインストール済みであること
  • Node.js がインストール済みであること
  • OpenAI API キー を用意していること

10.2 バックエンド(Docker)の起動

# 1. .env ファイルを作成し、API キーを記入
cp backend/.env.example backend/.env
# → OPENAI_API_KEY=sk-... を記入

# 2. バックエンドを起動
docker compose up -d backend

# 3. 動作確認
curl http://localhost:8001/api/health
# → {"status":"ok","service":"ragas-evaluation-api"} が返れば成功

10.3 フロントエンドの起動

# 1. frontend ディレクトリへ移動
cd frontend

# 2. 依存関係のインストール
npm install

# 3. 開発サーバーを起動
npm run dev

ブラウザで http://localhost:3000 を開き、「API 接続確認」で緑のメッセージが表示されれば疎通確認完了です。

10.4 よくあるトラブル

症状確認箇所
CORS エラーCORS_ORIGINS にフロントの URL(例:http://localhost:3000)が含まれているか確認。docker-compose では JSON 配列の文字列で渡す
metrics が空docker compose logs backend でエラーを確認。API キーとモデル名も確認
バックエンドに接続できないports の設定(例:8001:8000)と NEXT_PUBLIC_API_URL(例:http://localhost:8001)が一致しているか確認

まとめ

この記事では、RAGAS 評価 API を FastAPI で作り、Next.js の画面から呼び出し、Docker でバックエンドを動かすまでを、初学者にも分かるようにコード単位で解説しました。

技術学んだこと
FastAPI設定(config)・スキーマ(schemas)・ルート(routes)・サービス(ragas_service)の役割分担と、CORS・依存性注入の意味
Next.jsAPI クライアント(api.ts)で型と関数をまとめ、ページ(page.tsx)で状態と UI を扱う流れ
DockerDockerfile の各命令の意味と、docker-compose でのポート・環境変数・ヘルスチェックの指定方法
RAGASサンプルをデータセットに変換し、evaluate() でメトリクスを計算し、API 用に整形する流れ

実際に clone して docker compose up -d backendnpm run dev で動かし、コードを少しずつ変えてみると、各パーツの役割がよりはっきり理解できるはずです。本記事が、FastAPI・Next.js・Docker を「動かして学ぶ」きっかけになれば幸いです。

タイトルとURLをコピーしました