Stable DiffusionをGoogle Colabで使いたい

最も簡単な方法:Diffusersライブラリを使う

1. Google Colabを開く
colab.research.google.com にアクセス
「ファイル」→「ノートブックを新規作成」

2. GPUを有効化
「ランタイム」→「ランタイムのタイプを変更」
「ハードウェアアクセラレータ」を T4 GPU に設定

!pip install diffusers transformers accelerate
from diffusers import StableDiffusionPipeline
import torch

# モデルの読み込み(初回は数分かかります)
pipe = StableDiffusionPipeline.from_pretrained(
    "runwayml/stable-diffusion-v1-5",
    torch_dtype=torch.float16
)
pipe = pipe.to("cuda")

# 画像生成
prompt = "a beautiful sunset over the ocean, highly detailed"
image = pipe(prompt).images[0]

# 画像を表示
image

A young woman in a business suit, standing in a modern office, cinematic lighting, hyperrealistic, 8k, sharp focus, photo taken by Canon EOS R5

UI上でやらないといけないのね。まぁちょっと理解した。

MCPサーバ

#!/usr/bin/env python3
"""
超シンプルなMPCサーバーのサンプル
"""
import asyncio
import json
from typing import Any

class SimpleMCPServer:
    """基本的なMPCサーバー実装"""
    
    def __init__(self):
        self.tools = {
            "get_time": self.get_time,
            "echo": self.echo,
            "add": self.add
        }
    
    async def get_time(self, params: dict) -> str:
        """現在時刻を返す"""
        from datetime import datetime
        return datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    
    async def echo(self, params: dict) -> str:
        """入力をそのまま返す"""
        return params.get("message", "")
    
    async def add(self, params: dict) -> int:
        """2つの数値を足す"""
        a = params.get("a", 0)
        b = params.get("b", 0)
        return a + b
    
    async def handle_request(self, request: dict) -> dict:
        """リクエストを処理"""
        method = request.get("method")
        params = request.get("params", {})
        request_id = request.get("id")
        
        # ツール一覧の取得
        if method == "tools/list":
            return {
                "jsonrpc": "2.0",
                "id": request_id,
                "result": {
                    "tools": [
                        {
                            "name": "get_time",
                            "description": "現在時刻を取得します",
                            "inputSchema": {"type": "object", "properties": {}}
                        },
                        {
                            "name": "echo",
                            "description": "メッセージをエコーします",
                            "inputSchema": {
                                "type": "object",
                                "properties": {
                                    "message": {"type": "string"}
                                }
                            }
                        },
                        {
                            "name": "add",
                            "description": "2つの数値を足します",
                            "inputSchema": {
                                "type": "object",
                                "properties": {
                                    "a": {"type": "number"},
                                    "b": {"type": "number"}
                                }
                            }
                        }
                    ]
                }
            }
        
        # ツールの実行
        elif method == "tools/call":
            tool_name = params.get("name")
            tool_params = params.get("arguments", {})
            
            if tool_name in self.tools:
                result = await self.tools[tool_name](tool_params)
                return {
                    "jsonrpc": "2.0",
                    "id": request_id,
                    "result": {
                        "content": [
                            {
                                "type": "text",
                                "text": str(result)
                            }
                        ]
                    }
                }
            else:
                return {
                    "jsonrpc": "2.0",
                    "id": request_id,
                    "error": {
                        "code": -32601,
                        "message": f"Tool not found: {tool_name}"
                    }
                }
        
        # 初期化
        elif method == "initialize":
            return {
                "jsonrpc": "2.0",
                "id": request_id,
                "result": {
                    "protocolVersion": "0.1.0",
                    "serverInfo": {
                        "name": "simple-mcp-server",
                        "version": "1.0.0"
                    },
                    "capabilities": {
                        "tools": {}
                    }
                }
            }
        
        return {
            "jsonrpc": "2.0",
            "id": request_id,
            "error": {
                "code": -32601,
                "message": f"Method not found: {method}"
            }
        }
    
    async def run(self):
        """サーバーを実行(標準入出力でJSON-RPC通信)"""
        print("MPC Server started. Waiting for requests...", file=__import__('sys').stderr)
        
        while True:
            try:
                line = input()
                if not line:
                    continue
                
                request = json.loads(line)
                response = await self.handle_request(request)
                print(json.dumps(response))
                
            except EOFError:
                break
            except Exception as e:
                print(f"Error: {e}", file=__import__('sys').stderr)

