[figma] Motion / Interaction(アニメーション・状態変化)

1. Motion / Interaction の概念理解
Figmaでの「モーション」「インタラクション」は以下の2つを組み合わせて作る
– Variant(状態): デザイン上の“見た目の変化”, Default / Hover / Pressed など
– Prototype(遷移・動き): 状態や画面を“動的につなぐ”, クリックで次の画面へ、ホバーで色変化など

prototypeのプレビューでoverlayすると、画面が切り替わる

おおおおおおおお、すげぇええええええええ 
ちょっと世界観変わったぜ!

[iOS] Combine / Swift Concurrency(async/await)

非同期で呼び出す仕組み

import SwiftUI

struct ContentView: View {
    @State private var temperature: String = "__"
    @State private var windspeed: String = "__"
    @State private var showSheet = false
    
    var body: some View {
        VStack(spacing: 20) {
            Text("東京の現在天気")
                .font(.title)
            
            Text("気温: \(temperature)°C")
            Text("風速: \(windspeed)m/s")
            
            Button("天気を取得") {
                Task {
                    await fetchWeather()
                }
            }
            
            Button("詳細を表示(ボトムシート)") {
                showSheet = true
            }
        }
        .padding()
        .sheet(isPresented: $showSheet) {
            BottomSheetView(
                temperature: temperature,
                windspeed: windspeed
            )
            .presentationDetents([.fraction(0.3), .medium, .large])
            .presentationDragIndicator(.visible)
        }
    }
    
    func fetchWeather() async {
        guard let url = URL(string: "https://api.open-meteo.com/v1/forecast?latitude=35.6895&longitude=139.6917&current_weather=true") else { return }
        
        do {
            // 非同期で通信(完了を待つ)
            let (data, _) = try await URLSession.shared.data(from: url)
            let decoded = try JSONDecoder().decode(WeatherResponse.self, from: data)

            // メインスレッドでUI更新
            await MainActor.run {
                self.temperature = String(decoded.current_weather.temperature)
                self.windspeed = String(decoded.current_weather.windspeed)
            }
        } catch {
            print("エラー: \(error.localizedDescription)")
        }
    }
}


struct BottomSheetView: View {
    let temperature: String
    let windspeed: String
    
    var body: some View {
        VStack(spacing: 16) {
            Text("詳細情報")
                .font(.title3)
                .bold()
            Text("気温: \(temperature)°C")
            Text("風速: \(windspeed)m/s")
            Text("データ提供: open-meteo.com")
                .font(.footnote)
                .foregroundColor(.gray)
        }
        .padding()
    }
}

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

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

fetchWeather() に async を付ける 非同期処理を行う関数になる
Task { await fetchWeather() } SwiftUI のボタン内で非同期関数を呼ぶための安全な方法
try await URLSession.shared.data(from:) 通信が完了するまで待機(コールバック不要)
await MainActor.run { … } UI更新は常にメインスレッドで行う

うん、asyncは他の言語でもよく出てくるのでわかりやすい。

[LLM] オープンモデルとクローズドモデル

「オープンモデル」は中身が公開されていて自由に使える
「クローズドモデル」は中身が非公開で、企業のサーバー経由でしか使えないモデル

### オープンモデル(Open Model)
モデルの中身(重み・コード)が公開されている
研究者・開発者が自由にダウンロードして、改良・再学習できる
オフラインでも動かせる(ローカル環境で実行可能)

代表例
LLaMA 3(Meta社)
Mistral / Mixtral
Falcon
Gemma(Googleのオープン版)
Japanese StableLM(日本語特化)

### クローズドモデル(Closed Model)
■特徴
モデルの中身(重み)は非公開
提供企業(OpenAI, Googleなど)のAPIを通じて利用する
モデルの更新や最適化は提供企業が行う

■代表例
GPTシリーズ(OpenAI)
Claude(Anthropic)
Gemini(Google)
Command R+(Cohere)

超軽量モデル
$ pip3 install accelerate

from transformers import pipeline

