LLMの品質を可視化!Langfuseで実現する自動評価システムの構築

記事タイトルとURLをコピーする

はじめに

前回の記事では、LangfuseをAWS上にデプロイしてLLMアプリケーションのトレースを可視化する方法をご紹介しました。トレースによって「何が起きているか」は見えるようになりましたが、これだけでは「その回答は良いのか悪いのか」を判断することはできません。

そこで今回は、Langfuseの「評価」機能を使って、LLMの回答品質を自動で数値化し、ダッシュボードでリアルタイムに可視化する方法をご紹介します。

前提条件

  • Langfuse環境 ( 前回の記事でデプロイ済み )
  • 観測対象のRAGシステム
  • Python 3.9以上(評価スクリプト実行用)
  • OpenAI APIキー(自動評価で使用)

シナリオ

今回は、社内ナレッジベースを活用したRAG(Retrieval-Augmented Generation)チャットシステムを例に、Langfuseの評価機能を設定していきます。

評価対象のアプリケーション

社内のFAQやドキュメントをベクトルデータベースに格納し、ユーザーの質問に対して関連情報を検索して回答するRAGシステムです。以下のような質問に回答します。

  • 「社内の経費精算の手順を教えて」
  • 「リモートワークの申請方法は?」
  • 「新入社員のオンボーディング資料はどこにありますか?」

今回使用する評価指標

RAGシステムの評価には、以下の3つの指標を使用します。

  1. Context Precision(コンテキスト精度)

    • 検索されたコンテキストがどれだけ質問に関連しているか
    • 不要な情報を含まず、必要な情報だけを取得できているかを評価
  2. Faithfulness(忠実性)

    • 生成された回答が検索されたコンテキストに忠実か
    • ハルシネーション(事実と異なる情報の生成)を検出

これらの指標をLangfuseで自動評価し、ダッシュボードで可視化することで、RAGシステムの品質を継続的に監視・改善できます。

評価設定の手順

1. Amazon Bedrockを使った自動評価の有効化

LangfuseでAmazon Bedrock(Claude)を使って自動評価を行うには、まずECSタスクにBedrockへのアクセス権限を付与する必要があります。

1.1 WebタスクへのBedrock権限追加

cdk_stacks/ecs_task_langfuse_web.pyを編集し、Bedrock InvokeModel権限を追加します:

# Bedrock InvokeModel permission
task_role_policy_doc.add_statements(aws_iam.PolicyStatement(**{
  "effect": aws_iam.Effect.ALLOW,
  "resources": ["arn:aws:bedrock:*::foundation-model/*"],
  "actions": [
    "bedrock:InvokeModel",
    "bedrock:InvokeModelWithResponseStream"
  ]
}))

1.2 WorkerタスクへのBedrock権限追加

同様にcdk_stacks/ecs_task_langfuse_worker.pyにも権限を追加します:

# Bedrock InvokeModel permission
task_role_policy_doc.add_statements(aws_iam.PolicyStatement(**{
  "effect": aws_iam.Effect.ALLOW,
  "resources": ["arn:aws:bedrock:*::foundation-model/*"],
  "actions": [
    "bedrock:InvokeModel",
    "bedrock:InvokeModelWithResponseStream"
  ]
}))

1.3 変更のデプロイ

権限を追加したら、CDKで変更をデプロイします:

cdk deploy LangfuseWebECSTaskStack LangfuseWorkerECSTaskStack --require-approval never

デプロイには約5分程度かかります。

2. Langfuseでの評価設定

デプロイが完了したら、Langfuseの管理画面にアクセスして評価を設定します。

2.1 LLM接続の設定

まず、評価に使用するLLMプロバイダーを設定します。

Langfuseにログインし、左メニューから「Settings」を選択します。

設定画面が開いたら、左メニューから「LLM Connections」を選択し、「Add LLM Connection」ボタンをクリックします。

Amazon Bedrockを使って評価を行うため、「Add LLM Connection」をクリックして以下の設定で接続を追加します:

New LLM Connection画面で以下を入力します:

  • LLM adapter: bedrock
  • Provider name: blog provider
  • AWS Region: ap-northeast-1
  • AWS Access Key ID: (空欄でOK。LangFuseのIAMロールを使用)
  • AWS Secret Access Key: (空欄でOK。LangFuseのIAMロールを使用)

