Fessの文書レポートとインデックス統計でファイルを整理する

ファイルサーバーをクロールし続けると、重複した資料や長く更新されていない文書がたまってきます。Fessの管理画面に文書レポート、fess-kopfに文書インデックスの統計画面が追加され、整理対象を調べやすくなりました。

重複と休眠文書を調べる

Fessの「システム情報」>「文書レポート」で、重複と休眠文書のタブを切り替えます。smb://server/share/などのURL接頭辞で対象を絞り、CSVで取り出せます。管理ロールはadmin-docreport、閲覧専用はadmin-docreport-viewです。

fess_config.propertiesの初期値は次のとおりです。

docreport.duplicate.group.size=100
docreport.duplicate.docs.size=10
docreport.duplicate.export.page.size=10000
docreport.dormant.days=365

画面は最大100の重複グループ、各グループ10文書を表示します。重複判定には本文のMinHash署名content_minhash_bitsを使うので、完全一致だけでなく近い内容も含み得ます。ファイルのバイナリーが同一であることを保証する判定ではありません。トークンのない本文は誤った巨大グループになるため除外します。

通常のマッピングでは既存の署名を使い、署名のためだけの再インデックスは不要です。cloudやawsのマッピングでは署名を計算しないため、重複レポートを利用できません。大きなインデックスでは画面の集計が見落とす組み合わせもあり、全体確認にはページングで取得するCSVを使います。

休眠文書は初期値で365日以上更新されていない文書です。最終更新日時のない文書は含めません。「検索結果から一度も開かれていない」条件はクリック数が正でない文書を対象にします。画面のページングには結果ウィンドウの上限があるため、それを超える確認はCSVで行います。

インデックスの全体像を見る

fess-kopfのdocuments画面では、ファイル種別、MIMEタイプ、ホスト、ラベル、所有者、最終更新者の上位20件と、その他・値なしの件数を表示します。サイズ分布、更新年、インデックス登録年、最大サイズの10文書も確認できます。

fess.searchエイリアスがある環境で文書タブを表示します。インデックスのメニューから過去の世代を指定することもできます。画面を開くときと更新時に取得し、クラスターポーリングごとの集計は行いません。

数字の読み方と制限

createdは元ファイルの作成日ではなくFessへ登録した時刻です。ファイルの年齢を見るときはlast_modifiedを使います。年の集計は閲覧側のタイムゾーンに従い、サイズはバイナリー単位です。

古いインデックスのフィールド型によっては集計できない項目があります。利用可能な.keywordが全ての対象インデックスにある場合は代用し、それ以外は集計不能と表示します。fess-kopf側にはCSV出力と定期レポート機能はありません。

両画面とも調査のための読み取り機能です。重複や休眠というだけで不要と判断せず、原本や保管義務、実際の利用状況を確認してからファイル整理へつなげてください。

利用できるバージョン

Fess 15.9.0に含まれる予定の機能になります。現時点では、まだ、リリースしていないので、今後のテストで変更される可能性もあります。

関連PR

FessのStaticテーマでWebKitのプレビューが空になる場合の設定

FessのStaticテーマで、WebKit系ブラウザではPDFのプレビューやキャッシュ表示が空になる問題がありました。この対策として、テーマ画面が送るContent-Security-Policyのframe-ancestorsを設定できるようにしました。

プレビューが表示されない原因

テーマは取得したファイルやキャッシュをBlobにし、blob: URLのiframeで表示します。WebKitでは、この文書へ親ページのCSPが引き継がれ、frame-ancestors 'none'によって自分のページ内のフレームも拒否されます。ChromiumやFirefoxでは同じ表示が拒否されないため、ブラウザによって差が出ていました。

コンソールにframe-ancestorsに関するBlobの読み込み拒否が出る場合、今回の設定で対応できます。

設定方法

今回の変更を含むFessでは、fess_config.propertiesに以下を指定します。

theme.index.frame.ancestors=

空の値にすると、テーマのHTMLレスポンスからframe-ancestorsディレクティブを省略します。JVMオプションでは次の形です。

-Dfess.config.theme.index.frame.ancestors=

既存の起動オプションへ追加し、変更を反映して再起動します。docker-filesearchにはこの空値の指定を組み込む変更も追加しました。対応前のFessビルドではキーを指定してもプレビュー対策としては機能しません。

