Skip to main content

W&B Weave を使った Azure AI Foundry 上での GPT モデル比較

W&B Weave を使って、Azure の管理されたインフラと Weave のカスタマイズ可能な評価ツールを活用しながら、テキスト要約タスクにおける OpenAI の GPT モデルを比較・評価する方法を学びます。この記事は翻訳版です。誤訳の可能性があればコメント欄でお知らせください。
Created on August 26|Last edited on August 26
組織が運用の効率化にますます AI に依存する中で、言語モデルを効果的に比較・評価する能力は極めて重要になっています。研究論文の要約など、特定のユースケースに最適なモデルを選ぶことが求められます。 財務報告書、またはビジネス文書は、効率や成果に大きな影響を与え得ます。対して テキスト要約 説得力のある事例ではあるが、より広い焦点はツールを活用してモデルの性能を体系的に分析・比較することにある。
この記事は、評価と比較を行うためのガイドを提供します 大規模言語モデル(LLM) OpenAI の GPT モデルを使用して Azure AI Foundry、W&B Weave の強力な評価プラットフォームと統合されています。Azure AI Foundry のスケーラブルなインフラと Weave の可視化・解析ツールを組み合わせることで、組織はモデル間の詳細な比較を行い、設定を洗練し、独自の目標や運用要件に合わせてワークフローを最適化できます。


目次



Azure AI Foundryで利用可能なファウンデーションモデル

Azure AI Foundry は、多様なファウンデーションモデルへの包括的なアクセスを提供するプラットフォームです ファウンデーションモデルこれにより、組織は要約やその他の言語タスクを容易に実行できるようになります。 Azure、維持管理の複雑さを解消するマネージドインフラストラクチャの恩恵を受けられます。 AIシステムのスケーリングこれにより、洞察の抽出とワークフローの最適化に注力できるようになります。
プラットフォームは独自モデルとオープンソースモデルの混在をサポートしており、さまざまなユースケースに柔軟に対応できます。Azure のカタログには次のようなプロバイダーによる高度なオプションが含まれています。 OpenAI、Meta、そして Mistral、ならびに Microsoft の独自モデル PHI シリーズモデルこれらのモデルは、対話型AIや要約、ドキュメント処理、高スループットのアプリケーションなど幅広いタスクに最適化されています。複雑な処理で最先端の性能が必要な場合でも、より単純な要件に対してコスト効率の高いソリューションを求める場合でも、Azure の豊富なラインナップは多様な運用ニーズに対応します。
Weights & Biases Weave の高度な評価ツールと組み合わせることで、Azure AI Foundry はモデルの並列比較、パフォーマンス指標の可視化、強みと限界の把握を可能にします。このシームレスな連携により、組織は自分たちの目的やワークフローに最も適したモデルを見極め、情報に基づいた意思決定を行えます。

W&B Weave を使った Azure 上での GPT モデル要約の比較

W&B Weave は、評価中に生成された要約を記録・解析するための強力なプラットフォームを提供し、パフォーマンス比較のための集中ダッシュボードを実現します。この構成により、モデル出力を並べて詳細に比較・分析でき、整合性、関連性、全体的な品質の違いを明確に把握できます。
徹底的な評価を行うために、さまざまな指標を用います。
  • ROUGE生成された要約と参照要約の重要なフレーズや語句の並びの重複を測定します。
  • BERTScore:テキストの文脈埋め込みを比較して意味的類似性を評価します。
  • 圧縮率:生成された要約の簡潔さ(どれだけ要点を絞れているか)を評価します。
  • カバレッジ:要約が重要な内容をどれだけ的確に捉えているかを検証します。
さらに、専門特化した GPT-4o スコアリング手法は、要約に対する定性的な評価を提供することで分析を強化します。この手法では、各出力を1から5のスケールで評価し、正確性、完全性、参照要約との整合性といった要素を考慮します。これらの指標を組み合わせることで、モデル性能を包括的に把握でき、チームは強みを特定し、弱点を改善し、要約のニーズに最適なモデルを選定できるようになります。

ステップ1:Azure AI Foundryを通じたGPTモデルへのアクセス

AzureでGPT-4oやGPT-4o‑miniのようなGPTモデルをセットアップしてデプロイするには、まず次の操作を行います。 Azure AI Foundry Azureの資格情報でログインします。ログインすると、プロジェクトを作成できるダッシュボードが表示されます。