画面下部では、Bedrockで使用するモデル名を設定します。Claude 3.5 Sonnetを使用する場合は、Custom modelsセクションに以下を入力:

  • Model name: anthropic.claude-3-5-sonnet-20240620-v1:0

「Create connection」ボタンをクリックして接続を作成します。

接続が正常に作成されると、LLM Connectionsの一覧に「blog provider」が表示されます。これで評価で使用するLLMプロバイダーの設定が完了しました。

2.2 デフォルト評価モデルの設定

評価機能を使用する前に、デフォルトの評価モデルを設定する必要があります。左メニューから「LLM-as-a-Judge」を選択します。

まずは右上の「No default model set」リンクをクリックして、デフォルトの評価モデルを設定します。

「Set up」ボタンをクリックして、

Default model configurationを設定します。

Default model configuration画面で以下を設定します:

  • Provider: blog provider(先ほど作成したBedrock接続)
  • Model name: anthropic.claude-3-5-sonnet-20240620-v1:0

「Save」ボタンをクリックして設定を保存します。これで評価に使用するデフォルトモデルが設定されました。

2.3 評価テンプレートの作成

デフォルトモデルの設定が完了したら、RAG用の評価テンプレートを作成します。今回は以下の2つの評価テンプレートを作成します:

  • Context Precision(コンテキスト精度)
  • Faithfulness(忠実性)

評価テンプレート作成画面で「Create Evaluator」ボタンをクリックします。プレビュー画面では評価プロンプトのテンプレートが表示されています。

現在のデフォルトモデルが設定されていることを確認し、「Create Custom Evaluator」ボタンをクリックして新しい評価テンプレートを作成します。

Faithfulnessテンプレートの作成

最初に「Faithfulness」評価テンプレートを作成します。以下の内容を入力:

  • Name: Faithfulness
  • Evaluation prompt:
Given a question and an answer, analyze the complexity of each sentence in the answer. Break down each sentence into one or more fully understandable statements. Ensure that no pronouns are used in any statement.
Question: {{question}}
Answer: {{answer}}
  • Score reasoning prompt: Give a one-sentence justification for the score in Japanese.

Context Precisionテンプレートの作成

次に「Context Precision」評価テンプレートを作成します。以下の内容を入力:

  • Name: Context Precision
  • Evaluation prompt:
Given question, answer and context verify if the context was useful in arriving at the given answer.
Question: {{question}}
Answer: {{answer}}
Context: {{context}}
  • Score reasoning prompt: Give a one-sentence justification for the score in Japanese.

両方のテンプレートで「Save」ボタンをクリックして保存します。

これで評価テンプレートの設定は完了です。

次にサンプルのRAGアプリケーションを実行して、トレースデータを生成しましょう。

動作確認

サンプルRAGアプリケーションの実行

評価機能をテストするため、簡単なRAGアプリケーションを実行して、Langfuseにトレースデータを送信します。

必要なPythonパッケージのインストール

pip install langfuse openai python-dotenv chromadb

環境変数の設定

.envファイルを作成し、Langfuseの接続情報を設定します:

# .env  
LANGFUSE_PUBLIC_KEY="pk-lf-..."
LANGFUSE_SECRET_KEY="sk-lf-..."
LANGFUSE_BASE_URL="http://your-alb-url.ap-northeast-1.elb.amazonaws.com"
OPENAI_API_KEY="sk-proj-..."

RAGサンプルアプリケーション

以下のサンプルコードは、社内FAQを検索するシンプルなRAGシステムです。主な機能:

  1. ナレッジベース構築: ChromaDBに社内Q&Aドキュメントを埋め込み
  2. 質問に対する検索: ユーザーの質問に関連するドキュメントを検索
  3. 回答生成: 検索結果をコンテキストとしてGPT-4o-miniで回答生成
  4. トレース記録: @observeデコレータでLangfuseに各処理を記録

このRAGシステムを実行することで、評価用のトレースデータを生成します:

# rag_sample.py
# rag_sample.py
import os
from dotenv import load_dotenv
from langfuse import Langfuse
from langfuse.openai import openai
from langfuse import observe
import chromadb
from chromadb.utils import embedding_functions

load_dotenv()

# Langfuseクライアント初期化
langfuse = Langfuse()