# 軽量モデル(日本語対応)
pipe = pipeline(
    "text-generation",
    model="cyberagent/open-calm-1b",  # 約1Bの日本語モデル
)

prompt = "オープンモデルとクローズドモデルの違いを教えてください。"
result = pipe(prompt, max_new_tokens=150)
print(result[0]['generated_text'])

モデルを動かすにはGPUがないとキツそう…

[android] bearer tokenの使いたい

/data/api/ApiService.kt

interface ApiService {
    @GET("user/profile")
    suspend fun getUserProfile(): Response<UserProfile>
}

data/api/AuthInterceptor.kt

class AuthInterceptor(private val tokenProvider: ()-> String?):Interceptor {
    override fun intercept(chain: Interceptor.Chain): Response {
        val token = tokenProvider()
        val request = chain.request().newBuilder().apply {
            token?.let {
                addHeader("Authorization", "Bearer $it")
            }
        }.build()
        return chain.proceed(request)
    }
}

data/api/ApiClient.kt

object ApiClient {
    fun create(tokenProvider: () -> String?): ApiService {
        val client = OkHttpClient.Builder()
            .addInterceptor(AuthInterceptor(tokenProvider))
            .build()

        return Retrofit.Builder()
            .baseUrl("https://your-api.com/") // 実際のURLに変更
            .client(client)
            .addConverterFactory(GsonConverterFactory.create())
            .build()
            .create(ApiService::class.java)
    }
}

presentation/viewmodel/MyViewModel.kt

class MyViewModel : ViewModel() {
    private val token = ""

    private val apiService = ApiClient.create {token}

    var userProfile by mutableStateOf<UserProfile?>(null)
        private set

    fun loadUserProfile() {
        viewModelScope.launch {
            try {
                val response = apiService.getUserProfile()
                if (response.isSuccessful) {
                    userProfile = response.body()
                } else {
                    // エラー処理
                }
            } catch (e: Exception) {
                // 通信エラーなど
            }
        }
    }

}

presentation/screen/ProfileScreen.kt

@Composable
fun ProfileScreen(viewModel: MyViewModel = viewModel()) {
    val profile = viewModel.userProfile

    LaunchedEffect(Unit) {
        viewModel.loadUserProfile()
    }

    profile?.let {
        Text("ユーザー名: ${it.name}")
    } ?: Text("読み込み中...")
}

domain/model/UserProfile.kt

data class UserProfile(
    val id: Int,
    val name: String,
    val email: String
)

[iOS] Bearer Token

■Bearer Tokenの仕組み
1. サーバーがユーザにアクセストークンを発行(OAuth2などで取得)
2. クライアント(iOSアプリ)はAPIリクエスト時にHTTPヘッダにトークンを付与
3. サーバ側でトークンを検証し、アクセス許可を判断

Header example

Authorization: Bearer <YOUR_ACCESS_TOKEN>

を実際のトークンに置き換える
トークンは Keychain に安全に保存するのが推奨
HTTPS で通信することが必須

    func fetchWeather() {
        
        guard let url = URL(string: "https://api.example.com/weather") else { return }
        
        var request = URLRequest(url: url)
        request.httpMethod = "GET"
        let token = "YOUR_ACCESS_TOKEN"
        request.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
        
        URLSession.shared.dataTask(with: request) { data, response, error in
                if let data = data {
                    do {
                        let decoded = try JSONDecoder().decode(WeatherResponse.self, from: data)
                        DispatchQueue.main.async {
                            self.temperature = String(decoded.current_weather.temperature)
                            self.windspeed = String(decoded.current_weather.windspeed)
                        }
                    } catch {
                        print("JSONデコードエラー: \(error)")
                    }
                } else if let error = error {
                    print("通信エラー: \(error)")
                }
            }.resume()
    }

[Figma] colorのstyleの登録

Fillから「+」でstyleを選択して、登録したいstyle nameを入れる

フリーのアイコンサイト
https://www.flaticon.com/

■SVGのメリット
ベクター形式:拡大・縮小しても画質が劣化しない
編集可能:Figma上で色やサイズを自由に変更できる
軽量:同じ解像度のPNGよりファイルサイズが小さい場合が多い
デザインシステムとの相性:コンポーネント化して再利用しやすい