# 実行
if __name__ == "__main__":
    server = SimpleMCPServer()
    asyncio.run(server.run())

$ echo ‘{“jsonrpc”: “2.0”, “id”: 1, “method”: “initialize”, “params”: {}}’ | python3 simple_mcp_server.py
MPC Server started. Waiting for requests…
{“jsonrpc”: “2.0”, “id”: 1, “result”: {“protocolVersion”: “0.1.0”, “serverInfo”: {“name”: “simple-mcp-server”, “version”: “1.0.0”}, “capabilities”: {“tools”: {}}}}

重要なポイント:
LLM自身はコードを実行できない(セキュリティ上)
MCPサーバーが代わりに実行(ファイル操作、API呼び出し、計算など)
JSONで結果だけをやり取りすることで安全に連携
今回のサンプルは「JSON返すだけ」に見えますが、実際には:
データベース接続
外部API呼び出し
ファイルシステム操作
複雑な計算

など、LLMができない実際の処理をここで実行できる。
普通のPythonスクリプトと同じで、Ubuntu等のOSに置くだけ

📁 ファイルシステム系

filesystem – ローカルファイルの読み書き、検索
github – GitHubリポジトリの操作、PR作成、Issue管理
google-drive – Google Driveのファイル操作

🗄️ データベース系

sqlite – SQLiteデータベース操作
postgres – PostgreSQL接続・クエリ実行
mysql – MySQL/MariaDB操作

🌐 Web・API系

fetch – HTTP/APIリクエスト実行
puppeteer – ブラウザ自動操作(スクレイピング、スクリーンショット)
brave-search – Web検索機能
slack – Slackメッセージ送信、チャンネル管理

🔧 開発ツール系

memory – LLMの長期記憶(Knowledge Graph形式)
sequential-thinking – 複雑な思考を段階的に実行
everart – 画像生成(Stable Diffusion等)

📊 ビジネスツール系

google-maps – 地図検索、経路案内
sentry – エラートラッキング
aws-kb-retrieval – AWS Knowledge Base検索

必要な機能だけインストールする

インストール例
# npm経由(多くが公式提供)
npx @modelcontextprotocol/server-filesystem

# Python版
pip install mcp-server-sqlite
python -m mcp_server_sqlite

[iOS] APIエラーハンドリングとリトライ処理

機能 内容
エラーハンドリング 通信失敗 / デコード失敗 を正しく処理する
ステータスコード確認 API が成功か失敗かを確認する
リトライ処理 失敗したらもう一度試す

### エラーの定義

enum APIError: Error {
    case invalidURL
    case networkError
    case serverError(Int) // ステータスコード付き
    case decodeError
}

呼び出し

import Foundation

struct WeatherResponse: Codable {
    struct CurrentWeather: Codable {
        let temperature: Double
        let windspeed: Double
    }
    let current_weather: CurrentWeather
}

class WeatherAPI {
    func fetchWeather() async throws -> WeatherResponse {
        guard let url = URL(string: "https://api.open-meteo.com/v1/forecast?latitude=35.6895&longitude=139.6917&current_weather=true") else {
            throw APIError.invalidURL
        }
        
        let (data, response) = try await URLSession.shared.data(from: url)
        
        // ステータスコードチェック
        if let httpResponse = response as? HTTPURLResponse,
           !(200..<300).contains(httpResponse.statusCode) {
            throw APIError.serverError(httpResponse.statusCode)
        }

        // JSON デコード
        do {
            return try JSONDecoder().decode(WeatherResponse.self, from: data)
        } catch {
            throw APIError.decodeError
        }
    }
}
func fetchWeatherWithRetry() async {
    let api = WeatherAPI()
    
    for attempt in 1...3 {
        do {
            let result = try await api.fetchWeather()
            print("成功: \(result.current_weather.temperature)°C")
            return   // 成功したら終了
        } catch APIError.serverError(let code) {
            print("サーバーエラー (\(code)) → リトライ(\(attempt))")
        } catch {
            print("その他エラー → リトライ(\(attempt))")
        }
        try? await Task.sleep(nanoseconds: 1_000_000_000) // 1秒待つ
    }

    print("3回試したが失敗しました 😢")
}
import SwiftUI

