目次
はじめに
1ヵ月ほど前にOracle AI Database 26aiの新機能として"Oracle Trusted Answer Search"という製品がリリースされました。
こちらは自然言語でセマンティック検索できるというもので、いわゆるベクトル検索+テキスト検索を活用した製品です。
社内情報等の生成AIを通した活用としては、ベクトル検索を使ったRAGを実装し、LLMによる処理を介在させるのが一般的かと思います。
Trusted Answer SearchはそうしたRAGとは異なり、LLMを使わず決定論的な回答を行う点に重きを置いています。
それはLLMを使った情報検索において以下のような課題があるためです。
- 回答が非決定論的でぶれる
- ハルシネーションのリスクがある
- 回答までのレイテンシが大きい
- モデルによって振る舞いが変わる
- ドメイン知識が必要な質問への対応が難しい (LLM追加学習、RAG実装のコスト高)
- 複雑なスキーマにおいてNL2SQL (SQL RAG) の信頼性が低下する
これらを解決するため、Trusted Answer SearchはLLMを使わず、ONNXによるIn-Database Embedding、およびテキスト索引を使ったハイブリッド検索を中心に構成されています。
加えて検索結果に対するフィードバック機能や、専門用語や類義語に対応するための仕組みが備わっており、LLMの追加学習やRAGと比べ、低コストで検索精度を継続的に向上させられます。
またRAGの場合、検索対象は社内ドキュメントそのものや、SQL RAGであればDB内データになります。
Trusted Answer Searchは情報源を直接に検索対象とするのではなく、情報源のメタデータ(タイトル、概要、質問例)を検索します。
検索結果に含まれる情報はメタデータのほか、情報源につながるURL、もしくはSQLとなります。
例えばURLの場合、アクセスした先に何らかのドキュメントや統計情報、チャートなどがある、といったイメージです。
SQLであれば、それをDBに対して実行することで、もとの自然言語の検索クエリに対応するデータを抽出できる、といった具合です。
ちなみにTrusted Answer Searchを使った検索は以下イメージです。
言葉だけでは分かりにくい気がしますので、以下に具体的なTrusted Answer Searchの構築手順、利用手順を載せたいと思います。
構築手順
Oracle AI Database 26ai構築
今回はOCI Compute (1 OCPU、32 GB メモリ) にインストールしたOracle AI Database 26ai (23.26.1) を使いました。
なおTrusted Answer Searchはオンプレ版26aiに加え、ADB-Sの26aiでも利用できます。
オンプレ版を利用する際のDBインストール手順は以下記事をご参照ください。
(RAC向け手順ですが、GI関連の手順をSkipすればシングル構成で構築できます。)
ONNXファイルの準備
Trusted Answer SearchはONNXによるIn-Database Embeddingが前提となります。
そのためHugging Face等にあるEmbeddingモデルを、OML4PyでONNXファイルに変換しておく必要があります。
変換手順は以下記事をご参照ください。
上記ではサイズの大きい高精度なモデルを使っていますが、もちろんサイズの小さいモデルでも大丈夫です。
今回は↑の記事で作成した multilingual-e5-large を使いました。
APEX、ORDSインストール
Trusted Answer Searchは専用APEXアプリとの連携が必須の機能ですので、APEXとORDSをインストールします。
インストール手順は以下記事をご参照ください。
なおAPEXは 24.2 以上が要件です。
APEX、ORDSのインストール
Trusted Answer Search用PL/SQLパッケージ、ディクショナリのインストール
Trusted Answer Searchを使うには専用のPL/SQLパッケージおよびディクショナリのインストールが必要です。
インストール用スクリプトはTrusted Answer Search本体に同梱されているので、以下よりダウンロードします(要Oracleアカウント)。
スクリプトは解凍したファイルの trusted_search/backend_ship/ 配下にあります。
同階層に README.md があるので、そちらを読んで作業を進めます。
ざっくりお伝えすると以下作業を行います。
-
install_backend.confに以下の必要情報を入力-
DB_CONNECT_STRING: インストール先DBの接続識別子 -
DB_USER: インストールに利用するDBユーザ(私はSYSを使いました) -
DB_PASSWORD: インストールに利用するDBユーザのパスワード -
TASADMIN_PASSWORD: Trusted Answer Searchを管理するDBユーザTASADMINのパスワード -
MODEL_FILE_NAME: ONNXファイルのファイル名 -
MODEL_DIR: ONNXファイルが配置されている絶対パス
-
-
install_backend.shを実行
ちなみに install_backend.sh の実行ログは以下になります。
install_backend.sh の実行ログ
$ ./install_backend.sh --config install_backend.conf
ℹ Loaded configuration from: install_backend.conf
╔═══════════════════════════════════════════════════════════════╗
║ ║
║ Trusted Answer Search Backend Installation ║
║ ║
║ Version 26.1 ║
╚═══════════════════════════════════════════════════════════════╝
→ Pre-Installation Checks
────────────────────────────────────────────────────────────
• Validating SQL*Plus availability ✔
SQL*Plus:
• Testing database connectivity ✔
Connected: PDB1 as sysdba
User: SYS
• Checking database version ✔
Version: Oracle AI Database 26ai Enterprise Edition Release 23.26.1.0.0 - Production (Major: 23)
• Detecting setup type ✔
Setup type : On-Premises
• Validating user privileges ✔
Skipped: SYS on on-prem has the required privileges implicitly
→ Creating Application Schemas
────────────────────────────────────────────────────────────
• Creating TRUSTED_SEARCH schema ✔
Tablespace: USERS
• Granting INHERIT PRIVILEGES to TRUSTED_SEARCH ✔
Granted INHERIT PRIVILEGES on USER SYS to TRUSTED_SEARCH
• Creating TASADMIN schema ✔
TASADMIN schema created
→ Installing Application Objects
────────────────────────────────────────────────────────────
• Compiling DDL packages ✔
Compiled DDL related packages (as installer user)
• Granting privileges to SYS ✔
Granted execute privilege to SYS (as TRUSTED_SEARCH)
• Installing Trusted Search Schema ✔
Created Trusted Search objects (as TRUSTED_SEARCH)
• Revoking temporary privileges from SYS ✔
Revoked execute privilege from SYS (as TRUSTED_SEARCH)
• Installing Trusted Search packages ✔
Compiled Trusted Search packages (as installer user, in TRUSTED_SEARCH schema)
• Creating synonym in TASADMIN schema ✔
Created dbms_trusted_search synonym in TASADMIN schema
• Loading the embedding model ✔
• Securing TRUSTED_SEARCH account ✔
TRUSTED_SEARCH account locked and set to no authentication
→ Post-Installation Verification
────────────────────────────────────────────────────────────
• Verifying packages ✔
• Verifying model directory object ✔
• Verifying tables ✔
• Verifying indexes ✔
ℹ All post-installation checks passed successfully
╔═══════════════════════════════════════════════════════════════╗
║ ║
║ Installation Completed Successfully ║
║ ║
╚═══════════════════════════════════════════════════════════════╝
ℹ Installation log: /home/oracle/tas/trusted_search/backend_ship/logs/install_backend.log
APEXアプリのインポート
先述した通り、Trusted Answer Searchには専用APEXアプリがあります。
アプリは2種類あり、1つは管理用、もう1つはユーザ用です。
このうち管理用アプリは必須となります。
いずれも解凍した本体の trusted_search/apex_ship 配下にエクスポートされたファイルがあります。
admin.zip というファイルがあるので、こちらをAPEXにインポートすればインストール完了です。
細かい手順は同階層にある README.md をご参照ください。
APEXのインポート画面は以下のようになります。
動作確認にあたりユーザ用アプリもあった方が良いので、同じ手順で portal.zip もAPEXにインポートしておきます。
管理アプリにアクセスするとログイン画面が表示されるので、 TASADMIN でログインします。
ログインすると以下のようなダッシュボードが表示されます。
利用手順
ここから実際に検索対象となる情報を登録していきます。
今回はインストーラ本体に同梱されているサンプルデータを使います。
サンプルは trusted_search/apex_ship/samples/wikimedia 配下にあります。
また参考ドキュメントは以下になります。
Search Space作成
一番最初にやることは Search Space の作成です。
検索したい情報のテーマ、カテゴリ毎に Search Space を作るイメージです。
管理用APEXアプリにログインし、Search Spaces ⇒ Create Search Space と選択します。
以下のように記入し、Createを押下します。
Search Target、Target Value Set作成
次に検索対象となるデータを Search Space に追加します。
編集対象は Search Target および Target Value Set です。
- Search Target: 検索対象となる情報で、タイトルや概要説明、質問例文、情報源へアクセスするためのURL/SQLを保持します。
- Target Value Set: URL/SQLは動的に値を埋め込める変数を使えるのですが、その変数に入れるための値を定義します。
- ex:
frequencyという変数があるとき、セットできる値としてmonthly、dailyを定義
- ex:
これらの編集方法は2通りあり、管理アプリ上で1件ずつ追加するか、JSONファイルのインポートでバッチ的に追加するか、になります。
管理アプリ上で追加
今回は使いませんでしたが、管理アプリ上で情報を入力して追加する機能が提供されています。
まずは Search Target を作成します。
右上の Search Space を Wikimedia にした状態で Search Targets ⇒ Create Search Target と進み、1件ずつデータを追加します。
次に Target Value Set を作成します。
右上の Search Space を Wikimedia にした状態で Target Value Sets ⇒ Create Target Value Set と進みます。
フォームに変数名、格納する値の候補、各候補のシノニム(類義語)を入力します。
値の候補は手動で1件ずつ追加、もしくはDB内のテーブルから読み込む、の2通りがあります。
JSONファイルのインポートでバッチ的に追加
もう1つは、あらかじめ追加したいデータをJSONファイルに格納し、インポートしてバッチ的に追加する方法です。
今回はこちらの方法で追加します。
あらかじめJSONファイルを作成しておく必要があり、Search Target、Target Value Set それぞれ必要なプロパティが決まっています。
まず Search Target ですが、今回のサンプルデータでは以下のようになります。
[
{
"title": "Total Page Views - All Projects",
"descriptions": [
"This report shows overall pageview volume across all Wikimedia projects over time. It opens a time-series chart with a table view and supports changing the time window and daily or monthly granularity. It is useful for readers, analysts, and community members tracking overall demand for Wikimedia content."
],
"target_action": {
"url": "https://stats.wikimedia.org/#/all-projects/reading/total-page-views/normal|bar|:period|~total|:frequency",
"target_inputs": [
{
"name": "period",
"target_value_set": "period"
},
{
"name": "frequency",
"target_value_set": "frequency"
}
]
},
"sample_queries": [
"How many total page views did all Wikimedia projects get over the last 2 years?",
"Show monthly page views for all Wikimedia projects.",
"What is the daily pageview trend for all Wikimedia projects?",
"How has readership changed for all Wikimedia projects over the last year?",
"Show overall pageview totals for all Wikimedia projects.",
"Can I see page views for all Wikimedia projects by month?",
"How many page views did all Wikimedia projects get in 2025?",
"Show the long-term pageview trend for all Wikimedia projects.",
"Is traffic rising or falling for all Wikimedia projects?",
"What does the recent pageview pattern look like for all Wikimedia projects?"
]
},
...(略)...
- title: 各 Search Target のタイトル名
- descriptions: 各 Search Target の概要説明
- target_action:
- url: 参照したい情報源へのURL(SQLで参照させたい場合は
sqlに変更) - target_inputs: urlに埋め込む動的な変数の定義
- url: 参照したい情報源へのURL(SQLで参照させたい場合は
- sample_queries: 各 Search Target に対する質問例
これらの情報はベクトル索引、およびテキスト索引が作られ、検索対象となります。
次に Target Value Set ですが、今回のサンプルデータでは以下のようになります。
[
{
"name": "frequency",
"description": "Time bucket options that control the resolution of the trends",
"values": [
{
"value": "monthly",
"synonyms": [
"month",
"by month",
"per month",
"monthly view"
]
},
{
"value": "daily",
"synonyms": [
"day",
"by day",
"per day",
"daily view"
]
}
],
"default_value": "monthly"
},
...(略)...
- name: 変数名
- descriptions: 変数の説明
- values:
- value: セットする値の候補
- synonyms: 質問文から値を抽出する際に使う同義語の候補
- default_value: 初期値
Search Target、Target Value Set のJSONファイルを管理アプリからインポートします。
Search Spaces 画面から今回新たに作った Search Space である Wikimedia を選択します。
右上の Import を選択し、Search Target と Target Value Set のJSONファイルをアップロードします。
最後に Import を押下して完了です。
恐らくですが、Importすると内部で Search Target に追加したデータに対するEmbedding処理が走っているように見えます。
というのも、2分ほどCPUの負荷が50%くらい上昇しました。
メモリについても、Embedding処理にあたりONNXモデルをメモリ上へロードするためか、同時期に使用量が10%くらい増加しました。
精度テスト
Trusted Answer Searchの管理アプリにはバッチ的に精度テストをする機能が備わっています。
バッチテストをするには事前にJSONファイルの作成が必要です。
今回のサンプルにもテスト用JSONファイルが用意されており、以下のように定義されています。
[
{
"test_query": "Show total page views for all Wikimedia projects by month over the last 2 years.",
"ground_truth": [
{
"search_target_title": "Total Page Views - All Projects",
"target_inputs": [
{
"period": "2-year"
},
{
"frequency": "monthly"
}
]
}
]
},
...(略)...
- test_query: テスト用に投げる質問文
- ground_truth:
- search_target_title: 最上位に来るべき Search Target のタイトル名
- target_inputs: 選択されるべき変数の値
作成したJSONファイルは管理アプリの Test Runs 画面にD&Dしてインポートできます。
スクロールして一番下にある Run Tests を押下するとテストが実行されます。
View Past Runs を押下するとテストの実行状態を確認できます。
Status が COMPLETED になったら、Run Id のリンクを選択して結果を確認できます。
それぞれの質問文ごとにどうだったかも分かります。
作成したSearch SpaceのPublish
テストして問題無さそうだ、となれば、Publishしてユーザが利用できる状態にします。
Search Spaces ⇒ 対象Search Space名のリンク とアクセスし、作業中バージョンの3点リードから Publish を選択します。
これで Search Space が公開されました。
ユーザ追加
Trusted Answer SearchのユーザはDBユーザと連動しています。
そのため利用ユーザを新規に追加する際は、まず対応するDBユーザを作成します。
CREATE USER tasuser IDENTIFIED BY <password>;
その後、管理アプリの Users ⇒ Add User と進み、DBユーザ名と付与する権限、追加先の Search Space を指定して Add を押下します。
追加されたユーザはPortalアプリにログインしてSearch Targetの情報を検索できるようになります。
使ってみる
Trusted Answer Searchの利用はPortal経由とAPI経由の2通りがあります。
Portal経由
追加したユーザでPortalにログインします。
以下クエリを投げてみます。
Show a country map of page views for English Wikiversity.
一番上にきている Page Views by Country Map を選択すると、紐づけられているURLが開きます。
以下の通り、英語のWikiversityへのアクセス数が国ごとにヒートマップで表示されました。
API経由
Trusted Answer Search用に追加した DBMS_TRUSTED_SEARCH PL/SQLパッケージの SEARCH ファンクションを使って検索できます。
Show total page views for all Wikimedia projects. という質問文を、以下のようにAPI経由で実行してみます。
set serveroutput on
DECLARE
l_result JSON;
l_text CLOB;
BEGIN
DBMS_TRUSTED_SEARCH.SEARCH(
p_user_query => 'Show total page views for all Wikimedia projects.',
p_search_space => 'wikimedia',
p_search_record => l_result
);
SELECT json_serialize(l_result RETURNING CLOB PRETTY)
INTO l_text
FROM dual;
DBMS_OUTPUT.put_line(l_text);
END;
/
すると以下の通りJSON形式で結果が返ってきます。
{
"version" : 1,
"id" : "d500f229-14f2-4e34-b64e-4d85082313b4",
"user_query" : "Show total page views for all Wikimedia projects.",
"search_matches" :
[
{
"rank" : 1,
"search_target_id" :
"04b37744-efbb-45d4-aa69-186cfbd4af66",
"search_target_title" : "Total
Page Views - All Projects",
"rewritten_user_query" : "total page views
wikimedia projects",
"match_candidate_type" : "SAMPLE_QUERY",
"rewritten_candidate" : "overall pageview totals Wikimedia projects.",
"original_candidate" : "Show overall pageview totals for all Wikimedia
projects.",
"score" : 0.03279,
"url" :
"https://stats.wikimedia.org/#/all-projects/reading/total-page-views/normal|bar|
:period|~total|:frequency",
"target_input_matches" :
{
"period" : "2-year",
"frequency" : "monthly"
}
},
{
"rank" : 2,
"search_target_id" : "166570dd-3f68-42cd-8a50-e64f97cdab75",
"search_target_title" : "Total Page Views",
"rewritten_user_query" :
"total page views wikimedia projects",
"match_candidate_type" :
"UPVOTED_QUERY",
"rewritten_candidate" : "total page views per language",
"original_candidate" : "total page views per language",
"score" :
0.03202,
"url" :
"https://stats.wikimedia.org/#/:language.:project.org/reading/total-page-views/n
ormal|bar|:period|~total|:frequency",
"target_input_matches" :
{
"language" : "en",
"project" : "wikipedia",
"period" :
"2-year",
"frequency" : "monthly"
}
},
...(略)...
あとは呼び出し元の別アプリ側でJSONを解析し、得られたURL等を活用します。
継続的な精度改善
Trusted Answer Searchは一度Publishして終わりではなく、継続的に精度を改善できるようになっています。
継続的な精度改善が求められるケースとしては以下2点が考えられます。
- バッチテストは良かったけど、実際にユーザが使ってみると欲しい情報が上位に来ていない
- 時間と共に検索対象のバリエーションが増えたり、社内用語などの専門語も増えていき、当初のSearch Space内の情報ではカバーし切れなくなる
まず1.については検索結果に対する投票機能が提供されています。
以下のように上位に来て欲しいものには upvote 、上位に来てほしくないものには downvote します。
次回の似たような質問文に対して投票結果が反映され、出現する Search Target の顔ぶれが変わります。
投票結果は管理アプリの Search History からも確認できます。
Query Textのリンクを選択すると、検索結果が一覧表示されます。
表示された結果に対して管理者からも投票フィードバックができます。
次に2.への対応ですが、こちらは以下のような対策が考えられます。
- Search Targetの追加
- 既存Search Targetの概要説明への追記
- Target Value Set内のSynonym追加
以上、Trusted Answer Searchの導入、利用の流れでした。
社内情報を検索する際はLLMを介さずとも、単純なセマンティック検索の結果を利用者が解釈する形で十分、というケースはあるかと思います。
そのような利用シーンにおいて、Trusted Answer Searchは体系立てた仕組みを手早く実装できる機能と言えるのではないでしょうか。
ちなみに本記事を作成した時点では、検索クエリに日本語など英語以外を使うと ORA-20000 エラーが発生します。
テキスト索引の方が英語のみに対応しているとか、そういった理由なのかなと思いますが、多言語対応に期待したいと思います。。























