はじめに
Oracle Database 23ai の AI Vector Search機能を使ってPDFファイルをEmbeddingし、類似性検索をすることができます。
簡単なテストを実施してみました。EmbeddingモデルにはOCI Generative AIサービスとOracle Database 23aiにインポート(ロード)したONNXモデルを使用しました。
作業ステップ
- 事前作業
- PDFファイルデータのEmbedding
- 類似性検索
事前作業
- ONNXフォーマットでのモデルのエクスポート
Oracle Database 23ai FreeとAPEXでRAGを使った生成AIアプリをローコード開発してみた (事前準備編)
こちらの記事の(オプション)の項を参考にHugging Face上にあるモデルをONNXフォーマットにエクスポートします。
sentence-transformers/all-MiniLM-L6-v2をエクスポートした例
$ python3
>>> from oml.utils import EmbeddingModel, EmbeddingModelConfig
>>> config = EmbeddingModelConfig.from_template("text",max_seq_length=512,quantize_model=True)
>>> em = EmbeddingModel(model_name="sentence-transformers/all-MiniLM-L6-v2", config=config)
>>> em.export2file("all-MiniLM-L6-v2",output_dir=".")
エクスポートしたファイル(all-MiniLM-L6-v2.onnx)をデータベースサーバー上のディレクトリオブジェクトが作成されているディレクトリにコピーします。
- 作業用データベースユーザの作成
PDBにSYSDBA権限で接続し、データベースユーザを作成し、「DB_DEVELOPER_ROLE」、「create mining model」権限を付与します。エクスポートしたONNXファイルを保管したディレクトリオブジェクトの操作権限を付与します。
$ export NLS_LANG=American_America.AL32UTF8
$ sqlplus / as sysdba
alter session set container=pdb1;
CREATE USER docuser identified by <password> DEFAULT TABLESPACE USERS quota unlimited on USERS;
GRANT DB_DEVELOPER_ROLE to docuser;
grant create mining model to docuser;
grant read on directory data_pump_dir to docuser;
grant write on directory data_pump_dir to docuser;
- PDFファイルの準備、PDFファイルデータの表への格納
操作権限を保持するディレクトリオブジェクトのディレクトリにPDFファイルを配置します。
作成したデータベースユーザでPDFファイル内容を表に取り込みます。
drop table documentation_tab purge;
CREATE TABLE documentation_tab (id number, data blob);
INSERT INTO documentation_tab values(1, to_blob(bfilename('BFILE_DIR','database-concepts.pdf')));
INSERT INTO documentation_tab values(2, to_blob(bfilename('BFILE_DIR','oracle-ai-vector-search-users-guide.pdf')));
INSERT INTO documentation_tab values(3, to_blob(bfilename('BFILE_DIR','fy24q3-tanshin-jp.pdf')));
commit;
PDFファイルデータのEmbedding
ONNXフォーマットにしたモデルのインポートしEmbedding
モデルのインポート(ロード)
DBMS_VECTOR.LOAD_ONNX_MODELプロシージャを使用して、エクスポートしたONNXファイル(all-MiniLM-L6-v2.onnx)をインポート(ロード)します。
引数
- ディレクトリオブジェクト名 : DATA_PUMP_DIR
- インポートするONNXファイル名 : all-MiniLM-L6-v2.onnx
- 登録するモデル名 : minilm_model
- JSON形式のメタ情報
- function : embedding (モデルの種類)
- embeddingOutput : emveddingOutput (生成されたエンベディングを保持するモデル出力)
- input : モデルの入力マッピングについて説明
EXECUTE DBMS_VECTOR.LOAD_ONNX_MODEL( 'DATA_PUMP_DIR', 'all-MiniLM-L6-v2.onnx', 'minilm_model', JSON('{"function" : "embedding", "embeddingOutput" : "embedding", "input": {"input": ["DATA"]}}'));
登録されたモデルの確認(user_mining_modelsビュー)
SELECT MODEL_NAME, MINING_FUNCTION, ALGORITHM,ALGORITHM_TYPE, MODEL_SIZE FROM user_mining_models ;
MODEL_NAME
------------------------------------------------------------------------------------------------------------------------
MINING_FUNCTION ALGORITHM ALGORITHM_ MODEL_SIZE
------------------------------ ------------------------------ ---------- ----------
MINILM_MODEL
EMBEDDING ONNX NATIVE 23026809
Embedding
PDFファイルデータの表のdata列(BLOB)をEmbedding対象列としてEmbeddingし、Embedding結果を表に格納します。
Embedding結果を格納する表の作成
drop table documentation_tab_minilm purge;
CREATE TABLE documentation_tab_minilm (
DOC number,
POS number,
SIZ number,
TXT CLOB,
embed_vector VECTOR
);
Embedding
ステップ
- data列(BLOB)をテキスト化(DBMS_VECTOR_CHAIN.UTL_TO_TEXTファンクション)
- テキスト化した結果を一定の分量に分割(VECTOR_CHUNKS関数)
- 分割したテキストをEmbedding(VECTOR_EMBEDDING関数)
INSERT INTO documentation_tab_minilm
SELECT D.id doc, C.chunk_offset pos, C.chunk_length siz, C.chunk_text txt, VECTOR_EMBEDDING(MINILM_MODEL USING C.chunk_text as data) embed_vector
FROM documentation_tab D, VECTOR_CHUNKS(dbms_vector_chain.utl_to_text(D.data)
BY words
MAX 150
OVERLAP 0
SPLIT BY sentence
LANGUAGE japanese NORMALIZE all) C;
COMMIT;
類似性検索
SELECT doc, pos, txt
FROM
documentation_tab_minilm ORDER BY VECTOR_DISTANCE(embed_vector,TO_VECTOR(VECTOR_EMBEDDING(MINILM_MODEL USING '&Keyword' as data)), EUCLIDEAN) fetch first 5 rows only;
Enter value for keyword: Performance
検索結果
DOC POS
---------- ----------
TXT
--------------------------------------------------------------------------------
1 1642523
Chapter 22
Topics for Database Administrators
The Oracle performance method is based on i
dentifying and eliminating bottlenecks i
n the
database, and developing efficient SQL statements. Ap
plying the Oracle performance method
involves the following tasks:
<以下略>
1 659880
Dynamic performance views contain information such as the fo
llowing:
<以下略>
1 1641693
Typical problems include:
~
CPU bottlenecks
~
Undersized memory structures
<以下略>
1 1673740
designed data model answer the most common queries a
s efficiently as possible. For
example, the data model should use the type of i
ndexes that provide the best
performance. Tuning after deployment is undesirabl
<以下略>
1 1649806
Besides reporting potential performance issues, ADDM documen
ts areas of the database
that are not problems. Subcomponents such as I/O and m
emory that are not significantly
<以下略>
5 rows selected.
OCI Generative AIのEmbeddingモデルを使ったEmbedding
- ネットワークACLの設定
データベースユーザーにホストに対する接続権限を付与
BEGIN
DBMS_NETWORK_ACL_ADMIN.APPEND_HOST_ACE(
host => '*',
ace => xs$ace_type(privilege_list => xs$name_list('connect'),
principal_name => 'docuser',
principal_type => xs_acl.ptype_db));
END;
/
- credentialの作成
OCI Generative AIサービスを利用するための credentialを作成します。
OCI CLIの構成ファイル情報を使います。- OCIユーザOCID
- テナンシーOCID
- コンパートメントOCID
- pem形式の秘密鍵(ファイルの内容を使用)
- API Keyフィンガープリント
exec dbms_vector.drop_credential('OCI_GENAI_CRED');
declare
jo json_object_t;
begin
jo := json_object_t();
jo.put('user_ocid','ocid1.user.oc1..aaaaaaaa');
jo.put('tenancy_ocid','ocid1.tenancy.oc1..aaaaaaaa');
jo.put('compartment_ocid','ocid1.compartment.oc1..aaaaaaaa');
jo.put('private_key','aaaaaaaa');
jo.put('fingerprint','aa:aa:aa:aa:aa:aa:aa:aa:aa:aa:aa:aa:aa:aa:aa:aa');
dbms_output.put_line(jo.to_string);
dbms_vector.create_credential(
CREDENTIAL_NAME => 'OCI_GENAI_CRED',
PARAMS => json(jo.to_string));
end;
/
Embedding結果を格納する表の作成
drop table documentation_tab_ocigenai purge;
CREATE TABLE documentation_tab_ocigenai (
DOC number,
TXT CLOB,
embed_id NUMBER,
embed_data VARCHAR2(4000),
embed_article VECTOR
);
PDFデータのテキスト化(dbms_vector_chain.utl_to_text)と分割(VECTOR_CHUNKS)
INSERT INTO documentation_tab_genai(DOC,embed_id,embed_data)
SELECT D.id doc, C.chunk_offset pos, C.chunk_text
FROM documentation_tab D, VECTOR_CHUNKS(dbms_vector_chain.utl_to_text(D.data)
BY words
MAX 150
OVERLAP 0
SPLIT BY sentence
LANGUAGE japanese NORMALIZE all) C;
VECTOR_CHUNKS後のデータをInputにEmbeddingします。
操作を簡略するためにEmbedding用のファンクションを作成します。
CREATE OR REPLACE FUNCTION vector_get(keywd IN CLOB)
RETURN vector IS
v vector;
BEGIN
select et.embed_vector into v
from dbms_vector.utl_to_embeddings(
keywd,
json('{
"provider": "ocigenai",
"credential_name": "OCI_GENAI_CRED",
"url": "https://inference.generativeai.us-chicago-1.oci.oraclecloud.com/20231130/actions/embedText",
"model": "cohere.embed-multilingual-v3.0"
}')
) t,
JSON_TABLE(
t.column_value,
'$[*]' COLUMNS (
embed_id NUMBER PATH '$.embed_id',
embed_data VARCHAR2(4000) PATH '$.embed_data',
embed_vector CLOB PATH '$.embed_vector'
)
) et;
RETURN v;
END;
/
update documentation_tab_genai
set embed_vector = vector_get(EMBED_DATA);
おわりに
AI Vector Searchには「バイナリデータのテキスト化」、「テキストデータの分割」、「Embedding」用の関数が用意されており、外部ファイルのEmbedding化から類似性検索までの一連の操作が できました。