■PNGを使う場合
ラスタ形式:解像度に依存するので拡大するとぼやける
編集不可:Figma上で色や形を直接変更できない
適した用途:
写真やテクスチャを含むアイコン
細かいグラデーションや影付きアイコン

SVGもコンポーネント化される

なるほど〜 ちょいちょい勉強になるね!

LLMで、GPT系、LLaMA系、Claude、Geminiの違い

1. GPT系
特徴:
汎用性が非常に高く、最も実用化が進んでいる。
**RLHF(人間のフィードバックで学習)**により自然で安全な応答。
GPT-4oは音声・画像・動画も理解するフル・マルチモーダルモデル。
APIやChatGPT経由で商用利用が容易。
用途:
チャットボット、コード生成、文章校正、マルチモーダルアプリなど。

2. LLaMA系(Meta)
代表モデル:LLaMA-2, LLaMA-3, CodeLLaMA
特徴:
**完全オープンモデル(研究・商用利用OK)**として人気。
Hugging Face や Ollama などで簡単にローカル実行できる。
学習データは透明性が高く、再現性や拡張性に優れる。
企業や研究者が 独自ファインチューニングしやすい。

用途:
独自アシスタント、社内LLM開発、RAG(検索拡張生成)など。

3. Claude(Anthropic)
代表モデル:Claude 3 系列(Opus, Sonnet, Haiku)
特徴:
Anthropicは「Constitutional AI(憲法型AI)」という理念を採用。
→ 倫理的原則をあらかじめモデルに教え込み、安全性を確保。
**非常に長いコンテキスト(100k〜200kトークン以上)**を扱える。
文章理解力が高く、長文要約や複雑な推論に強い。
用途:
法務、ドキュメント要約、思考型タスク、知識ワークなど。

4. Gemini(Google DeepMind)
代表モデル:Gemini 1.0 → 1.5 Pro / Flash
特徴:
マルチモーダル統合設計が最初から前提(画像・音声・動画対応)。
高速モデル「Flash」など、応答速度と効率にも力を入れている。
Google 検索や Workspace などと密接に連携。
数学的推論・コード生成能力も非常に強い。

用途:
Google製品内のアシスタント、教育、研究、マルチモーダル処理。

import os
from openai import OpenAI
import google.generativeai as genai
import time
from dotenv import load_dotenv
load_dotenv()

# === APIキー設定 ===
client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
genai.configure(api_key=os.getenv("GOOGLE_API_KEY"))

prompt = "GPTとGeminiの違いを簡潔に説明してください。"

# === GPT呼び出し ===
def call_gpt(prompt):
    start = time.time()
    response = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=[{"role": "user", "content": prompt}],
    )
    latency = time.time() - start
    return {
        "model": "gpt-4o-mini",
        "text": response.choices[0].message.content.strip(),
        "latency": latency,
    }

# === Gemini呼び出し ===
def call_gemini(prompt, model="models/gemini-2.5-flash"):
    start = time.time()
    model_obj = genai.GenerativeModel(model)
    response = model_obj.generate_content(prompt)
    latency = time.time() - start
    return {
        "model": model,
        "text": response.text.strip(),
        "latency": latency,
    }

# === 実行 ===
if __name__ == "__main__":
    print("=== GPT ===")
    gpt_out = call_gpt(prompt)
    print(f"model: {gpt_out['model']} latency(s): {gpt_out['latency']:.2f}")
    print("text:", gpt_out["text"], "\n")

    print("=== Gemini Flash ===")
    gemini_flash_out = call_gemini(prompt, "models/gemini-2.5-flash")
    print(f"model: {gemini_flash_out['model']} latency(s): {gemini_flash_out['latency']:.2f}")
    print("text:", gemini_flash_out["text"], "\n")

    print("=== Gemini Pro ===")
    gemini_pro_out = call_gemini(prompt, "models/gemini-2.5-pro")
    print(f"model: {gemini_pro_out['model']} latency(s): {gemini_pro_out['latency']:.2f}")
    print("text:", gemini_pro_out["text"])