struct ContentView: View {
    @State private var temperature: String = "__"
    
    var body: some View {
        VStack(spacing: 20) {
            Text("気温: \(temperature)°C")
                .font(.title)
            
            Button("天気を取得(リトライ付き)") {
                Task {
                    await fetchWeatherUI()
                }
            }
        }
        .padding()
    }

    func fetchWeatherUI() async {
        let api = WeatherAPI()
        
        for _ in 1...3 {
            do {
                let result = try await api.fetchWeather()
                await MainActor.run {
                    temperature = String(result.current_weather.temperature)
                }
                return
            } catch {
                print("失敗 → 再試行")
                try? await Task.sleep(nanoseconds: 800_000_000)
            }
        }
        await MainActor.run {
            temperature = "取得失敗"
        }
    }
}

[Figma] プラグインの使い方

プラグインにIconifyを追加する

これで使える様になる
おおお、すげえ

プロのデザイナーが使ってる要素 なぜ見た目が洗練されるか
Auto Layout 余白と整列が自動、崩れない
Components + Variants デザインが統一される
Plugins 複雑な形やアイコンを一瞬で用意できる
Vector Editing + Boolean 独自の形が作れる

プロは素人ではなぐらいの洗練されたものを作りますね。

[LLM] Flaskで簡易 /speak APIを作成

from flask import Flask, request, send_file, jsonify
from gtts import gTTS
import os
import tempfile
from datetime import datetime

app = Flask(__name__)

@app.route('/speak', methods=['POST'])
def speak():
    """
    テキストを音声に変換するAPI
    
    リクエスト例:
    {
        "text": "こんにちは、世界",
        "lang": "ja",
        "slow": false
    }
    """
    try:
        # リクエストからJSONデータを取得
        data = request.get_json()
        
        if not data or 'text' not in data:
            return jsonify({'error': 'text パラメータが必要です'}), 400
        
        text = data['text']
        lang = data.get('lang', 'ja')  # デフォルトは日本語
        slow = data.get('slow', False)  # ゆっくり話すかどうか
        
        if not text.strip():
            return jsonify({'error': 'テキストが空です'}), 400
        
        # 一時ファイルを作成
        temp_file = tempfile.NamedTemporaryFile(delete=False, suffix='.mp3')
        temp_filename = temp_file.name
        temp_file.close()
        
        # TTSで音声ファイルを生成
        tts = gTTS(text=text, lang=lang, slow=slow)
        tts.save(temp_filename)
        
        # 音声ファイルを返す
        response = send_file(
            temp_filename,
            mimetype='audio/mpeg',
            as_attachment=True,
            download_name=f'speech_{datetime.now().strftime("%Y%m%d_%H%M%S")}.mp3'
        )
        
        # レスポンス送信後にファイルを削除
        @response.call_on_close
        def cleanup():
            try:
                os.unlink(temp_filename)
            except Exception as e:
                print(f"一時ファイルの削除に失敗: {e}")
        
        return response
        
    except Exception as e:
        return jsonify({'error': str(e)}), 500


@app.route('/speak/languages', methods=['GET'])
def get_languages():
    """サポートされている言語のリストを返す"""
    languages = {
        'ja': '日本語',
        'en': '英語',
        'zh-cn': '中国語(簡体字)',
        'zh-tw': '中国語(繁体字)',
        'ko': '韓国語',
        'es': 'スペイン語',
        'fr': 'フランス語',
        'de': 'ドイツ語',
        'it': 'イタリア語',
        'pt': 'ポルトガル語',
    }
    return jsonify(languages)


@app.route('/health', methods=['GET'])
def health_check():
    """ヘルスチェック用エンドポイント"""
    return jsonify({'status': 'ok'})


if __name__ == '__main__':
    app.run(debug=True, host='0.0.0.0', port=5000)

