ハイブリッド・ベクトル索引のエンドツーエンドの問合せの例

この例では、エンドツーエンドのハイブリッド検索ワークフローを確認できます。最初に、入力データを準備、チャンク化、埋込み、格納および索引付けするCREATE HYBRID VECTOR INDEX SQL文を実行します。次に、DBMS_HYBRID_VECTOR.SEARCH PL/SQL問合せAPIを使用して、キーワード検索とともにベクトル検索を実行します。

ここでは、HR採用シナリオでハイブリッド検索を使用する方法を確認できます。このシナリオでは、特定の技術スキル(「C, Python, Database」のキーワード検索)を持つ従業員を採用しますが、対象者は特定の性格とリーダーシップの特性(「prioritize teamwork and leadership experience」のセマンティック検索)も備えている必要があります。また、複数の検索モードで様々な種類の純粋なハイブリッド検索問合せおよび純粋ではないハイブリッド検索問合せを実行する方法も確認できます。
  1. ローカル・ユーザーとしてOracle Databaseに接続します。
    1. SQL*PlusにSYSユーザーとしてログインし、SYSDBAとして接続します。
      conn sys/password as sysdba
      CREATE TABLESPACE tbs1
      DATAFILE 'tbs5.dbf' SIZE 20G AUTOEXTEND ON
      EXTENT MANAGEMENT LOCAL
      SEGMENT SPACE MANAGEMENT AUTO;
      SET ECHO ON
      SET FEEDBACK 1
      SET NUMWIDTH 10
      SET LINESIZE 80
      SET TRIMSPOOL ON
      SET TAB OFF
      SET PAGESIZE 10000
      SET LONG 10000
    2. ローカル・ユーザー(docuser)を作成し、必要な権限を付与します。
      DROP USER docuser cascade;
      CREATE USER docuser identified by docuser DEFAULT TABLESPACE tbs1 quota unlimited on tbs1;
      GRANT DB_DEVELOPER_ROLE, create credential to docuser;
    3. 入力データおよびモデル・ファイルを格納するローカル・ディレクトリをサーバー(DEMO_DIR)に作成します。必要な権限を付与します。
      create or replace directory DEMO_DIR as '/my_local_dir/';
      grant read, write on directory DEMO_DIR to docuser;
      
      commit;
    4. ローカル・ユーザー(docuser)として接続します:
      CONN docuser/password
  2. load_onnx_modelプロシージャをコールして、ONNX形式の埋込みモデルをOracle Databaseにロードします。

    この埋込みモデルは、入力データからベクトル埋込みを生成するために内部的に使用されます。

    EXECUTE dbms_vector.drop_onnx_model(model_name => 'doc_model', force => true);
    EXECUTE dbms_vector.load_onnx_model(
      'DEMO_DIR', 'my_embedding_model.onnx', 'doc_model', 
       JSON('{"function" : "embedding", "embeddingOutput" : "embedding" , "input": {"input": ["DATA"]}}'));

    この例では、プロシージャによって、my_embedding_model.onnxという名前のONNXモデル・ファイルがDEMO_DIRディレクトリからデータベースにdoc_modelとしてロードされます。my_embedding_model.onnxを埋込みモデルのONNXエクスポート、およびdoc_modelをインポートされたモデルがデータベースに格納される名前に置き換える必要があります。

    ノート:

    ONNX形式の埋込みモデルがない場合は、「ONNXパイプライン・モデル: テキスト埋込み」にリストされているステップを実行します。
  3. リレーショナル表(doc_tabなど)を作成し、すべてのドキュメントをテキスト列(textなど)に挿入します。
    DROP TABLE doc_tab purge;
    CREATE TABLE doc_tab (id number, text varchar2(500));
    
    insert into t1 values(1, 'Candidate-1: C Master. Optimizes low-level system (i.e. Database) performance with C. Strong leadership skills in guiding teams to deliver complex projects.');
    insert into t1 values(2, 'Candidate-2: Full-Stack Developer. Skilled in Database, C, HTML, JavaScript, and Python with experience in building responsive web applications. Thrives in collaborative team environments.');
    insert into t1 values(3, 'Candidate-3: DevOps Engineer. Manages CI/CD pipelines (Jenkins, Gitlab) with expertise in cloud infrastructure (OCI, AWS, GCP). Proven track record of streamlining deployments and ensuring high availability.');
    insert into t1 values(4, 'Candidate-4: Database Administrator (DBA). Maintains and secures enterprise database (Oracle, MySql, SQL Server). Passionate about data integrity and optimization. Strong mentor for junior DBA(s).');
    insert into t1 values(5, 'Candidate-5: C, Java, Python, and Database (DBA) Guru. Develops scalable applications. Strong leadership, teamwork and collaborative.');
    
    commit;
  4. doc_tab表のtext列に、ハイブリッド・ベクトル索引(my_hybrid_idx)を作成します。
    CREATE HYBRID VECTOR INDEX my_hybrid_idx on 
      doc_tab(text)
      parameters('model doc_model');

    ここで、modelには、埋込みを生成するためにデータベースにインポートしたONNX形式の埋込みモデルを指定します。これは、ハイブリッド・ベクトル索引を作成するために必要な唯一の索引付けパラメータです。

    my_hybrid_idxという名前の索引が、doc_tab表のtext列に作成されます。デフォルトのベクトル索引タイプは、Inverted File Flat (IVF)に設定されます。
  5. ハイブリッド・ベクトル索引に問い合せます。
    次のステップでは、「ハイブリッド検索の理解」で説明されている複数の検索モードを使用してハイブリッド・ベクトル索引を問い合せることができるすべての方法を確認します。結果を比較してスコアとランキングの違いを検査し、包括的に理解できます。
    1. 単純なデフォルトの問合せ:

      デフォルトでは、ハイブリッド検索では、事前定義されたフィールドを含む簡易クエリーが提供されます。最低限必要な入力パラメータは、hybrid_index_nameおよびsearch_textです。

      ベクトル化されたチャンク索引およびテキスト・ドキュメント索引の問合せには、同じ検索テキスト(C, Python, Database)が使用されます。この検索テキストは、キーワード検索のCONTAINS問合せに変換され、セマンティック検索のVECTOR_DISTANCE問合せ用にベクトル化されます。

      select json_Serialize(
        dbms_hybrid_vector.search(
          json(
               '{ 
                 "hybrid_index_name" : "my_hybrid_idx",
                 "search_text"       : "C, Python, Database"
                }'
              )
        ) pretty)
      from dual;

      この問合せは、スコアの関連性の順に上位3行を返します。Candidate-2の最高の最終スコア(69.54)は、最適な一致を示します。この問合せでは、すべての戻り属性がデフォルトで表示されます。

      [
        {
          "rowid"        : "AAAR9jAABAAAQeaAAB",
          "score"        : 69.54,
          "vector_score" : 69.69,
          "text_score"   : 68,
          "vector_rank"  : 1,
          "text_rank"    : 1,
          "chunk_text"   : "Candidate-2: Full-Stack Developer. Skilled in Database, C, HTM
      L, JavaScript, and Python with experience in building responsive web application
      s. Thrives in collaborative team environments.",
          "chunk_id"     : "1"
        },
        {
          "rowid"        : "AAAR9jAABAAAQeaAAA",
          "score"        : 62.77,
          "vector_score" : 65.55,
          "text_score"   : 35,
          "vector_rank"  : 4,
          "text_rank"    : 2,
          "chunk_text"   : "Candidate-1: C Master. Optimizes low-level system (i.e. Da
      tabase) performance with C. Strong leadership skills in guiding teams to deliver
       complex projects.",
          "chunk_id"     : "1"
        },
        {
          "rowid"        : "AAAR9jAABAAAQeaAAD",
          "score" : 62.15,
          "vector_score" : 68.17,
          "text_score"   : 2,
          "vector_rank"  : 2,
          "text_rank"    : 3,
          "chunk_text"   : "Candidate-4: Database Administrator (DBA). Maintains and
      secures enterprise database (Oracle, MySql, SQL Server). Passionate about data i
      ntegrity and optimization. Strong mentor for junior DBA(s).",
          "chunk_id"     : "1"
        }
      ]
    2. ドキュメント・モードでの純粋なセマンティック(問合せ入力はテキスト):

      これは、ドキュメント・レベルの検索結果をフェッチするための純粋なベクトルベースの類似度の問合せです。ここで、search_text文字列は、VECTOR_DISTANCEセマンティック問合せの問合せベクトルにベクトル化されます。

      ベクトル検索はチャンク・レベルで動作します。問合せでは最初にベクトル化されたチャンクの最上位候補が抽出され、aggregator (MAX)関数を使用してドキュメント別に集計されて、結合されたスコアが生成され(aggregatorに従って)、最後に上位n個のドキュメントが返されます。この動作の詳細は、「ドキュメント・モードでの純粋なセマンティック」を参照してください。

      select json_Serialize(
        dbms_hybrid_vector.search(
          json(
            '{ "hybrid_index_name" : "my_hybrid_idx",
               "vector":
                  {
                   "search_text"   : "prioritize teamwork and leadership experience",
                   "search_mode"   : "DOCUMENT",
                   "aggregator"    : "MAX"
                  },
               "return":
                  {
                   "values"        : [ "rowid", "score" ],
                   "topN": 3
                  }
            }'
          )
        ) pretty)
      from dual;

      上位3つのドキュメントが、doc_tab表の対応する行のROWIDおよびそれらのベクトル・スコアとともに返されます。

      [
        {
          "rowid" : "AAAR9jAABAAAQeaAAA",
          "score" : 61
        },
        {
          "rowid" : "AAAR9jAABAAAQeaAAD",
          "score" : 56.64
        },
        {
          "rowid" : "AAAR9jAABAAAQeaAAB",
          "score" : 55.75
        }
      ]
    3. ドキュメント・モードでの純粋なセマンティック(問合せ入力としての埋込み):

      ドキュメント・モードでの以前の純粋なセマンティック問合せ(search_textパラメータを使用してベクトル検索の問合せテキストを指定)と比較すると、ここでは、search_vectorパラメータを使用して、ベクトル埋込み(問合せベクトル)をベクトル検索の入力として直接渡します。

      同じように、この問合せは、上位のベクトル化されたチャンク結果を取得し、aggregator (MAX)関数を使用してドキュメント別に集計し、最後に上位n個のドキュメントを返します。

      select json_Serialize(
        dbms_hybrid_vector.search(
          json(
            '{ "hybrid_index_name" : "my_hybrid_idx",
               "vector":
                {
                 "search_vector"   : vector_serialize(
                                                  vector_embedding(doc_model
                                                              using
                                                              "C, Python, Database"
                                                              as data)
                                                          RETURNING CLOB), 
                 "search_mode"     : "DOCUMENT",
                 "aggregator"      : "MAX"
                },
               "return":
                {
                 "values"     : [ "rowid", "score" ],
                 "topN": 3
                }
            }'
          )
        ) pretty)
      from dual;

      上位3つのドキュメントが、doc_tab表の対応する行のROWIDおよびそれらのベクトル・スコアとともに返されます。

      [
        {
          "rowid" : "AAAR9jAABAAAQeaAAB",
          "score" : 69.69
        },
        {
          "rowid" : "AAAR9jAABAAAQeaAAD",
          "score" : 68.17
        },
        {
          "rowid" : "AAAR9jAABAAAQeaAAC",
          "score" : 67.48
        }
      ]
    4. チャンク・モードでの純粋なセマンティック:

      これは、チャンク結果を取得するための純粋なベクトルベースの類似度の問合せです。これは、Oracle AI Vector Searchのセマンティック検索と同等であることに注意してください。ここで、ベクトル検索は、同じ一連のドキュメントまたは異なる一連のドキュメントから最適なベクトル化されたチャンクを取得し、そのベクトル・スコアを内部的に計算します。ベクトル・スコアが最も高い上位n個のチャンクが返されます。この動作の詳細は、「チャンク・モードでの純粋なセマンティック」を参照してください。

      ドキュメント・モードでの以前の純粋なセマンティック検索と比較すると、チャンク結果の集計はチャンク・モードで実行されないため、aggregator関数は必要ありません。

      select json_Serialize(
        dbms_hybrid_vector.search(
          json(
            '{ "hybrid_index_name" : "my_hybrid_idx",
               "vector":
                {
                   "search_text"   : "prioritize teamwork and leadership experience",
                   "search_mode"   : "CHUNK"
                },
               "return":
                {
                   "values"        : [ "rowid", "score", "chunk_text", "chunk_id" ],
                   "topN"          : 3
                }
            }'
          )
        ) pretty)
      from dual;

      スコアが最も高い上位3つのチャンクが、チャンクIDおよびチャンク・テキストとともに返されます。doc_tab表の行の対応するROWIDも確認できます。チャンクIDが1のCandidate-1の最高スコア(61)は、最上位の一致を示します:

      [
        {
          "rowid"      : "AAAR9jAABAAAQeaAAA",
          "score"      : 61,
          "chunk_text" : "Candidate-1: C Master. Optimizes low-level system (i.e. Da
      tabase) performance with C. Strong leadership skills in guiding teams to deliver
       complex projects.",
          "chunk_id"   : "1"
        },
        {
          "rowid"      : "AAAR9jAABAAAQeaAAD",
          "score"      : 56.64,
          "chunk_text" : "Candidate-4: Database Administrator (DBA). Maintains and
      secures enterprise database (Oracle, MySql, SQL Server). Passionate about data i
      ntegrity and optimization. Strong mentor for junior DBA(s).",
          "chunk_id"   : "1"
        },
        {
          "rowid"      : "AAAR9jAABAAAQeaAAB",
          "score"      : 55.75,
          "chunk_text" : "Candidate-2: Full-Stack Developer. Skilled in Database, C, HTM
      L, JavaScript, and Python with experience in building responsive web application
      s. Thrives in collaborative team environments.",
          "chunk_id"   : "1"
        }
      ]
    5. ドキュメント・モードでの純粋なキーワード:

      これは、ドキュメントレベルの結果をフェッチするための純粋なテキストベースのキーワード問合せです。これは、Oracle Textを使用した従来のCONTAINS問合せと同等であることに注意してください。ここで、全文検索は最適なドキュメントを取得し、そのキーワード・スコアを内部的に計算します。キーワード・スコアが最も高い上位n個のドキュメントが返されます。この動作の詳細は、「ドキュメント・モードでの純粋なキーワード」を参照してください。

      select json_Serialize(
        dbms_hybrid_vector.search(
          json(
            '{ "hybrid_index_name" : "my_hybrid_idx",
               "text":
                {
                 "contains"        : "C, Python, Database"
                },
               "return":
                {
                 "values"          : [ "rowid", "score" ],
                 "topN": 3
                }
            }'
          )
        ) pretty)
      from dual;

      スコアが最も高い上位3つのドキュメントが返され、doc_tab表の対応するROWIDおよびキーワード・スコアを確認できます:

      [
        {
          "rowid" : "AAAR9jAABAAAQeaAAB",
          "score" : 68
        },
        {
          "rowid" : "AAAR9jAABAAAQeaAAA",
          "score" : 35
        },
        {
          "rowid" : "AAAR9jAABAAAQeaAAD",
          "score" : 2
        }
      ]
    6. ドキュメント・モードでのキーワードとセマンティック(共通の問合せ文字列):

      これは、データに対してキーワード検索とベクトル検索の両方を実行し、キーワード・スコアとセマンティック・スコアを組み合せてドキュメント・レベルの結果をフェッチするハイブリッド問合せです。

      ここでは、同じテキスト文字列(C, Python, Database)が両方に使用されます:

      • SEARCH_TEXT文字列をCONTAINS ACCUM演算子構文に変換することによる、ドキュメント・テキスト索引に対するキーワード問合せ

      • VECTOR_DISTANCE問合せのSEARCH_TEXT文字列をベクトル化することによる、ベクトル化されたチャンク索引に対するセマンティック問合せ

      select json_Serialize(
        dbms_hybrid_vector.search(
          json(
            '{ "hybrid_index_name" : "my_hybrid_idx",
               "search_text"       : "C, Python, Database",
               "search_fusion"     : "INTERSECT",
               "search_scorer"     : "rsf",
               "vector":
                  {
                   "search_mode"   : "DOCUMENT",
                   "aggregator"    : "MAX"
                  },
               "return":
                  {
                   "values"        : [ "rowid", "score" ],
                   "topN"          : 3
                  }
            }'
          )
        ) pretty)
      from dual;

      ベクトル検索の場合、この問合せは、ベクトル索引に対して(SEARCH_TEXT文字列から作成された)問合せベクトルを検索します。ベクトル検索はチャンク・レベルで動作します。問合せでは最初にベクトル化されたチャンクの上位候補が抽出され、aggregator (MAX)関数を使用してドキュメント別に集計されて、結合されたベクトル・スコアが生成され(aggregatorに従って)、最後に上位n個のドキュメントが返されます。

      スコアリングの場合、最初にUNION ALL操作を使用して両方の検索結果が追加されます。次に、SEARCH_FUSIONの演算子INTERSECTを使用して結果が融合されます。この演算子は、両方の検索で選択されたすべての個別行を結合します。最終スコアリングは、定義されたSEARCH_SCORERアルゴリズムであるRSFを使用して計算されます。最後に、定義された最大topN件のドキュメントIDが返されます。

      スコアの計算方法の詳細は、「ドキュメント・モードでのキーワードとセマンティック」を参照してください。

      スコアが最も高い上位3つのドキュメントが返され、識別された最適なファイルのリストに対応する実表(doc_tab)のROWIDのリストが表示されます。

      [
        {
          "rowid" : "AAAR9jAABAAAQeaAAB",
          "score" : 69.54
        },
        {
          "rowid" : "AAAR9jAABAAAQeaAAA",
          "score" : 62.77
        },
        {
          "rowid" : "AAAR9jAABAAAQeaAAD",
          "score" : 62.15
        }
      ]
    7. ドキュメント・モードでのキーワードおよびセマンティック(個別の問合せ文字列):

      ドキュメント・モードでの前のキーワードおよびセマンティック検索(テキスト検索とベクトル検索の両方に同じsearch_text文字列を使用)と比較すると、ここでは、両方の検索タイプに2つの個別の検索テキストを指定します。

      select json_Serialize(
        dbms_hybrid_vector.search(
          json(
            '{ "hybrid_index_name" : "my_hybrid_idx",
               "search_fusion"     : "INTERSECT",
               "search_scorer"     : "rsf",
               "vector":
                {
                   "search_text"   : "prioritize teamwork and leadership experience",
                   "search_mode"   : "DOCUMENT",
                   "aggregator"    : "MAX"
                },
               "text":
                {
                   "contains"      : "C, Python, Database"
                },
               "return":
                {
                   "values"        : [ "rowid", "score" ],
                   "topN"          : 3
                }
            }'
          )
        ) pretty)
      from dual;

      同様に、キーワード検索では、CONTAINSテキスト問合せ文字列(「C, Python, Database」)を満たすドキュメントIDのリストが取得されます。ベクトル検索では、SEARCH_TEXT類似度問合せ文字列(「prioritize teamwork and leadership experience」)を満たすドキュメントIDのリストが取得されます。

      スコアリングの場合、最初にUNION ALL操作を使用して両方の検索結果が追加されます。次に、SEARCH_FUSIONの演算子INTERSECTを使用して結果が融合されます。最終スコアリングは、定義されたSEARCH_SCORERアルゴリズムであるRSFを使用して計算されます。最後に、定義された最大topN件のドキュメントIDが返されます。

      スコアの計算方法の詳細は、「ドキュメント・モードでのキーワードとセマンティック」を参照してください。

      スコアが最も高い上位3つのドキュメントが返され、識別された最適なファイルのリストに対応する実表(doc_tab)のROWIDのリストが表示されます。

      [
        {
          "rowid" : "AAAR9jAABAAAQeaAAA",
          "score" : 58.64
        },
        {
          "rowid" : "AAAR9jAABAAAQeaAAB",
          "score" : 56.86
        },
        {
          "rowid" : "AAAR9jAABAAAQeaAAD",
          "score" : 51.67
        }
      ]
    8. チャンク・モードでのキーワードとセマンティック:

      これは、データに対してキーワード検索とベクトル検索の両方を実行し、キーワード・スコアとセマンティック・スコアを組み合せてチャンク・レベルの結果をフェッチするハイブリッド問合せです。

      select json_Serialize(
        dbms_hybrid_vector.search(
          json(
            '{ "hybrid_index_name" : "my_hybrid_idx",
               "vector":
                {
                   "search_text"   : "prioritize teamwork and leadership experience",
                   "search_mode"   : "CHUNK"
                },
               "text":
                {
                   "contains"      : "C, Python, Database"
                },
               "return":
                {
                   "values"        : [ "rowid", "score", "chunk_text", "chunk_id" ],
                   "topN": 3
                }
            }'
          )
        ) pretty)
      from dual;

      キーワード検索では、CONTAINSテキスト問合せ文字列(「C, Python, Database」)を満たすドキュメントIDのリストが取得されます。

      ベクトル検索では、すべてのドキュメントのすべてのチャンクのベクトル索引に対して、問合せベクトル(SEARCH_TEXTの文字列「prioritize teamwork and leadership experience」から作成)で類似度問合せを実行します。SEARCH_TEXT類似度問合せ文字列を満たすチャンクIDおよび関連するドキュメントIDのリストを取得します。

      チャンク結果の集計はチャンク・モードでは実行されないため、AGGREGATOR関数は適用されません。

      スコアリングの場合、最初にドキュメントIDに対するRIGHT OUTER JOIN操作を使用して、テキスト・ドキュメントの結果がチャンク結果に追加されます。ベクトル候補のチャンクにないテキスト・ドキュメントの結果は返されません。次に、SEARCH_FUSIONの演算子INTERSECTを使用して結果が融合されます。この演算子は、両方の検索で選択されたすべての個別行を結合します。最終スコアリングは、定義されたSEARCH_SCORERアルゴリズムであるRSFを使用して計算されます。最後に、定義された最大topN件のチャンクIDが返されます。

      スコアの計算方法については、「チャンク・モードでのキーワードとセマンティック」を参照してください。

      上位3つのチャンクIDのリストが、実表(doc_tab)に格納されているファイルから、チャンク・テキストおよび対応するROWIDとともに返されます。チャンクIDが1のCandidate-1の最高の最終スコア(58.64)は、最上位の一致を示します:

      [
        {
          "rowid"      : "AAAR9jAABAAAQeaAAA",
          "score"      : 58.64,
          "chunk_text" : "Candidate-1: C Master. Optimizes low-level system (i.e. Da
      tabase) performance with C. Strong leadership skills in guiding teams to deliver
       complex projects.",
          "chunk_id"   : "1"
        },
        {
          "rowid"      : "AAAR9jAABAAAQeaAAB",
          "score"      : 56.86,
          "chunk_text" : "Candidate-2: Full-Stack Developer. Skilled in Database, C, HTM
      L, JavaScript, and Python with experience in building responsive web application
      s. Thrives in collaborative team environments.",
          "chunk_id"   : "1"
        },
        {
          "rowid"      : "AAAR9jAABAAAQeaAAD",
          "score"      : 51.67,
          "chunk_text" : "Candidate-4: Database Administrator (DBA). Maintains and
      secures enterprise database (Oracle, MySql, SQL Server). Passionate about data i
      ntegrity and optimization. Strong mentor for junior DBA(s).",
          "chunk_id"   : "1"
        }
      ]