# 機能設計書 135-MLモデルレジストリ

## 概要

本ドキュメントは、GitLabにおけるMLモデルレジストリ機能の設計について記述する。機械学習モデルの登録、バージョン管理、実験トラッキングを通じて、MLOpsワークフローを支援する機能を定義する。

### 本機能の処理概要

**業務上の目的・背景**：機械学習プロジェクトでは、モデルの開発からデプロイまでのライフサイクル管理が重要な課題である。MLモデルレジストリ機能により、モデルのバージョン管理、実験パラメータ・メトリクスの追跡、モデルアーティファクトの保存を一元化し、再現性のある機械学習開発を支援する。MLflowとの互換性を持ち、既存のMLワークフローとの統合も可能。

**機能の利用シーン**：
- 機械学習モデルの新規登録とメタデータ管理
- モデルバージョンの作成と履歴管理
- 実験（Experiment）の作成とパラメータ・メトリクス記録
- 候補（Candidate）の比較と評価
- モデルアーティファクトのパッケージング
- MLflowクライアントからのAPI連携

**主要な処理内容**：
1. MLモデルの作成・編集・削除
2. モデルバージョンの作成・管理
3. 実験（Experiment）の作成・管理
4. 候補（Candidate）の作成とメトリクス・パラメータ記録
5. モデルのパッケージングとアーティファクト管理
6. MLflow互換APIの提供

**関連システム・外部連携**：
- MLflow（実験トラッキングフレームワーク）
- GitLabパッケージレジストリ（アーティファクト保存）
- CI/CDパイプライン（モデルトレーニング自動化）

**権限による制御**：
- `read_model_registry`: モデルレジストリの閲覧
- `write_model_registry`: モデルの作成・編集・削除

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 103 | 実験一覧 | 主機能 | ML実験の一覧表示 |
| 104 | 実験詳細 | 主機能 | ML実験の詳細表示 |
| 105 | モデル一覧 | 主機能 | MLモデルの一覧表示 |
| 106 | モデル新規作成 | 主機能 | 新規MLモデルの登録 |
| 107 | モデル詳細 | 主機能 | MLモデルの詳細表示 |
| 108 | モデル編集 | 主機能 | MLモデルの編集 |
| 109 | モデルバージョン詳細 | 主機能 | モデルバージョンの詳細表示 |
| 110 | 候補詳細 | 主機能 | ML候補（実験結果）の詳細表示 |

## 機能種別

CRUD操作 / バージョン管理 / メトリクス管理 / API連携

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| name | String | Yes | モデル名 | 最大255文字、正規表現パターン準拠 |
| description | String | No | モデル説明 | 最大10000文字 |
| version | String | No | バージョン番号 | セマンティックバージョニング推奨 |
| experiment_name | String | Yes (実験作成時) | 実験名 | - |
| params | Hash | No | 候補のパラメータ | key-value形式 |
| metrics | Hash | No | 候補のメトリクス | key-value形式（数値） |

### 入力データソース

- GitLab UI上でのユーザー入力
- GraphQL APIからのミューテーション
- MLflow互換REST API

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| id | Integer | モデルID |
| name | String | モデル名 |
| description | String | モデル説明（マークダウン対応） |
| versions | Array | バージョン一覧 |
| latest_version | Object | 最新バージョン |
| version_count | Integer | バージョン数 |
| experiments | Array | 関連実験一覧 |
| candidates | Array | 候補一覧 |
| metadata | Array | メタデータ |

### 出力先

- GitLab UIでのモデル一覧・詳細表示
- GraphQL APIレスポンス
- MLflow互換REST APIレスポンス

## 処理フロー

### 処理シーケンス

```
1. モデル作成リクエスト
   └─ モデル名、説明等を受け取り
2. デフォルト実験作成
   └─ モデルに紐づく[model]プレフィックス付き実験を自動作成
3. モデルレコード作成
   └─ ml_modelsテーブルにレコード作成
4. バージョン作成（オプション）
   └─ 初期バージョンを作成
5. 候補作成（実験実行時）
   └─ パラメータ・メトリクスを記録
```

### フローチャート

