Claude CodeとNano Banana Proで議事録から提案書スライドを自動生成してみた

Claude CodeとNano Banana Proで議事録から提案書スライドを自動生成してみた

2025.12.03

クラスメソッドではAI駆動開発を推進するための取り組みを行っており、クラスメソッド社員も実際に日常的にAIを使って開発を行っています。

弊社メンバーが日常的に実践するAI駆動開発のナレッジやTipsを共有するために、AI駆動開発 Advent Calendar 2025を開催しています。

本ブログは、この企画の3日目の記事になります。

もしAI駆動開発の最先端を知りたい方は、この1ヶ月間、ぜひ本アドベントカレンダーをチェックしてみてください。

https://adventar.org/calendars/11778

はじめに

さて、本題に入りますが、みなさんNano Banana Pro(Gemini 3 Pro Image)(以後Nano Banana Pro)使ってますか?

自分も先日初めて使ってみて、かなりすごいと感じ、画像生成が一段階上のレベルに上がったという印象を受けました。

また、このNano Banana Proは、NotebookLMにも組み込まれており、NotebookLMからスライド作成を行うときなどにも内部で使われています。

https://workspaceupdates.googleblog.com/2025/11/workspace-nano-banana-pro.html

この機能を使えば、クオリティの高いスライドをあっという間に作れるようになりました。例えば、以下はAWSアップデートのサマリメモをNotebookLMのソースにテキストとして貼り付け、「スライド資料」ボタンを押すだけで作成できたものです。かなりの精度ではないでしょうか?

alt text

スライドの内容をコントロールしやすい形で自動作成する

上記のようにサクッとスライドを作れるようになったわけですが、作成されるスライドの内容は当然ながらある程度、ユーザー側でコントロールしたいですよね?ユーザー側で確認済の正しい情報をソースとして与えることでハルシネーションを抑える効果もあると思います。

ということで、まず考えたのが以下の方法でした。

方法1:スライドの内容を完全にテキスト化し、その内容に沿って作成を依頼する

この方法はNotebookLMにMarp形式のテキストを与え、Marpであることを明示したうえで、テキストに沿ったスライドを作成するように依頼するものになります。

私は以前から資料作成をMarp形式で行っていたのでまずこの方法を思いつきました。Marpによる資料作成については以下のブログがとてもわかりやすいのでご参照ください。

https://dev.classmethod.jp/articles/classmethod-marp-theme/

まず、NotebookLMのソースに以下のようなテキストを貼り付けます。

source.md(クリックで展開)
---
marp: true
theme: classmethod
paginate: true
title: Claude Code ハンズオン - 明日から業務で使える実践テクニック
description: Claude Codeをインストールした方向けに、明日から実際の業務で使える機能を学ぶハンズオン形式のセッション
keywords: Claude Code, AI, カスタムスラッシュコマンド, MCP, hooks, スキル, プラグイン
---

<!-- _class: title -->
<!-- _paginate: false -->

