FioneのSDK・JupyterLab連携案でノートブックから学習する

FioneのPython刷新案に、Pythonクライアントのfione-sdkと、画面内でJupyterLabを開く仕組みが追加されています。CSVの加工や可視化をノートブックで行い、そのままFioneのデータセット、学習ジョブ、モデルを扱うための提案です。

初期値では無効。使う人にだけ許可する

FIONE_NOTEBOOK_URLは初期値で未設定です。設定しない間はNotebookのリンクや機能は有効にならず、Composeのnotebookプロファイルも通常は起動しません。

有効にすると、ユーザーごとに1個のJupyterLabコンテナを起動します。管理者は利用でき、それ以外のユーザーには管理画面の「ユーザー」でNotebookの許可を与えます。閲覧者でもPythonコードを実行できるため、単なる画面の閲覧権限とは区別して判断します。

Notebook内のSDKは専用の期限付きAPIトークンを使います。管理者でもAPI上は最大で編集者相当となり、アカウント・トークン管理、モジュールのアップロード、モデルのインポート、共有設定などには使えません。閲覧者のトークンは読み取り専用です。

PRのコードを専用環境で試す

Docker、Compose v2、Git、OpenSSLを用意し、正式版の環境とは別の作業コピーでPRを取得します。

git clone https://github.com/codelibs/fione.git fione-notebook-review
cd fione-notebook-review
git fetch origin pull/15/head
git switch --detach FETCH_HEAD
cp docker/.env.example docker/.env

docker/.envのFIONE_S3_ACCESS_KEYとFIONE_S3_SECRET_KEYにそれぞれ生成した値を設定します。例としてopenssl rand -hex 16、openssl rand -hex 32が使えます。続けて次の項目を設定し、秘密値はGitへ登録しません。

FIONE_PUBLIC_URL=http://127.0.0.1:8080
FIONE_NOTEBOOK_URL=http://127.0.0.1:8888
FIONE_NOTEBOOK_LAUNCHER_SECRET=openssl rand -hex 32で生成した値

Launcherとの共有秘密は32文字以上が必要です。ComposeはFIONE_NOTEBOOK_LAUNCHER_URL=http://notebook-launcher:8000を内部用に設定します。Compose外ではこのURLも指定する必要があります。

docker compose -f docker/compose.yaml --env-file docker/.env --profile notebook build
docker compose -f docker/compose.yaml --env-file docker/.env --profile notebook up -d
docker compose -f docker/compose.yaml --env-file docker/.env logs fione

初回はログのSetup tokenから管理者を作成します。Notebookのイメージもローカルでビルドする手順で、Launcherが不足するイメージを自動取得するわけではありません。Notebook用イメージだけで約950MBというarm64での測定値があります。以後のbuild・up・downでも--profile notebookを付けます。

ブラウザーではhttp://127.0.0.1:8080を開き、「ノートブック」から起動します。新しいPython 3 Notebookで次のように利用します。

from fione_sdk import Client

fione = Client()
print(fione.projects())

埋め込み環境ではFIONE_URLとFIONE_TOKENが設定済みです。手元のJupyterやスクリプトでも、PRの作業コピーでpip install ./sdkを行い、この2つを設定すれば利用できます。外部用にアカウント画面で発行した通常のトークンは、Notebook用と違って明示的に無効化するまで期限切れになりません。

URLとリバースプロキシの条件

2つのURLはパスを持たないオリジンとして指定し、同じサイト内の異なるオリジンにします。ローカルでは同じホスト名でポートを分けます。localhostと127.0.0.1を混在させるとログインできません。ゲートウェイのホスト側ポートの初期値は127.0.0.1:8888です。

HTTPS環境では、FioneとNotebookに同じ登録可能ドメイン内の別ホスト名を用意します。プロキシはHostとWebSocket接続を保ち、Notebook画面のReferrer-Policy: originを上書きしない構成が必要です。Refererを削除するブラウザー設定や拡張機能でも、埋め込み先のログインが403になります。

実行上限と、停止後に残るもの

同時Notebook数は全利用者の合計でFIONE_NOTEBOOK_MAX_RUNNING=4、最大寿命はFIONE_NOTEBOOK_MAX_LIFETIME_SECS=43200秒、つまり12時間が初期値です。寿命は600〜604800秒の範囲で設定できます。1コンテナは2 CPU、4GiBメモリー、512プロセスが上限です。

内部ネットワークのためインターネットからのpip installはできず、イメージに含まれるライブラリを使います。ただし、Dockerホストの全インターフェースで待ち受けるサービスへの到達や、他NotebookコンテナへのTCP接続まですべて遮断する構成ではありません。Launcherはホスト上で強い権限を持つDockerソケットを扱い、全ユーザーのJupyterLabは1つのブラウザーオリジンを共有します。この前提を評価した検証環境で試してください。

