データベースにアップロードされたベクトル埋込みモデルの使用によるSQLクイック・スタート

Oracle AI Vector Searchの機能の理解に役立つ特定のシナリオを実行するために、一連のSQLコマンドが用意されています。

このクイック・スタート・シナリオでは、非構造化データの背後にある意味を表すVECTORデータ型を紹介します。また、ベクトル検索のSQL演算子を使用して、類似検索を実行し、相互に類似したベクトル(およびそれによってコンテンツ)を検索できます。ベクトル索引は、類似検索を近似的に高速化するためにも作成されます。純粋な類似検索に加えて、ハイブリッド・ベクトル索引を作成し、それらを使用してハイブリッド検索を実行します。

必要に応じて、「Oracle AI Vector Searchの概要」を参照してください。

このスクリプトは、2つのOracle Databaseドキュメント・ブックをチャンク化し、対応するベクトル埋込みを割り当て、ベクトル索引を使用した類似検索を示します。

このスクリプトを実行するには、次のような3つのファイルが必要です。

ノート:

ここにリストしたファイルのかわりに他のPDFファイルを使用できます。.onnxファイルとして生成できる場合は、別のモデルを選択して使用できます。

では始めましょう。

  1. ファイルをローカル・サーバーのディレクトリまたはOracle Cloud Infrastructure (OCI)のオブジェクト・ストレージにコピーします。

    ONNX形式のHugging Face all-MiniLM-L12-v2モデルをダウンロードした場合は、このステップの残りの部分を完了する前に次を実行します:

    unzip all-MiniLM-L12-v2_augmented.zip

    結果:

     Archive:   all-MiniLM-L12-v2_augmented.zip
     inflating: all_MiniLM_L12_v2.onnx
     inflating: README-ALL_MINILM_L12_V2-augmented.txt

    all-MiniLM-L12-v2モデルの詳細は、ブログ投稿「Oracle Database 23aiの事前組込み埋込み生成モデルが利用可能になりました」を参照してください。

    ローカルの場合はscpコマンド、およびオブジェクト・ストレージの場合はOracleコマンドライン・インタフェースまたはcURLを使用するオプションがあります。オブジェクト・ストレージの場合、Oracleコマンドライン・インタフェースを使用した関連コマンドはoci os object putです。

    オブジェクト・ストレージを使用している場合は、次の手順(rootユーザーとして実行)を使用して、データベース・サーバーにバケットをマウントすることもできます。これにより、ファイルをオブジェクト・ストレージに簡単にコピーできます。

    1. s3fs-fuseパッケージをインストールします。
      yum install -y s3fs-fuse
    2. OCIで、顧客秘密キーを作成します。ACCESS_KEYおよびSECRET_KEYをメモしておいてください。
    3. オブジェクト・ストレージ・バケットのマウント・ポイントとなるフォルダを作成します。
      mkdir /mnt/bucket
      chown oracle:oinstall /mnt/bucket
    4. OCIオブジェクト・ストレージの認証に使用されるファイルに顧客秘密キーを含めます。
      echo $ACCESS_KEY:$SECRET_KEY > .passwd=s3fs
      chmod 400 .passwd-s3fs
    5. オブジェクト・ストレージ・バケットをマウント・ポイント・フォルダにマウントします(これは1行のコマンドです)。
      s3fs ${BUCKET} /mnt/bucket -o passwd_file=.passwd-s3fs 
      -o url=https://${NAMESPACE}.compat.objectstorage.${REGION}.oraclecloud.com 
      -onomultipart -o use_path_request_style -o endpoint=${REGION} -ouid=${ORAUID},
      gid=${ORAGID},allow_other,mp_umask=022
    6. リブート後にマウントを永続的にする場合は、crontabエントリを作成できます(これは1行のコマンドです)。
      echo "@reboot s3fs ${BUCKET} /mnt/bucket -o passwd_file=.passwd-s3fs -o 
      url=https://${NAMESPACE}.compat.objectstorage.${REGION}.oraclecloud.com -onomultipart 
      -o use_path_request_style -o endpoint=${REGION} -ouid=${ORAUID},gid=${ORAGID},
      allow_other,mp_umask=022" > crontab-fragment.txt
    7. crontabのエントリをサーバーのcrontabに追加します。
      crontab -l | cat - crontab-fragment.txt >crontab.txt && crontab crontab.txt
       
      rm -f crontab.txt crontab-fragment.txt

    前述のオブジェクト・ストレージの手順の代替として、DBMS_VECTORパッケージのLOAD_ONNX_MODEL_CLOUDプロシージャを使用して、クラウド・オブジェクト・ストレージからONNX埋込みモデルをロードすることもできます。このプロシージャの詳細は、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』を参照してください。

  2. ストレージ、ユーザーおよび権限の作成

    ここでは、新規表領域および新規ユーザーを作成します。そのユーザーにDB_DEVELOPER_ROLEを付与し、PDFファイルを指すOracleディレクトリを作成します。新しいユーザーに、そのディレクトリに対する読取りおよび書込みを許可します。

    sqlplus / as sysdba
    
    CREATE TABLESPACE tbs1
    DATAFILE 'tbs5.dbf' SIZE 20G AUTOEXTEND ON
    EXTENT MANAGEMENT LOCAL
    SEGMENT SPACE MANAGEMENT AUTO;
    
    drop user vector cascade;
    
    create user vector identified by vector DEFAULT TABLESPACE tbs1 quota unlimited on tbs1;
    
    grant DB_DEVELOPER_ROLE to vector;
    
    create or replace directory VEC_DUMP as '/my_local_dir/';
    
    grant read, write on directory vec_dump to vector;
  3. ONNXファイルの格納場所に応じて、次のいずれかの方法を使用して、埋込みモデルをOracle Databaseにロードします。
    1. ONNXファイルがローカルに格納されている場合:

      DBMS_VECTORパッケージを使用して、埋込みモデルをOracle Databaseにロードします。モデルをONNX形式で格納したディレクトリを指定し、モデルのタイプとその使用方法を説明する必要があります。

      事前トレーニング済埋込みモデルのダウンロード、ONNX形式への変換およびONNXファイルのOracle Databaseへのインポートの詳細は、「ONNX形式での事前トレーニング済モデルのインポート」を参照してください。

      1. connect vector/<vector user password>@<pdb instance network name>
         
        EXEC DBMS_VECTOR.DROP_ONNX_MODEL(model_name => 'doc_model', force => true);
         
        EXECUTE DBMS_VECTOR.LOAD_ONNX_MODEL('VEC_DUMP', 
                                            'my_embedding_model.onnx', 
                                            'doc_model');

        ノート:

        Hugging Face all-MiniLM-L12-v2モデルのOracleの事前組込みONNXファイルをダウンロードした場合は、次の簡易コマンドを使用してデータベースにファイルをロードできます:
        BEGIN
           DBMS_VECTOR.LOAD_ONNX_MODEL(
                directory => 'DM_DUMP',
                file_name => 'all_MiniLM_L12_v2.onnx',
                model_name => 'ALL_MINILM_L12_V2');
        END;
        /
    2. ONNXファイルがオブジェクト・ストアにすでに格納されている場合:
      1. 資格証明を作成します:
        SET DEFINE OFF; 
        BEGIN
            DBMS_CLOUD.create_credential(
            credential_name => 'MY_CLOUD_CREDENTIAL',
            username => '<username>',
            password => '<user password>';
        END;
        /
      2. オブジェクト・ストレージに保存されているONNXモデルをリストします。location_uriは、ONNXファイルの場所に対応している必要があります。
        SELECT mod.object_name, 
               round(mod.bytes/1024/1024,2) size_mb, 
               to_date(substr(mod.last_modified,1,18), 'DD-MON-RR HH24.MI.SS') modified
          FROM table(dbms_cloud.list_objects(credential_name => 'CLOUD_CREDENTIAL',
                  location_uri => 'https://objectstorage.<region>.oraclecloud.com/n/<namespace>/b/<bucketName>/o/')) mod
          WHERE mod.object_name = 'my_embedding_model.onnx';
        
      3. モデルをデータベースにインポートします:
        DECLARE
          model_source BLOB := NULL;
        BEGIN
          model_source := DBMS_CLOUD.get_object(credential_name => 'MY_CLOUD_CREDENTIAL',
            object_uri => 'https://objectstorage.<region>.oraclecloud.com/n/<namespace>/b/<bucketName>/o/my_embedding_model.onnx'); 
          DBMS_VECTOR.load_onnx_model('doc_model',
                                      model_source);
        END;
        /
      4. データベース内のモデルをリストします:
        SELECT MODEL_NAME, ATTRIBUTE_NAME, ATTRIBUTE_TYPE, DATA_TYPE, VECTOR_INFO
          FROM USER_MINING_MODEL_ATTRIBUTES WHERE MODEL_NAME = 'doc_model';
        
        SELECT MODEL_NAME, MINING_FUNCTION, ALGORITHM, ALGORITHM_TYPE, MODEL_SIZE
          FROM USER_MINING_MODELS WHERE MODEL_NAME = 'doc_model';
        
  4. (オプション)ロードされた埋込みモデルが機能していることを確認します。

    VECTOR_EMBEDDING SQL関数をコールして、サンプル・テキスト文字列(hello)を入力として渡すことで、埋込みモデルをテストできます。

    SELECT TO_VECTOR(VECTOR_EMBEDDING(doc_model USING 'hello' as data)) AS embedding;
  5. リレーショナル表を作成して、PDF形式でブックを格納します。

    ここで、チャンク化およびベクトル化するすべてのブックを含む表を作成します。新しい各ブックをIDと、ブックが格納されているローカル・ディレクトリへのポインタに関連付けます。

    drop table documentation_tab purge;
    create table documentation_tab (id number, data blob);
    insert into documentation_tab values(1, to_blob(bfilename('VEC_DUMP', 'json-relational-duality-developers-guide.pdf')));
    insert into documentation_tab values(2, to_blob(bfilename('VEC_DUMP', 'oracle-database-23ai-new-features-guide.pdf')));
    commit;
    select dbms_lob.getlength(data) from documentation_tab;
  6. my_embedding_model.onnxを使用して、非構造化データのチャンクおよび関連するベクトル埋込みを格納するリレーショナル表を作成します。

    まず、VECTORデータ型を使用して表構造を作成します。表の列をVECTORデータ型として宣言する方法の詳細は、「VECTORデータ型を使用する表の作成」を参照してください。

    INSERT文では、DOCUMENTATION_TABから各PDFファイルを読み取り、各PDFファイルをテキストに変換し、結果の各テキストをチャンク化して、最後に作成された各チャンクに対応するベクトル埋込みが生成されます。これらはすべて、1つのINSERT SELECT文で実行されます。

    ここでは、ベクトル・ユーティリティのPL/SQLパッケージDBMS_VECTOR_CHAINを使用して、非構造化データを1つのエンドツーエンド・パイプラインで変換、チャンク化およびベクトル化することを選択します。ベクトル・ユーティリティのPL/SQLファンクションは、入力データを渡して別の表現に変換するチェーン可能なステージのセット(テーブル・ファンクションを使用)を意図しています。この場合、PDFからテキスト、チャンクからベクトルまでです。DBMS_VECTOR_CHAINパッケージでチェーン可能ユーティリティ関数を使用する方法の詳細は、「チェーン可能ユーティリティ関数および一般的なユースケースについて」を参照してください。

    drop table doc_chunks purge;
    create table doc_chunks (doc_id number, chunk_id number, chunk_data varchar2(4000), chunk_embedding vector);
     
    insert into doc_chunks
    select dt.id doc_id, et.embed_id chunk_id, et.embed_data chunk_data, to_vector(et.embed_vector) chunk_embedding
    from
        documentation_tab dt,
        dbms_vector_chain.utl_to_embeddings(
           dbms_vector_chain.utl_to_chunks(dbms_vector_chain.utl_to_text(dt.data), json('{"normalize":"all"}')),
           json('{"provider":"database", "model":"doc_model"}')) 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;
     
    commit;

    関連項目:

  7. 類似検索で使用する問合せベクトルを生成します。

    類似検索では、問合せベクトルが必要です。ここでは、問合せテキストを入力し、関連するベクトル埋込みを生成します。

    たとえば、「バックアップとリカバリの異なる方法」というテキストを使用できます。VECTOR_EMBEDDING SQL関数を使用して、入力テキストからベクトル埋込みを生成します。この関数は、埋込みモデル名とテキスト文字列を使用して、対応するベクトルを生成します。お気に入りのツールを使用して、データベースの外部にベクトル埋込みを生成できます。VECTOR_EMBEDDING SQL関数の使用の詳細は、「埋込みを生成するためのSQL関数について」を参照してください。

    SQL*Plusで、次のコードを使用します。

    ACCEPT text_input CHAR PROMPT 'Enter text: '
    VARIABLE text_variable VARCHAR2(1000)
    VARIABLE query_vector VECTOR
    BEGIN
      :text_variable := '&text_input';
      SELECT vector_embedding(doc_model using :text_variable as data) into :query_vector;
    END;
    /
     
    PRINT query_vector

    SQLCLで、次のコードを使用します。

    DEFINE text_input = '&text'
     
    SELECT '&text_input';
     
    VARIABLE text_variable VARCHAR2(1000)
    VARIABLE query_vector CLOB
    BEGIN
      :text_variable := '&text_input';
      SELECT vector_embedding(doc_model using :text_variable as data) into :query_vector;
    END;
    /
     
    PRINT query_vector
  8. 類似検索を実行して、ブック内で、バックアップとリカバリの最も関連性の高い最初の4つのチャンクを見つけます。

    生成された問合せベクトルを使用して、DOC_CHUNKS表で同様のチャンクを検索します。このためには、VECTOR_DISTANCE SQL関数とFETCH SQL句を使用して、最も類似したチャンクを取得します。

    VECTOR_DISTANCE SQL関数の詳細は、「ベクトル距離関数および演算子」を参照してください。

    完全類似検索の詳細は、「完全類似検索の実行」を参照してください。

    SELECT doc_id, chunk_id, chunk_data
    FROM doc_chunks
    ORDER BY vector_distance(chunk_embedding , :query_vector, COSINE)
    FETCH FIRST 4 ROWS ONLY;

    WHERE句を追加して、特定のブックを1つのみ参照する場合など、検索をさらにフィルタすることもできます。

    SELECT doc_id, chunk_id, chunk_data
    FROM doc_chunks
    WHERE doc_id=1
    ORDER BY vector_distance(chunk_embedding , :query_vector, COSINE)
    FETCH FIRST 4 ROWS ONLY;
  9. EXPLAIN PLANコマンドを使用して、オプティマイザがこの問合せをどのように解決したかを判断します。
    EXPLAIN PLAN FOR
    SELECT doc_id, chunk_id, chunk_data
    FROM doc_chunks
    ORDER BY vector_distance(chunk_embedding , :query_vector, COSINE)
    FETCH FIRST 4 ROWS ONLY;
     
    select plan_table_output from table(dbms_xplan.display('plan_table',null,'all'));
    PLAN_TABLE_OUTPUT
    ------------------------------------------------------------------------------
    Plan hash value: 1651750914
    -------------------------------------------------------------------------------------------------
    | Id  | Operation               | Name          | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |
    -------------------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT        |               |     4 |   104 |       |   549   (3)| 00:00:01 |
    |*  1 |  COUNT STOPKEY          |               |       |       |       |            |          |
    |   2 |   VIEW                  |               |  5014 |   127K|       |   549   (3)| 00:00:01 |
    |*  3 |    SORT ORDER BY STOPKEY|               |  5014 |   156K|   232K|   549   (3)| 00:00:01 |
    |   4 |     TABLE ACCESS FULL   | DOC_CHUNKS    |  5014 |   156K|       |   480   (3)| 00:00:01 |
    -------------------------------------------------------------------------------------------------
    
  10. マルチベクトル類似検索を実行して、最も関連する最初の2つのブック内の最も関連性の高い最初の4つのチャンクを見つけます。

    ここでは、以前使用したものと同じ問合せベクトルを使用します。

    マルチベクトル類似検索の実行の詳細は、「マルチベクトル類似検索の実行」を参照してください。

    SELECT doc_id, chunk_id, chunk_data
    FROM doc_chunks
    ORDER BY vector_distance(chunk_embedding , :query_vector, COSINE)
    FETCH FIRST 2 PARTITIONS BY doc_id, 4 ROWS ONLY;
  11. 作成したベクトル埋込みにインメモリー近傍グラフ・ベクトル索引を作成します。

    巨大なベクトル埋込みスペースを処理する場合、類似検索を高速化するためにベクトル索引を作成できます。ベクトル索引は、テーブルに埋め込まれた各ベクトルとすべてのベクトルをスキャンするのではなく、ヒューリスティックを使用して検索スペースを減らし、類似検索を高速化します。これは近似検索と呼ばれます。

    ベクトル索引の作成の詳細は、「ベクトル索引およびハイブリッド・ベクトル索引の作成」を参照してください。

    ノート:

    VECSYS.VECTOR$INDEX表から選択するには、ベクトル索引に関する詳細情報を提供する明示的なSELECT権限が必要です。
    create vector index docs_hnsw_idx on doc_chunks(chunk_embedding)
    organization inmemory neighbor graph
    distance COSINE
    with target accuracy 95;
     
    SELECT INDEX_NAME, INDEX_TYPE, INDEX_SUBTYPE
    FROM USER_INDEXES;

    結果:

    INDEX_NAME     INDEX_TYPE  INDEX_SUBTYPE
    -------------- ----------- -----------------------------
    DOCS_HNSW_IDX  VECTOR      INMEMORY_NEIGHBOR_GRAPH_HNSW
    
     SELECT JSON_SERIALIZE(IDX_PARAMS returning varchar2 PRETTY)
    FROM VECSYS.VECTOR$INDEX where IDX_NAME = 'DOCS_HNSW_IDX';
    

    結果:

    JSON_SERIALIZE(IDX_PARAMSRETURNINGVARCHAR2PRETTY)
    ________________________________________________________________
    {
      "type" : "HNSW",
      "num_neighbors" : 32,
      "efConstruction" : 300,
      "distance" : "COSINE",
      "accuracy" : 95,
      "vector_type" : "FLOAT32",
      "vector_dimension" : 384,
      "degree_of_parallelism" : 1,
      "pdb_id" : 3,
      "indexed_col" : "CHUNK_EMBEDDING"
    }
  12. ベクトル・メモリー領域でのメモリー割当てを判断します。

    メモリー内のインメモリー近傍グラフ・ベクトル索引のサイズについて理解するには、V$VECTOR_MEMORY_POOLビューを使用します。ベクトル索引の作成およびメンテナンスを可能にするためのベクトル・プールのサイズ設定の詳細は、「ベクトル・プールのサイズ設定」を参照してください。

    ノート:

    V$VECTOR_MEMORY_POOLビューから選択するには、ベクトル・プールに関する詳細情報を提供する明示的なSELECT権限が必要です。
    select CON_ID, POOL, ALLOC_BYTES/1024/1024 as ALLOC_BYTES_MB, 
    USED_BYTES/1024/1024 as USED_BYTES_MB
    from V$VECTOR_MEMORY_POOL order by 1,2;
  13. おおよその類似検索を実行して、ブック内で最も関連性の高い最初の4つのチャンクを識別します。

    以前に生成された問合せベクトルを使用して、問合せベクトルに似たDOC_CHUNKS表のチャンクを検索します。このためには、VECTOR_DISTANCEファンクションおよびFETCH APPROX SQL句を使用して、ベクトル索引を使用して最も類似したチャンクを取得します。

    近似類似検索の詳細は、「ベクトル索引を使用した近似類似検索の実行」を参照してください。

    SELECT doc_id, chunk_id, chunk_data
    FROM doc_chunks
    ORDER BY vector_distance(chunk_embedding , :query_vector, COSINE)
    FETCH APPROX FIRST 4 ROWS ONLY WITH TARGET ACCURACY 80;

    WHERE句を追加して、特定のブックを1つのみ参照する場合など、検索をさらにフィルタすることもできます。

    SELECT doc_id, chunk_id, chunk_data
    FROM doc_chunks
    WHERE doc_id=1
    ORDER BY vector_distance(chunk_embedding , :query_vector, COSINE)
    FETCH APPROX FIRST 4 ROWS ONLY WITH TARGET ACCURACY 80;
  14. EXPLAIN PLANコマンドを使用して、オプティマイザがこの問合せをどのように解決したかを判断します。

    Oracle Databaseオプティマイザがベクトル索引を使用して近似検索を実行する方法の詳細は、「ベクトル索引のオプティマイザ計画」を参照してください。

    EXPLAIN PLAN FOR
    SELECT doc_id, chunk_id, chunk_data
    FROM doc_chunks
    ORDER BY vector_distance(chunk_embedding , :query_vector, COSINE)
    FETCH APPROX FIRST 4 ROWS ONLY WITH TARGET ACCURACY 80;
     
    select plan_table_output from table(dbms_xplan.display('plan_table',null,'all'));
    PLAN_TABLE_OUTPUT
    --------------------------------------------------------------------------------
    Plan hash value: 2946813851
    --------------------------------------------------------------------------------------------------------
    | Id  | Operation                      | Name          | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |
    --------------------------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT               |               |     4 |   104 |       |   12083 (2)| 00:00:01 |
    |*  1 |  COUNT STOPKEY                 |               |       |       |       |            |          |
    |   2 |   VIEW                         |               |  5014 |   127K|       |   12083 (2)| 00:00:01 |
    |*  3 |    SORT ORDER BY STOPKEY       |               |  5014 |    19M|    39M|   12083 (2)| 00:00:01 |
    |   4 |     TABLE ACCESS BY INDEX ROWID| DOC_CHUNKS    |  5014 |    19M|       |    1    (0)| 00:00:01 |
    |   5 |      VECTOR INDEX HNSW SCAN    | DOCS_HNSW_IDX |  5014 |    19M|       |    1    (0)| 00:00:01 |
    --------------------------------------------------------------------------------------------------------
    
  15. 近似類似検索のベクトル索引のパフォーマンスを決定します。

    索引精度レポート機能を使用すると、ベクトル索引の精度を判断できます。ベクトル索引の作成後、ベクトル検索がどの程度正確であるかを知りたい場合があります。

    DBMS_VECTOR.INDEX_ACCURACY_QUERY PL/SQLプロシージャは、特定の問合せベクトルの上位K索引検索の精度レポートおよび特定のターゲット精度を提供します。この場合、以前に生成された問合せベクトルを引き続き使用します。索引精度レポートの詳細は、「索引精度レポート」を参照してください。

    SET SERVEROUTPUT ON
    DECLARE 
        report VARCHAR2(128);
    BEGIN 
        report := dbms_vector.index_accuracy_query(
            OWNER_NAME => 'VECTOR', 
            INDEX_NAME => 'DOCS_HNSW_IDX',
            qv => :query_vector,
            top_K => 10, 
            target_accuracy => 90 );
        dbms_output.put_line(report); 
    END; 
    /

    レポートは次のようになります。達成された精度(100%)は、要求されたターゲット精度(90%)より10%高くなります。

  16. ハイブリッド検索の実行に使用される新しい表を作成します。
    DROP TABLE documentation_tab2 PURGE;
    
    CREATE TABLE documentation_tab2 (id NUMBER, file_name VARCHAR2(200));
    
    INSERT INTO documentation_tab2 VALUES(1, 'json-relational-duality-developers-guide.pdf');
    
    INSERT INTO documentation_tab2 VALUES(2, 'oracle-database-23ai-new-features-guide.pdf');
    
    COMMIT;
  17. ハイブリッド・ベクトル索引を作成するには、ファイルが存在するデータ・ストアを指定する必要があります。ここでは、PDFファイルが格納されているVEC_DUMPディレクトリを使用しています:
    BEGIN
      ctx_ddl.create_preference('DS', 'DIRECTORY_DATASTORE');
      ctx_ddl.set_attribute('DS', 'DIRECTORY', 'VEC_DUMP');
    END;
    /
  18. documentation_tab2表にハイブリッド・ベクトル索引を作成できるようになりました。ここでは、索引付けが必要なファイルを探す場所、フィルタ処理されるタイプ、使用する埋込みモデル、およびベクトル索引のタイプをハイブリッド・ベクトル索引に示します。詳細は、「ハイブリッド・ベクトル索引の理解」を参照してください。
    CREATE HYBRID VECTOR INDEX my_hybrid_vector_idx ON documentation_tab2(file_name)
      PARAMETERS ('
                     DATASTORE      DS
                     FILTER         CTXSYS.AUTO_FILTER
                     MODEL          doc_model
                     VECTOR_IDXTYPE ivf
    ');
  19. ハイブリッド・ベクトル索引が作成されたら、作成された次の内部表を確認します:
    SELECT COUNT(*) FROM DR$my_hybrid_vector_idx$VR;

    結果:

       COUNT(*)
    ___________
           9581

    または

    SELECT COUNT(*) FROM my_hybrid_vector_idx$VECTORS;

    結果:

       COUNT(*)
    ___________
           9581
    DESC my_hybrid_vector_idx$VECTORS

    結果:

    
    Name                   Null?       Type
    ______________________ ___________ _________________
    DOC_ROWID              NOT NULL    ROWID
    DOC_CHUNK_ID           NOT NULL    NUMBER
    DOC_CHUNK_COUNT        NOT NULL    NUMBER
    DOC_CHUNK_OFFSET       NOT NULL    NUMBER
    DOC_CHUNK_LENGTH       NOT NULL    NUMBER
    DOC_CHUNK_TEXT                     VARCHAR2(4000)
    DOC_CHUNK_EMBEDDING                VECTOR
    SELECT COUNT(*) FROM DR$MY_HYBRID_VECTOR_IDX$I;

    結果:

       COUNT(*)
    ___________
           4927
  20. 次のパラメータを指定して、最初のハイブリッド検索を実行できます:
    • ハイブリッド・ベクトル索引名
    • 使用する検索スコアラ(このスコアリング機能は、キーワード検索および類似検索の結果をマージした後に使用されます)
    • 両方の検索の結果をマージするために使用する融合関数
    • 類似検索に使用する検索テキスト
    • ベクトル検索結果の生成に使用する検索モード
    • 類似検索で識別された各ドキュメントのベクトル・スコアの計算に使用する集計関数
    • ベクトル・スコアのスコア加重
    • キーワード検索のCONTAINS文字列
    • キーワード検索のスコア加重
    • 表示する最大の戻り値
    • 結果に表示するドキュメントおよびチャンクの最大数

    DBMS_HYBRID_VECTOR.SEARCH構文の詳細は、「SEARCH」を参照してください。

    SET LONG 10000
    
    SELECT json_serialize(
        DBMS_HYBRID_VECTOR.SEARCH(
          JSON(
               '{
                  "hybrid_index_name" : "my_hybrid_vector_idx",
                  "search_scorer"     : "rsf",
                  "search_fusion"     : "UNION",
                  "vector":
                            {
                              "search_text"   : How to insert data in json format to a table?",
                              "search_mode"   : "DOCUMENT",
                              "aggregator"    : "MAX",
                              "score_weight"  : 1,
                            },
                  "text":
                            {
                             "contains"      : "data AND json",
                             "score_weight"  : 1,
                            },
                  "return":
                            {
                              "values"        : [ "rowid", "score", "vector_score", "text_score" ],
                              "topN"          : 10
                            }
                }'
          )
       ) RETURNING CLOB pretty);

    結果:

    JSON_SERIALIZE(DBMS_HYBRID_VECTOR.SEARCH(JSON('{"HYBRID_INDEX_NAME":"MY_HYBRID_VECTOR_IDX","SEARCH_SCORER":"RSF","SEARCH_FUSION":"UNION","VECTOR":{"SEARCH_TEXT":"HOWTOSEARCHUSINGVECTORINDEXES?","SEARCH_MODE":"DOCUMENT","AGGREGATOR":"MAX","SCORE_WEIGHT
    ______________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________
    [
      {
        "rowid" : "AAASd4AALAAAFjYAAB",
        "score" : 88.77,
        "vector_score" : 77.53,
        "text_score" : 100
      }
    ]

    ノート:

    次の文を実行する前に、前の文の実行で取得した行ID値を置き換えます。
    SELECT file_name FROM documentation_tab2 WHERE rowid='AAASd4AALAAAFjYAAB';

    結果:

    FILE_NAME
    __________________________________________
    json-relational-duality-developers-guide.pdf

    ノート:

    このステップでは、多くのパラメータが明示的に示されています。ただし、デフォルトのままにして、かわりに次の文を実行できます。
    SELECT json_serialize(
         DBMS_HYBRID_VECTOR.SEARCH(
            JSON(
                 '{
                   "hybrid_index_name" : "my_hybrid_vector_idx",
                   "search_text"       : "How to insert data in json format to a table?"
                 }'
                )
        ) RETURNING CLOB pretty);
  21. ハイブリッド・ベクトル索引のメンテナンスは、バックグラウンドで2つのレベルで自動的に行われます。3秒ごとに索引同期が実行され、進行中のDMLで索引が維持されます。追加されたDMLおよびファイルの数によっては、索引のメンテナンスに時間がかかる場合があります。そのため、このシナリオで経験するように、変更内容がすぐに表示されない場合があります。また、索引を最適化するために、スケジューラ・ジョブが毎晩午前0時に実行されます。索引に対してDMLを実行すると、索引は断片化されます。最適化ジョブによって索引がデフラグされ、問合せのパフォーマンスが向上します。

    ハイブリッド・ベクトル索引のメンテナンスを試してみるには、実表に新しい行を挿入し、前のステップと同じハイブリッド検索問合せを実行します:

    INSERT INTO documentation_tab2 VALUES(3, 'json-relational-duality-developers-guide.pdf');
    
    COMMIT;
    
    
    SELECT json_serialize(
        DBMS_HYBRID_VECTOR.SEARCH(
          JSON(
               '{
                  "hybrid_index_name" : "my_hybrid_vector_idx",
                  "search_scorer"     : "rsf",
                  "search_fusion"     : "UNION",
                  "vector":
                            {
                              "search_text"   : "How to insert data in json format to a table?",
                              "search_mode"   : "DOCUMENT",
                              "aggregator"    : "MAX",
                              "score_weight"  : 1,
                            },
                  "text":
                            {
                             "contains"      : "data AND json",
                             "score_weight"  : 1,
                            },
                  "return":
                            {
                              "values"        : [ "rowid", "score", "vector_score", "text_score" ],
                              "topN"          : 10
                            }
                }'
          )
       ) RETURNING CLOB pretty);
    

    結果に変化はありません:

    JSON_SERIALIZE(DBMS_HYBRID_VECTOR.SEARCH(JSON('{"HYBRID_INDEX_NAME":"MY_HYBRID_VECTOR_IDX","SEARCH_SCORER":"RSF","SEARCH_FUSION":"UNION","VECTOR":{"SEARCH_TEXT":"HOWTOSEARCHUSINGVECTORINDEXES?","SEARCH_MODE":"DOCUMENT","AGGREGATOR":"MAX","SCORE_WEIGHT
    ______________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________
    [
      {
        "rowid" : "AAASd4AALAAAFjYAAB",
        "score" : 88.77,
        "vector_score" : 77.53,
        "text_score" : 100
      }
    ]
  22. 数分待ってから、ハイブリッド検索を再実行します。
    SELECT json_serialize(
        DBMS_HYBRID_VECTOR.SEARCH(
          JSON(
               '{
                  "hybrid_index_name" : "my_hybrid_vector_idx",
                  "search_scorer"     : "rsf",
                  "search_fusion"     : "UNION",
                  "vector":
                            {
                              "search_text"   : "How to insert data in json format to a table?",
                              "search_mode"   : "DOCUMENT",
                              "aggregator"    : "MAX",
                              "score_weight"  : 1,
                            },
                  "text":
                            {
                             "contains"      : "data AND json",
                             "score_weight"  : 1,
                            },
                  "return":
                            {
                              "values"        : [ "rowid", "score", "vector_score", "text_score" ],
                              "topN"          : 10
                            }
                }'
          )
       ) RETURNING CLOB pretty);
    

    この時点で、結果が更新されました:

    JSON_SERIALIZE(DBMS_HYBRID_VECTOR.SEARCH(JSON('{"HYBRID_INDEX_NAME":"MY_HYBRID_VECTOR_IDX","SEARCH_SCORER":"RSF","SEARCH_FUSION":"UNION","VECTOR":{"SEARCH_TEXT":"HOWTOSEARCHUSINGVECTORINDEXES?","SEARCH_MODE":"DOCUMENT","AGGREGATOR":"MAX","SCORE_WEIGHT
    ______________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________
    [
      {
        "rowid" : "AAASd4AALAAAFjYAAB",
        "score" : 88.77,
        "vector_score" : 77.53,
        "text_score" : 100
      },
      {
        "rowid" : "AAASd4AALAAAFjYAAC",
        "score" : 88.77,
        "vector_score" : 77.53,
        "text_score" : 100
      }
    ]