テンプレート処理中にエラーが発生しました。
Java method "com.liferay.portal.json.JSONFactoryImpl.createJSONObject(String)" threw an exception when invoked on com.liferay.portal.json.JSONFactoryImpl object "com.liferay.portal.json.JSONFactoryImpl@2ad66ae2"; see cause exception in the Java stack trace.

----
FTL stack trace ("~" means nesting-related):
	- Failed at: navigationJSONObject = jsonFactoryUti...  [in template "17855804202317#32484267#LEARN-ARTICLE-NAV" at line 4, column 9]
----
1<#assign 
2	groupFriendlyURL = themeDisplay.getScopeGroup().getFriendlyURL() 
3	groupPathFriendlyURLPublic = themeDisplay.getPathFriendlyURLPublic() + groupFriendlyURL 
4	navigationJSONObject = jsonFactoryUtil.createJSONObject(navigation.getData()) 
5	navigationMenuItems = 
6
7			"Analytics Cloud": { 
8				"image": "/documents/d${groupFriendlyURL}/analytics_c-svg", 
9				"title": "Analytics Cloud", 
10				"url": "analytics-cloud" 
11			}, 
12			"Commerce": { 
13				"image": "/documents/d${groupFriendlyURL}/commerce_product-svg", 
14				"title": "Commerce", 
15				"url": "commerce" 
16			}, 
17			"DXP": { 
18				"image": "/documents/d${groupFriendlyURL}/dxp_p-svg", 
19				"title": "DXP / Portal", 
20				"url": "dxp" 
21			}, 
22			"Liferay Cloud": { 
23				"image": "/documents/d${groupFriendlyURL}/dxp_c-svg", 
24				"title": "Liferay Cloud", 
25				"url": "liferay-cloud" 
26			}, 
27			"Reference": { 
28				"image": "/documents/d${groupFriendlyURL}/reference-svg", 
29				"title": "Reference", 
30				"url": "reference" 
31
32
33 
34	breadcrumbJSONArray = navigationJSONObject.getJSONArray("breadcrumb") 
35	childrenJSONArray = navigationJSONObject.getJSONArray("children") 
36	parentJSONObject = navigationJSONObject.getJSONObject("parent") 
37	productJSONObject = breadcrumbJSONArray.getJSONObject(breadcrumbJSONArray.length()-1)!navigationJSONObject.getJSONObject("self") 
38	siblingsJSONArray = navigationJSONObject.getJSONArray("siblings") 
39/> 
40 
41<div class="learn-article-nav"> 
42	<#if productJSONObject?has_content && productJSONObject.getString("title")?has_content && navigationMenuItems[productJSONObject.getString("title")]?has_content && navigationMenuItems[productJSONObject.getString("title")].title?has_content> 
43		<div 
44			class="dropdown learn-article-nav-root learn-dropdown" 
45
46			<div class="learn-article-nav-item"> 
47				<div class="d-flex"> 
48					<div class="learn-article-nav-image"> 
49						<img 
50							class="lexicon-icon lexicon-icon-caret-bottom product-icon" 
51							role="presentation" 
52							src='${navigationMenuItems[productJSONObject.getString("title")].image}' 
53							viewBox="0 0 512 512" 
54						/> 
55					</div> 
56 
57					<span class="learn-article-nav-text">${navigationMenuItems[productJSONObject.getString("title")].title}</span> 
58				</div> 
59 
60				<div id="dropdown-icon"> 
61					<svg 
62						class="lexicon-icon lexicon-icon-caret-bottom" 
63						role="presentation" 
64						viewBox="0 0 512 512" 
65
66						<use xlink:href="/o/admin-theme/images/clay/icons.svg#caret-bottom"></use> 
67					</svg> 
68				</div> 
69			</div> 
70 
71			<ul class="dropdown-menu learn-dropdown-menu"> 
72				<#list navigationMenuItems as key, value> 
73					<li> 
74						<a 
75							class="dropdown-item learn-article-nav-item" 
76							href="/w/${navigationMenuItems[key].url}/index" 
77							tabindex="4" 
78
79							<span class="d-flex"> 
80								<span class="learn-article-nav-image"> 
81									<img 
82										class="lexicon-icon lexicon-icon-caret-bottom product-icon mt-0 mr-2" 
83										role="presentation" 
84										src="${value.image}"height: 25px; margin-left: 5px; max-width: none; width: 25px; 
85										viewBox="0 0 512 512" 
86									/> 
87								</span> 
88								<span class="learn-article-nav-text">${value.title}</span> 
89							</span> 
90 
91							<#if navigationMenuItems[productJSONObject.getString("title")].url == value.url> 
92								<span> 
93									<@clay["icon"] symbol="check" /> 
94								</span> 
95							</#if> 
96						</a> 
97					</li> 
98				</#list> 
99			</ul> 
100		</div> 
101	</#if> 
102 
103	<div class="learn-article-nav-content"> 
104		<#if parentJSONObject?has_content && parentJSONObject.getString("url")?has_content> 
105			<div class="learn-article-nav-item learn-article-nav-parent liferay-nav-item p-2"> 
106				<div class="mr-2"> 
107					<a 
108						href='${parentJSONObject.getString("url")}' 
109
110						<svg 
111							class="lexicon-icon lexicon-icon-angle-left" 
112							role="presentation" 
113							viewBox="0 0 512 512" 
114
115							<use xlink:href="/o/admin-theme/images/clay/icons.svg#angle-left"></use> 
116						</svg> 
117					</a> 
118				</div> 
119 
120				<span>${parentJSONObject.getString("title")}</span> 
121			</div> 
122		</#if> 
123 
124		<#if childrenJSONArray.length() gt 0> 
125			<ul class="m-0 p-2"> 
126				<#list 0..childrenJSONArray.length()-1 as i> 
127					<li class="learn-article-nav-item"> 
128						<a 
129							class='liferay-nav-item ${(navigationJSONObject.getJSONObject("self").url == childrenJSONArray.getJSONObject(i).url)?then("selected", "")}' 
130							href="${childrenJSONArray.getJSONObject(i).url}" 
131
132							<span>${childrenJSONArray.getJSONObject(i).getString("title")}</span> 
133						</a> 
134					</li> 
135				</#list> 
136			</ul> 
137		<#elseif siblingsJSONArray.length() gt 0> 
138			<ul class="m-0 p-2"> 
139				<#list 0..siblingsJSONArray.length()-1 as i> 
140					<li class="learn-article-nav-item"> 
141						<a 
142							class='liferay-nav-item ${(navigationJSONObject.getJSONObject("self").url == siblingsJSONArray.getJSONObject(i).url)?then("selected", "")}' 
143							href="${siblingsJSONArray.getJSONObject(i).url}" 
144
145							<span>${siblingsJSONArray.getJSONObject(i).getString("title")}</span> 
146						</a> 
147					</li> 
148				</#list> 
149			</ul> 
150		</#if> 
151	</div> 
152</div> 

セマンティック検索

7.4 U70+ ベータ版特集

セマンティック検索は、検索されたフレーズの背後にある意図を評価する。 一方、 keyword 検索は、検索されたフレーズをインデックスされたテキストフィールドにマッチさせるもので、意味に基づいてマッチさせることはできない。

検索フレーズインデックス・コンテンツマッチタイプ
テクノロジー最新情報Liferayが7.3の検索エクスペリエンスをリリースセマンティック ✔
キーワード ✘
ニューリリースLiferay Search Experiencesに新機能リリースセマンティック ✔
キーワード ✔

Liferayのような(Elasticsearchを使った)洗練されたキーワード検索でさえ、以下のような独創的なテクニックを使っても、インデックス化された文書とユーザーの意図を一致させることはできない。

  • 解析でキーワードと文書フィールドをトークン化する。
  • 不正確なマッチングを可能にするために、ファジーさとスロッピングがある。
  • 同義語のマッチングを可能にするために、単語を語根に分解するステミング。
  • 些細な言葉を無視するために、言葉を止める。

トークン化されたキーワードと文書フィールドによる検索は、多くの検索ニーズにとって十分である。 検索エクスペリエンスにさらなるものを求めるのであれば、セマンティック検索は、キーワード検索が達成できることと、ユーザーが検索に本当に求めていることとのギャップを大きく縮めます。

Natural language search phrases are processed by semantic search systems.

セマンティック検索は、追加のコンテンツ処理パイプラインを可能にする。 有効にすると、プラットフォームはテキスト埋め込みと呼ばれる入力テキストのベクトル表現を生成し、Elasticsearchのインデックスドキュメントに格納する。 検索時には、ユーザーによって入力された検索キーワードは、同じベクトル化と埋め込みプロセスを経て、ユーザーにとってより意味のある関連検索結果を提供する類似検索を行うことが可能になる。 すべてのコンテンツタイプがテキスト埋め込みをサポートしているわけではありません:

対応コンテンツ・タイプデフォルト設定で有効?
ブログのエントリ
ナレッジベースの記事
掲示板のメッセージ
ウェブコンテンツの基本記事
Wikiページ
important

効果的なセマンティック検索ソリューションには、データ・ドメイン用にトレーニングされたモデルが必要です。 最も簡単なアプローチは、適切な訓練済みモデルを見つけ、それをデータに合わせて微調整することだ。 ここで示した例は、本番用のセマンティック検索ソリューションではない。

セマンティック検索を可能にする

Liferay でセマンティック検索を有効にする、

  1. グローバルメニュー( グローバルメニュー )を開き、 コントロールパネルインスタンス設定 をクリックします。
  2. PlatformFeature Flags セクションを開く。
  3. ベータの項目で、セマンティック検索を有効にする。

Semantic search is a beta feature and must be enabled in Instance Settings.

ポータル・プロパティ を使ってセマンティック検索を有効にするには、portal-ext.properties にこれを追加してください:

feature.flag.LPS-122920=true

環境変数 を使ってセマンティック検索を有効にするには、設定に次のように追加します:

LIFERAY_FEATURE_PERIOD_FLAG_PERIOD__UPPERCASEL__UPPERCASEP__UPPERCASES__MINUS__NUMBER1__NUMBER2__NUMBER2__NUMBER9__NUMBER2__NUMBER0_=true

セマンティック検索を設定するには

  1. モデルを選ぶか、自分で作る。
  2. テキスト埋め込みプロバイダーを有効にし、Liferayで設定します。
  3. テキスト埋め込みにインデックスを付ける。
  4. ベクトル化された検索語と文書間の類似性検索を実行する検索ブループリントを作成する。

モデルの選択

適切に訓練されたモデル が最も重要である:インデックスのデータは、選択したモデルに適切でなければならない。 事前に訓練されたモデルで作業するのは便利だが、本番で使用する前にデータに合わせて微調整する必要があるかもしれない。 ロバスト・テストによってのみ、選択したモデルが適切であることを知ることができる。

例えば、ユーザーが「スケートはどのように動くのか」と検索した場合、海洋生物学について訓練されたモデルと、レクリエーションについて訓練されたモデルでは、結果が異なるだろう。

Hugging Face モデルハブ は、事前に訓練された、ドメイン固有のモデルの大規模なコレクションを提供します。

テキスト埋め込みにインデックスを付ける

テキスト埋め込みは、以下の場合にインデックス化されなければならない。

  1. 初めてセマンティック検索が可能に。
  2. セマンティック検索の設定で、テキスト埋め込みプロバイダー、モデル、ベクトル次元、テキスト切り捨て戦略を変更する。

テキスト埋め込みにインデックスを付けるには、「インデックスアクション」画面を使用し、セマンティック検索システムまたはインスタンス設定の「アセットエントリクラス名」設定で有効にしているモデルタイプだけに Reindex ボタンをクリックします。

セマンティック検索の設定

テキスト埋め込みプロバイダーの設定 以外にも、セマンティック検索のための追加設定オプションが用意されている。 コントロールパネル → インスタンス設定 → セマンティック検索をご覧ください。

テキスト埋め込みプロバイダの設定については、 セマンティック検索を有効にする で説明しています。

インデックスの設定には以下のものがある:

Max Character Count: テキスト埋め込みプロバイダーに送信する最大文字数を設定します。デフォルトでは、最大500文字がベクトル表現に変換されるために送信されます。ここでの理想的な値は、使用しているテキスト埋め込みプロバイダに依存します。

テキスト切り捨て戦略: テキストの先頭(デフォルト)、中間、または末尾のいずれから変換前のサンプルを抽出するかを選択します。 この設定は、ソース・テキストが最大文字数より長い場合にのみ適用されます。 ストラテジーと最大文字数に応じて、タイトル/件名とコンテンツ/本文の一部をテキスト埋め込みに使用することができます。

Types: 変換するコンテンツタイプを選択します。デフォルトでは、Blogs Entry、Knowledge Base Article、Web Content Article、Wiki Page の 4 つのタイプが処理されます。掲示板 必要に応じて、メッセージエンティティを設定できます。

note

現在、基本的なウェブコンテンツ記事のみがサポートされています。

言語: 変換する言語とローカライズを選択します。 デフォルトでは、リストされたすべての言語が選択されています。 リストから複数の言語を選択するには、 Ctrl + クリックします

warning

言語を有効にしても、その言語用の文埋め込みが作成される保証はありません。 サイト内で使用可能な言語でなければならない。 システム/インスタンス設定で言語が有効になっており、サイト内で利用可能であるにもかかわらず、指定されたコンテンツに翻訳がない場合、デフォルトの翻訳がテキスト埋め込みを作成するために使用されます。

テキスト埋め込みキャッシュタイムアウト: 変換された検索キーワードのキャッシュタイムアウトをミリ秒単位で設定します。 キャッシュがタイムアウト内にある場合、Liferayはテキスト埋め込みプロバイダからキーワードのテキスト埋め込みを要求しません。 デフォルトでは、タイムアウトは604800ミリ秒(約10分)である。

Liferayのセマンティック検索を理解する

Liferayのセマンティック検索は

  1. 完全なセマンティック検索では、通常のインデクサーは検索ブループリントで無効にされ、テキスト埋め込みのみが関連するコンテンツを検索するために使用されます。

  2. ハイブリッド・セマンティック検索では、まずキーワード検索が実行され、テキスト埋め込みが結果の再スコアに使用される。

セマンティック検索とその複雑さをしっかりと理解することは、この簡単な説明の範囲を超えている。 ここでは、Liferayハイブリッドセマンティックサーチの実装がどのように機能するのか、セマンティックサーチの基本的な概念をいくつか説明します。

セマンティック検索はインデックス時と検索時の両方でLiferayの検索に影響を与え、追加レベルのコンテンツ処理を導入します。

インデックス作成段階でのセマンティック検索

  • まず、通常のコンテンツ処理が行われる:
    • [LIFERAY] Liferayのコンテンツは検索エンジンに送られ、そこでデータ型に従って処理されます:テキストは適切に分析され、インデックスに保存されます。
  • [LIFERAY] 追加の意味検索処理が行われる:
    • System/Instance Settingsの設定に従って、テキストスニペットがLiferayからテキスト埋め込みプロバイダに送信されます。
      • 最大文字数とテキスト切り捨て戦略は、テキスト埋め込みプロバイダーに送信されるスニペットを決定します。
      • LiferayはBlogs Entries、Knowledge Base Articles、Wiki Pages、Basic Web Content Articlesのタイトルとコンテンツを選択します。 メッセージ・ボードのメッセージでは、件名と本文のフィールドが処理されます。
  • [TEXT EMBEDDING PROVIDER] まず最初に、設定されたモデルに従ってスニペットが処理され、パラメータに従ってスニペットをトークン化する。 よく使用される BERT モデルでは、512 がモデルが扱うトークンの最大数である。 これは、システム/インスタンス設定のセマンティック検索 → 最大文字数設定で設定された文字数に影響されます。
  • [TEXT EMBEDDING PROVIDER] テキスト埋め込みと呼ばれるソースのベクトル表現は、変換器が使用するモデルに基づいて作成されます。
    • [LIFERAY]を参照してください。テキスト埋め込み処理の結果は、 Liferay Company Index 、各ドキュメント1dense_vector ]フィールドとして保存されます。
    • System/Instance Settingsの設定に従って、テキストスニペットがテキスト埋め込みプロバイダに送られ、テキスト埋め込みが行われ、トランスフォーマが使用するモデルに基づいてベクトル表現が作成される。 テキスト埋め込み処理の結果は、 Liferay Company Index に、 dense_vector フィールドとしてドキュメントごとに格納されます1

検索段階での意味検索

  • 通常のキーワードマッチングが行われる:
    • 検索バーウィジェットに入力された検索フレーズは、Liferayの検索フレームワークによって受信され、分析と追加処理のために検索エンジンに送られ、検索エンジン内の既存のインデックス文書とマッチングされ、関連性がスコアリングされ、追加処理(ハイライト、要約、許可のための追加フィルタリングの実行など)のためにLiferayに返されます。
  • 追加の意味検索処理が行われる:
    • 検索フレーズはテキスト埋め込みプロバイダーに送られ、ベクトル表現が作成される( テキスト埋め込み )。 キーワード検索の関連性によってスコアリングされた検索結果をレンダリングする前に、ウィンドウの制限設定内でキャプチャされた結果は、検索フレーズのベクトル表現をインデックス文書のベクトル表現と比較することによって再スコアリングされる。 新たなスコアが計算され、その結果が検索ページに返される。 詳しくはElasticの ベクターサーチとは をご覧ください。

  1. ドキュメント内のフィールドを検査するには、 Display Results in Document Form 設定、または Search Blueprints preview 機能を使用します。