「Create Project」ボタンをクリックして新しいプロジェクトを初期化します。表示されるダイアログでプロジェクト名を入力し、紐づけるハブを選択するか、必要であれば新しいハブを作成します。設定が終わったら「Create」をクリックしてセットアップを完了してください。

プロジェクトを作成したら開き、左側のサイドバーから「Model Catalog」を開いてください。ここで利用可能な各種AIモデルを閲覧・確認できます。
Model Catalogで、Deployment optionsの下にある「Serverless API」を選択してオプションを絞り込みます。これにより、サーバーレスインフラでデプロイ可能なモデルだけが表示されます。表示されたモデル一覧からGPT-4oとGPT-4o‑miniを探してください。

GPT‑4oを選択して詳細ページを開きます。次に「Deploy」をクリックし、デプロイ名(例:「GPT‑4o‑Deployment」)を入力してください。デプロイタイプは「Global Standard」を選択して設定を確定します。同様の手順をGPT‑4o‑miniにも繰り返し、両モデルをデプロイします。

デプロイが完了したら、左側のサイドバーで「Models + Endpoints」セクションに移動します。デプロイ済みのモデルをクリックして詳細を表示し、各モデルのエンドポイントURLとAPIキーをコピーしてください。これらは後でアプリケーションと統合する際に必要になります。

最後のステップとして、次のPythonライブラリをインストールしてください。
pip install openai==1.54.5 arxiv==2.1.3 PyMuPDF==1.24.9 weave==0.51.18 fitz==0.0.1.dev2 bert-score==0.3.13 rouge-score==0.1.2
この時点で、GPT‑4o と GPT‑4o‑mini の両方が Azure 上に正常にデプロイされ、API エンドポイント経由でアクセスできる準備が整っています。さあ、コードを書き始めましょう!

ステップ2:複数のGPTモデルで要約を評価するためのデータセット生成

GPT‑4o と GPT‑4o‑mini のテキスト要約能力を評価するため、元のアブストラクトを除いた研究論文からアブストラクトを正確に生成できるかをテストしてベンチマークを行います。この手法により、各論文の本文から重要な情報を簡潔かつ関連性の高い要約としてどれだけ効果的に抽出できるかを比較できます。
これはモデルの要約能力を評価するために有効なテストです。なぜなら、人間が複雑な情報を要約するときに直面する課題—論文の主要な目的、手法、結果を簡潔で一貫したアブストラクトに凝縮する作業—を模しているからです。アブストラクトを除外することで、モデルが独力で論文の最も重要な点を特定し伝達できるかどうかを評価できます。これは、モデルが学術的な内容を構造的かつ簡潔に処理・評価・要約する、人間に近い能力を持っているかを示す指標になります。この設定により、情報を正確に捉える能力だけでなく、人間の専門家のようにそれを簡潔に整理する技能も評価できます。
まずは、モデルで推論を実行する方法を示す基本的なスクリプトを共有します。
import weave
import os
from openai import AzureOpenAI
import json

# Initialize Weave for logging
weave.init('azure-api')

# Initialize the AzureOpenAI client
client = AzureOpenAI(
azure_endpoint="your enpoint url",
api_key="your key",
api_version="2024-09-01-preview"
)

@weave.op
def run_inference(prompt, client):
"""
Function to perform inference using the provided client and prompt.
"""
try:
response = client.chat.completions.create(
model="gpt-4o",
messages=[
{"role": "user", "content": prompt}
]
)
# Parse the response
response_json = json.loads(response.model_dump_json(indent=2))
choices = response_json.get("choices", [])
if choices:
content = choices[0].get("message", {}).get("content", "")
print("Generated Content:")
print(content)
return content
else:
print("No content found in response")
return None
except Exception as e:
print(f"Failed to get response: {e}")
return None

# Define the prompt and perform inference
PROMPT = "What steps should I think about when writing my first Python API?"
run_inference(PROMPT, client)
ここでは、Weaveを使ってモデルの入力と出力を追跡する方法も紹介します。これにより、使用方法を示すことができます。 Weave の Traces コンポーネント後ほど、使い方を実演します Weave Evaluationsの評価機能 これは同じデータセットでモデルを比較するために特別に設計されています。
ベンチマーク用データセットを作成するために、まず arXiv から AI と機械学習に関する論文を収集します。各論文からは通常アブストラクトが掲載されている最初のページのみを抽出し、GPT‑4o を使ってその部分を特定して JSON オブジェクトとして構造化します。抽出したアブストラクトは「ゴールドスタンダード」の参照データとして扱い、読み込みやすく一貫した評価ができるよう JSONL 形式のファイルに保存します。
このファイル形式により、GPT‑4o モデルを評価する際の要約の読み込みと処理が容易になり、参照データのバージョン管理や共有も簡単に行えます。以下は論文をダウンロードし、各論文の最初のページから GPT‑4o を使ってアブストラクトを抽出するコードです。
import os
import arxiv
import fitz # PyMuPDF
import json
from openai import AzureOpenAI
import weave
import re
from time import sleep

