機械学習モデルの精度向上には、高品質な教師データが不可欠です。しかし、データアノテーション(即時的なラベル付け作業)は非常に時間とコストがかかるプロセスです。本稿では、Label StudioとHolySheep AIのAPIを組み合わせた効率的なアノテーションプラットフォームの構築方法を詳しく解説します。
HolySheep AI vs 公式API vs 他のリレーサービスの比較
AI API 利用を検討する際、多くの開発者が迷うのがどのサービスを選択するかです。以下に主要な違いをまとめます。
| 比較項目 | HolySheep AI | OpenAI 公式API | 他のリレーサービス |
|---|---|---|---|
| 為替レート | ¥1 = $1(業界最安水準) | ¥7.3 = $1 | ¥2〜5 = $1 |
| コスト節約率 | 85%節約(公式比) | 基準 | 30〜70%節約 |
| 対応決済 | WeChat Pay / Alipay / クレジットカード | クレジットカードのみ | 限定的 |
| レイテンシ | <50ms | 100〜300ms | 80〜200ms |
| GPT-4.1出力単価 | $8 / MTok | $8 / MTok | $6〜7 / MTok |
| Claude Sonnet 4.5 | $15 / MTok | $15 / MTok | $12〜14 / MTok |
| Gemini 2.5 Flash | $2.50 / MTok | $2.50 / MTok | $2〜2.30 / MTok |
| DeepSeek V3.2 | $0.42 / MTok | 対応なし | 対応なし |
| 無料クレジット | 登録時付与 | $5〜18相当 | 限定的 |
| 日本語サポート | 充実 | 限定的 | 不一 |
HolySheep AIは、日本円ベースの定額制に近い形でAPIを利用できる点が最大の特徴です。DeepSeek V3.2などの最新モデルを低コストで利用できるのも大きな優位性です。
Label Studioとは
Label Studioは、MITライセンスで公開されているオープンソースのデータアノテーションプラットフォームです。画像、テキスト、音声、视频など多种多样的数据类型に対応しており、柔軟なカスタマイズが可能です。
- オープンソースで自己ホスティング可能
- 丰富的テンプレートとカスタマイズ性
- REST APIによる外部システムとの連携
- 機械学習モデルとの連結機能(Machine Learning Backend)
AIプレラベル機能のアーキテクチャ
本システムのアーキテクチャは以下の通りです。
+------------------+ +----------------------+ +------------------+
| Label Studio | --> | ML Backend (FastAPI)| --> | HolySheep AI |
| (Web UI) | | プレラベル生成 | | API |
+------------------+ +----------------------+ +------------------+
| | |
| プレラベル済みタスクを返す |
+--------------------------------------------------+
アノテーターが Label Studio でタスクを開くと、ML Backend が HolySheep AI の API を呼び出して自動プレラベルを生成します。これにより、アノテーション作業の効率が大幅に向上します。
プロジェクト構成
label-studio-holysheep/
├── docker-compose.yml
├── label-studio/
│ └── settings_config.xml
├── ml-backend/
│ ├── main.py
│ ├── requirements.txt
│ └── holysheep_client.py
└── data/
└── annotations/
HolySheep AI API クライアントの実装
まず、HolySheep AI API との通信を行うクライアントモジュールを作成します。
# ml-backend/holysheep_client.py
import httpx
from typing import Optional, Dict, Any
import json
class HolySheepAIClient:
"""HolySheep AI API クライアント
HolySheep AIは$1=¥1のレートで利用でき、
WeChat Pay / Alipay対応の高性能APIです。
"""
BASE_URL = "https://api.holysheep.ai/v1"
def __init__(self, api_key: str):
self.api_key = api_key
self.client = httpx.AsyncClient(timeout=60.0)
async def generate_prelabels(
self,
image_path: str,
prompt: str,
model: str = "gpt-4.1"
) -> Dict[str, Any]:
"""画像に対してAIプレラベルを生成する
Args:
image_path: 画像ファイルのパス
prompt: アノテーション指示プロンプト
model: 使用するモデル名
Returns:
プレラベル結果の辞書
"""
# 画像をBase64エンコード
import base64
with open(image_path, "rb") as f:
image_base64 = base64.b64encode(f.read()).decode("utf-8")
headers = {
"Authorization": f"Bearer {self.api_key}",
"Content-Type": "application/json"
}
payload = {
"model": model,
"messages": [
{
"role": "user",
"content": [
{
"type": "text",
"text": prompt
},
{
"type": "image_url",
"image_url": {
"url": f"data:image/jpeg;base64,{image_base64}"
}
}
]
}
],
"max_tokens": 4096,
"temperature": 0.1
}
response = await self.client.post(
f"{self.BASE_URL}/chat/completions",
headers=headers,
json=payload
)
if response.status_code != 200:
raise HolySheepAPIError(
f"APIエラー: {response.status_code} - {response.text}"
)
result = response.json()
return self._parse_prelabels(result)
async def text_classification(
self,
text: str,
categories: list,
model: str = "gpt-4.1"
) -> Dict[str, Any]:
"""テキスト分類のプレラベルを生成
Args:
text: 分類対象テキスト
categories: 分類カテゴリ一覧
model: 使用するモデル
Returns:
分類結果
"""
headers = {
"Authorization": f"Bearer {self.api_key}",
"Content-Type": "application/json"
}
prompt = f"""以下のテキストを最も適切なカテゴリに分類してください。
テキスト: {text}
利用可能なカテゴリ: {', '.join(categories)}
回答はJSON形式で返してください:
{{"category": "選択したカテゴリ", "confidence": 0.0〜1.0, "reasoning": "分類理由"}}
"""
payload = {
"model": model,
"messages": [
{"role": "user", "content": prompt}
],
"max_tokens": 512,
"temperature": 0.1,
"response_format": {"type": "json_object"}
}
response = await self.client.post(
f"{self.BASE_URL}/chat/completions",
headers=headers,
json=payload
)
if response.status_code != 200:
raise HolySheepAPIError(
f"APIエラー: {response.status_code} - {response.text}"
)
result = response.json()
content = result["choices"][0]["message"]["content"]
return json.loads(content)
def _parse_prelabels(self, response: Dict) -> Dict[str, Any]:
"""APIレスポンスをプレラベル形式にパース"""
content = response["choices"][0]["message"]["content"]
# 実際は画像の具体的なアノテーション情報を返す
return {
"raw_response": content,
"usage": response.get("usage", {}),
"model": response.get("model", "unknown")
}
async def close(self):
await self.client.aclose()
class HolySheepAPIError(Exception):
"""HolySheep API エラー"""
pass
グローバルクライアント实例(環境変数から初期化)
_client: Optional[HolySheepAIClient] = None
def get_client() -> HolySheepAIClient:
global _client
if _client is None:
api_key = os.environ.get("HOLYSHEEP_API_KEY", "YOUR_HOLYSHEEP_API_KEY")
_client = HolySheepAIClient(api_key)
return _client
Label Studio ML Backend の実装
Label Studio の Machine Learning Backend として動作する FastAPI アプリケーションを作成します。
# ml-backend/main.py
import os
import logging
from typing import List, Dict, Any, Optional
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
import label_studio_sdk
from holysheep_client import HolySheepAIClient, HolySheepAPIError
ロギング設定
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
FastAPI アプリケーション
app = FastAPI(title="Label Studio ML Backend - HolySheep AI")
クライアント初期化
holysheep_client: Optional[HolySheepAIClient] = None
def get_holysheep_client() -> HolySheepAIClient:
global holysheep_client
if holysheep_client is None:
api_key = os.environ.get("HOLYSHEEP_API_KEY")
if not api_key or api_key == "YOUR_HOLYSHEEP_API_KEY":
raise ValueError(
"HOLYSHEEP_API_KEY環境変数が設定されていません。"
"https://www.holysheep.ai/register でAPIキーを取得してください。"
)
holysheep_client = HolySheepAIClient(api_key)
return holysheep_client
class MLBackend:
"""Label Studio ML Backend クラス"""
def __init__(self, api_key: str):
self.client = HolySheepAIClient(api_key)
def predict(self, tasks: List[Dict], context: Optional[Dict] = None) -> List[Dict]:
"""予測を実行してプレラベルを生成
Label Studioから呼び出されるメインの予測メソッド
"""
results = []
for task in tasks:
try:
# タスクの種類に応じて処理を分岐
task_type = self._detect_task_type(task)
if task_type == "image_classification":
result = self._predict_image_classification(task)
elif task_type == "text_classification":
result = self._predict_text_classification(task)
elif task_type == "named_entity_recognition":
result = self._predict_ner(task)
else:
result = self._predict_generic(task)
results.append(result)
except HolySheepAPIError as e:
logger.error(f"APIエラー (task {task.get('id')}): {e}")
results.append({
"id": task.get("id"),
"error": str(e),
"predictions": []
})
except Exception as e:
logger.error(f"予測エラー (task {task.get('id')}): {e}")
results.append({
"id": task.get("id"),
"error": str(e),
"predictions": []
})
return results
def _detect_task_type(self, task: Dict) -> str:
"""タスクの種類を検出"""
data = task.get("data", {})
if "image" in data:
return "image_classification"
elif "text" in data:
# アノテーション設定に基づいて判定
return "text_classification"
else:
return "unknown"
def _predict_image_classification(self, task: Dict) -> Dict:
"""画像分類タスクのプレラベル生成"""
import base64
import json
data = task.get("data", {})
image_url = data.get("image", "")
# 画像を読み込み(URLまたはローカルパス)
image_data = self._load_image_data(image_url)
image_base64 = base64.b64encode(image_data).decode("utf-8")
prompt = """この画像に写っている主な物体やシーンを判定し、
利用可能なカテゴリから最も適切なものを選択してください。
利用可能なカテゴリ: person, vehicle, animal, food, building, nature, product, text, other
JSON形式で返答してください:
{
"category": "カテゴリ名",
"confidence": 0.0〜1.0,
"all_scores": {"カテゴリ1": スコア, ...}
}
"""
client = get_holysheep_client()
# 直接API呼び出し
import httpx
response = httpx.post(
f"{client.BASE_URL}/chat/completions",
headers={
"Authorization": f"Bearer {client.api_key}",
"Content-Type": "application/json"
},
json={
"model": "gpt-4.1",
"messages": [
{
"role": "user",
"content": [
{"type": "text", "text": prompt},
{"type": "image_url", "image_url": {"url": f"data:image/jpeg;base64,{image_base64}"}}
]
}
],
"max_tokens": 1024,
"temperature": 0.1,
"response_format": {"type": "json_object"}
},
timeout=60.0
)
if response.status_code != 200:
raise HolySheepAPIError(f"API呼び出し失敗: {response.text}")
result = response.json()
content = json.loads(result["choices"][0]["message"]["content"])
# Label Studio形式の予測結果に変換
return {
"id": task.get("id"),
"predictions": [{
"model": "holySheep-gpt-4.1",
"score": content.get("confidence", 0.5),
"result": [{
"from_name": "label",
"to_name": "image",
"type": "choices",
"value": {
"choices": [content.get("category", "other")]
}
}]
}]
}
def _predict_text_classification(self, task: Dict) -> Dict:
"""テキスト分類タスクのプレラベル生成"""
data = task.get("data", {})
text = data.get("text", "")
client = get_holysheep_client()
categories = ["positive", "negative", "neutral"]
result = client.text_classification(text, categories)
return {
"id": task.get("id"),
"predictions": [{
"model": "holySheep-gpt-4.1",
"score": result.get("confidence", 0.5),
"result": [{
"from_name": "sentiment",
"to_name": "text",
"type": "choices",
"value": {
"choices": [result.get("category", "neutral")]
}
}]
}]
}
def _predict_ner(self, task: Dict) -> Dict:
"""固有表現抽出タスクのプレラベル生成"""
data = task.get("data", {})
text = data.get("text", "")
import httpx
import json
client = get_holysheep_client()
prompt = f"""以下のテキストから固有表現(人名、組織名、場所、日付、数量など)を抽出してください。
テキスト: {text}
JSON形式で返答してください:
{{
"entities": [
{{"text": "抽出テキスト", "label": "ラベル名", "start": 開始位置, "end": 終了位置}}
]
}}
"""
response = httpx.post(
f"{client.BASE_URL}/chat/completions",
headers={
"Authorization": f"Bearer {client.api_key}",
"Content-Type": "application/json"
},
json={
"model": "gpt-4.1",
"messages": [{"role": "user", "content": prompt}],
"max_tokens": 1024,
"temperature": 0.1,
"response_format": {"type": "json_object"}
},
timeout=60.0
)
result = response.json()
entities_data = json.loads(result["choices"][0]["message"]["content"])
# Label Studio NER形式に変換
results = []
for entity in entities_data.get("entities", []):
results.append({
"from_name": "label",
"to_name": "text",
"type": "labels",
"value": {
"start": entity["start"],
"end": entity["end"],
"text": entity["text"],
"labels": [entity["label"]]
}
})
return {
"id": task.get("id"),
"predictions": [{
"model": "holySheep-gpt-4.1",
"score": 0.8,
"result": results
}]
}
def _predict_generic(self, task: Dict) -> Dict:
"""汎用プレラベル生成"""
return {
"id": task.get("id"),
"predictions": [],
"error": "未対応のタスク形式"
}
def _load_image_data(self, image_url: str) -> bytes:
"""画像データを読み込む"""
import httpx
if image_url.startswith("http"):
response = httpx.get(image_url, timeout=30.0)
return response.content
else:
with open(image_url, "rb") as f:
return f.read()
FastAPI エンドポイント
@app.on_event("startup")
async def startup_event():
"""アプリケーション起動時の処理"""
logger.info("Label Studio ML Backend 起動中...")
try:
client = get_holysheep_client()
logger.info("HolySheep AI API 接続確認完了")
except ValueError as e:
logger.warning(f"API設定警告: {e}")
@app.get("/health")
async def health_check():
"""健全性チェックエンドポイント"""
try:
client = get_holysheep_client()
return {"status": "healthy", "service": "holySheep AI"}
except ValueError:
return {"status": "configured", "service": "holySheep AI"}
@app.post("/predict")
async def predict(tasks: List[Dict]):
"""Label Studioから呼び出される予測エンドポイント"""
try:
client = get_holysheep_client()
ml_backend = MLBackend(client.api_key)
return ml_backend.predict(tasks)
except HolySheepAPIError as e:
raise HTTPException(status_code=500, detail=str(e))
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=9090)
docker-compose.yml の設定
version: '3.8'
services:
label-studio:
image: heartexlabs/label-studio:latest
container_name: label-studio
ports:
- "8080:8080"
environment:
- LABEL_STUDIO_LOCAL_FILES_SERVING_ENABLED=true
- LABEL_STUDIO_LOCAL_FILES_DOCUMENT_ROOT=/label-studio/data
volumes:
- ./label-studio/data:/label-studio/data
- ./label-studio/settings_config.xml:/label-studio/settings_config.xml
depends_on:
- postgres
environment:
- DJANGO_DB=default
- POSTGRE_NAME=labelstudio
- POSTGRE_USER=labelstudio
- POSTGRE_PASSWORD=labelstudio
- POSTGRE_HOST=postgres
- POSTGRE_PORT=5432
postgres:
image: postgres:14-alpine
container_name: label-studio-db
environment:
- POSTGRE_NAME=labelstudio
- POSTGRE_USER=labelstudio
- POSTGRE_PASSWORD=labelstudio
volumes:
- postgres_data:/var/lib/postgresql/data
ports:
- "5432:5432"
ml-backend:
build:
context: ./ml-backend
dockerfile: Dockerfile
container_name: ml-backend-holysheep
ports:
- "9090:9090"
environment:
- HOLYSHEEP_API_KEY=${HOLYSHEEP_API_KEY}
volumes:
- ./ml-backend:/app
- ./data:/data
redis:
image: redis:6-alpine
container_name: label-studio-redis
ports:
- "6379:6379"
volumes:
postgres_data:
Label Studio でのプロジェクト設定
Label Studio 管理画面での設定手順を説明します。