SQL RAGの例

このシナリオでは、ユーザー問合せに基づいて特定のドキュメント・コンテンツの類似検索を実行できます。ドキュメント・チャンクが取得されると、それらは連結され、取得したチャンクを使用してユーザーの質問に回答するようLLMに依頼するプロンプトが生成されます。

  1. SQL*Plusを起動し、Oracle Databaseにローカル・テスト・ユーザーとして接続します。
    1. SQL*Plusにsysユーザーとしてログインし、sysdbaとして接続します。
      conn sys/password AS sysdba
      SET SERVEROUTPUT ON;
      SET ECHO ON;
      SET LONG 100000;
    2. ローカル・テスト・ユーザー(vector)を作成し、必要な権限を付与します。
      DROP USER vector cascade;
      CREATE USER vector identified by <my vector password>
      GRANT DB_DEVELOPER_ROLE, CREATE CREDENTIAL TO vector;
    3. プロキシが存在する場合は、次のように設定します。
      EXEC UTL_HTTP.SET_PROXY('<my proxy full name>:<my proxy port>');
    4. DBMS_NETWORK_ACL_ADMINプロシージャを使用して、ホストへの接続権限を付与します。この例では、*を使用して任意のホストを許可します。ただし、接続する各ホストを明示的に指定できます。
      BEGIN
        DBMS_NETWORK_ACL_ADMIN.APPEND_HOST_ACE(
          host => '*',
          ace => xs$ace_type(privilege_list => xs$name_list('connect'),
                             principal_name => 'VECTOR',
                             principal_type => xs_acl.ptype_db));
      END;
      /
    5. テスト・ユーザーとしてOracle Databaseに接続します。
      conn docuser/password;
  2. Oracle Cloud Infrastructure Generative AIの資格証明を作成します:
    1. DBMS_VECTOR_CHAIN.CREATE_CREDENTIALを実行して、OCI資格証明(OCI_CRED)を作成および格納します。

      OCIGenAIには次のパラメータが必要です。
      { 
      "user_ocid"       : "<user ocid>",
      "tenancy_ocid"    : "<tenancy ocid>",
      "compartment_ocid": "<compartment ocid>",
      "private_key"     : "<private key>",
      "fingerprint"     : "<fingerprint>" 
      }

      ノート:

      生成された秘密キーは次のように表示されます。
      -----BEGIN RSA PRIVATE KEY-----
      <private key string>
      -----END RSA PRIVATE KEY-----
      (BEGINENDの行を除く) <private key string>値を単一行または複数行として渡します。
      BEGIN
        DBMS_VECTOR_CHAIN.DROP_CREDENTIAL(credential_name => 'OCI_CRED');
      EXCEPTION
        WHEN OTHERS THEN NULL;
      END;
      /
      DECLARE
        jo json_object_t;
      BEGIN
        jo := json_object_t();
        jo.put('user_ocid', '<user ocid>');
        jo.put('tenancy_ocid', '<tenancy ocid>');
        jo.put('compartment_ocid', '<compartment ocid>');
        jo.put('private_key', '<private key>');
        jo.put('fingerprint', '<fingerprint>');
        DBMS_VECTOR_CHAIN.CREATE_CREDENTIAL(
          credential_name => 'OCID_CRED',
          params          => json(jo.to_string));
      END;
      /
    2. 資格証明作成の確認:

      col owner format a15
      col credential_name format a20
      col username format a20
      SELECT owner, credential_name, username
      FROM all_credentials
      ORDER BY owner, credential_name, username;
  3. 類似検索結果を使用してプロンプトを生成します。

    ノート:

    ONNX形式モデルをdoc_modelとしてデータベースにロードする方法の詳細は、「Oracle Databaseのエンドツーエンド・サンプルへのONNXモデルのインポート」を参照してください。
    SET SERVEROUTPUT ON;
    
    VAR prompt CLOB;
    VAR user_question CLOB;
    VAR context CLOB;
    
    BEGIN
      -- initialize the concatenated string
      :context := '';
    
      -- read this question from the user
      :user_question := 'what are vector indexes?';
    
      -- cursor to fetch chunks relevant to the user's query
      FOR rec IN (SELECT EMBED_DATA
                  FROM doc_chunks
                  WHERE DOC_ID = 'Vector User Guide'
                  ORDER BY vector_distance(embed_vector, vector_embedding(
                      doc_model using :user_question as data), COSINE)
                  FETCH EXACT FIRST 10 ROWS ONLY)
      LOOP
        -- concatenate each value to the string
        :context := :context || rec.embed_data;
      END LOOP;
    
      -- concatenate strings and format it as an enhanced prompt to the LLM
      :prompt := 'Answer the following question using the supplied context 
                    assuming you are a subject matter expert. Question: '
                    || :user_question || ' Context: ' || :context;
    
      DBMS_OUTPUT.PUT_LINE('Generated prompt: ' || :prompt);
    END;
    /
  4. GenAIコールを発行します。

    ノート:

    サポートされているすべてのRESTエンドポイントのリストは、「サポートされているサードパーティ・プロバイダの操作およびエンドポイント」を参照してください。
    DECLARE
      input CLOB;
      params CLOB;
      output CLOB;
    BEGIN
      input := :prompt;
      params := '{
        "provider" : "ocigenai",
        "credential_name" : "OCI_CRED",
        "url" : "https://inference.generativeai.us-chicago-1.oci.
                oraclecloud.com/20231130/actions/generateText",
        "model" : "cohere.command"
      }';
    
      output := DBMS_VECTOR_CHAIN.UTL_TO_GENERATE_TEXT(input, json(params));
      DBMS_OUTPUT.PUT_LINE(output);
      IF output IS NOT NULL THEN
        DBMS_LOB.FREETEMPORARY(output);
      END IF;
    EXCEPTION
      WHEN OTHERS THEN
        DBMS_OUTPUT.PUT_LINE(SQLERRM);
        DBMS_OUTPUT.PUT_LINE(SQLCODE);
    END;
    /