summaryrefslogtreecommitdiff
path: root/doc/Design.md
blob: f22c24dafd5e7371d8f7f7ea84a22b875b2d267c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
# Design.md

## 1. 設計方針

| 方針 | 内容 |
|---|---|
| MCP公開面を小さくする | LLMには生成意図に必要な入力だけを公開する |
| 実行設定はTOMLへ集約 | モデル・VAE・LoRA・ControlNet・生成パラメータを一元管理 |
| SD1.x互換に限定 | SDXL / FLUX等は対象外 |
| 依存分離 | MCP層とDiffusion層を直接密結合させない |
| 単一GPU前提 | 生成処理は1本のキューで直列化 |
| ControlNetは固定3種 | Depth / Openpose / Inpaintのみ |
| 過剰な汎用化を避ける | 未使用ControlNetや動的Tool設定は持たない |

---

## 2. 全体アーキテクチャ

```text
MCP Client / LLM
       │
       ▼
┌──────────────────────┐
│ MCP Server           │
│ - tool schema        │
│ - request validation │
└──────────┬───────────┘
           │
           ▼
┌──────────────────────┐
│ ImageGenerationService│
│ - request routing    │
│ - queue control      │
└──────────┬───────────┘
           │
           ▼
┌──────────────────────┐
│ ModelManager         │
│ - checkpoint         │
│ - VAE                │
│ - LoRA               │
│ - ControlNet         │
└──────────┬───────────┘
           │
           ▼
┌──────────────────────┐
│ Diffusers / PyTorch  │
│ CUDA                 │
└──────────────────────┘
```

---

## 3. モジュール構成

```text
mcp-sd15/
├─ pyproject.toml
├─ uv.lock
├─ .python-version
├─ config.example.toml
├─ src/
│  └─ mcp_sd15/
│     ├─ __init__.py
│     ├─ cli.py
│     ├─ server.py
│     ├─ config.py
│     ├─ schema.py
│     ├─ service.py
│     ├─ model_manager.py
│     ├─ pipeline_factory.py
│     ├─ preprocessors/
│     │  ├─ depth.py
│     │  └─ openpose.py
│     └─ tools/
│        ├─ generate_image.py
│        ├─ generate_guided_image.py
│        └─ inpaint_image.py
└─ tests/
   ├─ test_config.py
   ├─ test_schema.py
   ├─ test_model_paths.py
   └─ test_tools.py
```

---

## 4. 各モジュールの責務

| モジュール | 責務 |
|---|---|
| `cli.py` | `--config`, `--version`の処理 |
| `server.py` | MCP server起動、Tool登録 |
| `config.py` | TOML読込、型変換、validation |
| `schema.py` | MCP入力値・内部request型 |
| `service.py` | Tool要求を生成処理へ振り分け |
| `model_manager.py` | checkpoint / VAE / LoRA / ControlNetの管理 |
| `pipeline_factory.py` | Diffusers pipeline構築 |
| `preprocessors/depth.py` | Midas前処理 |
| `preprocessors/openpose.py` | Openpose / Openpose Full前処理 |
| `tools/*` | MCP Toolからserviceへの薄いadapter |

---

## 5. 起動フロー

| Step | 処理 |
|---|---|
| 1 | CLI引数を解析 |
| 2 | TOMLを読込 |
| 3 | 設定値をvalidation |
| 4 | モデルパスを解決 |
| 5 | checkpoint存在確認 |
| 6 | VAE / LoRA / ControlNet存在確認 |
| 7 | Base SD1.x pipelineを構築 |
| 8 | VAEを適用 |
| 9 | LoRAを順次ロード |
| 10 | GPUへ配置 |
| 11 | MCP Toolを公開 |
| 12 | リクエスト待受開始 |

モデル構成の初期化に失敗した場合はToolを公開せず、プロセスを異常終了する。

---

## 6. 設定オブジェクト

推奨内部型:

```python
@dataclass(frozen=True)
class LoRAConfig:
    file: str
    weight: float = 1.0

@dataclass(frozen=True)
class ModelConfig:
    root: Path
    checkpoint: str
    vae: str | None
    loras: tuple[LoRAConfig, ...]

@dataclass(frozen=True)
class GenerationConfig:
    steps: int
    cfg_scale: float
    scheduler: str
    default_size: str
```

Pydanticは必須とせず、`tomllib + dataclass + 明示的validation`を基本とする。

---

## 7. モデルパス解決

| 種類 | 解決先 |
|---|---|
| checkpoint | `<root>/checkpoints/<file>` |
| VAE | `<root>/vae/<file>` |
| LoRA | `<root>/lora/<file>` |
| ControlNet | `<root>/controlnet/<file>` |

設計上、MCP入力から任意モデルパスを指定することは禁止する。

---

## 8. Diffusers構成

| 機能 | 実装方針 |
|---|---|
| Base model | SD1.x互換checkpointをロード |
| VAE | 設定された場合のみ置換 |
| LoRA | 複数adapterをロード |
| LoRA weight | `set_adapters`相当で適用 |
| LoRA fuse | 将来オプション。初期実装では必須としない |
| dtype | FP16 |
| device | CUDA |
| scheduler | TOMLで指定 |
| batch | 1 |
| images per prompt | 1 |
| CPU offload | 初期値OFF |

---

## 9. ControlNet設計

### 9.1 モード

