ラベル ベクトル検索 の投稿を表示しています。 すべての投稿を表示
ラベル ベクトル検索 の投稿を表示しています。 すべての投稿を表示

2025年7月24日木曜日

Oracle AI Vector SearchのBINARY Vector Generatorの例題をAPEXで実行する

先日、FLOAT32 Vector Generatorの例題について記事を書いています。今回は、その次のセクションに記載されているBINARY Vector Generatorの例題をAPEXのアプリケーションに実装してみます。

Oracle AI Vector Search User's Guide
3 Getting Started
SQL Quick Start Using a BINARY Vector Generator

注意:
ドキュメントに「Do not use the vector generator on production databases. The program is made available for testing and demo purposes.」記載されているように、Getting Startedの作業を本番データベースで実施しないでください。

作成したAPEXアプリケーションは以下のように動作します。今回は2次元の散布図なので、APEX標準のチャートを使用します。2次元の散布図にバイナリ・ベクトルを表示するため、バイナリ・ベクトルに対してt-SNEを適用し、2次元の埋め込み空間へ次元圧縮を行っています。t-SNEを適用するOML4Pyの埋め込みファンクションを定義し、OML4Py SQL APIから呼び出しています。


作成したAPEXアプリケーションのエクスポートを以下に置いています。
https://github.com/ujnak/apexapps/blob/master/exports/binary-vector-search-genbvec-jet.zip

Plotlyを組み込んでいないため、FLOAT32 Vector Generatorを扱うAPEXアプリケーションより簡単な作りになっています。

OML4Pyを使うため、このAPEXアプリケーションを実行できるプラットフォームはx86_64に限定されます。本記事ではAlways FreeのAutonomous Database上でアプリケーションを開発しています。

Autonomous DatabaseでOML4PyのSQL APIを呼び出す手順については、以前に記事「Autonomous DatabaseでPythonで記述したファンクションを表関数として実行する」で紹介しています。以下の2つの作業は、あらかじめ実施しておきます。
  1. APEXのワークスペース・スキーマのOMLユーザーオンにします。
  2. 管理者ユーザーADMINにて、pyqAppendHostAceを呼び出してネットワークACLを追加します。
OML4Pyが標準で持っているパッケージのみを使用するため、condaによる環境作成とアップロードは不要です。

また、実行計画を表示するため、APEXのワークスペース・スキーマに以下の権限を割り当てています。

grant select_catalog_role to <APEXワークスペース・スキーマ>;
grant select on sys.v_$sql to <APEXワークスペース・スキーマ>;
grant select on sys.v_$session to <APEXワークスペース・スキーマ>;
grant select on sys.v_$sql_plan to <APEXワークスペース・スキーマ>;

以下より、APEXアプリケーションの実装と使用しているAPEXの機能について、大まかに説明します。

サポートするオブジェクトインストール・スクリプトで、アプリケーションの動作に必要なデータベース・オブジェクトを作成しています。


この中で、表GENBVECの作成(スクリプトgenbvec)、プロシージャgenerate_random_binary_vectorgenerate_binary_clustergenerate_binary_vectorsの作成スクリプトは、ドキュメントに記載されているコードをそのままインストール・スクリプトにしています。

スクリプトgenbvec_tsneにて、表GENBVEC_TSNEを作成します。OML4PyのSQL APIを呼び出してt-SNEを適用した結果が、表GENBVEC_TSNEに保存されます。
create table genbvec_tsne(
    name varchar2(500),
    x number,
    y number
);
スクリプトgenbvec_vにてビューGENBVEC_Vを作成します。
create or replace view genbvec_v
as
select name, bv from genbvec;
OML4PyのpyqTableEvalの引数inp_namに与える表はVECTOR型を含むことができないようです。t-SNEの適用に必要な列NAMEと列BV(バイナリ・ベクトルの文字列表現)のみを含むビューGENBVEC_Vを作成し、pyqTableEvalのinp_namに指定します。

スクリプトcompute_tsne_embeddingにて、OML4PyのSQL APIから呼び出すPythonファンクションcompute_tsne_embeddingを作成します。


Pythonスクリプトcompute_tsne_embeddingは、入出力仕様を与えた上で、Claude Sonnet 4とOpenAI GPT-4oの両方を使って書いてもらっています。

