Pythonを使用したOracle AI DatabaseでのONNX埋込みワークフローの構築 (2026/04/18)

Pythonを使用したOracle AI DatabaseでのONNX埋込みワークフローの構築 (2026/04/18)

ONNX埋込みモデルのインポート、埋込みの生成およびOracle AI Databaseでのセマンティック検索の実行に関する実用的なガイド

https://medium.com/oracledevs/building-onnx-embedding-workflows-in-oracle-ai-database-with-python-80e6dfdfcee0

投稿者:Daniela Pavlenco

関連ノートブック:Oracle AI Database 26ai を使用した ONNX データベース内埋め込み

Enterキーを押すか、画像をクリックしてフルサイズで表示します。
Oracle AI DatabaseにおけるONNX埋め込み

主なポイント

  • Oracle AI Database は、 DBMS_VECTOR.LOAD_ONNX_MODEL()を使用して拡張 ONNX 埋め込みモデルをロードおよび登録できます
  • VECTOR_EMBEDDING()を使用すると、SQLで埋込みをOracle AI Database内で直接生成できます。
  • 埋め込みデータは、VECTORカラム内にネイティブに保存できます
  • VECTOR_DISTANCE()は、SQLでセマンティク検索を直接有効にします。
  • LangChainは、埋め込みや取得をデータベースの外に移動することなく、同じOracleネイティブのワークフローに基づいて構築できます(LangChain Oracleベクターストア統合)。

学習内容

  • Oracle AI Databaseに拡張ONNXモデルをロードする方法。
  • VECTOR_EMBEDDING()を使ってSQL で直接埋め込みを生成する方法
  • Oracle AI DatabaseとLangChainフレームワークでVECTOR_DISTANCE()を使用してセマンティック検索を実行する方法。

アーキテクチャ概要

このワークフローでは、モデルの実行、ベクトルの保存、および意味的検索は Oracle AI Database 内に保持されます。拡張 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-communitylangchain-oracledbなど依存関係
  • クラウドへのロードの場合:Oracle Cloud Object StorageバケットとモデルURI(またはPAR URL)
  • PAR URLを使用しない場合は、オブジェクトストレージ認証情報を作成します。DBMS_CLOUD.CREATE_CREDENTIAL

ノートブックでは、これらのパッケージは事前にインストールされています。

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 ( "パッケージがインストールされました。" if result.returncode == 0 else f"インストールに失敗しました: {result.stderr} " )

この例では、Oracle AI Database 26aiがコンテナ内で実行されており、ONNXモデルファイル用のマウントされたディレクトリが存在することを前提としています。このマウントされたディレクトリは、後で重要になります。なぜなら、Oracleはアドホックなファイルアクセスではなく、データベースディレクトリオブジェクトを介してモデルにアクセスするからです。

ステップバイステップガイド

ステップ1:Oracleが拡張ONNXモデルを必要とする理由を理解する

このワークフローにおける最も重要な点の1つは、Oracleが標準的なトランスフォーマーエクスポートだけでなく、拡張されたONNXモデルを必要とするということです。

VECTOR_EMBEDDING()がRAWテキストを直接受け入れるには、トークン化および関連する前処理を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モデルディレクトリの登録を行うための、一度限りの管理者設定が含まれています。実行時に重要な部分は次のとおりです。

  • 必要な権限を持つデータベースユーザー、
  • マイニングモデルをロードする許可、
  • 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 から呼び出されます。

Enterキーを押すか、画像をクリックしてフルサイズで表示します。

ステップ2b:クラウドオプション - Oracle Object StorageからONNXをロードする

Oracleは、Oracle Cloud Object StorageからONNXモデルをロードすることもサポートしていますDBMS_VECTOR.LOAD_ONNX_MODEL_CLOUD()。これは、付属のノートブックで使用されているローカルディレクトリワークフローに代わる、文書化された方法です。

Oracleのドキュメントによると、標準のオブジェクトストレージURIには認証情報を使用し、credential => NULL事前認証リクエスト(PAR)URLには認証情報を渡してください。

-- オプション A: 通常のオブジェクト ストレージ URI (認証情報が必要) 
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 (資格情報は 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'
); </ bucket > </ namespace > </ par-token > </ region > </ bucket > </ namespace > </ region >

注: 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ネイティブに組み込み続けることが可能になります。

これにより、モデルアーティファクトのホスティングをOCI外で行いながら、生成と意味的検索をOracleネイティブに組み込み続けることが可能になります。

import os 
import requests

model_url = os.environ[ "MODEL_SIGNED_URL" ] # S3 事前署名 URL / GCS 署名 URL / Drive 直接 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()

with open (target_path, "wb" ) as f:
for chunk in resp.iter_content(chunk_size= 1024 * 1024 ):
if chunk:
f.write(chunk)

