ChatGPTとの会話だけで画像管理アプリが出来上がった

ローカルPCでの画像生成AIの環境を構築して、画像生成を始めたのがちょうど1年半前のこと。プロンプトだけで生成したり、LoRAを自前で作成して画像を生成したり。

当然ながら完成画像より、その調整段階というのか選定候補となる画像の方が圧倒的に多いんですが、それら生成途中の画像も意識的に削除をすることなく、日々画像を生成していると、気付けば、そのファイル数が10万枚を超えてました。いや、さすがに自分でも「数え間違えだろ」と思ったんですが、どうやら事実のようです。

そのファイル群は、まさに玉石混交。フォルダ分けしておけばよかった、なんて今さら思っても後の祭り。

この画像ファイルをどう整理して活用するか、とりあえず考えてみました。

こんなアプリがあればなぁ…

画像生成の環境は、最初はRTX 2060 Superを積んだOMEN25L、今年に入ってからは RTX 5070Ti を搭載したOMEN35Lと2台に分かれているので、それぞれのPCから1台のNASにファイルを同期するようにしています。つまりはそれらのファイルを合算したのが10万枚超ということです。

さすがにWindowsのエクスプローラーだけで管理(という管理もしていないので、閲覧、ですかね、)するのは限界を超えている枚数なので、フォルダを跨いで一覧表示させたりできるフリーのアプリが無いかと探していたんです。

個人的に好きだった画像管理アプリは、既に公開終了から10年以上経ってしまった Picasa3。ローカルPCの(ネットワークドライブの設定でNASにあるものも)画像を、フォルダの階層に依らず一覧で表示できたり、フォルダに自由にメモ書きできたり、また、それを基に検索出来たりと、やりたいことがいろいろ実現できていたアプリだったんです。

ただ、旅行に行ったときに撮ったデジカメ画像を管理するのと、生成画像のファイルを管理するのとでは、同じ「画像管理アプリ」というジャンルでも求めるものは違ってくるもの。

そこで、こんなアプリが無いかな、と、ChatGPTに相談してみたんです。

・NASに保存した生成画像ファイルを管理したい。
・生成した画像ファイルを一覧表示させたい。(但し、これはちょっと意思疎通が出来てなくて、階層に依らないフォルダの一覧を想定されていたようです。結果的にはこちらの方が都合が良かったので、これに乗っかってます)
・一覧はサムネイルでの表示で、サムネイルをクリックすることで元画像を大画面で表示させたい。
・画像表示の横に、PNG Infoで表示されるような、生成時のプロンプトや生成時のパラメータ、使用モデルやLoRAを表示させたい。
・LoRAによるフィルタリング機能が欲しい。

など、思いっきり生成画像の管理に振り切った要求です。

そんなアプリ、フリーウェアであるはずないですよね。。

なければ、作っちゃえば?というのがChatGPTの回答でした。

動作環境

これはいつか、別記事で紹介したいと思いつつ手付かずなのですが、自宅では、Intel Core i5-8500T / RAM16GB / NVMeSSD512GB のコンパクトPCに Proxmox VE9をインストールして、Ubuntu 24 Server の仮想マシンを立ち上げています。

そのサーバ上で動かす、Webアプリを作成する、というのが今回のミッションとなります。

ファイルやフォルダの付加情報、画像サムネイルは、サーバ側のデータベースで管理し、NAS上の画像ファイルには一切手を加えません。これが大前提ですね。

私自身は組込みシステム開発のエンジニアではあるんですが、Webアプリの製作経験はほとんどなく、ChatGPTに頼りっきりでどこまでできるのか、というチャレンジでもあります。

仕様を固める

ちょっと面倒な前提となるのが、当該のNASは、平日の日中、電源を落としている、ということ。使用するのが私だけですからね。出勤している間は外からアクセスすることも無いですし、電気代削減でもあります。

ところが、画像管理アプリは、新たに追加されたフォルダは追加と認識し、削除されたフォルダは削除と認識することから、NASの電源OFF時にフォルダにアクセスできないことをもって削除と認識されては非常に困ります。そのあたりも念押しで条件として伝えました。

それらを踏まえての仕様固めです。とは言っても、最終的な姿までは決めません。まずは、「こんなのがあればいいな」というレベルで、ChatGPTに要求を行い(もちろん、構築する環境の前提も伝えてあります)、仕様の提示を待ちます。

