Oracle AI DatabaseでONNX埋め込みモデルをインポートし、埋め込みを生成してセマンティック検索を実行するための実践ガイド
連携ノートブック: ONNX In-Database Embeddings with Oracle AI Database 26ai
要点
- Oracle AI Databaseは、DBMS_VECTOR.LOAD_ONNX_MODEL() を使って、拡張(augmented)ONNX埋め込みモデルを読み込み、登録できます。
-
VECTOR_EMBEDDING()により、SQLがOracle AI Database内で直接埋め込みを生成できます。 - 埋め込みはネイティブな
VECTOR列に格納できます。 -
VECTOR_DISTANCE()により、SQL内で直接セマンティック検索が可能になります。 - LangChainは、同じOracleネイティブのワークフローを、埋め込みや検索(リトリーバル)をデータベースの外へ移動することなく構築できます(LangChain Oracle ベクターストア統合)。
これが重要な理由
多くの埋め込みパイプラインでは、ソースデータはリレーショナル・データベースに存在し、モデルはどこか別の場所で外部サービスとして実行され、ベクトルは別のベクターデータベースに格納されます。このアーキテクチャはうまく機能し得るものの、追加のデータ移動、インフラストラクチャ、そして運用上の複雑さが生じます。
Oracle AI Databaseは、より統合されたアプローチをサポートしています。ONNX の埋め込みモデルをデータベースに直接読み込み、呼び出し、生成された埋め込みをネイティブな VECTOR 列に格納し、同じデータベースでセマンティック検索を実行できます。
この記事では、ONNXモデルを使ったそのエンドツーエンドのワークフローを説明します。つまり、Oracle AI Databaseに読み込み、正しく登録されていることを検証し、SQLで埋め込みを生成し、それをネイティブなベクター列に格納し、セマンティックな類似度によってクエリします。また、埋め込みと検索(リトリーバル)が行われる場所を変えずに、同じアーキテクチャをLangChainで使う方法も示します。
学べること
- Oracle AI Databaseで拡張(augmented)ONNXモデルを読み込む方法。
-
VECTOR_EMBEDDING()を使ってSQL内で直接埋め込みを生成する方法。 - Oracle AI DatabaseおよびLangChainを通じて、
VECTOR_DISTANCE()でセマンティック検索を実行する方法。
アーキテクチャ概要
このワークフローでは、モデルの実行、ベクトルの格納、セマンティックな取得(リトリーバル)をOracle AI Databaseの内部に維持します。拡張(augmented)されたONNXモデルは、Oracleのディレクトリ・オブジェクトとして公開され、DBMS_VECTOR.LOAD_ONNX_MODEL() で読み込まれ、VECTOR_EMBEDDING() で呼び出され、VECTOR_DISTANCE() でクエリされます。モデル成果物(アーティファクト)は、ローカルまたはコンテナにマウントされたパスのいずれかから取得できます。あるいは、DBMS_VECTOR.LOAD_ONNX_MODEL_CLOUD() を使って、Oracle Cloud Object Storage から直接取得することもできます。LangChainは、OracleEmbeddings と OracleVS を通じて、同じOracleネイティブの実行パスをベースに構築できます。
前提条件
- Python 3.10+
- コンテナで実行されている Oracle AI Database 26ai
-
oracledb,python-dotenv,pandas,numpy,langchain,langchain-community,langchain-oracledbなどの依存関係 - クラウドでの読み込みの場合: Oracle Cloud Object Storage のバケットとモデルURI、またはPARのURL
- PARのURLを使わない場合は、
DBMS_CLOUD.CREATE_CREDENTIALで作成したObject Storageの資格情報
ノートブックでは、これらのパッケージが事前にインストールされます:
import subprocess
import sys
result = subprocess.run(
[sys.executable, "-m", "pip", "install", "-q",
"oracledb", "python-dotenv", "pandas", "numpy",
"langchain", "langchain-core", "langchain-community", "langchain-oracledb"],
capture_output=True, text=True
)
print("Packages installed." if result.returncode == 0 else f"Install failed: {result.stderr}")
この例では、Oracle AI Database 26ai がコンテナで実行されており、ONNXモデルファイル用のディレクトリがマウントされていることも前提としています。このマウントされたディレクトリは後で重要になります。Oracleは、アドホックなファイルアクセスではなく、データベースのディレクトリ・オブジェクト経由でモデルにアクセスするためです。
手順ガイド
手順 1: Oracleが拡張(augmented)ONNXモデルを必要とする理由を理解する
このワークフローで最も重要な詳細の1つは、Oracleが拡張(augmented)ONNXモデルを必要としており、単なる標準のトランスフォーマーのエクスポートだけでは不十分だという点です。
VECTOR_EMBEDDING() が生のテキストを直接受け取るには、トークン化や関連する前処理をONNXグラフ自体に含める必要があります。これにより、OracleはPythonでの外部前処理に頼ることなく、通常のテキスト文字列から埋め込みを生成できます。
ノートブックで使用するモデルは、all-MiniLM-L12-v2 の拡張バージョンです:
MODEL_NAME = "all_MiniLM_L12_v2"
ONNX_FILE = "all_MiniLM_L12_v2.onnx"
そのような拡張パッケージングがなければ、事前処理はまずデータベースの外で行う必要があるため、フローはもはや完全にOracleネイティブではなくなってしまいます。
ステップ 2: Oracle AI Database 用に ONNX モデルを準備する
モデルをSQLで使用できるようにする前に、Oracleはデータベースディレクトリオブジェクトを通じてONNXファイルへの制御されたアクセスを必要とします。これはファイルシステム上の場所へのデータベース管理の参照であり、モデル成果物へのアクセスは、ファイルシステムを直接前提にするのではなく、Oracleの権限を通して処理されることを意味します。
ノートブックには、ユーザーの作成、権限の付与、ONNXモデルディレクトリの登録を行う1回限りの管理者セットアップが含まれています。実行時に重要な要素は次のとおりです:
- 必要な権限を持つデータベースユーザー
- マイニングモデルをロードするための許可
ONNX_DIRのように登録されたOracleディレクトリ- コンテナの内部からONNXファイルへアクセスできること
ディレクトリ設定の簡略版は次のようになります:
CREATE OR REPLACE DIRECTORY ONNX_DIR AS '/opt/oracle/onnx_models';
GRANT READ, WRITE ON DIRECTORY ONNX_DIR TO my_user;
この点が重要なのは、モデルのインポートがアドホックなファイル操作として扱われないためです。ファイルは制御されたデータベースオブジェクトを通じてOracleに公開されるため、企業のガバナンスに対する期待により一層合致します。
図 1. 拡張されたONNXモデルは、Oracleディレクトリオブジェクトを通じて公開され、DBMS_VECTOR.LOAD_ONNX_MODEL() で読み込まれ、Oracleに登録され、その後SQLから呼び出されます。
ステップ 2b: クラウドオプション - Oracle Object Storage から ONNX をロードする
Oracleは、DBMS_VECTOR.LOAD_ONNX_MODEL_CLOUD() を使って、Oracle Cloud Object Storage から ONNX モデルを読み込むこともサポートしています。これは、同梱のノートブックで使われているローカルディレクトリのワークフローに対するドキュメント化された代替手段です。
Oracleのドキュメントに従い、標準的な Object Storage のURIには資格情報(credential)を使用し、プリオーセンティケーテッドリクエスト(PAR)URL に対しては credential => NULL を渡します。
-- オプションA: 通常のObject Storage URI(credentialが必要)
EXECUTE DBMS_VECTOR.LOAD_ONNX_MODEL_CLOUD(
model_name => 'ALL_MINILM_L12_V2',
credential => 'OBJ_STORE_CRED',
uri => 'https://objectstorage.<region>.oraclecloud.com/n/<namespace>/b/<bucket>/o/all_MiniLM_L12_v2.onnx',
metadata => JSON('{
"function":"embedding",
"embeddingOutput":"embedding",
"input":{"input":["DATA"]}
}')
);
-- オプションB: PAR URL(credentialはNULLである必要がある)
EXECUTE DBMS_VECTOR.LOAD_ONNX_MODEL_CLOUD(
model_name => 'ALL_MINILM_L12_V2',
credential => NULL,
uri => 'https://objectstorage.<region>.oraclecloud.com/p/<par-token>/n/<namespace>/b/<bucket>/o/all_MiniLM_L12_v2.onnx'
);
注: Oracleのドキュメントによれば、metadata はOracleのPythonユーティリティのデフォルトで準備されたモデルでは省略可能であり、モデル名はOracleの命名規則に従う必要があり、クラウド読み込みのONNXファイルサイズ制限は2 GBです。
ステップ 2c: マルチクラウドの注意(AWS/GCP/Google Drive)
DBMS_VECTOR.LOAD_ONNX_MODEL_CLOUD() は Oracle Cloud Object Storage 用としてドキュメント化されています。モデル成果物がAWS S3、Google Cloud Storage、またはGoogle Driveでホストされている場合は、移植可能な2ステップのパターンを使用します。つまり、ONNXファイルをデータベースからアクセス可能なローカルパスにダウンロードし、その後 DBMS_VECTOR.LOAD_ONNX_MODEL() で読み込みます。
これにより、OCIの外でモデル成果物をホストできる一方で、埋め込み生成とセマンティック検索はOracleネイティブのまま維持されます。
import os
import requests
model_url = os.environ["MODEL_SIGNED_URL"] # S3 pre-signed URL / GCS signed URL / Drive direct URL
target_path = "/opt/oracle/onnx_models/all_MiniLM_L12_v2.onnx"
resp = requests.get(model_url, stream=True, timeout=180)
resp.raise_for_status()
BEGIN
DBMS_VECTOR.LOAD_ONNX_MODEL(
directory => 'ONNX_DIR',
file_name => 'all_MiniLM_L12_v2.onnx',
model_name => 'ALL_MINILM_L12_V2'
);
END;
/
Step 3: Python から Oracle AI Database に接続する
このノートブックは python-oracledb を Thin モードで使用して Oracle AI Database に接続するため、Oracle クライアントライブラリは不要です:
import oracledb
conn = oracledb.connect(...)
print("Connected to Oracle AI Database")
その同じ接続は、ノートブック後半の SQL の例や LangChain の統合でも再利用されます。
ノートブックの可読性を保つため、SQL を実行し、必要に応じて結果を pandas の DataFrame として返す小さなヘルパー関数を定義します:
import pandas as pd
def run_sql(sql, params=None, fetch=False, many=False, data=None):
"""Oracle Database に対して SQL を実行します。"""
with conn.cursor() as cur:
if manyand data:
cur.executemany(sql, data)
elif params:
cur.execute(sql, params)
else:
cur.execute(sql)
if fetch:
cols = [c[0] for c in cur.description]
return pd.DataFrame(cur.fetchall(), columns=cols)
conn.commit()
この例では、Oracle AI Database 26ai がコンテナ内で実行されており、ONNX モデルファイル用のマウントディレクトリが用意されていることも前提としています。このマウントディレクトリは後で重要になります。というのも、Oracle は ad hoc なファイルアクセスではなく、データベースのディレクトリオブジェクト経由でモデルにアクセスするためです。
Step 4: ONNX 埋め込みモデルを Oracle AI Database に読み込む
このノートブックは、ONNX モデルがすでに存在していることを前提にしていません。ファイルが見つからない場合は、公式の事前構築済みの拡張モデルをダウンロードし、Oracle が使用するモデルディレクトリに配置します。
モデルファイルが、Oracle のディレクトリオブジェクト経由であっても、クラウド URI 経由であっても、DBMS_VECTOR.LOAD_ONNX_MODEL() または DBMS_VECTOR.LOAD_ONNX_MODEL_CLOUD() を使ってインポートできます。
ローカルディレクトリ呼び出しの簡略版は次のようになります:
BEGIN
DBMS_VECTOR.LOAD_ONNX_MODEL(
directory => 'ONNX_DIR',
file_name => 'all_MiniLM_L12_v2.onnx',
model_name => 'ALL_MINILM_L12_V2',
metadata => JSON('{
"function":"embedding",
"embeddingOutput":"embedding",
"input":{"input":["DATA"]}
}')
);
END;
/
ここが、モデルが「ファイル」から「それ以上のもの」になるポイントです。Oracle はそれを登録し、関連するメタデータを保存し、SQL から直接呼び出せる名前付きオブジェクトとして公開します。
メタデータは特に重要です。これは、Oracle が SQL の入力テキストをモデルグラフへどのようにマッピングするかを定義し、どの出力ノードを埋め込みベクトルとして使用すべきかを特定します。ノートブックでは、読み込み直す前にモデルがすでに存在するかどうかもワークフローが確認します。これにより再実行が安全になり、ワークフローが冪等性(idempotent)を保てます。
model_check = run_sql(
"SELECT COUNT(*) AS cnt FROM USER_MINING_MODELS WHERE MODEL_NAME = UPPER(:model_name)",
params={"model_name": MODEL_NAME},
fetch=True
)
期待される出力: モデルチェックによって ONNX モデルがすでに登録されているかどうかが確認されるため、再実行は冪等性を保ちます。
Step 5: Verify that Oracle registered the model correctly
インポート後の次のステップは、Oracle がモデルを正しく認識していることを検証することです。
ノートブックでは、モデルカタログに対する問い合わせによって、ONNX モデルが正常に読み込まれたことを確認します:
SELECT model_name, mining_function, algorithm
FROM user_mining_models
WHERE model_name = 'ALL_MINILM_L12_V2';
これは小さいものの重要なワークフローの一部です。登録済みのオブジェクトとしてモデルが Oracle に見える状態になっており、次に行うベクトル関数で使用できる準備が整っていることを確認します。
期待される出力: クエリが USER_MINING_MODELS から登録済みの ONNX モデルを返します。
Step 6: Generate embeddings in SQL with VECTOR_EMBEDDING()
モデルが登録されると、Oracle は VECTOR_EMBEDDING() を通じてそれを直接利用できます。
ノートブックではまず、簡単なテキスト入力で動作確認し、返されるベクトルのサイズが期待どおりであることを確かめます。
SELECT VECTOR_EMBEDDING(
ALL_MINILM_L12_V2
USING 'Oracle Database supports vector search.' AS DATA
) AS embedding
FROM dual;
この記事の中でも最も重要な部分のひとつです。埋め込みの生成は、もはや別のサービス呼び出しではありません。SQL 操作になります:
- アプリケーションは外部の埋め込み API を呼び出す必要がない
- データベースが内部で埋め込みを生成できる
- 意味表現が、それが表すデータにより近い状態に保たれる
期待される出力: Oracle は、指定したテキストに対して 384 次元の埋め込みを返します。
Step 7: Store embeddings in a native VECTOR column
埋め込み生成を検証した後、ノートブックは、ソーステキストとその埋め込みが同じ場所に存在するテーブルを作成します。
CREATE TABLE onnx_docs (
id NUMBER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
category VARCHAR2(100),
doc_text CLOB,
embedding VECTOR(384, FLOAT32)
);
これは重要な設計上の選択です。ベクトルは不透明な BLOB や外部ペイロードとして保存しません。Oracle のネイティブ VECTOR 型として保存するため、リレーショナルデータと同じデータベースモデルの一部になります。
- ベクトルは、それが説明する正確な行にリンクされたままになる
- アクセス制御が一貫して適用される
- バックアップと保持ポリシーが統一されたままになる
- アプリケーションは複数のストレージシステムにまたがってデータを調整する必要がない
ノートブックはデモコンテンツを挿入し、同じ SQL ステートメントの中で埋め込みを直接生成します:
INSERT INTO onnx_docs (category, doc_text, embedding) VALUES ( 'database', 'Oracle AI Database supports in-database vector search and semantic retrieval.', VECTOR_EMBEDDING( ALL_MINILM_L12_V2 USING 'Oracle AI Database supports in-database vector search and semantic retrieval.' AS DATA ) );
意味表現は、行を書き込むと同時に、同じトランザクション境界の内部で作成されます。
図 2. 埋め込み生成は Oracle AI Database 内で、挿入時に行われます。ドキュメントテキストは VECTOR_EMBEDDING() を通じて埋め込まれ、VECTOR カラムの行と一緒に保存されます。
取得に入る前に、ノートブックは挿入された行を検査します:
SELECT id, category, DBMS_LOB.SUBSTR(doc_text, 120, 1) AS preview
FROM onnx_docs
ORDER BY id;
ステップ 8: SQL と LangChain でセマンティック検索を実行
埋め込み(embeddings)を保存したら、セマンティック取得はすべて Oracle の内部で処理されます。ノートブックでは VECTOR_DISTANCE() と VECTOR_EMBEDDING() を使用し、クエリ文はその場で埋め込んだうえで、保存済みのベクトルと比較します:
SELECT
id,
category,
DBMS_LOB.SUBSTR(doc_text, 200, 1) AS doc_preview,
VECTOR_DISTANCE(
embedding,
VECTOR_EMBEDDING(ALL_MINILM_L12_V2 USING 'How does Oracle support semantic search?' AS DATA),
COSINE
) AS distance
FROM onnx_docs
ORDER BY distance
FETCH FIRST 3 ROWS ONLY;
ユーザーのクエリは Oracle 内で直接埋め込まれ、そこで保存済みのドキュメント・ベクトルと比較されます。その後、結果は類似度でランキング付けされ、最も近いセマンティック一致が SQL を通じて返されます。
ノートブックは出力の解釈方法も明示的に説明します。コサイン距離が小さいほど、そのドキュメントはクエリに対してセマンティック的により類似しているということです。
ノートブックはさらに、さまざまな言い回しにわたってセマンティックな順位付けが意味を保つことを検証するために、いくつかのクエリを実行します:
test_queries = [
"Which Oracle feature helps semantic retrieval?",
"Can I store embeddings in the database?",
"How does LangChain work with Oracle vectors?",
"Why are ONNX models useful here?"
]
図 3. クエリ時、Oracle は入力テキストを埋め込み、VECTOR_DISTANCE() を使った距離検索で保存済みのベクトルと比較し、最も近いセマンティック一致を SQL を通じて順位付け結果として直接返します。
その後、ノートブックは LangChain を使って任意のフレームワーク層を追加します:
from langchain_oracledb.embeddings import OracleEmbeddings
from langchain_oracledb.vectorstores.oraclevs import OracleVS
OracleEmbeddings を使うことで、アプリケーションは Oracle の登録済みのデータベース内埋め込みモデルを利用できます:
oracle_embedder = OracleEmbeddings(
conn=conn,
params={"provider": "database", "model": MODEL_NAME}
)
ノートブックはまた、LangChain の埋め込み呼び出しが期待されるサイズのベクトルを返すことを検証します:
lc_embedding = oracle_embedder.embed_query(
"Oracle AI Database performs semantic search using vectors."
)
print(f"Embedding dimension: {len(lc_embedding)}")
print(f"First 5 values: {lc_embedding[:5]}")
その後、ノートブックは Oracle AI Vector Search をバックエンドに持つ、LangChain 対応のベクトルストアである OracleVS を使用します。
from langchain_core.documents import Document
from langchain_oracledb.vectorstores.oraclevs import OracleVS
from langchain_community.vectorstores.utils import DistanceStrategy
langchain_docs = [
Document(page_content="Oracle AI Database はベクターストレージとセマンティック検索をサポートします。"),
Document(page_content="ONNX 埋め込みモデルは Oracle に直接ロードできます。"),
Document(page_content="LangChain は OracleVS を使って Oracle AI Vector Search をクエリできます。"),
Document(page_content="データベース内での埋め込みの利用により、アーキテクチャの複雑さを軽減できます。"),
]
vector_store = OracleVS.from_documents(
documents=langchain_docs,
embedding=oracle_embedder,
client=conn,
table_name="LC_ONNX_DEMO",
distance_strategy=DistanceStrategy.COSINE
)
このノートブックでは、LangChain の抽象化を通じて類似度クエリも実行します。
results = vector_store.similarity_search(
"Oracle Database はセマンティックな取得にどのように役立てられますか?",
k=3
)
for i, doc in enumerate(results, start=1):
print(f"{i}. {doc.page_content}")
検証 & トラブルシューティング
DBMS_VECTOR.LOAD_ONNX_MODEL()またはDBMS_VECTOR.LOAD_ONNX_MODEL_CLOUD()の後に、モデルがUSER_MINING_MODELSに表示されることを確認してください。VECTOR_EMBEDDING()が、ロードしたモデルに対して 384 次元の埋め込みを返すことを確認してください。- セマンティックなランキングが意図したとおりでないように見える場合は、格納済みドキュメント埋め込みとクエリ埋め込みの両方に同じモデルが使用されていることを確認してください。
- クラウドでロードする場合は、URI または PAR の有効性、バケットパス、リージョン、および資格情報(クレデンシャル)の権限を確認してください。
- ノートブックを再実行するときは、モデルとデモテーブルが既に存在するかどうかを確認し、重複オブジェクトエラーを避けてください。
よくある質問
なぜ、外部 API を呼び出すのではなく Oracle にモデルをロードするのですか?
Oracle は SQL 内で直接埋め込みを生成できるため、外部依存関係を減らし、データと推論を同一のシステム境界内に保つことができます。
なぜモデルを拡張する必要があるのですか?
Oracle は、生のテキスト入力を直接受け取れる必要があります。そのためには、トークン化と前処理のロジックを、ONNX グラフ内に既に含めておく必要があります。
VECTOR_EMBEDDING() は何をしますか?
これは、Oracle 内に登録されたモデルを呼び出し、入力テキストに対する埋め込みベクトルを返します。
VECTOR 列には何が格納されますか?
モデルによって生成された数値の埋め込み表現を格納します。この例では、ベクターは 384 次元の FLOAT32 値です。
セマンティックな類似性はどのように計算されますか?
このワークフローでは、格納済みドキュメントベクトルと埋め込まれたクエリを比較するために、VECTOR_DISTANCE() をコサイン距離で使用します。
モデルは複数のアプリケーションで再利用できますか?
はい。いったん登録され、適切に権限付与されれば、Oracle 環境にアクセスできる任意のアプリケーションからモデルを呼び出せます。
ローカルでマウントしたディレクトリではなく、クラウドストレージからモデルをロードできますか?
はい。Oracle AI Database は、資格情報または PAR URL のいずれかを使って、Oracle Cloud Object Storage 内のモデルに対して DBMS_VECTOR.LOAD_ONNX_MODEL_CLOUD() をサポートしています。
LangChain は埋め込みを Oracle の外へ移動しますか?
いいえ。LangChain はより高レベルのインターフェースを提供しますが、モデルの実行とベクター検索はいずれも Oracle で行われます。
これは別のベクターデータベースを置き換えますか?
多くのユースケースでは、はい。Oracle はデータベース内でベクターストレージとベクター検索をネイティブに提供します。
関連ドキュメントおよび追加の読み物
- GitHub 上のコンパニオンノートブック
- Oracle Database 26ai ドキュメント
- Oracle AI Vector Search ユーザーガイド
- LOAD_ONNX_MODEL_CLOUD
- DBMS_VECTOR パッケージ参照
- VECTOR_EMBEDDING SQL 参照
- VECTOR_DISTANCE SQLリファレンス
- DBMS_CLOUDパッケージ・リファレンス
- Oracle JSONデベロッパーズ・ガイド
- Oracle Textアプリケーション・デベロッパーズ・ガイド
- Oracle SpatialおよびGraphドキュメント
- Oracle Databaseセキュリティ・ガイド
- LangChain Oracleベクトル・ストア統合