$ python3 compare.py
=== GPT ===
model: gpt-4o-mini latency(s): 6.15
text: GPTとGeminiは、AI言語モデルですが、設計や機能にいくつかの違いがあります。

1. **開発者**:
– GPT(Generative Pre-trained Transformer)は、OpenAIによって開発されました。
– Geminiは、Google DeepMindによって開発されています。

2. **アプローチ**:
– GPTは大規模なテキストデータを用いて事前に学習し、生成タスクに強みを持っています。
– Geminiは、より多様なデータソースを統合し、より広範な知識や能力を持つことを目指しています。

3. **用途**:
– GPTは主に会話、文章生成、質問応答などに利用されます。
– Geminiは、同様の機能を持ちながら、強化学習やマルチモーダル処理などの高度な機能を取り入れることが期待されています。

これらの違いにより、各モデルは異なるニーズや用途に応じて使われることがあります。

=== Gemini Flash ===
WARNING: All log messages before absl::InitializeLog() is called are written to STDERR
E0000 00:00:1760237589.456894 56153 alts_credentials.cc:93] ALTS creds ignored. Not running on GCP and untrusted ALTS is not enabled.
model: models/gemini-2.5-flash latency(s): 8.99
text: GPTとGeminiの最も大きな違いは、**「開発元」**と**「マルチモーダル能力への注力度」**です。

* **GPT(OpenAI製)**
* 主にテキストベースの処理に強みを持つ大規模言語モデルです。自然な会話、文章生成、要約、翻訳などが得意です。元々はテキスト中心で進化してきました。

* **Gemini(Google製)**
* テキストだけでなく、画像、音声、動画といった**複数の情報形式(マルチモーダル)を最初から統合的に理解し、生成すること**に特に注力して開発されています。

どちらも非常に高性能なAIですが、Geminiはより多様な種類の情報を横断的に扱えるように設計されている点が特徴と言えます。

=== Gemini Pro ===
model: models/gemini-2.5-pro latency(s): 13.69
text: はい、承知いたしました。GPTとGeminiの違いを簡潔に説明します。

一番大きな違いは、AIの**「生まれと育ち(設計思想)」**です。

### GPT (OpenAI製) – 「テキストが得意な専門家」

* もともと**テキスト(文章)を極めるために開発**され、後から画像などを認識する能力が追加されました。
* 例えるなら「国語をマスターした人が、後から美術を学んだ」イメージです。
* **得意なこと:** 創造的な文章作成、自然な会話、要約など、言語に関するタスク全般。

### Gemini (Google製) – 「生まれながらのマルチタレント」

* 最初から**テキスト、画像、音声、動画などを同時に扱える**ように設計されています(ネイティブ・マルチモーダル)。
* 例えるなら「国語も美術も音楽も、最初から一緒に学んできた」イメージです。
* **得意なこと:** 画像を見ながら質問に答える、図やグラフを読み解くなど、複数の情報を組み合わせた複雑なタスク。

### まとめ

| | GPT (GPT-4など) | Gemini |
| :— | :— | :— |
| **開発元** | OpenAI | Google |
| **特徴** | テキスト中心に発展 | 最初からマルチモーダル |
| **強み** | **文章生成**や**対話の自然さ** | **画像や音声を含む複合的な質問** |
| **搭載例** | ChatGPT, Microsoft Copilot | Gemini (旧Bard), Google検索 |

どちらも非常に高性能ですが、**文章作成ならGPT**、**画像や音声も絡めた分析ならGemini**といったように、現時点では得意な分野が少し異なります。

—-
このコードで示している「差」の解説

モデル選択(モデル名)

GPT 側は gpt-4o のように「オムニモーダル」かつ会話最適化を想定。
OpenAI
+1

Gemini は flash(低遅延・低コスト向け)と pro(精度重視)などプロファイルがある点を示している。
blog.google
+1

マルチモーダル入力