![classmethod-logo w:400px](https://classmethod.jp/wp-content/themes/cmn/assets/images/common/logo_classmethod.svg)

# Claude Code ハンズオン
## 明日から業務で使える実践テクニック

2025/11/14

---

<!-- _class: section -->
<!-- _paginate: false -->

## オープニング

---

# 本セッションの目的

## ターゲット
Claude Codeのインストールをしたぞ。さて次はどうしよう?という方

## ゴール
明日からClaude Codeを実際の業務で使い始められるようになる

- **最低1つは業務で使える機能を持ち帰る**
- **次に試すべき機能が明確になっている**

---

# アジェンダ

1. スコープについて
2. 【デモ】カスタムスラッシュコマンド
3. 【デモ】よく使う組み込みコマンド
4. MCPとは? 外部ツール連携の仕組み
5. 【デモ】hooks
6. 【デモ】プラグイン

---

<!-- _class: section -->
<!-- _paginate: false -->

## スコープについて

---

# スコープとは?

Claude Codeでは、設定やカスタムコマンドをどの範囲で利用するかを**スコープ**で管理します。

3種類のスコープがあります:
- **ローカル**スコープ
- **プロジェクト**スコープ
- **ユーザー**スコープ

---

<!-- _class: content-image -->

# スコープの種類と特徴

| スコープ | 利用範囲 | 設定方法・場所 | 共有 | 主な用途・特徴 |
|----------|----------|----------------|------|----------------|
| **ローカル** | プロジェクト内のみ | コマンドで追加 || 個人用MCP、開発中のMCP、チーム共有不要 |
| **プロジェクト** | プロジェクト内のみ | `.mcp.json`ファイル | ✅ Git管理 | チーム開発、環境変数対応 |
| **ユーザー** | PC内全プロジェクト | グローバル設定 || 汎用的なMCP、常用ツール |

---

<実際は更に内容が続きます>

次にスライドを作成ボタンを押すのですが、このときにスライド作成ボタン横のペンのボタンを押します。

alt text

すると以下のようにスライドの内容について指示を追加できる画面が出てきます。ここで以下のように指定をします。スライドの説明の箇所でMarp形式であることと、どこからどこまでを1スライドとするかを明記しています。

  • 形式:詳細なスライド
  • 長さ:デフォルト
  • 作成するスライドについて説明してください:後述

alt text

「作成するスライドについて説明してください」の箇所ですが、以下のようなプロンプトで指示しました。

この資料はMarp形式のマークダウンスライドです。以下の指示に厳密に従ってスライドを作成してください:

【重要な形式理解】
- `---` がスライドページの区切りです
- 各 `---` の間が1ページ分の内容です
- スライドは全44ページあります

【作成の絶対条件】
1. 提供された全ページを順番通りに、内容を一切省略せずに含めること
2. 各ページのテキスト、コード例、表、箇条書きをすべて保持すること
3. ページ番号、セクション構造、見出しレベルを維持すること
4. フロントマター(最初の`---`で囲まれた設定)も保持すること

【禁止事項】
- ページの統合や省略は絶対にしないこと
- 内容の要約や簡略化をしないこと
- ページ順序の変更をしないこと

元の資料の構造と内容を100%忠実に再現してください。

これで出来上がったのが以下のスライドです。

alt text
alt text
alt text

マークダウンの書式である ### をそのまま文字列として解釈してしまっているのがかなり微妙ですね。また、上記のプロンプトで スライドは全44ページあります と明示しているにも関わらず作成されたスライドは20ページしかありませんでした。もちろん生成AIなので成果物に揺らぎはあると思いますが、3回ほど作成しましたがどのバージョンでも同じような感じでした。

ちなみにNotebookLMにNano Banana Proが搭載された当初に作成できたスライドはこんな感じでした。このクオリティなら素晴らしいのですが・・・。

alt text

方法2:Claude CodeでMarp形式のスライドを作り、Gemini 3 Pro APIを呼ぶことで図を追加する

方法1がちゃんと機能したとしても、この方法には欠点があります。それは作成したスライドの修正を行うのが大変ということです。

NotebookLMによるスライド作成は文量にもよると思いますが、私の実測では上記の20ページのスライドを作成するのに10分ほどかかりました。

作成したあとに「あ、ここ修正したい」、「ここの絵がイマイチだな」となるとそれを修正するために再度10分かけなければならないわけです。しかもNotebookLMの場合は一発出しなので、この部分だけ修正といったことも難しく、指摘したところは直ったけど今度は別の良かったスライドが改悪されてしまったということもあり得ます。これでは、なかなか実際の業務の中で使うのは難しいです。

そこで考えたのが従来の方法で作成したMarp形式のマークダウンにNano Banana Proで生成した画像を追加するといった方法です。図解すると以下のような形になります。

もちろん普通にMarpで作ったあとにブラウザ等からGeminiのチャットを使って画像生成させ、その画像をダウンロードし、Marp形式マークダウンに統合してもいいのですが、私は面倒くさがりなので、上記を1コマンドでできるといいなと思いました。

ということでこれを作成していくのが本ブログの本題となります。

Marp形式ファイルを自動生成しさらにイラストを自動で追加する

ここまでは技術登壇資料を例に試してきましたが、ここからは提案書作成を題材に実装していきます。ちょうど直近で提案書を作る機会があったからです。

ユースケースとしては顧客と初回MTGを完了しその議事録を元に顧客に対して提案書を作るというシーンを想定しています。そのためインプットとなる情報は顧客とのMTG議事録です。

Nano Banana Proは今回はVertex AIを使ってAPI形式で呼ぶ方式でやってみます。全体の構成としてはこんな感じです。

Gemini API呼び出しの部分は今回はClaude CodeのAgent Skills機能で実装することにしました。他にMCPサーバーとして実装する案も考えましたが、やることが画像生成だけと決まっているので単純にスクリプトでAPI実行したほうがシンプルだし実装が複雑にならないだろうと考えたからです。

もう少し詳細なフローにすると以下のような形で一連の処理を実行していきます。

カスタムスラッシュコマンド

それではまずは、カスタムスラッシュコマンドから作っていきましょう。

カスタムスラッシュコマンドはcc-sddの書き方が参考になると感じており、最近はこの書き方にしています。

ポイントとしては処理とルールとテンプレートをそれぞれファイルとして分けるということです。

今回は以下のような構成にしました。

marp-proposal-creation/
├── commands
│   └── marp-tech-proposal.md # カスタムスラッシュコマンド
├── rules
│   ├── image-prompt-guidelines.md # Nano Banana Pro用の画像生成プロンプト指針
│   └── proposal-structure-rules.md # 提案書スライドの構成ルール(セクション構成など)
└── templates
    ├── sample-slide.md # Marp classmethodテーマのサンプルスライド
    └── tech-proposal-slide.md # 技術提案書用のスライドテンプレート(Marp形式)

カスタムスラッシュコマンドの中身は以下のような構成です。これもcc-sddの書き方を参考にしました。

  • background_information: このコマンドのミッションと成功基準を定義
  • 実行ステップ:このコマンドで実行する手順を定義
    • ステップ0: ルールとテンプレートの読み込み
    • ステップ1: 入力ファイルの読み込みと分析
    • ステップ2: 可変セクションの設計
    • ステップ3: Marp形式スライド生成
    • ステップ4: 画像生成と置換(Skill呼び出し)
  • 重要な制約: スライド生成時に守るべきルール(固定セクションの変更禁止、必須のfrontmatter、機密情報の取り扱いなど)を定義
  • 補足情報: Claude Codeが使用できる各ツールをどの用途で使用するかのガイダンスやエラー時の対応を記載

上記の構成で書いた実際のカスタムスラッシュコマンドがこちらです。

marp-tech-proposal.md(クリックで展開)
---
description: MTG議事録からMarp形式のIT技術支援提案書スライドを自動生成
allowed-tools: ["Read", "Write", "Edit", "Glob", "Bash(mkdir:*)", "Skill", "AskUserQuestion"]
argument-hint: <ファイル1> [ファイル2] ... [--out 出力ディレクトリ]
---

# MTG議事録からIT技術支援提案書スライド生成

<background_information>
- **ミッション**: 顧客MTG議事録を分析し、Marp形式の技術支援提案書スライドを生成
- **成功基準**:
  - 議事録から課題・要件を正確に抽出
  - Marp形式で即座にプレビュー可能なスライドを出力
  - 固定セクション(その他〜最終)は一切変更しない
</background_information>

<instructions>
## 実行ステップ

### ステップ0: ルールとテンプレートの読み込み

**最初に以下のファイルを読み込む**:
- `{{CLAUDE_DIR}}/commands/marp-proposal-creation/rules/proposal-structure-rules.md` - 提案書構成ルール
- `{{CLAUDE_DIR}}/commands/marp-proposal-creation/rules/image-prompt-guidelines.md` - 画像プロンプト作成ガイドライン
- `{{CLAUDE_DIR}}/commands/marp-proposal-creation/templates/tech-proposal-slide.md` - スライドテンプレート
- `{{CLAUDE_DIR}}/commands/marp-proposal-creation/templates/sample-slide.md` - Marpテーマの書き方サンプル

### ステップ1: 入力ファイルの読み込みと分析

**引数**: 複数ファイル指定可、`--out` で出力ディレクトリ指定

/marp-proposal-creation:marp-tech-proposal mtg-notes.md requirements.md --out ./output

**処理**:
1. 指定されたファイルをすべて Read ツールで読み込む
2. 各ファイルから以下の要素を抽出・統合:
   - **顧客名**: 議事録から顧客名を特定
   - **課題**: 顧客が抱える課題・ペイン
   - **要件**: 明示された要件や要望
   - **制約**: 予算、期間、技術的制約
   - **決定事項**: MTGで決まったこと
3. **不明な要素がある場合**: AskUserQuestion で確認

### ステップ2: 可変セクションの設計

抽出した情報を基に、**可変セクション**(表紙〜スケジュール)の内容を設計:

- **表紙**: タイトル、顧客名、日付
- **はじめに**: 背景・経緯、現状の課題、目的
- **ご提案内容**: 主要項目、各項目の詳細(実施内容・期待効果)
- **スケジュール**: 支援期間、マイルストーン

※ 案件に応じてスライド数・構成は自由に変更可

### ステップ3: Marp形式スライド生成

#### 図を挿入すべきスライドの判断

| 優先度 | スライド種別 | Mermaid構文 |
|--------|-------------|-------------|
| **推奨** | スケジュール | `gantt` |
| **推奨** | アーキテクチャ系 | `graph TD` / `sequenceDiagram` |
| **推奨** | フロー系 | `flowchart LR` / `flowchart TD` |
| 任意 | テキスト中心 | 画像なしでもOK |

**重要**: `content-image-right` クラスのスライドには**必ず図を入れる**(レイアウト崩れ防止)

#### 図の記述方法

**原則: Mermaidコードブロック**

※ ネスト内のコードブロック記法(```mermaid〜```)は表示の都合上省略しています。以降のコード例も同様です。

markdown
gantt
    title プロジェクトスケジュール
    dateFormat YYYY-MM
    section フェーズ1
    タスク1    :2025-12, 1M

**フォールバック: IMAGEコメント**(Mermaidで表現困難な場合のみ)

markdown
<!-- IMAGE: AWS Organizations OU構造図。Root配下にSecurityOU、WorkloadsOUがあり、それぞれにアカウントが配置 -->

#### スライド出力

1. テンプレートを基に、可変セクションのプレースホルダーを置換
2. 固定セクション(`## その他` 以降)はテンプレートから**そのままコピー**
3. 図が必要な箇所に**Mermaidコードブロック**または**IMAGEコメント**を挿入
4. 出力先: `--out` 指定時はそのディレクトリ、なければ入力ファイルと同じディレクトリ
5. ファイル名: `proposal_{顧客名}_{YYYYMMDD}.md`

### ステップ4: 画像生成と置換

**目的**: ステップ3で挿入したMermaid/IMAGEコメントを実際の画像に置換

**実行手順**:
1. `mkdir -p {出力ディレクトリ}/images` で画像出力先を作成
2. `Skill(skill: "gemini-image")` を呼び出し
3. スライド内のMermaidコードブロック/IMAGEコメントを検出
4. **Mermaidコードを直接プロンプトに含めて**画像生成を依頼
5. 生成した画像でMermaid/IMAGEコメントを置換

#### Mermaidからプロンプトを作成する方法

**重要**: Mermaidコードブロックを検出したら、そのコードを**そのまま**プロンプトに含めてgemini-imageに渡す

**プロンプトテンプレート**`image-prompt-guidelines.md`より):

