はじめに
Oracle のデータベースは、ONNX フォーマットのモデルを取り込むことが可能です。
そのため、例えば Embedding モデルを ONNX フォーマットにエクスポートし、それをデータベースに取り込むことが出来ます。
結果として、ベクトル検索を実施する際に、外部の API を実行してテキスト データをベクトル変換する必要が無くなります。
データベースの中でベクトル化出来ることで、Rerank 処理時のクエリや候補文書を外部の Rerank API へ送信せずに済みます。
Embedding モデルをデータベースにインポートして利用する Qiita 記事は良く見るのですが、そう言えば Rerank モデルをインポートして利用する記事が無いなぁ……と思いました。
Embedding モデルを取り込む例 :
なので今回は実際に、Autonomous AI Database (ADB) に Rerank モデルを組み込んで、In-Database で Rerank 処理を行ってみたいと思います。
準備
ADB とスキーマの準備
ADB を作成します。
OCI 環境があれば簡単に作成出来ます。
次にテスト用のスキーマを作成します。
ADMIN ユーザーで下記のクエリを実行して、テスト用のスキーマを作成。
ADB のページから Database Actions を開いて、クエリを実行。
GRANT DWROLE, UNLIMITED TABLESPACE TO onnx_lab IDENTIFIED BY <パスワード>;
GRANT DB_DEVELOPER_ROLE TO onnx_lab;
GRANT CREATE MINING MODEL TO onnx_lab;
GRANT CREATE CREDENTIAL TO onnx_lab;
その後、作成したスキーマに対して REST サービスを有効化する。
次に作成したスキーマでログインして、下記のクエリを実行する。
Object Storage へアクセスして ONNX フォーマットのモデルをインポートするために必要だからです。
パラメーター値は適宜変更します。
BEGIN
DBMS_CLOUD.CREATE_CREDENTIAL (
credential_name => 'OCI_CRED',
user_ocid => 'ocid1.user.oc1..xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
tenancy_ocid => 'ocid1.tenancy.oc1..xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
private_key => '-----BEGIN PRIVATE KEY-----
プライベート キーの値
-----END PRIVATE KEY-----',
fingerprint => '5d:d6:xxxxxxxxxxxx:3a'
);
END;
/
ONNX フォーマットのモデルを作成
OML4Py Slim Client のインストール
Autonomous AI Database に ONNX フォーマットの Rerank モデルや Embedding モデルを取り込むには、モデルの作成が必要です。
作成するためには OML4Py Slim Client が必要なので、それを準備します。
こちらのサイトを見ると、Python 3.13.5 が必要とのこと。
私の WSL2 (Ubuntu) 環境にて、下記のコマンドを実施。
事前に uv はインストール済み。
mkdir oml4py-lab
cd oml4py-lab
uv python install 3.13.5
uv venv --python 3.13.5 .venv
source .venv/bin/activate
python --version を実行。
問題なくインストール出来ていることを確認。
下記のサイトから oml4py-client-linux-x86_64-2.1.1.zip を DL し、Ubuntu 環境へコピー。
unzip oml4py-client-linux-x86_64-2.1.1.zip を実行して解凍。
Oracle が OML4Py 2.1.1 Slim Client 用として指定している PyPI 側のバージョンはこちら。
こちらを実行して、必要なパッケージをインストール出来るようにする。
cat > requirements-slim.txt <<'EOF'
numpy==2.1.0
pillow==10.4.0
onnxruntime==1.20.0
onnxruntime-extensions==0.14.0
onnx==1.18.0
torch==2.9.0
transformers==4.56.1
sentencepiece==0.2.1
EOF
下記コマンドを実行して、必要なパッケージをインストール。
uv pip install \
--torch-backend cpu \
-r requirements-slim.txt
OML4Py Slim Client をインストールします。
uv pip install \
--no-deps \
./client/slim/oml-2.1.1-cp313-cp313-linux_x86_64.whl
インストール出来たことを確認するため、下記のコマンドを実行。
問題なく出来てそうです。
python - <<'PY'
import oml
from oml.utils import ONNXPipeline
from oml.utils import ONNXPipelineConfig
from oml.utils import MiningFunction
print("OML4Py ONNX utilities: OK")
PY
早速 Rerank モデルを ONNX フォーマットにエクスポートする処理を Python スクリプトに実装します。
下記公開情報を見ると、このように記載があります。
Pre-processing for reranking pipeline includes tokenization. The tokenizer class: transformers.models.xlm_roberta.tokenization_xlm_roberta.XLMRobertaTokenizer is supported in OML4Py 2.1 for reranking models.
XLMRobertaTokenizer の Tokenizer がサポートしているとの事なので、日本語に対応していて XLMRobertaTokenizer の Tokenizer を使っている Rerank モデルを探します。
結果、hotchpotch/japanese-reranker-cross-encoder-xsmall-v1 を使ってみようと思います。
ONNX フォーマットでエクスポートするために、下記の Python スクリプトを作成します。
Hugging Faceで公開されているPyTorch形式のモデルを、OML4PyのONNXPipelineを使って、Tokenizerを含むOracle Database向けのONNXモデルへ変換します。
from oml.utils import (
ONNXPipeline,
ONNXPipelineConfig,
MiningFunction,
)
MODEL_NAME = "hotchpotch/japanese-reranker-cross-encoder-xsmall-v1"
OUTPUT_NAME = "japanese-reranker-cross-encoder-xsmall-v1"
config = ONNXPipelineConfig.from_template(
"text",
max_seq_length=512,
)
print(f"Loading model: {MODEL_NAME}")
pipeline = ONNXPipeline(
MODEL_NAME,
config=config,
function=MiningFunction.REGRESSION,
)
print("Exporting ONNX model...")
pipeline.export2file(
OUTPUT_NAME,
output_dir=".",
)
print(f"Done: {OUTPUT_NAME}.onnx")
ADB へモデルをインポート
まずは、Object Storage に作成した ONNX フォーマットのモデルをアップロードします。
次に、Database Actions からテスト用に作成したスキーマにログイン。
下記のコマンドを実行して、ONNX フォーマットのモデルをインポートします。
DECLARE
l_result CLOB;
BEGIN
l_result := DBMS_VECTOR_DATABASE.LOAD_MODEL(
model_name => 'RERANK_MODEL',
url => '<Object Storage にアップロードしたモデルの URL>',
model_params => JSON(
'{
"credential": "OCI_CRED",
"metadata": {
"function": "regression",
"regressionOutput": "output",
"input": {
"first_input": ["DATA1"],
"second_input": ["DATA2"]
}
}
}'
)
);
DBMS_OUTPUT.PUT_LINE(l_result);
END;
/
これで Rerank モデルの取り込み完了です。
Rerank 処理を試す
実際に下記のクエリを実行し、ハイブリッド検索結果を模擬したデータに対してRerankを実行します。
WITH hybrid_results AS (
/*
* ハイブリッド検索によって取得された Top 5 を模擬。
*
* vector_score : ベクトル検索側のスコア
* text_score : キーワード検索側のスコア
* hybrid_score : 両者を統合した検索スコア
*/
SELECT
101 AS doc_id,
VECTOR('[0.91, 0.12, 0.31, 0.44]', 4, FLOAT32) AS vector_data,
'CREATE VECTOR INDEX文を実行すると、ベクトル列に新しいベクトルインデックスを作成できます。'
AS passage_text,
0.94 AS vector_score,
0.97 AS text_score,
0.955 AS hybrid_score
FROM dual
UNION ALL
SELECT
102,
VECTOR('[0.88, 0.15, 0.29, 0.41]', 4, FLOAT32),
'既存のベクトルインデックスを削除するには、DROP INDEX文を実行します。',
0.91,
0.88,
0.895
FROM dual
UNION ALL
SELECT
103,
VECTOR('[0.81, 0.20, 0.34, 0.38]', 4, FLOAT32),
'ベクトルインデックスの状態や名前はデータディクショナリから確認できます。',
0.85,
0.82,
0.835
FROM dual
UNION ALL
SELECT
104,
VECTOR('[0.74, 0.29, 0.27, 0.33]', 4, FLOAT32),
'VECTOR_DISTANCE関数を使用すると、2つのベクトル間の距離を計算できます。',
0.79,
0.71,
0.750
FROM dual
UNION ALL
SELECT
105,
VECTOR('[0.62, 0.35, 0.18, 0.22]', 4, FLOAT32),
'表そのものを削除する場合はDROP TABLE文を使用します。',
0.68,
0.63,
0.655
FROM dual
),
/*
* Hybrid Search 時点での順位
*/
hybrid_ranked AS (
SELECT
h.*,
ROW_NUMBER() OVER (
ORDER BY hybrid_score DESC
) AS hybrid_rank
FROM hybrid_results h
),
/*
* Top 5 に対して Reranker を実行
*/
rerank_scored AS (
SELECT
h.*,
PREDICTION(
RERANK_MODEL
USING
'既存のベクトルインデックスを削除するにはどうすればよいですか?'
AS DATA1,
passage_text
AS DATA2
) AS rerank_score
FROM hybrid_ranked h
),
/*
* Rerank 後の順位
*/
rerank_ranked AS (
SELECT
r.*,
ROW_NUMBER() OVER (
ORDER BY rerank_score DESC
) AS rerank_rank,
1 / (1 + EXP(-rerank_score))
AS rerank_sigmoid
FROM rerank_scored r
)
SELECT
hybrid_rank,
rerank_rank,
CASE
WHEN rerank_rank < hybrid_rank
THEN 'UP +' || (hybrid_rank - rerank_rank)
WHEN rerank_rank > hybrid_rank
THEN 'DOWN -' || (rerank_rank - hybrid_rank)
ELSE 'SAME'
END AS rank_change,
doc_id,
passage_text,
ROUND(vector_score, 3) AS vector_score,
ROUND(text_score, 3) AS text_score,
ROUND(hybrid_score, 3) AS hybrid_score,
ROUND(rerank_score, 3) AS rerank_score,
ROUND(rerank_sigmoid, 3) AS rerank_sigmoid
FROM rerank_ranked
ORDER BY rerank_rank;
prediction(...) を実行することで Rerank 処理が行われます。
prediction(...) が返す値は、2 テキスト間の Rerank score (logit/未正規化の類似度スコア) です。
値の範囲は -∞ ~ +∞ で、値が大きいほど検索キーワードと候補文書の関連性が高いです。
上記のクエリですが、「ハイブリッド検索ではキーワード一致の強い誤候補が1位 → Rerank 後は質問意図に合う候補が1位」 というシナリオを想定してみました。
例えば RAG アーキテクチャでナレッジ検索を行う場合、下記のような流れかなと思います。
- ユーザーがナレッジとなる情報を保存する
- 保存のタイミングで、そのデータを「Chunking → Embedding → 保存」する (Pipeline 処理)
- ユーザーが自然言語で検索する
- バックエンド側でベクトル検索 or テキスト検索も含めたハイブリッド検索を実施、該当するナレッジ情報とともに LLM へ渡す
この時の工程 4 でもし誤ったナレッジ情報が上位の候補としてピックアップされると、期待どおりナレッジ検索が出来ないかなと思います。
そういう場合に Rerank 処理が精度向上の役に立ちます。それを、上記クエリで再現してみました。
個人的な感想
Embedding モデルと Rerank モデルを ADB に取り込むことで、外部へのデータ送信を最小限に出来るかなと思います。
ただ一方で、大量のユーザーがアクセスすることで Embedding 処理や Rerank 処理も大量に実行され、CPU リソースをバカ食いしちゃう可能性もあります。
そのため Resource Manager を用いて CPU の使用上限を指定したり、CPU / I/O の相対的な配分比率をコンシューマー グループごとで指定するなど対策が必要になるかもしれません。
あとは、ADB は MCP サーバーの機能が実装されています。
例えば MCP サーバーの Tool として、「ハイブリッド検索 と Rerank 処理を組み合わせた自然言語での検索ツール」を ADB に定義することで、AI エージェントとしても魅力的な機能を提供出来るかなぁと思います。
例えば Azure の話にはなりますが、Foundry IQ (元 Azure AI Search) のナレッジ ソースとして、MCP を指定することが可能です。
なので AI 用データ基盤として ADB (Autonomous Database@Azure とか) を利用。
ETL のようなデータ処理パイプラインでナレッジ情報などを ADB に保存。
今回の Rerank 処理や Embedding モデルの取り込みなどを組み合わせて、Microsoft Foundry に作成した AI Agent と連携させても面白いなと思いました。