以上のインストール・スクリプトが実行されると、このAPEXアプリケーションが必要としているデータベース・オブジェクトが準備されます。

インストール・スクリプトによって作成されたオブジェクトは、削除スクリプトによる削除されます。そのため、APEXアプリケーションを削除すると元の状態に戻ります。

APEXアプリケーションをインストールして実行します。

ナビゲーション・メニューにはホームTableConfigurationsOMLの4つのメニューが含まれます。記事の先頭にあるGIF動画は、ホーム・ページでの作業になります。

Configurationsのページでは、完全一致検索に使用するSELECT文と、検索条件が与えられていない場合に使用するSELECT文が登録されています。Getting Startedに記載されているSELECT文がデフォルトになっています。


OMLのページでは、OML4PyのSQL APIの呼び出しに必要な認証を実行します。APEXのワークスペース・スキーマのパスワードを入力し、ボタンGet Token / Set Auth Tokenをクリックします。

このページの実装については、OML4Pyの記事で説明しています。


Tableのページでは、表GENBVECへのデータ生成を行います。


プロセスGenerate Vectorsが、プロシージャGENERATE_BINARY_VECTORSを呼び出しています。ページ・アイテムはぞれぞれプロシージャGENERATE_BINARY_VECTORSの引数に対応しています。


表GENBVECへのデータ生成に続けてt-SNEを適用します。t-SNEの適用はプロセスcompute_tsne_embeddingが実行します。実行するPL/SQLコードは以下になります。適用結果は表GENBVEC_TSNEに保存されます。

Pythonファンクションcompute_tsne_embeddingは引数としてrandom_stateperplexitylearning_raten_tierを含んでいます。pyqTableEvalの引数par_lstに与えるJSONで、これらの引数の値を指定できます。


ボタンTruncate Tableをクリックすると、プロセスTruncate Tableが実行されます。表GENBVECおよびGENBVEC_TSNEがトランケートされます。


ホーム・ページには2つのボタン、SearchResetがあります。ボタンResetはページ・アイテムに設定された値を空白にします。そのため、実質的な処理を行うボタンはSearchのみになります。


ボタンSearchをクリックすると、以下のPL/SQLコードをサーバー側のコードとして実行します。検索されたバイナリ・ベクトルの名前をAPEXコレクションに保存します。

検索が完了した後に、チャート、実行計画、レポートのリージョンをリフレッシュして検索結果を反映します。


2次元の散布図はAPEXの標準チャートを使用しています。シリーズソースとして以下のSQL問合せを記述しています。

select REGEXP_SUBSTR(name, '^[^-]+') series, name, x, y from genbvec_tsne
where name in (
    select c001 from apex_collections where collection_name = 'SEARCH_RESULT'
)

列のマッピングシリーズ名に列SERIESラベルに列NAMEXに列XはいこれはYの翻訳ミスでしょう)に列Yを割り当てます。


Oracle APEXのチャートでは、チャートのX軸やY軸の最大値と最小値をページ・アイテムを元に設定できません。最大値と最小値が無指定の場合、表示するデータに合わせて最大値と最小値が決まります。

例えばベクトルC1の近傍20件を検索すると、チャートの表示は以下のようになります。


ベクトルC2の近傍20件を検索すると、チャートの表示は以下のようになります。検索されたベクトルに合わせてX軸やY軸の範囲が代わり、検索されたベクトルはつねにチャート全体に表示されます。


チャートのX軸、Y軸の最小値と最大値を、検索結果によらず、すべてのベクトルが表示できる値に固定するために、チャートの初期化JavaScriptファンクションに以下を記述しています。
function(config) {
    minVal = Number(apex.item("P1_MIN_VALUE").getValue());
    maxVal = Number(apex.item("P1_MAX_VALUE").getValue());
    config.xAxis.min = minVal;
    config.xAxis.max = maxVal;
    config.yAxis.min = minVal;
    config.yAxis.max = maxVal;
    return config;
}

X軸、Y軸の最小値(ページ・アイテムP1_MIN_VALUE)最大値(ページ・アイテムP1_MAX_VALUE)は表GENBVEC_TSNEの列XとYの値より算出しています。

今回の記事は以上になります。

Oracle APEXのアプリケーション作成の参考になれば幸いです。