停止するとコンテナと専用トークンを破棄しますが、保存済みNotebookとファイルのユーザー別ボリュームは残ります。実行中のカーネルは残らず、JupyterLabのレイアウトや設定も永続化されません。ディスク容量の上限は設定されていないので、ホストの空き容量を監視します。

アイドル時の自動停止もありますが、Notebookを開いたタブがカーネルを維持すると寿命まで枠を使う場合があります。使い終わったら画面から停止する運用が確実です。権限取り消しなどでトークンは無効になりますが、Launcherに届かない場合はコンテナ停止が保留され、すでにログインした画面が一時的に使えることがあります。

docker compose down -vでもNotebook用ボリュームは残ります。一方でFioneのデータベースを初期化するとユーザーIDを再利用するため、新しいユーザーへ古いファイルを渡さないよう、再作成前に残存ボリュームを確認する必要があります。

関連PR

Fess CrawlerのHttpClient 5でSOCKS5プロキシを設定する

Fess CrawlerのHTTPクライアントに、SOCKS5プロキシを指定する機能が追加されました。対象はHc5HttpClientです。

ホストとポートを両方指定する

初期状態ではsocksProxyHostもsocksProxyPortも未設定で、SOCKSプロキシを使いません。両方を設定した場合だけ、接続マネージャーにSOCKSプロキシを渡します。ポートだけの指定では有効にならず、1080などが自動補完されるわけでもありません。

Hc5HttpClientを直接生成・設定するJavaアプリケーションでは、初期化前に次のように指定します。1080は例で、実際のプロキシの待受ポートへ変更します。

Hc5HttpClient client = new Hc5HttpClient();
client.setSocksProxyHost("proxy.internal.example");
client.setSocksProxyPort(1080);
// この後、アプリケーション側の通常の初期化・実行処理を行う

初期化パラメーターマップを使う場合のキーもsocksProxyHostとsocksProxyPortです。HTTPプロキシのproxyHost・proxyPortとは別の指定です。Fess管理画面にSOCKS専用入力欄を追加するPRではないため、画面にこの名前を入力すればそのまま使えるとは判断しません。Fessへ組み込む場合は、実際にHc5HttpClientが選ばれ、パラメーターが渡る構成かを確認します。

認証と名前解決の制限

SOCKS認証には対応していません。また、宛先ホスト名はクローラー側で解決し、プロキシへはIPアドレスを渡します。プロキシ側だけが社内ホスト名を解決できる構成や、リモートDNSを前提とする接続では、この設定だけでは届きません。

Hc4HttpClientの動作は変わりません。導入時は小さなHTTP取得でプロキシを通ること、SOCKSを未設定に戻した場合の経路、クローラー環境からのDNS解決を確認します。PRでは組み込みSOCKS5サーバーを使った中継テストが報告されていますが、本記事では実環境のFessクロールを検証したとはしていません。

関連PR

Fessのファイルクロールで親へ戻るシンボリックリンクを避ける

ファイルクロールで、同じファイルが長いパスを伴って何度も登録されることがあります。sub/up -> ..のように、子ディレクトリのシンボリックリンクが親へ戻る場合の巡回を避ける修正が、Fess Crawlerへマージされました。

file:のパスが長くなり続ける場合

従来はfile:でディレクトリを一覧すると、リンク経由で同じ木構造へ戻り、sub/up/a.txt、sub/up/sub/up/a.txtのように別URLとして取得を繰り返す場合がありました。深さの上限で止まっても、同じ内容が多数登録されます。

修正では子要素が「ディレクトリへのシンボリックリンク」であるとき、実パスを確認します。現在のディレクトリ自身や実際の親へ戻るリンク、URL上で既に通過したディレクトリへ戻るリンクを、次の取得対象から除外します。a/x -> bとb/y -> aのような相互リンクも対象です。

シンボリックリンクをすべて禁止する変更ではない

FileSystemClientのfollowSymlinkは初期値trueで、既存の指定方法は変わりません。新しい設定項目もありません。通常ファイル、別の場所を指すリンク、壊れたリンクの一覧処理は従来の扱いを維持します。

followSymlink=falseは従来どおりリンクをたどらないための指定ですが、今回の修正は、リンクを利用する構成で特定の循環を除外するものです。このプロパティはCrawlerの初期化パラメーターで、同じ名前のFess全体プロパティが新設されたわけではありません。SMBなど別クライアントの動作を一律に変えるものでもありません。

既存の重複は別途確認する

修正はこれから列挙するURLを抑えます。既にインデックスへ登録された重複文書を自動で削除する機能ではありません。

対象ディレクトリのリンク先を確認し、修正入りのCrawlerを含む環境で小さな範囲を再クロールします。ログのSkipped a symbolic link that leads back to a parent directoryと、繰り返しパスが増えなくなったことを確認してから、古い文書の整理を検討します。実パスの解決に失敗した場合もあるため、深さや対象範囲の既存の制限も引き続き必要です。

関連PR