以下のMermaid図をビジネス向けの図解にしてください。

[検出したMermaidコードをそのまま貼り付け]

要件:
- シンプルなボックスと矢印
- フラットデザイン、ビジネススタイル
- 白背景

**スケジュール図の場合**:

以下のMermaidガントチャートコードをビジネス向けスケジュール表の画像にしてください。

[検出したganttコードをそのまま貼り付け]

要件:
- ヘッダーに月名を表示
- タスクは色分けされた水平バー
- クリーンなビジネステーブルスタイル、白背景

#### 置換ルール

| 検出対象 | 置換後 |
|----------|--------|
| ` ```mermaid gantt ... ``` ` | `![w:600px](images/schedule.png)` |
| ` ```mermaid graph TD ... ``` ` | `![w:400px](images/ou_structure.png)` |
| `<!-- IMAGE: ... -->` | `![w:400px](images/xxx.png)` |

**サイズ目安**: 全幅表示 `w:600px``w:700px` / 右側配置 `w:400px``w:500px`

## 重要な制約
- **絶対禁止**: 固定セクション(`## その他` 以降)の変更
- **必須**: Marp frontmatter(marp: true, theme: classmethod, paginate: true)
- **禁止**: 顧客固有の機密情報をスライド以外に出力しない
</instructions>

## 補足情報

**ツール使用**:
- **Read**: ルール・テンプレート・入力ファイル読み込み
- **Write**: スライドファイル初期出力
- **Edit**: 画像生成後のスライド更新
- **Skill**: gemini-image で画像生成

**エラー時**:
- ファイル読み込みエラー → ユーザーに通知
- 出力ディレクトリなし → `mkdir` で作成
- 構成不明 → 汎用的な提案書構成をデフォルト使用

$ARGUMENTS

ポイントとしてはステップ1の議事録などを読み込んだ際に不明な点があればユーザーに確認するようにしているところでしょうか。

