メインコンテンツへジャンプ
Engineering blog

オフラインLLM評価:Databricks上での段階的なGenAIアプリケーション評価

Share this post

背景

RAG(Retrieval-Augmented Generation)がAIを駆使したアプリケーションとの関わり方に革命をもたらす時代において、これらのシステムの効率性と有効性を確保することは、かつてないほど不可欠なことである。DatabricksとMLflowはこの革新の最前線にあり、GenAIアプリケーションの重要な評価のための合理化されたソリューションを提供している。

このブログポストでは、Databricks Data Intelligence Platformを活用いて、GenAIアプリケーションの3つのコアコンポーネント(プロンプト、検索システム、Foundation LLM)の品質を強化および評価し、GenAIアプリケーションの継続的な品質を確保するためのするためにシンプルで効果的なプロセスを紹介する。

ユースケース

MLflowのドキュメントの質問に回答し、その結果を評価するQAチャットボットを作成する。

フローチャート

Databricksで外部モデルを設定する

Databricksのモデルサービング機能は、Azure OpenAI GPT、Anthropic Claude、AWS Bedrockなど、様々な大規模言語モデル(LLM)プロバイダからの外部モデルを組織内で管理、統制、アクセスするために使用できる。特定のLLM関連リクエストを処理する統一的なエンドポイントを提供することで、これらのサービスとのやりとりを簡素化する高レベルのインターフェイスを提供する。

モデルサービングを使用する主な利点:

  • 統一されたインターフェイスによるモデルの照会:組織内の複数のLLMを呼び出すためのインターフェイスを簡素化する。 統一されたOpenAI互換のAPIとSDKを通じてモデルを照会し、単一のUIを通じてすべてのモデルを管理する。
  • モデルの管理:組織内の複数のLLMのエンドポイントを一元管理する。 これには、権限を管理し、使用制限を追跡する機能が含まれる。
  • 集中的なキー管理:APIキーの管理を安全な場所に一元化することで、システムやコードにおけるキーの露出を最小限に抑え、エンドユーザーの負担を軽減し、組織のセキュリティを強化する。

Databricksで外部モデルを持つサービングエンドポイントを作成する

import mlflow
import mlflow.deployments

client = mlflow.deployments.get_deploy_client("databricks")

endpoint_name = f"test-endpoint-{uuid.uuid4()}"

client.create_endpoint(
name=endpoint_name,
config={
        "served_entities": [
            {
                "name": "test",
                "external_model": {
                    "name": "gpt-3.5-turbo-instruct",
                    "provider": "openai",
                    "task": "llm/v1/completions",
                    "openai_config": {
                        "openai_api_type": "azure",
                        "openai_api_key": "{{secrets/<your-scope-name>/<your-key-name>}}", ## Use Databricks Secrets. 
                        "openai_api_base": "https://<your-endpoint>.openai.azure.com/",
                        "openai_deployment_name": "<your-deployment-name>",
                        "openai_api_version": "2023-05-15",
                    },
                },
            }
        ],
    	},
)

Databricks AI Playgroundでプロンプトを探る

このセクションでは次の内容を扱う:選択したLLMで異なるプロンプトがどの程度のパフォーマンスを示すのか?

私たちは最近、完璧なプロンプトを作成するための業界最高の体験を提供するDatabricks AI Playgroundを導入した。コードは必要なく、Databricksのエンドポイントとして提供される複数のLLMを試し、異なるパラメータやプロンプトをテストすることができる。

Databricks AI Playgroundの主な利点は以下の通り:

  • 迅速なテスト:Databricks でデプロイされたモデルを直接すばやくテストできる。
  • 簡単な比較:複数のモデルを異なるプロンプトとパラメータで比較し、選択するための中心的な場所。

Databricks AI Playgroundの使用

Databricks AI Playgroundを活用し、OpenAI GPT 3.5 Turboで関連するプロンプトをテストする。

異なるプロンプトとパラメータを比較する

Playgroundでは、複数のプロンプトの出力を比較して、どのプロンプトがより良い結果をもたらすかを確認することができる。Playgroundで直接、いくつかのプロンプト、モデル、パラメーターを試して、どの組み合わせが最良の結果をもたらすかを見極めることができる。モデルとパラメータの組み合わせは、GenAIアプリに追加され、適切なコンテキストで回答生成に使用される。

コンパシング・プロンプト

GenAIアプリにモデルとパラメータを追加する

いくつかのプロンプトとパラメータを試した後、GenAIアプリケーションで同じ設定とモデルを使用することができる。

モデルパラメータの追加

LangChainで同じ外部モデルをインポートする例。 次のセクションでは、これをGenAI POCに変える方法について説明する。

from langchain.llms import Databricks

llm = Databricks(
    endpoint_name="<endpoint-name>",
    extra_params={"temperature": 0.1,
                 "top_p": 0.1,
                 "max_tokens": 500,
                 } #parameters used in AI Playground
)

