[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()
    }
}

なるほど〜

LLMの学習方法(事前学習、FineTuning, RLHF)

LLMの学習方法は大きく分けて3つある

1. 事前学習(Pre-training)
目的:
「言語の基礎的な知識」を身につける段階
文法・語彙・一般常識・文脈の理解などを、膨大なテキストから学ぶ

方法:
教師なし学習(Self-supervised learning)
入力文の一部を隠して、隠された部分を予測する(=マスク言語モデル、例:BERT)
次の単語を予測する(=自己回帰モデル、例:GPT系列)

データ:
インターネット上のテキスト(Webページ、書籍、Wikipediaなど)
数百億〜数兆トークン規模

2. ファインチューニング(Fine-tuning)
目的:
事前学習で得た「言語の基礎力」を、特定の目的や用途に合わせて調整

方法:
教師あり学習(Supervised fine-tuning)
入力と正解(出力)のペアを与える。
例:「質問 → 回答」「命令 → 応答」
少量の高品質データで調整。

3.人間のフィードバックによる強化学習(RLHF: Reinforcement Learning from Human Feedback)
目的:
モデルの出力を「人間にとって好ましい形」にする。
(=有用で、正確で、安全で、自然な応答にする)

① SFTモデル(ファインチューニング済)を使って、複数の応答候補を生成。
② 人間の評価者が「どの回答が良いか」を順位付け。
**③ 報酬モデル(Reward Model)**を学習。
→ 「この応答が好ましい」と判断するスコア関数を作る。
**④ 強化学習(PPOなど)**でモデルを更新し、報酬が高い出力を出すように最適化。

### Pretraining

import torch
import torch.nn as nn
import torch.optim as optim

text = "I love AI . AI loves people ."
vocab = list(set(text.split()))
word2idx = {w:i for i,w in enumerate(vocab)}
idx2word = {i:w for w,i in word2idx.items()}

def make_data(text):
    words = text.split()
    X, Y = [], []
    for i in range(len(words)-2):
        X.append([word2idx[words[i]], word2idx[words[i+1]]])
        Y.append(word2idx[words[i+2]])
    return torch.tensor(X), torch.tensor(Y)


X, Y = make_data(text)

class TinyLM(nn.Module):
    def __init__(self, vocab_size, hidden_size=8):
        super().__init__()
        self.emb = nn.Embedding(vocab_size, hidden_size)
        self.fc = nn.Linear(hidden_size*2, vocab_size)

    def forward(self, x):
        x = self.emb(x).view(x.size(0), -1)
        return self.fc(x)

model = TinyLM(len(vocab))
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.01)

for epoch in range(200):
    output = model(X)
    loss = criterion(output, Y)
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

test = torch.tensor([[word2idx["I"], word2idx["love"]]])
pred = torch.argmax(model(test), dim=1)
print("Predicted next word:", idx2word[pred.item()])

### Fine tuning

train_data = [
    ("Hello", "Hi there!"),
    ("How are you?", "I'm fine, thank you."),
    ("Bye", "Goodbye!")
]

from transformers import AutoTokenizer, AutoModelForCausalLM, Trainer, TrainingArguments

tokenizer = AutoTokenizer.from_pretrained("gpt2")
model = AutoModelForCausalLM.from_pretrained("gpt2")

# データを整形
inputs = [tokenizer(f"User: {q}\nAI:", return_tensors="pt") for q, _ in train_data]
labels = [tokenizer(a, return_tensors="pt")["input_ids"] for _, a in train_data]

# 学習っぽいループ
for i, (inp, lab) in enumerate(zip(inputs, labels)):
    out = model(**inp, labels=lab)
    loss = out.loss
    loss.backward()
print("Fine-tuning step complete ✅")

### RLHF

import random

# モデルの応答候補
responses = ["Sure, here’s an example.", "I don’t know.", "You’re stupid."]

# 人間が選んだランキング(良い順)
human_ranking = {"Sure, here’s an example.": 1, "I don’t know.": 0, "You’re stupid.": -1}

# 報酬モデル(スコア関数)を模擬
def reward(response):
    return human_ranking[response]

# 強化学習っぽい更新(高報酬応答を強化)
policy = {r: 0.0 for r in responses}
for _ in range(10):
    r = random.choice(responses)
    policy[r] += reward(r) * 0.1

print("Learned policy:", policy)

[android]Composeのanimate関数

class MainActivity : ComponentActivity() {

    overrider fun onCreate(savedInstanceState: Bundle?){
        super.onCreate(saveInstanceState)
        setContent {
            MaterialTheme {
                AnimatedBoxExample()
            }
        }
    }

