OmniAICreator/Qiita-1.07M huggingface dataset:
【実践編】今すぐ使えるAI技術の最先端プラットフォーム完全ガイド| [第5回] Rustを活用した高性能AIアプリケーション開発

近年、Rustはその高性能性とメモリ安全性から、多くの分野で注目されています。特にAIアプリケーション開発においても、PythonやC++に代わる選択肢としての可能性が高まっています。本記事では、**Rustを活用した高性能AIアプリケーション開発**について、基本的な概念から実装方法まで詳しく解説します。

---

## 1. RustがAI開発に適している理由

Rustは以下の特長を持ち、AIアプリケーション開発に最適です。

- **メモリ安全性**: ガベージコレクションを使わず、安全なメモリ管理が可能。
- **高性能**: C/C++と同等の速度を持ち、大規模データ処理に向いている。
- **並行処理の強さ**: マルチスレッド処理が安全に実装可能。
- **Pythonとの連携**: PyO3やRustPythonを利用してPython環境とも統合可能。

まず、Rust環境をセットアップしましょう。

```bash
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
cargo install cargo-edit
```

また、AI開発に利用するクレート（ライブラリ）を導入します。

```bash
cargo add ndarray tch-rs burn
```

---

## 2. AIモデルの実装

### 2.1. Rustでの行列演算（ndarray）

RustにはNumPyのような行列計算ライブラリ**ndarray**があります。

```rust
use ndarray::{array, Array2};

fn main() {
    let a: Array2<f32> = array![[1.0, 2.0], [3.0, 4.0]];
    let b: Array2<f32> = array![[5.0, 6.0], [7.0, 8.0]];
    let c = a.dot(&b);
    println!("Result: {:?}", c);
}
```

### 2.2. PyTorchをRustで利用（tch-rs）

`Tch-rs`を使用すれば、RustからPyTorchの機能を直接利用できます。

```rust
use tch::{nn, Device, Tensor};

fn main() {
    let device = Device::cuda_if_available();
    let tensor = Tensor::randn(&[3, 3], (tch::Kind::Float, device));
    println!("Generated Tensor: {:?}", tensor);
}
```

### 2.3. Rust製ディープラーニングフレームワーク（Burn）

RustネイティブのAIフレームワーク**Burn**を活用してニューラルネットワークを構築します。

```rust
use burn::{nn::Linear, tensor::Tensor};

fn main() {
    let input = Tensor::from_floats(&[1.0, 2.0, 3.0]);
    let layer = Linear::new(3, 2);
    let output = layer.forward(input);
    println!("Output: {:?}", output);
}
```

---

## 3. RustでAI APIを構築（Axum）

RustでAI推論APIを提供するために、軽量Webフレームワーク**Axum**を利用します。

```rust
use axum::{routing::post, Router, Json};
use serde::{Deserialize, Serialize};
use tch::{Tensor, nn, Device};

#[derive(Serialize, Deserialize)]
struct InputData {
    values: Vec<f32>,
}

#[derive(Serialize)]
struct OutputData {
    prediction: Vec<f32>,
}

#[tokio::main]
async fn main() {
    let app = Router::new().route("/predict", post(predict));
    axum::Server::bind(&"0.0.0.0:8000".parse().unwrap())
        .serve(app.into_make_service())
        .await
        .unwrap();
}

async fn predict(Json(input): Json<InputData>) -> Json<OutputData> {
    let tensor = Tensor::of_slice(&input.values);
    let result = tensor * 2.0;
    Json(OutputData { prediction: result.into() })
}
```

このコードを実行すれば、Rust製のAI推論APIを構築できます。

---

## 4. Rust AIの応用分野

### 4.1. 高速なデータ処理
金融取引やビッグデータ分析でのリアルタイム推論に最適。

### 4.2. エッジAI
軽量で高性能なRustは、IoTデバイスや組み込みシステム向けのAIモデル開発に適している。

### 4.3. ブロックチェーンとAIの融合
Rustはブロックチェーン開発でも多く使われており、AIと組み合わせることで新たな可能性が広がる。

---

## 5. まとめ

本記事では、Rustを活用した高性能AIアプリ開発の基礎から実装までを紹介しました。

✅ **Rustは高性能かつ安全なAI開発に適した言語である**  
✅ **tch-rsを利用すれば、PyTorchと連携可能**  
✅ **Axumを活用すると、Rust製のAI APIを簡単に構築できる**  
✅ **エッジAIやブロックチェーンとの組み合わせも魅力的**  

**RustでのAI開発に興味がある方は、ぜひ試してみてください！**

**「LGTM」＆コメントでフィードバックをお待ちしています！**

---
ANSI ターミナル　エスケープシーケンスのモジュール[Python]

ANSI　ターミナルのエスケープシーケンスを簡単なライブラリにしてみました。
エスケープシーケンスをそのまま書くのはあまりにも判りづらいから、ニモニックにしていただけると幸いです。
全てはカバーしていませんが、よく使うであろうと思われる主要なものを関数化しています。

リファレンス：

https://qiita.com/PruneMazui/items/8a023347772620025ad6

```escseq.py
#!/usr/bin/python3
ESC='\033['
def escup(n=1):
    print(f"{ESC}{n}A",end='')

def escdown(n=1):
    print(f"{ESC}{n}B",end='')

def escright(n=1):
    print(f"{ESC}{n}C",end='')

def escleft(n=1):
    print(f"{ESC}{n}D",end='')

def esclocate(x=0,y=0):
    print(f"{ESC}{y+1};{x+1}H",end='',flush=True)

def escscrollup(n=1):
    print(f"{ESC}{n}S",end='')

def escscrolldown(n=1):
    print(f"{ESC}{n}T",end='')

def escclear():
    print(f"{ESC}2J",end='')
    esclocate()

def esccolor(col1=7,col2=0):
    print(f"{ESC}3{col1}m{ESC}4{col2}m",end='')

def escresetcolor():
    print(f"{ESC}0m",end='')

if __name__=="__main__":
    escclear()
    for i in range(8):
        for j in range(8):
            esccolor(j,i)
            print("#",end='')
    escresetcolor()

```
【実践編】今すぐ使えるAI技術の最先端プラットフォーム完全ガイド| [第3回] LangChain – スマートなデータ処理パイプラインの構築

近年、生成AI（Generative AI）や大規模言語モデル（LLM）の活用が急速に進んでいます。特に、データを動的に処理しながら高度なアプリケーションを構築するためのフレームワークとして **LangChain** が注目されています。

本記事では、**LangChainを活用したスマートなデータ処理パイプラインの構築** 方法を紹介し、実践的なコード例とともに解説します。

---

## 1. LangChainとは？

### 1.1. LangChainの概要

LangChainは、以下の機能を提供するPython向けのフレームワークです：

- **LLMとの統合**: OpenAI、Anthropic、Mistral などのLLMを簡単に利用可能
- **データの検索と処理**: RAG（Retrieval-Augmented Generation）を活用した検索システムの構築
- **エージェントの作成**: LLMを活用した自律的なエージェントの開発
- **ワークフローのオーケストレーション**: API呼び出しやデータ処理を組み合わせたパイプラインの構築

LangChainを使用することで、データ取得、変換、応答生成の各ステップをスムーズに統合できるため、**スマートなデータ処理パイプライン** を実装するのに最適なツールとなります。

---

## 2. LangChainを使ったデータ処理パイプラインの構築

ここでは、LangChainを活用して、外部データを取得し、加工・分析し、最終的にLLMに渡して最適な回答を生成するスマートなパイプラインを構築します。

### 2.1. 必要なライブラリのインストール

まず、Python環境にLangChainと関連ライブラリをインストールします。

```bash
pip install langchain openai faiss-cpu tiktoken requests
```

### 2.2. 外部データの取得（Retrieval）

外部APIからデータを取得し、それをLangChainのパイプラインに組み込みます。

```python
import requests

def fetch_data_from_api():
    url = "https://api.publicapis.org/entries"
    response = requests.get(url)
    if response.status_code == 200:
        return response.json()["entries"]
    return []

# APIから取得したデータを確認
data = fetch_data_from_api()
print(f"取得データ数: {len(data)}")
```

### 2.3. データのベクトル化と検索

取得したデータをベクトル化し、検索エンジン（FAISS）にインデックスを作成します。

```python
from langchain.vectorstores import FAISS
from langchain.embeddings.openai import OpenAIEmbeddings

# OpenAI APIキーの設定
import os
os.environ["OPENAI_API_KEY"] = "your-api-key"

# データをテキスト化
documents = [entry["Description"] for entry in data]

# ベクトル化とインデックス作成
embeddings = OpenAIEmbeddings()
vector_store = FAISS.from_texts(documents, embeddings)
```

### 2.4. LangChainを用いた応答生成（LLM Integration）

ベクトルストアを活用し、LangChainのパイプラインを構築します。

```python
from langchain.chains import RetrievalQA
from langchain.llms import OpenAI

# RAGを活用した検索対応型LLMパイプライン
rag_chain = RetrievalQA.from_chain_type(
    llm=OpenAI(),
    chain_type="stuff",
    retriever=vector_store.as_retriever()
)

# クエリを入力し、最適な回答を取得
query = "無料で使えるAPIをいくつか教えてください。"
response = rag_chain.run(query)

print(response)
```

---

## 3. 応用例 – LangChainを活用したデータパイプライン

LangChainは、以下のような多様なシナリオで活用可能です。

### 3.1. カスタマーサポートボット
顧客の質問に対し、企業のFAQやドキュメントを参照しながら適切な回答を提供するチャットボットを開発可能。