print ( f"モデルが{target_path}にダウンロードされました" )
BEGIN
DBMS_VECTOR.LOAD_ONNX_MODEL(
directory => 'ONNX_DIR',
file_name => 'all_MiniLM_L12_v2.onnx',
model_name => 'ALL_MINILM_L12_V2'
);
END;
/

ステップ3:PythonからOracle AI Databaseに接続する

このノートブックはpython-oracledb ThinsモードでOracle AI Databaseに接続するため、Oracleクライアントライブラリは不要です。

import oracledb 

connection = oracledb.connect(...)
print ( "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データベースに対してSQLを実行します。"""
with conn.cursor() as cur:
if many and 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()

ステップ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入力テキストをモデルグラフにどのようにマッピングするかを定義し、どの出力ノードを埋め込みベクトルとして使用すべきかを特定します。ノートブックでは、ワークフローはモデルを再ロードする前に、モデルが既に存在するかどうかも確認します。これにより、再実行がより安全になり、ワークフローの冪等性が維持されます。

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 モデルが既に登録されているかどうかが確認されるため、再実行しても冪等性が維持されます。

ステップ5:Oracleがモデルを正しく登録したことを確認します。

インポート後、次のステップはOracleがモデルを認識していることを確認することです。

このノートブックは、モデルカタログにクエリを実行して、ONNXモデルが正常にロードされたことを確認します。

SELECT model_name, mining_function, algorithm 
FROM user_mining_models
WHERE model_name = 'ALL_MINILM_L12_V2' ;

これはワークフローの小さな部分ですが、重要な部分です。モデルが登録済みオブジェクトとしてOracleに認識され、後続のベクトル関数で使用できる状態になっていることを確認します。

期待される出力:クエリは、USER_MINING_MODELSから登録された ONNX モデルを返します

ステップ6:VECTOR_EMBEDDING()を使用してSQLで埋め込みを生成する

モデルが登録されると、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次元の埋め込みを返します。

ステップ7:埋め込みをネイティブVECTOR列に格納する

埋め込み生成の検証後、ノートブックはソーステキストとその埋め込みが一緒に格納されるテーブルを作成します。

CREATE  TABLE onnx_docs ( 
id NUMBER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
category VARCHAR2( 100 ),
doc_text CLOB ,
embedding VECTOR( 384 , FLOAT32)
);

これは重要な設計上の選択です。ベクトルは不透明なブロブや外部ペイロードとして格納されるのではなく、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列内の行とともに格納されます。

Enterキーを押すか、画像をクリックしてフルサイズで表示します。

ノートブックは、データ取得に進む前に、挿入された行を検査します。

SELECT id, category, DBMS_LOB.SUBSTR(doc_text, 120 , 1 ) AS preview 
FROM onnx_docs
ORDER BY id;

ステップ8:SQLとLangChainでセマンティック検索を実行する

埋込みが格納されると、セマンティック取得は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 = [ 
"Oracleのどの機能が意味検索に役立ちますか?" ,
"データベースに埋め込みを保存できますか?" ,
"LangChainはOracleベクトルとどのように連携しますか?" ,
"ONNXモデルはなぜここで役立つのですか?"
]

図3。クエリ実行時に、Oracleは入力テキストを埋め込み、VECTOR_DISTANCE()を使用して格納されているベクトルと比較し、SQLを介して最も近い意味的一致を直接返します。

Enterキーを押すか、画像をクリックしてフルサイズで表示します。

次に、ノートブックは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 はベクトルを使用してセマンティック検索を実行します。"
)

print ( f"埋め込み次元: { len (lc_embedding)} " )
print ( f"最初の 5 つの値: {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 supports vector storage and semantic search."),
Document(page_content="An ONNX embedding model can be loaded directly into Oracle."),
Document(page_content="LangChain can use OracleVS to query Oracle AI Vector Search."),
Document(page_content="Using in-database embeddings can reduce architectural complexity."),
]

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は、DBMS_VECTOR.LOAD_ONNX_MODEL_CLOUD()認証情報またはPAR URLのいずれかを使用して、Oracle Cloud Object Storage内のモデルをサポートしています。

LangChainは埋め込みデータをOracleの外に移動させるのですか?
いいえ。LangChainはより高レベルのインターフェースを提供しますが、モデルの実行とベクトル検索は依然としてOracle内で実行されます。

これは、別途用意していたベクトルデータベースを置き換えるものですか?
多くのユースケースにおいて、はい。Oracleは、データベース内でベクトルデータの保存と検索をネイティブに提供します。

コメント

このブログの人気の投稿

Oracle Database 19cサポート・タイムラインの重要な更新 (2024/11/20)

ミリ秒の問題: BCCグループとOCIが市場データ・パフォーマンスを再定義する方法(AWSに対するベンチマークを使用) (2025/11/13)

OCIのカスタム・ルート表を使用した詳細なルーティング制御 (2025/02/27)