2025年7月23日水曜日

Oracle AI Vector SearchのFLOAT 32 Vector Generatorの例題をAPEXで実行する

Oracle AI Vector Search User's Guideに以下の章が含まれています。

Oracle AI Vector Search User's Guide
3 Getting Started
SQL Quick Start Using a FLOAT32 Vector Generator

ドキュメントではコマンドを実行して動作を確認する手順になっています。Getting Startedがコマンドラインの操作というのも敷居が高いように感じたので、SQL Quick Start Using a FLOAT32 Vector Generatorに記載されている作業を実行できるAPEXアプリケーションを作ってみました。

注意:
ドキュメントに「Do not use the vector generator on production databases. The program is made available for testing and demo purposes.」記載されているように、Getting Startedの作業を本番データベースで実施しないでください。

作成したAPEXアプリケーションは以下のように動作します。チャート表示にPlotlyのJavaScriptライブラリ(scatter3dチャート)を使用しています。


実行計画を表示するために、APEXのワークスペース・スキーマに以下の権限を割り当てています。

grant select_catalog_role to <APEXワークスペース・スキーマ>;
grant select on sys.v_$sql to <APEXワークスペース・スキーマ>;
grant select on sys.v_$session to <APEXワークスペース・スキーマ>;
grant select on sys.v_$sql_plan to <APEXワークスペース・スキーマ>;

Plotlyのscatter3dチャートに検索結果を表示するため、ベクトルの次元数は3以上である必要があります。次元数は3より大きい値にできますが、チャートは最初の3次元だけを表示に使います。

記述したコードのほとんどは、データベースからPlotly向けにデータを取得するためのコードなので、Oracle DatabaseのVector Searchのサンプルというよりは、PlotlyのチャートをOracle APEXのアプリケーションに組み込んで使うサンプルになっています。

作成したAPEXアプリケーションのエクスポートを以下に置いています。
https://github.com/ujnak/apexapps/blob/master/exports/vector-search-genvec-plotly.zip

以下よりAPEXアプリケーションの実装と使用しているAPEXの機能について、大まかに説明します。

Oracle APEXのアプリケーションには、サポートするオブジェクトという項目があります。


サポートするオブジェクトでは、APEXアプリケーションのインストールアップグレードおよび削除時の処理を定義できます。

ほとんどの場合、インストールではAPEXアプリケーションが必要としている表、ビューおよびパッケージの作成を行います。削除では、それらのデータベース・オブジェクトの削除を行います。


本記事のアプリケーションのインストール・スクリプトでは、表GENVECの作成とパッケージVECTOR_GEN_PKGの作成を行なっています。


削除スクリプトでは、パッケージVECTOR_GEN_PKGの削除と表GENVECの削除を行なっています。


そのため、APEXアプリケーションをインストールするとGetting Startedの作業を行うために必要な表GENVECとパッケージVECTOR_GEN_PKGが作成されます。また、アプリケーションを削除すると、表GENVECとパッケージVECTOR_GEN_PKGも合わせて削除されます。

APEXアプリケーションをインストールして実行します。

ナビゲーション・メニューには、ホームIndexTableConfigurationsの4つのメニューが含まれます。記事の先頭にあるGIF動画は、ホーム・ページでの作業になります。

Configurationsのページでは、上から近似近傍検索(ANN検索)に使用するSELECT文、完全一致検索に使用するSELECT文、検索条件が与えられていない場合に使用するSELECT文、HNSW索引を作成するDDL、IVF索引を作成するDDLの5つのスクリプトが登録されてます。概ねGetting Startedに記載されているSELECT文やCREATE INDEX文がデフォルトになっています。

索引名はHNSW、IVFともにGENVEC_VECTOR_IDXとしています。また、SELECT文にコメントとして/* my_vector_query */を含めることにより、実行計画を取り出しやすくしています。検索条件の第1引数としてベクトル値、第2引数として検索する件数が与えられます。

SELECT文やDDLを変更することで、例えば距離をEUCLIDEANからCOSINEに変更したり、索引の精度を変更したりできます。


これらのSELECT文やDDLを、共有コンポーネントアプリケーション・アイテムに保存しています。


