👻

Langfuse でプロンプトをデプロイ&A/B テストする方法

に公開

はじめに

本記事では、Langfuse の Prompt Management 機能を使ってプロンプトをデプロイし、A/B テストを行う手順をまとめています。実例中心に紹介しますので、Langfuse 未経験の方もぜひチャレンジしてみてください。

1. プロンプト管理とは(Prompt Management)

Langfuse のプロンプト管理は、プロンプトを一元的にバージョン管理し、共同で編集できるようにするものです。

Langfuse は以下のような機能を提供しています:

  • プロンプトは name、テンプレート構文({{変数}})、version によって管理され、更新時に自動で version がインクリメントされます。
  • labels は特定のバージョンへのポインタとして機能し、productionlatest の他、stagingprod-atenant-x など任意で設定可能です。
  • SDK でラベルを指定しなければ、デフォルトで production ラベルが返されます。

この仕組みにより、コードを触らずにプロンプトの切り替えやロールバックが可能です。

1-1. プロンプト管理にプロンプ​​トを追加するコード例

  • name:Langfuse のプロンプト管理画面で識別するための一意の名称
  • prompt:{{変数名}} を含むテンプレート形式のプロンプト本文
  • config:使用するmodeltemperatureなどの設定
  • labels:production などのラベルを付けることで、本番用プロンプトとしてすぐに利用できるようにする

今回の例で使用するプロンプトはSDK経由で追加しています。

langfuse.create_prompt(
    name="event-planner",
    prompt=
    "イベント名『{{Event Name}}』の企画を立ててください。イベントの内容は「{{Event Description}}」です。"
    "開催場所は{{Location}}、開催日は{{Date}}です。"
    "次の要素を考慮してください:対象となる参加者、予算、会場、ケータリングの選択肢、エンターテインメント。"
    "候補となる業者や物流の手配を含めた、詳細なイベント企画案を作成してください。",
    config={
        "model": "gpt-4o",
        "temperature": 0,
    },
    labels=["production"]
)

2. A/B テストとは

A/B テストとは、「AパターンとBパターン、どっちが良いか比べる方法」です。

Langfuse では、プロンプト管理を利用するとプロンプトの異なるバージョン(例:prod-aprod-b)にラベルを付けることで A/B テストが可能になります。

3. 実装方法(コード例)

3-1. セットアップ

3-1-1. API Key の作成

事前に Langfuse にログインが必要です。

Langfuse の Project Settings から Langfuse の API Key を作成します。

APIKeyの作成

3-1-2. ライブラリのアップデート

%pip install langfuse langchain langchain-openai --upgrade

3-1-3. 環境変数の設定

先程作成した API Key を設定します。

本記事では作成方法を省きますが、OPENAI_API_KEY も事前に作成する必要があります。

import os
 
os.environ["LANGFUSE_PUBLIC_KEY"] = "pk-lf-..." 
os.environ["LANGFUSE_SECRET_KEY"] = "sk-lf-..." 
os.environ["LANGFUSE_HOST"] = "https://cloud.langfuse.com" 

os.environ["OPENAI_API_KEY"] = "sk-proj-..."

3-2. プロンプトのバージョンにラベルをつける

プロンプトのバージョンにラベルをつけるコード例をご紹介します。

以下は Python SDK によるプロンプト作成例ですが、JS/TS SDK でもほぼ同様の構文で対応できます。

from langfuse import get_client
langfuse = get_client()

# prod-a variant
langfuse.create_prompt(
  name="support-response",
  type="text",
  prompt="こんにちは、{{name}}さん。今日はどんなご用件でしょうか?",
  labels=["prod-a"],
  config={"model": "gpt-3.5-turbo", "temperature": 0.3}
)

# prod-b variant
langfuse.create_prompt(
  name="support-response",
  type="text",
  prompt="お世話になります、{{name}}様。本日はどのようなご質問でしょうか?",
  labels=["prod-b"],
  config={"model": "gpt-3.5-turbo", "temperature": 0.3}
)

prod-aprod-b は A/B テスト用のラベルとして機能し、後のテストに使います。

3-3. プロンプトを取得して A/B テストを実行する

プロンプトを取得して A/B テストを実行するコード例をご紹介します。

metadata に variant を設定することで、どのラベルが選択されたかを確認することができます。

Python(OpenAI + Langfuse)

from langfuse import get_client
from langfuse.openai import openai
import random

langfuse = get_client()

# 2種類のラベルを取得
prompt_a = lf.get_prompt("support-response", label="prod-a")
prompt_b = lf.get_prompt("support-response", label="prod-b")

# ランダムでA/B割当
selected = random.choice([prompt_a, prompt_b])
variant = 'prod-a' if selected == prompt_a else 'prod-b'

# OpenAI実行 + Langfuseに紐付け + variantメタデータ付与
resp = openai.chat.completions.create(
  model="gpt-3.5-turbo",
  messages=[{"role":"user", "content":selected.compile(name="佐藤") }],
  langfuse_prompt=selected,
 metadata={"variant": variant}
)
print(resp.choices[0].message.content)

ランダムに選択する際に比率を設定することも可能です。

# A=80%、B=20% の比率でランダム選択
selected = random.choices(
    [prompt_a, prompt_b],   # 候補
    weights=[0.8, 0.2],     # 比率を指定
    k=1                     # 1件選ぶ
)[0]

JavaScript/TypeScript(OpenAI + Langfuse)

import { Langfuse, observeOpenAI } from "langfuse";
import OpenAI from "openai";

const langfuse = new Langfuse();
const openai = observeOpenAI(new OpenAI());

