🧙‍♂️

ruri-v3をOpenAI互換embedding APIで使う

に公開

ruri-v3

ruriシリーズは名古屋大学のhppさんが公開している 日本語に特化した汎用テキスト埋め込みモデル です。

SentenceTransformerをAPIにする

OpenAIのAPI互換アプリ

infinity-emb を使います。

$ pip install infinity-emb[all]
$ mkdir -p /mnt/d/models/ruri-v3
$ cd /mnt/d/models/ruri-v3
$ git clone https://huggingface.co/cl-nagoya/ruri-v3-30m
$ pip install -U "transformers>=4.48.0" sentence-transformers sentencepiece
$ infinity_emb v2 --model-id /mnt/d/models/ruri-v3/ruri-v3-30m --device cuda

やっていることは、

  1. HuggingFaceからruri-v3をダウンロード
  2. infinityの元プロジェクトのSentenceTransformerのバージョンが低いのでバージョンアップ
  3. 動かす

となっています。

テスト

embedテスト
$ curl http://localhost:7997/embeddings \
    -H "Content-Type: application/json" \
    -d '{
        "input":"おはようございます。今日も一日いい天気になるといいですね。",
        "model":"ruri-v3/ruri-v3-30m"
    }' | jq .

やってみますと、

結果
{
  "object": "list",
  "data": [
    {
      "object": "embedding",
      "embedding": [
        0.0032781818881630898,
        -0.029971949756145477,
        (snip)
        0.0020983966533094645,
        0.028530990704894066
      ],
      "index": 0
    }
  ],
  "model": "ruri-v3/ruri-v3-30m",
  "usage": {
    "prompt_tokens": 29,
    "total_tokens": 29
  },
  "id": "infinity-979f7871-cb1f-4efd-b5e3-c098448f029b",
  "created": 1745823809
}

マルチモデル

複数のモデルで動かすことも可能です。
ruri-v3は4種類のサイズで公開されており、複数のサイズを同居させたり、日本語以外のために BAAI/bge-m3 を同居させたりもできます。

起動
$ cd /mnt/d/models/ruri-v3
$ git clone https://huggingface.co/cl-nagoya/ruri-v3-130m
$ infinity_emb v2 \
    --model-id /mnt/d/models/ruri-v3/ruri-v3-30m \
    --model-id /mnt/d/models/ruri-v3/ruri-v3-130m \
    --model-id BAAI/bge-m3 \
    --device cuda
テスト
$ curl http://localhost:7997/models | jq .
テスト結果
{
  "data": [
    {
      "id": "ruri-v3/ruri-v3-30m",
      "stats": {
        "queue_fraction": 0.0,
        "queue_absolute": 0,
        "results_pending": 0,
        "batch_size": 32
      },
      "object": "model",
      "owned_by": "infinity",
      "created": 1745824585,
      "backend": "torch",
      "capabilities": [
        "embed"
      ]
    },
    {
      "id": "ruri-v3/ruri-v3-130m",
      "stats": {
        "queue_fraction": 0.0,
        "queue_absolute": 0,
        "results_pending": 0,
        "batch_size": 32
      },
      "object": "model",
      "owned_by": "infinity",
      "created": 1745824585,
      "backend": "torch",
      "capabilities": [
        "embed"
      ]
    },
    {
      "id": "BAAI/bge-m3",
      "stats": {
        "queue_fraction": 0.0,
        "queue_absolute": 0,
        "results_pending": 0,
        "batch_size": 32
      },
      "object": "model",
      "owned_by": "infinity",
      "created": 1745824585,
      "backend": "torch",
      "capabilities": [
        "embed"
      ]
    }
  ],
  "object": "list"
}

ここで、 bge-m3 はHuggingFaceのIDで動いている理由は…。
察してください。

また、 --device cuda をつけていますが、embeddingだけならスピードは変わらないのでつけなくても構いません。
(rerankerを動かすとcudaは効きます)

embedテスト
$ curl http://localhost:7997/embeddings \
    -H "Content-Type: application/json" \
    -d '{
        "input":"おはようございます。今日も一日いい天気になるといいですね。",
        "model":"ruri-v3/ruri-v3-130m"
    }' | jq .

dockerで動かす

上記コマンドで動かすよりdocker使うともっと楽でした…。
(最初からやっとけばよかった)

おもむろにcomposeファイルを入力。

docker-compose.yaml
services:
  infinity:
    image: michaelf34/infinity:latest
    restart: always
    ports:
      - 7997:7997
    volumes:
      - ./volumes/model:/app/.cache
    command: ['v2', '--model-id', 'cl-nagoya/ruri-v3-310m', '--model-id', 'cl-nagoya/ruri-v3-reranker-310m']
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              capabilities: [gpu]
              device_ids: [all]
読み込み確認
$ curl http://localhost:7997/models | jq .
embedテスト
$ curl http://localhost:7997/embeddings \
    -H "Content-Type: application/json" \
    -d '{
        "input":"おはようございます。今日も一日いい天気になるといいですね。",
        "model":"cl-nagoya/ruri-v3-310m"
    }' | jq .

動いているように見えます。
実はまだrerankerの確認はできていないのです…。
時間を見てぼちぼちやってみましょう。

Discussion