それぞれのアプリケーション・アイテムアプリケーションの計算を作成し、デフォルト値を設定しています。計算ポイント新規インスタンス(新規セッション)開始時を選択し、計算タイプ静的値計算にデフォルトのスクリプトを記述しています。

結果として、セッション開始時アプリケーションの計算に設定したスクリプトがアプリケーション・アイテムに設定されます。


アプリケーション・アイテムはページに直接配置できません。そのため、アプリケーション・アイテムソースとしたページ・アイテムを作成しています。


ボタンSUBMITをクリックしたときに以下のコードを実行することにより、ページ・アイテムに記述したスクリプトをアプリケーション・アイテムに転記しています。
begin
    apex_session_state.set_value('SELECT_EXACT',     :P4_SELECT_EXACT);
    apex_session_state.set_value('SELECT_APPROX',    :P4_SELECT_APPROX);
    apex_session_state.set_value('SELECT_DEFAULT',   :P4_SELECT_DEFAULT);
    apex_session_state.set_value('CREATE_INDEX_IVF', :P4_CREATE_INDEX_IVF);
    apex_session_state.set_value('CREATE_INDEX_HNSW', :P4_CREATE_INDEX_HNSW);
end;

Tableのページでは、表GENVECへのデータの生成とトランケートを行います。データの生成にはVECTOR_GEN_PKG.GENERATE_VECTORSを呼び出します。ページ・アイテムはそれぞれ、VECTOR_GEN_PKG.GENERATE_VECTORSの引数に対応しています。


Oracle APEXではプロセス・タイプとしてAPIの呼出しを選択することにより、コードを記述せずにプロシージャおよびファンションを呼び出すことができます。


Truncate文のようなDDLは、EXECUTE IMMEDIATE文で実行します。こちらは若干ですが、コーディングが必要です。
begin
    execute immediate 'truncate table genvec';
exception
    when others then
        null;
end;

Indexのページでは、HNSWとIVFの索引の作成および削除を行います。索引GENVEC_VECTOR_IDXが作成済みの場合は、V$VECTOR_INDEXの内容を表示します。

ドキュメントのGetting StartedではVECSYS.VECTOR$INDEXを検索していますが、この表はAutonomous Databaseには存在しないため、V$VECTOR_INDEXに置き換えています。


画面上のボタンとしてDrop IndexCreate Hnsw IdxCreate Ivf Idxの3つがあります。

このボタンをクリックしたときに実行されるプロセスとして、以下の4つが作成されています。
  1. Drop Index
  2. Create Hnsw Index
  3. create Ivf Index
  4. Gather Table Stats
この内、Drop IndexおよびGather Tables Statsには、サーバー側の条件が無く、どのボタンを押しても実行されます。


ボタンCreate Hnsw Idxがクリックされた時に限り、プロセスCreate Hnsw Indexが実行されます。この時、アプリケーション・アイテムCREATE_INDEX_HNSWに設定されているコマンドが実行されます。


ボタンCreate Ivf Idxがクリックされたは、プロセスCreate Ivf Indexが実行されます。この時、アプリケーション・アイテムCREATE_INDEX_IVFに設定されているコマンドが実行されます。


このようにサーバー側の条件を設定して、単一の処理を組み合わせた簡単な処理フローを定義することができます。これとは逆に、以下のようにプロセス中のコードで処理フローを記述することもできます。
declare
    C_DROP_INDEX   constant varchar2(400) := q'~DROP INDEX if exists genvec_vector_idx~';
begin
    /* 索引のドロップ */
    execute immediate C_DROP_INDEX;
    /* 索引の作成 */
    if :REQUEST = 'CREATE_HNSW_IDX' then
        execute immediate :CREATE_INDEX_HNSW;
    elsif :REQUEST = 'CREATE_IVF_IDX' then
        execute immediate :CREATE_INDEX_IVF;
    end if;
    /* 統計情報の収集 */
    DBMS_STATS.GATHER_TABLE_STATS(
        ownname => null,
        tabname          => 'GENVEC',
        estimate_percent => DBMS_STATS.AUTO_SAMPLE_SIZE,
        cascade          => TRUE
    );
end;
ホーム・ページには3つのボタン、SearchApprox SearchおよびResetがあります。ボタンResetはページ・アイテムに設定された値を空白にします。そのため、実質的な処理を行うボタンは、完全一致検索を行うSearch近傍近似検索を行うApprox Searchになります。