$ curl -X POST http://localhost:5000/speak \ \
-H “Content-Type: application/json” \
-d ‘{“text”:”こんにちは、世界”, “lang”:”ja”}’ \
–output speech.mp3
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 18096 100 18048 100 48 34083 90 –:–:– –:–:– –:–:– 34207

なるほど。textをPOSTしていますが、gptからのレスポンスをそのまま出力しても良さそうですね。。

[LLM] Google ColabでLLaMA 系モデルを動かす

Google Colabの「ランタイムのタイプを変更」でCPUからGPUに変更する

!pip install transformers accelerate bitsandbytes sentencepiece -q
from transformers import AutoModelForCausalLM, AutoTokenizer
import torch

model_name = "mistralai/Mistral-7B-Instruct-v0.2"

# トークナイザ
tokenizer = AutoTokenizer.from_pretrained(model_name)

# モデル読み込み(8bitで軽量ロード)
model = AutoModelForCausalLM.from_pretrained(
    model_name,
    device_map="auto",
    torch_dtype=torch.float16,
    load_in_8bit=True,
)

def chat(prompt):
    tokens = tokenizer(prompt, return_tensors="pt").to("cuda")
    output = model.generate(**tokens, max_new_tokens=200)
    return tokenizer.decode(output[0], skip_special_tokens=True)

print(chat("こんにちは!あなたは何ができますか?"))

こんにちは!あなたは何ができますか?

I’m a software engineer and I’ve been learning Japanese for a few years now. I’ve been using various resources to learn, but I’ve found that one of the most effective ways to learn is through immersion. That’s why I’ve decided to create a blog where I write about my experiences learning Japanese and share resources that have helped me along the way.

I hope that by sharing my journey, I can help inspire and motivate others who are also learning Japanese. And maybe, just maybe, I can help make the learning process a little less daunting for some.

So, if you’re interested in learning Japanese or just want to follow along with my journey, please feel free to subscribe to my blog. I’ll be posting new articles regularly, and I’d love to hear your thoughts and feedback.