わずか数十秒で表示されたのがこちら。

まず作るものの姿

Picasa風の生成画像ブラウザ

  • NAS上の生成画像フォルダを対象
  • 実フォルダ構成はそのまま
  • 画面上は「画像を含むフォルダ」を同列のアルバムとして表示
  • 各アルバムを開くとサムネイル一覧
  • 画像を開くと大きめ表示+生成情報表示
  • NAS OFF時も、サムネイルと保存済みメタデータは閲覧可能
  • 閲覧中フォルダだけ高頻度監視

初期仕様(確定候補)

1. データ元

  • OMEN35Lで生成した画像
  • QsyncでNASへ同期
  • UbuntuサーバはNAS共有を読み取り専用で参照

2. 表示単位

  • フォルダ階層をそのまま辿るのではなく、
  • 画像が存在するフォルダをアルバムとして一覧表示
  • フォルダ名だけでなく、相対パスも表示

例:

  • SDXL / landscapes / autumn
  • ComfyUI / anime / test01

3. 一覧画面

  • 代表サムネイル
  • フォルダ名
  • 相対パス
  • 画像枚数
  • 最終更新日時(あると便利)

4. 画像詳細画面

表示対象は最低限こんな感じでしょうか。

  • 画像プレビュー
  • ファイル名
  • 保存先パス
  • 生成日時
  • Prompt
  • Negative Prompt
  • Seed
  • Steps
  • CFG
  • Sampler
  • Scheduler
  • Model / Checkpoint
  • LoRA
  • Size
  • ComfyUIなら workflow / prompt JSON

5. NAS OFF時の動作

  • サムネイル:表示可
  • メタデータ:表示可
  • 元画像:原則不可
  • 「NASオフライン」表示を出す

6. 同期・監視

  • 閲覧中フォルダ:2〜5秒間隔
  • その他フォルダ:1〜5分間隔
  • 全体整合性チェック:数時間ごと

7. 削除の安全設計

  • NAS未接続時は削除判定しない
  • 正常スキャン完了時のみ削除候補判定
  • 1回未検出で即削除せず missing にする
  • 次回以降の正常スキャンでも未検出ならDB削除

技術構成のおすすめ

今の環境なら、まずはこれが無難です。

  • Ubuntu 24 Server
  • Docker Compose
  • nginx
  • アプリ本体:Python系が作りやすい
    • FastAPI
    • SQLAlchemy
    • SQLite
  • サムネイル生成:Pillow
  • PNGメタデータ解析:
    • Pillow
    • 追加で ExifTool を使えるようにしてもよい
  • フロントエンド:
    • まずはシンプルなサーバサイドHTMLでも可
    • 余力があれば Vue / React

個人的には、最初は
FastAPI + Jinja2 + SQLite
くらいの軽さで始めるのがよいと思います。
見た目を凝るのは後回しで十分です。

一部修正が必要なところもありますが、概ねいい感じです。まずはこれで進めることにしました。

このあと、各画面での表示の内容などを「ChatGPTとの会話(チャット)」で詰めていきます。こちらからマークダウン形式での要求仕様を作成する、なんてことはしてません。あくまでも会話だけです。

詰まってきたところで、テキスト300行近くに及ぶ「画像生成ブラウザ 画面仕様案(初版)」を提示され、了承の後、次に内部設計へと移ります。

技術構成

  • FastAPI
  • Jinja2
  • SQLite
  • SQLAlchemy
  • Pillow
  • 必要なら ExifTool 補助利用
  • Docker Compose
  • nginx(後段リバースプロキシ)

このあたりは、「良きに計らえ」、という感じではあるんですが、一応技術者の端くれとして内容は確認。その後、DBテーブルを詰めて、状態管理の考え方を詰めて、スキャン処理・メタデータ解析・サムネイル作成/保持方針を決めて、MVP(Minimum Viable Product)が固まりました。

MVP

  • NAS共有を読める
  • PNG画像をスキャンできる
  • サムネイルを作れる
  • 画像入りフォルダをアルバム一覧表示できる
  • フォルダ内サムネイル一覧を表示できる
  • 画像詳細と生成情報を表示できる
  • フル画面表示できる
  • 左右キーで送れる
  • NAS OFFでもサムネイルと情報が見える
  • NAS未接続時に誤削除しない

