はじめに
みなさん、こんにちは。2026年新卒として株式会社インプルに入社しました、yotaです。大学では、数学/数理学を専攻していました。ゲームが趣味で、プログラミングはゲーム用のツール開発のために勉強し始めました。
最近は生成AIの活用が主流になってきましたが、みなさんはどのAIをよく使っていますか?
私はGeminiをよく使っています。大学時代、定理の証明などの論理的な問題を解かせる際、当初使っていたChatGPTよりもGeminiの方が優秀だと感じたのがきっかけです(今は逆転してるかも?)。それ以来、趣味の開発でもGeminiを活用しています。とはいえ、最近はClaude Codeのコーディング能力も気になっており、少し浮気心が芽生えつつある今日この頃です。
今後、rambleでは、LLM(大規模言語モデル)やAI技術を軸にした記事を更新していく予定です!
今回の目標と流れ
手書きスケッチからWebUIを作る
プログラミングの学習を始めた頃、HTMLやCSSを使ったUIデザインの配置に大いに苦戦しました。「UIデザインが難しすぎる……手書きで直感的に配置できたらいいのに!」とも思いました。
そこで今回は、「手書きスケッチからWebアプリのプロトタイプ(HTML/CSS)を自動生成するアプリ」の構築を目指して検証してみます。
Geminiに相談!ローカルVLM「Llama 3.2-VIsion」との出会い
とはいえ、LLMを用いた開発については何も知らないため、まずは相棒のGeminiに相談してみました。
すると、「画像内の配置や要素を解釈し、コードを生成するにはVLM(視覚言語モデル)が適している」と教えてくれました。その中でも、ローカル環境で動作し、かつコード生成能力が高いモデルとして、Meta社のオープンソースモデル「Llama 3.2-Vision」を推奨してくれました。

今回は、完全無料でローカルPC上でAIを動かせる「Ollama」を使って環境を構築していきます。
環境構築
アプリ開発にはPythonとStreamlitを使用します。さっそく環境を作っていきましょう。
0. 事前準備:Homebrewの導入
今回の環境構築では、パッケージマネージャーであるHomebrewを使用します。もしターミナルで brew -v と入力して command not found と表示される(まだインストールしていない)場合には、先に以下のコマンドをターミナルに貼り付けてHomebrewをインストールしておいてください。
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
1. Ollamaとモデルのインストール
まずはOllamaをインストールし、Llama 3.2-Visionモデルをダウンロードします。
# Ollamaのインストール
brew install ollama
# Ollamaサービスの起動
brew services start ollama
# Llama 3.2-Visionモデルのダウンロード
ollama pull llama3.2-vision
※終了時は brew services stop ollama を実行します。
2. Pythonプロジェクトの準備
番外編:MacのPython環境構築でのプチトラブル
さて、次はPythonの準備!と思ったのですが、Macの設定で少し罠にハマったので共有します。
「Macなら最初からPythonが入っているだろう」と思い、VSCodeでPythonの拡張機能をインストールすると「Python入ってないかも…」との警告が…。ターミナルでpython3 --versionを叩くと、「Command Line Toolsをインストールしてください」とポップアップが出ました。
しかし、そのままインストールしようとすると「ソフトウェアアップデートサーバから入手できない」というエラーが発生。調べて「XCodeをインストールすると治った」という報告があり、Xcodeを入れようとするも、今度は「macOSのバージョンが古い」と弾かれてしまいました…。
結論として、「MacのOSを最新にアップデートする」ことで全て解決しました。OSアップデート後に再度コマンドを実行すると、無事にCommand Line Toolsが入り、Pythonが使えるようになりました(やはり元々入っていたようです)。もし同じエラーで詰まった方は、OSのバージョンを疑ってみてください!
本編:Pythonプロジェクトの準備
気を取り直して、アプリ用のディレクトリを作成し、仮想環境を立ち上げます。仮想環境を立ち上げることで、PC内にある他のPythonプロジェクトとライブラリのバージョンが混ざってエラーになるのを防ぐことができます。今回は、OllamaやStreamlitに加え、画像の読み込みやリサイズも行うためにPillowも併せてインストールしておきます。
# ディレクトリを作成 + そのディレクトリに移動("sketch-to-web"のところは好きな名前にしてください)
mkdir sketch-to-web && cd sketch-to-web
# "venv"という名前の仮想環境を作成(ここで先ほど作成したディレクトリに新たに"venv"というディレクトリが作成されます)
python3 -m venv venv
# 仮想環境をアクティベート(ここでターミナルの入力行の先頭に(venv)という文字がつけば、無事に仮想環境に入れた合図です)
source venv/bin/activate
# Ollama, Streamlit, Pillowをインストール
pip install ollama streamlit pillow
仮想環境を終了(ディアクティベート)する時は、deactivate と入力します。
プロトタイプの作成
自分で一からコードを書く方が勉強にはなるのですが、今回はスピード重視!ということで、Streamlitを使ったWebアプリのプロトタイプコードはGeminiに書いてもらいました(app.pyなどのPythonファイルは作成しておいてください)。
import streamlit as st
import ollama
from PIL import Image
import io
import re
# ページの設定
st.set_page_config(page_title="sketch-to-web", layout="wide")
st.title("🎨 sketch-to-web")
st.caption("手書きのスケッチをローカルLLMでHTML/CSSコードに変換します")
# サイドバー:モデル選択
st.sidebar.header("Settings")
model_name = st.sidebar.selectbox("Model", ["llama3.2-vision"], index=0)
# メインエリア:ファイルアップローダー
uploaded_file = st.file_uploader("手書きの構成図やスケッチをアップロードしてください", type=["png", "jpg", "jpeg"])
if uploaded_file is not None:
# 画像の表示
image = Image.open(uploaded_file)
col1, col2 = st.columns(2)
with col1:
st.subheader("Uploaded Sketch")
st.image(image, width='stretch')
with col2:
if st.button("Generate HTML"):
with st.spinner("思考中... (ローカルLLMで解析しています)"):
try:
# 画像をバイトデータに変換
img_byte_arr = io.BytesIO()
image.save(img_byte_arr, format='PNG')
img_bytes = img_byte_arr.getvalue()
# システムプロンプト
prompt = """
You are an expert web developer.
Analyze the provided sketch and convert it into a professional single-file HTML with Tailwind CSS.
Include all styles within the HTML file.
Output ONLY the code block starting with ```html.
"""
# Ollamaにリクエスト
response = ollama.chat(
model=model_name,
messages=[{
'role': 'user',
'content': prompt,
'images': [img_bytes]
}]
)
raw_content = response['message']['content']
# 正規表現によるコード抽出
code_match = re.search(r'```html\n(.*?)```', raw_content, re.DOTALL)
if code_match:
clean_code = code_match.group(1)
else:
clean_code = raw_content.strip().replace('```html', '').replace('```', '')
st.subheader("Generated Code")
st.code(clean_code, language='html')
# プレビュー表示
st.subheader("Live Preview")
st.components.v1.html(clean_code, height=600, scrolling=True)
# ダウンロードボタン
st.download_button(
label="Download HTML",
data=clean_code,
file_name="prototype.html",
mime="text/html"
)
except Exception as e:
st.error(f"エラーが発生しました: {e}")
st.info("Ollamaアプリが起動しているか確認してください。")
一瞬で作ってくれますね。モデルの選択やダウンロードボタン、プレビュー表示など頼んでいないところまで作ってくれました。プロンプトが英語で書いてありますが、プロンプト設計は後回しにしてとりあえず試してみましょう!
コードを保存したら、以下のコマンドでWebアプリを立ち上げます。
streamline run app.py
ブラウザが自動的に開き、画像アップロード機能のついたWebアプリが起動します!

