
はじめに
カミナシの認証認可チームのmanaty(@manaty226)です。今年もラスベガスにて12月1日から12月5日まで開催されているre:Inventに参加しています。この記事では、4日目に参加した以下のワークショップセッションについて記載します。
- Automating LLM evaluation at scale: AIOps for continuous improvement (AIM405)
基盤モデルの選択からファインチューニングと評価
このワークショップでは、Amazon SageMakerシリーズを使って基盤モデルのデプロイ、ファインチューニング、評価を行うものでした。また、Bedrockガードレールを使ったLLMからの回答フィルタリングも実施しました。

まず、どういった基盤モデルをデプロイするか選択する必要があります。モデルの選択には、パラメータサイズ、ベンチマークや実環境でのパフォーマンススコア、ライセンス、タスクの種類などを考慮する必要があるようです。ワークショップではQwen/Qwen3-4B-Instruct-2507というモデルを選択しました。
Qwen/Qwen3-4B-Instruct-2507 · Hugging Face
モデルのイメージをダウンロードした後、以下のようなコードでSageMaker AIにデプロイします。
SageMaker AIにデプロイされたモデルは、AWS上で動作してリモートから呼び出すことができるようになるようです。10分ほど待つとデプロイが完了します。
model_name = "Qwen3-4B-Instruct-2507" lmi_model = sagemaker.Model( image_uri=inference_image_uri, env=inference_llm_config, role=role, name=model_name ) from sagemaker.utils import name_from_base endpoint_name = f"{model_name}-endpoint" BASE_ENDPOINT_NAME = name_from_base(endpoint_name) predictor = lmi_model.deploy( initial_instance_count=1, instance_type="ml.g5.2xlarge", endpoint_name=BASE_ENDPOINT_NAME )
デプロイしたモデルを使って、プロンプトを投げてみた結果が下図です。

まず、sagemaker.Predictorのインスタンス生成でデプロイ先のエンドポイントとセッション情報、モデルの入出力に合わせたデータ形式に変換するためのシリアライザとデシリアライザを設定します。その後、predict()メソッドを使って予め用意したプロンプトをリクエストして、デプロイしたモデルに推論させるという流れのようです。レスポンスとして帰ってきた結果を取り出したのが図中のコード下の文章です。
Predictors — sagemaker 2.254.1 documentation
SageMaker AI Trainingによるカスタマイズ
基盤モデルを利用することができるようになった次は、基盤モデルを特定のユースケースに特化させるようにカスタマイズします。こうすることで、自分たちのビジネス領域やアプリケーションで利用される用語やニュアンスを汲み取ることができるようになり、元の基盤モデルよりも性能を高くなるようです。ワークショップでは、医療推論用のデータセットを使ってファインチューニングを試みました。
FreedomIntelligence/medical-o1-reasoning-SFT · Datasets at Hugging Face
下図に、SageMakerを使ってファインチューニングする際のおおまかなシステム構成を示します。まず、SageMaker control planeはトレーニングとリソースを管理して、ユーザーからのトレーニングリクエストを受け付けるサービスです。ECRにはトレーニング用のコンテナイメージを格納し、イメージをコンピューティングインスタンスにデプロイして学習を実行します。S3にトレーニング中の入力データとモデル成果物を格納しつつ、CloudWatchでログとメトリクスを管理して学習の状況確認ができるようです。基盤モデルのファインチューニングをAWSサービスで完結して実行できることを知らなかったので驚きでした。

