Skip to content

Pontus-X 向けのカスタムアルゴリズムを作る

Pontus-X の Compute-to-Data(CtD)機能で使うアルゴリズムの書き方を解説します。Compute-to-Data は、非公開データを外部にさらすことなくアルゴリズムをその上で実行できるようにすることで、データのプライバシーとセキュリティを保ちながらデータ共有を可能にします。

本ガイドでは、CtD におけるアルゴリズムの作成と設定を、コードの構成、Docker イメージの利用、ストレージの扱い、環境変数の設定、実行の準備まで順に扱います。読み終えるころには、CtD でアルゴリズムを公開し実行するために必要な構成要素と実践的な手順を理解できます。

Compute-to-Data アルゴリズムの主要な構成要素

Pontus-X のスタックでは、アルゴリズムはデータセットと並ぶ独立したアセット種別として扱われます。Compute-to-Data のアルゴリズムは、次の主要な構成要素からなります。

1. アルゴリズムのコード

アルゴリズムのコードは、データセット上で実行される計算手順を定義する具体的な命令とロジックの集合です。アルゴリズムの機能、計算、変換処理が含まれます。

これらの指針に従うことで、Pontus-X の CtD の枠組みの中で、アルゴリズムの Docker コンテナに対するアクセスと権限を安全に管理できます。


2. Docker イメージ

Docker イメージは、アルゴリズムのコードとその実行時依存関係をまとめたものです。次の要素からなります。

  • ベースイメージ:アルゴリズムの土台となる環境を提供します。
  • タグ:イメージの特定のバージョンを識別します。

よく使われるのは Docker Hub の python:3.15node:24 などですが、アルゴリズムに固有の依存関係がある場合は、独自の Docker イメージを作成できます。

2.1 独自の Docker イメージを作る

アルゴリズムが特定の依存関係を必要とする場合は、Dockerfile を作成します。

# Dockerfile の例
FROM python:3.15
RUN pip install requests pandas
COPY algorithm.py /algorithm.py
ENTRYPOINT ["python3", "/algorithm.py"]

Docker イメージを公開します。

  1. イメージをビルドする:docker build -t your-image-name .
  2. Docker Hub へプッシュする:docker push your-dockerhub-username/your-image-name

3. エントリーポイント

エントリーポイントは、コンピュート環境内でアルゴリズムの実行を開始するコマンドです。アルゴリズムを公開する際、Pontus-X ポータルの公開手順の中で直接エントリーポイントを設定します。これは Dockerfile で定義されたエントリーポイントを上書きします。

  • python3 $ALGO

エントリーポイントの一部として $ALGO を指定すれば、コンピュート環境が正しいアルゴリズムで起動することが保証され、設定作業がより柔軟で確実になります。

3.1 独自のエントリーポイントを使う

コンテナ内の特定の場所にアルゴリズムのコードを直接含めている場合は、公開手順で /app/script.py のようなコンテナ内の任意のパスをエントリーポイントとして指定することもできます。

公開手順でエントリーポイントを設定することで、公開時に指定したロジックと設定でアルゴリズムの実行が始まり、機微な情報が意図せず露出することもなく、安全に運用できます。

4. 環境の設定

アルゴリズムを公開する際、Docker 環境の設定は Pontus-X ポータルから直接指定できます。公開手順の中で、次のことが行えます。

  1. Docker イメージを選ぶ:あらかじめ用意された選択肢(python:latestnode:latest など)から選ぶか、固有の依存関係が必要な場合は独自の Docker イメージの URL を指定します。

  2. エントリーポイントを指定する:コンテナ内でアルゴリズムの実行を開始するエントリーポイントを定義します。ここで設定したエントリーポイントは、Dockerfile で指定したものを上書きします。

  3. カスタムパラメータを設定する(任意)
    この手順は任意です。アルゴリズムがカスタムパラメータを必要とする場合にのみ使用してください。
    コンテナ内でのアルゴリズムの挙動を設定するパラメータを定義できます。これらのパラメータは、アルゴリズムから参照できる JSON ファイルに保存されます。

4.1 アルゴリズムからカスタムパラメータを参照する(任意)

この手順は任意で、アルゴリズムがカスタムパラメータを使うよう設定されている場合にのみ該当します。

アルゴリズムは /data/inputs/algoCustomData.json に置かれた JSON ファイルを参照できます。このファイルには、公開手順で指定した入力データのキーと値の組が含まれます。これにより、利用者が定義した入力に応じて、アルゴリズムの挙動を動的に変えられます。

algoCustomData.json の内容の例:

{
    "hometown": "São Paulo",
    "age": 10,
    "developer": true,
    "languagePreference": "nodejs",
    "threshold": 25
}
 

公開手順でこれらの項目を設定することで、アルゴリズムのコンテナに必要な環境、カスタムパラメータへの安全なアクセス、入力検証が正しく整います。

4.2 Compute-to-Data で利用できる環境変数

各アルゴリズムの Pod では、データセットや CtD 環境とやり取りするために次の環境変数が利用できます。

  • DIDS:入力データセットの識別子(DID)を並べた JSON 配列。
    • ENV DIDS='["87bdaabb33354d2eb014af5091c604fb4b0f67dc6cca4d18a96547bffdc27bcf"]'
  • TRANSFORMATION_DID:アルゴリズムの DID。適用される変換処理を識別します。

これらの変数は、アルゴリズムのコードからプログラム的に参照できます。

  • PythonDIDS = json.loads(os.getenv("DIDS"))
  • Node.jsconst DIDS = JSON.parse(process.env.DIDS);

5. コンピュート Pod でのデータ保存