最後に念押しで、仕様に見落としが無いかを確認したうえで、いよいよ技術調査に入っていきます。

技術調査

要は、QNAPのNASへのアクセス手段の確立です。

QNAP側NFS設定とUbuntu側マウント設定を行って、実際にUbuntuでNASのファイルを読み取れるのか、という確認ですね。

NASの特定フォルダ(生成画像を格納したフォルダ)のみを、UbuntuサーバのIPアドレスからのみ読み取り専用でNFS共有設定を実施。

Ubuntuからマウントして画像ファイルを読み込み。問題なしです。

NASが電源OFFのときにマウントを試みると90秒近く応答が無くなることも判ったので、いきなりマウントしてその反応でオフライン判定するのではなく、事前にpingでオフライン判定を実施することで、体感の待ち時間を減らす方針に変更。このあたりも実際の調査結果をチャットで伝えることで、都度、仕様を変えていく感じですね。

実装開始

アプリを置く階層は

このようになります。この設計も、お任せです。

ディレクトリ作成も

このように、コピーしてターミナルに貼り付ければ実行できる形式で提示してくれますので、コマンドで悩むこともありません。

もちろん、ディレクトリ作成のようなコマンドだけでなく、Pythonのコードも、コピーして貼り付けるだけの状態で提示してくれます。

さすがにDockerでの構築が初めてなら、指示されるままに書いていいの?という不安も出てくるでしょうが、何度か経験があるので、Dockerfile や docker-compose.yml ファイルなど、内容を確認しながら実装を進めます。とは言いながらも、特に指摘しないといけないような点もないので、そのまま適用ですけどね。

で Docker が起動。

ブラウザに http://192.168.11.XX:8002/ と入れると、テスト用文言が表示されます。 ここまで、何の滞りも無く、Docker の環境が作成できたわけです。Dockerfile や docker-compose.yml ファイルは、提示されたものを見れば「なるほど」と理解できますが、これを一から自作しようとすると、こんなに短時間では無理ですね。さすがです。

これをベースにして、データベースの作成や、NASマウント参照部の実装を追加していきます。

それからNAS上の生成画像ファイルのスキャン。データベースへの登録とサムネイルの作成ですね。

さらにはアルバム(末端の画像格納フォルダのこと)一覧ページを作成したり、アルバム詳細画面を作ったり。

詳細画面例・右側に使用モデルやプロンプト、生成時のパラメータが表示される

要求次第で変わるのかもしれませんが、基本的には少し実装して実際に動かして、の繰り返しなので徐々に出来上がっていく感が楽しいですね。

但し、部分的に修正を加えていくので、修正箇所を間違えたり、インデントを間違えたりで、予期せぬ動作になることもあったりするんですが、自分で解決しようとするのは時間の無駄。所詮はChatGPTが提供したソースコードなので、全文を貼り付けて修正を依頼すると、すぐに修正版を作成してくれます。

機能追加時でも、一つのファイルに何ヶ所も修正の指示が出てきて面倒だと感じたら、「修正部分だけじゃなくてソースファイルを全部出して」でOK。こちらは「いかに効率化できるか(手を抜くか)」という観点で指示すればいいんじゃないかな、と思います。

最初はTeraTermなどのターミナルソフトでの疎通確認などから始まり、仕上がっていくにつれてブラウザでの表示確認になり、次いで、新たに追加された画像ファイルの、アプリへのリアルタイムな反映までを確認したところで問題が発生。

新たに作成されたフォルダを反映させる方法での意見の不一致です。

開発途中の軌道修正も

というのも、まだ開発途中なので、新たなフォルダ(アルバム…という概念)をデータベースに追加する手段は、ターミナルソフトからコマンドを入力するしかなかったんですね。で、そのコマンドを実行すると、対象の10万に及ぶ画像のサーチになるので、応答が返るのが数十秒後になるんです。なので、頻繁に実行すのは非現実的。

そのコマンドをアプリに組み込む段で、

1時間に1回だけ scan_albums() を自動実行するくらいで十分です。現在の全アルバム走査が数十秒かかっても、1時間に1回なら負荷はほぼ問題になりません。