いざ検証!
ここからが本番です。AIによる「意味解釈」の精度を測るため、自作したテスト画像を読み込ませてHTMLを出力させてみました。
テスト1:シンプルな基本レイアウト
最初は「Header」「Main」「Footer」のみを描いたシンプルなスケッチを入力してみました。

結果は次のようになりました。
画像の構成を認識し、概ね正しいレイアウトのHTMLが出力されました!プレビューを見てもHeader、Main、Footerが縦並びに配置されています。
テスト2:画像プレースホルダーを含むUI
次は少し難易度を上げて、「3つの並んだカード」のスケッチを入力してみます。カードの上部には画像のプレースホルダーのつもりで「×」印を描いています。

結果は次のようになりました。

失敗です。画像のプレースホルダーという意味を理解できず、スケッチに描かれた斜め線を「幾何学模様」として解釈してしまい、HTMLで無理やり斜め線を再現しようとする複雑なコード(ループ)を生成してしまいました。
考察と次なる一歩
今回の検証で、OllamaとLlama 3.2-Visionを使えば、完全無料のローカル環境だけで「画像からコードを生成するアプリ」の基盤が作れることがわかりました。
一方で、テスト2のように「画像の図形を無理やりコーディングしようとする」という失敗も起きました。しかし、これを直ちに「VLMの限界や弱点」と結論づけるのは早計です。今回はプロンプト設計をほとんど行わずに画像を丸投げしたため、AIが「意味を解釈する」のではなく「見た目を物理的に再現する」タスクと勘違いした可能性が非常に高いためです。
本格的なアプリに昇華させるには、画像をそのままVLMに丸投げするのではなく、プロンプト設計の調節や画像の前処理などにより、精度の向上を図るべきでしょう。加えて、そもそも「どこで精度が落ちているのか」を確認するためにも、処理の「機能分解」が必要だと考えています。
次回の記事では、この方針をもとに、機能を分解した処理を実装し、より精度の高いプロトタイプの構築に挑みたいと思います。お楽しみに!