```mermaid
flowchart TD
    A[モデル作成リクエスト] --> B{権限チェック}
    B -->|OK| C[デフォルト実験作成]
    B -->|NG| X[403 Forbidden]
    C --> D[モデルレコード作成]
    D --> E{バージョン作成?}
    E -->|Yes| F[バージョン作成]
    E -->|No| G[成功レスポンス]
    F --> G

    H[実験実行] --> I[候補作成]
    I --> J[パラメータ記録]
    J --> K[メトリクス記録]
    K --> L{パッケージ関連付け?}
    L -->|Yes| M[パッケージリンク]
    L -->|No| N[候補保存]
    M --> N
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-135-01 | モデル名一意性 | プロジェクト内でモデル名は一意 | モデル作成時 |
| BR-135-02 | モデル名形式 | 正規表現パターンに準拠 | モデル作成/更新時 |
| BR-135-03 | 説明文字数制限 | 説明は最大10000文字 | モデル作成/更新時 |
| BR-135-04 | デフォルト実験自動作成 | モデル作成時に[model]プレフィックス付き実験を自動作成 | モデル作成時 |
| BR-135-05 | 実験-モデル整合性 | デフォルト実験はモデルと同一プロジェクト | モデル作成時 |

### 計算ロジック

- **実験名プレフィックス**: EXPERIMENT_NAME_PREFIX = '[model]'
- **バージョン数カウント**: `with_version_count`スコープでSQLレベルでカウント

## データベース操作仕様

### 操作別データベース影響一覧

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| モデル作成 | ml_models | INSERT | モデルレコード作成 |
| モデル更新 | ml_models | UPDATE | モデル情報更新 |
| モデル削除 | ml_models | DELETE | モデルと関連データ削除 |
| 実験作成 | ml_experiments | INSERT | 実験レコード作成 |
| バージョン作成 | ml_model_versions | INSERT | バージョンレコード作成 |
| 候補作成 | ml_candidates | INSERT | 候補レコード作成 |
| メトリクス記録 | ml_candidate_metrics | INSERT | メトリクスレコード作成 |
| パラメータ記録 | ml_candidate_params | INSERT | パラメータレコード作成 |
| メタデータ記録 | ml_model_metadata | INSERT | メタデータレコード作成 |

### テーブル別操作詳細

#### ml_models

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | project_id, name, description, user_id | ユーザー入力値 | default_experiment_idは自動設定 |
| UPDATE | description | マークダウン形式 | キャッシュマークダウン対応 |
| SELECT | project_id, id / project_id, name | IDまたは名前で取得 | - |

#### ml_experiments

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | project_id, name | [model]プレフィックス + モデル名 | - |

#### ml_model_versions

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | model_id, version, package_id | バージョン情報 | - |
| SELECT | model_id | モデルIDで取得 | latest_by_modelスコープあり |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 403 | Forbidden | 権限不足 | write_model_registry権限を付与 |
| 404 | Not Found | モデルが存在しない | 正しいモデルを指定 |
| 422 | Unprocessable Entity | バリデーションエラー | 入力値を修正 |

### リトライ仕様

該当なし（同期処理）

## トランザクション仕様

- モデル作成とデフォルト実験作成は同一トランザクション
- バージョン作成は別トランザクション

## パフォーマンス要件

- モデル一覧取得は20件以下で200ms以内
- 候補一覧はページネーション対応

## セキュリティ考慮事項

- モデルへのアクセスはプロジェクトメンバーシップに依存
- MLflow APIはプロジェクトトークンで認証
- モデルアーティファクトはパッケージレジストリの権限に従う

## 備考

- MLflow互換APIは`/api/v4/projects/:id/ml/mlflow/`で提供
- モデルはプロジェクト単位で管理

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

MLモデルレジストリの中核となるデータモデルを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | model.rb | `app/models/ml/model.rb` | モデルのデータ構造 |
| 1-2 | model_version.rb | `app/models/ml/model_version.rb` | バージョンモデル |
| 1-3 | experiment.rb | `app/models/ml/experiment.rb` | 実験モデル |
| 1-4 | candidate.rb | `app/models/ml/candidate.rb` | 候補モデル |

**読解のコツ（model.rb）**:
- **9行目**: EXPERIMENT_NAME_PREFIX = '[model]' でデフォルト実験名の接頭辞を定義
- **11-16行目**: バリデーションでname形式とプロジェクト内一意性をチェック
- **22-28行目**: default_experiment, versions, candidates等との関連を定義
- **30-40行目**: スコープ定義（including_latest_version, with_version_count等）
- **49-54行目**: valid_default_experiment?でデフォルト実験の整合性検証
- **64-66行目**: prefixed_experimentでプレフィックス付き実験名を生成

#### Step 2: エントリーポイントを理解する

MLモデルレジストリのUIエントリーポイント。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | models_controller.rb | `app/controllers/projects/ml/models_controller.rb` | モデル画面制御 |
| 2-2 | experiments_controller.rb | `app/controllers/projects/ml/experiments_controller.rb` | 実験画面制御 |
| 2-3 | candidates_controller.rb | `app/controllers/projects/ml/candidates_controller.rb` | 候補画面制御 |
| 2-4 | model_versions_controller.rb | `app/controllers/projects/ml/model_versions_controller.rb` | バージョン画面制御 |

**主要処理フロー（models_controller.rb）**:
- **6行目**: `authorize_read_model_registry!`で閲覧権限チェック
- **7行目**: `authorize_write_model_registry!`で書き込み権限チェック（destroy, new, edit時）
- **11行目**: MAX_MODELS_PER_PAGE = 20 でページあたり件数定義
- **21-26行目**: `destroy`アクションでモデル削除

#### Step 3: サービス層を理解する

モデル作成・更新のビジネスロジック。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | create_model_service.rb | `app/services/ml/create_model_service.rb` | モデル作成 |
| 3-2 | update_model_service.rb | `app/services/ml/update_model_service.rb` | モデル更新 |
| 3-3 | destroy_model_service.rb | `app/services/ml/destroy_model_service.rb` | モデル削除 |
| 3-4 | create_model_version_service.rb | `app/services/ml/create_model_version_service.rb` | バージョン作成 |

### プログラム呼び出し階層図

```
ModelsController
    │
    ├─ index (モデル一覧)
    │      └─ Ml::Model.by_project
    │             └─ with_version_count
    │
    ├─ show (モデル詳細)
    │      └─ Ml::Model.by_project_id_and_id
    │
    ├─ new/edit (作成/編集画面)
    │
    └─ destroy (モデル削除)
           └─ Ml::Model#destroy!

