引き続き勉強中。今度はプロンプトの最適化。
MLflowのプロンプト最適化機能 mlflow.genai.optimize_prompt() によって、データドリブン アプローチを使用してプロンプトを自動的に改善できます。この API は、既存のプロンプトを高度な最適化アルゴリズムと統合します。現在、この API は DSPy の MIPROv2 アルゴリズムをサポートしています。この強力な機能は、 MLflowのプロンプト レジストリ、トレース、および評価機能とシームレスに連携し、 生成AI アプリケーションのプロンプト パフォーマンスを向上させます。
DSPy、こんなところにいたのか!こちらの記事などで勉強しました。
サンプルノートブックを実行していきます。トレース、評価データセット、プロンプトが繋がっていく感じです。
プロンプト最適化チュートリアル:マルチステップエージェントとデータセット作成
このノートブックでは、mlflow.genai.optimize_prompt
API を使ってマルチステップエージェントのプロンプトをエンドツーエンドで改善する方法を紹介します。このノートブックで学べること:
- マルチステップエージェント実行時にLLMコールのトレースを収集する方法
- MLflowトレースから評価用データセットを作成する方法
- プロンプト、評価指標、データセットを使ったプロンプト最適化の実行方法
エージェントの定義
最初のステップはAIエージェントの定義です。このノートブックでは、LangGraphを使って記事の主題を抽出するエージェントを定義します。エージェントは2回のLLMコールで構成されます。最初のLLMコールで長いドキュメント内容を短い要約にし、2回目のコールでその要約から主題を抽出します。
%pip install --upgrade mlflow>=3.1.0 langchain-community langchain-openai beautifulsoup4 langgraph dspy databricks-agents
dbutils.library.restartPython() # Pythonを再起動します
import os
# 必要に応じてカタログ名とスキーマ名を変更してください
CATALOG = "takaakiyayoi_catalog"
SCHEMA = "agents"
os.environ["OPENAI_API_KEY"] = dbutils.secrets.get("demo-token-takaaki.yayoi", "openai_api_key")
# mlflowのライブラリをインポートします
import mlflow
# Promptエンティティをインポートします
from mlflow.entities import Prompt
# レジストリのURIを設定します
mlflow.set_registry_uri("databricks-uc")
from langchain_community.document_loaders import WebBaseLoader
from langchain_text_splitters import CharacterTextSplitter
text_splitter = CharacterTextSplitter.from_tiktoken_encoder(
chunk_size=1000, chunk_overlap=0
)
loader = WebBaseLoader("https://lilianweng.github.io/posts/2023-06-23-agent/")
docs = loader.load()
split_docs = text_splitter.split_documents(docs)
print(f"{len(split_docs)} 件のドキュメントが生成されました。")
読み込んでいるのはこちらのエージェントに関する記事ですね。
WARNING:langchain_community.utils.user_agent:USER_AGENT environment variable not set, consider setting it to identify your requests.
WARNING:langchain_text_splitters.base:Created a chunk of size 1003, which is longer than the specified 1000
13 件のドキュメントが生成されました。
from langchain.chat_models import init_chat_model
# モデルを初期化します
llm = init_chat_model("gpt-4o-mini", model_provider="openai")
# 要約用の最初のプロンプト
summary_prompt = mlflow.genai.register_prompt(name=f"{CATALOG}.{SCHEMA}.summary_prompt", template="次の内容を簡潔に要約してください:{{content}}")
from langchain_core.output_parsers import StrOutputParser, JsonOutputParser
summary_chain = llm | StrOutputParser()
@mlflow.trace()
def call_summary_chain(content):
# コンテンツを要約チェーンに渡します
return summary_chain.invoke([HumanMessage(summary_prompt.format(content=content))])
# 主題抽出用の2つ目のプロンプト。
topic_prompt = mlflow.genai.register_prompt(name=f"{CATALOG}.{SCHEMA}.topic_prompt",
template="""
以下は要約です:
{{summary}}
この要約から主題を数語で抽出してください。
レスポンスはJSON形式で返してください: {\"topic\": \"...\"}
""")
topic_chain = llm | JsonOutputParser()
@mlflow.trace()
def call_topic_chain(summary):
return topic_chain.invoke([HumanMessage(topic_prompt.format(summary=summary))])
主題抽出用のプロンプトバージョン1が登録されます。バージョン2は後で作成されます。
from langchain_core.messages import HumanMessage, SystemMessage
@mlflow.trace
def agent(content):
# コンテンツを要約する
summary = call_summary_chain(content=content)
# 要約からトピックを取得する
return call_topic_chain(summary=summary)["topic"]
# オートロギングを有効化
mlflow.langchain.autolog()
# エージェントを実行
for doc in split_docs:
try:
print(agent(doc.page_content))
except Exception as e:
print(f"エラー: {e}")
pass
ドキュメントごとにトピックが生成されます。
自律エージェントシステム
複雑なタスクの計画と自己反省
モデル改善と履歴学習
人間の記憶の種類と情報検索方法
LLMとツール使用の重要性
タスク実行とLLM評価
抗癌薬の発見, Generative Agents, シミュレーション技術
タスク効率化とリソース活用
Requirements Clarification for MVC Component Structure
コード実装手順
コーディング手順とファイル構成
有限なコンテキスト長とエージェントの限界
LLMを活用した自律型エージェントの開発
オートロギングが有効化されているのでトレースも生成されます。
データセット作成
生成されたトレースから mlflow.genai.datasets
API を使って評価用データセットを作成します。この例では、2回目のLLMコール(主題抽出)に注目します。
import mlflow
# 2回目のLLMコールの入力と出力を抽出
traces = mlflow.search_traces(extract_fields=[
"call_topic_chain.inputs",
"call_topic_chain.outputs",
])
traces.head(10)
from mlflow.genai import datasets
EVAL_DATASET_NAME=f"{CATALOG}.{SCHEMA}.data"
dataset = datasets.create_dataset(EVAL_DATASET_NAME)
# エージェントの出力をデフォルトの期待値としてデータセットを作成
traces = traces.rename(
columns={
"call_topic_chain.inputs": "inputs",
"call_topic_chain.outputs": "expectations",
}
)[["inputs", "expectations"]]
traces = traces.dropna()
dataset.merge_records(traces)
MLflowエクスペリメントの評価タブにも表示されます。そういうことか。ここでは編集が可能です。期待するアウトプットに応じて編集します。
ラベリング
現在、データセットのexpectation列にはエージェントの出力が入っています。プロンプト最適化を実行するには高品質なラベルが必要です。「evaluation」タブ→「dataset」タブでexpectationを修正してください。
ラベリングが終わったら、下記コマンドで評価用データセットをダウンロードします。
dataset = datasets.get_dataset(EVAL_DATASET_NAME)
dataset.merge_records([])
dataset = dataset.to_df()
dataset.head()
最適化
最後に mlflow.genai.optimize_prompt
を実行してプロンプトを最適化します。下記コードでは組み込みのCorrectnessスコアラーを目的関数として使います。最適化されたプロンプトは自動的にPromptレジストリに保存されます。オプティマイザー実行後、新しいプロンプトテンプレートを確認してください。
import os
from typing import Any
import mlflow
from mlflow.genai.scorers import Correctness
from mlflow.genai.optimize import OptimizerConfig, LLMParams
from mlflow.genai.scorers import scorer
_correctness = Correctness()
@scorer
def correctness(inputs, outputs, expectations):
expectations = { "expected_response": expectations.get("topic") }
return _correctness(inputs=inputs, outputs=outputs, expectations=expectations).value == "yes"
# プロンプトを最適化
result = mlflow.genai.optimize_prompt(
target_llm_params=LLMParams(model_name="openai/gpt-4.1-mini"),
prompt=topic_prompt,
train_data=dataset,
scorers=[correctness],
optimizer_config=OptimizerConfig(
num_instruction_candidates=8,
max_few_show_examples=2,
verbose=True,
)
)
# 最適化されたプロンプトは自動的に新しいバージョンとして登録されます
# PromptレジストリのWebサイトで新しいプロンプトを確認してください
print(f"新しいプロンプトURI: {result.prompt.uri}")
最適化実行結果
2025/10/02 06:52:14 INFO mlflow.genai.optimize.base: 🚀 MLflow Run `2595b302a0c0436c898562c42ca04119` started for prompt optimization! Watch the run to track the optimization progress.
2025/10/02 06:52:18 INFO mlflow.genai.optimize.optimizers.dspy_optimizer: 🎯 Starting prompt optimization for: prompts:/takaakiyayoi_catalog.agents.topic_prompt/1
⏱️ This may take several minutes or longer depending on dataset size...
📊 Training with 13 examples.
2025/10/02 06:52:20 WARNING dspy.teleprompt.mipro_optimizer_v2: 'requires_permission_to_run' is deprecated and will be removed in a future version.
2025/10/02 06:52:20 INFO dspy.teleprompt.mipro_optimizer_v2:
==> STEP 1: BOOTSTRAP FEWSHOT EXAMPLES <==
2025/10/02 06:52:20 INFO dspy.teleprompt.mipro_optimizer_v2: These will be used as few-shot example candidates for our program and for creating instructions.
2025/10/02 06:52:20 INFO dspy.teleprompt.mipro_optimizer_v2: Bootstrapping N=8 sets of demonstrations...
Bootstrapping set 1/8
Bootstrapping set 2/8
Bootstrapping set 3/8
67%|██████▋ | 2/3 [00:06<00:03, 3.47s/it]
Bootstrapped 2 full traces after 2 examples for up to 1 rounds, amounting to 2 attempts.
Bootstrapping set 4/8
67%|██████▋ | 2/3 [00:06<00:03, 3.36s/it]
Bootstrapped 2 full traces after 2 examples for up to 1 rounds, amounting to 2 attempts.
Bootstrapping set 5/8
33%|███▎ | 1/3 [00:02<00:04, 2.13s/it]
Bootstrapped 1 full traces after 1 examples for up to 1 rounds, amounting to 1 attempts.
Bootstrapping set 6/8
33%|███▎ | 1/3 [00:01<00:03, 1.87s/it]
Bootstrapped 1 full traces after 1 examples for up to 1 rounds, amounting to 1 attempts.
Bootstrapping set 7/8
67%|██████▋ | 2/3 [00:05<00:02, 2.76s/it]
Bootstrapped 2 full traces after 2 examples for up to 1 rounds, amounting to 2 attempts.
Bootstrapping set 8/8
67%|██████▋ | 2/3 [00:04<00:02, 2.22s/it]
2025/10/02 06:52:48 INFO dspy.teleprompt.mipro_optimizer_v2:
==> STEP 2: PROPOSE INSTRUCTION CANDIDATES <==
2025/10/02 06:52:48 INFO dspy.teleprompt.mipro_optimizer_v2: We will use the few-shot examples from the previous step, a generated dataset summary, a summary of the program code, and a randomly selected prompting tip to propose instructions.
Bootstrapped 2 full traces after 2 examples for up to 1 rounds, amounting to 2 attempts.
2025/10/02 06:52:52 INFO dspy.teleprompt.mipro_optimizer_v2:
Proposing N=8 instructions...
2025/10/02 06:53:43 INFO dspy.teleprompt.mipro_optimizer_v2: Proposed Instructions for Predictor 0:
2025/10/02 06:53:43 INFO dspy.teleprompt.mipro_optimizer_v2: 0: 要約文から主題を数語で抽出し、JSON形式で{"topic": "..."}の形で返してください。
2025/10/02 06:53:43 INFO dspy.teleprompt.mipro_optimizer_v2: 1: 次の要約文の内容をよく読み、その主題を示す最適なキーワードや短いフレーズを日本語で表現し、JSON形式で{"topic": "..."}として出力してください。要約文の核心となる概念やテーマを的確かつ簡潔に反映させてください。
2025/10/02 06:53:43 INFO dspy.teleprompt.mipro_optimizer_v2: 2: 以下の要約文を読み、その内容に最もふさわしい主なトピックを簡潔な数語で抽出してください。トピックは要約の中心となるテーマや重要な概念を表現するものとし、結果はJSON形式で {"topic": "抽出したトピック名"} の形で返してください。確実に要約の要点を反映した明確かつ具体的なトピック名を選んでください。
2025/10/02 06:53:43 INFO dspy.teleprompt.mipro_optimizer_v2: 3: あなたは高度な知識を持つAIアシスタントとして、危機的な状況下で迅速かつ正確な意思決定を支援しなければなりません。今から提示する技術的な要約文を読み取り、内容の主題を最も適切に表す数語のトピックを抽出してください。この抽出されたトピックは、限られた時間内に関連情報を素早く分類し、緊急対応や学術研究に活用される重要な手がかりとなります。抽出したトピックは必ずJSON形式で {"topic": "..."} の形で返してください。例えば、上級AI技術や人間記憶に関する専門的内容でも、最も核心をつく数語に簡潔にまとめることを心がけてください。
2025/10/02 06:53:43 INFO dspy.teleprompt.mipro_optimizer_v2: 4: You are given a concise technical summary related to advanced topics in AI or cognitive science. In a high-stakes research or educational setting where accurately categorizing complex summaries is critical, extract a few precise topical keywords that best represent the main themes of the summary. Return your output strictly in JSON format as {"topic": "..."} to ensure clarity and easy integration into knowledge management systems.
2025/10/02 06:53:43 INFO dspy.teleprompt.mipro_optimizer_v2: 5: You are an expert in AI and cognitive science tasked with analyzing concise technical summaries related to human memory, information retrieval, and machine learning techniques. Given a summary text, extract a clear and precise topic label that captures the core subject matter in just a few words. Return your answer strictly as a JSON object in the format {"topic": "..."} without any additional commentary or explanation.
2025/10/02 06:53:43 INFO dspy.teleprompt.mipro_optimizer_v2: 6: You are an expert AI system well-versed in advanced language model learning methods and cognitive science concepts. Given a concise technical summary, analyze its content carefully and extract the key topic in a few clear words or phrases that accurately represent the main subject. Respond strictly with a JSON object in the following format: {"topic": "..."}, ensuring the topic captures the core theme of the input summary.
2025/10/02 06:53:43 INFO dspy.teleprompt.mipro_optimizer_v2: 7: 与えられた要約文を読み、その内容の中心となる主題を数語で的確に表現してください。特に、要約文内の技術的な概念や手法、対象領域を考慮しながら、主題を短く明確にまとめてください。最終的に、その主題を日本語で簡潔に示し、JSON形式の{"topic": "..."}で出力してください。
2025/10/02 06:53:43 INFO dspy.teleprompt.mipro_optimizer_v2:
2025/10/02 06:53:43 INFO dspy.teleprompt.mipro_optimizer_v2: ==> STEP 3: FINDING OPTIMAL PROMPT PARAMETERS <==
2025/10/02 06:53:43 INFO dspy.teleprompt.mipro_optimizer_v2: We will evaluate the program over a series of trials with different combinations of instructions and few-shot examples to find the optimal combination using Bayesian Optimization.
2025/10/02 06:53:43 INFO dspy.teleprompt.mipro_optimizer_v2: == Trial 1 / 16 - Full Evaluation of Default Program ==
Average Metric: 10.00 / 10 (100.0%): 100%|██████████| 10/10 [01:13<00:00, 7.34s/it]2025/10/02 06:54:57 INFO dspy.evaluate.evaluate: Average Metric: 10 / 10 (100.0%)
2025/10/02 06:54:57 INFO dspy.teleprompt.mipro_optimizer_v2: Default program score: 100.0
2025/10/02 06:54:57 INFO dspy.teleprompt.mipro_optimizer_v2: == Trial 2 / 16 - Minibatch ==
Average Metric: 6.00 / 6 (100.0%): 100%|██████████| 6/6 [00:04<00:00, 1.33it/s]2025/10/02 06:55:01 INFO dspy.evaluate.evaluate: Average Metric: 6 / 6 (100.0%)
2025/10/02 06:55:01 INFO dspy.teleprompt.mipro_optimizer_v2: Score: 100.0 on minibatch of size 6 with parameters ['Predictor 0: Instruction 1', 'Predictor 0: Few-Shot Set 4'].
2025/10/02 06:55:01 INFO dspy.teleprompt.mipro_optimizer_v2: Minibatch scores so far: [100.0]
2025/10/02 06:55:01 INFO dspy.teleprompt.mipro_optimizer_v2: Full eval scores so far: [100.0]
2025/10/02 06:55:01 INFO dspy.teleprompt.mipro_optimizer_v2: Best full score so far: 100.0
2025/10/02 06:55:01 INFO dspy.teleprompt.mipro_optimizer_v2: =========================================
2025/10/02 06:55:01 INFO dspy.teleprompt.mipro_optimizer_v2: == Trial 3 / 16 - Minibatch ==
Average Metric: 6.00 / 6 (100.0%): 100%|██████████| 6/6 [00:04<00:00, 1.43it/s]2025/10/02 06:55:06 INFO dspy.evaluate.evaluate: Average Metric: 6 / 6 (100.0%)
2025/10/02 06:55:06 INFO dspy.teleprompt.mipro_optimizer_v2: Score: 100.0 on minibatch of size 6 with parameters ['Predictor 0: Instruction 0', 'Predictor 0: Few-Shot Set 2'].
2025/10/02 06:55:06 INFO dspy.teleprompt.mipro_optimizer_v2: Minibatch scores so far: [100.0, 100.0]
2025/10/02 06:55:06 INFO dspy.teleprompt.mipro_optimizer_v2: Full eval scores so far: [100.0]
2025/10/02 06:55:06 INFO dspy.teleprompt.mipro_optimizer_v2: Best full score so far: 100.0
2025/10/02 06:55:06 INFO dspy.teleprompt.mipro_optimizer_v2: =========================================
2025/10/02 06:55:06 INFO dspy.teleprompt.mipro_optimizer_v2: == Trial 4 / 16 - Minibatch ==
Average Metric: 6.00 / 6 (100.0%): 100%|██████████| 6/6 [00:03<00:00, 1.62it/s]2025/10/02 06:55:09 INFO dspy.evaluate.evaluate: Average Metric: 6 / 6 (100.0%)
2025/10/02 06:55:09 INFO dspy.teleprompt.mipro_optimizer_v2: Score: 100.0 on minibatch of size 6 with parameters ['Predictor 0: Instruction 0', 'Predictor 0: Few-Shot Set 4'].
2025/10/02 06:55:09 INFO dspy.teleprompt.mipro_optimizer_v2: Minibatch scores so far: [100.0, 100.0, 100.0]
2025/10/02 06:55:09 INFO dspy.teleprompt.mipro_optimizer_v2: Full eval scores so far: [100.0]
2025/10/02 06:55:09 INFO dspy.teleprompt.mipro_optimizer_v2: Best full score so far: 100.0
2025/10/02 06:55:09 INFO dspy.teleprompt.mipro_optimizer_v2: =========================================
2025/10/02 06:55:09 INFO dspy.teleprompt.mipro_optimizer_v2: == Trial 5 / 16 - Minibatch ==
Average Metric: 5.00 / 6 (83.3%): 100%|██████████| 6/6 [00:03<00:00, 1.62it/s]2025/10/02 06:55:13 INFO dspy.evaluate.evaluate: Average Metric: 5 / 6 (83.3%)
2025/10/02 06:55:13 INFO dspy.teleprompt.mipro_optimizer_v2: Score: 83.33 on minibatch of size 6 with parameters ['Predictor 0: Instruction 0', 'Predictor 0: Few-Shot Set 6'].
2025/10/02 06:55:13 INFO dspy.teleprompt.mipro_optimizer_v2: Minibatch scores so far: [100.0, 100.0, 100.0, 83.33]
2025/10/02 06:55:13 INFO dspy.teleprompt.mipro_optimizer_v2: Full eval scores so far: [100.0]
2025/10/02 06:55:13 INFO dspy.teleprompt.mipro_optimizer_v2: Best full score so far: 100.0
2025/10/02 06:55:13 INFO dspy.teleprompt.mipro_optimizer_v2: =========================================
2025/10/02 06:55:13 INFO dspy.teleprompt.mipro_optimizer_v2: == Trial 6 / 16 - Minibatch ==
Average Metric: 6.00 / 6 (100.0%): 100%|██████████| 6/6 [00:03<00:00, 1.51it/s]2025/10/02 06:55:17 INFO dspy.evaluate.evaluate: Average Metric: 6 / 6 (100.0%)
2025/10/02 06:55:17 INFO dspy.teleprompt.mipro_optimizer_v2: Score: 100.0 on minibatch of size 6 with parameters ['Predictor 0: Instruction 0', 'Predictor 0: Few-Shot Set 3'].
2025/10/02 06:55:17 INFO dspy.teleprompt.mipro_optimizer_v2: Minibatch scores so far: [100.0, 100.0, 100.0, 83.33, 100.0]
2025/10/02 06:55:17 INFO dspy.teleprompt.mipro_optimizer_v2: Full eval scores so far: [100.0]
2025/10/02 06:55:17 INFO dspy.teleprompt.mipro_optimizer_v2: Best full score so far: 100.0
2025/10/02 06:55:17 INFO dspy.teleprompt.mipro_optimizer_v2: =========================================
2025/10/02 06:55:17 INFO dspy.teleprompt.mipro_optimizer_v2: ===== Trial 7 / 16 - Full Evaluation =====
2025/10/02 06:55:17 INFO dspy.teleprompt.mipro_optimizer_v2: Doing full eval on next top averaging program (Avg Score: 100.0) from minibatch trials...
Average Metric: 10.00 / 10 (100.0%): 100%|██████████| 10/10 [00:04<00:00, 2.06it/s]2025/10/02 06:55:22 INFO dspy.evaluate.evaluate: Average Metric: 10 / 10 (100.0%)
2025/10/02 06:55:22 INFO dspy.teleprompt.mipro_optimizer_v2: Full eval scores so far: [100.0, 100.0]
2025/10/02 06:55:22 INFO dspy.teleprompt.mipro_optimizer_v2: Best full score so far: 100.0
2025/10/02 06:55:22 INFO dspy.teleprompt.mipro_optimizer_v2: =======================
2025/10/02 06:55:22 INFO dspy.teleprompt.mipro_optimizer_v2:
2025/10/02 06:55:22 INFO dspy.teleprompt.mipro_optimizer_v2: == Trial 8 / 16 - Minibatch ==
Average Metric: 6.00 / 6 (100.0%): 100%|██████████| 6/6 [00:03<00:00, 1.82it/s]2025/10/02 06:55:26 INFO dspy.evaluate.evaluate: Average Metric: 6 / 6 (100.0%)
2025/10/02 06:55:26 INFO dspy.teleprompt.mipro_optimizer_v2: Score: 100.0 on minibatch of size 6 with parameters ['Predictor 0: Instruction 3', 'Predictor 0: Few-Shot Set 6'].
2025/10/02 06:55:26 INFO dspy.teleprompt.mipro_optimizer_v2: Minibatch scores so far: [100.0, 100.0, 100.0, 83.33, 100.0, 100.0]
2025/10/02 06:55:26 INFO dspy.teleprompt.mipro_optimizer_v2: Full eval scores so far: [100.0, 100.0]
2025/10/02 06:55:26 INFO dspy.teleprompt.mipro_optimizer_v2: Best full score so far: 100.0
2025/10/02 06:55:26 INFO dspy.teleprompt.mipro_optimizer_v2: =========================================
2025/10/02 06:55:26 INFO dspy.teleprompt.mipro_optimizer_v2: == Trial 9 / 16 - Minibatch ==
Average Metric: 6.00 / 6 (100.0%): 100%|██████████| 6/6 [00:04<00:00, 1.47it/s]2025/10/02 06:55:30 INFO dspy.evaluate.evaluate: Average Metric: 6 / 6 (100.0%)
2025/10/02 06:55:30 INFO dspy.teleprompt.mipro_optimizer_v2: Score: 100.0 on minibatch of size 6 with parameters ['Predictor 0: Instruction 6', 'Predictor 0: Few-Shot Set 2'].
2025/10/02 06:55:30 INFO dspy.teleprompt.mipro_optimizer_v2: Minibatch scores so far: [100.0, 100.0, 100.0, 83.33, 100.0, 100.0, 100.0]
2025/10/02 06:55:30 INFO dspy.teleprompt.mipro_optimizer_v2: Full eval scores so far: [100.0, 100.0]
2025/10/02 06:55:30 INFO dspy.teleprompt.mipro_optimizer_v2: Best full score so far: 100.0
2025/10/02 06:55:30 INFO dspy.teleprompt.mipro_optimizer_v2: =========================================
2025/10/02 06:55:30 INFO dspy.teleprompt.mipro_optimizer_v2: == Trial 10 / 16 - Minibatch ==
Average Metric: 6.00 / 6 (100.0%): 100%|██████████| 6/6 [00:03<00:00, 1.59it/s]2025/10/02 06:55:34 INFO dspy.evaluate.evaluate: Average Metric: 6 / 6 (100.0%)
2025/10/02 06:55:34 INFO dspy.teleprompt.mipro_optimizer_v2: Score: 100.0 on minibatch of size 6 with parameters ['Predictor 0: Instruction 1', 'Predictor 0: Few-Shot Set 7'].
2025/10/02 06:55:34 INFO dspy.teleprompt.mipro_optimizer_v2: Minibatch scores so far: [100.0, 100.0, 100.0, 83.33, 100.0, 100.0, 100.0, 100.0]
2025/10/02 06:55:34 INFO dspy.teleprompt.mipro_optimizer_v2: Full eval scores so far: [100.0, 100.0]
2025/10/02 06:55:34 INFO dspy.teleprompt.mipro_optimizer_v2: Best full score so far: 100.0
2025/10/02 06:55:34 INFO dspy.teleprompt.mipro_optimizer_v2: ==========================================
2025/10/02 06:55:34 INFO dspy.teleprompt.mipro_optimizer_v2: == Trial 11 / 16 - Minibatch ==
Average Metric: 6.00 / 6 (100.0%): 100%|██████████| 6/6 [00:04<00:00, 1.24it/s]2025/10/02 06:55:38 INFO dspy.evaluate.evaluate: Average Metric: 6 / 6 (100.0%)
2025/10/02 06:55:38 INFO dspy.teleprompt.mipro_optimizer_v2: Score: 100.0 on minibatch of size 6 with parameters ['Predictor 0: Instruction 4', 'Predictor 0: Few-Shot Set 0'].
2025/10/02 06:55:38 INFO dspy.teleprompt.mipro_optimizer_v2: Minibatch scores so far: [100.0, 100.0, 100.0, 83.33, 100.0, 100.0, 100.0, 100.0, 100.0]
2025/10/02 06:55:38 INFO dspy.teleprompt.mipro_optimizer_v2: Full eval scores so far: [100.0, 100.0]
2025/10/02 06:55:38 INFO dspy.teleprompt.mipro_optimizer_v2: Best full score so far: 100.0
2025/10/02 06:55:38 INFO dspy.teleprompt.mipro_optimizer_v2: ==========================================
2025/10/02 06:55:38 INFO dspy.teleprompt.mipro_optimizer_v2: == Trial 12 / 16 - Minibatch ==
Average Metric: 6.00 / 6 (100.0%): 100%|██████████| 6/6 [00:03<00:00, 1.72it/s]2025/10/02 06:55:42 INFO dspy.evaluate.evaluate: Average Metric: 6 / 6 (100.0%)
2025/10/02 06:55:42 INFO dspy.teleprompt.mipro_optimizer_v2: Score: 100.0 on minibatch of size 6 with parameters ['Predictor 0: Instruction 1', 'Predictor 0: Few-Shot Set 4'].
2025/10/02 06:55:42 INFO dspy.teleprompt.mipro_optimizer_v2: Minibatch scores so far: [100.0, 100.0, 100.0, 83.33, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0]
2025/10/02 06:55:42 INFO dspy.teleprompt.mipro_optimizer_v2: Full eval scores so far: [100.0, 100.0]
2025/10/02 06:55:42 INFO dspy.teleprompt.mipro_optimizer_v2: Best full score so far: 100.0
2025/10/02 06:55:42 INFO dspy.teleprompt.mipro_optimizer_v2: ==========================================
2025/10/02 06:55:42 INFO dspy.teleprompt.mipro_optimizer_v2: ===== Trial 13 / 16 - Full Evaluation =====
2025/10/02 06:55:42 INFO dspy.teleprompt.mipro_optimizer_v2: Doing full eval on next top averaging program (Avg Score: 100.0) from minibatch trials...
Average Metric: 10.00 / 10 (100.0%): 100%|██████████| 10/10 [00:03<00:00, 2.53it/s]2025/10/02 06:55:46 INFO dspy.evaluate.evaluate: Average Metric: 10 / 10 (100.0%)
2025/10/02 06:55:46 INFO dspy.teleprompt.mipro_optimizer_v2: Full eval scores so far: [100.0, 100.0, 100.0]
2025/10/02 06:55:46 INFO dspy.teleprompt.mipro_optimizer_v2: Best full score so far: 100.0
2025/10/02 06:55:46 INFO dspy.teleprompt.mipro_optimizer_v2: =======================
2025/10/02 06:55:46 INFO dspy.teleprompt.mipro_optimizer_v2:
2025/10/02 06:55:46 INFO dspy.teleprompt.mipro_optimizer_v2: == Trial 14 / 16 - Minibatch ==
Average Metric: 6.00 / 6 (100.0%): 100%|██████████| 6/6 [00:04<00:00, 1.22it/s]2025/10/02 06:55:51 INFO dspy.evaluate.evaluate: Average Metric: 6 / 6 (100.0%)
2025/10/02 06:55:51 INFO dspy.teleprompt.mipro_optimizer_v2: Score: 100.0 on minibatch of size 6 with parameters ['Predictor 0: Instruction 2', 'Predictor 0: Few-Shot Set 5'].
2025/10/02 06:55:51 INFO dspy.teleprompt.mipro_optimizer_v2: Minibatch scores so far: [100.0, 100.0, 100.0, 83.33, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0]
2025/10/02 06:55:51 INFO dspy.teleprompt.mipro_optimizer_v2: Full eval scores so far: [100.0, 100.0, 100.0]
2025/10/02 06:55:51 INFO dspy.teleprompt.mipro_optimizer_v2: Best full score so far: 100.0
2025/10/02 06:55:51 INFO dspy.teleprompt.mipro_optimizer_v2: ==========================================
2025/10/02 06:55:51 INFO dspy.teleprompt.mipro_optimizer_v2: == Trial 15 / 16 - Minibatch ==
Average Metric: 6.00 / 6 (100.0%): 100%|██████████| 6/6 [00:03<00:00, 1.68it/s]2025/10/02 06:55:55 INFO dspy.evaluate.evaluate: Average Metric: 6 / 6 (100.0%)
2025/10/02 06:55:55 INFO dspy.teleprompt.mipro_optimizer_v2: Score: 100.0 on minibatch of size 6 with parameters ['Predictor 0: Instruction 5', 'Predictor 0: Few-Shot Set 0'].
2025/10/02 06:55:55 INFO dspy.teleprompt.mipro_optimizer_v2: Minibatch scores so far: [100.0, 100.0, 100.0, 83.33, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0]
2025/10/02 06:55:55 INFO dspy.teleprompt.mipro_optimizer_v2: Full eval scores so far: [100.0, 100.0, 100.0]
2025/10/02 06:55:55 INFO dspy.teleprompt.mipro_optimizer_v2: Best full score so far: 100.0
2025/10/02 06:55:55 INFO dspy.teleprompt.mipro_optimizer_v2: ==========================================
2025/10/02 06:55:55 INFO dspy.teleprompt.mipro_optimizer_v2: ===== Trial 16 / 16 - Full Evaluation =====
2025/10/02 06:55:55 INFO dspy.teleprompt.mipro_optimizer_v2: Doing full eval on next top averaging program (Avg Score: 100.0) from minibatch trials...
Average Metric: 10.00 / 10 (100.0%): 100%|██████████| 10/10 [00:03<00:00, 2.81it/s]2025/10/02 06:55:58 INFO dspy.evaluate.evaluate: Average Metric: 10 / 10 (100.0%)
2025/10/02 06:55:59 INFO dspy.teleprompt.mipro_optimizer_v2: Full eval scores so far: [100.0, 100.0, 100.0, 100.0]
2025/10/02 06:55:59 INFO dspy.teleprompt.mipro_optimizer_v2: Best full score so far: 100.0
2025/10/02 06:55:59 INFO dspy.teleprompt.mipro_optimizer_v2: =======================
2025/10/02 06:55:59 INFO dspy.teleprompt.mipro_optimizer_v2:
2025/10/02 06:55:59 INFO dspy.teleprompt.mipro_optimizer_v2: Returning best identified program with score 100.0!
2025/10/02 06:55:59 INFO mlflow.genai.optimize.optimizers.dspy_mipro_optimizer: Optimization complete! Score remained stable at: 100.0.
2025/10/02 06:55:59 INFO mlflow.genai.optimize.optimizers.dspy_mipro_optimizer: Optimization complete! Score remained stable at: 100.0.
新しいプロンプトURI: prompts:/takaakiyayoi_catalog.agents.topic_prompt/2
最後の行から、主題抽出プロンプトバージョン2が作成されたことがわかります。
新しいプロンプトURI: prompts:/takaakiyayoi_catalog.agents.topic_prompt/2
ちなみに評価ランも作成されています。
プロンプトも比較できます。以前、DSPy触った時には「最適化後のプロンプト、どこで確認できるんだろう」と思っていたのですが、明確に確認できてよかったです。
バージョン2は英語にはなっていますが、非常に構造化されたプロンプトになっていることがわかります。
こう言った形でDSPyとMLflowが連携するんだなーとしみじみ。