@observe()
def setup_knowledge_base():
    """ナレッジベースの準備"""
    # ChromaDBクライアント初期化
    client = chromadb.Client()
    collection = client.get_or_create_collection(
        name="company_kb",
        embedding_function=embedding_functions.OpenAIEmbeddingFunction(
            api_key=os.environ["OPENAI_API_KEY"],
            model_name="text-embedding-3-small"
        )
    )

    # 既存のドキュメントがある場合はスキップ
    if collection.count() > 0:
        return collection

    # サンプルドキュメント(Q&A形式)
    documents = [
        "Q: 経費精算はいつまでに申請すればいいですか? A: 経費精算は毎月末日までに申請してください。領収書の添付が必要です。",
        "Q: リモートワークの申請方法を教えてください。 A: リモートワークの申請は3日前までに上司に提出してください。人事システムから申請可能です。",
        "Q: 新入社員向けの資料はどこにありますか? A: 新入社員のオンボーディング資料は人事部のSharePointにあります。"
    ]

    # ドキュメントを埋め込み
    collection.add(
        documents=documents,
        ids=[f"doc_{i}" for i in range(len(documents))]
    )

    return collection

@observe()
def search_context(collection, query: str):
    """関連ドキュメントの検索"""
    results = collection.query(
        query_texts=[query],
        n_results=2
    )
    return results["documents"][0]

@observe()
def generate_answer(query: str, context: list):
    """回答の生成"""
    context_text = "\n".join(context)

    completion = openai.chat.completions.create(
        model="gpt-4o-mini",
        messages=[
            {"role": "system", "content": "あなたは社内のヘルプデスクです。提供されたコンテキストを基に質問に回答してください。"},
            {"role": "user", "content": f"コンテキスト:\n{context_text}\n\n質問: {query}"}
        ]
    )

    return completion.choices[0].message.content

@observe()
def rag_pipeline(query: str):
    """RAGパイプライン全体"""
    collection = setup_knowledge_base()
    context = search_context(collection, query)
    answer = generate_answer(query, context)

    print(f"質問: {query}")
    print(f"検索されたコンテキスト: {context}")
    print(f"回答: {answer}")

    return answer

if __name__ == "__main__":
    # テスト質問
    test_queries = [
        "経費精算の方法を教えてください",
        "リモートワーク申請はいつまでに提出すればいいですか?",
        "新入社員向けの資料はどこにありますか?"
    ]

    for query in test_queries:
        print("="*50)
        rag_pipeline(query)
        print()

サンプルアプリケーションの実行

python rag_sample.py

実行すると、Langfuseにトレースデータが送信され、各RAG処理が記録されます。

トレースデータの確認

Langfuseの「Tracing」ページで、rag_pipelineという名前で5つのトレースが記録されています。各トレースには質問内容、検索されたコンテキスト、生成された回答、そして各ステップの実行時間が記録されています。

Running Evaluatorsの設定

トレースデータが生成されたので、作成した評価テンプレートを使って自動評価システムを設定しましょう。

Running Evaluatorの作成

左メニューから「LLM-as-a-Judge」を選択し、「Running Evaluators」タブに移動します。現在は「No results.」と表示されており、まだRunning Evaluatorが設定されていません。右上の「Set up evaluator」ボタンをクリックして評価器を設定します。

評価テンプレート選択画面で、先ほど作成した「Context Precision」と「Faithfulness」のテンプレートが表示されています。まず「Context Precision」を選択します。

Context Precision評価器の設定

「Run Evaluator: Context Precision」画面で以下を設定します。

  • Generated Score Name: Context Precision(デフォルト)
  • Target data: Live tracing data(リアルタイムのトレースデータを使用)
  • Evaluator runs on: New traces(新しいトレースに対して自動評価実行)
  • Sampling: 100%(すべてのトレースを評価)

下部のプレビューで、評価対象となるトレースが5つ表示されています。これらは先ほどRAGサンプルアプリで生成したトレースです。この設定により、今後新しいトレースが生成されるたびに自動的にContext Precision評価が実行されます。

変数マッピングの設定

次に、Variable mapping を設定します。これは評価プロンプトで使用する変数({{question}}、{{answer}}、{{context}})を、実際のトレースデータのどの部分から取得するかを指定します。 今回のサンプルアプリでは以下の設定となります。

{{question}}の設定: - Object: Trace - Object Variable: Input
- JsonPath: $.args[0]

{{answer}}の設定: - Object: Trace - Object Variable: Output

{{context}}の設定: - Object: Event(search_contextイベント) - Object Name: search_context - Object Variable: Output