計算ジョブ内の各アルゴリズムは Kubernetes(K8s)の Pod 内で実行され、データ保存用に特定のボリュームがマウントされます。

  • /data/inputs:アルゴリズムがアクセスする入力データセット。データセット ID ごとに整理されています。
  • /data/ddos:データセットとアルゴリズムのメタデータ(DDO の JSON 形式)。
  • /data/outputs:アルゴリズムが生成したすべての出力ファイル。
  • /data/logs:アルゴリズムの実行中に生成されたログ。
  • /data/inputs/algoCustomData.json:公開手順で定義できる algoCustomData の値。アルゴリズムから参照でき、挙動のカスタマイズに使えます。

6. アルゴリズムのコードを書く

アルゴリズムのコードでは、次を行います。

  1. 必要なデータを /data/inputs から読み込む。
  2. /data/inputs/algoCustomData.json からカスタムパラメータを取得する。
  3. カスタムパラメータを検証する(例:threshold が 1〜50 の範囲かを確認する)。
  4. 計算または変換を実行する。
  5. 結果を /data/outputs に保存する。

6.1 Python によるアルゴリズムの例

# アルゴリズム用の Python スクリプト
import requests
import json
import os
 
# DID とカスタムパラメータを読み込む
DIDS = json.loads(os.getenv("DIDS"))
DID = DIDS[0]
payload_file_path = f'/data/inputs/{DID}/0'
 
# algoCustomData.json からカスタムパラメータを読み込む
custom_params_path = '/data/inputs/algoCustomData.json'
with open(custom_params_path, 'r') as params_file:
    custom_params = json.load(params_file)
 
# 'threshold' パラメータを取得して検証する
threshold = custom_params.get("threshold", 10)  # 指定がなければ既定値 10
if not (1 <= threshold <= 50):
    print(f"Invalid threshold value {threshold}. Setting to default 10.")
    threshold = 10
 
# API のエンドポイントとヘッダーを定義する
API_URL = "https://api.example.com/data"
HEADERS = {
    "Authorization": "Bearer YOUR_ACCESS_TOKEN",
    "Content-Type": "application/json"
}
 
# データセットのファイルからペイロードを読み込む
with open(payload_file_path, "r") as payload_file:
    payload = json.load(payload_file)
 
# 必要に応じてペイロードに threshold を含める
payload['threshold'] = threshold
 
# API リクエストを実行し、レスポンスを処理する
try:
    response = requests.post(API_URL, headers=HEADERS, json=payload)
    response.raise_for_status()
    result = response.json()
 
    # 結果を出力ファイルに保存する
    with open("/data/outputs/results.csv", "w") as f:
        json.dump(result, f)
except requests.exceptions.RequestException as e:
    print(f"API request failed: {e}")
    with open("/data/logs/error.log", "w") as log_file:
        log_file.write(str(e))

6.2 Node.js によるアルゴリズムの例

// アルゴリズム用の Node.js スクリプト
const fs = require('fs');
const fetch = require('node-fetch');
 
// DID とカスタムパラメータを読み込む
const DIDS = JSON.parse(process.env.DIDS);
const DID = DIDS[0];
const payloadFilePath = `/data/inputs/${DID}/0`;
 
// algoCustomData.json からカスタムパラメータを読み込む
const customParamsPath = '/data/inputs/algoCustomData.json';
const customParams = JSON.parse(fs.readFileSync(customParamsPath, 'utf-8'));
 
// 'threshold' パラメータを取得して検証する
let threshold = customParams.threshold !== undefined ? customParams.threshold : 10;  // 指定がなければ既定値 10
if (threshold < 1 || threshold > 50) {
    console.log(`Invalid threshold value ${threshold}. Setting to default 10.`);
    threshold = 10;
}
 
// API のエンドポイントとヘッダーを定義する
const API_URL = "https://api.example.com/data";
const HEADERS = {
    "Authorization": "Bearer YOUR_ACCESS_TOKEN",
    "Content-Type": "application/json"
};
 
(async () => {
    try {
        // データセットのファイルからペイロードを読み込む
        const payload = JSON.parse(fs.readFileSync(payloadFilePath, 'utf-8'));
 
        // 必要に応じてペイロードに threshold を含める
        payload.threshold = threshold;
 
        // API リクエストを実行し、レスポンスを処理する
        const response = await fetch(API_URL, {
            method: 'POST',
            headers: HEADERS,
            body: JSON.stringify(payload)
        });
 
        if (response.ok) {
            const result = await response.json();
 
            // 結果を出力ファイルに保存する
            fs.writeFileSync('/data/outputs/results.csv', JSON.stringify(result));
        } else {
            console.error('API request failed:', response.status);
            fs.writeFileSync('/data/logs/error.log', `Error ${response.status}`);
        }
    } catch (error) {
        console.error('An error occurred:', error);
    }
})();

6.3 Docker コンテナを選ぶ

Compute-to-Data(CtD)では、既定の Docker コンテナを使うことも、必要な依存関係を含む独自のコンテナを指定することもできます。

コンテナの例

  • Pythonpython:3.15
  • Nodenode:24

追加のライブラリが必要な場合は、上で示したように独自の Dockerfile を用意し、Docker Hub に公開してください。

これらの指針に従うことで、アルゴリズムの実行環境は予測可能で安全になり、CtD での実行にあたって公開済みデータセットとも互換性を保てます。

7. ロギングとエラー処理

ログを含め、アルゴリズムのスクリプトが生成したすべての出力は、そのアルゴリズムの利用者から参照できます。特定の出力を記録したい場合は、/data/outputs/ に書き出してください。

これらの指針に従うことで、機微な情報を守りながら、アルゴリズムの出力における透明性とセキュリティを確保できます。