### 3.2. 自動ニュース要約
外部ニュースサイトから情報を取得し、LangChainを用いて要約するアプリケーションを構築可能。

### 3.3. プログラミングアシスタント
GitHubのリポジトリを解析し、コードに関する質問に適切な回答を提供するAIアシスタントを作成。

---

## 4. まとめ

本記事では、LangChainを活用したスマートなデータ処理パイプラインの構築方法について解説しました。

✅ **LangChainはLLMとの統合、データ検索、エージェント作成に適したフレームワーク**  
✅ **APIから取得したデータをベクトル化し、検索対応型のAIシステムを構築可能**  
✅ **LangChainを用いることで、カスタマーサポート、ニュース要約、プログラミングアシスタントなど幅広い分野に応用できる**  

**LangChainを活用して、あなたのAIアプリケーションをスマートに進化させましょう！**

**「LGTM」＆コメントでフィードバックをお待ちしています！**

---
【実践編】今すぐ使えるAI技術の最先端プラットフォーム完全ガイド| [第2回] RAG – 検索と生成を組み合わせた最新AI技術

近年、生成AIの発展に伴い、**RAG（Retrieval-Augmented Generation）**が注目を集めています。RAGは、**検索（Retrieval）**と**生成（Generation）**を組み合わせた技術であり、従来のLLM（大規模言語モデル）の課題を克服し、より正確で文脈に沿った応答を生成することが可能になります。

本記事では、RAGの基本概念、実際の実装方法、そして応用事例について詳しく解説します。

---

## 1. RAGとは？

### 1.1. RAGの仕組み

RAGは、以下の2つの主要なプロセスを組み合わせたアーキテクチャです。

1. **検索（Retrieval）**: 外部のデータソース（データベース、ベクトルストア、ドキュメントなど）から関連情報を検索
2. **生成（Generation）**: 検索した情報を活用し、LLMが適切な応答を生成

従来のLLMは、トレーニング済みのデータに基づいて応答を生成するため、新しい情報を反映するのが困難でした。一方、RAGを活用することで、最新のデータを動的に取得し、より正確な回答を提供できます。

### 1.2. RAGのメリット

- **正確性の向上**: LLM単体よりも事実ベースの回答が可能
- **情報のアップデート**: 外部データを活用するため、モデルを再学習せずに新しい情報を取り入れられる
- **計算コストの削減**: モデル自体を大きくする必要がなく、軽量なままで高性能を実現

---

## 2. RAGの実装方法

ここでは、**LangChain**と**FAISS（Facebook AI Similarity Search）**を用いたRAGの基本的な実装を紹介します。

### 2.1. 必要なライブラリのインストール

まず、Python環境に必要なライブラリをインストールします。

```bash
pip install langchain openai faiss-cpu tiktoken
```

### 2.2. データのインデックス化（Retrieval）

FAISSを利用して、テキストデータをベクトル化し、検索可能なインデックスを作成します。

```python
from langchain.vectorstores import FAISS
from langchain.embeddings.openai import OpenAIEmbeddings

# OpenAIのAPIキーを設定
import os
os.environ["OPENAI_API_KEY"] = "your-api-key"

# 例となるドキュメント
documents = [
    "RAGは検索と生成を組み合わせたAI技術です。",
    "FAISSは高速なベクトル検索を提供します。",
    "LangChainはRAGを簡単に実装できるライブラリです。"
]

# テキストのベクトル化
embeddings = OpenAIEmbeddings()
vector_store = FAISS.from_texts(documents, embeddings)
```

### 2.3. RAGによる応答生成（Generation）

次に、検索結果を活用して、GPTを使った応答生成を行います。

```python
from langchain.chains import RetrievalQA
from langchain.llms import OpenAI

# 検索機能を組み込んだRAGモデルの作成
rag_chain = RetrievalQA.from_chain_type(
    llm=OpenAI(),
    chain_type="stuff",
    retriever=vector_store.as_retriever()
)

# クエリを入力し、回答を取得
query = "RAGとは何ですか？"
response = rag_chain.run(query)

print(response)
```

このコードを実行すると、FAISSが適切な情報を検索し、それをもとにGPTが回答を生成します。

---

## 3. RAGの応用事例

RAGはさまざまな分野で活用されています。

### 3.1. カスタマーサポート
企業のFAQやサポートデータを活用し、ユーザーの問い合わせに対して正確な回答を提供できます。

### 3.2. 医療・法律分野
専門的なドキュメントや論文を検索し、エビデンスベースの回答を生成することで、専門家の支援が可能になります。

### 3.3. コード補完・ドキュメント検索
ソフトウェア開発において、コードのリファレンスやドキュメントを検索し、適切なサンプルコードを提示するAIアシスタントの構築が可能です。

---

## 4. まとめ

本記事では、RAG（Retrieval-Augmented Generation）の概念から実装方法、活用事例までを詳しく解説しました。

✅ **RAGは検索と生成を組み合わせた技術であり、LLMの精度を向上させる**  
✅ **LangChainとFAISSを活用すれば、簡単にRAGを実装できる**  
✅ **RAGはカスタマーサポート、医療、法律、ソフトウェア開発など幅広い分野で活用可能**  

**RAGを活用したAI開発に興味がある方は、ぜひ試してみてください！**

**「LGTM」＆コメントでフィードバックをお待ちしています！**

---
.javaをスクリプト的に使いたい時のbash_completion

### .javaが直接実行できるようになって久しい

`java xxx.java` と直接ソースを実行できるようになって久しいです。裏ではコンパイルしているので、ちょっとだけタイムラグを感じますが、スクリプト的にJavaが使えるのは便利です。

### java [タブ]で、xxx.javaを補完したい

スクリプト的に使いたいとなると、ファイル名の補完もやりたいです。

以下のbash_completion設定ファイルを作成・保存します。


``` /etc/bash_completion.d/java
_java()
{
    local cur prev opts
    COMPREPLY=()
    cur="${COMP_WORDS[COMP_CWORD]}"
    prev="${COMP_WORDS[COMP_CWORD-1]}"
    opts="$(find . -maxdepth 1 -name '*.java' -print0 | xargs -0 -n1 basename)"

    COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
    return 0
}
complete -F _java java
```

あとは、`bash -l` でログインスクリプトから読み直して反映すれば使えます。
【実践編】今すぐ使えるAI技術の最先端プラットフォーム完全ガイド| [第1回] 自動言語モデルとMistral AIの基礎と実践

近年、自然言語処理（NLP）の分野で急速に発展している**自動言語モデル（LLM: Large Language Model）**は、多くのアプリケーションに応用されています。その中でも**Mistral AI**は、最先端の技術を駆使し、高速で軽量なLLMを提供することで注目を集めています。本記事では、Mistral AIの基礎と実践的な使い方について解説し、具体的なコード例を示します。

## 1. 自動言語モデル（LLM）とは？

### LLMの基本概念
LLMは、大量のテキストデータを学習し、人間のように自然な文章を生成するモデルです。一般的な特徴は以下の通りです：
- 文脈を理解し、適切な応答を生成する能力
- コード生成や翻訳、要約など、多様なタスクに対応
- 事前学習（Pre-training）とファインチューニング（Fine-tuning）を活用した学習方法

代表的なLLMには**GPT-4, LLaMA, Falcon, Mistral**などがあります。

## 2. Mistral AIとは？

### Mistral AIの特徴
Mistral AIは、軽量かつ高性能なオープンソースのLLMを提供するフランスの企業です。以下のような特長があります：
- **高効率なアーキテクチャ**: 8bit量子化や分散計算を活用し、軽量かつ高速な推論が可能
- **オープンソースモデル**: Mistral 7B、Mixtralなど、無料で利用可能なモデルを提供
- **競争力のある精度**: 他の大規模モデルと比較して、高い精度を誇る

### Mistralの代表的なモデル
1. **Mistral 7B**：7B（70億）パラメータを持つモデルで、LLaMA 2 7Bと比べても優れたパフォーマンスを発揮
2. **Mixtral**：複数のエキスパート（MoE: Mixture of Experts）を活用し、精度と効率を両立

## 3. Mistral AIの実践

ここでは、Pythonを使ってMistral AIを試す方法を紹介します。

### 3.1. Mistralモデルのセットアップ
Mistralのモデルは`transformers`ライブラリを使って簡単に扱えます。まず、必要なパッケージをインストールします。

```bash
pip install transformers torch
```

次に、Hugging Faceの`transformers`を利用してMistral 7Bをロードします。

```python
from transformers import AutoModelForCausalLM, AutoTokenizer
import torch

# モデルとトークナイザのロード
model_name = "mistralai/Mistral-7B-Instruct-v0.1"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(model_name, torch_dtype=torch.float16, device_map="auto")

# プロンプトを準備
prompt = "Mistral AIの特徴を簡単に説明してください。"
inputs = tokenizer(prompt, return_tensors="pt").to("cuda")

# 推論
with torch.no_grad():
    outputs = model.generate(**inputs, max_new_tokens=100)
    result = tokenizer.decode(outputs[0], skip_special_tokens=True)

print(result)
```

### 3.2. APIを利用する方法
Mistral AIのAPIを利用すれば、より簡単にモデルを活用できます。以下のコードは、APIを使ったテキスト生成の例です。

```python
import requests

API_URL = "https://api.mistral.ai/v1/generate"
HEADERS = {"Authorization": "Bearer YOUR_API_KEY"}
DATA = {
    "model": "mistral-7b-instruct-v0.1",
    "prompt": "Mistral AIの活用方法を教えてください。",
    "max_tokens": 100
}

response = requests.post(API_URL, headers=HEADERS, json=DATA)
print(response.json())
```