| MCP mode | ControlNet | Preprocessor |
|---|---|---|
| `depth` | Depth 1.1 | Midas |
| `openpose` | Openpose 1.1 | body |
| `openpose_full` | Openpose 1.1 | body + hand + face |
| `inpaint` | Inpaint 1.1 | mask生成規約に従う |

### 9.2 パイプライン

```text
Depth/Openpose:
input image
   │
   ▼
preprocessor
   │
   ▼
control image
   │
   ▼
StableDiffusionControlNetPipeline
   │
   ▼
PNG
```

```text
Inpaint:
input image + mask
   │
   ▼
ControlNet Inpaint input
   │
   ▼
Inpaint-compatible pipeline
   │
   ▼
PNG
```

### 9.3 ロード方針

8GB級GPUを主対象とするため、ControlNetは必要時ロードを基本候補とする。

| 状態 | 動作 |
|---|---|
| 未ロード | 必要なControlNetをロード |
| 同一ControlNet | 再利用 |
| 別ControlNet要求 | 既存ControlNetを解放後ロード |
| generation中 | 切替禁止 |

---

## 10. MCP Tool設計

### `generate_image`

```text
Input:
- positive_prompt
- negative_prompt?
- size?

Output:
- image/png
- generation metadata
```

### `generate_guided_image`

```text
Input:
- positive_prompt
- negative_prompt?
- control_mode: depth | openpose | openpose_full
- input_image
- size?

Output:
- image/png
- generation metadata
```

### `inpaint_image`

```text
Input:
- positive_prompt
- negative_prompt?
- input_image
- mask_image
- size?

Output:
- image/png
- generation metadata
```

Tool層はDiffusers APIを直接呼ばず、必ずService層を経由する。

---

## 11. 生成キュー

```text
MCP Request
    │
    ▼
asyncio.Semaphore(1)
    │
    ▼
GenerationService
    │
    ▼
GPU
```

| 項目 | 方針 |
|---|---|
| 同時GPU処理 | 1 |
| キュー | FIFO相当 |
| OOM防止 | 並列生成禁止 |
| cancellation | MCP SDKで扱える範囲で対応 |
| timeout | 設定値として追加可能 |

---

## 12. 出力

| 項目 | 仕様 |
|---|---|
| Format | PNG |
| MCP返却 | ImageContent相当 |
| ローカル保存 | 設定により有効化可能 |
| ファイル名 | UUIDまたはgeneration ID |
| metadata | seed, size, mode, timestamp等 |
| prompt保存 | ログ方針により設定 |

---

## 13. エラー設計

| エラー分類 | 例 | 処理 |
|---|---|---|
| CONFIG_ERROR | TOML不正 | 起動失敗 |
| MODEL_NOT_FOUND | モデル未配置 | 起動失敗 |
| MODEL_INCOMPATIBLE | SD1.x非互換 | 起動失敗 |
| INVALID_REQUEST | 不正size / mode | Tool error |
| INVALID_IMAGE | 画像形式不正 | Tool error |
| CUDA_OOM | VRAM不足 | Tool error + GPU状態回復 |
| GENERATION_FAILED | 推論例外 | Tool error |
| INTERNAL_ERROR | 想定外例外 | ログ出力 + Tool error |

---

## 14. pyproject / uv方針

### Runtime依存

| Package | 用途 |
|---|---|
| `mcp` | MCP server |
| `torch` | CUDA / Tensor |
| `diffusers` | SD / ControlNet |
| `transformers` | CLIP |
| `peft` | LoRA |
| `safetensors` | モデル形式 |
| `pillow` | 画像I/O |
| `numpy` | 数値処理 |
| `opencv-python` | 画像前処理 |

### Development依存

| Package | 用途 |
|---|---|
| `pytest` | テスト |
| `ruff` | lint / format |
| `pyright` | 型チェック |

### 例

```toml
[project]
name = "mcp-sd15"
version = "0.1.0"
requires-python = ">=3.11,<3.12"

[project.scripts]
mcp-sd15 = "mcp_sd15.cli:main"
```

運用は`pyproject.toml + uv.lock`を基準とする。

---

## 15. テスト設計

| テスト種別 | GPU | 内容 |
|---|---:|---|
| Config parsing | 不要 | TOML読込・型検証 |
| Path resolution | 不要 | モデルパス解決 |
| MCP schema | 不要 | Tool schema検証 |
| Request validation | 不要 | mode / size / image必須条件 |
| Service routing | 不要 | 適切なbackend呼出 |
| Model load smoke | 必要 | checkpoint / VAE / LoRA |
| Txt2Img smoke | 必要 | 512x512生成 |
| Depth smoke | 必要 | ControlNet Depth |
| Openpose smoke | 必要 | Openpose / Full |
| Inpaint smoke | 必要 | mask付き生成 |

---

## 16. 将来拡張

初期設計では以下を実装対象外とする。

| 項目 | 方針 |
|---|---|
| SDXL / FLUX | 対象外 |
| Multi-ControlNet | 対象外 |
| MCPからのモデル切替 | 対象外 |
| 任意width / height | 対象外 |
| batch > 1 | 対象外 |
| LoRA動的追加 | 対象外 |
| Web UI | 対象外 |
| 学習機能 | 対象外 |
| 複数GPU | 対象外 |

必要になった場合のみ、既存のService / ModelManager境界を維持したまま拡張する。