また技術提案書用のスライドテンプレートの中で変更してもよい部分と、固定にしてほしい部分をはっきりさせ、変更してもよい部分だけを修正させるようにしています。

ステップ4の画像生成のところが一番頭を悩ませた部分です。特に提案書上のスケジュールの部分も画像として生成させようと試行錯誤したのですが、簡素な絵になったり、どの作業項目のスケジュールかを明記してくれなかったり(アイコンで項目を表していた)と難儀しました。

散々悩んだ結果、ステップ3のMarp形式スライド生成の時点でMermaid記法を使った図をClaude Codeに作らせておくことを思いつきました。そして画像生成のステップでは、そのMermaid図をまるごと渡してMermaid図をもとに画像生成させるようにしたところ画像の品質が安定するようになりました。

具体的には、画像生成用pythonプログラムに以下のようなプロンプトを渡しています。もちろんプロンプトはClaude Codeが自動生成しています。

 以下のMermaidガントチャートコードをビジネス向けスケジュール表の画像にしてください。

 gantt
     title Project Schedule
     dateFormat YYYY-MM
     section Requirements & Design
     Requirements Definition  :a1, 2030-03, 1M
     Basic Design            :a2, 2030-04, 1M
     section Infrastructure
     AWS Environment Setup   :b1, 2030-04, 2M
     section Development
     Phase1 Product Browse   :c1, 2030-05, 2M
     Phase2 Cart Payment     :c2, 2030-06, 2M
     Phase3 Member Features  :c3, 2030-07, 2M
     section Migration
     Test & Migration        :d1, 2030-09, 1M
     Production Release      :d2, 2030-10, 1M

 要件:
 - ヘッダーに月名(Mar, Apr, May, Jun, Jul, Aug, Sep, Oct)を表示
 - タスクは色分けされた水平バー
 - セクション名は左側に太字表示
 - クリーンなビジネステーブルスタイル、白背景
 - ラベルは英語で表示

Mermaid記法をそのままプロンプトで渡したほうが品質が安定するというのが今回の最大の気づきでした。

Agent Skill

画像生成は上述の通りClaude CodeのAgent Skill機能を使って実装しています。

ファイルとしてはスキル内容が書かれたSKILL.mdとVertex AI経由でGemini APIを呼び出すgemini_image.pyの2つのみです。

SKILL.md

これは私の解釈なのでもしかしたら間違っているのかもしれませんが、Agent SkillはClaudeモデルが読む「ツールやワークフローの説明書」と捉えています。モデルがタスクを受けた際、必要に応じてSKILL.mdを読み込み、使用方法を理解した上でツール(今回はgemini_image.py)を実行します。

そのため、SKILL.mdにはgemini_image.pyの引数やスタイルオプションなど「実行方法」を記載しています。一方、画像生成に渡すプロンプト文の作成は、プロンプトの内容・品質は呼び出し側が責任を持つとして、このスキルの責任範囲外としています。呼び出し元のモデルがユーザーの要求を解釈し、適切なプロンプトを組み立てることとしているわけです。

正直カスタムスラッシュコマンドからgemini_image.pyを直接呼び出す形でもいいのかもと思っていますが、skillにしておけば後々別のプロンプトでも使いまわしがしやすいかもと思ってskillで実装しています。

SKILL.md(クリックで展開)
---
name: gemini-image
description: Gemini API(Nano Banana Pro)で画像生成。Marpスライド、ドキュメント、提案書用の技術図解・アーキテクチャ図・アイコン・写真を作成する際に使用。
allowed-tools: Bash(~/.local/bin/adc-run uv run {SKILL_DIR}/scripts/gemini_image.py:*)
---

# Gemini画像生成Skill

Vertex AI Gemini APIを使用した画像生成。

## 役割

**このSkillは「プロンプトを受け取り、画像を生成する」だけ**。
プロンプトの内容・品質は呼び出し側が責任を持つ。

## Usage

adc-run uv run {SKILL_DIR}/scripts/gemini_image.py "PROMPT" OUTPUT_PATH [--style STYLE]

### 引数

| 引数 | 必須 | 説明 |
|------|------|------|
| `PROMPT` | Yes | 画像生成プロンプト |
| `OUTPUT_PATH` | Yes | 出力ファイルパス(.png) |
| `--style STYLE` | No | スタイルプリセット(下記参照) |

**注意**: 画像内に描画されるテキストは英語推奨(日本語は文字化けリスクあり)

### スタイルオプション

| Style | 用途 |
|-------|------|
| `diagram` | アーキテクチャ図、フローチャート(デフォルト) |
| `icon` | シンプルなフラットアイコン |
| `illustration` | アイソメトリックなビジネスイラスト |
| `photo` | フォトリアリスティック画像 |

## Examples

# スケジュール図(日本語プロンプト推奨)
adc-run uv run {SKILL_DIR}/scripts/gemini_image.py \
  "以下の内容でガントチャート形式のスケジュール図を作成。期間: 12月〜3月。作業項目: 設計(12月)、実装(1-2月)、テスト(3月)。横向きバーチャート、シンプルなビジネススタイル、白背景" \
  ./images/schedule.png --style diagram

# アーキテクチャ図(英語でもOK)
adc-run uv run {SKILL_DIR}/scripts/gemini_image.py \
  "Three-tier architecture diagram with API Gateway, Lambda, DynamoDB" \
  ./images/arch.png --style diagram

# アイコン
adc-run uv run {SKILL_DIR}/scripts/gemini_image.py \
  "Cloud security shield icon, minimal flat design" \
  ./images/security.png --style icon

## 制限事項

- 複雑な図は品質低下の可能性
- APIレート制限あり

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

| 問題 | 解決策 |
|------|--------|
| 認証エラー | `adc-run`がブラウザで自動ログイン処理 |
| 生成失敗 | プロンプトを簡潔に、不適切コンテンツ確認 |
| レート制限 | 少し待って再実行 |

gemini_image.py

