ruri-v3-310m-coreml

English | 日本語

Model Summary

This is an unofficial Core ML conversion of cl-nagoya/ruri-v3-310m (a general-purpose Japanese text-embedding model), for running directly on iOS/macOS. All credit for the original model goes to its authors (Nagoya University / cl-nagoya).

  • Base model: cl-nagoya/ruri-v3-310m (ModernBERT-Ja, 315M params, hidden=768)

  • Output: a mean-pooled, L2-normalized sentence embedding (768-dim). You can use a dot product instead of cosine similarity directly.

  • The model is split into fixed-length buckets per sequence length (Core ML has trouble tracing variable-length graphs, so this buckets into a few practical lengths instead). Pad/truncate input_ids / attention_mask to the matching bucket length.

  • Live demo: Ruri Atlas — explore Japanese & English sentence embeddings as a 3-D map in your browser (WebGPU), switch embedding models, toggle the reranker, and see where a prompt-injection lands. Nothing is sent to a server.

Files

File Seq. length Precision Approx. size
ruri-v3-310m_seq128_fp16.mlpackage 128 fp16 630MB
ruri-v3-310m_seq256_fp16.mlpackage 256 fp16 630MB
ruri-v3-310m_seq512_fp16.mlpackage 512 fp16 630MB
ruri-v3-310m_seq128_int8.mlpackage 128 int8 (weight-only) 316MB
ruri-v3-310m_seq256_int8.mlpackage 256 int8 (weight-only) 316MB
ruri-v3-310m_seq512_int8.mlpackage 512 int8 (weight-only) 316MB

For short queries/chunks, use seq128; for longer document chunks, use seq256/512. The int8 variant is recommended for mobile apps.