# Initialize Weave for logging
weave.init('azure_paper_abstract_gen')

# Set up Azure OpenAI
os.environ["AZURE_OPENAI_ENDPOINT"] = "your endpoint url"
os.environ["AZURE_OPENAI_API_KEY"] = "your api key"

client = AzureOpenAI(
azure_endpoint=os.getenv("AZURE_OPENAI_ENDPOINT"),
api_key=os.getenv("AZURE_OPENAI_API_KEY"),
api_version="2024-09-01-preview"
)

# Directory to save downloaded papers
download_dir = "arxiv_papers"
os.makedirs(download_dir, exist_ok=True)

# Define AI-specific search queries
search_queries = [
"Large Language Models for vision tasks AND cat:cs.AI",
"Multimodal AI techniques AND cat:cs.CV",
"Applications of Transformers in healthcare AI AND cat:cs.LG",
"Few-shot learning in AI and ML AND cat:cs.LG",
"Vision and language models integration AND cat:cs.CV",
"Domain-specific fine-tuning for ML models AND cat:cs.LG",
"Foundational models in AI and CV applications AND cat:cs.AI",
"NLP in robotics and vision systems AND cat:cs.AI",
"Bias and fairness in AI for CV AND cat:cs.CV",
"Evaluation metrics for multimodal AI AND cat:cs.LG"
]

def download_papers(max_pages=15, max_attempts_per_query=20):
"""Download one suitable paper for each query, retrying if papers exceed page limit."""
papers = []
downloaded_titles = set()
client = arxiv.Client()

for query in search_queries:
paper_found = False
attempt = 0
while not paper_found and attempt < max_attempts_per_query:
search = arxiv.Search(
query=query,
max_results=100,
sort_by=arxiv.SortCriterion.SubmittedDate
)
try:
results = list(client.results(search))
start_idx = attempt * 5
end_idx = start_idx + 5
current_batch = results[start_idx:end_idx]
for result in current_batch:
if result.title not in downloaded_titles:
print(f"Downloading: {result.title}")
paper_id = result.entry_id.split('/')[-1]
pdf_filename = f"{paper_id}.pdf"
pdf_path = os.path.join(download_dir, pdf_filename)
result.download_pdf(dirpath=download_dir, filename=pdf_filename)
try:
with fitz.open(pdf_path) as pdf:
if pdf.page_count <= max_pages:
papers.append({
"title": result.title,
"file_path": pdf_path,
"arxiv_id": paper_id
})
downloaded_titles.add(result.title)
print(f"Accepted: {result.title}")
paper_found = True
break
else:
os.remove(pdf_path)
print(f"Skipped (too many pages: {pdf.page_count}): {result.title}")
except Exception as e:
print(f"Error checking PDF {pdf_path}: {e}")
if os.path.exists(pdf_path):
os.remove(pdf_path)
attempt += 1
if not paper_found:
print(f"Attempt {attempt}/{max_attempts_per_query} for query: {query}")
sleep(3)
except Exception as e:
print(f"Error during download: {e}")
sleep(3)
attempt += 1
continue
if not paper_found:
print(f"Failed to find suitable paper for query after {max_attempts_per_query} attempts: {query}")

print(f"\nSuccessfully downloaded {len(papers)} papers")
return papers

def extract_first_page_text(pdf_path):
"""Extract text from only the first page of the PDF."""
with fitz.open(pdf_path) as pdf:
if pdf.page_count > 0:
page = pdf[0]
return page.get_text()
return ""

@weave.op
def extract_abstract_with_azure(text, title):
"""Extract abstract using Azure GPT-4o with JSON output."""
try:
response = client.chat.completions.create(
model="gpt-4o",
messages=[
{"role": "system", "content": "You are a research paper analysis assistant. Extract ONLY the abstract section from the paper content provided. Return the result in JSON format with 'abstract' as the key. If you cannot find the abstract, return an empty string as the value."},
{"role": "user", "content": f"Paper title: {title}\n\nPaper content:\n\n{text}"}
],
response_format={"type": "json_object"}
)
content = response.choices[0].message.content
return json.loads(content)
except Exception as e:
print(f"Error extracting abstract for {title}: {e}")
sleep(3)
return {"abstract": ""}

