> ## Documentation Index
> Fetch the complete documentation index at: https://docs.coreweave.com/llms.txt
> Use this file to discover all available pages before exploring further.

# DSPy によるプロンプト最適化

> W&B Weave で DSPy のプロンプト最適化を使用する方法を説明します

<Note>
  これはインタラクティブなノートブックです。ローカルで実行するか、次のリンクから利用できます。

  * [Google Colab で開く](https://colab.research.google.com/github/wandb/docs/blob/main/weave/cookbooks/source/dspy_prompt_optimization.ipynb)
  * [GitHub でソースを表示](https://github.com/wandb/docs/blob/main/weave/cookbooks/source/dspy_prompt_optimization.ipynb)
</Note>

[BIG-bench (Beyond the Imitation Game Benchmark)](https://github.com/google/BIG-bench) は、200 を超えるタスクで大規模言語モデルを検証し、その将来の能力を推定する共同ベンチマークです。[BIG-Bench Hard (BBH)](https://github.com/suzgunmirac/BIG-Bench-Hard) は、BIG-Bench のタスクのうち、現世代の言語モデルでも解くのが難しい、特に難易度の高い 23 のタスクをまとめたものです。

このチュートリアルでは、BIG-bench Hard ベンチマークの因果判断タスクを対象に実装した LLM ワークフローのパフォーマンスを改善し、プロンプト戦略を評価する方法を紹介します。LLM ワークフローの実装とプロンプト戦略の最適化には [DSPy](https://dspy.ai) を使用します。また、LLM ワークフローのトラッキングとプロンプト戦略の評価には [Weave](/ja/products/wandb/weave) を使用します。

このチュートリアルでは、因果推論のためのベースライン DSPy プログラムを構築して Weave で評価し、DSPy のオプティマイザーを適用してプロンプト戦略を改善したうえで、最適化したプログラムをベースラインと比較します。自身の LLM ワークフローにプロンプト最適化を適用し、Weave で結果をトラッキング・比較したい実務者を対象としています。

<h2 id="install-the-dependencies">
  依存関係をインストールする
</h2>

始める前に、このチュートリアルで使用するライブラリをインストールします。このチュートリアルでは、次のライブラリを使用します。

* [DSPy](https://dspy.ai): LLM ワークフローの構築と最適化に使用します。
* [Weave](/ja/products/wandb/weave): LLM ワークフローのトラッキングと、プロンプト戦略の評価に使用します。
* [datasets](https://huggingface.co/docs/datasets/index): HuggingFace Hub の BIG-Bench Hard データセットへのアクセスに使用します。

```python lines theme={"system"}
!pip install -qU dspy weave "datasets<4"
```

このチュートリアルでは LLM ベンダーとして [OpenAI API](https://openai.com/index/openai-api/) を使用するため、OpenAI APIキーも必要です。OpenAI Platform で[サインアップ](https://platform.openai.com/signup)すると、ご自身の APIキーを取得できます。

```python lines theme={"system"}
import os
from getpass import getpass

api_key = getpass("Enter you OpenAI API key: ")
os.environ["OPENAI_API_KEY"] = api_key
```

<h2 id="enable-tracking-using-weave">
  Weave を使用してトラッキングを有効にする
</h2>

このセクションでは Weave を設定し、チュートリアルでこれ以降に実行する DSPy の Call が自動的にトレースされ、Weights & Biases UI で確認できるようにします。

Weave は DSPy と連携しています。コードの冒頭に [`weave.init`](/ja/products/wandb/weave/reference/python-sdk/trace/weave_client#method-init) を追加すると、DSPy の関数が自動的にトレースされ、Weights & Biases UI で詳しく確認できます。詳細については、[DSPy 向け Weave インテグレーションのドキュメント](/ja/products/wandb/weave/guides/integrations/dspy)を参照してください。

```python lines theme={"system"}
import weave

weave.init(project_name="dspy-bigbench-hard")
```

このチュートリアルでは、[`weave.Object`](/ja/products/wandb/weave/reference/python-sdk#class-object) を継承したメタデータクラスを使用してメタデータを管理します。

```python lines theme={"system"}
class Metadata(weave.Object):
    dataset_address: str = "maveriq/bigbenchhard"
    big_bench_hard_task: str = "causal_judgement"
    num_train_examples: int = 50
    openai_model: str = "gpt-4o-mini"
    openai_max_tokens: int = 2048
    max_bootstrapped_demos: int = 8
    max_labeled_demos: int = 8

metadata = Metadata()
```

<Tip>
  オブジェクトのバージョン管理：`Metadata` オブジェクトを使用する関数をトレースすると、その `Metadata` オブジェクトも自動的にバージョン管理され、トレースされます。
</Tip>

<h2 id="load-the-big-bench-hard-dataset">
  BIG-Bench Hard データセットを読み込む
</h2>

Weave のトラッキングを有効にしたら、次に DSPy プログラムのトレーニングと評価に使用するデータを準備します。

HuggingFace Hub からこのデータセットを読み込み、トレーニングセットと検証セットに分割して、Weave に[パブリッシュ](/ja/products/wandb/weave/guides/core-types/datasets)します。パブリッシュすると、データセットをバージョン管理できるだけでなく、[`weave.Evaluation`](/ja/products/wandb/weave/guides/core-types/evaluations) を使用してプロンプト戦略を評価することもできます。

```python lines theme={"system"}
import dspy
from datasets import load_dataset

@weave.op()
def get_dataset(metadata: Metadata):
    # タスクに対応する BIG-Bench Hard データセットを Huggingface Hub から読み込みます
    dataset = load_dataset(metadata.dataset_address, metadata.big_bench_hard_task)[
        "train"
    ]

    # トレーニング用と検証用のデータセットを作成します
    rows = [{"question": data["input"], "answer": data["target"]} for data in dataset]
    train_rows = rows[0 : metadata.num_train_examples]
    val_rows = rows[metadata.num_train_examples :]

    # `dspy.Example` オブジェクトからなるトレーニング用と検証用のサンプルを作成します
    dspy_train_examples = [
        dspy.Example(row).with_inputs("question") for row in train_rows
    ]
    dspy_val_examples = [dspy.Example(row).with_inputs("question") for row in val_rows]

    # データセットを Weave にパブリッシュします。これにより、データをバージョン管理して評価に使用できます
    weave.publish(
        weave.Dataset(
            name=f"bigbenchhard_{metadata.big_bench_hard_task}_train", rows=train_rows
        )
    )
    weave.publish(
        weave.Dataset(
            name=f"bigbenchhard_{metadata.big_bench_hard_task}_val", rows=val_rows
        )
    )

    return dspy_train_examples, dspy_val_examples

dspy_train_examples, dspy_val_examples = get_dataset(metadata)
```

<Frame>
  <img src="https://mintcdn.com/coreweave-dbfa0e8d/3Dv_sw2eg8feUJlx/products/wandb/weave/_media/1.png?fit=max&auto=format&n=3Dv_sw2eg8feUJlx&q=85&s=a09604e56f8b63187f78199c46e21cc6" alt="データセットの準備手順とデータ構造を示す DSPy のデータセット読み込みインターフェース" width="2893" height="1041" data-path="products/wandb/weave/_media/1.png" />
</Frame>

<h2 id="the-dspy-program">
  DSPy プログラム
</h2>

データセットを Weave にパブリッシュしたので、次に、後で評価と最適化を行うベースラインの DSPy プログラムを定義します。

[DSPy](https://dspy.ai) は、新しい LM パイプラインの構築を、任意形式の文字列を操作する作業から、プログラミング (モジュール化されたオペレーターを組み合わせてテキスト変換グラフを構築すること) に近いものへと転換するフレームワークです。DSPy では、コンパイラーがプログラムから最適化された LM invocation 戦略とプロンプトを自動的に生成します。

[`dspy.LM`](https://dspy.ai/learn/programming/language_models) で言語モデルを設定し、[`dspy.configure`](https://dspy.ai/api/utils/configure/) でそのモデルをデフォルトに設定します。

```python lines theme={"system"}
llm = dspy.LM("openai/gpt-4o-mini")
dspy.configure(lm=llm)
```

<h3 id="write-the-causal-reasoning-signature">
  因果推論の Signature を記述する
</h3>

[Signature](https://dspy.ai/learn/programming/signatures) は、[DSPy モジュール](https://dspy.ai/learn/programming/modules)の入出力の動作を宣言的に定義する仕様です。DSPy モジュールは、タスクに応じて適応するコンポーネント (ニューラルネットワークの層に相当) で、任意のテキスト変換を抽象化します。

```python lines theme={"system"}
class CausalReasoning(dspy.Signature):
    """You are an expert in causal reasoning. Analyze the given question carefully
    and answer Yes or No. Provide a detailed explanation justifying your answer."""

    question: str = dspy.InputField(desc="The question to be answered")
    answer: str = dspy.OutputField(desc="Yes or No")
    confidence: float = dspy.OutputField(desc="Confidence score between 0 and 1")
    explanation: str = dspy.OutputField(desc="Detailed explanation for the answer")

class CausalReasoningModule(dspy.Module):
    def __init__(self):
        self.prog = dspy.Predict(CausalReasoning)

    @weave.op()
    def forward(self, question: str) -> dict:
        result = self.prog(question=question)
        return {
            "answer": result.answer,
            "confidence": result.confidence,
            "explanation": result.explanation,
        }
```

BIG-Bench Hard の因果推論サブセットにある例を 1 つ使って、LLM ワークフロー (つまり `CausalReasoningModule`) をテストします。

```python lines theme={"system"}
import rich

baseline_module = CausalReasoningModule()

prediction = baseline_module(dspy_train_examples[0]["question"])
rich.print(prediction)
```

<Frame>
  <img src="https://mintcdn.com/coreweave-dbfa0e8d/3Dv_sw2eg8feUJlx/products/wandb/weave/_media/2.png?fit=max&auto=format&n=3Dv_sw2eg8feUJlx&q=85&s=fa53fd11627944e47df0efedef7dd003" alt="ベースライン DSPy プログラムの評価結果（パフォーマンスメトリクスと出力例）" width="2887" height="1749" data-path="products/wandb/weave/_media/2.png" />
</Frame>

<h2 id="evaluate-the-dspy-program">
  DSPy プログラムを評価する
</h2>

ベースラインとなるプロンプト戦略ができたので、[`weave.Evaluation`](/ja/products/wandb/weave/guides/core-types/evaluations) を使用して検証セットで評価します。メトリクスには、予測された回答を正解と照合するものを使用します。Weave は各例をアプリケーションに渡し、その出力を複数のカスタムスコアリング関数でスコア付けします。これにより、アプリケーションのパフォーマンスを把握できるほか、充実した UI で個々の出力やスコアを詳しく確認できます。

まず、予測された回答が正解と一致するかどうかを判定するスコアリング関数を作成します。Weave のスコアリング関数は、モデルの戻り値を `output` として受け取り、データセットの例に含まれるキーのうち名前が一致するものを追加の引数として受け取ります。ここでは、`answer` はデータセットから渡され、`output` は `CausalReasoningModule.forward` が返す dict です。

```python lines theme={"system"}
@weave.op()
def weave_evaluation_scorer(answer: str, output: dict) -> dict:
    return {"match": int(answer.lower() == output["answer"].lower())}
```

次に、`weave.Evaluation` から呼び出せるように、モジュールをトレース対象の関数でラップします。ラッパーの引数名は、モデルが使用するデータセットの列名と一致させる必要があります。

```python lines theme={"system"}
@weave.op()
def predict(question: str) -> dict:
    return baseline_module(question=question)
```

これで、評価を定義して実行できます。

```python lines theme={"system"}
validation_dataset = weave.ref(
    f"bigbenchhard_{metadata.big_bench_hard_task}_val:v0"
).get()

evaluation = weave.Evaluation(
    name="baseline_causal_reasoning_module",
    dataset=validation_dataset,
    scorers=[weave_evaluation_scorer],
)

await evaluation.evaluate(predict)
```

<Frame>
  <img src="https://mintcdn.com/coreweave-dbfa0e8d/3Dv_sw2eg8feUJlx/products/wandb/weave/_media/dspy_optimization-3.png?fit=max&auto=format&n=3Dv_sw2eg8feUJlx&q=85&s=29d1d351812ba7be3990ed5216bd2408" alt="DSPy プログラムのパフォーマンスメトリクス、トレース、比較結果を表示した Weave の評価ダッシュボード" width="2893" height="1752" data-path="products/wandb/weave/_media/dspy_optimization-3.png" />
</Frame>

<Note>
  Python スクリプトから実行する場合は、次のコードで評価を実行できます。

  ```python lines theme={"system"}
  import asyncio
  asyncio.run(evaluation.evaluate(predict))
  ```
</Note>

<Warning>
  因果推論データセットで評価を実行すると、約 \$0.24 分の OpenAI クレジットを消費します。
</Warning>

<h2 id="optimize-the-dspy-program">
  DSPy プログラムを最適化する
</h2>

ベースラインのパフォーマンスを測定できたので、DSPy のオプティマイザーを適用し、その結果をベースラインと比較します。

ベースラインとなる DSPy プログラムが用意できたら、[BootstrapFewShot](https://dspy.ai/api/optimizers/BootstrapFewShot/) オプティマイザーを使用して、因果推論におけるパフォーマンスを向上させます。このオプティマイザーは、指定したメトリクスが最大になるように DSPy プログラムのパラメーターを調整します。

```python lines theme={"system"}
from dspy.teleprompt import BootstrapFewShot

@weave.op()
def get_optimized_program(model: dspy.Module, metadata: Metadata) -> dspy.Module:
    @weave.op()
    def dspy_evaluation_metric(true, prediction, trace=None):
        return prediction["answer"].lower() == true.answer.lower()

    teleprompter = BootstrapFewShot(
        metric=dspy_evaluation_metric,
        max_bootstrapped_demos=metadata.max_bootstrapped_demos,
        max_labeled_demos=metadata.max_labeled_demos,
    )
    return teleprompter.compile(model, trainset=dspy_train_examples)

optimized_module = get_optimized_program(baseline_module, metadata)
```

<Frame>
  <img src="https://mintcdn.com/coreweave-dbfa0e8d/3Dv_sw2eg8feUJlx/products/wandb/weave/_media/4.png?fit=max&auto=format&n=3Dv_sw2eg8feUJlx&q=85&s=d411afcc6be58ea4eb8989d6a25131f8" alt="テレプロンプターの設定と最適化の進行状況を表示する DSPy プログラム最適化プロセスのインターフェース" width="2893" height="1752" data-path="products/wandb/weave/_media/4.png" />
</Frame>

<Warning>
  因果推論データセットで評価を実行すると、OpenAI のクレジットが約 \$0.04 かかります。
</Warning>

最適化されたプログラム (最適化されたプロンプト戦略) ができたので、これを検証セットで再度評価し、ベースラインの DSPy プログラムと比較します。

```python lines theme={"system"}
@weave.op()
def predict_optimized(question: str) -> dict:
    return optimized_module(question=question)

evaluation = weave.Evaluation(
    name="optimized_causal_reasoning_module",
    dataset=validation_dataset,
    scorers=[weave_evaluation_scorer],
)

await evaluation.evaluate(predict_optimized)
```

<Frame>
  <img src="https://mintcdn.com/coreweave-dbfa0e8d/3Dv_sw2eg8feUJlx/products/wandb/weave/_media/5.png?fit=max&auto=format&n=3Dv_sw2eg8feUJlx&q=85&s=92efdb07512581f4dcce5d9cfed0f574" alt="パフォーマンスメトリクスと出力品質が向上した、最適化済み DSPy プログラムの評価結果" width="2893" height="1752" data-path="products/wandb/weave/_media/5.png" />
</Frame>

ベースラインのプログラムと最適化済みのプログラムの評価結果を比較すると、最適化済みのプログラムのほうが因果推論の質問により高い精度で回答できていることがわかります。

<h2 id="conclusion">
  まとめ
</h2>

このチュートリアルでは、DSPy を使用してプロンプト最適化を行い、Weave でトラッキングと評価を行って、元のプログラムと最適化後のプログラムを比較する方法を学びました。


## Related topics

- [サンプルコードとノートブック](/ja/products/wandb/examples.md)