## 4. Mistral AIの活用例

Mistral AIは様々な用途で活用できます。

### 4.1. コード生成
MistralはPythonやJavaScriptなどのコードを生成するのにも適しています。

```python
prompt = "PythonでFizzBuzzを実装するコードを書いてください。"
```

### 4.2. 文書要約
長いテキストを短く要約する機能も強力です。

```python
prompt = "以下のテキストを要約してください:\n長い文章..."
```

### 4.3. チャットボット
Mistralを活用したAIチャットボットを構築し、カスタマーサポートに導入することも可能です。

## 5. まとめ

本記事では、**Mistral AIの基礎と実践的な使い方**について解説しました。

- LLMの基本概念とMistral AIの特徴
- Mistral 7BとMixtralの紹介
- Pythonを用いたMistral AIの実装方法
- APIを活用したMistralの利用例

Mistral AIを活用すれば、高精度なAIアプリケーションを構築できます。ぜひ試してみてください！

### 📢 ぜひコメント＆シェアを！
もしこの記事が役に立ったら、Qiitaで「LGTM」やコメントをお願いします！また、Mistral AIの活用方法についてのアイデアがあれば、ぜひ共有してください！
@nuxt/test-utilsのmountSuspendedってなんぞやという話

# @nuxt/test-utilsのmountSuspendedについて

## はじめに
- @vue/test-utils(Vitest)のMount関数のラッパー関数
- マウントするコンポーネントを非同期でPromise.resolveしてくれるので、マウントを待つ処理がいらない
- 個々のマウントの把握・チェックをしたいなら大人しくMountとPromise.resolveと$nextTickつかっときましょう(なんだけど、Nuxt固有の自動import全部処理してくるのでクソ便利)

## Nuxtの一次情報にはなんと書かれているのか
https://nuxt.com/docs/getting-started/testing#mountsuspended

Helpers項目の１個目に載ってます。
@nuxt/test-utils特有のヘルパー関数らしく、説明は以下

>`mountSuspended`Nuxt 環境内に任意の Vue コンポーネントをマウントできるため、Nuxt プラグインからの非同期セットアップとインジェクションへのアクセスが可能になります。

なるほどわからん。（名推理)
その直後に

>Under the hood, mountSuspended wraps mount from @vue/test-utils, so you can check out the Vue Test Utils documentation for more on the options you can pass, and how to use this utility.

とのことで、Vitestのmountのラッパーだよーということが書いてあります。
当たり前ですが、Vitestのmount関数の理解が先ということですな。
mount関数の記事は星の数ほどはないですが、そこそこあるので割愛します。

## mountSuspendedの内部動作

ポイントは非同期処理の取り扱いにあります。通常の`mount`関数と異なり、`mountSuspended`は内部で以下のような処理を行っています：

1. コンポーネントをマウント
2. 非同期処理の解決を自動的に待機
3. Nuxt特有のインジェクションやプラグインのセットアップを完了させる

これにより、テストコード内で`await nextTick()`や`flushPromises()`のような追加の待機処理を書かなくても良くなるという利点があるわけですよ！

## 使用例と従来の方法との比較

### mountSuspendedを使った場合
```ts
import { mountSuspended } from '@nuxt/test-utils'
import MyComponent from '~/components/MyComponent.vue'

describe('MyComponent', () => {
  it('properly loads async data', async () => {
    const wrapper = await mountSuspended(MyComponent)
    // この時点で非同期処理は完了している
    expect(wrapper.text()).toContain('データが読み込まれました')
  })
})
```

### 従来のmountを使った場合
```ts
import { mount } from '@vue/test-utils'
import MyComponent from '~/components/MyComponent.vue'

describe('MyComponent', () => {
  it('properly loads async data', async () => {
    const wrapper = mount(MyComponent)
    // 非同期処理の完了を待つ必要がある
    await flushPromises()
    await wrapper.vm.$nextTick()
    expect(wrapper.text()).toContain('データが読み込まれました')
  })
})
```

## mountSuspendedのメリットとデメリット
### メリット
- テストコードがシンプルになる
- 非同期処理の待機漏れによるフレーキーテストを防げる
- Nuxt特有の機能（プラグインやインジェクション）が正しく初期化される

### デメリット
- 非同期処理の各ステップを細かく制御したい場合には不向き
- デバッグが難しくなる可能性がある（どのタイミングで何が起きているか把握しづらい）
- マウント処理の詳細な把握が必要な場合は従来の方法が適している

## どんなときに使うべきか

以下のような場合に`mountSuspended`の使用をおすすめします：

1. Nuxtのコンポーネントをシンプルにテストしたい
2. `useAsyncData`や`useFetch`などの非同期データ取得を含むコンポーネントのテスト
3. Nuxtプラグインやプロバイダーに依存するコンポーネントのテスト

一方で、以下の場合は従来の`mount`と明示的な非同期処理の方が適しています：

1. 非同期処理の各ステップを個別にテストしたい
2. ローディング状態など、特定の中間状態を検証したい
3. 複雑なユーザーインタラクションを含むテストシナリオ

## まとめ
`mountSuspended`は、Nuxtアプリケーションのテストを書く際に非常に便利なヘルパー関数です。特に非同期処理を含むコンポーネントのテストを簡略化できる点が大きな利点です。

ぶっちゃけ個人的な使用感ですが、現段階では`mount`で毎回`await nextTick()`とかで処理進めた方がいいと思います。
非同期処理の解決を自分で行いながらテストして行った方が、統合テストを流れに沿って実装できるかなと思います。