こちらがNano Banana Proによる画像生成を行うためのキモになるプログラムです。

gemini_image.py(クリックで展開)
#!/usr/bin/env python3
# /// script
# requires-python = ">=3.10"
# dependencies = [
#     "google-genai>=0.3.0",
# ]
# ///
"""
Gemini API Image Generation Script for Claude Code Skills

Usage:
    adc-run uv run gemini_image.py "プロンプト" output.png [--style diagram|icon|illustration|photo]

Authentication:
    Uses Google Cloud Application Default Credentials (ADC) via Vertex AI.
    Run with adc-run wrapper for automatic login/logout.

Styles:
    diagram      - AWS/Cloud style technical diagram (default)
    icon         - Simple flat icon, minimal design
    illustration - Modern isometric business illustration
    photo        - Photorealistic image
"""

import argparse
import base64
import os
import sys
from pathlib import Path

# Default location for Vertex AI (global for image generation models)
DEFAULT_LOCATION = "global"


def generate_image(prompt: str, output_path: str, style: str = "diagram") -> None:
    """Generate image using Gemini API and save to file."""

    # Lazy import to allow script metadata to work with uv
    from google import genai
    from google.genai import types

    # Style-specific prompt enhancements
    style_prompts = {
        "diagram": "Clean technical diagram, flat design, AWS/cloud style icons, white background, professional presentation style, no text labels, simple geometric shapes",
        "icon": "Simple flat icon, minimal design, single color accent, white background, vector style, clean edges",
        "illustration": "Modern business illustration, isometric style, soft pastel colors, professional, clean design",
        "photo": "High quality photograph, professional, sharp focus, good lighting"
    }

    style_suffix = style_prompts.get(style, style_prompts["diagram"])
    full_prompt = f"{prompt}. Style: {style_suffix}"

    print(f"Generating image with style '{style}'...", file=sys.stderr)
    print(f"Prompt: {full_prompt[:100]}...", file=sys.stderr)

    try:
        # Use ADC (Application Default Credentials) via Vertex AI
        project = os.environ.get("GOOGLE_CLOUD_PROJECT")  # None -> auto-detect from ADC
        location = os.environ.get("GOOGLE_CLOUD_LOCATION", DEFAULT_LOCATION)
        client = genai.Client(
            vertexai=True,
            project=project,
            location=location
        )

        response = client.models.generate_content(
            model="gemini-3-pro-image-preview",  # Nano Banana Pro
            contents=full_prompt,
            config=types.GenerateContentConfig(
                response_modalities=["image", "text"]
            )
        )

        # Extract image from response
        for part in response.candidates[0].content.parts:
            if part.inline_data:
                # Ensure output directory exists
                output_file = Path(output_path)
                output_file.parent.mkdir(parents=True, exist_ok=True)

                # Get image data (may be bytes or base64 string depending on API version)
                data = part.inline_data.data
                if isinstance(data, bytes):
                    image_data = data
                elif isinstance(data, str):
                    image_data = base64.b64decode(data)
                else:
                    print(f"Error: Unexpected data type: {type(data)}", file=sys.stderr)
                    sys.exit(1)

                with open(output_file, "wb") as f:
                    f.write(image_data)

                print(f"✅ Generated: {output_path}")
                return

        # No image in response
        print("Error: No image was generated in the response", file=sys.stderr)

        # Check if there's text response (might contain error message)
        for part in response.candidates[0].content.parts:
            if hasattr(part, 'text') and part.text:
                print(f"Response text: {part.text}", file=sys.stderr)

        sys.exit(1)

    except Exception as e:
        print(f"Error generating image: {e}", file=sys.stderr)
        sys.exit(1)


def main():
    parser = argparse.ArgumentParser(
        description="Generate images using Gemini API",
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog=__doc__
    )
    parser.add_argument(
        "prompt",
        help="Image generation prompt"
    )
    parser.add_argument(
        "output",
        help="Output file path (e.g., images/diagram.png)"
    )
    parser.add_argument(
        "--style",
        choices=["diagram", "icon", "illustration", "photo"],
        default="diagram",
        help="Image style preset (default: diagram)"
    )

    args = parser.parse_args()
    generate_image(args.prompt, args.output, args.style)


if __name__ == "__main__":
    main()

ポイントだけ説明します。

        client = genai.Client(
            vertexai=True,
            project=project,
            location=location
        )

Google Cloud の Gemini API に接続するためにクライアントを初期化している部分です。

vertexai=Trueとすることで、Vertex AI API エンドポイントを使用することができます。Vertex AIとはGoogle CloudのマネージドAI/MLプラットフォームで、Geminiを含む各種モデルを利用できるサービスです。

またこちらをFalseにした場合は、Gemini Developer API エンドポイントを使用するという挙動になります。こちらはGoogle AI Studio(Googleが提供する生成AIを開発・実験するためのウェブベースのプラットフォーム)経由で提供される、Geminiモデルに直接アクセスするための開発者向けAPIです。こちらはどちらかというと個人向けのユースを想定しており、Vertex AIで使用する場合と比較してエンタープライズ向け機能等が利用できない等の違いがあります。

https://docs.cloud.google.com/vertex-ai/generative-ai/docs/migrate/migrate-google-ai?hl=ja

私は今回、ADC(Application Default Credentials)で認証して使いたかったのでVertex AIで利用しています。

        response = client.models.generate_content(
            model="gemini-3-pro-image-preview",  # Nano Banana Pro
            contents=full_prompt,
            config=types.GenerateContentConfig(
                response_modalities=["image", "text"]
            )
        )

gemini-3-pro-image-previewがNano Banana Proを利用する場合のモデル名になります。

config=〜の部分は生成する際の設定を記載するもので、["image", "text"]とすることで画像データを生成してレスポンスに含め、テキスト説明も一緒に返すという挙動になります。

このように設定することでレスポンスの構造としては以下のようになります。