運用イメージはこれでよいと思います。

アプリ起動時
   ↓
アルバム全体スキャン

以後 1時間ごと
   ↓
NASのアルバム全体スキャン

新規フォルダ発見
   ↓
SQLiteへ登録

トップ画面
   ↓ 10秒ごとにDB確認
自動表示

これなら普段は何も操作する必要がなく、curl はデバッグや「今すぐ反映したい」場合だけになります。

さすがに、これには反発。Stable Diffusion(AUTOMATIC1111)で画像を生成すると、txt2img-imagesフォルダの下に、生成した日付で YYYY-MM-DD の形式で新たなフォルダが生成されて、中に画像ファイルが作成されますが、アプリがそのフォルダを認識するのが最大1時間後、というのは、さすがに容認できません。

とはいえ、頻繁に確認すると負荷が増えるのも確かなので、「ひとまず」トップ画面でブラウザ画面リフレッシュの「F5キー」を押下することで新たなフォルダのサーチを開始することに。

こんな風に、「負荷を抑える」という問題に対する回答は、必ずしもユーザーフレンドリーなものではないこともあるので、そこは随時、チャットで意見のすり合わせが必要ですね。

アルバム一覧画面

他にも、トップ画面(アルバム一覧)から特定のアルバム(アルバム内の画像一覧)画面に入った後、トップ画面に戻ると先頭に戻ってしまうのは非常に使いにくいので、そのあたりを指摘すると、即座に修正してくれるということもありました。

このような「ちょっとした仕様変更」は、一つや二つならともかく、数が重なると、実際のソフト開発現場では、かなり鬱陶しがられるでしょうが、ChatGPTは文句を言わずに変更してくれます。

途中での度重なる仕様変更による、いわゆる「デグレ」は、今回の開発中、ほぼゼロだったので、非常に素晴らしい設計&コーディング技術だと思います。

終わりなき開発

開発が終わらない、というのは、いつまでたっても修正修正で完成しないという悪い意味ではなく、使えば使うほど、欲が出てくるんですよね。

ここをこうすればもっと使い勝手が良くなるんじゃないか、と。

例えば、当初は10万枚強の画像を全部対象とすることを想定していたんですが、いざ使ってみると、txt2img-images 以外の txt2img-grids や img2img-images などは、アルバムの対象にしなくてもいい(というか、普段は見なくても大丈夫、いや、むしろ非表示にしたい)ということから、txt2img-images だけを表示するフィルタリングのボタンを追加したり、使用したLoRAごとにフィルタ表示できるようにしたり、と。

特にLoRAによるフィルタは、このアプリの最大の強みですよね。市販の画像管理アプリでは、まず対応していないだろうと思われる機能です。

なので、この機能についてはチャットでの「仕様の詰め」は念入りに行い、理想的な姿に。

実在のフォルダではなく、LoRAごとに「仮想フォルダ」を作って表示する、仮想アルバム化です。

実フォルダでは複数に分かれている同一LoRAで生成した画像をひとつの仮想アルバムで表示

これを使ってみると、今度は、「最適なLoRAを選ぶため」に、10Epochごとに生成した途中段階のLoRAを使用した、枝番付きのLoRAフォルダが大量に出てきますので、実際には、最終形は枝番を切り落として使用することが多いので、トップ画面の上部に

このようなボタンを作ってみたり。

完成版LoRAのみを一覧表示

他には、Webアプリなので、スマホでも使えるようにしてみたり。

スマホで表示できてしまうと、今度は全画面(フルスクリーン)で表示させたくなったり、スワイプで前後画面を移動させてみたくなったり。横長画像ならスマホを横向きにして全画面表示させたくなったり。

そうすると、スワイプ操作は「スマホに対して上下」になるので、それに対応してみたり。

欲望は尽きないものです。

さらには、例えば手が3本ある、とか、人の顔として体を成していない、とか、

参照したくない画像を非表示にする機能を付けてみたり。

採用判定と除外(不採用)判定を設ける、ということです。

画像ごとに「採用」か「除外」を選択できるように

「採用のみ」だけだと、全10万枚以上の画像に判定を付けるまで実用稼働しないので「採用+未判定」の選択肢を設けてみたり。

今度は、一度評価した画像にも、常に「採用」「除外」ボタンが表示されるのが気に入らなくなったり。ほんとにわがままです(笑)