def count_words(text):
"""Count words excluding punctuation and special characters."""
cleaned_text = re.sub(r'[^\w\s]', ' ', text.lower())
words = [word for word in cleaned_text.split() if word.strip()]
return len(words)

def main():
# Download papers
papers = download_papers()
print(f"\nDownloaded {len(papers)} papers. Processing abstracts...\n")
# Process papers and extract abstracts
paper_data = []
for paper in papers:
title = paper["title"]
pdf_path = paper["file_path"]
print(f"Processing: {title}")
first_page_text = extract_first_page_text(pdf_path)
abstract_json = extract_abstract_with_azure(first_page_text, title)
abstract_text = abstract_json.get('abstract', '')
word_count = count_words(abstract_text)
paper_data.append({
"title": title,
"file_path": pdf_path,
"abstract": abstract_text,
"word_count": word_count,
"arxiv_id": paper["arxiv_id"]
})
sleep(2)

# Save to JSONL file
output_file = "paper_abstracts.jsonl"
with open(output_file, "w") as f:
for entry in paper_data:
json.dump(entry, f)
f.write("\n")

print(f"\nProcessed {len(paper_data)} papers. Results saved to {output_file}")

if __name__ == "__main__":
main()
このスクリプトは Azure の GPT‑4o モデルを評価するための参照要約データセットを作成します。元のアブストラクトは arXiv から取得した AI 研究論文から直接抽出しており、一貫性のある信頼できるゴールドデータとして評価の基準になります。これらのアブストラクトは JSONL 形式で保存され、比較用のベンチマークとして利用されます。
このプロセスでは、研究論文をダウンロードし、各PDFから本文ではなくアブストラクト部分のみを抽出して構造化された形式で整理します。こうして構造化されたデータセットを作成することで、GPT‑4o モデルの性能を評価するための信頼性が高く標準化された基準を確保します。このゴールドデータセットを用意した上で、GPT‑4o モデルによる要約を元のアブストラクトと比較し、要約性能を包括的に評価します。

Weave Evaluations を使ったモデル評価

Azure AI Foundry 上の GPT‑4o モデルのテキスト要約能力を評価するために、複数の指標を用いて包括的に分析します。これらの指標は、従来のテキスト類似度指標、ニューラルな意味的類似度、そして LLM ベースの採点システムを組み合わせ、性能を効果的に評価できるように設計されています。
GPT‑4o を自動評価者として用い、生成された要約が目的、手法、結果といった主要要素をどれだけ適切に捉えているかに基づき、1〜5 のスケールで評価します。ニューラルな意味的類似度の評価には BERTScore を使って文脈の整合性を判定し、ROUGE スコアで語彙的・構造的な重なりを測定します。さらに、カバレッジや圧縮率といった指標を追加して、情報の保持度や要約の簡潔さを評価します。
設定を行うことをお勧めします WEAVE_PARALLELISM 評価コードを実行する前に環境変数を低い値に設定してください。これは次のコマンドで行えます。 export WEAVE_PARALLELISM=1円滑な実行を確保します。これらの指標は Weave の評価ダッシュボードで可視化され、性能を多次元的に把握するとともに改善点を明示します。以下は評価に使用するコードです:
import weave
from weave import Model
import json
from time import sleep
import asyncio
from rouge_score.rouge_scorer import RougeScorer
from typing import Dict, Any
import bert_score
import fitz
from weave.trace.box import unbox
import time
from openai import AzureOpenAI
import time
import json

from weave import Scorer
import json


# Initialize Weave
weave.init('azure_abstract_eval')


gpt4o_client = AzureOpenAI(
azure_endpoint="https://<your-resource-name>.openai.azure.com/openai/deployments/<gpt-4o-deployment-name>/chat/completions?api-version=2024-08-01-preview",
api_key="<your-api-key>",
api_version="2024-08-01-preview"
)

gpt4o_mini_client = AzureOpenAI(
azure_endpoint="https://<your-resource-name>.openai.azure.com/openai/deployments/<gpt-4o-mini-deployment-name>/chat/completions?api-version=2024-08-01-preview",
api_key="<your-api-key>",
api_version="2024-08-01-preview"
)