## 参考リンク
- [Nuxt Testing Documentation](https://nuxt.com/docs/getting-started/testing)
- [Vue Test Utils Documentation](https://test-utils.vuejs.org/)
Haskell の お勉強メモ #1

# Haskell での `where` 句を使う・使わない実装パターン

`where` 句を使うか使わないかで、Haskell のコードの可読性や関数プログラミングのスタイルがどう変わるかを比較します。

## `where` 句を使った実装

まずは、`where` 句を使った実装です。このパターンでは、インデックスのリストを `where` 句内で定義し、インデックスを使って文字列にインデックスを追加します。

### 実装

```haskell
addEqualsAndIndex :: [String] -> [String]
addEqualsAndIndex xs = zipWith addIndex xs indices
  where
    indices = [0 ..]  -- インデックスのリストを生成
    addIndex :: (String, Int) -> String
    addIndex (s, i) = s ++ "=" ++ show i  -- 文字列にインデックスを付けて返す

main :: IO ()
main = do
  let result = addEqualsAndIndex ["a", "b", "c", "d", "e"]
  mapM_ putStrLn result
```

### 解説
`addEqualsAndIndex`関数は、文字列のリスト`xs`とインデックスのリスト`indices`を`zipWith`を使って組み合わせ、それぞれにインデックスを付け加えます。

`indices = [0 ..]`でインデックスのリストを生成し、`zipWith`で`addIndex`関数を適用します。

`addIndex`は、文字列`s`とインデックス`i`を受け取り、s="インデックス" の形式に変換します。

## `where`句を使わない実装

次に、where 句を使わずに、同じ処理を関数内で直接記述する方法です。ここでは、無名関数（ラムダ式）を使ってインデックスのリストと文字列を組み合わせます。

### 実装
```haskell
addEqualsAndIndex :: [String] -> [String]
addEqualsAndIndex xs = zipWith (\s i -> s ++ "=" ++ show i) xs [0..]

main :: IO ()
main = do
  let result = addEqualsAndIndex ["a", "b", "c", "d", "e"]
  mapM_ putStrLn result
```

### 解説
`zipWith`の部分で、無名関数（ラムダ式）を使って、`xs`と`[0..]`の各要素を結びつけます。

ラムダ式`(\s i -> s ++ "=" ++ show i)`は、文字列`s`とインデックス`i`を受け取って、s="インデックス" の形式に変換します。

`[0..]`は、無限リストですが、`zipWith`が`xs`の長さに合わせてインデックスを取り出すため、問題なく動作します。
PythonのFastAPI入門を読んで

PythonでWebサービスを開発するにあたって参考にしたのが以下のドキュメント。
無料ながら素晴らしい内容で入門者におすすめ。

https://zenn.dev/sh0nk/books/537bb028709ab9

読み進めていくなかで前提となる知識が必要になる部分もいくつかあり備忘録としてここに記す。
FastAPIだけでなく、Dockerも使っているのでその内容も含む。
（DockerもPythonも経験値少なめなので初歩的な内容多め）

### Docker Composeのこと
複数のDockerコンテナを一度に制御できるツール
以下のリンクが分かりやすい。

https://qiita.com/gon0821/items/77369def082745d19c38

Macであれば「Docker Desktop on Mac」、
Windowsであれば「Docker Desktop on Windows」をインストールすることで
Docker Composeも使用することができる。
通常、Dockerと言えば「Docker Desktop」のことを指す。
Dockerは個人で利用する場合には無償だが、従業員数250名以上の会社で商用利用する場合には
有償となる。（有償となる要件等は公式サイトで確認すること）

Dockerfileとdocker-compose.ymlの関係等も、上述のリンクが分かりやすい。
Dockerfileがまずあって、docker-compose.ymlの「build: .」の部分で
Dockerfileの存在するディレクトリのパスを示している。

Docker Composeの各種コマンドは以下のリンクが分かりやすい。

https://qiita.com/tegnike/items/bcdcee0320e11a928d46

### Pythonのこと

#### 基本知識
以下の動画が非常に分かりやすい

https://www.youtube.com/watch?v=tCMl1AWfhQQ

#### 開発環境について
VisualStudioCodeでコードを書くときに補完機能が働かず効率が悪い
以下を参考に設定したうえでpyファイルを開くと解決する
注意点として「FastAPI入門」でのDockerコンテナの設定の場合だと、
指定するPythonのインタープリタパスは「.bin/python」にすること（ここで少しはまった）

https://it-dxblog.com/vscode-python-docker/

#### 構文について
以下の一文は、「fastapiというモジュールからFastAPIという関数をインポートしている」という意味
```Python
from fastapi import FastAPI
```

#### コーディングスタイルについて
変数名を例にすると、Javaのようなキャメルケース（例：helloWorld）ではなく、スネークケース（例：hello_world）のように定義する

#### サーバーについて
「Uvicorn」(ユビコーン)を使用する
調べるとWSGIの後継にあたるASGIサーバーとのこと
（ASGIという言葉は初めて聞いたが、Webアプリを動かすのに必要なAPサーバーのようなものと捉えた）
Pythonの特徴について

## はじめに
　Pythonの特徴についてまとめてみました。

## フリーのオープンソースソフトウェアである
　Pythonは、**無料**で使える。しかも、その**ソース**までもが公開されている（Python自体が、どのように作られているのかが公開されている）。そのため、Pythonを使ってプログラムを作るだけでなく、Python自身の中身まで調べたり学習したり出来る。

## マルチプラットフォームである
　MS-Windows、macOS、Linuxなど、多くの環境で動作する。

## 各種ドキュメントが豊富
　チュートリアルを含むドキュメントがインターネット上で公開されている。

## 幅広い分野に適用出来る汎用言語である
　全てのプログラミング言語が、あらゆる分野に適用出来るわけではない。数値計算が得意な言語、事務処理やデータベースが得意な言語、といった具合で、言語ごとに得意分野がある。
　**その意味で、Pythonはオールラウンドプレーヤー的な存在である。**
　**機械学習、ディープラーニングなどのAI（人工知能）分野、データ解析、科学技術計算、Webアプリケーション、GUI(Graphical User Interface)**など、極めて多くの分野を得意としている。
　しかも、他の言語で開発したプログラムとの組合せが容易な"**グルー言語**（接着剤のような言語という意味）"としての性格を持つので、Pythonが不得意な分野では、それを得意とする他の言語で開発したプログラムと組み合わせて開発する、といったことも可能である。
　なお、教育の現場でも、学習すべきプログラミング言語として採用が増えつつある。

## 多くのプログラミングパラダイムに対応している
　プログラムには、その根本となる思想・発想法・開発法を表す各種の**パラダイム**がある。
　Pythonは、**命令型プログラミング、手続き型プログラミング、関数型プログラミング、オブジェクト指向プログラミング**といった、複数の**プログラミングパラダイム**に対応する。すなわち、極めて懐が深い言語である。
　Pythonを学習すれば、上記のプログラミングパラダイムに精通出来る。また、作成者が得意とするプログラミング技術や、作成するプログラムの性格などに応じて、採用するプログラミングパラダイム（や、その比率）を自由に変えることが出来る。

## スクリプト言語である
　**スクリプト言語**とは、プログラムの作成・実行・テストなどを行いやすい、比較的小規模な体系を持つプログラミング言語である。Pythonには、次のような特徴がある。
・**記述性が高い**。他の言語よりも数割ほど短く記述出来る。
・**可読性が高い**。プログラムが読みやすい。
・**インタプリタ形式である**。プログラムを対話的に1行ずつ実行出来て、試行錯誤しやすい。

## ライブラリが豊富である
　多くのプログラミング言語がそうであるが、言語自体で行えることは限られている。グラフィック、ネットワークといった処理は、**ライブラリ**（処理を行うための部品が集められたもの）に任せる。
　Pythonは、急速な普及とともに、幅広い分野のライブラリが充実している。

## プログラムの実行が高速ではない
　**インタプリタ形式**であること（さらに、**動的な型付け言語**であることなど、いくつかの理由から）Pythonのプログラムは、決して高速には動作しない。
　ただし、「高速な技術計算のライブラリを利用する」といった感じで、処理の主要部分を高速なライブラリなどに委ねることで、それなりの速度でプログラムを実行出来る。

## 習得は決して容易ではない
　Pythonは習得が容易、と宣伝されるが、そうではない。記述性が高い、ということは、短い記述の中に、多くの深い意図が潜んでいるということである。また、Pythonには、いわゆる（習得が難しいといわれる）「ポインタ」は表面的にはないが、その内部はポインタ（参照）だらけである。学習においては、一つ一つの式や文の意味を正しく理解していく必要がある。

## おわりに
ここまで読んでいただきありがとうございます！

## 参考文献
・新・明解Python入門 (新・明解シリーズ) 単行本 – 2019/5/23
柴田 望洋 (著)
p.3,4
PRレビュー、Copilot に日本語でレビューをしてもらいたい！！！

# はじめに
Copilotが凄すぎて、「PRレビューもやってくれればいいのに…」と思っていた今日この頃。
何気なくPRレビュー欄見ていたら、居ました。
Copilot君天才🎉


![スクリーンショット 2025-03-26 11.18.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3644890/b6a9e8df-5e80-4f60-b176-6441ac77b534.png)

こちらCopilot君をクリックすれば、確かにレビューをしてくれるのですが、
手動でポチポチするのは正直面倒…
この際、PR出すと同時にレビューしてくれれば…🙏

そんな悩み、解決できます✨

# 結論
リポジトリから、[settings]->[rules]->[New rulest]->[New branch rulest]をクリックするとこの画面になります👇


![https___qiita-image-store.s3.ap-northeast-1.amazonaws.com_0_3644890_f73abe8f-cebb-4467-a77e-076867b3b333のコピー.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3644890/b94a8bba-6d0d-4112-9733-bbb929d56de3.jpeg)
![スクリーンショット 2025-03-26 11.07.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3644890/9807f79e-0dbb-4dc5-9a13-8d94778af9c6.png)
機能自体はPreviewではありますが、こちらの設定をすることで、
PRレビューを出した時に自動でCopilot君が速攻でレビューをしてくれます🚀
(Draft状態だと、手動でリクエストする必要があります)
# 終わりに
PRレビューが英語なのは、少しネックではありますよね。
こちらも解決策があります✨

`.github/pull_request_template.md`に Copilot用のコメントを残すことで、
日本語でコメントしてくれるようになります！
![スクリーンショット 2025-03-27 21.52.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3644890/42eb31b8-7ee7-45ff-a596-2aaf55b02672.png)

最終的なコメントはこんな感じ👀
![スクリーンショット 2025-03-27 21.57.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3644890/82dd2c36-093a-40cf-9b20-365212070843.png)

快適ですね💐

記載：2025/03/26
windows11で、sketchup6 その2

# 概要
windows11に、sketchup6を入れてみた。
rubyやってみた。

# 練習問題
fizzbuzz、zundoko、九九を書け。
helpを書け。

# 手順

C:\Program Files (x86)\Google\Google SketchUp 6\Plugins に、startup.rbを置く。

ウィンドウ＞rubyコンソールを開く。

# サンプルコード

```
def help
	puts "fizzbuzz"
	puts "zundoko"
	puts "kuku"
	puts ""
end

def kuku
	for x in 1..9 do 
		for y in 1..9 do
			if x * y < 10 then
				print (x * y).to_s + '  '
			else
				print (x * y).to_s + ' '
			end
		end 
		puts ''
	end 
end

def fizzbuzz
	for i in 1..100
		if i % 15 == 0
			puts "FizzBuzz"
		elsif i % 3 == 0
			puts "Fizz"
		elsif i % 5 == 0
			puts "Buzz"
		else
			puts i
		end
	end
end

def zundoko
	words = []
	def zd
		word = (rand(2) == 0) ? "zun" : "doko"
		puts word
		return word
	end
	while true
		words.push zd
		ans = words[-5, 5]
		if ans == ["zun", "zun", "zun", "zun", "doko"]
			puts "kiyosi！"
			break
		end
	end
end


```

# 実行結果

```
help
fizzbuzz
zundoko
kuku

nil
fizzbuzz
1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz
16
17
Fizz
19
Buzz
Fizz
22
23
Fizz
Buzz
26
Fizz
28
29
FizzBuzz
31
32
Fizz
34
Buzz
Fizz
37
38
Fizz
Buzz
41
Fizz
43
44
FizzBuzz
46
47
Fizz
49
Buzz
Fizz
52
53
Fizz
Buzz
56
Fizz
58
59
FizzBuzz
61
62
Fizz
64
Buzz
Fizz
67
68
Fizz
Buzz
71
Fizz
73
74
FizzBuzz
76
77
Fizz
79
Buzz
Fizz
82
83
Fizz
Buzz
86
Fizz
88
89
FizzBuzz
91
92
Fizz
94
Buzz
Fizz
97
98
Fizz
Buzz
1..100

zundoko
zun
doko
doko
zun
zun
zun
doko
doko
zun
zun
zun
zun
doko
kiyosi！
nil
kuku
1  2  3  4  5  6  7  8  9  
2  4  6  8  10 12 14 16 18 
3  6  9  12 15 18 21 24 27 
4  8  12 16 20 24 28 32 36 
5  10 15 20 25 30 35 40 45 
6  12 18 24 30 36 42 48 54 
7  14 21 28 35 42 49 56 63 
8  16 24 32 40 48 56 64 72 
9  18 27 36 45 54 63 72 81 
1..9

```

以上。
Google Driveの複数フォルダに一括でファイルを追加するPythonスクリプト（Googleサービスアカウント使用）

## はじめに

Google Driveで多数の顧客フォルダを管理していると、  
「全フォルダに共通ファイル（スプレッドシートやフォルダなど）を追加したい」という場面があります。

でも、手作業でひとつずつコピー＆ペースト…なんてやっていたら時間も手間も大変。

今回は、**Python＋Google Drive API＋サービスアカウント**を使って、  
「複数のフォルダに指定ファイルを一括コピーで挿入する」自動化スクリプトを紹介します。

---

## やりたいこと
![Google Driveでのフォルダ管理自動化スクリプト - visual selection.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/557468/ed57d13d-657d-406d-91c1-b9331d5922e8.png)
- Google Drive内にある、複数の顧客フォルダ（数百件）
- それぞれに同じファイル（例：テンプレスプレッドシート）を追加したい
- 作業者のアカウントではなく、**サービスアカウント**を使って処理したい

---

## サービスアカウントとは？

Googleが提供する **「自分の代わりに処理してくれるbotのような専用アカウント」** です。

- 通常のGoogleアカウントとは別に動作  
- プログラムからAPI経由でDriveやSheetsを操作できる  
- 権限設定は手間だけど、慣れればとても便利  
- GASでは難しい「大量処理」や「非ログイン状態での操作」に強い

> ✅ 設定手順は [Google公式ドキュメント](https://developers.google.com/identity/protocols/oauth2/service-account) を参照  
> Qiita内にもたくさんの解説記事があります

---

## 必要なライブラリ

```bash
pip install google-api-python-client google-auth google-auth-httplib2 google-auth-oauthlib
```
---

## スクリプトの全体構成（ざっくり）
- サービスアカウントでGoogle Drive APIにログイン

- 対象フォルダのID一覧を読み込む（スプレッドシートなど）

- コピー元ファイルを指定して、各フォルダに複製

必要に応じてエラーハンドリングや条件分岐を追加


## サンプルコード（一部）

```bash
from google.oauth2 import service_account
from googleapiclient.discovery import build

# サービスアカウントの認証
SCOPES = ['https://www.googleapis.com/auth/drive']
SERVICE_ACCOUNT_FILE = 'your_service_account.json'

creds = service_account.Credentials.from_service_account_file(
    SERVICE_ACCOUNT_FILE, scopes=SCOPES)

drive_service = build('drive', 'v3', credentials=creds)

# コピー元ファイルID（テンプレートファイル）
template_file_id = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXX'

# 対象のフォルダID一覧（例としてリスト化）
target_folder_ids = ['folder_id_1', 'folder_id_2', 'folder_id_3']

for folder_id in target_folder_ids:
    copied_file = {
        'name': '新しいファイル名',
        'parents': [folder_id]
    }

    drive_service.files().copy(
        fileId=template_file_id,
        body=copied_file
    ).execute()

```


## ハマりポイントと対策
| 課題                                      | 対策                                                                 |
|-------------------------------------------|----------------------------------------------------------------------|
| サービスアカウントにDrive権限がない       | 対象フォルダに手動で共有設定（または共有ドライブ利用）             |
| 共有ドライブで動かない？                  | API呼び出し時に `supportsAllDrives=True` を明示する必要あり         |
| 既存ファイルが上書きされる？              | `.copy()` は新規コピーなので上書きされない（ファイル名に注意）     |
| GSpreadやSheets APIとの併用               | コピー後に取得したIDでGSpread処理も可能                            |

## おわりに

この処理を自動化することで「数時間かかる地味だけど大事な作業」を、数分で終わらせることができるようになりました。

---

ポイントは、

- **やらなくていい作業を減らす**
- **人間がミスりやすい部分を自動化で潰す**

という発想。

業務効率化は、派手なツール導入よりも、  
こうした「地味だけど効果が大きい工夫」の積み重ねが一番効くと実感しています。

同じように業務を効率化したい方の参考になればうれしいです！
ReactにおけるCSSの設計手法

**ReactアプリケーションにおけるCSS設計のアウトプットとして記事を書きます**。

# CSS Modules

CSS ModulesはCSSのスコープをコンポーネント単位で限定し、クラス名の衝突を防ぐことができます。
```css
/* Button.module.css */
.button {
  background-color: blue;
  color: white;
  padding: 10px 20px;
  border-radius: 5px;
}
```
```css
import styles from './Button.module.css';

function Button() {
  return <button className={styles.button}>Click me</button>;
}
```

# Styled Components

Styled ComponentsはJavaScript内でCSSを記述できるライブラリで、動的なスタイリングが可能です。

```css
import styled from 'styled-components';

const Button = styled.button`
  background-color: blue;
  color: white;
  padding: 10px 20px;
  border-radius: 5px;
`;

export default function App() {
  return <Button>Click me</Button>;
}
```

# Next.jsでのCSS設計

Next.jsでは、CSS ModulesやStyled Componentsに加え、以下のような方法も一般的です。

グローバルCSS

Next.jsでは、グローバルスタイルを _app.js 内でインポートできます。
```css
// pages/_app.js
import '../styles/globals.css';

export default function App({ Component, pageProps }) {
  return <Component {...pageProps} />;
}
```

内蔵のCSSサポート（CSS Modules）

Next.jsはデフォルトでCSS Modulesをサポートしています。
```css
// components/Button.js
import styles from '../styles/Button.module.css';

export default function Button() {
  return <button className={styles.button}>Click me</button>;
}
```

# プロジェクト規模ごとの使い分け

**小規模プロジェクト**

シンプルな構成を保つため、グローバルCSSやCSS Modulesが適しています。

**中規模プロジェクト**

コンポーネントごとにスタイルを分けられるCSS ModulesやStyled Componentsを推奨します。

**大規模プロジェクト**

テーマやデザインシステムとの連携が容易なStyled Componentsや、複数のCSS設計手法を組み合わせたハイブリッドな手法が適しています。

# 効果的なCSS設計のポイント

・コンポーネント単位でスタイルを管理することで、再利用性を向上させる

・明確な命名規則を使用することで、他の開発者との協力が容易になる

・テーマや変数を活用して一貫性のあるデザインを維持する

**レスポンシブデザインの実践例**

メディアクエリを利用してレスポンシブデザインを実現します。
```css
.button {
  background-color: blue;
  padding: 10px 20px;
}

@media (max-width: 600px) {
  .button {
    padding: 5px 10px;
  }
}
```
画像分析API: 視覚的コンテンツの安全性評価（Azure AI Content Safety）

## 画像分析API: 視覚的コンテンツの安全性評価

Azure AI Content Safetyの画像分析APIは、視覚的コンテンツの安全性を評価する強力なツールです。このAPIは、テキスト分析と同様に、性的コンテンツ、暴力、憎悪、自傷行為といった複数のカテゴリについて画像をスキャンし、不適切なビジュアルコンテンツを高精度で検出します。

https://learn.microsoft.com/ja-jp/azure/ai-services/content-safety/how-to/containers/image-container

## 機能の重要性

画像は文脈やニュアンスを伝える強力な媒体であり、テキスト以上に慎重な管理が必要です。画像分析APIを使用することで、ユーザーがアップロードする画像やAIが生成する視覚的コンテンツの安全性を効果的に確保できます。これにより、オンラインプラットフォームやアプリケーションの信頼性と安全性が大幅に向上します。

## 主要機能

1. **マルチカテゴリ分析**: 性的コンテンツ、暴力、憎悪、自傷行為の4つの主要カテゴリについて、画像を包括的に分析します。
2. **重大度レベル評価**: 各カテゴリにおいて、コンテンツの不適切さを複数の重大度レベルで評価します。
3. **高速処理**: 大量の画像を迅速に分析し、リアルタイムでの判断を可能にします。
4. **APIとコンテナ対応**: REST APIやクライアントSDKを通じて利用可能で、さらにDockerコンテナとしても提供されています。

## 適用シナリオ

画像分析APIは、以下のようなさまざまなシナリオで活用できます：

1. **画像共有プラットフォーム**: ユーザーがアップロードする画像の不適切コンテンツを自動検出し、プラットフォームの健全性を維持します。
2. **オンラインマーケットプレイス**: 出品される商品画像を監視し、不適切な商品や詐欺的な画像を排除します。
3. **ソーシャルメディア**: プロフィール画像や投稿画像を確認し、コミュニティガイドラインに違反するコンテンツを特定します。
4. **教育機関**: 安全な視覚的学習環境を維持し、学生が不適切なコンテンツにさらされるリスクを最小限に抑えます。
5. **コンテンツモデレーション**: ニュースサイトやブログプラットフォームで、投稿される画像コンテンツを自動的にモデレートします。
6. **広告プラットフォーム**: 広告画像の適切性を確認し、ブランドセーフティを確保します。

## 実装例

Pythonを使用してAzure AI Content SafetyのAnalyze Image APIを呼び出す基本的な実装例は以下の通りです：

```python
from azure.ai.contentsafety import ContentSafetyClient
from azure.ai.contentsafety.models import AnalyzeImageOptions, ImageData
from azure.core.credentials import AzureKeyCredential
import os

# クライアントの初期化
endpoint = os.environ["CONTENT_SAFETY_ENDPOINT"]
key = os.environ["CONTENT_SAFETY_KEY"]
client = ContentSafetyClient(endpoint, AzureKeyCredential(key))

# 画像の分析
image_path = "sample_data/image.png"
with open(image_path, "rb") as image_file:
    image_data = image_file.read()

request = AnalyzeImageOptions(image=ImageData(content=image_data))

try:
    response = client.analyze_image(request)
    for category in response.categories_analysis:
        print(f"{category.category} severity: {category.severity}")
except Exception as e:
    print(f"画像分析に失敗しました。エラー: {str(e)}")
```

このコードが実行する主な機能は以下の通りです：

1. **Azure AI Content Safetyクライアントの初期化**: 環境変数からエンドポイントとキーを取得し、APIクライアントを設定します。
2. **画像ファイルの読み込み**: 指定されたパスから画像ファイルをバイナリデータとして読み込みます。
3. **画像分析リクエストの作成**: 読み込んだ画像データを使用して分析リクエストを作成します。
4. **画像の分析実行**: analyze_image()メソッドを呼び出して、画像の内容を分析します。
5. **結果の処理**: 分析結果から各カテゴリ（憎悪、自傷行為、性的コンテンツ、暴力）の重大度を取得し、表示します。
6. **エラー処理**: API呼び出し中に発生する可能性のある例外を捕捉し、エラーメッセージを表示します。

このコードは、指定された画像ファイルを分析し、不適切なコンテンツの存在を検出します。各カテゴリの重大度スコアを0から5の範囲で返し、値が高いほどそのカテゴリのコンテンツがより顕著であることを示します。これにより、アプリケーションやプラットフォームで共有される画像コンテンツの安全性を自動的に評価することができます。


## 高度な利用方法

1. **Sentinelとの連携**: Azure Functionsを使用してBlobストレージにアップロードされた画像を自動的に分析し、結果をLog Analyticsに送信。これにより、Sentinelを通じて脅威検知、インシデント管理、ダッシュボード監視が可能になります。
2. **コンテナ化された展開**: Dockerコンテナを使用してイメージ分析機能をオンプレミスや他のクラウド環境に展開できます。これにより、データのプライバシーやコンプライアンス要件に対応しつつ、柔軟な運用が可能になります。
3. **RAGとの統合**: Retrieval Augmented Generation (RAG)システムに画像分析APIを組み込むことで、画像コンテンツの安全性を確保しつつ、より豊かな情報検索と生成が可能になります。

Azure AI Content Safetyの画像分析APIは、視覚的コンテンツの安全性を確保する上で不可欠なツールです。適切に実装することで、ユーザー体験の向上、ブランド保護、法的リスクの軽減など、多岐にわたるメリットを享受できます。
【中断】お名前.com から Cloudflare Registrar にドメイン移管する

## 概要
- たびたび話題になる、お名前ドットコムよくない論に押される形で移行を決意
- Cloudflareがドメインとしては安いと聞いたので選択した

## 作業
https://zenn.dev/muchoco/articles/9039762136e15c

主にこちらを参考にやっていく。

:::note info
参考資料を増やすような意味で記載していくので、サクッと読みたい場合は提示したURLを参照すること
:::
### 余談：ドメイン移管ってなに？
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3125890/2d6b404b-f45e-48e9-9f06-fb0a8b87ea3a.png)

### Whois 情報の公開代行設定を解除
Whois 情報の公開代行設定を解除が必要らしい

https://navi.onamae.com/domain/setting/whoisprotect/cancel/list

ここから、次の画面に行ける。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3125890/040b731a-bab3-413a-a726-ca00adb09d89.png)

解除したいものを選択する。
意図せず高い？やつを選択していたっぽいことを考えると、やっぱり解約に踏み切ってよかったと思う。（メール転送はつけた記憶がない）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3125890/ed5d3a66-8a3b-4e4d-9e1d-441006076ede.png)