response.candidates[0].content.parts[
    # Part 1: 画像データ
    {inline_data: {data: <base64 or bytes>, mime_type: "image/png"}},
    # Part 2: テキスト(オプション)
    {text: "Generated description..."}
]

後続の処理でこのレスポンスから画像データを取り出してファイル保存している形です。

ルールファイル

image-prompt-guidelines.md

このルールファイルはgemini_image.pyにわたすプロンプトの作成指針を書いたものです。

カスタムスラッシュコマンドに書いている内容と重複している部分が多いので、もしかしたらいらないかも?という気はしています。

image-prompt-guidelines.md(クリックで展開)
# 提案書向け画像プロンプトガイドライン

gemini-image Skill を使用して提案書向け画像を生成する際のプロンプト作成ガイドライン。

## 基本方針

- 提案書の図は **シンプル・ビジネス的・わかりやすい** が最優先
- **Mermaidコードを直接プロンプトに含める**のが推奨方式

## プロンプト言語について

- **プロンプト自体**: 日本語OK(具体的な内容を正確に伝えられる)
- **Mermaidコード内の日本語ラベル**: 問題なく描画可能

---

## Mermaidコードからの画像生成(推奨)

### なぜMermaidを使うか

| メリット | 詳細 |
|---------|------|
| **構造化された入力** | Mermaidは構造定義済み、プロンプトが簡潔 |
| **一貫性** | Mermaid記法に従えば品質が安定 |
| **自動化可能** | スライド内のMermaidコードを検出→自動画像生成 |

### 対応するMermaid図の種類

| 図の種類 | Mermaid構文 | 用途 |
|---------|------------|------|
| スケジュール | `gantt` | プロジェクトスケジュール |
| フローチャート | `flowchart LR/TD` | 運用フロー、プロセスフロー |
| 組織図・階層図 | `graph TD` | OU構造、組織体制 |
| シーケンス図 | `sequenceDiagram` | 認証フロー、API連携 |

---

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

### 汎用テンプレート(フロー図・階層図)

以下のMermaid図をビジネス向けの図解にしてください。

[検出したMermaidコードをそのまま貼り付け]

要件:
- シンプルなボックスと矢印
- フラットデザイン、ビジネススタイル
- 白背景

### スケジュール図(gantt)用テンプレート

以下のMermaidガントチャートコードをビジネス向けスケジュール表の画像にしてください。

[検出したganttコードをそのまま貼り付け]

要件:
- ヘッダーに月名を表示
- タスクは色分けされた水平バー
- セクション名は左側に太字表示
- クリーンなビジネステーブルスタイル、白背景

---

## 実例

### 実例1: スケジュール(gantt)

**Mermaidコード**:
mermaid
gantt
    title プロジェクトスケジュール
    dateFormat YYYY-MM
    section 運用フロー整備
    手順書作成           :a1, 2025-12, 1M
    運用開始             :a2, after a1, 1M
    section OU移動・SCP適用
    影響調査             :b1, 2025-12, 1M
    アカウント移動実施   :b2, after b1, 1M

**プロンプト**:
以下のMermaidガントチャートコードをビジネス向けスケジュール表の画像にしてください。

gantt
    title プロジェクトスケジュール
    dateFormat YYYY-MM
    section 運用フロー整備
    手順書作成           :a1, 2025-12, 1M
    運用開始             :a2, after a1, 1M
    section OU移動・SCP適用
    影響調査             :b1, 2025-12, 1M
    アカウント移動実施   :b2, after b1, 1M

要件:
- ヘッダーに月名(12月, 1月, 2月)を表示
- タスクは色分けされた水平バー
- クリーンなビジネステーブルスタイル、白背景

### 実例2: 運用フロー(flowchart LR)

**Mermaidコード**:
mermaid
flowchart LR
    A[Security Alert] --> B[CCoE Triage]
    B --> C[Account Team Response]
    C --> D[Resolution]

**プロンプト**:
以下のMermaid図をビジネス向けの図解にしてください。

flowchart LR
    A[Security Alert] --> B[CCoE Triage]
    B --> C[Account Team Response]
    C --> D[Resolution]

要件:
- 左から右への流れ
- シンプルなボックスと矢印
- フラットデザイン、ビジネススタイル
- 白背景


---

## Mermaid記述のベストプラクティス

| 項目 | 推奨 |
|------|------|
| ノード名 | 短く簡潔に |
| 階層 | 3-4レベルまで |
| タスク数(gantt) | 8個程度まで |
| 期間(gantt) | 6ヶ月程度まで |

**矢印の種類**:
- `-->` 実線矢印(基本)
- `-.->` 点線矢印(補助的な流れ)
- `==>` 太線矢印(重要な流れ)

---

## 避けるべきこと

| NG | 理由 |
|----|------|
| `"beautiful"`, `"artistic"` | 装飾的になりすぎる |
| `"photorealistic"`, `"3D render"` | 提案書に不適切 |
| Mermaid構文エラー | AIが解釈できない |

---

## 図の種類別スタイル指定

| 図の種類 | --style オプション |
|----------|-------------------|
| アーキテクチャ図 | `diagram` |
| フローチャート | `diagram` |
| 組織図・体制図 | `diagram` |
| スケジュール | `diagram` |
| アイコン単体 | `icon` |
| イラスト(人物含む) | `illustration` |

proposal-structure-rules.md

このルールファイルは提案書スライドを作成する際のルールを記載したものです。(一部、実際に使用している内容を含むので割愛しています)

この中で可変部分と固定部分について定義してあります。またClassmethod Marpテーマ特有の記法についても記載しています。

proposal-structure-rules.md(クリックで展開)
# 提案書スライド構成ルール

IT技術支援提案書スライドの構成に関する制約とルール。

## 基本原則

### 1. 固定セクションと可変セクションの分離
提案書は「可変セクション」と「固定セクション」で構成される。固定セクションは**絶対に変更してはならない**### 2. 固定セクションの完全性
固定セクションの文言・構成・順序は一切変更しない。プレースホルダーの使用も禁止。