def create_prediction_prompt(text, title, target_length):
"""Create a prompt for abstract generation with target length."""
return (
f"You are tasked with generating an abstract for a research paper titled '{title}'. "
f"The abstract should be approximately {target_length} words long.\n\n"
f"Generate an abstract that summarizes the key points of the paper, including the "
f"research objective, methodology, and main findings. The abstract should be "
f"self-contained and clearly communicate the paper's contribution. Respond only with the ABSTRACT, and NOT the title\n\n"
f"Paper content:\n\n{text}"
f"Respond only with the ABSTRACT!"
)

def create_evaluation_prompt(gt_abstract: str, generated_abstract: str) -> str:
"""Create standardized evaluation prompt."""
return f'''You are evaluating how well a generated abstract captures the information from a ground truth abstract.

Ground Truth Abstract:
{gt_abstract}

Generated Abstract:
{generated_abstract}

Rate the generated abstract on a scale from 1-5, where:
1: Poor - Missing most key information or seriously misrepresenting the research
2: Fair - Captures some information but misses crucial elements
3: Good - Captures most key points but has some gaps or inaccuracies
4: Very Good - Accurately captures nearly all key information with minor omissions
5: Excellent - Perfectly captures all key information and maintains accuracy

Respond ONLY with a JSON object containing a single "score" field with an integer value from 1-5.
Example response format:
{{"score": 4}}'''


def extract_text_after_page_one(pdf_path: str) -> str:
"""Extract text from page 2 onwards."""
if isinstance(pdf_path, weave.trace.box.BoxedStr):
pdf_path = unbox(pdf_path)
text = ""
try:
with fitz.open(pdf_path) as pdf:
if pdf.page_count > 1:
for page_num in range(1, pdf.page_count): # Start from page 2
page = pdf[page_num]
text += page.get_text()
except Exception as e:
print(f"Error extracting text from PDF {pdf_path}: {e}")
return text


def run_inference(client: AzureOpenAI, model: str, prompt: str, max_retries: int = 10, base_wait: int = 10) -> str:
"""
Function to perform inference using specified Azure model with exponential backoff retry.
Args:
client: AzureOpenAI client
model: Model name/id
prompt: Input prompt
max_retries: Maximum number of retry attempts (default: 10)
base_wait: Initial wait time in seconds (default: 10)
"""
for attempt in range(max_retries):
try:
response = client.chat.completions.create(
model=model,
messages=[
{"role": "system", "content": "You are a research paper abstract writer. Write clear, concise, and informative abstracts."},
{"role": "user", "content": prompt}
],
temperature=0.0
)
response_json = json.loads(response.model_dump_json(indent=2))
choices = response_json.get("choices", [])
if choices:
content = choices[0].get("message", {}).get("content", "")
return content
else:
print("No content found in response")
except Exception as e:
wait_time = base_wait * (2 ** attempt) # Exponential backoff
print(f"Attempt {attempt + 1}/{max_retries} failed: {e}")
print(f"Waiting {wait_time} seconds before retrying...")
time.sleep(wait_time)
continue
print(f"Failed to get response after {max_retries} retries")
return None




class GPT4o(Model):
@weave.op
def predict(self, title: str, pdf_path: str, word_count: int) -> dict:
"""Predict abstract using GPT-4O."""
paper_text = extract_text_after_page_one(pdf_path)
prompt = create_prediction_prompt(title, paper_text, word_count)
prediction = run_inference("gpt-4o-2024-08-06", prompt)
return {"model_output": prediction}

class GPT4oMini(Model):
@weave.op
def predict(self, title: str, pdf_path: str, word_count: int) -> dict:
"""Predict abstract using GPT-4O-mini."""
paper_text = extract_text_after_page_one(pdf_path)
prompt = create_prediction_prompt(title, paper_text, word_count)
prediction = run_inference("gpt-4o-mini", prompt)
return {"model_output": prediction}

@weave.op
def bert_scorer(gt_abstract: str, model_output: dict) -> Dict[str, float]:
"""Calculate BERTScore for the abstract."""
if not model_output or 'model_output' not in model_output:
return {'bert_score': 0.0}
try:
P, R, F1 = bert_score.score(
[model_output['model_output']],
[gt_abstract],
lang='en',
model_type='microsoft/deberta-xlarge-mnli'
)
return {'bert_score': float(F1.mean())}
except Exception as e:
print(f"Error calculating BERTScore: {e}")
return {'bert_score': 0.0}