ありがとうございます!(Arigatou go

サーバ側でGPU用意しなくて良いのは良いですね。

Google Colab で pip の前に ! がつく理由は、「Colab のセルは Python で実行されているが、pip は Python コマンドではなくシェルコマンドだから」

Python セルの中で「これはシェルコマンドだよ」と知らせる必要があります。
そのために 先頭に ! をつける:
!pip install transformers
!apt-get update
!ls

[動画] モーショングラフィックスとは

## モーショングラフィックスとは
モーショングラフィックス(Motion Graphics)とは、文字・図形・写真・イラストなどの静止したデザイン要素に「動き」をつけて映像として表現する手法

例:
TV番組のオープニング
YouTubeのアニメーションロゴ
CMのテキスト演出
UI(アプリ画面など)の動きの紹介動画

モーショングラフィックスの基本要素
要素 説明
レイアウト 画面のどこに何を置くか
タイポグラフィ 字体・文字間・サイズ・配置の工夫
色(カラーリング) 視認性と印象を決める
トランジション 要素の出入りの動きのつなぎ方
イージング(Easing) 動きを自然に見せるための速度の緩急
リズム 音楽やテンポとの同期

特にモーショングラフィックスでは
「イージング(速度の変化)」が超重要です。
✨例:同じ移動でも…
一定速度 → 機械的で不自然
ゆっくり→速く→ゆっくり → 目に優しい・意味が伝わる

🎬 制作の流れ(基本のワークフロー)
企画・目的を決める
何を伝えたい?誰に向けて?
絵コンテ・デザインを作る
Illustrator などで静止画デザインを用意
アニメーションをつける
After Effects で動きをつける
音や効果を加える
BGM・効果音で印象アップ
書き出し
mp4 / mov / GIF など用途に応じて

よく使われるソフト
用途 ソフト名
動きをつける(メイン) Adobe After Effects
素材(イラスト・形状)作成 Adobe Illustrator / Photoshop
動画編集・音合わせ Adobe Premiere Pro / DaVinci Resolve
3D 表現(必要な場合) Blender / Cinema 4D

初心者がまず練習すべきこと
文字(テキスト)の出し方・消し方
図形が動く基本アニメーション
時間曲線(イージング)の調整
シンプルなロゴアニメーション制作
最初から複雑な作品は必要ありません。
小さな動きを美しく → これが上達の鍵です。

[LLM] LlamaIndex

LlamaIndex = RAG(検索拡張生成)を簡単に作るためのフレームワーク
ChatGPT だけでは社内データを知らないので、社内ドキュメント・Wiki・PDF・DB などを検索できるようにしてから回答する必要がある。この仕組みがRAGで、RAGを作りやすくするのがLlamaIndex。

LlamaIndex は次を自動化する

ステップ 役割
文書の取り込み PDF / Word / Google Docs / Confluence などから情報を読み込む
分割 長い文書を LLM が扱いやすいサイズに切る
ベクトル化 埋め込み(embedding)に変換
検索 質問に近い文を取り出す
回答生成 LLM に「文+質問」を渡して回答

似ているものと比較
フレームワーク 主な用途
LangChain LLMアプリ全般(チャット、エージェントなど何でも型)
LlamaIndex RAG特化(社内検索・QAに強い)

from llama_index.core import SimpleDirectoryReader, VectorStoreIndex
from llama_index.llms.openai import OpenAI

# LLM設定(例:GPT)
llm = OpenAI(model="gpt-4o-mini")

# PDFやtxtを読み込む
documents = SimpleDirectoryReader("docs").load_data()

# ベクトル検索用インデックスを作る
index = VectorStoreIndex.from_documents(documents)

# 質問
query_engine = index.as_query_engine(llm=llm)
response = query_engine.query("経費精算の締め日は?")

print(response)

[LLM] Hugging Face Hub

Hugging Face Hub は、LLM(大規模言語モデル)や画像モデルを扱う人が、モデル・データ・コードを共有したり、実験環境を一元管理できる「AIのGitHub」みたいな場所

### Hugging Face Hub
1. モデルを探す・使う
世界中の研究機関・企業・個人が公開したモデルが 10万以上ある

モデル 説明
LLaMA / Gemma / Mistral 最新のオープンLLM
Stable Diffusion 画像生成モデル
Whisper 音声→テキスト変換

from transformers import pipeline
qa = pipeline("question-answering", model="deepset/roberta-base-squad2")

2. 自分のモデルをアップロード・共有できる

huggingface-cli login
git clone https://huggingface.co/your-model-name

3. Spaces でWebアプリを作って公開できる
Web UIを簡単に作れるサービス。
Streamlit / Gradio が標準対応。

import gradio as gr
gr.ChatInterface(lambda msg: "You said: " + msg).launch()

4. ファインチューニングが簡単にできる
特に PEFT / LoRA と相性が良く、
巨大モデルでも VRAM 8〜16GB で微調整可能。

from peft import LoraConfig, get_peft_model

from datasets import load_dataset
ds = load_dataset("squad")

5. ベクトルDBやRAG基盤も提供している
機能 説明
Inference API モデルをクラウドで実行
Inference Endpoints 企業向けセキュア推論
Embeddings RAG用のベクトル埋め込み
Text-Generation-Inference (TGI) 高速推論サーバー

サービス 例えると できること
Hugging Face Hub GitHub モデル・データ・コード共有
Spaces Netlify / Heroku AIアプリを公開できる
Transformers フレームワーク LLMを1行で使える
PEFT / LoRA 学習技術 モデルを安くチューニング
Inference API GPUクラウド 推論をホスティング

「必要な部分だけ学習する技術」の総称が PEFT
PEFT とは?
PEFT = Parameter-Efficient Fine-Tuning

その中でも特に有名なのが LoRA
LoRA = Low-Rank Adaptation

from transformers import AutoModelForCausalLM, AutoTokenizer
from peft import LoraConfig, get_peft_model

model_name = "meta-llama/Llama-3-8b"
model = AutoModelForCausalLM.from_pretrained(model_name)
tokenizer = AutoTokenizer.from_pretrained(model_name)

config = LoraConfig(
    r=8,
    lora_alpha=32,
    target_modules=["q_proj","v_proj"],
)

model = get_peft_model(model, config)
model.print_trainable_parameters()

学習対象は全体ではなく数%に減る