確認画面が出るので同意する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3125890/dc30c5f5-9650-4824-b73d-4a00563ade40.png)

完了しました。このときうまくいかない場合について、元記事に記載があったのでうまくいかない場合は参照するとよいでしょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3125890/8fb62125-dc96-4f6e-84bd-6bf5f8ac851e.png)

### AuthCode の確認
AuthCode の確認を後程利用するため、事前に取得しておくようです

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3125890/662bed50-2085-4cd4-a746-b289cca5e3f4.png)

### Cloudflare Registrar で移管申請

#### Cloudflareにお支払情報を設定する
以下のURLからひとまずログインします。

https://www.cloudflare.com/ja-jp/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3125890/c0765410-11af-4d30-b0cf-94df258f4152.png)

請求を押します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3125890/0268a6ab-6297-4789-92a6-a33183d7d74f.png)

後は流れでできそうなので省略...

#### ドメイン移管
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3125890/d0ae66be-2a15-4362-8b1f-210d106e7370.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3125890/383a73b9-e90c-4de0-940c-28f3fda60bfe.png)

今回はフリープランにしました。今まで利用していなかったですが、無料でこのレベルができるのはすごいですね、、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3125890/0e92b50d-a135-4aee-a3af-14eef26b575f.png)

これだけで、設定した内容をAレコード全部、SSL証明書の対象外と出てしまうのは悲しいですね。
全部インポートしてくれるのはめっちゃありがたい。
とはいえ、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3125890/a3791a0f-d82f-4f2c-9d4f-512fe7fc4f41.png)