ページ・プロパティJavaScriptファイルURLに以下を記述し、Plotlyのライブラリを読み込みます。

https://cdn.plot.ly/plotly-3.0.1.min.js

ファンクションおよびグローバル変数の宣言にて、scatter3dチャートのレイアウトをlayoutとして設定します。rangenullを設定していますが、rangeは検索結果に基づいて設定されます。



ボタンSearchApprox Searchの双方とも、ボタンクリック時の動的アクションで以下のJavaScriptコードを実行します。


x01this.triggeringElement.idを与えることで、ボタンの違いを認識します。ボタン名をIDとして参照させるため、ボタンに静的IDを設定しています。Oracle APEXではHTML要素のIDにランダムな文字列を割り当てます。そのため、要素をID指定で参照する場合は、明示的に静的IDを設定する必要があります。


このコードでは、サーバー側に実装したAjaxコールバックGET_DATAを呼び出し、返されたデータを元にPlotlyのscatter3dチャート(DIV要素myDiv)を更新しています。また、ページ・アイテムに値を設定しリージョンをリフレッシュすることにより、実行計画(リージョンPLAN)および検索結果のレポート(リージョンVECTORS)を更新しています。

ベクトル検索の実行および呼び出し元に返すデータを生成するプロセスGET_DATAのコードは以下になります。



実行計画は動的コンテンツとして表示しています。ソースCLOBを返すPL/SQLファンクション本体に以下を記述しています。



対話モード・レポートによる検索されたベクトルの一覧は、プロセスGET_DATA内で保存したベクトルの名前を元にしています。

ソースSQL問合せは以下になります。

select * from genvec where name in (select column_value from apex_string.split(:P1_ALL_VECTORS,','))


今回の記事は以上になります。

Oracle APEXのアプリケーション作成の参考になれば幸いです。

2025年7月16日水曜日

DifyがOracle Databaseに作成したナレッジベースをAPEXアプリケーションで検索する

Difyのナレッジベースの格納先として、比較的簡単にOracle Databaseを利用できます。Difyはナレッジの検索に、Oracle Databaseが提供する全文検索とベクトル検索を活用します。

DifyはAI向けの開発ツールなだけあって、ナレッジベースへのドキュメントの投入、チャンクの分割およびエンべディングの生成など、一通りの作業を開発ツールのUIで実行できます。Dify自体は「Difyプラットフォームに組み込まれたナレッジベース機能とテキスト検索・取得メカニズムには制約があり、検索結果を簡単に変更することができません。」(ドキュメントのここ)と言っていて、高い要求には外部ナレッジベースの連携機能を提供しています。

そのため、Oracle Databaseとの連携という意味では、Oracle Databaseをナレッジベースとして呼び出せる外部連携APIを実装するという手段もあるかとは思います。今回は、手早くテキスト検索とベクトル検索を実装するために、DifyのナレッジベースをAPEXアプリケーションで検索してみます。

Difyの環境は記事「Oracle Database 23ai Freeをベクトル・ストアとしたDifyのローカル環境を作成する」にて紹介している手順で作成しています。DifyおよびOracle Databaseのコンテナは、macOSのpodmanで実行しています。

テキスト・エンべディングのモデルとして、Ollamaのbge-m3:latestを使用するように設定済みとします。


以下よりDifyでナレッジベースを作成して、APEXアプリケーションから検索するまでの作業を紹介します。

最初にDifyでナレッジベースを作成します。

ナレッジタブを開き、ナレッジベースを作成を実行します。


今回はテキストファイルからインポートしてナレッジベースを作成します。

参照をクリックして、アップロードするテキストファイルを選択します。


ファイルを選択したのち、次へ進みます。


APEXアプリケーションから検索できるように、インデックス方法高品質検索設定ハイブリッド検索を設定します。エンべディングの生成に使用される埋め込みモデルは、APEXアプリケーションでも使用するモデルになるため、確認しておきます。

検索ハイブリッド検索を設定することにより、エンべディングの生成とOracle Text索引の作成の両方が行われます(実際にはベクトル検索を選んだ時もOracle Text索引が生成されるように見受けられますが、ハイブリッド検索を選んだ方が確実です)。

その他のパラメータは必要に応じて調整します。