LangChainでGenAI POCを作成し、MLflowでログを取る

ユースケースに適したモデルとプロンプトパラメータが見つかったので、ベクターデータベースとDatabricks Foundation Model APIを使ったエンベッディングモデル、さらにAzure OpenAI GPT 3.5を生成モデルとして使い、MLflowドキュメントからの質問に答えるQAチャットボットであるサンプルGenAIアプリを作成する。

MLflowウェブサイトのドキュメントを使用して、LangChainを使用したサンプルGenAIアプリを作成する

import os
import pandas as pd
import mlflow
import chromadb
from langchain.chains import RetrievalQA
from langchain.document_loaders import WebBaseLoader
from langchain.llms import Databricks
from langchain.embeddings.databricks import DatabricksEmbeddings
from langchain.text_splitter import CharacterTextSplitter
from langchain.vectorstores import Chroma
from langchain.embeddings.sentence_transformer import SentenceTransformerEmbeddings

loader = WebBaseLoader(
    [ 
     "https://mlflow.org/docs/latest/index.html",
     "https://mlflow.org/docs/latest/tracking/autolog.html", 
     "https://mlflow.org/docs/latest/getting-started/tracking-server-overview/index.html",
     "https://mlflow.org/docs/latest/python_api/mlflow.deployments.html" ])

documents = loader.load()
CHUNK_SIZE = 1000
text_splitter = CharacterTextSplitter(chunk_size=CHUNK_SIZE, chunk_overlap=0)
texts = text_splitter.split_documents(documents)

llm = Databricks(
    endpoint_name="<endpoint-name>",
    extra_params={"temperature": 0.1,
                 "top_p": 0.1,
                 "max_tokens": 500,
                 } #parameters used in AI Playground
)

# create the embedding function using Databricks Foundation Model APIs
embedding_function = DatabricksEmbeddings(endpoint="databricks-bge-large-en")
docsearch = Chroma.from_documents(texts, embedding_function)

qa = RetrievalQA.from_chain_type(
    llm=llm,
    chain_type="stuff",
    retriever=docsearch.as_retriever(fetch_k=3),
    return_source_documents=True,
)

GenAIアプリケーションで使用するRetrieverを拡張したいお客様には、メタデータを含むデータのベクター表現をベクターデータベースに保存できるサーバーレス類似検索エンジン、Databricks Vector Searchの使用を推奨する。

MLflowによる検索システムの評価

このセクションでは次の内容を扱う:Retrieverは与えられたクエリに対してどの程度機能するのか?

MLflow 2.9.1では、Retrieverの評価が導入され、MLflow evaluate APIを使用してRetrieverの効率を評価する方法が提供された。このAPIを使って、埋め込みモデル、トップKのしきい値の選択、チャンキング戦略の有効性を評価することができる。

グラウンド・トゥルース・データセットの作成

GenAIを評価するためのグランドトゥルースデータセットの作成には、手作業でテストセットに注釈を付けるという細心の注意が必要であり、時間と専門知識の両方が要求される。このブログでは、それとは異なるルートを取る。 LLMのパワーを活用して、テスト用の合成データを生成し、GenAIアプリの検索能力の感覚を得るためのクイックスタートアプローチと、その後に続くかもしれない詳細な評価作業のウォーミングアップを提供する。読者やお客様には、GenAIアプリケーションの期待される入力と出力を反映したデータセットを作成することの重要性を強調する。信じられないほどの洞察が得られるので、参加する価値のある旅である。

全データセットを使って調べることもできるが、ここでは生成されたデータのサブセットを使ってデモをしてみよう。 questionカラムには評価されるすべての質問が含まれ、sourceカラムには文字列の順序付きリストとして質問に対する回答の予想されるソースが含まれる。

eval_data = pd.DataFrame(
    {
        "question": [
            "What is MLflow?",
            "What is Databricks?",
            "How to serve a model on Databricks?",
            "How to enable MLflow Autologging for my workspace by default?",
        ],
        "source": [
            ["https://mlflow.org/docs/latest/index.html"],
            ["https://mlflow.org/docs/latest/getting-started/tracking-server-overview/index.html"],
            ["https://mlflow.org/docs/latest/python_api/mlflow.deployments.html"],
            ["https://mlflow.org/docs/latest/tracking/autolog.html"],
        ],
    }
)

MLflowによる埋め込みモデルの評価

埋め込みモデルの品質は、正確な検索にとって極めて重要である。MLflow 2.9.0では、Retrieverがどれだけ効果的に予測するかを判断できるように、3つの組み込みメトリクス、mlflow.metrics.precision_at_k(k)mlflow.metrics.recall_at_k(k)mlflow.metrics.ndcg_at_k(k)を導入した。例えば、ベクトル・データベースが10個の結果を返し(k=10)、その10個の結果のうち、4個がクエリに関連しているとする。precision_at_10は4/10、つまり40%となる。