awsのを削除して、設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3125890/e2b18d45-d34a-4dc7-96b0-03d46802343a.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3125890/4526d0ae-07cd-4da4-acdd-956911b249f0.png)

#### ドメイン移管をする
ちょっと、４５ドルと高いのに気が付きこのドメインでこのままいくかちょっと悩み中...
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3125890/6fc67c4d-840d-4579-8a00-d9d3b32781b7.png)
notes

Function IsExcelFileOpen(filePath As String) As Boolean
    Dim excel As Variant
    Dim wb As Variant
    Dim isOpen As Boolean
    isOpen = False

    On Error Resume Next
    Set excel = GetObject(, "Excel.Application") ' 既存のExcelインスタンスを取得
    If Not excel Is Nothing Then
        Forall book In excel.Workbooks
            If book.FullName = filePath Then
                isOpen = True
                Exit Forall
            End If
        End Forall
    End If
    On Error GoTo 0

    IsExcelFileOpen = isOpen
End Function


Function IsFileLocked(filePath As String) As Boolean
    Dim fileNum As Integer
    Dim isLocked As Boolean
    fileNum = Freefile()
    
    On Error Resume Next
    Open filePath For Binary Access Read Write Lock Read Write As #fileNum
    If Err <> 0 Then
        isLocked = True
    Else
        isLocked = False
        Close #fileNum
    End If
    On Error GoTo 0
    
    IsFileLocked = isLocked
End Function
メモ：Oracle_SQLPlusでTSV出力（CSV出力）

・データの取得にSQLPlusの「SET MARKUP CSV」というSET句の機能を利用するため
それがサポートされているバージョン（おそらくOracleClient 12.2以上）が前提

・ポイント
「SET MARKUP CSV」は区切り文字設定（DELIMI～）できるが、TAB文字は普通には設定できないっぽいので下記のように設定している。（これを設定しなければデフォルトカンマ区切りでCSV出力）
```ruby:title.rb

COLUMN TAB NEW_VALUE varTAB
SELECT CHR(9) AS TAB FROM DUAL;
SET MARK CSV ON DELIMI '&varTAB' QUOTE ON

```

・その他SET句などは下記のように設定したりしている。（取得するデータの内容によって設定は見直し）
```ruby:title.rb
--データベースから一度にフェッチする配列の大きさ
SET ARRAYSIZE 512
--スクリプトのSQLPlusコマンドを表示しない
SET ECHO OFF
--問い合わせの結果レコード件数を表示しない
SET FEED OFF
--出力をユーザの表示デバイスに表示しない
SET FLU OFF
--実行するスクリプトのコマンドによって生成される出力を表示しない
SET TERM OFF
--SQL実行時間を表示しない
SET TIMI OFF
--置換変数に設定する前後の状態を表示しない
SET VERIFY OFF
--レコード・セパレータ設定（これをせていしないと結果に余計な改行が入ってしまう）
SET RECSEP OFF
--プロンプト画面に現在時刻を表示させる。
SET TIME ON
--NUMBER型の表示幅を指定（桁数が多いと指数表示になってしまうのでそれの回避用）
SET NUMWIDTH 15

--TAB区切り
COLUMN TAB NEW_VALUE varTAB
SELECT CHR(9) AS TAB FROM DUAL;
SET MARK CSV ON DELIMI '&varTAB' QUOTE ON

--日付型の表示形式設定
ALTER SESSION SET NLS_DATE_FORMAT='YYYY-MM-DD HH24:MI:SS';
ALTER SESSION SET NLS_TIMESTAMP_FORMAT='YYYY-MM-DD HH24:MI:SS';

```

・その他のメモ
実例：下記のようなSQLをbatなどから実行して、実行した日のフォルダ、日時のファイルを出力するようにしている。
```ruby:title.rb

--フォルダ名の日付部分取得
COLUMN DIR DATE NEW_VALUE varDIR_DATE
SELECT TO_CHAR(SYSDATE,'YYYYMMDD') AS DIR_DATE FROM DUAL;

--ファイル名の日付時刻部分取得
COLUMN LOG_DATE NEW_VALUE varLOG_DATE
SELECT TO_CHAR(SYSDATE, 'YYYYMMDD_HH24MISS') AS LOG_DATE FROM DUAL;

--HostコマンドでOSのコマンドが実行できるようになる。
--WindowsコマンドのMdコマンドでフォルダを作成
host Md &varDIR_DATE.

--ログ出力
spool ./&varDIR_DATE./OutputTest_&varLOG_DATE..tsv append

--列ヘッダを表示する
SET HEAD ON

--取得したいSQL実施
SELECT
    *
FROM
    DUAL
;

spool off

```

