ローカルEmbeddingモデルのデプロイ方法は?

AIインフラ層

Posted by LuochuanAD on April 10, 2026 本文总阅读量

背景

プライベート化された大規模モデルシステムにおいて、外部依存を避け、データ漏洩リスクを低減し制御性を向上させるために、Embeddingモデルをローカルにデプロイします。また、標準化されたインターフェースサービスを実現し、外部システムがHTTP経由でEmbedding機能をリクエストできるようにし、フォールトトレランス、拡張性、並行処理の対応も備えています。

選定

FastAPI + Uvicorn + EmbeddingModel(e5-large)

プロジェクト構成(ローカルEmbeddingモデルをFastAPIでラップ)

embedding-service/
│
├── app/
│   ├── main.py          # FastAPIエントリーポイント
│   ├── model.py         # モデルの読み込み
│   ├── schemas.py       # 入出力スキーマ定義
│   ├── router.py        # モデル用ルーティング
│   ├── services.py      # リクエスト処理サービス
│   └── config.py        # 設定
│
├── requirements.txt
└── run.sh

詳細解説

config.py

主にEmbeddingマイクロサービスの設定項目(embedding_name、deviceなど)

MODEL_NAME = "intfloat/e5-large"
DEVICE = "cpu"   # GPUがある場合は "cuda" に変更

router.py

モデルのルーティング設定:/embed、/embed_batch

router = APIRouter()

@router.get("/")
def root():
    return {"message": "Welcome to the E5 Embedding Service!"}  

@router.post("/embed", response_model=EmbeddingResponse)
def embed(request: EmbeddingRequest):
    vector = embed_query(request.text)
    return {"vector": vector}

@router.post("/embed_batch", response_model=BatchEmbeddingResponse)
def batch_embed(request: BatchEmbeddingRequest):
    vectors = embed_batch(request.texts, is_query=request.is_query)
    return {"vectors": vectors}

main.py

ローカルEmbeddingモデルのAPIエンドポイント。OpenAI APIと同様に「api/v1/embeddings」として設定可能。

from fastapi import FastAPI
from .router import router

app = FastAPI(title="E5 Embedding Service")
app.include_router(router, prefix="/api/v1/embeddings")

model.py

Embeddingモデルの実装。


from .config import MODEL_NAME, DEVICE
class EmbeddingModel:
    def __init__(self):
        self.model = SentenceTransformer(MODEL_NAME, device=DEVICE)

    def embed_query(self, text: str):
        # ⚠️ E5はプレフィックスが必要
        text = "query: " + text
        return self.model.encode(text, normalize_embeddings=True).tolist()

    def embed_passage(self, text: str):
        text = "passage: " + text
        return self.model.encode(text, normalize_embeddings=True).tolist()

    def embed_batch(self, texts: list[str], is_query=False):
        ...
        ).tolist()


# シングルトン(重複読み込み回避用)
embedding_model = EmbeddingModel()

schemas.py

Embeddingモデルの入力・出力フォーマットの定義

from pydantic import BaseModel
from typing import List

class EmbeddingRequest(BaseModel):
    text: str

class BatchEmbeddingRequest(BaseModel):
    texts: List[str]
    is_query: bool = False

class EmbeddingResponse(BaseModel):
    vector: List[float]

class BatchEmbeddingResponse(BaseModel):
    vectors: List[List[float]]

services.py

Embeddingモデルのリクエスト処理メソッド

from .model import embedding_model

def embed_query(text: str):
    return embedding_model.embed_query(text)

def embed_passage(text: str):
    return embedding_model.embed_passage(text)

def embed_batch(texts: list[str], is_query: bool = True):
    return embedding_model.embed_batch(texts, is_query)

run.sh

uvicornを使った高速起動コマンド:

uvicorn app.main:app –reload

まとめ

ローカルにモデルをデプロイする場合、Embeddingモデル、rerankerモデル、ローカルLLMモデル問わず、プロジェクト構造はほぼ同じです。ここでは、それぞれの構造の違いを中心に説明しました。

今後

次回は高並行処理モジュールについて解説予定です。随時、記事をアップしていきます。