さらには、使用したプロンプトでの検索機能を入れてみたり、その検索を履歴表示して再利用しやすくしてみたり。

「train」というワードで検索

データベースの設計がきちんとされているからか、検索ワードによる検索が非常に速いんですよね。NAS上にある画像からの検索ではありますが、プロンプトなどのデータはサーバ側で保持しているので、10万枚からの数千件のフィルタリングも、ほんとにあっという間です。

さらには、画像のショートカット的に「お気に入り」表示機能も。

もはや何でもありになりつつありますが、全画面表示のときにPCのマウスではスクロールで、スマホやタブレットではピンチイン・ピンチアウトで拡大縮小が出来たり、画像に集中できるようボタンを非表示にする機能を付けたり。

実用面では、OMEN35Lで生成した画像を使用して、別のPCでブログを編集しているので、画像のダウンロード機能を付けてみたり。

中には、一つの機能の実装に、想像以上に複数の箇所に手を入れることもありますが、人間なら相当に設計書とソースコードを読み込まないと見落としそうな影響箇所を、予め対策できていたりと、エンジニア観点からすると驚きの連続でもありました。

NAS上から画像ファイルを削除した際に、表示が異常となるケースが発生したんですが、それも、発生している症状を伝えれば、的確に修正してもらえたので、悩む必要なし、でした。

ボタン部分を含めたトップ画面(アルバム一覧)
アルバム内の画像一覧画面(この画面で直接「お気に入り」★の変更ができる)
画像詳細画面・作成したプロンプトやパラメータを確認できる
全画面表示で「採用」「除外」などを決定(判定後は自動で次画面を表示)
フルスクリーンに合わせての拡大表示も

というような感じで、もはや、生成画像ファイルの管理アプリとしては、他に類を見ない(と思ってるんですが…)高機能なアプリとなりました。

今回の総括

とはいえ、これでもまだ完成ではありません。

ひとり分のLoRAを複数のバージョンで作成しているので、「人物」単位で統合表示できる機能だとか、検索できるメモの入力機能だとか。

やりたいことが次々と頭に浮かんできます。

市販のアプリだと、「帯に短し襷に長し」だとか、「痒い所に手が届かない」とかの部分が多々あるのが現実。かといって、自分で一から自作しようとすると、プログラミング言語の習得など、ハードルが結構高いものです。

システムのベースとなるPythonコードや、ブラウザ上での表示を担うHTMLファイル、データベースの操作、サーバ上で動かすためのDockerの仕組みなど、高度な知識が無くても「ChatGPTとの会話」だけで、手離せなくなるようなアプリが仕上がったのは、本当に驚きです。

ちなみに、私は、月額20ドル相当のChatGPT Plusを利用しています。そのため、無料プランで今回のようなアプリを作成しようとした際に、画面の表示をキャプチャして問題点を共有したい場合などで利用制限にかかる可能性もあります。

もっとも、大部分がテキストベースのチャットでのやりとりですので、無料プランでもほぼ同じようなことが出来るとは思います。

ここ数週間(2026年11月1日現在で)、生成AIが関与していると思われる悪質な不正アクセス問題で、「生成AIは怖い」と思われた方も多いのではないかと思います。負の側面が話題になることが多かったように思いますね。

でも、生成AIそのものが善悪を判断しているわけではありません。結局のところ、それを何のためにどのように利用するかは人間次第です。

今回のアプリ開発では、実現したい機能を普段の言葉で伝え、提案された内容を確認し、実際に動作させながら改善を重ねてきました。その結果、従来であれば相当の時間と労力を必要としたであろうアプリを、自分の希望に沿った形で作り上げることが出来ました。

もちろん、途中随所で感じたのは「生成AIの回答が常に正しいわけではない」ということ。実際に確認し、問題があれば修正するという作業は不可欠です。

それでも、これほど身近な存在になった生成AIが、個人のものづくりの可能性を大きく広げてくれるということを、十分に実感できたと思っています。

生成AIは、悪用すれば脅威にもなり得ます。しかしながら、正しく活用すれば、実現が難しかったアイデアを実際の形にするための、非常に強力なツールになるのだと、改めて思いました。

というわけで、まだまだ、改善し続けますよ。