・呼び出すbatは下記のような感じ
```ruby:title.rb

--実行するDBの文字コードに合わせて設定（下記はUTF-8）
chcp 65001
SET NLS_LANG=Japanese_Japan.AL32UTF8

salplus ユーザ名@接続先/パスワード @test.sql

exit

```
MCPを使いたい

## MCPとは
ClaudeやCursorなどのAIツールが外部ないしローカルのデータやシステムにアクセスしてあれこれできるってやつです。

例えば、「最新の売上データを取得して」とプロンプトを打ち込むとSQLite MCP ServerにSQLクエリを送信し、「売上が1,000円以上」のデータを取得できるといったことができます。


同じ場所から、自然言語でいろんなアプリが動かせるよ！っていうわけです。


## データ保護の観点
MCPは、クエリで指定された範囲内でのみデータを使用し、ローカル上で完了するため、データが外部ネットワークに漏れることはありません。

## MCPを使おう
開発者がMCPを活用するためには(Claudeでの例)
1. MCPの仕様とSDKをダウンロード：公式サイトから必要なツールを取得します。

2. ClaudeデスクトップアプリでローカルMCPサーバーを設定：内部データとシステムを接続し、AIの活用を開始します。

3. オープンソースリポジトリの利用：既存の事前構築済みサーバー(GoogleドライブやGitHubなど)を活用します。

4. 初心者向けガイドを参照：MCPのクイックスタートガイドに従い、迅速にプロジェクトを開始します。


## MCPを使って楽していきましょう！



## 参考サイト⬇(あとで読み返したい)

https://zenn.dev/karaage0703/articles/42f7b0655a6af8

https://zenn.dev/makumaaku/articles/85fc9e17f5bd5f

https://note.com/shuzon__/n/na2aafacf7324

https://www.ai-souken.com/article/claude-mcp-overview

https://apidog.com/jp/blog/cursor-ai-mcp/

https://www.nvv.genai.co.jp/anthropic%E3%81%8Cmcp%E3%82%92%E3%82%AA%E3%83%BC%E3%83%97%E3%83%B3%E3%82%BD%E3%83%BC%E3%82%B9%E5%8C%96%EF%BC%81%E6%9C%80%E6%96%B0%E3%81%AEai%E3%83%A2%E3%83%87%E3%83%AB%E3%81%8C%E3%81%95%E3%82%89/#toc4
テキスト分析API: 有害なテキストコンテンツの検出（Azure AI Content Safety）

## テキスト分析APIとは

Azure AI Content Safetyのテキスト分析APIは、オンライン環境における安全性を向上させるための強力なツールです。このAPIは、性的コンテンツ、暴力、憎悪、自傷行為などの有害なテキストをスキャンし、重大度レベルを評価する機能を提供します。以下では、このAPIの特徴や具体的な機能について詳しく解説します。

https://learn.microsoft.com/ja-jp/azure/ai-services/content-safety/quickstart-text

## **テキスト分析APIの概要**

テキスト分析APIは、有害なテキストコンテンツを検出し、その深刻度を評価することで、プラットフォーム運営者が迅速かつ適切に対応できるよう支援します。具体的には以下を実現します：

- **複数の重大度レベルで評価**: コンテンツの深刻度を0（安全）から6（高リスク）までの範囲で分類。
- **カテゴリ別検出**: 性的コンテンツ、暴力、憎悪表現、自傷行為といったカテゴリに分類して分析。

## **重大度レベルとカテゴリ**

テキスト分析APIでは、有害コンテンツを以下の重大度レベルで評価します：


| **重大度レベル** | **説明** |
| :-- | :-- |
| 0 | 安全 |
| 2 | 低リスク |
| 4 | 中リスク |
| 6 | 高リスク |

また、検出対象となるカテゴリは以下の通りです：

- **性的コンテンツ**: 不適切な性的表現や暗示。
- **暴力**: 暴力的な言葉や脅迫。
- **憎悪表現**: 差別的・侮辱的な発言。
- **自傷行為**: 自殺や自己破壊的な内容。

これらの情報は、ユーザー生成コンテンツやAI生成コンテンツから抽出されます。

## **機能の重要性**

オンラインプラットフォームでは、ユーザー生成コンテンツが急増しており、安全性確保が重要な課題となっています。テキスト分析APIを活用することで以下が可能になります：

- **自動検出と対応**: 有害な内容をリアルタイムで検出し、自動フィルタリングや手動レビューへの振り分け。
- **プラットフォームの健全化**: 不適切な発言や投稿を排除し、安全なコミュニケーション環境を維持。
- **効率化**: 大量のコンテンツを迅速にスキャンし、人手による確認作業を軽減。

## **適用シナリオ**

テキスト分析APIは幅広い用途に対応しています。以下はその代表的な例です：

1. **ソーシャルメディアプラットフォーム**:
コメントや投稿内容を監視し、不適切な発言を排除。
2. **オンラインフォーラム**:
ユーザー間で健全な議論が行われるよう、有害コンテンツをフィルタリング。
3. **教育アプリケーション**:
学習環境で不適切な内容が含まれないよう監視。
4. **カスタマーレビュー管理**:
商品レビュー内で攻撃的または不適切な内容がないか確認し、ブランドイメージを保護。

## **導入方法と技術的詳細**

Azure AI Content Safetyのテキスト分析APIは簡単に導入できます。以下はJavaScriptでの使用例です：

```javascript
import ContentSafetyClient, { isUnexpected } from "@azure-rest/ai-content-safety";
import { AzureKeyCredential } from "@azure/core-auth";

export async function analyzeText(text) {
  const endpoint = process.env.AZURE_CONTENT_SAFETY_ENDPOINT;
  const key = process.env.AZURE_CONTENT_SAFETY_KEY;
  const credential = new AzureKeyCredential(key || "");
  const client = ContentSafetyClient(endpoint, credential);

  const analyzeTextParameters = { body: { text: text } };
  const result = await client.path("/text:analyze").post(analyzeTextParameters);
  
  return result.body;
}
```

このコードでは、入力されたテキストをスキャンし、重大度レベルとカテゴリごとの評価結果を取得できます。

### **このコードができること**

- 入力されたテキストをAzure AI Content Safety APIに送信。
- テキスト内に含まれる有害コンテンツを検出。
- 重大度レベル（0〜6）やカテゴリ（性的コンテンツ、暴力など）の評価結果を取得。

このコードは、実際に有害コンテンツが含まれているかどうかを判定するために利用でき、オンラインプラットフォームやアプリケーションで安全性確保に役立ちます。

## **料金体系**

Azure AI Content Safetyサービスはコスト効率も優れています。例えば:

- **料金**: 約0.054円/1000文字
- 無料枠: 約500万文字まで無料

これにより、小規模から大規模なプロジェクトまで柔軟に対応可能です。


## **まとめ**

Azure AI Content Safetyのテキスト分析APIは、安全性確保が求められるあらゆる場面で活用できる強力なツールです。重大度レベルとカテゴリ分類による詳細な分析機能により、オンライン環境での健全性維持に貢献します。このAPIの導入により、安全で信頼性の高いプラットフォーム運営が可能になります。
MySQLの起動・停止・再起動コマンド（Windows & Mac）

## はじめに
開発や学習でMySQLを使っていると、「手動で起動したい」「再起動したいけどどうやるの？」という場面が必ず出てきます。
この記事では、Windows / macOS の両方で使える MySQL の基本操作コマンド（起動・停止・再起動）をまとめました。

## 方法①：ターミナル / コマンドプロンプトから操作
### Windows の場合
#### 起動
初めて起動する前に**mysqld --initialize**が必要な場合もあります。
```
cd "C:\Program Files\MySQL\MySQL Server 8.0\bin"
mysqld
```

#### 停止
サーバーが起動中で、rootユーザーに適切なパスワードが設定されている必要があります。
```
mysqladmin -u root -p shutdown
```

#### 再起動
MySQL には「再起動コマンド」はないため、手動で以下のように実行します。
```
mysqladmin -u root -p shutdown
mysqld
```

### macOS の場合（Homebrewインストール前提）
#### 起動
```
brew services start mysql
```
#### 停止
```
brew services stop mysql
```
#### 再起動
```
brew services restart mysql
```
※Homebrew 経由でMySQLをインストールしていない場合
```
# 起動
mysql.server start

# 停止
mysql.server stop

# 再起動
mysql.server restart
```

## 方法②：GUIから操作
#### Windows：サービス（services.msc）
1. Win + R → services.msc と入力
2. MySQL80 や MySQL を探す
3. 右クリックして「開始」「停止」「再起動」が可能
#### macOS：システム環境設定（MySQLアイコン）
/Applications/System Preferences にあるMySQLパネルから起動・停止が可能
※インストール方法による

## 方法③：バッチ・スクリプトで効率化
スクリプトとして保存しておけば、1コマンドでサーバー操作ができます。
#### Windows
```
:: start_mysql.bat
cd "C:\Program Files\MySQL\MySQL Server 8.0\bin"
start mysqld
```

#### macOS
```
#!/bin/bash
brew services restart mysql
```
## トラブルシューティング（起動しないときの原因と対処）
#### 起動時にエラー：Failed to set datadir
```
[ERROR] Failed to set datadir to 'C:\Program Files\MySQL\MySQL Server 8.0\data\'
```
原因 → data ディレクトリが存在しない or 権限不足
対処 → 初期化
```
mysqld --initialize --console
```
#### ポート3306が使用中
```
Can't bind to port 3306
```
対処法
→ タスクマネージャー（またはlsof -i :3306）で競合アプリを確認
→ my.cnf や my.ini でポートを変更