保存して処理をクリックします。


チャンクやエンべディングの生成が行われ、ナレッジベースの保管先であるOracle Databaseに保存されます。

ドキュメントに移動します。


アップロードされたドキュメントが利用可能になっていることを確認します。

検索テストを開きます。


ソーステキストに適当な文章を入力し、テスト中をクリックします。

チャンクが検索できたら、とりあえずナレッジベースの作成は完了です。


ナレッジベースの保存先になっているOracle Databaseのスキーマで、SQLを実行します。

今回はOracle APEXのワークスペース・スキーマにナレッジベースを保存しているので、SQLの実行にSQLワークショップSQLコマンドを使用します。

最初に作成されたナレッジベースの表を探します。以下のSELECT文を実行します。
select object_type, object_name, to_char(created,'RR-MM-DD HH24:MI:SS') created from user_objects
where object_type = 'TABLE' and object_name like 'EMBEDDING_VECTOR_INDEX%NODE' order by created desc

ナレッジベースの表の名前は、EMBEDDING_VECTOR_INDEXで始まりNODEで終わるようです。これは現状がこうだった、ということで今後変わる可能性はあります。

この表名を参照してAPEXアプリケーションを作ると、表名が変わった時に面倒なので、ビューとしてDIFY_KB_TESTを作成します。元表の名前は上記のSELECT文で見つけたOBJECT_NAMEで置き換えます。主キー列はID、チャンクが保存されている列はTEXT(この列にOracle Text索引が作成されています)、エンべディングが保存されている列はEMBEDDINGです。
create or replace view dify_kb_test
as
select id, json_value(meta, '$.source') source, text, embedding from 
EMBEDDING_VECTOR_INDEX_A6C2A40F_41B4_4D1C_B543_3EF634CC408A_NODE;

エンべディングが保存されている列のVECTOR_INFOを確認します。
select column_name, vector_info from user_tab_cols where table_name = 'DIFY_KB_TEST' and data_type = 'VECTOR'
VECTOR(*,*,DENSE)となっているため、エンべディングの次元数や精度を確認するには、表に保存されているエンべディングを参照する必要があります。


ビューDIFY_KB_TESTより1つだけエンべディングを取り出し、次元数と精度を確認します。
select vector_dimension_count(embedding) count, vector_dimension_format(embedding) format 
from dify_kb_test where embedding is not null fetch first 1 rows only;

count1024formatFLOAT64と返されました。APEXアプリケーションで検索文章からエンべディングを生成するときに、この次元数と精度を指定する必要があります。

以上で、Difyのナレッジベースとして作成された表について確認ができました。

これからAPEXでアプリケーションを作成します。

最初にエンべディングを生成するために、Ollamabge-m3:latestを呼び出すベクトル・プロバイダを作成します。

データベースに以下のファンクションgenerate_embeddingを作成します。

OllamaのようなローカルLLMをベクトル・プロバイダとする場合はPL/SQLによるカスタム・ファンクションが必要です。ONNXモデル、Oracleの生成AIサービス、OpenAIやCohereであれば、設定だけでベクトル・プロバイダを作成することができます。しかし、Difyがエンべディングを生成する際に選んだ精度とOracle側が選んだ精度が異なる場合は、これらの組み込みのプロバイダでもPL/SQLによるカスタム・ファンクションの作成が必要になるでしょう。

Difyと同じモデルを呼び出せないため、ONNXモデルは対象外になります。

作成したファンクションgenerate_embeddingを呼び出すベクトル・プロバイダを作成します。

共有コンポーネントベクトル・プロバイダを開きます。


作成済みのベクトル・プロバイダの一覧画面で、作成をクリックします。

プロバイダ・タイプカスタムPL/SQLを選択します。名前Ollama bge-m3:latest静的IDollama_bge_m3_latestとします。

ローカル埋込みカスタム・ファンクション名に先ほどPL/SQLで作成したファンクションgenerate_embeddingを指定します。

以上で、ベクトル・プロバイダを作成します。


ベクトル・プロバイダとしてOllama bge-m3:latestが作成されました。


空のAPEXアプリケーションを作成します。名前Difyナレッジベース検索とします。


アプリケーションが作成されたら、共有コンポーネント構成の検索(検索構成)を開きます。