// 2種類のラベルを取得
const [promptA, promptB] = await Promise.all([
    langfuse.getPrompt("support-response", undefined, { label: "prod-a" }),
    langfuse.getPrompt("support-response", undefined, { label: "prod-b" })
]);

// 50%でA/Bを選択
const chosen = Math.random() < 0.5 ? promptA : promptB;
const variant = chosen === promptA ? "prod-a" : "prod-b";

// OpenAI実行 + Langfuseに紐付け + variantメタデータ付与
const completion = await openai.chat.completions.create({
  model: "gpt-3.5-turbo",
  messages: [{ role: "user", content: chosen.compile({name:"山田"}) }],
  langfusePrompt: chosen,
  metadata: {            
    variant: variant,
  }
});
console.log(completion.choices[0].message.content);

このようにアプリ側でランダム選択するだけで、Langfuse 側で latency/cost/評価スコアなどを自動で追跡できます。

4. 実行結果(Langfuse UI)

Langfuse UI では、A/B テスト版それぞれに対して以下の指標を可視化できます:

  • 応答レイテンシー、トークン使用量、コスト
  • 評価スコア(LLM-as-a-Judge や手動評価)
  • カスタムメトリクス(例:クリック率や満足度など)

Playground 機能を使えば、UI 上で即時にプロンプトを試しながら調整することも可能です。

4-1. プロンプト管理画面での確認

4-1-1. プロンプト管理

Langfuse UI から Prompt Management タブの Prompts を選択します。

先程作成した support-response がプロンプト管理に表示されていることを確認できます。

プロンプト管理

4-1-2. バージョンごとのプロンプト

support-response をクリックすると、作成した2つのバージョンのプロンプトを確認できます。

ラベルA
ラベルB

4-2. トレース での実行ログの確認

4-2-1. トレース

Langfuse UI から Observability タブの Tracing を選択します。

A/B テストを実行した際の実行ログを確認することができます。

トレース画面

4-2-2. トレースの詳細

反映されたトレースをクリックすると、実行ログの詳細を確認することができます。

variant から今回の A/B テストでは、prod-b が選択されたことが確認できます。

トレース詳細

更に詳細を確認したい場合は、以下をクリックすると詳しいログを確認することができます。

トレース更に詳細

4-2-3. 指標の詳細

  • Latency: 1.42s
    → OpenAI APIへのリクエスト〜レスポンス完了までにかかった時間

  • $0.000121
    → この1回のAPI呼び出しにかかった推定コスト(トークン数×モデル単価)

  • Prompt: support-response - v2
    → 使われた Langfuse のプロンプト名(support-response)とそのバージョン(Version #2)

  • 44 prompt → 66 completion (∑ 110)
    → トークン数の内訳
    44 = プロンプトの入力トークン数
    66 = モデルが生成した出力トークン数
    ∑ 110 = 合計使用トークン数

  • gpt-3.5-turbo-0125
    → 実際に使われた OpenAI モデル名

指標詳細

5. Dataset を活用した Prompt Experiments(オフライン評価)

Langfuse の Native Dataset Runs(Prompt Experiments) 機能を使えば、プロンプトバージョンを事前に検証できます:

  • データセット:入力と期待出力を JSON 形式で作成
  • プロンプトの変数名データセットのキー名 を一致させる必要あり
  • LLM-as-a‑Judge Evaluator を使えば回答の質を自動スコア化し、バージョン比較が可能

I 上で複数の Dataset Run を選択して「Compare」アクションを選ぶと、実験結果を視覚的に比較できます。

6. 運用の全体像

ここまでで プロンプトの作成 → A/B テスト実装 → UIでの可視化 → Datasetによるオフライン評価 までを体験しました。
実際のプロダクション運用を考えると、次のような流れで管理することができます。

開発環境(staging)

  • 新しいプロンプトを追加・修正
  • チームでレビュー&軽いテスト
  • Dataset Run を使ったオフライン検証

A/B テスト環境(prod-a / prod-b)

  • 複数のバリアントを同時に本番トラフィックへ流す
  • Langfuse UI で latency/cost/評価スコアを比較
  • ユーザー行動ログやカスタムメトリクスと組み合わせて分析

本番運用(production)

  • テストで最も良かったバージョンを production ラベルに昇格
  • コード変更なしで即時反映&ロールバック可能

このように、「staging → A/B テスト → production」 という流れを設計しておくことで、
安全かつ継続的にプロンプトを改善しながら運用できます。

7. ラベル戦略と環境アーキテクチャ図

以下の図は、開発〜本番の環境別デプロイ戦略を示しています:

  • staging: QA やレビューテスト用
  • prod-a / prod-b: 実際に A/B テストするバリアント
  • production: 評価後に本番に昇格させたバージョン(例:prod-a)

運用では labels によって環境を分離し、UI や SDK 設定を変えずにバージョン切り替えやロールバックが可能です。

8. ベストプラクティスと注意点

  • Labels を中心とした運用設計で、コードに version をハードコードしないこと
  • まずは staging → A/B テスト → 評価後 production へという段階的リリースがおすすめ
  • Dataset Run や LLM-as-a‑Judge を CI/CD に組み込み、リグレ防止の自動化を目指す
  • Playground の活用で prompt の微調整をすばやく実施

まとめ

  • Langfuse の Prompt Management により、テンプレートプロンプトの運用・切り替え・ロールバックが容易に
  • アプリ側でラベルをランダムに選択すれば、リアルタイム A/B テスト が可能
  • UI や Dataset Run による 定量評価で信頼性ある比較 が実現できる
  • 運用上は labels 戦略と Offline テスト(Dataset Run)を組み合わせた設計が鍵

参考リンク

Discussion