    @Composable
    fun AnimatedBoxExample() {
        var expaned by remember {mutableStateOf(false)}

        val boxSize by animateDpAsState(
            targetValue = if(expanded) 200.dp else 100.dp,
            label ="BoxSizeAnimation"
        )

        Column(
            modifier = Modifier
                .fillMaxSize()
                .padding(32.dp),
            verticalArrangement = Arrangement.Center,
            horizontalAlignment = Alignment.CenterHorizontally
        ) {
            Box(
                modifier = Modifier
                    .size(boxSize)
                    .padding(8.dp),
                contentAlignment = Alignment.Center
            ) {
                color = MaterialTheme.colorScheme.primary,
                modifier = Modifier.fillMaxSize()
            } {}
        }
        Spacer(modifier = Modifier.height(16.dp))

        Button(onClick= {expanded = !expanded}) {
            Text(text =if (expanded) "縮小する" else "拡大する")
        }
    }
}

animateDpAsState:Dp 値を滑らかにアニメーションさせます。
targetValue:アニメーションで変化させたい目標値。
expanded を切り替えることで、Boxのサイズが 100.dp ↔ 200.dp にアニメーション付きで変化。

[LLM] トランスフォーマー構造の概要とAttentionの考え方

## 1. トランスフォーマーとは?
トランスフォーマーは2017年に登場した自然言語処理のニューラルネットワーク構造
RNNやCNNと違って系列データの処理を並列化できるのが最大の特徴
– 入力: 文章(単語やトークンに分けたもの)
– 出力: 文章の予測や分類など
– 主な構成:
1. エンコーダ: 入力を内部表現に変換
2. デコーダ: 内部表現から出力を生成
LLM(ChatGPTなど)は、基本的にデコーダ中心のトランスフォーマを使っている

## Attentionの考え方
Attentionは「文章の中でどの単語に注目すべきかを学習する仕組み」
文章: 「猫がネズミを追いかける」
「追いかける」を予測するとき、
「猫」が主語だから重要
「ネズミ」も目的語として重要
他の単語(「が」や「を」)はそれほど重要ではない
これを 数値化して重み付け するのが Attention の仕組み

## Self-Attentionの仕組み
トランスフォーマーでは 各単語が文章の他の単語を参照して特徴を作る
これを Self-Attention と呼ぶ

Query (Q):注目するための質問
Key (K):候補の特徴
Value (V):候補の情報

Query と Key の内積 → 「どれくらい注目すべきか」を示すスコア
Softmax で正規化 → 重みを 0〜1 に
Value に重みをかけて足し合わせ → 注目した情報の合成

## Multi-Head Attention
Attention は 1種類の見方だけでなく、複数の異なる視点で注目することができます。
これを Multi-Head Attention と呼ぶ

例:
1つ目のヘッド:主語と動詞の関係に注目
2つ目のヘッド:目的語と動詞の関係に注目
これにより、文脈を多面的に理解できる

なるほど~

[iOS/Swift] ネットワーク通信

swiftでネットワーク通知を学ぶ
– URLSession でAPIを叩く(例:天気アプリでAPIから天気データを取得)
– JSONデータのデコード(Codable)

対象API
https://api.open-meteo.com/v1/forecast?latitude=35.6895&longitude=139.6917&current_weather=true

データ

{
    "latitude":35.6895,
    "longitude":139.6917,
    "generationtime_ms":0.234,
    "utc_offset_seconds":0,
    "current_weather":{
        "temperature":28.3,
        "windspeed":5.2,
        "winddirection":90
    }
}

Swiftの場合だと、New Group で新規 Views, Modelsなどのディレクトリを作成する
– Views:画面用の SwiftUI View ファイルを入れる
– Models:JSON の Codable 構造体やデータモデルを入れる
models/Weather.swift

import Foundation

struct WeatherResponse: Codable {
    let current_weather: CurrentWeather
}

struct CurrentWeather: Codable {
    let temperature: Double
    let windspeed: Double
    let winddirection: Double
}

ContentView

import SwiftUI

struct ContentView: View {
    @State private var temperature: String = "__"
    @State private var windspeed: String = "__"
    
    var body: some View {
        VStack(spacing: 20) {
            Text("東京の現在天気")
                .font(.title)
            
            Text("気温: \(temperature)°C")
            Text("風速: \(windspeed)m/s")
            
            Button("天気を取得") {
                fetchWeather()
            }
        }
        .padding()
    }
    
    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 ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

うおおおおおおおお、何だこれは すげえ

ポイント
– URLSession.shared.dataTask で非同期に API を叩く
– Codable で JSON を Swift の構造体にデコード
– DispatchQueue.main.async で UI 更新
– @State で変数をバインドして、UI に表示