# シーンベース原稿生成機能（LLM統合版）

## 概要

**シーンベース原稿生成** は、Novelerの18ステップ執筆システム（STEP 12）において、シーン単位での詳細な原稿生成を実現する機能です。

### 特徴

- **品質優先**: 各シーンを丁寧に生成し、内容の質を最大化
- **順次実行**: 前シーンのコンテキストを次のシーン生成に活用
- **LLM統合**: OpenAI/Anthropicなどのモデルを利用した高品質生成
- **自動フォールバック**: LLM生成失敗時は従来のテンプレート構造へ自動切り替え
- **段階的品質チェック**: 各シーン生成後に品質検証を実施

## 推奨される使用場面

### シーンベース生成が効果的な場合

1. **長編作品（10シーン以上）**
   - 複雑な構成を持つエピソード
   - シーン間の因果関係が重要な作品

2. **キャラクター重視作品**
   - キャラクターの心理描写が重要
   - 対話シーンが多い

3. **高品質な原稿が必要な場合**
   - 出版用原稿
   - 重要なシーン

### シーンベース生成が不要な場合

1. **短編作品（3シーン以下）**
   - テンプレート生成で十分

2. **急速な初稿生成が必要な場合**
   - 速度を優先する場合は従来のテンプレート生成

## 動作仕組み

### 1. シーン分割

STEP 5（シーン設計）で設計されたシーン情報を活用します：

```yaml
scenes:
  - scene_number: 1
    title: "出会い"
    location: "図書館"
    characters: ["主人公", "ヒロイン"]
    events: ["初対面", "言葉の交換"]
    description: "主人公がヒロインと初めて出会うシーン"
```

### 2. コンテキスト伝播

各シーン生成時に、前シーンまでの要約が次のシーン生成に渡されます：

```
シーン1生成 → 要約抽出 →
シーン2生成（シーン1の要約付き） → 要約更新 →
シーン3生成（累積要約付き）...
```

このプロセスにより、シーン間の一貫性と論理的繋がりが確保されます。

### 3. LLM実行

各シーンについて独立したLLM呼び出しを実施：

- **プロンプト**: `write_step12_scene_generation.yaml` テンプレートに基づく
- **入力**: シーンメタデータ、前シーン要約、エピソード文脈
- **出力**: 詳細な原稿テキスト（Markdown形式）

### 4. 品質チェック

生成後の原稿について自動チェック：

```
✓ 最小文字数（300字以上）
✓ プレースホルダー未含有
✓ 基本的な日本語妥当性
✓ 前シーンとの論理的接続
```

チェック失敗時は、最大3回までリトライを試行します。

## 実装詳細

### 主要コンポーネント

#### `ManuscriptGeneratorService`

```python
class ManuscriptGeneratorService(BaseWritingStep):
    async def convert_scene_to_content_with_llm(
        self,
        scene: SceneData,
        previous_scenes_summary: str = "",
        episode_context: dict[str, Any] | None = None,
        llm_executor: Any | None = None,
        project_root: Path | None = None,
        episode_number: int | None = None,
        max_retries: int = 3,
        target_word_count: int = 2000,
    ) -> str:
        """シーンをLLMで原稿生成。"""
```

**責務**:
- シーンメタデータからLLM向けプロンプト構築
- LLM呼び出しとリトライ管理
- 生成内容の品質検証
- エラーハンドリング

#### プロンプトテンプレート

**ファイル**: `templates/writing/write_step12_scene_generation.yaml`

**特徴**:
- Schema v2 準拠の構造化YAML
- シーン単位の詳細なプロンプト定義
- システムプロンプト（基本方針）とユーザープロンプト（具体指示）の分離

### 設定

#### LLM生成の有効化

`config_manager` に以下を設定：

```python
config.manuscript_generation.use_llm = True
config.llm_executor = your_llm_executor_instance
```

#### 目標文字数の設定

```python
workspace.target_word_count = 8000  # 全体の目標文字数
# シーン数に応じて自動分割（1500-3000字/シーン）
```

## 使用例

### 基本的な使用方法

```python
from noveler.domain.services.writing_steps.manuscript_generator_service import (
    ManuscriptGeneratorService
)

# サービス初期化
service = ManuscriptGeneratorService(
    logger_service=logger,
    path_service=path_service,
    config_manager=config_manager
)

# 原稿生成実行（LLM統合モード）
response = await service.execute(
    episode_number=1,
    previous_results={...}  # STEP 0-11の結果
)

# 結果確認
if response.success:
    print(f"生成完了: {response.manuscript_path}")
    print(f"シーン数: {response.scenes_converted}")
else:
    print(f"エラー: {response.error_message}")
```

### プログラム的なLLM実行（上級）

```python
# LLMエグゼキュータを自分で用意する場合
from noveler.domain.interfaces.progressive_write_llm_executor import (
    ProgressiveWriteLLMExecutor
)

service = ManuscriptGeneratorService(...)
workspace = await service._initialize_workspace(1, previous_results)

# シーン単位での詳細制御
scene = workspace.scenes[0]
content = await service.convert_scene_to_content_with_llm(
    scene=scene,
    previous_scenes_summary="",
    episode_context={"title": "第001話", "theme": "出会い"},
    llm_executor=your_executor,
    project_root=Path("/path/to/project"),
    episode_number=1,
    target_word_count=2000
)
```

## パフォーマンス特性

### 実行時間

| シーン数 | 推定時間 | 備考 |
|---------|---------|------|
| 1-3 | 10-30分 | 素早い |
| 4-6 | 30-60分 | 中程度 |
| 7-9 | 60-120分 | やや長い |
| 10-12 | 120-240分 | 相当時間を要する |