### 3. 可変セクションの柔軟性
可変セクションは案件の内容に応じて自由に構成を変更してよい。

## スライド構成

### 可変セクション(自由に構成変更可)

以下のセクションは案件に応じて自由に構成・内容を変更してよい:

1. **表紙**
2. **はじめに**(背景、経緯、目的など)
<他にも項目あり>

### 固定セクション(変更禁止)

`## その他` 以降のセクションは**構成・文言ともに変更禁止**。テンプレートからそのままコピーすること。

<複数項目あり>

4. **最終スライド**(クラスメソッドロゴ)

## classmethod Marpテーマの書き方

**重要**: 通常のMarp記法とは異なる。必ず `sample-slide.md` を参照し、classmethod テーマの書き方に忠実に従うこと。

### `_class` 指定(必須)

スライドの種類に応じて `<!-- _class: xxx -->` を指定する:

| クラス | 用途 |
|--------|------|
| `title` | 表紙スライド |
| `section` | 中扉・セクション区切り |
| `image` | 図のみ表示 |
| `content-image` | タイトル・図・テキスト |
| `content-image-right` | 図が右側(`content-60` 等で幅調整可) |
| `content-image-left` | 図が左側 |
| `column-layout` | 横並びカラム |
| `no-header` | ヘッダーなし |
| `all-text-center` | 全テキスト中央揃え |
| `align-center` | 縦方向中央揃え |

### ページネーション制御

- `<!-- _paginate: false -->`: ページ番号非表示(表紙、セクション区切り等)

### 画像サイズ指定