作成済みの検索構成が一覧されます。作成をクリックし、新規に検索構成の作成を始めます。


最初にベクトル検索の検索構成を作成します。

名前ベクトル検索とします。検索タイプOracleベクトル検索を選択します。

へ進みます。


ベクトル・プロバイダに先ほど作成したOllama bge-m3:latestを選択します。ソース・タイプ表/ビューの名前としてDIFY_KB_TESTを選択します。

へ進みます。


主キー列IDベクトル列EMBEDDINGタイトル列SOURCE説明列TEXTを選択します。アイコン・ソースアイコン・クラスを選択し、アイコンCSSクラスfa-chatbotを指定します。

以上で検索構成の作成をクリックします。


検索構成としてベクトル検索が作成されます。編集画面が開きます。

必須ではありませんが、後から参照しやすいように静的IDVECTOR_SEARCHに変更します。

変更の適用をクリックします。


検索構成の一覧画面に戻ります。続けてテキスト検索の検索構成を作成します。


名前テキスト検索とします。検索タイプOracle Textを選択します。

へ進みます。


ソース・タイプ表/ビューの名前としてDIFY_KB_TESTを選択します。

へ進みます。


主キー列IDOracle Text索引列TEXTタイトル列SOURCE説明列TEXTを選択します。アイコン・ソースアイコン・クラスを選択し、アイコンCSSクラスfa-fontを指定します。

以上で検索構成の作成をクリックします。


検索構成としてテキスト検索が作成されます。編集画面が開きます。

必須ではありませんが、後から参照しやすいように静的IDTEXT_SEARCHに変更します。

変更の適用をクリックします。


以上で検索構成としてベクトル検索テキスト検索が作成されました。


検索ページを作成します。

ページの作成をクリックします。


コンポーネントとして検索ページを選択します。


作成するページの名前ナレッジベース検索とします。ページ・モード標準です。構成の検索テキスト検索ベクトル検索の双方をチェックします。

以上でページの作成をクリックします。


検索ページが作成されます。

今回は検索ができることが確認できるだけで良いので、検索結果テキスト検索ベクトル検索の双方を選択し、外観最大結果数に制限します。

以上で、ページの保存と実行をクリックします。


検索ページが開かれます。

適当な文章や文字を入力して、ベクトル検索とテキスト検索の双方で検索結果が返されることを確認します。



Difyで全文検索を行った際に以下のエラーが発生しました。

** Resource punkt_tab not found. Please use the NLTK Downloader to obtain the resource: >>> import nltk >>> nltk.download('punkt_tab')  For more information see: https://www.nltk.org/data.html Attempted to load tokenizers/punkt_tab/english/ Searched in: - '/root/nltk_data' - '/app/api/.venv/nltk_data' - '/app/api/.venv/share/nltk_data' - '/app/api/.venv/lib/nltk_data' - '/usr/share/nltk_data' - '/usr/local/share/nltk_data' - '/usr/lib/nltk_data' - '/usr/local/lib/nltk_data' **

原因をClaudeに聞いたところ、以下の回答が得られました。

「このエラーは、Difyのナレッジベースでテキスト処理を行う際に、NLTK(Natural Language Toolkit)のpunkt_tabリソースが見つからないために発生しています。」

対処としてコンテナdocker-api-1にpunktにpunkt_tabをインストールしました。

% podman exec -it docker-api-1 bash

root@4d7fbfca0440:/app/api# python

Python 3.12.11 (main, Jul  1 2025, 10:08:28) [GCC 12.2.0] on linux

Type "help", "copyright", "credits" or "license" for more information.

>>> import nltk; nltk.download('punkt_tab')

[nltk_data] Downloading package punkt_tab to /root/nltk_data...

[nltk_data]   Unzipping tokenizers/punkt_tab.zip.

True

>>> exit

Use exit() or Ctrl-D (i.e. EOF) to exit

>>> 

root@4d7fbfca0440:/app/api# 


punkt_tabをインストールすると、エラーの発生は解消しました。

今回の記事は以上になります。

単純にこのまま使えるというものではありませんが、少なくても検索はできることが確認できました。

今回作成したAPEXアプリケーションのエクスポートを以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/dify-knowlegebase-search.zip

Oracle APEXのアプリケーション作成の参考になれば幸いです。