※時間はLLMの性能とネットワークに依存

### トークン使用量

```
入力（1シーンあたり）:
  - 共通部（システム/設定）: 500 tokens
  - 前シーン要約: 300-500 tokens
  - シーンメタデータ: 200 tokens
  合計: 1000-1200 tokens

出力（1シーンあたり）:
  - 目標2000字: 1500-2000 tokens
```

**合計概算**: (1000 + 1500) × シーン数 tokens

## トラブルシューティング

### シーン生成が失敗する

#### 原因1: LLMエグゼキュータが設定されていない

```python
# エラー: ValueError("llm_executor is required...")

# 対策
config.manuscript_generation.use_llm = True
config.llm_executor = your_executor
```

#### 原因2: APIレート制限に達した

```python
# エラー: RuntimeError("Failed to generate scene after 3 attempts")

# 対策: リトライ待機時間を増やす（手動実装必要）
# または、待機後に再実行
```

#### 原因3: プロンプトの言語が合わない

テンプレートのシステムプロンプトを確認：

```yaml
llm_config:
  role_messages:
    system: |
      あなたは長編小説の執筆アシスタントです。...
```

モデルが日本語に対応していることを確認してください。

### 品質チェックで失敗する

#### 生成内容が短すぎる（300字未満）

```python
# テンプレートで目標文字数を増やす
target_word_count = 3000
```

または `_validate_scene_quality` の閾値を調整してください。

#### プレースホルダーが含まれている

テンプレートのプロンプトを確認し、モデルが指示を正しく理解しているか確認：

```yaml
constraints:
  hard_rules:
    - "空行や説明文は含めない（原稿テキストのみ）"
```

## ベストプラクティス

### 1. テンプレートのカスタマイズ

作品のジャンル・トーンに合わせてプロンプトを調整：

```yaml
llm_config:
  role_messages:
    user: |
      【執筆指示】
      1. 詩的で叙情的な描写を優先
      2. 主人公の内面描写を重視
      3. 自然の情景描写を効果的に活用
```

### 2. シーン設計の充実

STEP 5 でのシーン設計が詳細なほど、生成品質が向上：

```yaml
scenes:
  - scene_number: 1
    title: "出会い"
    description: "主人公がヒロインと図書館で出会い、..."
    location: "図書館の古書コーナー"
    time_setting: "秋の午後、3時ごろ"
    characters: ["主人公（18歳）", "ヒロイン（17歳）"]
    events:
      - "本を探している主人公"
      - "背の高い本棚から本を取るヒロイン"
      - "目があって言葉を交わす"
      - "共通の興味を発見"
```

### 3. 前シーンコンテキストの確認

生成ログで前シーンコンテキストが正しく渡されているか確認：

```
[INFO] Scene 1/9 generated successfully (2150 chars)
[INFO] Scene 2/9: Previous context summary generated (498 chars)
[INFO] Scene 2/9 generated successfully (2020 chars)
```

### 4. LLM選択の工夫

モデル選択のガイド：

| モデル | 推奨用途 | 特徴 |
|--------|---------|------|
| GPT-4 | 高品質が必要な場合 | 高コスト、高品質 |
| Claude Sonnet | バランス重視 | 中コスト、良好な品質 |
| GPT-3.5 | 速度重視 | 低コスト、十分な品質 |

## 設定リファレンス

### writing_tasks.yaml

```yaml
  - id: 12
    name: "初稿執筆（シーンベース生成）"
    estimated_duration: "180-240分（品質優先、最大12シーン）"
    notes:
      - "シーン数が多い場合は、予想実行時間が大幅に延長される"
      - "品質優先モードのため、各シーン生成に時間を要する"
      - "前シーンコンテキストを活用した順次実行"
      - "失敗時のリトライは最大3回"
```

### write_step12_scene_generation.yaml

```yaml
metadata:
  step_id: 12
  integration: "LLM executor required"
  estimated_duration: "15-25分/シーン（最大12シーン）"

control_settings:
  timeout_seconds: 180
  retry_on_error: true
  max_retries: 3
```

## 関連ドキュメント

- [18ステップ執筆システム](../guides/18_step_writing_system.md)
- [STEP 5: シーン設計](./step5_scene_design.md)
- [LLMエグゼキュータ](../infrastructure/llm_executor.md)
- [プロンプトエンジニアリングガイド](../guides/prompt_engineering.md)

## FAQ

### Q: シーン単位生成と全体一括生成、どちらが良い？

**A**: 用途によって使い分けてください。

- **シーン単位**: 品質重視、複雑な作品、再編集が多い場合
- **全体一括**: 速度重視、単純な構成、初稿のみの場合

### Q: シーン数が12を超えるエピソードはどうする？

**A**: 以下の対応が推奨されます。

1. **シーンの統合**: 類似シーンを結合（ただし情報量が増加）
2. **複数回生成**: エピソードを前後半に分割して実行
3. **手動編集**: 一部を手動執筆で補完

### Q: 前シーンコンテキストが不正確なことがある？

**A**: これは正常な動作です。

- `_build_context_summary()` は簡潔性を優先
- 重要な情報はプロンプトに明示的に記載してください
- 必要に応じて前シーンを手動で要約し、指定することも可能

### Q: LLM生成をキャンセルできる？

**A**: 現在の実装では、一度実行されたシーン生成をキャンセルすることはできません。

代替案：
- CLI/MCP経由で `Ctrl+C` で全体実行をキャンセル
- 失敗したシーンのみを手動実行し直す

## 更新履歴

- **2025-10-28**: 初版作成（v0.1.0）
  - LLM統合シーン生成機能の実装
  - テンプレートベースのプロンプト設計
  - 品質優先モードの実装