Ml::CreateModelService
    │
    ├─ モデル作成
    │      └─ Ml::Model.create
    │
    └─ デフォルト実験作成
           └─ Ml::CreateExperimentService
                  └─ Ml::Experiment.create

Ml::CreateModelVersionService
    │
    ├─ バージョン作成
    │      └─ Ml::ModelVersion.create
    │
    └─ パッケージ関連付け
           └─ Packages::MlModel::Package
```

### データフロー図

```
[入力]                       [処理]                          [出力]

ユーザーリクエスト ───────▶ ModelsController ───────────────▶ モデル一覧画面
      │                           │                              │
      ▼                           ▼                              ▼
モデル名/説明           CreateModelService              モデル詳細画面
      │                           │                              │
      ▼                           ▼                              ▼
                      CreateExperimentService           バージョン一覧
                           │                                   │
                           ▼                                   ▼
                      Ml::Model.create                   候補一覧/詳細
                      Ml::Experiment.create
                           │
                           ▼
                      ml_models / ml_experiments
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| model.rb | `app/models/ml/model.rb` | モデル | MLモデル |
| model_version.rb | `app/models/ml/model_version.rb` | モデル | バージョン |
| experiment.rb | `app/models/ml/experiment.rb` | モデル | 実験 |
| candidate.rb | `app/models/ml/candidate.rb` | モデル | 候補 |
| candidate_metric.rb | `app/models/ml/candidate_metric.rb` | モデル | メトリクス |
| candidate_param.rb | `app/models/ml/candidate_param.rb` | モデル | パラメータ |
| models_controller.rb | `app/controllers/projects/ml/models_controller.rb` | コントローラー | モデル画面 |
| experiments_controller.rb | `app/controllers/projects/ml/experiments_controller.rb` | コントローラー | 実験画面 |
| create_model_service.rb | `app/services/ml/create_model_service.rb` | サービス | モデル作成 |
| create_model_version_service.rb | `app/services/ml/create_model_version_service.rb` | サービス | バージョン作成 |
| model_presenter.rb | `app/presenters/ml/model_presenter.rb` | プレゼンター | モデル表示 |
| mlflow_helper.rb | `app/helpers/projects/ml/mlflow_helper.rb` | ヘルパー | MLflow連携 |