def evaluate_embedding(embedding_function):
    CHUNK_SIZE = 1000
    list_of_documents = loader.load()
    text_splitter = CharacterTextSplitter(chunk_size=CHUNK_SIZE, chunk_overlap=0)
    docs = text_splitter.split_documents(list_of_documents)
    retriever = Chroma.from_documents(docs, embedding_function).as_retriever()

    def retrieve_doc_ids(question: str) -> List[str]:
        docs = retriever.get_relevant_documents(question)
        doc_ids = [doc.metadata["source"] for doc in docs]
        return doc_ids

    def retriever_model_function(question_df: pd.DataFrame) -> pd.Series:
        return question_df["question"].apply(retrieve_doc_ids)

    with mlflow.start_run() as run:
        evaluate_results = mlflow.evaluate(
                model=retriever_model_function,
                data=eval_data,
                model_type="retriever",
                targets="source",
                evaluators="default",
            )
    return evaluate_results

result1 = evaluate_embedding(DatabricksEmbeddings(endpoint="databricks-bge-large-en"))result2 = evaluate_embedding(<another-embedding-function>)

eval_results_of_retriever_df_bge = result1.tables["eval_results_table"]
display(eval_results_of_retriever_df_bge)

評価は、各質問に対する評価結果を表にして返す。例えば、このテストでは、Retrieverは"How to enable MLflow Autologging for my workspace for my default?" という質問に対しては、Precision @ K スコアが1であり、素晴らしいパフォーマンスをしているようだ。また、"What is MLflow?" という質問に対しては、Precision @ K スコアが0であるため、正しいドキュメントを取得していないことがわかる。この知見により、Retrieverをデバッグし、"What is MLflow? "のような質問に対するRetrieverを改善できる。

MLflow-価値
Evaluation results when using databricks-bge-large-en embedding model

MLflowによるトップK値の異なるRetrieverの評価

extra_metrics引数を指定することで、様々なK値に対してメトリックス、指標を素早く計算できる。

with mlflow.start_run() as run:
        evaluate_results = mlflow.evaluate(
        data=eval_results_of_retriever_df_bge,
        targets="source",
        predictions="outputs",
        evaluators="default",
        extra_metrics=[
            mlflow.metrics.precision_at_k(1),
            mlflow.metrics.precision_at_k(2),
            mlflow.metrics.precision_at_k(3),
            mlflow.metrics.recall_at_k(1),
            mlflow.metrics.recall_at_k(2),
            mlflow.metrics.recall_at_k(3),
            mlflow.metrics.ndcg_at_k(1),
            mlflow.metrics.ndcg_at_k(2),
            mlflow.metrics.ndcg_at_k(3),
        ],
    )

display(evaluate_results.tables["eval_results_table"])

評価では、各質問に対する評価結果の表が返され、文書を検索する際にどのK値を使用すればよいかをよりよく理解できる。 すなわち、このテストでは、トップのK値を変更することで、「Databricksとは」のような質問に対するRetrieverの精度にプラスの影響を与えることがわかる。

MLflow-イバル-2
Evaluation result with all precision @ K values

MLflowによるチャンキング戦略の評価

チャンキング戦略の効果は極めて重要だ。 MLflowがこの評価をどのように支援できるかを、検索モデルの種類と全体的なパフォーマンスへの影響に焦点を当てながら探る。

def evaluate_chunk_size(chunk_size):
  list_of_documents = loader.load()
  text_splitter = CharacterTextSplitter(chunk_size=chunk_size,chunk_overlap=0)
  docs = text_splitter.split_documents(list_of_documents)
  embedding_function = DatabricksEmbeddings(endpoint="databricks-bge-large-en")
  retriever = Chroma.from_documents(docs, embedding_function).as_retriever()
  
  def retrieve_doc_ids(question: str) -> List[str]:
    docs = retriever.get_relevant_documents(question)
    doc_ids = [doc.metadata["source"] for doc in docs]
    return doc_ids
   
  def retriever_model_function(question_df: pd.DataFrame) -> pd.Series:
    return question_df["question"].apply(retrieve_doc_ids)

  with mlflow.start_run() as run:
      evaluate_results = mlflow.evaluate(
          model=retriever_model_function,
          data=eval_data,
          model_type="retriever",
          targets="source",
          evaluators="default",
      )
  return evaluate_results

result1 = evaluate_chunk_size(500)
result2 = evaluate_chunk_size(2000)

display(result1.tables["eval_results_table"])
display(result2.tables["eval_results_table"])

評価では、2つの異なるチャンクサイズを使用した各質問に対する評価結果が2つのテーブルで返され、ドキュメントを検索する際にどのチャンクサイズを使用すべきかをよりよく理解できる。つまり、この例では、チャンクサイズを変えてもメトリックス、指標には影響がないように見える。