markdown
![w:400px](https://devio2024-2-media.developers.io/upload/6J1Kx9HsuVLaf9qI3wWU3k/2025-12-03/1wt4ZZOUMGwZ.png)  # 幅400px
![h:300px](https://devio2024-2-media.developers.io/upload/6J1Kx9HsuVLaf9qI3wWU3k/2025-12-03/xkLzHWX5Xhhc.png)  # 高さ300px

### 見出しのアクセントカラー

markdown
## 見出しの一部を**青色のアクセントカラー**にする

## 品質チェックリスト

- [ ] 固定セクションがテンプレートと完全一致しているか
- [ ] 固定セクションの順序が正しいか
- [ ] `## その他` 以降の構成が変更されていないか
- [ ] 最終スライドがクラスメソッドロゴになっているか

## 避けるべきアンチパターン

- ❌ 固定セクションの文言を「改善」しようとする
- ❌ 固定セクションにプレースホルダーを入れる
- ❌ 固定セクションの順序を入れ替える
- ❌ 固定セクション内にスライドを追加・削除する

テンプレート

sample-slide.md

これはClassmethod Marpテーマを使ったサンプルのMarp形式マークダウンファイルになっています。

ルールファイルに記法が書いてあるのでいらないかもしれないです。内容は以下のリポジトリのものと同一です。

https://github.com/classmethod/classmethod-marp-theme/blob/main/sample-slide.md

tech-proposal-slide.md

このファイルは私が所属している部署で標準的に使用している提案書テンプレートをMarp形式マークダウンファイルにしたものとなっています。

実際に使用している提案書テンプレートの内容を含むので公開することはできませんが、中身としては必要となる目次構成や固定文言等が記載されている形です。

実際に使ってみる

それでは完成したカスタムスラッシュコマンドを実際に使ってみましょう。

今回は以下のような仮想の顧客とやり取りしたMTG議事録を使用しました。

サンプルMTG議事録(クリックで展開)
# ECサイトリニューアル 要件整理ミーティング

**日時**: 2030年2月15日(土)14:00-16:00
**参加者**:
- 株式会社サンプルマート様:鈴木部長、田中様(EC担当)
- テックパートナー株式会社:山田(PM)、佐藤(インフラ)

---

## ミーティングの目的

1. 現行ECサイトの課題を整理
2. リニューアル後の理想状態を確認
3. 技術的なアプローチの方向性を決定
4. 概算スケジュールの合意

---

## 1. 現行システムの課題

### 1.1 ビジネス面の課題

| 課題 | 現状 | 影響 |
|------|------|------|
| **ページ表示速度** | 商品一覧ページで平均4.5秒 | 離脱率が高い(直帰率65%) |
| **スマホ対応** | レスポンシブ非対応、PC表示のまま | モバイルユーザー(70%)の体験が悪い |
| **セール時の負荷** | 月末セール時にサーバーダウン頻発 | 機会損失、顧客クレーム |
| **在庫連携** | 手動でCSVアップロード(1日2回) | 在庫切れ商品の注文が発生 |

### 1.2 技術面の課題

- **サーバー構成**: オンプレミスの単一サーバー(5年前に構築)
- **CMS**: 独自開発のPHPアプリケーション(ドキュメントなし)
- **データベース**: MySQL 5.6(サポート終了)
- **インフラ運用**: 社内に専任担当者不在、障害時は外部ベンダーに都度依頼

### 1.3 直近で発生したインシデント

1. **2029年12月セール時のダウン**
   - 原因:アクセス集中によるDBコネクション枯渇
   - 復旧まで3時間、推定損失500万円

2. **2030年1月の在庫不整合**
   - 原因:CSV連携の遅延により、在庫切れ商品が購入可能状態に
   - 影響:50件の注文キャンセル対応、顧客へのお詫びクーポン発行

---

## 2. リニューアル後の理想状態

### 2.1 お客様からのご要望

#### パフォーマンス
- ページ表示速度:2秒以内
- セール時(通常の10倍アクセス)でも安定稼働
- 99.9%の可用性

#### 機能面
- スマホファースト設計
- 在庫のリアルタイム連携(基幹システムとAPI連携)
- 商品レコメンド機能の追加
- 会員ランク制度の導入

#### 運用面
- コンテンツ更新を社内で完結したい(バナー、特集ページ等)
- 障害時の自動復旧
- アクセス状況の可視化ダッシュボード

#### 予算・スケジュール
- 予算:3,000万円以内
- 本番稼働:2030年10月(繁忙期前)
- 段階的なリリースも可

---

## 3. 技術アプローチの検討

### 3.1 インフラ構成案

#### 案A:AWSフルマネージド構成(推奨)
- **フロントエンド**: CloudFront + S3(静的コンテンツ)
- **アプリケーション**: ECS Fargate(コンテナ)
- **データベース**: Aurora MySQL Serverless v2
- **キャッシュ**: ElastiCache(Redis)
- **検索**: OpenSearch Service

**メリット**:
- オートスケーリングでセール時も自動対応
- マネージドサービス中心で運用負荷軽減
- 従量課金で初期コスト抑制

**デメリット**:
- AWSの学習コストが発生
- 月額ランニングコストの見積もりが変動

#### 案B:Shopify Plus + カスタム連携
- **ECプラットフォーム**: Shopify Plus
- **基幹連携**: カスタムアプリ開発
- **追加機能**: Shopifyアプリで対応

**メリット**:
- 構築期間短縮(3-4ヶ月)
- EC機能は標準で充実

**デメリット**:
- 月額利用料が高い(約50万円/月)
- カスタマイズに制限あり
- 基幹連携の複雑さ

### 3.2 アプリケーション構成案

| 項目 | 推奨案 |
|------|--------|
| フレームワーク | Next.js(React)+ TypeScript |
| CMS | Contentful(ヘッドレスCMS) |
| 決済 | Stripe |
| 認証 | Amazon Cognito |
| 在庫連携 | API Gateway + Lambda + SQS |

### 3.3 移行戦略

1. **並行稼働期間を設ける**
   - 新旧システム並行で2週間運用
   - 問題なければ完全切り替え

2. **段階的リリース**
   - Phase 1(7月): 商品閲覧・検索機能
   - Phase 2(8月): カート・決済機能
   - Phase 3(9月): 会員機能・レコメンド
   - Phase 4(10月): 本番切り替え

---

## 4. 概算見積もり

### 4.1 初期構築費用

| 項目 | 工数 | 金額 |
|------|------|------|
| 要件定義・設計 | 2ヶ月 | 400万円 |
| インフラ構築 | 1.5ヶ月 | 300万円 |
| アプリケーション開発 | 4ヶ月 | 1,200万円 |
| 基幹システム連携開発 | 1.5ヶ月 | 350万円 |
| テスト・移行 | 1ヶ月 | 250万円 |
| **合計** | - | **2,500万円** |

### 4.2 月額ランニングコスト(概算)

| 項目 | 月額 |
|------|------|
| AWSインフラ | 30-50万円(トラフィックにより変動) |
| Contentful | 5万円 |
| 監視・運用サポート | 15万円 |
| **合計** | **50-70万円** |

---

## 決定事項

- 技術アプローチは**案A(AWSフルマネージド構成)**を採用
- アプリケーションは**Next.js + Contentful**で構築
- スケジュールは**段階的リリース**方式で進める
- 本番稼働目標は**2030年10月1日**
- 次回MTGまでに詳細見積もりと提案書を作成

---

## ネクストアクション

### お客様側

- [ ] 基幹システムのAPI仕様書の共有(田中様)
- [ ] 現行サイトのアクセスログ提供(田中様)
- [ ] 会員ランク制度の要件詳細化(鈴木部長)
- [ ] 社内稟議スケジュールの確認(鈴木部長)

### 弊社側

- [ ] 詳細見積書の作成(山田)3月1日まで
- [ ] AWSアーキテクチャ図の作成(佐藤)3月1日まで
- [ ] 技術提案書の作成(山田・佐藤)3月5日まで
- [ ] Contentfulデモ環境の準備(佐藤)次回MTGまで

---

## 次回ミーティング

- **日時**: 2030年3月8日(土)14:00-16:00
- **場所**: オンライン(Zoom)
- **アジェンダ**: 詳細見積もり説明、アーキテクチャ説明、Q&A

これを引数として以下のように実行します。

/marp-proposal-creation:commands:marp-tech-proposal  /tmp/sample_meeting_notes_ec_renewal.md ./test.md

完成した提案書がこちらです。(冒頭の部分だけお見せします)

alt text
alt text
alt text
alt text
alt text
alt text
alt text
alt text
alt text

いかがでしょうか?この提案書はカスタムスラッシュコマンド一発実行しただけで一切の編集をしてないものです。一発でこのレベルの提案書が作成でき、また編集も容易であればかなり実用レベルではないかなと個人的には思います。

まとめ

本記事では、Claude CodeとNano Banana Pro(Gemini 3 Pro Image)を組み合わせて、MTG議事録から提案書スライドを自動生成する仕組みを紹介しました。

ポイントの振り返り

  1. NotebookLMのスライド生成は便利だが修正が大変

    • 一発出しのため、部分修正が難しい
    • 生成に時間がかかる
  2. Claude Code + Nano Banana Proの組み合わせで解決

    • Marp形式マークダウンで編集容易性を確保
    • 必要な箇所だけNano Banana Proで画像生成
  3. Mermaid記法をプロンプトに直接渡すと品質が安定する

    • スケジュール図やフローチャートはMermaidで構造を定義
    • その構造をそのままGemini APIに渡して画像化

今後の展望

今回は提案書作成を題材にしましたが、同様のアプローチは技術登壇資料やドキュメント作成など、様々な場面で応用できると思います。

Nano Banana Proの画像生成能力は日々進化しており、今後さらに高品質な図解が生成できるようになることを期待しています。

ぜひ皆さんも、自分の業務に合わせたカスタムスラッシュコマンドを作成してみてください。

以上、とーちでした。

この記事をシェアする

FacebookHatena blogX

関連記事