# you can also use the "function" format for your scorer
# @weave.op
# def GPT4oScorer(gt_abstract: str, model_output: dict) -> dict:
# """Evaluate abstract using GPT-4o."""
# if not model_output or 'model_output' not in model_output:
# return {'gpt4o_score': 0.0}
# try:
# prompt = create_evaluation_prompt(gt_abstract, model_output["model_output"])
# response = run_inference(gpt4o_client, "gpt-4o", prompt)
# if response:
# # Clean the response text
# response_text = response.strip()
# # Remove any additional text before or after the JSON
# response_text = response_text.split('{')[1].split('}')[0]
# response_text = '{' + response_text + '}'
# try:
# result = json.loads(response_text)
# if 'score' in result and isinstance(result['score'], (int, float)):
# score = float(result['score'])
# if 1 <= score <= 5:
# return {'gpt4o_score': score}
# except json.JSONDecodeError:
# print(f"Invalid JSON response: {response_text}")
# print("Using default score due to invalid response")
# return {'gpt4o_score': 0.0}
# except Exception as e:
# print(f"Error in GPT-4o evaluation: {e}")
# return {'gpt4o_score': 0.0}


class GPT4oScorer(Scorer):
model_id: str = "gpt-4o"
system_prompt: str = "You are evaluating how well a generated abstract captures the information from a ground truth abstract."
@weave.op
def create_evaluation_prompt(self, gt_abstract: str, generated_abstract: str) -> str:
"""Create standardized evaluation prompt."""
return f'''Ground Truth Abstract:
{gt_abstract}

Generated Abstract:
{generated_abstract}

Rate the generated abstract on a scale from 1-5, where:
1: Poor - Missing most key information or seriously misrepresenting the research
2: Fair - Captures some information but misses crucial elements
3: Good - Captures most key points but has some gaps or inaccuracies
4: Very Good - Accurately captures nearly all key information with minor omissions
5: Excellent - Perfectly captures all key information and maintains accuracy

Respond ONLY with a JSON object containing a single "score" field with an integer value from 1-5.
Example response format:
{{"score": 4}}'''

@weave.op
def call_llm(self, gt_abstract: str, model_output: str) -> dict:
"""Call GPT-4o for evaluation."""
try:
prompt = self.create_evaluation_prompt(gt_abstract, model_output)
response = run_inference(gpt4o_client, self.model_id, prompt)
if response:
# Clean the response text
response_text = response.strip()
# Remove any additional text before or after the JSON
response_text = response_text.split('{')[1].split('}')[0]
response_text = '{' + response_text + '}'
try:
result = json.loads(response_text)
if 'score' in result and isinstance(result['score'], (int, float)):
score = float(result['score'])
if 1 <= score <= 5:
return {'gpt4o_score': score}
except json.JSONDecodeError:
print(f"Invalid JSON response: {response_text}")
print("Using default score due to invalid response")
return {'gpt4o_score': 0.0}
except Exception as e:
print(f"Error in GPT-4o evaluation: {e}")
return {'gpt4o_score': 0.0}

@weave.op
def score(self, model_output: dict, gt_abstract: str) -> dict:
"""Score the generated abstract against the ground truth.
Args:
model_output: Dictionary containing the generated abstract under 'model_output' key
gt_abstract: The ground truth abstract to compare against
"""
if not model_output or 'model_output' not in model_output:
return {'gpt4o_score': 0.0}
return self.call_llm(gt_abstract, model_output['model_output'])

@weave.op
def rouge_scorer(gt_abstract: str, model_output: dict) -> Dict[str, float]:
"""Calculate ROUGE scores for the abstract."""
if not model_output or 'model_output' not in model_output:
return {
'rouge1_f': 0.0,
'rouge2_f': 0.0,
'rougeL_f': 0.0
}
try:
scorer = RougeScorer(['rouge1', 'rouge2', 'rougeL'], use_stemmer=True)
scores = scorer.score(gt_abstract, model_output['model_output'])
return {
'rouge1_f': float(scores['rouge1'].fmeasure),
'rouge2_f': float(scores['rouge2'].fmeasure),
'rougeL_f': float(scores['rougeL'].fmeasure)
}
except Exception as e:
print(f"Error calculating ROUGE scores: {e}")
return {
'rouge1_f': 0.0,
'rouge2_f': 0.0,
'rougeL_f': 0.0
}

