Hugging Face Hub: モデルを探して使う
1. 概要
Hugging Face Hubは、機械学習のためのモデル、データセット、デモを集めた、今最大のリポジトリです。この記事では、必要なモデルを正しく見つけ(名前を推測する代わりに)、モデルカードを読んでライセンスやアーキテクチャの誤りを避け、2つの方法でそのモデルを呼び出す方法を説明します:Pythonでローカルに実行するか、Spring BootアプリケーションからInference APIで呼び出すか。最後には、GPUを自分でホストすることなく、NLPモデルをJavaサービスに統合できるようになります。
2. Hugging Face Hubとは
Hubは主に3種類のリソースを保存しています:
- Models: 事前に学習済みの重み(weights)で、使い方を説明するモデルカード付き。
- Datasets: トレーニング/ファインチューニングまたはベンチマークに使うデータ。
- Spaces: ブラウザで直接実行できるデモ(Gradio、Streamlit)。
各モデルは組織/モデル名の形式のmodel_idを持ちます。例えばdistilbert-base-uncased-finetuned-sst-2-englishのようにです。このmodel_idがコード内で使う値で、UIの表示名ではありません。
3. Hubでモデルを探す
3.1. Webインターフェースで探す
Hubのホームページには、task(text-classification、translation、image-segmentation…)、library(transformers、sentence-transformers、timm…)、license、languageで絞り込めるフィルターがあります。「Most downloads」または「Trending」でソートすると、最新モデルを選ぶより安定した結果が得られます。最新モデルはまだ十分なユーザーに検証されていない可能性があるからです。
3.2. huggingface_hub(Python)で探す
スクリプトからモデルを探す必要があるとき(例えば要件を満たす最小モデルを自動選択する場合)、HfApiを使います:
pip install huggingface_hub
from huggingface_hub import HfApi
api = HfApi()
models = api.list_models(
search="sentiment",
library="transformers",
sort="downloads",
direction=-1,
limit=5,
)
for m in models:
print(m.id, m.downloads)
searchは名前/タグ内のキーワードでフィルタ、sort="downloads"とdirection=-1は最も人気のあるモデルを先頭にソート、limit=5は結果を5件に制限します。出力は次のようになります:
distilbert-base-uncased-finetuned-sst-2-english 5123456
cardiffnlp/twitter-roberta-base-sentiment-latest 2876543
nlptown/bert-base-multilingual-uncased-sentiment 1987654
...
注意: ダウンロード数は必ずしも最高の品質を意味しません。あなたのタスクに対して最適とは限りません。常に実際のデータで検証してから決定してください。
4. 使う前にモデルカードを読む
各モデルにはREADME.mdファイルがあり、モデルカードとして表示されます。以下を含みます:
- Task: モデルが学習したタスク(分類、翻訳、テキスト生成…)。
- License:
apache-2.0、mit、cc-by-nc(非商用 — 商用製品には使えない)。 - Gated model: 一部のモデルはログインと所有者の承認が必要な場合があります(通常は大規模または機密性の高いモデル)。
APIでライセンスとgated状態を素早くチェック:
from huggingface_hub import model_info
info = model_info("meta-llama/Llama-3.1-8B")
print(info.gated, info.tags)
True ['text-generation', 'license:llama3.1']
gated=Trueは、個人トークンが必要で、アクセスが許可されていることを意味します。許可されていない場合、リクエストは401/403エラーを返します。
5. transformersでローカルにモデルを実行する
小さなモデルなら、pipelineで試すのが最速です:
pip install transformers torch
from transformers import pipeline
classifier = pipeline(
"sentiment-analysis",
model="distilbert-base-uncased-finetuned-sst-2-english",
)
result = classifier("Hugging Face Hub makes finding models easy!")
print(result)
[{'label': 'POSITIVE', 'score': 0.9998}]
pipelineはHubから重みをローカルキャッシュ(~/.cache/huggingface)に自動ダウンロードし、対応するtokenizerを読み込み、結果をdict型のlistで返します。初回実行はモデルファイルのダウンロードが必要なので遅くなります。帯域幅やディスク容量が限られた環境にいる場合は、事前にHub上でモデルサイズを確認してください。
6. Spring BootからInference API経由でモデルを呼び出す
メインアプリケーションがJavaで書かれている場合、自分でモデルをホストする必要はありません。Hugging Faceは多くの人気モデル向けにInference API(HTTP)を提供しています。個人トークンでRESTを呼び出すだけです。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
huggingface.api-token=${HF_API_TOKEN}
huggingface.model=distilbert-base-uncased-finetuned-sst-2-english
@Service
public class SentimentAnalysisService {
private final RestClient restClient;
private final String model;
public SentimentAnalysisService(RestClient.Builder builder,
@Value("${huggingface.api-token}") String token,
@Value("${huggingface.model}") String model) {
this.model = model;
this.restClient = builder
.baseUrl("https://api-inference.huggingface.co/models")
.defaultHeader("Authorization", "Bearer " + token)
.build();
}
public List<SentimentResult> analyze(String text) {
SentimentResult[][] response = restClient.post()
.uri("/{model}", model)
.body(Map.of("inputs", text))
.retrieve()
.body(SentimentResult[][].class);
return response == null ? List.of() : List.of(response[0]);
}
public record SentimentResult(String label, double score) {}
}
RestClient.BuilderはSpring Bootが自動設定するので、baseUrlとAuthorizationヘッダを設定するだけです。uri("/{model}", model)は.../models/distilbert-base-uncased-finetuned-sst-2-englishのようなURLを作成します。text-classificationタスクのInference APIレスポンスはネストされた配列([[{...}]])なので、戻り値の型はSentimentResult[][]です。
呼び出してみます:
List<SentimentAnalysisService.SentimentResult> results =
sentimentAnalysisService.analyze("I love this library!");
[SentimentResult[label=POSITIVE, score=0.9997]]
JSONレスポンスのパースをテストする
実際のレスポンスはネットワークに依存するため、実APIを呼び出さずにテストできるようにJSONパース部分を分離する必要があります:
import com.fasterxml.jackson.databind.ObjectMapper;
import static org.assertj.core.api.Assertions.assertThat;
class SentimentResultParsingTest {
@Test
void shouldParseInferenceApiResponse() throws Exception {
String json = """
[[{"label":"POSITIVE","score":0.9998}]]
""";
ObjectMapper mapper = new ObjectMapper();
SentimentAnalysisService.SentimentResult[][] result =
mapper.readValue(json, SentimentAnalysisService.SentimentResult[][].class);
assertThat(result[0][0].label()).isEqualTo("POSITIVE");
assertThat(result[0][0].score()).isGreaterThan(0.99);
}
}
このテストは、ネットワーク接続や有効なトークンに依存せず、SentimentResult recordがlabel/scoreフィールドを正しくマップしていることを保証します。
7. よくあるエラーと、Inference APIを使わない方がいい場合
- 最初の呼び出しで503 Service Unavailableが返される: モデルがフリーティアサーバーで「ウォームアップ」されていません。Hugging Faceは
estimated_timeフィールドを返します。本当のエラーではなく、数秒後にリトライしてください。 - 429 Too Many Requests: フリーティアは厳しいレート制限があります。安定した本番トラフィックの場合は、フリーAPIではなくInference Endpoints(専用、有料)を検討してください。
- Gated modelだが未承認: トークンが有効でも403エラーが返されます。モデルページに行き「Request access」をクリックして承認を待つ必要があります。
- ライセンスが商用利用に適していない: Llamaからファインチューニングされたモデルやデータセットの非商用制限には特別な条項がある場合があります。製品で使用する前に、モデルカードのライセンスセクションをよく読んでください。
注意: 低遅延の安定性やSLAが必要なシステムにはフリーのInference APIを使わないでください。実験、デモ、または低トラフィックに適しています。大規模ワークロードの場合は、
transformers/text-generation-inferenceでローカルにモデルをホストするか、有料のInference Endpointsを使用してください。
8. まとめ
Hugging Face Hubは明確なプロセスを提供します:UIまたはhuggingface_hubでモデルを探し、モデルカードを読んでtask/license/gated状態をチェックし、その後使用方法を選択します。完全に制御したいときはpipelineでローカルに実行し、既存のJavaシステムに素早く統合したいときはSpring BootからInference APIを呼び出します。重要なのは、本番環境にモデルを導入する前に、常にライセンスとレート制限をチェックすることです。