25
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

はじめに

Difyで作成したRAGを評価する方法が、今のところ見つけられなかったのでここに残しておきます。
評価するための連携方法を書くだけで、評価自体のことはほとんど書いていません。

Ragasについて

Ragasに関しては別ブログで記載しているのでそちらをご覧いただければと思います。

ここでも少し記載しておこうと思います。
Ragasで使用できる指標はいくつかあります。

  • Faithfulness
  • Answer relevancy
  • Context recall
  • Context precision
  • Context relevancy
  • Answer semantic similarity
  • Answer correctness
    etc …

Ragasではこの中でもRAGを評価する時に重要だとされる4つの指標を使います。

RAGはRetrievalとGenerationの二つのプロセスに分かれます。
Ragasの評価指標はそれぞれのプロセスを評価することができます。
Generation → faithfulness, answer relevancy
Retrieval  → context precision, context recall

スクリーンショット 2024-07-07 12.53.02.png
(https://docs.ragas.io/en/stable/concepts/metrics/index.html)

これらの評価指標は以下のデータに基づいて評価されます。

  • Question : LLMに投げる質問
  • Answer : LLMが生成する回答
  • Context : Retrieverが取得してきた文献情報など
  • Ground Truth : 参考となる正確な回答

これらのデータと評価指標の全体像は図のような形になっています。
スクリーンショット 2024-07-07 13.28.40.png

Ragasの説明に関してはここまでにして、実際にDifyの評価でRagasを使うためにDifyとLangfuseとRagasをどのように連携させるかを書いていきます。

Difyのワークフロー

今回はこちらのワークフローの評価をRagasで行いたいと思います。
スクリーンショット 2024-07-07 13.33.14.png

かなり単純なものにしています。
LangGraphについてRAGを構築し、それを評価するような形を取りたいと思います。

DifyとLangfuseの連携について

ローカルDifyとローカルLangfuseでの連携に関しては以下で書いているので、ローカルでやる方は以下をお読みください。

ここまでできたら質問をいくつかしてデータをLangfuseに送っておいてください。

LangfuseとRagas連携のコード

では実際にDifyから送信されたLangfuseのデータをRagasで検証していきましょう。こちらを参考に構築していきます。

まずは環境変数を設定してください。

import os
 
os.environ["LANGFUSE_SECRET_KEY"] = "LANGFUSE_SECRET_KEY"
os.environ["LANGFUSE_PUBLIC_KEY"] = "LANGFUSE_PUBLIC_KEY"
os.environ["LANGFUSE_HOST"] ="LANGFUSE_HOST"
os.environ["OPENAI_API_KEY"] = "OPENAI_API_KEY"

次にLangfuseのクライアントを用意します。

from langfuse import Langfuse
langfuse = Langfuse()

そしてDifyがLangfuseに送信したトレースを取得するメソッドを用意します。

def get_generations(name=None, limit=None, user_id=None):
    all_data = []
    page = 1
 
    while True:
        response = langfuse.get_generations(
            name=name, page=page, user_id=user_id
        )
        if not response.data:
            break
        page += 1
        all_data.extend(response.data)
        if len(all_data) > limit: # type: ignore
            break
    return all_data[:limit]

Cookbookではtraceを取得指定しましたが、Traceの中身からContextを取得できないのでTraceではなくGenerationを取得してきました。Generationだとちゃんと以下のようにContextも質問も入っています。
スクリーンショット 2024-07-07 13.40.54.png

そしてサンプルをランダムに取得します。

from random import sample
 
NUM_TRACES_TO_SAMPLE = 3
traces = get_generations(limit=5)

traces_sample = sample(traces, NUM_TRACES_TO_SAMPLE)
 
len(traces_sample)
traces_sample

以下のコードでquestion、context、answerに分けます。
trace_idとobservation_idの両方を入れておかないとGenerationとの紐付けができないので注意です。


evaluation_batch = {
    "question": [],
    "contexts": [],
    "answer": [],
    "trace_id": [],
    "observation_id": []
}
for t in traces_sample:
    observations = t
    d = dict(observations)
    question = ""
    context = []
    for item in d["input"]:
        if item["role"] == "user":
            question = item["content"]
        elif item["role"] == "system":
            context.append(item["content"])
    
    evaluation_batch["question"].append(question)
    evaluation_batch["contexts"].append(context)
    
    if "output" in d and "text" in d["output"]:
        evaluation_batch["answer"].append(d["output"]["text"])
    evaluation_batch["trace_id"].append(t.trace_id)
    evaluation_batch["observation_id"].append(t.id)

そして以下のコードでRagasを実行してください。

from datasets import Dataset
from ragas import evaluate
from ragas.metrics import faithfulness, answer_relevancy
 
ds = Dataset.from_dict(evaluation_batch)
r = evaluate(ds, metrics=[faithfulness, answer_relevancy])

最後にLangfuseに送りましょう。

df = r.to_pandas()
df["trace_id"] = ds["trace_id"]
df["observation_id"] = ds["observation_id"]

df.head()
for _, row in df.iterrows():
    for metric_name in ["faithfulness", "answer_relevancy"]:
        langfuse.score(
            name=metric_name,
            value=row[metric_name],
            trace_id=row["trace_id"],
            observation_id=row["observation_id"]
        )

評価結果

Langfuseで以下のような評価結果が得られます。
スクリーンショット 2024-07-07 13.43.57.png
いい感じです。今後はこんな感じでDifyでは評価していこうと思います。

最後に

Difyで作成したRAGを評価する方法の記事が今のところなかったので書きました。
他にいい方法があれば教えてください!

Xをやっているので気になる方はフォローお願いします。
https://x.com/hudebakonosoto

25
13
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
25
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?