はじめに こんにちは。Insight Edgeでデータサイエンティストをしている善之です。 AIでのPowerPoint資料の作成、みなさんも一度は試したことがあるのではないでしょうか。そして、こんな悩みを感じたことはありませんか? 「生成されたスライドを、手作業で自由に編集できない…」 「デザインがイマイチ…」 「一見かっこいいけど、自分のいつものデザインではないので、編集しづらいし内容も頭に入ってこない…」 私も同じ悩みを抱えながら、AIを使ったスライド生成をあれこれ試してきました。そして試行錯誤の末、 「いつもの自分が作成したかのような」スライドを自動生成する ことで、これらの問題を解決できました。 まず、実際にClaude Codeで作成したスライドの例をお見せします。 ※ 本記事用に用意した架空プロジェクト(食品スーパーの需要予測AI導入検討)のサンプルスライドです どれも私が以前から手作業で作っていたスライドとよく似ていて、「私が手作業で作成した」と言っても気づかない同僚が多いと思います。 「自分のいつものフォーマット」にこだわる理由は2つあります。 内容が理解しやすく、良し悪しをすぐ判断できる :いつもの自分のフォーマットで出てくるので、自分にとって(おそらく周囲にとっても)内容が理解しやすく、成果物の良し悪しもすぐに判断できます 修正したい時も、いつもの作業ですぐ直せる :生成物がネイティブなPowerPointオブジェクトで、かつ見慣れたフォーマットなので、テキストの微修正も表の組み替えも普段どおりの操作で完結します 逆に、「他人が作った感」のあるスライドは、一部だけ直したいときにも、どう直せば全体のデザインバランスが保てるのかがすぐにわからず、編集に時間がかかります。 結局AIに修正を頼むことになり、やり取りの往復でさらに時間がかかってしまいます。「それなら最初から自分でゼロから作った方が早かった」というケースもありました。 一般的によく採用されているアプローチには、この観点で限界がありました。 PowerPoint直接生成方式 :ネイティブなpptxが得られるものの、プロンプトの指示を意図通りに守ってくれないことが多い。デザインの見栄えが良くないケースも多い(この方式でLLMがつまずきやすい具体的な課題は、以前の記事「 LLMによるパワポ自動生成にチャレンジしてわかった課題 」でも解説しています)。 画像生成方式 :見栄えはそれなりに良いものの、編集できない。「自分の細かな思い」を込められない HTML生成方式 :見栄えが良くAIによる編集と相性が良いが、自身での編集は難しく、結局AIへの指示に頼ることになる そして、どの方式にも共通するのが、結局「 自分の好み通りのものに仕上げ切るのが難しい 」ということです。 そこでこの記事では、試行錯誤の末に辿り着いた現時点の最適解として、 書式・ルールを全てPythonコードに規定し、Claude Codeのスキルでワークフローを制御する方式 を紹介します。 本記事は、AIによるスライド生成を試したものの「なんか違う」と感じた経験のある方や、自分好みのフォーマットで資料を自動生成したい方に向けた内容となっています。 目次 1. まず試してダメだったこと 2. 辿り着いた最適解:書式・ルールを全てPythonコードに規定する 3. 仕組みの詳細①:デザインをコードに固定する 4. 仕組みの詳細②:品質を担保するワークフロー 5. 仕組みの詳細③:トークン効率 6. 実際に作ったスライドの例 感想・まとめ 1. まず試してダメだったこと 1-1. XML(OOXML)直接編集:Anthropic公式skillをそのまま使う 最初に試したのは、Anthropicが公開している公式skillリポジトリの pptxスキル をそのまま使う方式です。pptxファイルの実体であるOOXML(XML)をAIが直接読み書きします。 結果は、以下の理由で使い物になりませんでした。 デザインが崩壊 :シェイプの座標・配色・整列といった細かい制御をXMLレベルで正確に行うのは、AIには難易度が高く、デザインが崩壊していました。 コンテキスト消費が激しい :スライド1枚分のXMLだけでも膨大な量になり、読み書きのたびにコンテキストが圧迫されます。デッキ全体を扱うと、すぐにトークン消費量が膨大になりました。 1-2. 画像生成方式 スライドを画像として生成する方式は、第一印象の見栄えは悪くありませんでした。しかし、 編集できないことが不便でした 。 1文字直すにもAIに指示を出して再生成を待つ必要がありました。 1-3. HTML生成方式 HTML生成は見栄えが比較的良く、編集自体は容易ですが、その編集は基本的にAIへの自然言語指示になります。自分の手で直接修正できず、手触り感がありません。 さらに、デザインの指定も自然言語ベースなので守られないケースがあり、どうしても「HTML感」が出てしまいます。「自分が作った感」のない資料は、レビューも編集もどこか他人事になってしまい、甘くなってしまうことがありました。 1-4. 3方式に共通する敗因 振り返ると、失敗した方式には共通点がありました。 デザインルールを「自然言語のプロンプト」で守らせようとしていた ことです。 「余白は0.3インチ以上」「フォントはMeiryo UI」「この配色を使って」。こうした指示をプロンプトで与えても、AIは毎回少しずつ違う解釈をします。 自然言語での指示に頼る限り、「いつもの自分のフォーマット」の再現性は担保できないと感じました。 2. 辿り着いた最適解:書式・ルールを全てPythonコードに規定する 2-1. コアの発想:デザイン判断をAIから取り上げる 最終的に辿り着いた答えはシンプルで、 デザインをAIに判断させるのではなく、自作ヘルパーライブラリの関数に組み込む というものです。 python-pptxライブラリを活用した、自作のヘルパーライブラリ pptx_helpers.py を構築しました。表を作る make_table 、見出しを置く add_heading 、スライド1枚の中での分割レイアウトを組む draw_split_layout 。これらの関数には、私の「いつものフォーマット」の配色・罫線・フォント・余白が全てハードコードされています。 スキルには、こう明記しています。 関数のデザインこそが承認済みデザイン pptx_helpers.py の make_table ・ add_heading などのヘルパーに組み込まれたビジュアルデザインが承認済みのデザインそのものである。自身の美的判断に合わせて色・罫線・フォント・余白を上書きしてはならない。関数がパラメータを受け付けないなら、それは意図的に固定されている。 AIの仕事は「どの関数を、どのデータで呼ぶか」だけです。自然言語でデザインを守らせるのではなく、そもそも守る以外の選択肢をなくしてしまうのがポイントでした。 2-2. ワークフローはAnthropic公式skillの設計思想を参考に実装 ワークフロー自体はゼロから発想したわけではなく、Anthropic公式のpptxスキルの設計思想を参考にしています。公式skillから以下の考え方を取り入れて、ゼロから自分のskillとして書き起こしました。 参考にした考え方 :段階的なワークフロー構成、サブエージェントによるレビューの仕組み 独自に実装した部分 :OOXML直接編集ではなくpython-pptx+自作ヘルパー関数を採用し、自然言語で書かれがちなデザインルールをコードに固定 2-3. リポジトリ全体像 . ├── scripts/ # 共有ライブラリとツール (git管理) │ ├── pptx_helpers.py # スライド構築ヘルパー(全ビルドスクリプトの基盤) │ └── generate_template_images.py # テンプレートから高解像度参照画像を生成 ├── template/ # ベーステンプレート資産 (git管理) │ ├── template.pptx # 「いつもの自分のフォーマット」を体現するベーステンプレート │ └── template_images/ # レイアウト・チャート別の参照画像 ├── output/ # 生成物 (テーマごとに1ディレクトリ) │ └── <theme>/ │ ├── python/ # ビルドスクリプト (git管理。後から修正・再生成可) │ │ └── slideNN_build.py # スライド1枚 = スクリプト1本 │ ├── <theme>.pptx # 生成されたpptx本体 (git管理対象外) │ └── slides/ # AIレビュー用スライド画像 (git管理対象外) └── .claude/skills/ # PowerPoint生成・レビュー用スキル ├── pptx/ │ └── SKILL.md # 中核ワークフロー(作成・編集) ├── pptx_review/ │ └── SKILL.md # 完成デッキのレビュー └── pptx_overall_structure_review/ └── SKILL.md # スライド構成案のレビュー 設計上のポイントは、 スライド1枚をPythonスクリプト1本( slideNN_build.py )に対応させ、スクリプトの方をgit管理する ことです。pptx本体はスクリプトからいつでも再生成できるため、git管理していません。 3. 仕組みの詳細①:デザインをコードに固定する 3-1. デザインの原本はPythonコード 私の「いつものフォーマット」の配色・罫線・フォント・余白は、全て pptx_helpers.py の関数の中に実装されています。表なら make_table 、見出しなら add_heading 、分割レイアウトなら draw_split_layout という具合に、スライドの構成要素ごとに専用関数を用意し、スキルには「必ずこれらの関数を使うこと」「関数のデザインを自身の判断で上書きしないこと」を指示しています。 デザインの正解がコードとして1箇所に集約されているので、AIの解釈が揺れる余地がありません。デザインを変えたくなったら関数を直せばよく、以降の生成物全てに反映されます。 3-2. Grand Rules:例外なく守らせる強制ルール スキルの冒頭には「Grand Rules」というセクションを置き、デザイン判断の余地を潰しています。例えば以下のようなルールです。 分割レイアウトは必ず draw_split_layout() を使う コンテンツ領域を左右に分割するスライドで、セクションごとに見出しを個別に置くと、見出しの縦位置がズレるリスクが生まれます。そこで分割とヘッダー配置を1つの関数に閉じ込め、構造的にズレが起きないようにしました。 例えば以下のコードは、コンテンツ領域を「背景」(左1/3)と「課題分析」(右2/3)に分割し、左に前提の箇条書き、右に課題の一覧表を配置して、間を三角コネクタでつなぐものです。 draw_split_layout() が見出し付きの分割エリアとコネクタ用の領域を作って座標を返すので、あとはその座標を使ってコンテンツを描くだけです。 areas, triangle_arrow_areas = draw_split_layout( slide, col_ratios=[ 1 , 2 ], titles=[ "背景" , "課題分析" ], triangle_arrow_width=TRIANGLE_ARROW_WIDTH, ) left_x, content_top, left_w, content_h = areas[ 0 ] right_x, _, right_w, _ = areas[ 1 ] conn_x, _, conn_w, _ = triangle_arrow_areas[ 0 ] add_bullet_list(slide, items=[...], x=left_x, y=content_top, cx=left_w, cy=content_h) add_triangle(slide, x=conn_x + BETWEEN_SHAPE_GAP, y=content_top + TRIANGLE_ARROW_V_PAD, cx=conn_w - BETWEEN_SHAPE_GAP * 2 , cy=content_h - TRIANGLE_ARROW_V_PAD * 2 , direction= "right" , fill=COLOR_BORDER) make_table(slide, ..., x=right_x, y=content_top, cx=right_w, cy=content_h) このコードから生成されるスライドがこちらです。 表は必ず make_table(HeaderCell, BodyCell) で作る 行と列で情報を整理する構造を、シェイプの手動配置で実装することを禁止しています。ヘッダーのスタイル、グループラベルの塗り、セル内箇条書きの体裁は全て関数側で決まり、すべて私好みのデザインにしています。 見出しは必ず add_heading() を使う 文字色と下線色は関数内で固定されており、独自の色を渡すことはできません。 3-3. カラーパレット・タイポグラフィも定数化 色は COLOR_PRIMARY (プライマリの青)、 COLOR_PRIMARY_MID 、 COLOR_PRIMARY_PALE 、 COLOR_ACCENT (強調の赤)などの定数のみ使用可能とし、hexコードの直書きを許容しない形にしています。 単に色を列挙するだけでなく、「Mid Primaryは二次的な塗りの既定色」「Pale Primaryは表の交互行など、背景からかすかに区別できれば足りる場面だけ」といった 使い分けのルール までスキルに規定しています。 タイポグラフィも同様で、フォントはMeiryo UI固定、サイズはスライドタイトル24pt・リード文18pt・Bodyテキスト12〜16ptと決めています。 3-4. スキルに書くだけでは守られない:絶対に守らせたいルールはエラーで止める 運用してみて気づいたのは、 スキルにいくら明確にルールを書いても、AIが守らないことがある という事実です。 象徴的だったのがフォントサイズです。スキルには「Bodyテキストは12pt以上必須」と明記していたにもかかわらず、情報量の多いスライドで「デザイン上、何とか1行に収めたい」と判断したAIが、勝手に11pt以下に下げるケースが見られました。 これは、skillで指示の書き方を強めても根絶できませんでした。 そこで、このルールはプロンプトではなくコードで強制することにしました。共通のフォント設定処理に検証を入れ、12pt未満が渡されたら ValueError を投げて実行そのものを止めます。 MIN_BODY_PT = 12 # Bodyテキストの下限。これ未満はValueErrorにする raise ValueError ( f "フォントサイズ {sz_pt}pt はBodyテキストの下限 {MIN_BODY_PT}pt 未満です。" ) エラーで実行が止まれば、AIは文字数を削る・レイアウトを調整するなど、フォントを下げる以外の道を探すしかありません。これにより、12pt未満のテキストは発生しなくなりました。 4. 仕組みの詳細②:品質を担保するワークフロー デザインの再現性はコードで担保できますが、それだけでは「きれいなだけで中身のないスライド」ができてしまいます。そこでもう1つの柱として、 自分のスライド作成の作法をワークフローとして強制する ことにしました。 4-1. スライド計画:作法を計画段階で強制する スライド作成の起点はAIではなく私です。議事録や過去資料をもとに通常のChat型AIと壁打ちして「何を伝えるか」を固め、その結論を自然言語でスキルに渡すところから始めます。 ただし、その後いきなりスライドをAIに作らせることはしません。実装に入る前に、AIには全スライドについて「Section/Title/Lead text/Layout/Chart type/Body outline」を文字で書き出させます。 どういうスライド設計にするつもりなのかを事前に見える化し、自身の目でレビューしてから作成に取り掛からせることで、「pptxはできあがったけど、全体のストーリーがイマイチなので作り直し」という時間の無駄を避けられます。 この「ストーリーラインを最初に固める」という考え方自体は、以前紹介した「 技術者も知っておくべきプレゼン資料作成術:社内研修会レポート 」の研修内容を、AIのワークフローに応用したものです。 4-2. テンプレートpptx:複製のベースであり、デザインのカタログ template/template.pptx は、私が普段使っているフォーマットをそのまま詰め込んだベーステンプレートです。このテンプレートには2つの役割があります。 1つ目は、 スライドを複製してコンテンツを書き込むためのベース としての役割です。表紙・目次・セクション区切り・標準スライドといった複製元スライドを含んでおり、各スライドはspeaker notesに書いた識別子( layout_title 、 layout_toc 、 base_template など)で内容を機械的に特定できます。AIはこれをコピーした上にコンテンツを配置していくので、所定のテンプレート(会社テンプレートなど)に沿った体裁が最初から保証されます。 2つ目は、 標準的な視覚デザインをAIに教えるカタログ としての役割です。デザインの原則はPythonコードで規定していますが、「関数をどう組み合わせると、どのような見た目のスライドになるのか」は視覚的に教える必要があります。 そこで、私が普段よく使うレイアウト5種(単一チャート、チャート+左に前提、チャート+右に結論など)とチャート約20種(ツリー、ステップ図、マトリクス、ロードマップ、評価テーブルなど)を参照画像のカタログとして整備し、AIにはこのカタログからデザインを選ばせるようにしました。 4-3. 多段レビュー:「サブエージェントと自分自身によるレビュー」 このワークフローでポイントになるのが、公式skillから踏襲・発展させたレビューの仕組みです。 作成過程のコンテキストを一切持たない新しいサブエージェントを起動し、先入観のない目でレビューさせます。 レビューは2段階あります。 構成レビュー(実装前) : スライドを作る前に、計画ドラフトを別のサブエージェントがレビューします。レビュアーには自分自身の考え方を踏襲したペルソナを与え、厳しくレビューをするよう指示しています。 さらに、AIのレビューを反映した計画は必ず私自身にも提示され、 私が承認しない限りAIは実装を開始しない フローにしています。スライドを作り込んだ後に構成からやり直すのが最大の時間の無駄なので、実装前の段階で人間のレビューを必ず挟むようにしています。 完成後レビュー : デッキが完成したら、全スライドを画像化して、別のサブエージェントが目視レビューを行います。要素の重なり、1〜2pxの不整列、低コントラスト、フォントの不統一といったビジュアル品質と、全体のストーリー・各スライドのリード文を全数チェックします。 指摘はMust fix/Nice to fixの優先度付きで返ってくるので、私が最終的に対応する項目を取捨選択し指示を出します。そのうえで、修正が必要なスライドのビルドスクリプトだけを修正・再実行します。 4-4. AI目視レビューのためのレンダリング基盤 AIによる目視レビューにはpptxのスライド画像化が必須です。当初はLibreOfficeで変換していましたが、フォント代替で一部の文字が合成斜体になったり、オブジェクトが欠落したりする問題がありました。 そこでMicrosoft PowerPointのネイティブ変換(macOSはosascript、WindowsはCOM経由)ができるレンダリングCLIを整備しました。 5. 仕組みの詳細③:トークン効率 やってみて想像以上に重要だったのが、トークン効率の設計です。pptx生成は画像・大きなソースコードといった成果物を扱うため、意識しないとメインコンテキストがすぐ溢れ、品質もコストも悪化してしまいます。 そこでスキルには、「品質を落とさずトークンを節約する」ためのルールを明記しました。 ヘルパーライブラリは実装を含めた全文を読ませない :スキル内の関数リファレンス表とdocstringだけで使用方法が全てわかる設計にする 目視レビューはサブエージェントに委譲する :全スライドの画像はサブエージェント(独立コンテキスト)側で読み、メインエージェントはテキストの所見だけを受け取る 修正後は変更したスライドだけを再レンダリング・再読込する 6. 実際に作ったスライドの例 冒頭でお見せしたスライドは、いずれも架空の「食品スーパーの需要予測AI導入検討」というテーマで、この仕組みを使って生成したものです。 スライド1枚分のビルドスクリプトがどのようなものか、冒頭2枚目の「需要予測AI導入スケジュール」のスライドを例にお見せします。 import sys from datetime import date sys.path.insert( 0 , "." ) from pptx import Presentation from scripts.pptx_helpers import ( COLOR_BG_WHITE, COLOR_PRIMARY_MID, COLOR_PRIMARY_PALE, COLOR_TEXT_DARK, add_step_arrow, clear_body_shapes, make_schedule_frame, set_base_slide, ) PPTX = "output/techblog_sample/techblog_sample.pptx" # 担当別の塗り色 FILL_OURS = COLOR_PRIMARY_MID # 弊社(白文字) FILL_CLIENT = COLOR_PRIMARY_PALE # 貴社(濃色文字) prs = Presentation(PPTX) slide = prs.slides[ 5 ] # 6枚目のスライド clear_body_shapes(slide) # セクション・タイトル・リード文をまとめて設定 set_base_slide( slide, "導入計画" , "需要予測AI導入スケジュール" , "12月上旬までにパイロット検証を完了し、来期初からの全店展開を目指す4ヶ月の導入計画です" , ) # 年・月・週のヘッダーとタスク分類行を持つスケジュール枠を描画する # (右上の凡例「弊社/貴社」の描画は省略) info = make_schedule_frame( slide, from_date=date( 2026 , 9 , 7 ), to_date=date( 2026 , 12 , 27 ), task_categories=[ "要件定義・データ整備" , "モデル開発・検証" , "導入・展開" ], category_sz_pt= 14 , ) col_xs = info[ "col_xs" ] col_w = info[ "col_width" ] cat_ys = info[ "category_ys" ] cat_h = info[ "category_h" ] # (カテゴリindex, 開始週, 終了週, ラベル, 塗り色)。週は1始まり bars = [ ( 0 , 1 , 3 , "現状分析・KPI定義" , FILL_OURS), ( 0 , 4 , 7 , "販売・気象データの整備" , FILL_CLIENT), # ...残り4本は省略 ] BAR_CY = 520000 for cat_i, w_from, w_to, label, fill in bars: bar_x = col_xs[w_from - 1 ] bar_cx = col_xs[w_to - 1 ] + col_w - bar_x bar_y = cat_ys[cat_i] + (cat_h - BAR_CY) // 2 text_color = COLOR_TEXT_DARK if fill == FILL_CLIENT else COLOR_BG_WHITE add_step_arrow(slide, label, x=bar_x, y=bar_y, cx=bar_cx, cy=BAR_CY, fill=fill, text_color=text_color, sz_pt= 13 ) prs.save(PPTX) デザインに関する記述がほぼないことがわかると思います。座標とデータを渡せば「いつもの自分のフォーマット」で描画される、というのがこの仕組みの本質です。 再掲になりますが、このコードによって生成されたスライドがこちらです。 Plotlyで生成した定量チャートを埋め込むスライドも、同じ仕組みで作れます。 ※本チャートは記事用に作成した架空のサンプルデータであり、当社の実績や導入効果を示すものではありません そして「スライド=Pythonスクリプト」なので、その後の修正は2通りから選べます。大幅に変えたければスクリプトをAIに編集してもらって再実行すればよいですし、文言や表の中身をさっと直したければpptxを開いて普段どおり手で編集できます。 どちらの方法も使える ことが、実運用では非常に便利です。 感想・まとめ 当初の目的は果たせた 今回作った仕組みは、非常に細かいところまで自分の好みに合わせられました。実際にかなり便利で、当初の目的は果たせています。 出てくるスライドは自分にとって読みやすく、大幅な修正が基本的に不要 修正したい時も「いつもの自分のフォーマット」なので、好みの修正がいつもの作業でpptx上ですぐできる 作成時間についても、正確に計測はしていませんが、手作業で作る場合と比べて6割ほど削減できている体感です。 工程 作成時間の削減率 主な担当 構成・ストーリー設計 約5割減 AIが原案、私がレビューと承認 スライド作成 約9割減 AI(ビルドスクリプトの生成と実行) 見直し・手修正 ほぼ変化なし 私 全体 約6割減 削減が効いているのは主にスライド作成の工程で、構成の検討と最後の手修正はそこまで削減できていません。特に手修正がまったく減っていないのは、仕組みが不十分だからではなく、意図的に残している部分です。 減らなかった手修正は、むしろ必要な工程 手修正の中身は、テキストの修正がメインですが、表の項目を大幅に削ったり追加したりすることもあります。 ただ、これはそこまで苦になりません。自分のいつものフォーマットなので修正は楽ですし、「自分が作った感」のあるスライドなので、修正に魂を込めやすいです。 そしてこの手修正は、 最後に人間が自分で語れる資料にするため必要な工程 だと考えています。完全に消すことはできず、最終的にこのスライドをもとに自分の口で説明する以上、消すべきでもないと思っています。 pptxのテイストは企業によって、人によって全然違う これまで様々な企業の資料を見てきて思うのは、pptxのテイストは企業によって本当に違うということです。配色、レイアウトの密度、リード文の書き方、表の使い方など、どれも組織の文化そのものです。さらに言えば、同じ企業の中でも人によって好みが違います。 だからこそ、スライド自動生成は万人向けの汎用サービスで済むものではなく、 個人が自分の好みでカスタマイズできる仕組みであるべき だと思います。テンプレートとヘルパー関数を自分用に作り込むこの方式は、その点で理にかなった仕組みなのではと考えています。 この記事が、自分好みのPowerPointを自動生成したい方の助けになれば幸いです。