SageMakerのPythonライブラリからModelTrainerと呼ばれる、モデルの学習に利用するクラスを呼び出して実行します。イメージは下のような形式です。
from sagemaker.training import ModelTrainer trainer = ModelTrainer( training_image="...", # コンテナイメージのURI instance_count=1, # インスタンス数 instance_type="ml.m5.xlarge", # インスタンスタイプ source_dir="src", # 学習スクリプトのディレクトリ entry_point="train.py", # 実行するスクリプト hyperparameters={"epochs": 10} # ハイパーパラメータ ) # 学習の実行 trainer.train()
今回はワークショップで時間に限りがあるため、学習セットも小さいものを利用して10分ほどで完了しました。ファインチューニングしたモデルに先ほどと同じプロンプトを実行した結果が以下です。1つのプロンプトに対する回答を人間が読んで、ファインチューニングの結果がどうであったか判別することは困難なため、ここからワークショップは基盤モデルの評価に移ります。

基盤モデルの評価
基盤モデルの評価観点としては、あるタスク実行のパフォーマンスだけでなく、公平性やバイアス、汎化性能、透明性や説明責任といった様々な観点があるようです。本ワークショップでは、Hugging Faceが開発したLightevalというオープンソースのツールを利用して評価しました。
https://github.com/huggingface/lighteval
特に、ROUGEと呼ばれる、ある質問に対する人間の回答とどの程度似ているかを検証する手法を利用して評価しています。ここで評価しているのは以下の3つです。
ROUGE-1
文章中の単語がどの程度重なっているかを比較する。いわゆるUnigramと呼ばれるもの。
ROUGE-2
連続する二単語がどの程度重なっているかを比較する。いわゆるBigramと呼ばれるもの。
ROUGE-L
最長共通部分列を計算する。
3つの指標で評価した結果が以下のグラフと表です。青色が元の基盤モデル、オレンジ色がファインチューニングした基盤モデルです。いずれの評価方式においても、オレンジ色の基盤モデルの性能が向上していることがわかると思います。今回は時間の都合上それほど学習量を増やすことができませんでしたが、もっと学習させるとさらに精度が向上するとのことでした。


ガードレールの設定
ここまでは基盤モデル自体の性能をあげていくことに取り組んできました。一方で、実アプリケーションの世界においては、安全上絶対に回答してはいけないことや、個人情報のような回答中でも隠さなければならない情報が存在します。Amazon Bedrock Guardrailsは、ユーザーのプロンプトや基盤モデルの出力を評価して、回答に制限を加えたり情報のマスキングを行うサービスです。

ワークショップの例では、下記のようなユーザーが質問したトピックに対する制限や、
# Topic-based restrictions (e.g., denying non-medical advice) topicPolicyConfig={ 'topicsConfig': [ {'name': 'non-medical-advice', 'definition': 'Any recommendations outside medical expertise or context', 'type': 'DENY'}, {'name': 'misinformation', 'definition': 'Dissemination of inaccurate or unverified medical information', 'type': 'DENY'}, {'name': 'medical-cure-claims', 'definition': 'Claims of guaranteed or definitive cures for medical conditions without sufficient evidence', 'type': 'DENY'} ] },
コンテンツポリシーの設定
contentPolicyConfig={
'filtersConfig': [
{'type': 'HATE', 'inputStrength': 'HIGH', 'outputStrength': 'HIGH'},
{'type': 'INSULTS', 'inputStrength': 'HIGH', 'outputStrength': 'HIGH'},
{'type': 'SEXUAL', 'inputStrength': 'HIGH', 'outputStrength': 'HIGH'},
{'type': 'VIOLENCE', 'inputStrength': 'HIGH', 'outputStrength': 'HIGH'},
{'type': 'MISCONDUCT', 'inputStrength': 'HIGH', 'outputStrength': 'HIGH'},
{'type': 'PROMPT_ATTACK', 'inputStrength': 'HIGH', 'outputStrength': 'NONE'}
]
},
個人情報や任意の情報パターンに対するセンシティブ判定などが設定されていました。
sensitiveInformationPolicyConfig={
# Anonymize identifiable patient information
'piiEntitiesConfig': [
{'type': "NAME", "action": "ANONYMIZE"}, {'type': "EMAIL", "action": "ANONYMIZE"},
{'type': "PHONE", "action": "ANONYMIZE"}, {'type': "US_SOCIAL_SECURITY_NUMBER", "action": "ANONYMIZE"},
{'type': "ADDRESS", "action": "ANONYMIZE"}, {'type': "CA_HEALTH_NUMBER", "action": "ANONYMIZE"},
{'type': "PASSWORD", "action": "ANONYMIZE"}, {'type': "IP_ADDRESS", "action": "ANONYMIZE"},
{'type': "CA_SOCIAL_INSURANCE_NUMBER", "action": "ANONYMIZE"}, {'type': "CREDIT_DEBIT_CARD_NUMBER", "action": "ANONYMIZE"},
{'type': "AGE", "action": "ANONYMIZE"}, {'type': "US_BANK_ACCOUNT_NUMBER", "action": "ANONYMIZE"}
],
# Example regex patterns for anonymizing sensitive medical data
'regexesConfig': [
{
"name": "medical_procedure_code",
"description": "Pattern for medical procedure codes",
"pattern": "\\b[A-Z]{1,5}\\d{1,5}\\b",
"action": "ANONYMIZE"
},
{
"name": "clinical_trial_id",
"description": "Pattern for clinical trial identifiers",
"pattern": "\\bNCT\\d{8}\\b",
"action": "ANONYMIZE"
}
]
},
Bedrock Gurdrailsを設定した状態で、モデルに対して以下のような質問をするとブロックされたことがわかります。
ユーザーの入力: Are there any cures for COVID-19? 出力: Input Blocked: Sorry, I cannot provide non-medical advice, confirm/deny unverified medical information, or make any claims of guaranteed/definitive cures without sufficient evidence.
おわりに
本セッションでは、Amazon SageMaker AIを利用した基盤モデルのデプロイ、ファインチューニングおよび評価と、Amazon Bedrock Guardrailsを利用した入出力の制限を学びました。このあたりは殆ど経験がなかったため、ワークショップで初めて実施してみて何となくの感触をつかむことができました。
カミナシではデッキのチューニングにも熱心なソフトウェアエンジニアを募集しています。興味がある方はカジュアル面談からお願いします。