デフォルトとフレーム埋め込み制限

デフォルトは従来と同じ'none'です。アップグレードしただけではWebKit向けの挙動は変わりません。

空値でも、同じレスポンスのX-Frame-Options: DENYは維持します。PRのブラウザ検証では、同一オリジン・別オリジンからのページ埋め込みをともに拒否しつつ、Blobのプレビューを表示できることを確認しています。

'self'を指定した場合は意味が異なります。CSPを優先するブラウザでは同一オリジンからの埋め込みを許可するため、プレビュー対策として空値と同じ扱いにはしないでください。

検証範囲

変更の確認はPlaywrightのChromium、Firefox、WebKitで行われています。実機Safariでの検証は含まれません。また、ヘッドレスWebKitではPDFの画面描画そのものを比較できず、PDF文書がフレームに読み込まれることと拒否の解消までを確認しています。

キャッシュ中のbase要素について出る別のCSP警告は、今回の変更の対象外です。表示できない原因がこの設定に該当するか、コンソールのメッセージを確認して適用してください。

関連PR

DockerのFessファイル検索で多言語ハイブリッド検索を試す

docker-filesearchで、Fess 15.9のキーワード検索とベクトル検索を組み合わせたハイブリッド検索を利用するようにしました。日本語の資料を英語で質問するなど、同じ単語を含まない検索でも関連する文書を探すためのデモ環境です。

検索エンジン側で順位を統合する

BM25によるキーワード検索と、多言語埋め込みモデルによるベクトル検索を1つのOpenSearchのhybridリクエストで実行します。順位はReciprocal Rank Fusionで統合します。テーマは従来どおり/api/v2/searchを利用するため、検索画面側で2つの結果を組み合わせる必要はありません。

埋め込みにはparaphrase-multilingual-MiniLM-L12-v2を使い、ベクトル次元数は384です。起動時のinit-semanticサービスがモデルを登録・デプロイし、生成されたモデルIDをFessへ渡します。クロール後にContent Chunk Vector Indexerを動かして文書のチャンクとベクトルを作成します。

デモ環境を起動する

docker-filesearchの作業ディレクトリで、READMEに沿って以下を実行します。

bash ./bin/setup.sh
docker compose up -d
bash ./bin/configure.sh

Docker Compose v2に加え、モデルを動かすためにおおむね8GBの空きメモリーを用意します。初回は約490MBのモデルなどをダウンロードするためネットワーク接続が必要です。初回の設定処理はサンプル環境で約9〜16分という測定があり、実際の時間はマシンに依存します。

キーワード検索はクロール完了後に使えますが、ベクトル検索へ反映するにはインデクサーの完了を待つ必要があります。

調整する項目

.envでは次の値を調整できます。

MODEL_DIMENSION=384
CHUNK_SIZE=500
SEMANTIC_MIN_SCORE=0.35
OPENSEARCH_HEAP=2g

チャンクを小さくすると細かな内容を拾いやすくなる一方、生成するベクトルと処理時間が増えます。類似度の下限を上げると関連の薄い結果を減らせますが、探したい言い換えも落とす場合があります。0.35はサンプルデータで選んだ値なので、実データでも最適とは限りません。

content_chunker.*はFessのシステムプロパティとして渡します。fess_config.properties用の設定と経路が異なる点にも注意してください。

検索と更新の注意点

すべての検索がハイブリッドになるわけではありません。明示的なソート、複数語の引用フレーズ、ワイルドカード、除外などではキーワード検索になる条件があります。まず通常の関連度順のクエリで比較すると動作を把握しやすくなります。

旧デモの768次元インデックスへ384次元のモデルをそのまま使うことはできません。モデル、次元、チャンクサイズを変更する場合は、新しいインデックスを用意する前提でREADMEの再構築手順を確認してください。

あわせて、同時セグメント検索による部分的な検索結果を避けるデモ設定と、ベクトル書き込みの競合を同じ実行中に再試行するFessの修正も入りました。再試行は本文と処理状態が同じ場合だけ既存のベクトルを再利用し、競合が続く文書は次回へ残します。ジョブの完了状態だけでなく、処理結果の件数も確認するとよいと思います。

関連PR