両者とも画像や音声を扱えるが、実装のインターフェースや得意分野(音声・動画の理解、あるいは空間・映像処理)に差がある。Geminiは特にマルチモーダル統合を重視している。
blog.google
+1

レイテンシとコスト(コード内の time.sleep は擬似)

Gemini の Flash 系は「高速・効率化」をうたっており、高頻度・低遅延なユースケースに向く。OpenAIも GPT-4o で高速化・低コスト化の改善を進めている(モデルと提供形態で差がある)。
blog.google
+1

用途の違い(選び方)

「対話の自然さ・汎用性」と「広いエコシステム連携(Googleサービス)」、さらに「長文コンテキストや特殊なマルチモーダル処理」などで判断する。具体的な要件(コンテキスト長、マルチモーダル比重、レイテンシ、運用コスト、データポリシー)で選ぶのが実務的。
OpenAI
+1

補足(実務でのチェックリスト)

API の利用規約/データ利用方針を必ず確認(トレーニングへの利用、保存、削除ポリシー)。
G2 Learn Hub

日本語・専門分野での品質比較はケースバイケース。ベンチマーク(自分のデータで)を取るのが確実。
labelyourdata.com

大きなコンテキスト(100kトークン以上など)を扱う必要がある場合は、各モデルの「最大コンテキスト長」を確認。

[Dify] Zepプラグインによる長期メモリ活用

■Zepプラグインの主なブロック
1. Initialize Session
新しいセッション(ユーザーごとの会話コンテキスト)を作成
例:ユーザーが初めてチャットを開始するときに使用

2. Get Session Memory
既存セッションの過去の会話や記憶を取得
例:直近の会話履歴や保存しておいたメモを LLM に渡したいとき

3. Add Message to Session
新しいメッセージをセッションに追加(保存)

[Figma] AutoLayoutとは?

1. Auto Layoutとは?
通常のFrameは固定配置ですが、AutoLayoutを設定すると、要素を自動整列できる
– 横並び(ボタン内のアイコン+テキスト)
– 縦並び(フォームのラベル+入力欄)

2. Auto Layoutの設定方法
要素を2つ選択してShift + A

うーん

[iOS] ボトムシートの表示

import SwiftUI

struct ContentView: View {
    @State private var temperature: String = "__"
    @State private var windspeed: String = "__"
    @State private var showSheet = false
    
    var body: some View {
        VStack(spacing: 20) {
            Text("東京の現在天気")
                .font(.title)
            
            Text("気温: \(temperature)°C")
            Text("風速: \(windspeed)m/s")
            
            Button("天気を取得") {
                fetchWeather()
            }
            
            Button("詳細を表示(ボトムシート)") {
                showSheet = true
            }
        }
        .padding()
        .sheet(isPresented: $showSheet) {
            BottomSheetView(
                temperature: temperature,
                windspeed: windspeed
            )
            .presentationDetents([.fraction(0.3), .medium, .large])
            .presentationDragIndicator(.visible)
        }
    }
    
    func fetchWeather() {
        guard let url = URL(string: "https://api.open-meteo.com/v1/forecast?latitude=35.6895&longitude=139.6917&current_weather=true") else { return }
        URLSession.shared.dataTask(with: url) { data, response, error in
            if let data = data {
                do {
                    let decoded = try JSONDecoder().decode(WeatherResponse.self, from: data)
                    DispatchQueue.main.async {
                                            self.temperature = String(decoded.current_weather.temperature)
                                            self.windspeed = String(decoded.current_weather.windspeed)
                                        }
                } catch {
                    print("JSONデコードエラー: \(error)")
                }
            } else if let error = error {
                print("通信エラー: \(error)")
            }
        }.resume()
    }
}


struct BottomSheetView: View {
    let temperature: String
    let windspeed: String
    
    var body: some View {
        VStack(spacing: 16) {
            Text("詳細情報")
                .font(.title3)
                .bold()
            Text("気温: \(temperature)°C")
            Text("風速: \(windspeed)m/s")
            Text("データ提供: open-meteo.com")
                .font(.footnote)
                .foregroundColor(.gray)
        }
        .padding()
    }
}

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

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

なるほど〜