@weave.op
def compression_scorer(gt_abstract: str, model_output: dict) -> Dict[str, float]:
"""Calculate compression ratio of the abstract."""
if not model_output or 'model_output' not in model_output:
return {'compression_ratio': 0.0}
try:
gt_words = len(gt_abstract.split())
generated_words = len(model_output['model_output'].split())
compression_ratio = min(gt_words, generated_words) / max(gt_words, generated_words)
return {'compression_ratio': float(compression_ratio)}
except Exception as e:
print(f"Error calculating compression ratio: {e}")
return {'compression_ratio': 0.0}

@weave.op
def coverage_scorer(gt_abstract: str, model_output: dict) -> Dict[str, float]:
"""Calculate content coverage using word overlap."""
if not model_output or 'model_output' not in model_output:
return {'coverage_score': 0.0}
try:
gt_words = set(gt_abstract.lower().split())
generated_words = set(model_output['model_output'].lower().split())
intersection = len(gt_words.intersection(generated_words))
union = len(gt_words.union(generated_words))
coverage_score = intersection / union if union > 0 else 0.0
return {'coverage_score': float(coverage_score)}
except Exception as e:
print(f"Error calculating coverage score: {e}")
return {'coverage_score': 0.0}


def create_evaluation_dataset(gt_file: str):
"""Create dataset from ground truth file."""
dataset = []
with open(gt_file, 'r') as f:
for line in f:
entry = json.loads(line)
dataset.append({
"title": entry["title"],
"gt_abstract": entry["abstract"],
"pdf_path": entry["file_path"],
"word_count": entry["word_count"]
})
return dataset


async def run_evaluations(gt_file: str):
"""Run evaluations for each model."""
eval_dataset = create_evaluation_dataset(gt_file)
# Initialize models
models = {
"gpt4o": GPT4o(),
"gpt4o_mini": GPT4oMini()
}

gpt_scorer = GPT4oScorer()
# Setup scorers
scorers = [
gpt_scorer, # class based scorer
rouge_scorer,
compression_scorer,
coverage_scorer,
bert_scorer
]
# Run evaluations
results = {}
for model_name, model in models.items():
print(f"\nEvaluating {model_name}...")
evaluation = weave.Evaluation(
dataset=eval_dataset,
scorers=scorers,
name=model_name + " Eval"
)
results[model_name] = await evaluation.evaluate(model)
# Print results
print("\nEvaluation Results:")
for model_name, result in results.items():
print(f"\n{model_name} Results:")
print(json.dumps(result, indent=2))
# Save results to file
output_file = "gpt4o_evaluation_results.json"
with open(output_file, 'w') as f:
json.dump(results, f, indent=2)
print(f"\nResults saved to {output_file}")
return results

if __name__ == "__main__":
gt_file = "paper_abstracts.jsonl"
asyncio.run(run_evaluations(gt_file))
我々の評価では、Weave の堅牢なフレームワークを活用して、Azure の GPT‑4o モデルが生成した要約と参照アブストラクトを体系的に比較します。既に生成された出力に着目することで、追加の推論コストをかけずに繰り返し評価できる効率的なワークフローを実現しています。この設計によりデバッグが容易になり、指標の反復的な改善が促進され、生成要約の評価における一貫性が確保されます。
モデルの性能を区別するために、2つの異なるクラスを定義します。 GPT4o および GPT4oMini これらはそれぞれの構成に合わせて調整され、Weave の評価ダッシュボード内で別々のエンティティとして表示されます。これにより、出力を並べて比較・分析する際の明確さと正確さが確保されます。

包括的な評価指標

評価では、モデルの性能を総合的に把握するために複数の指標を導入しています。
  • ROUGE 捉える N-グラム および生成された要約と参照要約とのシーケンス重複。
  • カバレッジ:生成された要約が元の要旨から重要な内容をどれだけ保持しているかを測定します。
  • 圧縮率:要約の簡潔さと詳細保持のトレードオフを評価します。
  • BERTScore:テキストの文脈埋め込みを比較して意味的類似性を評価します。
  • LLMジャッジGPT-4o を用いた要約の整合性・正確性・完全性を評価するカスタムスコアリング手法
語彙的・意味的・構造的評価を組み合わせることで、このフレームワークは各モデルの強みと弱点を詳しく評価します。

カスタムスコアリング統合