評価プロンプトのプレビューで、実際のデータがどのようにマッピングされるかが確認できます。設定が完了したら「Execute」ボタンをクリックします。

Context Precision評価器が正常に作成されました。Running Evaluatorsの一覧に「Context Precision」が表示され、ステータスが「active」になっています。これで、新しいトレースが生成されるたびに自動的にContext Precision評価が実行されます。

Faithfulness評価器の作成

同様にFaithfulness評価器も作成しましょう。

評価テンプレート選択画面で「Faithfulness」を選択します。

「Run Evaluator: Faithfulness」画面で変数マッピングを設定します:

{{question}}の設定: - Object: Trace - Object Variable: Input - JsonPath: $.args[0]

{{answer}}の設定: - Object: Trace
- Object Variable: Output

Faithfulness評価では{{context}}変数は不要なため設定しません。「Execute」ボタンをクリックして評価器を作成します。

両評価器の完成確認

両方のRunning Evaluatorsが正常に作成されました。「Faithfulness」と「Context Precision」の両方がactive状態で表示されています。これで、新しいトレースが生成されるたびに両方の評価指標が自動的に計算され、品質スコアが記録されます。

評価結果の確認

Running Evaluatorsが設定完了したので、再度RAGサンプルアプリを実行して評価結果を確認してみましょう。

python rag_sample.py

実行後、Langfuseで評価結果を確認してみましょう。

「LLM-as-a-Judge」の「Running Evaluators」タブで、両方の評価器(FaithfulnessとContext Precision)がactiveステータスで動作していることが確認できます。ResultカラムにはそれぞれのEvaluatorで評価が実行されたトレース数(3件)が表示されています。

「View」ボタンをクリックすると、評価の詳細結果が確認できます。

Faithfulness評価の詳細画面では、各トレースの評価結果が表示されています:

  • Score Value: 0.7000や1など、評価スコア(0-1の範囲)
  • Score Comment: 日本語での評価理由(「回答は1つの文で構成されており、複数の情報を含んでいるため」など)

評価結果から、RAGシステムの各質問に対する忠実性が数値とコメントで可視化されていることがわかります。同様にContext Precisionの評価結果も確認でき、検索精度の品質を定量的に把握できます。

ダッシュボードでの可視化

評価結果をより効果的に監視するため、専用のダッシュボードを作成しましょう。

左メニューから「Dashboards」を選択します。Langfuseには事前に用意されたダッシュボードテンプレート(Cost Dashboard、Latency Dashboard、Usage Management)がありますが、今回は評価スコアを可視化するカスタムダッシュボードを作成します。

「New dashboard」ボタンをクリックして、ダッシュボード名を「Evaluators」として「Create」ボタンをクリックします。

新しいダッシュボードが作成され、「Add Widget」ボタンから評価指標のウィジェットを追加できます。

「Add Widget」をクリックすると、ウィジェット選択ダイアログが表示されます。「Create New Widget」ボタンをクリックして新しいウィジェットを作成します。

Faithfulness評価ウィジェット

Faithfulness評価用のウィジェットを設定します

  • View: Scores Numeric(数値スコア表示)
  • Metric: Value → Avg(平均値)
  • Filters: Score Name = "Faithfulness"(Faithfulness評価のみ表示)
  • Name: "Avg Faithfulness"
  • Chart Type: Line Chart(線グラフ)
  • Date Range: Past 7 days(過去7日間)

右側のプレビューで、Faithfulnessスコアの時系列変化が線グラフで可視化されます。「Save Widget」をクリックして保存します。

Context Precision評価ウィジェット

同様にContext Precision評価用のウィジェットも作成します

  • View: Scores Numeric(数値スコア表示)
  • Metric: Value → Avg(平均値)
  • Filters: Score Name = "Context Precision"
  • Name: "Avg Context Precision"
  • Chart Type: Line Chart(線グラフ)
  • Date Range: Past 7 days(過去7日間)

完成したダッシュボード

両方のウィジェットを追加すると、FaithfulnessとContext Precisionの評価スコア推移が並んで表示されます。

まとめ

今回は、LangfuseのRunning Evaluators機能を使用して、RAGシステムの品質を自動評価するシステムを構築しました。 RAGシステムの品質向上において、このような自動評価システムは非常に強力なツールとなります。ぜひ皆さんのLLMアプリケーションでも活用してみてください。