Verification

  • On a real iPhone 17 Pro (iOS 27): both the seq128 fp16 and int8 variants of ruri-v3-310m run on GPU/Neural Engine (computeUnits = .all). Steady-state inference is about 5ms per sentence (Apple's own NLContextualEmbedding is about 9-10ms). The fp16/int8 similarity-score difference is at most 0.0042, with search-result ranking essentially unchanged.
  • On Mac (coremltools): all files show cosine similarity 0.9998+ against the original PyTorch output.

See REPORT.md for detailed verification results.

Real-world usage

This Core ML conversion is used in the iOS app "道程 -Michinori-" (free, iOS 17.0+), which compares a user's input text against Japanese literature (classical works, etc.) to find the semantically closest passages. The app uses this ruri-v3 model for the initial embedding-based candidate search.

Prefixes (important)

ruri-v3 uses a "1+3 prefix scheme" -- prepend the following prefix to the text before tokenizing, depending on its role (required to match the original model's behavior):

  • Empty string: general semantic similarity
  • トピック: ("Topic: "): classification/clustering
  • 検索クエリ: ("Search query: "): the query side of retrieval
  • 検索文書: ("Search document: "): the document side of retrieval

Swift usage example

See MANUAL.md for how to add the downloaded model to an Xcode project, and a complete implementation example.

import CoreML

let configuration = MLModelConfiguration()
configuration.computeUnits = .all
let model = try MLModel(
    contentsOf: Bundle.main.url(forResource: "ruri-v3-310m_seq128_int8", withExtension: "mlmodelc")!,
    configuration: configuration
)

// You'll need a tokenizer separately -- huggingface/swift-transformers'
// Tokenizers, or an equivalent implementation that can load tokenizer.json,
// is recommended.
let inputIDs: MLMultiArray = ...       // shape [1, 128], Int32
let attentionMask: MLMultiArray = ...  // shape [1, 128], Int32

let input = try MLDictionaryFeatureProvider(dictionary: [
    "input_ids": MLFeatureValue(multiArray: inputIDs),
    "attention_mask": MLFeatureValue(multiArray: attentionMask),
])
let output = try model.prediction(from: input)
let embedding = output.featureValue(for: "sentence_embedding")!.multiArrayValue!
// A [1, 768] L2-normalized vector (dtype float16; read it as Swift's Float16).

You must use the original model's tokenizer.json as-is (a ModernBERT-Ja / PLaMo-family tokenizer).

Python verification example

import coremltools as ct
import numpy as np
from transformers import AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained("cl-nagoya/ruri-v3-310m")
model = ct.models.MLModel("ruri-v3-310m_seq128_int8.mlpackage")

text = "検索文書: 瑠璃色(るりいろ)は、紫みを帯びた濃い青のことである。"
encoded = tokenizer([text], return_tensors="np", padding="max_length", truncation=True, max_length=128)
output = model.predict({
    "input_ids": encoded["input_ids"].astype(np.int32),
    "attention_mask": encoded["attention_mask"].astype(np.int32),
})
print(output["sentence_embedding"].shape)  # (1, 768)

How it was converted (reproduction steps)

Generated with the ruri_coreml_convert conversion tool. Steps:

  1. Load the ModernBERT-based ruri-v3 with transformers' AutoModel.
  2. Wrap it in an nn.Module that does mean pooling + L2 normalize.
  3. Trace with torch.jit.trace (since transformers.masking_utils.and_masks/ or_masks use Tensor.new_ones/new_zeros, which the Core ML converter doesn't support, these were swapped for a torch.ones/torch.zeros-based implementation before tracing).
  4. Generate the .mlpackage with coremltools.convert(..., convert_to="mlprogram").
  5. Generate the int8 variant with coremltools.optimize.coreml.linear_quantize_weights.

License

Same as the base model, Apache License 2.0. Copyright for the original model belongs to Nagoya University's conversational AI research group (cl-nagoya). This repository only performs a weight-format conversion.

Citation

@misc{ruri2024,
  title={{Ruri}: {J}apanese {G}eneral {T}ext {E}mbeddings},
  author={Hayato Tsukagoshi and Ryohei Sasano},
  year={2024},
  eprint={2409.07737},
  archivePrefix={arXiv},
  primaryClass={cs.CL},
}

Notes

  • This is a community conversion, not an official release from the Ruri / cl-nagoya team.
  • Security audit uses model-audit-lite (see SECURITY.md for details).

Security

Audited against its upstream with model-audit-lite: weight format, bundled code, and a machine-readable lineage (ML-BOM). Details, checksums and how to reproduce: SECURITY.md.


モデルの概要

cl-nagoya/ruri-v3-310m(日本語汎用テキスト埋め込みモデル)を、iOS/macOS (Core ML) で直接動かせるように変換したものです。元モデルの著作権はその作者(名古屋大学 / cl-nagoya)に帰属します。

  • ベースモデル: cl-nagoya/ruri-v3-310m(ModernBERT-Ja, 315M params, hidden=768)

  • 出力: mean pooling + L2 normalize 済みの文埋め込みベクトル(768次元)。そのままコサイン類似度の代わりに内積(dot product)で類似度計算できます。

  • 系列長ごとに固定長でモデルを分けています(CoreMLはグラフ内の可変長トレースに難があるため、実用的な長さでバケット化しています)。入力は input_ids / attention_mask を該当の長さまでパディング/切り詰めしてください。

  • ライブデモ: Ruri Atlas — 日本語・英語の文の埋め込みを、ブラウザ上(WebGPU)で3Dの地図として見られます。埋め込みモデルの切り替え、リランカーのON/OFF、プロンプトインジェクションの効き方の可視化もできます。文章はサーバーに送られません。

ファイル一覧

ファイル 系列長 精度 サイズ目安
ruri-v3-310m_seq128_fp16.mlpackage 128 fp16 630MB
ruri-v3-310m_seq256_fp16.mlpackage 256 fp16 630MB
ruri-v3-310m_seq512_fp16.mlpackage 512 fp16 630MB
ruri-v3-310m_seq128_int8.mlpackage 128 int8(重みのみ量子化) 316MB
ruri-v3-310m_seq256_int8.mlpackage 256 int8(重みのみ量子化) 316MB
ruri-v3-310m_seq512_int8.mlpackage 512 int8(重みのみ量子化) 316MB

短いクエリやチャンクで検索するなら seq128、長めの文書チャンクなら seq256/512 を選んでください。モバイルアプリには int8版 を推奨します。

動作確認

  • iPhone 17 Pro 実機(iOS 27): ruri-v3-310m の seq128 fp16版・int8版がともに GPU/Neural Engine(computeUnits = .all)で動作。定常状態の推論は1文あたり約5ms(Apple標準の NLContextualEmbedding は約9〜10ms)。fp16版とint8版の類似度スコア差は最大0.0042で、検索結果の順位はほぼ同一。
  • Mac(coremltools): 全ファイルでオリジナル(PyTorch)出力とのコサイン類似度0.9998以上を確認。

詳しい検証結果は REPORT.md を参照してください。

実際の利用例

このCore ML版は、iOSアプリ「道程 -Michinori-」(iOS 17.0以降対応、無料)で実際に使われています。ユーザーが入力した文章を日本語文学(古典作品など)と比較し、意味的にどの部分と類似しているかを検索する機能に活用されています。候補の絞り込み(埋め込み検索)にこのモデルが使われています。

プレフィックスについて(重要)

ruri-v3 は "1+3 prefix scheme" を採用しているため、埋め込み対象のテキストに応じて以下のプレフィックスを付けてからトークナイズしてください(元モデルと同じ挙動にするため必須です)。

  • 空文字列: 意味的な類似度計算全般
  • トピック: : 分類・クラスタリング用
  • 検索クエリ: : 検索クエリ側
  • 検索文書: : 検索対象の文書側

Swift (Core ML) での使用例

ダウンロードしたモデルをXcodeプロジェクトに追加する手順・完全な実装例は MANUAL.md を参照してください。

import CoreML

let configuration = MLModelConfiguration()
configuration.computeUnits = .all
let model = try MLModel(
    contentsOf: Bundle.main.url(forResource: "ruri-v3-310m_seq128_int8", withExtension: "mlmodelc")!,
    configuration: configuration
)

// トークナイザは別途用意する必要があります。huggingface/swift-transformers の
// Tokenizers、もしくは tokenizer.json を読み込める同等の実装を推奨します。
let inputIDs: MLMultiArray = ...       // shape [1, 128], Int32
let attentionMask: MLMultiArray = ...  // shape [1, 128], Int32

let input = try MLDictionaryFeatureProvider(dictionary: [
    "input_ids": MLFeatureValue(multiArray: inputIDs),
    "attention_mask": MLFeatureValue(multiArray: attentionMask),
])
let output = try model.prediction(from: input)
let embedding = output.featureValue(for: "sentence_embedding")!.multiArrayValue!
// [1, 768] の L2 正規化済みベクトル(dtype は float16。Swift の Float16 として読み取る)

トークナイザは元モデルの tokenizer.json(ModernBERT-Ja / PLaMo系トークナイザ)をそのまま使う必要があります。

Pythonでの動作確認例

import coremltools as ct
import numpy as np
from transformers import AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained("cl-nagoya/ruri-v3-310m")
model = ct.models.MLModel("ruri-v3-310m_seq128_int8.mlpackage")

text = "検索文書: 瑠璃色(るりいろ)は、紫みを帯びた濃い青のことである。"
encoded = tokenizer([text], return_tensors="np", padding="max_length", truncation=True, max_length=128)
output = model.predict({
    "input_ids": encoded["input_ids"].astype(np.int32),
    "attention_mask": encoded["attention_mask"].astype(np.int32),
})
print(output["sentence_embedding"].shape)  # (1, 768)

変換方法(再現手順)

このリポジトリのモデルは ruri_coreml_convert 変換ツールで生成されています。手順の概要:

  1. transformers の AutoModel で ModernBERT ベースの ruri-v3 をロード
  2. mean pooling + L2 normalize を行う nn.Module でラップ
  3. torch.jit.trace でトレース(transformers.masking_utils.and_masks/or_masks が Tensor.new_ones/new_zeros を使っており Core ML コンバータが未対応のため、torch.ones/torch.zeros ベースの実装に差し替えてからトレース)
  4. coremltools.convert(..., convert_to="mlprogram") で .mlpackage を生成
  5. coremltools.optimize.coreml.linear_quantize_weights で int8 版も生成

ライセンス

ベースモデル cl-nagoya/ruri-v3-310m と同じ Apache License 2.0 です。オリジナルモデルの著作権は名古屋大学 conversational AI research group (cl-nagoya) に帰属します。本リポジトリは重みフォーマットの変換のみを行ったものです。

引用

@misc{ruri2024,
  title={{Ruri}: {J}apanese {G}eneral {T}ext {E}mbeddings},
  author={Hayato Tsukagoshi and Ryohei Sasano},
  year={2024},
  eprint={2409.07737},
  archivePrefix={arXiv},
  primaryClass={cs.CL},
}

備考

  • 本変換は非公式のコミュニティ版です。cl-nagoyaチームによる公式リリースではありません。
  • セキュリティー監査にはmodel-audit-liteを 使用しています(詳細はSECURITY.md)。

セキュリティー

model-audit-lite で変換元と突き合わせて監査済みです(重みの形式、同梱コード、機械可読な系譜=ML-BOM)。詳細・チェックサム・再現方法は SECURITY.md をご覧ください。

Downloads last month
33
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support

Model tree for masahiroid/ruri-v3-310m-coreml

Quantized
(14)
this model

Paper for masahiroid/ruri-v3-310m-coreml