## おわりに
MySQL の起動や再起動は、開発環境でトラブルが起きたときや、設定を変更した際に使用します。
GUIだけでなくコマンド操作にも慣れておくと、作業がスムーズに進むと思います！
ご参考になれば幸いです。
カスタムカテゴリAPI: 柔軟なコンテンツ分類機能（Azure AI Content Safety）

## カスタムカテゴリAPIとは

Azure AI Content Safetyは、AIを活用してコンテンツをフィルタリングし、機密情報漏洩や不適切な利用を防ぐ強力なツールです[^1]。その中でも、カスタムカテゴリAPIは、組織固有のニーズに応じて柔軟にコンテンツ分類を行える機能として注目されています。

**2025年3月現在、英語のみサポートされております。**

https://learn.microsoft.com/ja-jp/azure/ai-services/content-safety/concepts/custom-categories

### カスタムカテゴリAPIの具体的な使用例

1. **業界特有の専門用語フィルタリング**
    - 医療分野: 患者の個人情報や診断結果に関連する用語を検出し、機密情報の漏洩を防止
    - 金融セクター: インサイダー取引や市場操作に関連する表現を識別し、コンプライアンス違反を防止
2. **ブランド保護**
    - 商標侵害の検出: 自社ブランド名や製品名の不正使用を監視
    - ネガティブな表現の特定: ブランドイメージを損なう可能性のある文脈や表現を検出
3. **コミュニティガイドラインの実装**
    - オンラインフォーラム: 特定のトピックや表現を禁止し、健全な議論環境を維持
    - 教育プラットフォーム: 年齢に適さない内容や不適切な言葉遣いを自動的に検出し、安全な学習環境を確保
4. **新興の有害トレンドへの対応**
    - ソーシャルメディア: 新たに出現した有害なミームや隠語を迅速に特定し、対策を講じる
    - オンラインゲーム: プレイヤー間のいじめや嫌がらせに使用される新しい表現を検出し、ゲーム内のコミュニケーションを監視


## カスタムカテゴリAPIの種類

Azure AI Content Safetyは、2つのタイプのカスタムカテゴリAPIを提供しています：

### 1. カスタムカテゴリ（標準）API

この機能allows組織が独自のコンテンツカテゴリを作成し、トレーニングすることができます。以下のような用途に適しています：

- 特定の業界用語のフィルタリング
- ブランド特有の不適切表現の検出
- 特定のコンテキストで問題となる言葉の識別


### 2. カスタムカテゴリ（急速）API

この機能は、新たな有害コンテンツパターンをより迅速に定義し、テキストと画像の両方をスキャンして一致を確認できます。主な特徴は：

- 緊急事態への迅速な対応
- 新興の有害トレンドへの即時対策
- テキストおよび画像コンテンツの同時スキャン


## カスタムカテゴリの仕組み

カスタムカテゴリ機能は、以下のステップで実装されます：

1. **定義とセットアップ**
    - カテゴリ名の設定
    - 詳細な定義の提供
    - 肯定的および否定的な例のデータセット収集
2. **モデルトレーニング**
    - Azure AI Content Safetyによる機械学習モデルのトレーニング
    - 大規模言語モデルを使用したデータ拡張
    - トレーニングデータセットの品質向上
3. **モデル評価と最適化**
    - トレーニングされたモデルの性能評価
    - 必要に応じたモデルの微調整
4. **デプロイと使用**
    - トレーニングされたモデルのデプロイ
    - APIを通じたカスタムカテゴリの利用

## 適用シナリオ

カスタムカテゴリAPIは、以下のようなシナリオで特に有効です：

1. **特定の業界向けの専門用語フィルタリング**
    - 医療業界での機密情報保護
    - 金融セクターでのコンプライアンス遵守
2. **ブランド保護のための特定表現の監視**
    - 商標侵害の検出
    - ブランドイメージを損なう表現のフィルタリング
3. **特定のコミュニティガイドラインの実装**
    - オンラインフォーラムでの不適切な言葉遣いの防止
    - 教育プラットフォームでの安全な環境維持
4. **新興の有害トレンドへの迅速な対応**
    - ソーシャルメディアでの新たな有害コンテンツの検出
    - オンラインゲームでの不適切な行動の即時特定

## カスタムカテゴリAPIの利点

1. **柔軟性**: 組織固有のニーズに合わせてカスタマイズ可能
2. **迅速な対応**: 新たな脅威や課題に素早く適応
3. **マルチモーダル**: テキストと画像の両方に対応（急速API）
4. **精度向上**: 大規模言語モデルによるデータ拡張
5. **スケーラビリティ**: Azure AIプラットフォームの強力なインフラストラクチャを活用

## 実装のベストプラクティス

1. **明確な定義**: カテゴリの定義を具体的かつ詳細に行う
2. **バランスの取れたデータセット**: 肯定的・否定的な例を適切に混ぜる
3. **定期的な更新**: 新たなトレンドや表現に合わせてモデルを更新
4. **パフォーマンスモニタリング**: モデルの精度を継続的に評価し最適化

カスタムカテゴリAPIは、Azure AI Content Safetyの強力な機能の一つとして、組織が安全で適切なオンライン環境を維持するための重要なツールとなっています。この機能を効果的に活用することで、コンテンツの品質管理と有害コンテンツの防止を、より柔軟かつ効率的に行うことが可能になります。
AWS認定試験 AIF-C01 受けてみた！(2025-03-15)

## はじめに
* CLF/SAA/SOA/DVAを取得している
* AIに関する知識はほぼない
* 直近のAssociate試験で苦労したこともあり、試験勉強を直前まで念入りに勉強した
   

## 試験結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4045441/a11b0a3d-7ccb-4c35-ace3-2a75c27ee822.png)
      
* 見直しは３つ
* 30分くらいで退室
* 久々にストレスなしで試験を受験できた
      

## 学習期間
* 20時間ほど

## 学習方法
* YouTubeでAIに関する用語の理解をした
* Web問題集のCloudTechを利用  
* Web問題集に出てくるワードを生成AIを活用して理解を深めた
* Web問題集で出てきた「マルチモーダル機能」。問題で終わらず、Claudeを使って実際に、テキストと画像を使ってデータを生成、出力する事に感動した
* ただの暗記ではなく、実機の操作と学習していることが繋がると理解度は深まる。このような学習方法が一番いいと感じる    
    
## 所感
* 資格試験を通じて得た知識をどう生かすかが大事であると感じた
* 次はMLAを受験したい
JBOSS - How to Migrate JBOSS 7 picketlink to JBOSS 8 keycloak-saml?

# 前言
因為 JBOSS EAP 8 已經刪除 picketlink 模組，並改用 keycloak-saml 取代，但 keycloak-saml 需要手動自行安裝。

# Step1. 下載 [keycloak-saml](https://mvnrepository.com/artifact/org.keycloak/keycloak-saml-wildfly-adapter-dist) 套件，目前最新版本是 26.1.4。

# Step2. 上傳到 /opt 並解壓縮
```shell
johnny# unzip -o /opt/keycloak-saml-wildfly-adapter-dist-26.1.4.zip -d keycloak-saml-wildfly-adapter-dist-26.1.4
```
# Step3. 複製套件到 JBOSS 資料夾底下
```shell
johnny# cp -R /opt/keycloak-saml-wildfly-adapter-dist-26.1.4/modules/system/add-ons/keycloak/org/keycloak/* /opt/jboss-eap-8.0/modules/system/layers/base/org/keycloak
```

# Step4.  執行安裝 keycloak-saml 設定
```shell
johnny# /opt/jboss-eap-8.0/bin/jboss-cli.sh --file=/opt/keycloak-saml-wildfly-adapter-dist-26.1.4/bin/adapter-elytron-install-saml-offline.cli -Dserver.config=standalone.xml
```

# Step5. 修改 standalone.xml
```xml
    <subsystem xmlns="urn:jboss:domain:keycloak-saml:1.4">
            <secure-deployment name="abs-portal.war">
                <SP entityID="https://YOUR_URL" sslPolicy="EXTERNAL" nameIDPolicyFormat="urn:oasis:names:tc:SAML:2.0:nameid-format:transient" forceAuthentication="false">
                    <Keys>
                        <Key signing="true" encryption="true">
                            <KeyStore password="changeit" file="/etc/pki/java/cacerts">
                                <PrivateKey alias="YOUR_URL_SSL_CERT_ALIAS_NAME" password="changeit"/>
                                <Certificate alias="YOUR_URL_SSL_CERT_ALIAS_NAME"/>
                            </KeyStore>
                        </Key>
                    </Keys>
                    <IDP entityID="https://YOUR_ADFS_URL">
                        <SingleSignOnService signRequest="true" validateResponseSignature="true" requestBinding="POST" responseBinding="POST" bindingUrl="https://YOUR_ADFS_URL" assertionConsumerServiceUrl="https://YOUR_URL/saml"/>
                        <SingleLogoutService validateResponseSignature="true" signRequest="true" requestBinding="POST" postBindingUrl="https://YOUR_URL"/>
                        <Keys>
                            <Key signing="true">
                                <KeyStore password="changeit" file="/etc/pki/java/cacerts">
                                    <Certificate alias="YOUR_ADFS_URL_SSL_CERT_ALIAS_NAME"/>
                                </KeyStore>
                            </Key>
                        </Keys>
                        <AllowedClockSkew unit="MILLISECONDS">120000</AllowedClockSkew>
                    </IDP>
                </SP>
            </secure-deployment>
        </subsystem>
```