評価を強化するため、カスタムのLLMジャッジスコアラーを開発し、GPT‑4oがゴールドスタンダードの要約との整合性に基づいて自身の出力を評価できるようにしました。Weaveのパイプラインにシームレスに統合されたこのスコアリング手法は、データセット全体での自動ログ記録と比較を可能にし、反復的なモデル分析に不可欠なものとなっています。カスタムクラスは複雑なワークフローに柔軟性を与えますが、基本的なスコアリング関数はより単純なシナリオでも利用でき、多様なニーズに対応します。

Weaveによる直感的な可視化

Weaveのインタラクティブなダッシュボードは分析を簡素化し、評価結果の詳細な可視化を提供します。チームは直感的なインターフェースでモデルの出力、性能指標、比較結果を確認でき、改善点を明確に特定して実務的な意思決定に活用できます。
この構造化された評価、カスタムスコアリング手法、および洞察に富んだ可視化を組み合わせることで、Weaveは組織がGPTモデルを効果的に分析・改善できることを実証します。定量的厳密さと使いやすさを両立させることで、Weaveはさまざまなユースケースにおけるモデル性能最適化のための重要な枠組みを提供します。


ここでは、GPT‑4o がいくつかの主要指標で GPT‑4o‑mini をわずかに上回っていることが確認されます。特に LLM ジャッジスコア、ROUGE‑L、ROUGE‑1、圧縮率、BERTScore で優位でした。GPT‑4o は参照要約との整合性が高く、構造やフレーズレベルの類似性をより多く捉え、簡潔さと情報保持のバランスが良好です。これらの結果は、意味的に正確で構成の整った出力を生成する上での有効性を示しています。
一方で、GPT‑4o‑mini は効率性と詳細保持の面で利点があります。入力の詳細をよりよく保持していることを示す高いカバレッジスコアを維持し、推論レイテンシが大幅に低いため速度やリソース効率が重要な用途により適しています。
Weave Evaluations は、モデルが得意な点や弱点を明らかにし、これらの違いが実務上の意思決定にどのように影響するかを示すうえで非常に有用であることを実証しています。指標と出力の両面で詳細な並列比較を可能にすることで、Weave は組織が性能と効率の目標に最も合致するモデルを特定するための実践的な枠組みを提供します。
この種の分析は、モデル間のトレードオフを理解するうえで不可欠であり、組織がAI投資を最適化するために役立ちます。Weave が定量的・定性的な比較の両方を提供できることで、MLエンジニアは単なる指標にとどまらず運用面での適合性に注目して、特定のユースケースに最も適したモデルを選択できます。以下は比較ビューのスクリーンショットです。

なぜ Azure AI を選ぶのか

Azure AI は取り組みやすい堅牢なプラットフォームを提供します 大規模言語モデル多様なタスク向けに設計されたさまざまなモデルへのアクセスを提供します。このバラエティにより、各ユースケースの要件に最も適したモデルを選択できます。Microsoft Azure のエコシステムとシームレスに統合されるため、デプロイやデータ管理が容易になり、生産性と運用効率が向上します。
Azure のスケーラビリティにより、モデルのデプロイは変動する需要に応じて容易に調整でき、さまざまなワークロードで最適なパフォーマンスを発揮します。プラットフォームはセキュリティとコンプライアンスを重視しており、Microsoft の厳格な基準に準拠した強力なデータ保護対策を実装することで機密情報の安全性を確保します。Azure の高性能クラウド基盤に支えられたこのプラットフォームは、信頼性が高く効率的なモデル運用を保証し、幅広い用途にわたって一貫して高品質な結果を提供します。

Azure AI と W&B Weave を使ったパフォーマンス評価

Azure AI と W&B Weave を活用して、GPT-4o と GPT-4o-mini を重要な指標(LLM ベースのジャッジスコアを含む)で評価しました。結果は、GPT-4o が正確で簡潔な要約の生成に優れており、ROUGE‑L、ROUGE‑1、圧縮率、ならびに LLM ジャッジスコアといった指標で GPT-4o-mini を上回ることを示しています。
一方で、GPT-4o‑mini は効率性に優れており、推論時間が短く、入力の重要な詳細を保持する能力を示す高いカバレッジスコアを達成しています。そのため、処理速度が重要な用途やリソース制約のあるアプリケーションにとって非常に有効な選択肢です。
Azure のスケーラブルな基盤と Weave の高度な評価ツールを組み合わせることで、速度、精度、総合的な効率といった優先事項に応じて最適なモデルを選択できる知見が得られます。