1000回中
Evaluation result with Chunk size of 1000

2000チャンク
Evaluation result with Chunk size of 2000

検索評価に関する詳細をノートブックでチェックする。

GenAIの結果をMLflowで評価

このセクションでは次の内容を扱う:与えられたプロンプトとコンテクストに対するGenAIアプリの応答はどの程度良いのか?

生成された回答の質を評価することが重要である。 MLflowのQA メトリクス、指標を活用することで、質問と回答による評価の手動プロセスを補強し、生成された回答の有効性を理解するためのベンチマークとしてGPT-4モデルと比較する。

GPT-4のようなLLMを審査員として使用することで、いくつかの利点が得られます:

  • 迅速でスケーラブルな実験:多くの状況において、LLMジャッジはスイートスポットであると我々は考えている。LLMジャッジは、構造化されていない出力(チャットボットからの応答のような)を、自動的に、迅速に、低コストで評価することができる。
  • 費用対効果:LLMで一部の評価を自動化することで、人間による評価に匹敵する価値があると考える。人間による評価は、より遅く、よりコストがかかるが、モデル評価のゴールドスタンダードとなる。

MLflowで評価し、LLMで判断する

いくつかのサンプル問題を取り上げ、LLMを判定に使用し、MLflowで結果を検査し、組み込みのメトリクスで結果の包括的な分析を提供する。GenAIアプリを関連性(入力とコンテキストの両方に関して、出力がどれだけ関連性があるか)で判断するつもりだ。

各入力をチェーンを通して実行する単純な関数を作成する。

def model(input_df):
    return input_df["questions"].map(qa).tolist()
eval_df = pd.DataFrame(
    {
        "questions": [
            "What is MLflow?",
            "What is Databricks?",
            "How to serve a model on Databricks?",
            "How to enable MLflow Autologging for my workspace by default?",
        ],
    }
)

関連性 メトリクスを使って、答えと文脈の関連性を判断する。 他にも使えるメトリクスがある。

from mlflow.deployments import set_deployments_target
from  mlflow.metrics.genai.metric_definitions import relevance

set_deployments_target("databricks") #To retrieve all endpoint in your Databricks Workspace

relevance_metric = relevance(model=f"endpoints:/{endpoint_name}") #You can also use any model you have hosted on Databricks, models from the Marketplace or models in the Foundation model API

with mlflow.start_run():
    results =  mlflow.evaluate(
        model,
        eval_df,
        model_type="question-answering",
        evaluators="default",
        predictions="result",
        extra_metrics=[relevance_metric, mlflow.metrics.latency()],
        evaluator_config={
            "col_mapping": {
                "inputs": "questions",
                "context": "source_documents",
            }
        }
    )
    print(results.metrics)

Databricksのワークスペースでは、すべての入力と出力、ソースドキュメント、関連性、評価関数に追加したその他のメトリックス、指標を比較および評価できる。

ワークスペース内の比較結果

LLMの評価に関する詳細をNotebookでチェックする

Databricksを使用してGenAIアプリの品質を向上させているお客様

高度な評価機能を備えたDatabricksは、私たちのRAG(Retrieval-Augmented Generation)プロジェクトを非常に効果的かつ効率的なQAチャットボットへと昇華させる上で重要な役割を果たしました。ユーザーフレンドリーなインターフェースは、詳細なメトリクスと相まって、RAGアプリケーションのパフォーマンスに関する貴重な知見を提供してくれました。これらの機能は私たちのビジネスにとって不可欠であることが証明され、誤検出や幻覚の大幅な減少につながり、その結果、私たちのチャットボットの応答の精度と信頼性が大幅に向上しました。 - マヌエル・バレロ・メンデス、サンタ・ルシア・セグロスのビッグデータ部門責任者

まとめ

Databricksデータインテリジェンスプラットフォームを用いることで、GenAIアプリケーションを簡単に評価し、高品質なアプリケーションを確保できる。AIプレイグラウンドによるプロンプト作成から最終的な回答生成まで、各コンポーネントを分解することで、GenAIアプリケーションのあらゆる側面が最高水準の品質と効率を満たすことを保証できる。

このブログは、Databricksデータインテリジェンスプラットフォームを利用してGenAIアプリケーションを評価しようとする開発者のためのガイドだ。

商用グレードのGenAIアプリケーションの場合、評価は自動化され、ジョブとして実行され、アプリケーションが変更されるたびに実行され、パフォーマンス後退がないことを確認するために以前のバージョンに対してベンチマークされるべきである。

DatabricksデータインテリジェンスプラットフォームでLLM評価を始める

Databricks 評価版Notebookを今すぐお試しください。

さらに詳しい情報はこちら: