OmniAICreator/Qiita-1.07M huggingface dataset:
VertiTab - サイドパネルの縦型タブ v2.10.0

こんにちは皆さん！VertiTabが v2.10.0 にアップデートされました！

Chromeブラウザで究極のサイドバータブ管理を体験しましょう。便利な新機能が盛りだくさん！

インストールはこちらから: 

https://chromewebstore.google.com/detail/chejfhdknideagdnddjpgamkchefjhoi?hl=ja


![Video_20241007233949_edit_edit (1).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3836968/26c3f332-bed0-372b-1e9d-7ce8474e0996.gif)


### 追加
- **ドキュメント ピクチャーインピクチャー**: プレミアムバージョンの拡張機能の公式リリース前に無料トライアルとして利用可能な高度なピクチャーインピクチャーを導入します。有効にすると、標準のピクチャーインピクチャーよりも優先されます。現在のページがサポートしていない場合は、標準モードが使用されます。高度なピクチャーインピクチャーは、次のような機能を備えたカスタムビデオプレーヤーを特徴とします：
  * **ビデオの再生/一時停止**（スペースまたはK）
  * **音量調整**（上/下矢印）
  * **ビデオのミュート/ミュート解除**（M）
  * **ビデオの早送り/巻き戻し**（左/右矢印またはマウスホイール）
  * **ビデオの5秒早送り/巻き戻し**（左/右矢印）
  * **ビデオの10秒早送り/巻き戻し**（J/L）
  * **次のビデオを再生**（Shift + N）
  * **前のビデオを再生**（Shift + P）
  * **字幕を表示**（youtube.com、vimeo.com、tver.jpなどの一部のウェブサイトでサポート）（C）
  * **弾幕を表示**（nicovideo.jp、bilibili.comなどの一部のウェブサイトでサポート）（D）
  * **ピクチャーインピクチャーを終了**（Esc）
  * **ビデオの表示/非表示と再生/一時停止を切り替え**（Q）
  * **全画面表示を切り替え**（F）
  * **再生速度を調整**（ > または <）
  * **ビデオの開始/終了にシーク**（Home/End）
  * **ビデオのパーセンテージにシーク**（0-9）
  * **ウィンドウをビデオサイズに合わせて調整**（W）
  * **メインページからピクチャーインピクチャーを切り替え**（Alt + P）


https://www.loom.com/share/cf4688be3c1a4e159a38e78a3426707d?sid=5b929682-c328-499e-b4ef-d320f065a77b
  
  > 頻繁に訪れるウェブサイトが字幕や弾幕をサポートしている場合は、[問題: 高度なピクチャーインピクチャー](https://github.com/RabbitPair/colorful_sidepanel_tabs_extension/issues/new?assignees=&labels=&projects=&template=Advanced-Picture-in-Picture.md&title=)を提出できます。できるだけ早く対応します。一部のウェブサイトには地域制限があり、追加情報が必要な場合がありますのでご注意ください。
- **ピクチャーインピクチャーのショートカット**: ピクチャーインピクチャーモードをすばやく切り替えるための新しいキーボードショートカットAlt+Pが追加されました。これにより、マウスを使用せずにビデオを簡単にピクチャーインピクチャービューに切り替えることができ、生産性とマルチタスクの能力が向上します。
- **下部ナビゲーションバーでピクチャーインピクチャーを切り替え**: 下部ナビゲーションバーにピクチャーインピクチャーの切り替えオプションを追加できるようになりました。これは、外観設定の「下部ナビゲーションバーを表示」-「設定」で構成できます。
- **URLでタブを並べ替え**: 「その他」メニューに新しいメニューオプション「URLでタブを並べ替え」が追加されました。
- **タブグループの折りたたみ動作**: 「高度なタブグループ」メニューに新しいオプション「タブグループの折りたたみ動作」が追加されました。ブラウザでタブグループの折りたたみ動作を変更できます。オプションには、「現在のグループを表示し、他のグループを折りたたむ」、「すべてのグループを展開」、「ブラウザのデフォルト設定を使用」が含まれます。
- **サイト設定**: サイト設定に3つの新しいオプションが追加されました：
  * **ピクチャーインピクチャー制限アクション**: ピクチャーインピクチャー制限のアクションを構成します。
  * **自動ピクチャーインピクチャー**: ページに入るときにビデオが存在する場合、自動的にピクチャーインピクチャーモードに入ります。
  * **キャプション設定**: ページ上のキャプション要素とその親要素のCSSセレクタを構成します。

### 変更
- サイドパネルタブが開いていない場合、「タブ切り替え時のピクチャーインピクチャー」が有効になっていると（デフォルトで有効）、自動的にピクチャーインピクチャーモードに入ります（重要なリマインダー：ユーザーの操作が必要です。ビデオを再生しているページをクリックするなどして、ユーザーの操作を有効にします）。
- ページのサイドバーを閉じると、非表示ではなく削除されるようになりました。ページを更新すると再表示されます。

### 修正
- クイックアクセスリストが複数のURLを処理しなかった問題を修正しました。

----


これまで以上にスマートで効率的なブラウジングを楽しんでください！
【Ruby】array.map(&:method)の記法の仕組みメモ

## 概要
`array.map { |a| a.method }` を `array.map(&:method)` と略記できるやつの仕組みを何度調べても忘れるのでメモ。
これに関する記事は他にも多くありますが、自分の中で咀嚼したつもりのものを書き残します。

## 本文
### 前提
`to_proc` を持つオブジェクトの頭に `&` をつけてメソッドの引数として渡すと、 `to_proc` が実行されProcオブジェクトとなり、メソッドにブロックとして渡される。

https://docs.ruby-lang.org/ja/latest/doc/spec=2fcall.html#block

また、Symbolクラスのインスタンスメソッド `to_proc` は、シンボルと同名のメソッドを呼び出し、第1引数をそのメソッドのレシーバとする。

https://docs.ruby-lang.org/ja/latest/class/Symbol.html#I_TO_PROC

### つまり

```ruby
# これの &:upcase 部分は
['hoge', 'fuga'].map(&:upcase)

# to_proc してメソッドに渡されるのでこれと同じ
proc = :upcase.to_proc
['hoge', 'fuga'].map(&proc)

# Symbol#to_proc は Proc.new したこれに置き換えられる
# (厳密にはlambdaらしいがわかりやすさのためにこれで)
proc = Proc.new { |a| a.upcase }
['hoge', 'fuga'].map(&proc)

# そしてそれはもはや直接ブロックを渡すこれと同じ
['hoge', 'fuga'].map { |a| a.upcase }
```
AndroidStudioのエミュレータが起動しない

### よくある対策
1. 一時ファイルを削除する
2. IDEやプラグインをアップデートする
3. Winodowsを再起動する

```deleteTemp.bat
del %USERPROFILE%\AppData\Local\Temp\AndroidEmulator\emu-crash-*.db /f /s /q
```

### 今回自分がハマったポイント

**ユーザー名のフォルダをASCIIにする**

Q. なぜ、こんなことにハマったのか？
A. 法人のMicrosoftアカウントでログインするため、ユーザー名（漢字）がフォルダ名になってしまう


会社に申請すればどうにかできるだろうけど、そもそもMicrosoftさん…？
いや、これを対策してないGoogleも…
【生成AI入門 OpenAI API】2024年10月　LangChainで簡単にOpenAI APIを使う方法

# 概要
・LangChainでOpen AIのAPIをコールするためのPythonコードを紹介します。
・OpenAIの公式サイトからAPIキーを発行していることが前提です。


# コード

``` Python 
import os
from langchain_core.messages import HumanMessage, SystemMessage
from langchain_openai import ChatOpenAI


# OpenAIのAPIキーを設定
os.environ["OPENAI_API_KEY"] = "{APIキーを入力してください}"

# OpenAIのインスタンスを作成
model = ChatOpenAI(model="gpt-4", max_tokens=200)

messages = [
    SystemMessage(content="日本語でチャットをしてください。ハルシネーションを起こさないで。"),
]

# チャットの実行
print("Chat with GPT-4. Type 'exit' to end the conversation.")
while True:
    user_input = input("You: ")
    if user_input.lower() == "exit":
        break
    if not user_input:
        print("メッセージを入力して下さい。")
        continue
    messages.append(HumanMessage(content=user_input))
    result = model.invoke(messages)
    print(f"GPT-4: {result.content}")

```

# 解説コメントアウト付き
``` python
import os
from langchain_core.messages import HumanMessage, SystemMessage
from langchain_openai import ChatOpenAI


# OpenAIのAPIキーを設定
os.environ["OPENAI_API_KEY"] = "{APIキーを入力してください}"
# 環境変数 "OPENAI_API_KEY" にAPIキーを設定し、OpenAI APIにアクセスする際に認証を行えるようにしています。

# OpenAIのインスタンスを作成
model = ChatOpenAI(model="gpt-4", max_tokens=200)
# ChatOpenAIクラスを使って、GPT-4モデルを使用するインスタンスを作成します。
# max_tokens=200は、生成される応答の最大トークン数を設定しています。

# 会話に含まれるメッセージリストを初期化
messages = [
    SystemMessage(content="日本語でチャットをしてください。ハルシネーションを起こさないで。"),
]
# 最初のメッセージとしてSystemMessageを設定しています。
# ここでは、「日本語でチャットをしてください」と指示することで、チャットが日本語で進行するようにしています。
# また、「ハルシネーションを起こさないで」と明示して、AIの誤った応答を減らすよう促しています。


# チャットの実行
print("Chat with GPT-4. Type 'exit' to end the conversation.")
# ユーザーに対して、チャットを開始することを示すメッセージを出力します。
# 'exit'と入力することで会話を終了できることを伝えています。

while True:
    user_input = input("You: ")
    # ユーザーからの入力を受け取ります。
    if user_input.lower() == "exit":
        break
        # 'exit'と入力された場合、whileループを終了してプログラムを終了します。
    
    if not user_input:
        print("メッセージを入力して下さい。")
        continue
        # 入力が空の場合、再度メッセージを入力するように促します。

    # ユーザーからのメッセージを追加
    messages.append(HumanMessage(content=user_input))
    # ユーザーからの入力をHumanMessageとしてメッセージリストに追加します。

    # モデルにメッセージを送信して応答を生成
    result = model.invoke(messages)
    # ここでChatOpenAIインスタンスを使って、モデルにメッセージリストを送信し、AIからの応答を受け取ります。

    # AIからの応答を出力
    print(f"GPT-4: {result.content}")
    # モデルからの応答を画面に出力します。


```
Amazon Athenaについて

## Amazon Athenaについて
Amazon Athenaとは所定の形式で格納されたAmazon S3上のデータに対して標準SQLを実行できるサーバーレスのデータ分析サービスです。Athenaは内部的にはオープンソースの分析型SQLクエリエンジンであるPrestoで実装されていて、CSV、JSON、ORC、Avro、Parquetのデータ形式に対応しています。また、AthenaはJDBCドライバを通じてBIツールとの連携が可能です。

## Prestoとは
presto (または PrestoDB) は、オープンソースの分散型 SQL クエリエンジンです。Amazon AthenaではAmazon EMRでPrestoを使用した場合と同じような処理が可能ですがAthenaを使うと自前でインフラの管理をすることなくクエリから簡単に結果を取り出すことができます。
XcodeでiOSのバージョンの最低設定を変更する手順

XcodeでiOSのバージョンの最低設定を変更する手順です。

Xcode　Version 16.0を使用しました。

![スクリーンショット 2024-09-27 10.34.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274615/1c5469ab-8333-7ca5-f773-20766ede5b91.png)

左側の「TARGETS」セクションから変更したいターゲットを選択します。
Build Settingsをクリックします。
「iOS Deployment Target」を検索すると画像のようになります。

あとは値を希望する最低設定を入力すれば終わりです。
VPCフローログについて

## VPCフローログとは
VPCフローログはVPC内の通信の解析に利用します。VPC内のENI(Elastic Network Interface)に流れるネットワークトラフィック情報を出力する機能です。ログはAmazon CloudWatch LogsまたはS3へ保存されます。記録される内容は送信元/送信先IPアドレス、送信元/送信先ポート番号、プロトコル番号、通信の許可/拒否の結果などがあります。
AWS Global Acceleratorについて

## AWS Global Acceleratortとは
ユーザーからAWSリソースまでのアクセス経路をAWSネットワークを利用して最適化するサービスです。
通常インターネット経由のアクセスの場合、AWSリソースがあるリージョンまでに経由するインターネット回線の影響を受けます。Global Acceleratorを利用するとユーザーから最も近いAWSエッジロケーションにリクエストをルーティングできます。
Global Acceleratorは2つの固定パブリックIPアドレスを保有しており、ユーザーはこの固定IPアドレスへアクセスします。エンドポイントが増減してもIPアドレスに影響なくサービスを継続できるため可用性が向上します。

## CloudFrontとの違い
CloudFrontはAWS上で動作する安全で高速なコンテンツ配信ネットワークです。コンテンツ配信ネットワークとは、インターネット上のコンテンツを高速化して配信するためのネットワークのことです。コンテンツ配信ネットワークでは、世界各地の配信サーバー（エッジサーバー）がオリジナルデータがあるサーバー（オリジンサーバー）のコンテンツをコピーして保管（キャッシュ）します。クライアントはオリジンサーバーへアクセスする代わりに、エッジサーバーのキャッシュからコンテンツを受け取ります。したがって固定IPアドレスという概念はありません。
CodeIQ:「スパイラル・ウォーク  」問題の解答

Kawazoe(@riverplus)さんのCodeIqの問題です。（<-2024.10.24追加）
問題はこちらにお世話になりました。解答例もあります。
->https://sw-logic.com/Portfolio/Programing/CodeIQ/3053.php
こちらにも情報があります。テストケースもこちらで見つけました。
->https://togetter.com/li/1062323

ほかにもテストケースがあったようです。今まで気が付きませんでした。(2025.5.3追加)
->https://sangaku0418.hatenablog.com/entry/2016/12/22/100100
有難く参照させていただきテストケースを追加しました。

図をよく見ると気が付くのですが、螺旋というのは目くらましで、要するに、
距離mの螺旋は（出発点を加えて）m+1個の交差点のある矩形を意味します。
そこでこれは積がm+1(m<=n)になる2以上の2つの整数の組み合わせを
求める問題です。

x\*y=m+1(m<=n)となるx,yをmごとに求めるのと
x\*y<=n+1となるyをxごとに求めるのは同等ですので
2<=x<=sqrt(n+1)のxに対してx*y<=n+1になるy（x< y,y>x,x=y)を集めます。
あるxに対してx\*y<=n+1となるyの数はdiv(n+1,x)個あります。
そのうちx>=yとなるのがx\*1...x*xのx個ですので
x< yとなるyの数はdiv(n+1,x)-xです。y>xとなるyの数も同じです。
これを2<=x<=sqrt(n+1)のxについて足していきます。
x=yとなるのはxの数と同じですので最後にint(sqrt(n+1))-1を足します。

元の問題の範囲ではbigはいりません。
10^15で3-5秒くらいかかります。

ideoneがまた使えるようになっていました。

```Julia
#ver 1.53, 1.73,1.10.3

function solve(n,a)
     sum=big(0)
     k=Int(floor(sqrt(n+1)))
     for i in 2:k
        sum += div(n+1,i) - i  #(i^1...i^iの数を引く->x<yとなるyの数)
     end
     sum　=　sum + sum　+　k-　1   #(y>xとなるyの数とx=yとなるyの数を足す)
     s = a == sum ? "ok " : "no "
     println(s,sum)
end

#2025.5.3テストケース追加
solve(1,0)
solve(11,12)
solve(100,283)
solve(1000,5076)
solve(25, 40)
solve(298,1152)
solve(1234, 6518)
solve(137945, 1377974)
solve(876459, 10375657)
solve(991245,11856448)
solve(1000000,11970037)
solve(1000000000,18877697665)
solve(1000000000000,25785452449093)
solve(1000000000000000,32693207724724373)
#solve(1000000000000000000,419035480966899467511)

```
Prologも同じ方針で書いています。
10^15で7秒以上かかります。

```Prolog
%:-initialization(start).   %(Online Prolog Compiler,ideone.)
%start.

loop(_,1,R,R).
loop(N,E,R1,R):-
    R2 is R1+div(N,E) - E,E1 is E-1,loop(N,E1,R2,R).

solve(N,R):-    
   N1 is N+1,E is floor(sqrt(N1)),loop(N1,E,0,R1),
   R is R1*2 + E - 1.
   
start:-f(N,A),(solve(N,R)->(R==A->Str=" ok  ";Str=" no  ");
    write(fail)),write(" "),write(Str),writeln(R),fail.
start.

%2025.5.3テストケース追加
f(1,0).
f(11,12).
f(100,283).
f(1000,5076).
f(25, 40).
f(298,1152).
f(1234, 6518).
f(137945, 1377974).
f(876459, 10375657).
f(991245,11856448).
f(1000000,11970037).
f(1000000000,18877697665).
f(1000000000000,25785452449093).
%f(1000000000000000,32693207724724373).
%f(1000000000000000000,419035480966899467511).
```
Android Studioショートカットキー

これまではWeb開発で`VSCode`を使用していましたが、アプリエンジニアへのキャリアチェンジをきっかけに`Android Studio`を使用することが増えたので、ショートカットキーをまとめました。

### ツールウインドウの開閉
```
⌘ + 0~9
```

画面左にあるツールウインドウの開閉を行うことが可能
各ツールにマウスホバーすることで対応する番号を確認することできる
![スクリーンショット 2024-10-05 9.05.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2987584/f8631ba7-b611-1ed3-3e0a-c93eb3060d0c.png)

### 設定画面を開く
```
⌘ + ,
```

### ファイル内検索
開いているファイル内で単語検索を行う
```
⌘ + F
```

### プロジェクトファイル内検索
単一ファイル内だけでなく、全てのファイルから検索
```
⌘ + ⇧ + F
```

### 置換
指定した文字列を別の文字に置き換える
```
⌘ + R
```

### プロジェクトファイル内置換
```
⌘ + ⇧ + R
```

# 開発系
### クイックドキュメントの確認
```
⌘ + J
```

### コメントアウト
```
行単位でのコメントアウト
⌘ + /

ブロック単位でのコメントアウト
⌘ + ⌥ +  /
```
AIの分類とデータドリブン

# はじめに
　AIという言葉は多くの場面で使われていますが、定義が曖昧であり、具体的に何を指しているのかが文脈によって大きく異なることがよくあります。単純なプログラムから、高度なディープラーニングを活用するシステムまで、AIにはさまざまなレベルや種類があります。本記事では、その分類を明確にし、AI技術の発展を理解する一助としたいと思います。

# AIの分類
　人工知能（AI）は、大まかに4つのレベルに分けて説明されます。

- **レベル1: 単純な制御プログラム**

説明: 温度センサーを使ってエアコンのオン/オフを制御するなど、シンプルな仕組みを指します。

特徴: 学習や適応を伴わない、単純な制御プログラムです。

- **レベル2: 古典的な人工知能**

説明: 自ら学習はしないが、自動掃除ロボットのように複雑な動作を行うAIです。

特徴: 事前にプログラムされた動作を行うが、自主的に学習する機能はありません。

- **レベル3: 機械学習を取り入れたAI**

説明: 通販サイトの推薦システムのように、自ら特徴やルールを学習するAIです。

特徴: 機械学習を利用してデータのパターンに基づいて適応することができます。

- **レベル4: ディープラーニングを取り入れたAI**

説明: 機械学習の中でもディープラーニングを活用し、高精度な結果を実現するAIです。

特徴: 深層学習（ディープラーニング）によって、より高精度かつ複雑な問題に対応できます。

![17280883542517860794437216375569.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2631481/e7551089-c17f-e72f-4566-6598cdd9d583.jpeg)

引用：https://zero2one.jp/ai-word/classification-of-ai/

# データドリブンとは

　データドリブンとは、データを基にして意思決定やシステム設計を行うアプローチのことです。例えば、機械学習においては、システムが大量のデータを使って自動的にパターンやルールを学習し、その結果に基づいて適切な判断や予測を行います。このような手法は、プログラムされたルールに頼ることなく、データそのものに基づいて行動するため、「データドリブン」（Data-Driven）と呼ばれます。

## データドリブンに含まれるAI

　上記のようにAIを分類した場合、**レベル3**および**レベル4**がデータドリブンな手法に該当します。

- **レベル3: 機械学習を取り入れたAI**  
  このレベルのAIは、データから学習する能力を持っています。つまり、データを基に自ら特徴やルールを発見し、その後の判断や行動に反映します。これは典型的なデータドリブンなAIと言えます。

- **レベル4: ディープラーニングを取り入れたAI**  
  ディープラーニングは、機械学習の中でも特に大量のデータを使用して高度な予測や分類を行います。これもまた、データを使ってモデルを訓練し、精度の高い結果を得るため、データドリブンな手法です。

## データドリブンのメリット

1. **自動的な学習**  
   データドリブンなシステムでは、ルールを明示的にプログラムする必要がなく、データから自動的にパターンやルールを学習します。これにより、事前に全てのケースを予測してプログラムする必要がなく、システムが自らデータに基づいて学習するため、より柔軟な対応が可能です。

2. **複雑な問題に対応可能**  
   データドリブンのアプローチは、特に人間がルールベースで定義することが困難なタスクや、非常に複雑なデータに対しても有効です。機械学習やディープラーニングを用いることで、画像認識や音声認識、自然言語処理などの高度な技術が実現されます。

# 終わりに

　データドリブンなアプローチは、AI技術の中でますます重要性を増しています。大量のデータを用いて学習することで、これまで予測が難しかった現象を把握し、新たな知見を得ることができます。これからもAIの進化に伴い、より精度の高い予測や意思決定が可能となるでしょう。データドリブンによる可能性は無限大であり、私たちは今後もその恩恵を享受していくと思われます。
IAM Identity CenterユーザーのprofileをAWS CLIに登録する手順

## はじめに

AWS 初学者です。

AWS CLIの profile にIAM Identity Centerユーザーを登録する手順を備忘録としてまとめます。

この記事におけるバージョンは次のとおりです。

```bash
$ aws --version           
aws-cli/2.17.56 Python/3.12.6 Darwin/23.4.0 exe/x86_64
```

なおIAM Identity Centerユーザーは作成してある前提です。

また記事で登場する`aws configure sso`コマンドは AWS CLI のバージョン2でしか利用できません。

バージョン1しかインストールされていない場合は[公式ドキュメント](https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/getting-started-install.html)の手順にしたがって事前にアップデートしましょう。

## IAM Identity CenterユーザーのprofileをAWS CLIに登録する手順

`aws configure sso`コマンドを実行し、流れに沿って入力していけばOK。

```bash
$ aws configure sso
SSO session name [default]: sample-profile
SSO start URL [None]: https://a-1234567a01.awsapps.com/start/
SSO region [None]: ap-northeast-1
SSO registration scopes [sso:account:access]: sso:account:access
Attempting to automatically open the SSO authorization page in your default browser.
If the browser does not open or you wish to use a different device to authorize this request, open the following URL:

https://device.sso.ap-northeast-1.amazonaws.com/

Then enter the code:

ABCD-EFGH
The only AWS account available to you is: 123456789012
Using the account ID 123456789012
The only role available to you is: PowerUserAccess
Using the role name "PowerUserAccess"
CLI default client Region [ap-northeast-1]: ap-northeast-1
CLI default output format [json]: json
CLI profile name [PowerUserAccess-597088053766]: sample-profile

To use this profile, specify the profile name using --profile, as shown:

aws s3 ls --profile sample-profile
$ 
```

`SSO registration scopes`を入力後、ブラウザが起動します。

ターミナルのコード（`ABCD-EFGH`）とブラウザに表示されるコードが一致しているか確認し、問題なければ承認してください。

ターミナルに戻ると`CLI default client Region`が入力できるようになっています。

登録が完了したら、ログインできることを確認しましょう。

```bash
$ aws sso login --profile sample-profile
Attempting to automatically open the SSO authorization page in your default browser.
If the browser does not open or you wish to use a different device to authorize this request, open the following URL:

https://device.sso.ap-northeast-1.amazonaws.com/

Then enter the code:

ABCD-EFGH
Successfully logged into Start URL: https://a-1234567a01.awsapps.com/start/
```

`aws sso login`コマンドを実行すると再びブラウザが立ち上がります。

ターミナルのコマンド（`ABCD-EFGH`）とブラウザに表示されるコードが一致しているか確認し、問題なければ承認してください。

ターミナルに戻って`Successfully logged into Start URL: 〇〇`と表示されていれば成功です。

設定されたプロファイルは`~/.aws/config`ファイルに保存されます。

必要に応じて直接編集することも可能です。

```
$ cat ~/.aws/config
[profile sample-profile]
sso_session = sample-profile
sso_account_id = 123456789012
sso_role_name = PowerUserAccess
region = ap-northeast-1
output = json
[sso-session sample-profile]
sso_start_url = https://a-1234567a01.awsapps.com/start/
sso_region = ap-northeast-1
sso_registration_scopes = sso:account:access
```


## おわりに

AWSは公式ドキュメントが充実しているのですが、逆にありすぎて探すのに一苦労です。

逐一アウトプットして定着させていきます。

### 参考資料

https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-sso.html

https://dev.classmethod.jp/articles/how-to-use-terraform-with-aws-sso-permission/
コマンドラインインターフェース (CLI) の基本操作

---
CLI（コマンドラインインターフェース）では、ユーザーが「コマンド」を入力してコンピュータに指示を出し、結果が文字で返されます。ここでは、よく使われる基本コマンドや概念を整理しました。

---

## ディレクトリとパスの基本

- **ディレクトリ**  
  フォルダと似ていますが、CLIでは「ディレクトリ」と呼びます。

- **階層構造 (ツリー構造)**  
  ディレクトリの中にディレクトリが存在する構造。

- **カレントディレクトリ**  
  現在作業中のディレクトリ。`pwd`で確認可能。

- **ホームディレクトリ**  
  自由に使えるディレクトリで、ログイン時の初期位置。

- **ルートディレクトリ**  
  階層構造の最上位にあるディレクトリ。パスは `/` から始まる。

- **パス**  
  ディレクトリやファイルの場所を示す文字列。

- **引数**  
コマンドに渡す値。例：`cd ディレクトリ名` の場合、`ディレクトリ名`が引数。
 
- **｜(バーティカルバー)** 
2つのコマンドを連結して、1つの結果を別コマンドに渡す。

- **① && ②**  
2つのコマンドを連結。①を実行後、成功した場合に②を実行。
---

## 基本コマンド一覧

| コマンド | 説明 |
| -------- | ---- |
| `pwd`    | カレントディレクトリのパスを表示 |
| `ls`     | カレントディレクトリの内容を表示 |
| `cd`     | ディレクトリを移動（引数なしでホームディレクトリへ） |
| `rm`     | ファイルを削除：`rm ファイル名` |
| `touch`  | 新しいファイルを作成：`touch ファイル名` |
| `echo`  | 引数の内容を表示：`echo test >> memo.txt` でファイルに追記 |
| `mkdir`  | 新しいディレクトリを作成：`mkdir ディレクトリ名` |
| `rmdir`  | ディレクトリを削除：`rmdir ディレクトリ名` |
| `cp`     | ディレクトリをコピー：`cp ディレクトリ名 移動先パス` |
| `mv`     | 引数によって、動作が変わる。移動or名前の変更 |
| `①mv`     | ディレクトリを移動：`mv ディレクトリ名 移動先` |
| `②mv`     | ディレクトリ名を変更：`mv ディレクトリ名 ディレクトリ名` |
|      |「既に存在しているディレクトリのパス」を指定する場合には、「名前は②、中身は①」のディレクトリができる|
| `history`| コマンド履歴を表示 |
| `zip`    | ファイルやディレクトリを圧縮：`zip 〇〇.zip ファイル(ディレクトリ)名` |
| `unzip`  | 圧縮ファイルを解凍：`unzip 〇〇.zip` |
| `exit`   | CLIを終了 |

---

## オプションコマンド

| オプション | 説明 |
| ---------- | ---- |
| `-a` / `--all`     | 隠しファイルも含めて表示 |
| `-f` / `--force`   | コマンドを強制実行 |
| `-i`               | 確認ステップを追加。削除時に「y」で実行可能 |
| `-r`               | ディレクトリ全体に対してコマンドを実行 |
| `-R`               | 再帰的に実行（ディレクトリ内のディレクトリにも適用） |
| `--help`           | コマンドの使い方を表示 |
| `-v` / `--version` | バージョン情報を確認 |

---

## 知っておくと便利な機能

- **Tabキー補完**  
  コマンド入力中にTabキーを押すと、ディレクトリやファイル名を自動補完。

- **ワイルドカード (`*`)**  
  任意の文字列を表す。
  例：`ls *.txt`でテキストファイルのみを表示。

- **履歴検索**  
  `history | grep コマンド` で、特定のコマンドを履歴から検索。例：`history | grep mv`


---

随時更新していきます。
JupyterNotebook を GitHubPages にデプロイする

JupyterLite を使用することで可能です。  
JupyterNoteBook を WASM 実装しているようです。  
GoogleColab の場合、Google アカウントが必要になりますが、JupyterLite はアカウント不要です。

https://github.com/jupyterlite/jupyterlite

多くの Python ライブラリ（特にネイティブコードに依存するもの）は、まだ WebAssembly 上では動作しません。

## 手順

[1]　[デモページ](https://github.com/jupyterlite/demo)にアクセスし、「Use the template」から「Create a new Repository」を選択する

![1](https://github.com/user-attachments/assets/30ea71ec-6ab3-418b-adca-bc60fa1e56b0)

[2] デモリポジトリが自分のアカウントにフォークされるので、フォークしたリポジトリにアクセスする

※私の場合は次の URL

https://github.com/pea-sys/jupyterlite-demo

[3] Settings タブ -> Actions -> General と選択し、ワークフロー権限を読み取りと書き込み権限に変更する

![2](https://github.com/user-attachments/assets/c4536a47-0472-460e-b2a8-69936561fa8d)

[4] Pages を選択し、Build and depoloyment を GitHub Actions に変更する

![3](https://github.com/user-attachments/assets/356f714b-7768-442c-a996-9aef292ab7c3)

[5] Actionst タブから initial Commit を選択し、Re-run-all jobs を実行する

![4](https://github.com/user-attachments/assets/e6465c73-fcf1-471e-86af-e0f9a3f5a6ab)

[6] 成功するとデプロイ先の URL が表示されるのでアクセスする

![6](https://github.com/user-attachments/assets/5c892f3f-7d40-462c-932d-a9bd40816ef5)


[7] デフォルトの設定を変えたい場合は、replフォルダ配下にoverride.json を作成します  
     例えば、次のようにすることでデフォルトでダークテーマで表示します。

```json
{
  "@jupyterlab/apputils-extension:themes": {
    "theme": "JupyterLab Dark"
  }
}
```

[8] デフォルトで使用できるパッケージは少ない。例えば、pandasを使用するには、各種ライブラリをインストールします。

```Python
import piplite
piplite.install("matplotlib==3.3.3")
piplite.install("itkwidgets>=1.0a5")
piplite.install("skimage==0.19.2")
piplite.install("pandas>=1.4.0")
piplite.install("pooch>=1.3.0")
```

![ss](https://github.com/user-attachments/assets/e4483ce8-b87e-46aa-8e7f-f9bd400389ee)

[9] Kernel を追加したい場合は、replフォルダ配下のrequirements.txt を編集する  
     例えば、SQliteKernel を使いたい場合、次の行を追加する

```
# SQLite kernel（optional)
jupyterlite_xeus_sqlite
```

デプロイされた Notebook に SQLite が追加されていることが確認できる

![ss](https://github.com/user-attachments/assets/64afedeb-526b-443a-86c0-033ad0039156)

最終的な成果物

https://pea-sys.github.io/jupyterlite-demo/lab/index.html

以上
macOSのバージョンを調べる方法

## はじめに

macOSユーザーの皆様、オペレーティングシステムのバージョン確認は、トラブルシューティングやソフトウェアの互換性チェックに不可欠です。今回は、ターミナルを使用したバージョン確認方法をご紹介します。

## sw_versコマンド

macOSには、システム情報を簡潔に表示する`sw_vers`（print macOS system version information）コマンドが実装されています。
### 基本的な使用方法

ターミナルを起動し、以下のコマンドを入力します:

```bash
sw_vers
```

このコマンドは、以下のような出力を生成します:

```
ProductName:            macOS
ProductVersion:         15.0.1
BuildVersion:           24A348
```

ここで表示される情報は以下の通りです:
- **ProductName**: オペレーティングシステムの名称
- **ProductVersion**: macOSのメジャーバージョン番号
- **BuildVersion**: 特定のビルドを識別する文字列

## オプションの活用

`sw_vers`コマンドには、より詳細な情報を取得するためのオプションが用意されています。

### --productVersion オプション

特定のバージョン情報のみを取得したい場合、`--productVersion`オプションが有用です:

```bash
sw_vers --productVersion
```

この場合、出力は以下のようになります:

```
15.0.1
```

このオプションは、スクリプト内でバージョン番号を変数として使用する際に特に便利です.

## まとめ

`sw_vers`コマンドは、macOSのバージョン情報を正確に取得するための便利なツールです。GUIベースの方法と比較して、このコマンドラインツールは自動化やスクリプティングに適しており、システム管理者や開発者にとって非常に有用です。
DFPlayer Miniで音楽再生中はLEDを点灯するようにしてみた

この記事では音楽が再生している間はLEDを付けるように制御してみます。このような記事はネットで見つからなかったので、自分で作成してみました。
DFPlayer Miniの音楽再生方法がわからない方はこちらの記事(https://qiita.com/ajimaru/items/dfd1e75d8de20980f665)
を参考にしていただくと、理解が深まると思います

# 準備

・Arduino UNO R3
・DFPlayerMini 秋月商店で購入可能
・マイクロSDカード　32GB以下でフォーマット形式がFAT16またはFAT32であること
・ジャンパワイヤ
・スピーカ
・LED　2個
・抵抗器1kΩ　2本
・抵抗器200Ω　1本

# 配線

配線はこのようになります。
![3899B24F-865A-462C-9BC0-1DD2DA8E3C4F.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3900339/6cae0228-f0d4-fb43-695b-5f64f71ed963.jpeg)


まず、df playerでは、 vccなどのピンを使ってましたが、今回は再生中にLEDをつけたいので、busyピンというのを使います。これは再生中はLOW、再生中でないときはHIGHとなるのでこれを利用して、LEDを付けたり消したりします。
![スクリーンショット 2024-10-02 201307.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3900339/7a3ebd9e-4d3c-a5d3-5b62-2a548664250d.png)



また、LEDの点灯ですが、こちらは電流を安定させるために抵抗器200Ωを入れてます。


# コード

コードは次のようになります。LEDとBUSYピンを追加してます。

```
#include <SoftwareSerial.h>
#include <DFRobotDFPlayerMini.h>

// DFPlayer MiniとArduinoのシリアル通信用
SoftwareSerial mySoftwareSerial(10, 11); // RX, TX
DFRobotDFPlayerMini myDFPlayer;

const int busyPin = 4; // DFPlayer MiniのBUSYピン
const int ledPin = 9;  // LEDを接続するピン

void play_sound(int folder,int file){
 
  int end_flg = 0;
  
  myDFPlayer.playFolder(folder, file);
LOOP:
  // BUSYピンがLOWなら再生中
  if (digitalRead(busyPin) == LOW) {
    digitalWrite(ledPin, HIGH); // LEDを点灯
    Serial.println("0");
    end_flg = 1;
  } else {
    digitalWrite(ledPin, LOW);  // LEDを消灯
    Serial.println("1");
    if(end_flg == 1)  end_flg = 2;
  }
  if(end_flg != 2)  goto LOOP;
}

void setup() {
  // シリアル通信の初期化
  Serial.begin(115200);
  mySoftwareSerial.begin(9600);
  
  // DFPlayerの初期化
  if (!myDFPlayer.begin(mySoftwareSerial)) {
    Serial.println("DFPlayer Miniの初期化に失敗しました");
    while(true);
  }
  
  // LEDピンとBUSYピンのモード設定
  pinMode(ledPin, OUTPUT);
  pinMode(busyPin, INPUT);
  
  Serial.println("DFPlayer Miniの初期化が成功しました");
  
  // ボリューム設定
  myDFPlayer.volume(30);  // 音量を0-30の範囲で設定
}

void loop() {
  play_sound(1,1);
  delay(1000);
  play_sound(99,100);
  delay(1000);
  play_sound(99,103);
  delay(1000);
}

```

音楽を再生する関数では、音楽が鳴り終わるまでは次の音楽を再生しないようにendflagをたててます。最初は0で再生しだすと1でたてて、再生し終えると2にします。それにより、2ということは終わってるので再生関数を抜けられます。
```
void play_sound(int folder,int file){
 
  int end_flg = 0;
  
  myDFPlayer.playFolder(folder, file);
LOOP:
  // BUSYピンがLOWなら再生中
  if (digitalRead(busyPin) == LOW) {
    digitalWrite(ledPin, HIGH); // LEDを点灯
    Serial.println("0");
    end_flg = 1;
  } else {
    digitalWrite(ledPin, LOW);  // LEDを消灯
    Serial.println("1");
    if(end_flg == 1)  end_flg = 2;
  }
  if(end_flg != 2)  goto LOOP;
}
```

# テスト

テストしたところ、再生中はランプが光り、再生してない場合は消えてるのでオーケーとなりました。

# 最後に
以上が音楽再生中でのLEDの点灯方法でした。ご意見感想などあればぜひコメントしてください。
AIエージェントのガバナンス - 安全で責任あるAIのための提言

## はじめに

AI技術の目覚ましい進歩は、AIエージェントシステムという新たな可能性を切り開きました。[生成AIのハイプ・サイクル：2024年](https://www.gartner.co.jp/ja/newsroom/press-releases/pr-20240910-genai-hc) において**自律エージェント**として言及されているAIエージェントは、黎明期に位置付けられています。これは、技術の成熟度としてはまだ初期段階にあるものの、将来的な期待が高いことを示唆しています。  

本稿では、OpenAIの研究者らによるホワイトペーパー *[Practices for Governing Agentic AI Systems](https://openai.com/index/practices-for-governing-agentic-ai-systems/)* を基に、AIエージェントのガバナンス、特にそのエージェント性に焦点を当てた実践的な提言と実装における課題を考察します。


## AIエージェントとは？その利点とリスク、そしてエージェント性

AIエージェントは、従来のAIシステムとは異なり、環境との相互作用を通じて学習し、適応的に行動します。ホワイトペーパーでは、AIエージェントを **「適応的に複雑な目標を追求し、複雑な環境下で限定的な直接監督の下で動作するシステム」** と定義し、この**エージェント性**こそがAIシステムとの大きな違いであると強調しています。

**エージェント性**とは、目標の複雑さ、環境の複雑さ、適応性、独立した実行という4つの要素から構成されます。複雑な目標を、複雑な環境の中で、状況に合わせて適応しながら、人間による介入を最小限に抑えて実行できる能力、それがエージェント性です。

例えば、旅行計画を立てるAIエージェントを考えてみましょう。

- 目標: ユーザーの希望や予算に合った最適な旅行プランを作成する。例えば、ユーザーが「ローマで歴史的な観光地を巡り、美味しいイタリア料理を楽しみたい。予算は20万円」と指定した場合、エージェントはその条件に合った旅程、航空券、ホテル、レストランなどを提案します。
- 環境: 航空券予約サイト、ホテル予約サイト、観光情報サイトなど、複数の外部ツールと対話する必要がある複雑な環境。これらのサイトはそれぞれ異なるインターフェースやデータ形式を持っており、エージェントはそれらを理解し、適切に操作する必要があります。
- 適応性: ユーザーの好みや予算の変更、航空券の価格変動、天候の変化など、予期せぬ状況にも対応する必要がある。例えば、予約済みのフライトが欠航になった場合、エージェントは代替のフライトを探し、ホテルの予約を変更するなどの対応を自律的に行います。
- 独立性: ユーザーとの対話を最小限に抑えつつ、旅行プランの作成、予約、チケットの手配などを自律的に行う。ユーザーは初期の希望を伝えるだけで、エージェントが残りの作業を処理してくれます。必要に応じて、エージェントはユーザーに追加情報を求める場合もあります。

AIエージェントは、高いエージェント性により、生産性の向上、ユーザーエクスペリエンスの向上、スケーラビリティの向上など、様々な利点をもたらすと期待されています。一方で、高いエージェント性であるが故のリスクとして、予期せぬ動作、悪用、責任所在の不明確化といった点が挙げられます。


### AIエージェントガバナンスのための7つの提言

ホワイトペーパーでは、AIエージェントのリスクを軽減し、高いエージェント性を安全に活用するための7つの実践的な提言が示されています。これらの提言は、AIエージェントの**エージェント性**を制御し、人間社会にとって有益な方向に活用することを目指しています。

1. **タスクへの適合性の評価**: AIエージェントを導入する前に、タスクへの適合性と信頼性を評価することが重要です。高いエージェント性を持つAIエージェントは想定外の状況にも適応するため、評価はより複雑になります。例えば、旅行計画AIを導入する場合、複雑な旅程や特別なニーズ（医療的な配慮、アクセシビリティなど）に対応できるか、信頼性のある情報源を利用しているかなどを評価する必要があります。

2. **行動空間の制約と承認要求**: 特にリスクの高い行動は、人間の承認なしに実行できないよう制約することで、予期せぬ結果を抑制します。旅行計画AIであれば、高額な航空券の購入や、安全性の低い地域のホテル予約など、リスクの高い行動はユーザーの承認を必須とするべきでしょう。

3. **エージェントのデフォルト動作設定**: デフォルトの動作を安全側に設定することで、予期せぬ損害を最小限に抑えます。AIエージェントは自律的に行動するため、デフォルト設定が重要になります。旅行計画AIでは、デフォルトで直行便を優先したり、キャンセル可能なホテルを予約したりするなど、安全性を重視した設定が考えられます。

4. **アクティビティの可読性向上**: AIエージェントの思考プロセスや行動履歴をユーザーが理解できる形で提供することで、透明性を確保し、問題発生時の対応を容易にします。旅行計画AIであれば、選択したフライトやホテルの理由、代替案の比較などをユーザーに分かりやすく提示することが重要です。

5. **自動監視**: AIエージェントの動作を自動的に監視し、リアルタイムで問題を検出することで迅速な対応を可能にします。旅行計画AIでは、予約状況、価格変動、天候の変化などを常時監視し、問題発生時にはユーザーに通知する機能が求められます。

6. **帰属可能性の確保**: AIエージェントの行動を特定の個人または組織に帰属させる仕組みを構築することで、説明責任を明確化し、悪用を抑制します。旅行計画AIの場合、どのAIエージェントがどの予約を行ったかを明確に記録し、問題発生時の責任所在を明確にする必要があります。

7. **中断可能性と制御の維持**: 緊急時や問題発生時には、AIエージェントの動作を中断または停止できる仕組みが不可欠です。ユーザーがいつでも旅行計画AIの動作を停止したり、予約を変更したりできるようにするべきです。

## 実装における課題と今後の展望

これらの提言の実装には、技術的・社会的な課題が伴います。ホワイトペーパーでは各提言に付随する具体的な課題や未解決の疑問も提示されており、今後の研究開発の指針となります。AIエージェントの**エージェント性**が高まるほど、これらの課題は複雑化すると予想されます。

AIエージェントシステムは社会に大きな変革をもたらす可能性を秘めています。その潜在能力を最大限に活かし、安全かつ責任ある形で利用するためには、技術開発だけでなく、ガバナンスの枠組みの構築が不可欠です。OpenAIのホワイトペーパー *[Practices for Governing Agentic AI Systems](https://openai.com/index/practices-for-governing-agentic-ai-systems/)* は、AIエージェントガバナンスを考える上で重要な指針となるでしょう。継続的な議論と技術の進歩への適応を通じて、AIエージェントと人間が共存する未来を築いていく必要があります。
Ubuntuコンテナの作成とコマンド実行及びサービスの追加

ホストOSからコンテナ内のUbuntuにSSH接続できるようにするための手順です。

### 1. Ubuntuコンテナの作成

まず、DockerでUbuntuコンテナを作成し、ホストのポート1022をコンテナの22番ポートにフォワーディングして、SSH接続できるようにします。

#### コマンド
```bash
docker run -d -p 1022:22 --name ubuntu-ssh ubuntu:latest bash -c "apt update && apt install -y openssh-server && service ssh start && /usr/sbin/sshd -D"

※sudo docker run -d -p 1022:22 --name ubuntu-ssh ubuntu:latest tail -f /dev/null
  sudo docker exec -it ubuntu-ssh bash
  apt-get update
  apt-get install -y openssh-server
  #apt-get install sudo
  #usermod -aG sudo <username>
  service ssh start
　こちのほうがうまくいく

```


- **`docker run -d`**: バックグラウンドでコンテナを起動します。
- **`-p 1022:22`**: ホストのポート1022をコンテナの22番ポートにフォワーディングします（SSH接続用）。
- **`--name ubuntu-ssh`**: コンテナに`ubuntu-ssh`という名前を付けます。
- **`bash -c`**: コンテナ起動時に以下のコマンドを順番に実行します：
  - `apt update`: パッケージリストを更新
  - `apt install -y openssh-server`: OpenSSHサーバーをインストール
  - `service ssh start`: SSHサーバーを起動
  - `/usr/sbin/sshd -D`: SSHデーモンをフォアグラウンドで起動し続ける（これによりコンテナが停止しません）

---

### 2. ユーザーの作成とパスワード設定

SSHで接続するために、新しいユーザーを作成し、パスワードを設定します。

#### 2.1 コンテナ内に入る
まず、コンテナ内にアクセスします。

```bash
docker exec -it ubuntu-ssh bash
※　sshサービスが起動されない場合は、次のコマンドで起動する。
　service ssh start

```

#### 2.2 ユーザーの作成
次に、SSH接続用のユーザーを作成します。

```bash
adduser yourusername
```

ここで、`yourusername`を好きなユーザー名に置き換えてください。パスワードを設定するように求められます。

---

### 3. ホストからコンテナにSSH接続

ホストマシンからSSHクライアントを使用して、コンテナに接続します。ポート1022を指定して接続します。

#### SSH接続コマンド
```bash
ssh -p 1022 yourusername@localhost
```

- **`-p 1022`**: ホストのポート1022を指定します（コンテナの22番ポートにフォワードされています）。
- **`yourusername`**: 先ほど作成したユーザー名です。

接続すると、先ほど設定したパスワードを求められるので、入力してログインします。

---

### 4. コンテナ再起動時に自動でSSHサーバーを起動する

コンテナを再起動しても、SSHサーバーが自動的に起動するように設定します。

#### 再起動ポリシーの設定
コンテナを再起動してもSSHサーバーが起動するようにするため、`--restart`オプションを追加します。例えば、次のようにコンテナを起動します。

```bash
docker run -d -p 1022:22 --name ubuntu-ssh --restart unless-stopped ubuntu:latest bash -c "apt update && apt install -y openssh-server && service ssh start && /usr/sbin/sshd -D"
```

- **`--restart unless-stopped`**: コンテナが手動で停止されない限り、自動的に再起動します。

これにより、ホストマシンの再起動後でも、コンテナは自動的に再起動し、SSHサーバーが動作するようになります。

---

### 5. 動作確認とトラブルシューティング

#### 5.1 コンテナのステータス確認
コンテナが正常に動作しているか確認するには、以下のコマンドを使用します。

```bash
docker ps
```

`ubuntu-ssh`が一覧に表示されていれば、コンテナは正常に動作しています。

#### 5.2 SSH接続テスト
ホストから再度SSH接続を試して、問題がないか確認します。

```bash
ssh -p 1022 yourusername@localhost
```

もし接続できない場合、以下を確認してください。
- ポートフォワーディングの設定が正しいか (`1022:22`)
- コンテナ内でSSHサーバーが正しく起動しているか (`service ssh status`)
- 作成したユーザーのパスワードが正しく設定されているか

---

### まとめ

1. **Ubuntuコンテナの作成とSSHサーバーのインストール**:  
   - `docker run`でコンテナを作成し、SSHサーバーをインストールして起動。
   - フォアグラウンドで`sshd`を起動し、コンテナが停止しないように設定。
   
2. **ユーザー作成とパスワード設定**:  
   - `adduser`コマンドでSSH接続用のユーザーを作成し、パスワードを設定。

3. **ホストからSSH接続**:  
   - ホストのポート1022経由で、SSHクライアントを使って接続。

4. **自動再起動設定**:  
   - コンテナを再起動した際にSSHサーバーが自動的に再起動するように設定。

これで、ホストOSからSSHでUbuntuコンテナに接続できる環境が整い、コンテナが停止することなく常に動作する状態になります。



追伸：再起動ポリシーの設定は以下で良かったかも。
docker run -d -p 1022:22 --name ubuntu-ssh --restart unless-stopped ubuntu:latest bash
【基本情報】独学マラソン フィリップ・コトラーの競争戦略 Day 5

マーケティングは企業の成長エンジン

:::note worn
この記事は自分用の備忘録です。
:::



# 誰？

### フィリップ・コトラー

- マーケティングの神様
- 「マーケティング・マネジメント」はマーケ界のバイブルらしい

https://www.amazon.co.jp/-/en/Philip-Kotler/dp/4621066137/ref=pd_sbs_d_sccl_2_3/356-7610972-1657332?pd_rd_w=4Hucj&content-id=amzn1.sym.99f902cf-fc99-4f25-a4a5-78eda3eec3ef&pf_rd_p=99f902cf-fc99-4f25-a4a5-78eda3eec3ef&pf_rd_r=8PBDGY5HCNG754WGR7XG&pd_rd_wg=WK5ru&pd_rd_r=ba88116b-c5ef-4a28-bb2e-76eb643e9f3d&pd_rd_i=4621066137&psc=1

- 「作ったものをどう売るか。これは昔のマーケティング。新しいマーケティングは、自分たちが何を作るべきかを決める。」
- 「新しいマーケティングは、ターゲット顧客に対してより優れた価値を創造し、コミュニケーションし、届けること。」

<br>

# コトラーの競争地位戦略

競合他社の基本戦略の内容を予測して自社の基本戦略を設計すること
業界内の立ち位置によって取る戦略が変わる
立ち位置は4つに分類される

<table>
<caption>経済資源の質と量で分類</caption>
  <thead>
    <tr>
      <th></th> <th>量：多</th> <th>量：少</th> 
    </tr>
  </thead>
  <tr>
    <td> 質：多 </td> <td>リーダー</td> <td>ニッチャー</td>
  </tr>
  <tr>
    <td> 質：少 </td> <td>チャレンジャー</td> <td>フォロワー</td>
  </tr>
</table>

### リーダー

- 業界におけるトップの座に位置する企業
    - スターバックス
- 市場シェアの維持と拡大を狙う
- 下位企業の安売りに応じない姿勢が大事
    - 差別化には同質化でねじ伏せる
        - Amazonがよくやるやつ
        - 最近OpenAIもGPTの機能追加という形でやってる気がする
- 独占禁止法に注意

### チャレンジャー

- リーダーを狙う企業
    - タリーズ、ドトール
- 経済資本の量や質では勝てないので、差別化戦略で勝負
    - リーダーの同質化戦略によって無力化されることもある
        - よって、自社でしか生み出せない新しい価値の創出が必要

### ニッチャー

- ニッチな分野への特化を目指した企業
    - 星乃珈琲
- 定番商品にひそむ”隙間”を見つけることが重要
- とにかくニッチな領域に特化
    - 集中化戦略
- 需要の変動には気を付けるべし
- 動物カフェとか高くても好きな動物なら行きたくなる、みたいな感覚

### フォロワー

- 経営資源が少なく、多くのライバルを抱える企業
    - エクセルシオール、ベローチェ
- リーダーやチャレンジャーの真似をする
    - 模倣戦略
        - 研究費用や開発費を抑えられる
        - 経験やノウハウを蓄積する
            - そしてオリジナル製品へ
- 徹底したコストダウンによって利益を確保する



# 感想
ニッチャー好きかも


# 参考

https://www.midknowledge-workshop.com/archives/competitive-position/

https://www.libcon.co.jp/column/ktlers-competitive-position-strategy/
[Python] 九九表の作成

# 九九表を作成する　その１
最初はfor文の二重ループを使って九九表を作成しました。
Python3.6から導入されたf文字列を使用して桁が揃うように出力されるようにしました。
~~~Python:kuku_1.py
for i in range(1, 10):
    for j in range(1, 10):
        print(f'{i * j:4d}', end="") # 4桁の幅で出力されるよう指定
    print("\n", end="")

# 実行結果
   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と基本的には同じですが、出力の部分で書式化演算子「%」を使っています。
CやJavaなど他のプログラミング言語に慣れている方にはお馴染みな書き方だと思います。
~~~Python:kuku_2.py
for i in range(1, 10):
    for j in range(1, 10):
        print('%2d' %(i * j) , end=' ') # 書式化演算子「%」を使用
    print()
# 実行結果はその１と同じです
~~~
# itertoolsを使う
itertools.product()を使って複数のリストの直積（デカルト積）を生成することで、forの入れ子による多重ループよりも簡潔にコードを書くことができます。
~~~Python:kuku_3.py
from itertools import product
for i, j in product(range(1, 10), range(1, 10)):
    print(f'{i} * {j} = {i * j}')
# 実行結果
1 * 1 = 1
1 * 2 = 2
1 * 3 = 3
1 * 4 = 4
1 * 5 = 5
1 * 6 = 6
1 * 7 = 7
1 * 8 = 8
1 * 9 = 9
2 * 1 = 2
2 * 2 = 4
2 * 3 = 6
2 * 4 = 8
2 * 5 = 10
2 * 6 = 12
2 * 7 = 14
2 * 8 = 16
2 * 9 = 18
3 * 1 = 3
3 * 2 = 6
3 * 3 = 9
3 * 4 = 12
3 * 5 = 15
3 * 6 = 18
3 * 7 = 21
3 * 8 = 24
3 * 9 = 27
4 * 1 = 4
4 * 2 = 8
4 * 3 = 12
4 * 4 = 16
4 * 5 = 20
4 * 6 = 24
4 * 7 = 28
4 * 8 = 32
4 * 9 = 36
5 * 1 = 5
5 * 2 = 10
5 * 3 = 15
5 * 4 = 20
5 * 5 = 25
5 * 6 = 30
5 * 7 = 35
5 * 8 = 40
5 * 9 = 45
6 * 1 = 6
6 * 2 = 12
6 * 3 = 18
6 * 4 = 24
6 * 5 = 30
6 * 6 = 36
6 * 7 = 42
6 * 8 = 48
6 * 9 = 54
7 * 1 = 7
7 * 2 = 14
7 * 3 = 21
7 * 4 = 28
7 * 5 = 35
7 * 6 = 42
7 * 7 = 49
7 * 8 = 56
7 * 9 = 63
8 * 1 = 8
8 * 2 = 16
8 * 3 = 24
8 * 4 = 32
8 * 5 = 40
8 * 6 = 48
8 * 7 = 56
8 * 8 = 64
8 * 9 = 72
9 * 1 = 9
9 * 2 = 18
9 * 3 = 27
9 * 4 = 36
9 * 5 = 45
9 * 6 = 54
9 * 7 = 63
9 * 8 = 72
9 * 9 = 81
~~~
# NumPyのブロードキャストを利用する
NumPyのブロードキャスト（形状の自動変換）を上手く使えば配列の掛け算一回で九九表が作成できます。ちなみに私はNumPyを初めたころ、配列の公差を指定するarangeをarrangeだと勘違いしていました（笑）
~~~Python:kuku_brdcast.py
import numpy as np
row = np.arange(1, 10).reshape(1, -1) #[[1, 2, 3, 4, 5, 6, 7, 8, 9]]
column = np.arange(1, 10).reshape(-1, 1) #[[1], [2], [3], [4], [5], [6], [7], [8], [9]]
kuku = row * column
print(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]]
~~~
Grove- HUBを改造してLチカ。(M5Nano C6)



![o_coq487.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/47fded9a-f624-a784-41c1-9b8de0750186.jpeg)



結果


![o_coq488.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/d95edaf9-93fa-08f8-9546-52cbaf1c0927.jpeg)


プログラム


```c++

/*
  Blink

  Turns an LED on for one second, then off for one second, repeatedly.

  Most Arduinos have an on-board LED you can control. On the UNO, MEGA and ZERO
  it is attached to digital pin 13, on MKR1000 on pin 6. LED_BUILTIN is set to
  the correct LED pin independent of which board is used.
  If you want to know what pin the on-board LED is connected to on your Arduino
  model, check the Technical Specs of your board at:
  https://www.arduino.cc/en/Main/Products

  modified 8 May 2014
  by Scott Fitzgerald
  modified 2 Sep 2016
  by Arturo Guadalupi
  modified 8 Sep 2016
  by Colby Newman

  This example code is in the public domain.

  https://www.arduino.cc/en/Tutorial/BuiltInExamples/Blink
*/

// the setup function runs once when you press reset or power the board
void setup() {
  // initialize digital pin LED_BUILTIN as an output.
  pinMode(1, OUTPUT);
}

// the loop function runs over and over again forever
void loop() {
  digitalWrite(1, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);                       // wait for a second
  digitalWrite(1, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);                       // wait for a second
}


```
create-pull-request@v7注意点

## 何
余計なことをしたせいでしょーもないところでハマったので備忘録
[create-pull-request@v7](https://github.com/peter-evans/create-pull-request)でGitHubのPR作成を自動化しようとしたときのちょっとしたハマりどころです。

## 起きたこと

こんなGitHub Actionを作ってました。差分があったら自動でPRを作りたかったのです。

```yaml
on:
  pull_request:
jobs:
  sample:
    runs-on: ubuntu-latest
    steps:
    - name: change
      run: |
      git branch -b "sample"
      <ファイルチェンジの処理何か>
      git add .
      git commit -m "Update!"
      git push origin sample
    - name: create pr
      uses: peter-evans/create-pull-request@v7
      with:
        branch: "sample"
        title: "auto update"
        body: "auto update dayo!"
        base: main
```

ただ、これを実行すると、**差分が全くないPR**が作成されてしまっていました。
commitもpushもうまく行っていたのになぜ？と思って調べてみると、create-pull-requestのステップで、その前のステップで作った同名のブランチを上書きしていることが判明…
つまり、create-pull-request以前のステップがなかったことになっていたのです。

## これが起きないようにするために

create-pull-requestさんはPR作成だけをやってくれるツールではなく、

- 新しいブランチ作成
- 差分の自動検出
- コミット
- リモートへのプッシュ
- PR作成

までを一括してやってくれるツールです。
ゆえに、手元で余計なことをしてはならず、ユーザーがGitHub Actionで指定すべきことは**ファイルを更新するべきことだけ**なのです。

これで問題解決。

```yaml
on:
  pull_request:
jobs:
  sample:
    runs-on: ubuntu-latest
    steps:
    - name: change
      run: |
      <ファイルチェンジの処理何か>
    - name: create pr
      uses: peter-evans/create-pull-request@v7
      with:
        branch: "sample"
        title: "auto update"
        body: "auto update dayo!"
        commit-message: "Update!"
        base: main
```

他のステップなどで適用した、今手元にある変更を、`with.branch`で指定したブランチに自動的にコミット＆プッシュしてくれます。`with.commit-message`を指定すれば、`git commit -m`のメッセージに代替させることもできます。かんたんだね。
【Ruby】後置ifは便利だけど計画的に使おう

# はじめに
本日は後置ifについての記事を書きたいと思います。
後置ifとは簡潔で読みやすいコードを書くための構文で、条件分岐を一行で書けるようにします。
主に、シンプルな条件を確認して動作を行いたいときや、コードの可読性を高めたいときに使用します。
後置ifの基本構文は`処理 if 条件`になります

## 後置ifのメリット
例えばこれは普通の`if`文です
```ruby:if.rb
if is_holiday
  puts "Enjoy your day!"
end
```
一方後置ifを使用すると
```ruby:back_if.rb
puts "Enjoy your day!" if is_holiday
```

とこんな感じで1行で済ませることができるのです。
メリットをまとめると
* コードが簡潔になる
* 可読性の向上
* 無駄なインデントを減らす
* 軽量な条件処理に向いている

## 後置ifのデメリット
上記を見る限りだとメリットのほうが多いからこれからは後置ifを多用しようと思いますよね。
しかし後置ifを使うことで可読性が逆に落ちてしまう例もあるのです
* 複雑な条件の場合
* 複数の処理を実行する場合
* elseが必要な場合
* ネストが深くなる場合

### 複雑な条件の場合
例えばこのコードを見てください。
```ruby:bad1.rb
puts "You passed!" if score > 60 && (attendance_rate > 80 || special_permission)
```
まあ読めなくはないが、横にずらーっと長くなってしまうのでとても見ずらいですね。

### 複数の処理を実行する場合
複数処理を実行する際にも後置ifはみずらくなってしまいます
```ruby:bad2.rb
puts "Processing data..." if ready
update_data if ready && granted
send_notification if notify && granted
```
ここでは ready、grantedなどの条件が絡むため、それぞれの処理が独立して散らばっており、どの条件で何が行われるのかを理解するのに時間がかかります。
また、同じ条件（granted など）が何度も出てくるため、条件の関係性が混乱しやすくなります。
```ruby:good2.rb
if ready
  puts "Processing data..."
  if granted
    update_data
    send_notification if notify
  end
end
```
これによって、同じ条件を繰り返し書く必要がなく、処理が一箇所にまとまるため、可読性が向上します。

### elseが必要な場合
後置ifはelseをサポートしていないため、条件によって異なる処理を行いたい場合には通常のif-else文を使うべきです。
```ruby:bad3.rb
puts "You're an adult." if age >= 18
puts "You're a minor." if age < 18
```

### ネストが深くなる場合
後置ifで条件をネストするのは避けたほうがいいです。
ネストが深くなると、読み手が条件の流れを理解するのが難しくなります。
```ruby:bad4.rb
puts "You passed with distinction!" if score > 90 if passed
puts "You passed!" if score.between?(60, 90) if passed
puts "You failed!" if score < 60 || !passed
```
それぞれの条件が別々に処理されているため、条件の分岐が複雑になるにつれ、どの条件がどの出力に対応するのかが分かりにくくなっています。
特にscore.between?(60, 90)やscore < 60など複数の条件があると、後置ifでは直感的に理解しにくくなります。
```ruby:good4.rb
if passed
  if score > 90
    puts "You passed with distinction!"
  elsif score.between?(60, 90)
    puts "You passed!"
  else
    puts "You failed!"
  end
else
  puts "You failed!"
end
```
特にelsifを含むような分岐や複雑なロジックが絡む場合、後置ifは逆にコードを難読化してしまうデメリットがあることがここから分かると思います。

# まとめ
今回は後置ifについての記事を作成しました。
短い分量でサクッとif文作れるのはとても魅力的ですが、複雑な条件の場合やネストが深くなる場合などの使用は極力さけて使いましょう。
レポートのUIの問題


+ [Cannot complete "Create Reports and Dashboards for Sales and Marketing Managers > Filter Your Reports"](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007erwbf)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/b11561ef-b6d5-a98f-13b7-79b76693c8a6.png)

:::note
Try your browser's incognito mode.Or try it in a different browser.

I had to switch to Salesforce Classic to get it done!
:::
M5NanoC6、ブザー Grove- Buzzer で遊ぶ




参考


![o_coq436.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/27c60e98-25b1-f32d-5477-12462cc5c9eb.jpeg)


https://qiita.com/caa45040/items/8c8ae674051215de13df


結果

わかりずらいが確かに音がなった
(発振器内蔵タイプだった)


![o_coq486.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/c0cf7cf9-110e-cda6-1462-f842a01a5772.jpeg)


プログラム


```c++

/*
  Blink

  Turns an LED on for one second, then off for one second, repeatedly.

  Most Arduinos have an on-board LED you can control. On the UNO, MEGA and ZERO
  it is attached to digital pin 13, on MKR1000 on pin 6. LED_BUILTIN is set to
  the correct LED pin independent of which board is used.
  If you want to know what pin the on-board LED is connected to on your Arduino
  model, check the Technical Specs of your board at:
  https://www.arduino.cc/en/Main/Products

  modified 8 May 2014
  by Scott Fitzgerald
  modified 2 Sep 2016
  by Arturo Guadalupi
  modified 8 Sep 2016
  by Colby Newman

  This example code is in the public domain.

  https://www.arduino.cc/en/Tutorial/BuiltInExamples/Blink
*/

// the setup function runs once when you press reset or power the board
void setup() {
  // initialize digital pin LED_BUILTIN as an output.
  pinMode(1, OUTPUT);
}

// the loop function runs over and over again forever
void loop() {
  digitalWrite(1, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);                       // wait for a second
  digitalWrite(1, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);                       // wait for a second
}


```
gofmtについて

## gofmtについて

goに標準で搭載されているコード整形機能のこと。
`fmt.Println()`ばかり使っていたのでこの機能を知った時はとても便利な機能があるなと思いました。

### 例）hogehoge.goのコード
```
package main

import "fmt"

const (
idKey   = "id"
	nameKey = "name"
		runeKey = 'a'
)

func main() {

	for i := 0;      i < 10; i++ {
		fmt.Println(i)
		          if i == 5 {
			break
}
	}

	t := 10
    fmt.Println(t)
	fmt.Println(1 + 1, 2+2)
	fmt.Println("1 + 1 =", 1+1)
	fmt.Println("10 - 1", 10-1)
	fmt.Println("10 / 2", 10/2)
	fmt.Println("10 / 3", 10/3)
	fmt.Println("10.0 / 3", 10.0/3)
	fmt.Println("10 / 3.0", 10/3.0)
	fmt.Println("10 % 2", 10%2)
	fmt.Println("10 % 3", 10%3)
}
```

### gofmt を使用後表示されるhogehoge.go
お使いのterminalにて`gofmt ファイル名`を打ってください。
すると下記のように表示されます。
```
~~~~~~~~~~~~~~~~~~ % gofmt hogehoge.go
package main

import "fmt"

const (
        idKey   = "id"
        nameKey = "name"
        runeKey = 'a'
)

func main() {

        for i := 0; i < 10; i++ {
                fmt.Println(i)
                if i == 5 {
                        break
                }
        }

        t := 10
        fmt.Println(t)
        fmt.Println(1+1, 2+2)
        fmt.Println("1 + 1 =", 1+1)
        fmt.Println("10 - 1", 10-1)
        fmt.Println("10 / 2", 10/2)
        fmt.Println("10 / 3", 10/3)
        fmt.Println("10.0 / 3", 10.0/3)
        fmt.Println("10 / 3.0", 10/3.0)
        fmt.Println("10 % 2", 10%2)
        fmt.Println("10 % 3", 10%3)
}
```

インデントやスペースを整形してくれるのはもちろんなのですが、constの定数の `=` が全て揃える事や`fmt.Println(1 + 1, 2+2)`が`fmt.Println(1+1, 2+2)`になったのを確認しました。pythonとはまたスタンダードが違うみたいです。


お使いのvscodeでは command + sで整形も設定すれば整形するようになると思うので、拡張機能とか設定をいじってみてください。
【備忘録】String.format の使い方

String.formatのメソッドについてのメモ書き。

## 文字列
文字列を扱う場合は、`%s` を使う。
```java:Sample.java
public class Sample {
  public static void main(String[] args) {
    String place = "動物園";
    String str = String.format("明日は、%sに行きます。", place);
    
    System.out.println(str); // 明日は、動物園に行きます。
  }
}
```

## 整数
整数を扱う場合は、`%d` を使う。
```java:Sample.java
public class Sample {
  public static void main(String[] args) {
    int age = 30;
    String str = String.format("私は%d歳です。", age);

    System.out.println(str); // 私は30歳です。
  }
}
```
`%,d` と記載することによって、3桁区切りでカンマを入れることができる。
```java:Sample.java
public class Sample {
  public static void main(String[] args) {
    int price = 1000000;
    String str = String.format("支払金額は、%,d円です。", price);

    System.out.println(str); // 支払金額は、1,000,000円です。
  }
}
```
「001234567」のように先頭を0で埋めたい場合は、`%09d`と記載する。
```java:Sample.java
public class Sample {
  public static void main(String[] args) {
    int id = 1234567;
    String str = String.format("あなたのIDは、「%09d」です。", id);

    System.out.println(str); // あなたのIDは、「001234567」です。
  }
}
```
「  1234567」のように先頭を空白で埋めたい場合は、`%9d`と記載する。
```java:Sample.java
public class Sample {
  public static void main(String[] args) {
    int id = 1234567;
    String str = String.format("あなたのIDは、「%9d」です。", id);

    System.out.println(str); // あなたのIDは、「  1234567」です。
  }
}
```

## 浮動小数点
浮動小数点を扱う場合は、`%f` を使う。
```java:Sample.java
public class Sample {
  public static void main(String[] args) {
    double pi = 3.14159265;
    String str = String.format("円周率は%fです。", pi);

    System.out.println(str); // 円周率は3.141593です。
  }
}
```
また、`%.2f` のように記載すると、表示する小数点以下の桁数を指定できる。
```java:Sample.java
public class Sample {
  public static void main(String[] args) {
    double pi = 3.14159265;
    String str = String.format("円周率は%.2fです。", pi);

    System.out.println(str); // 円周率は3.14です。
  }
}
```

## 日付／時刻
日付／時刻を扱う場合は、`%t〇` を使う。 (`〇`には日付／時刻書式の指定が必要)
```java:Sample.java
public class Sample {
  public static void main(String[] args) {
    Date day = new Date();　// Fri Oct 04 10:06:30 JST 2024 の場合
    
    System.out.println(String.format("%tD", day)); // 10/04/24
    System.out.println(String.format("%tY年 %tm月 %td日", day, day, day)); // 2024年 10月 04日

    System.out.println(String.format("%tT", day)); // 10:06:30
    System.out.println(String.format("%tH時 %tM分 %tS秒", day, day, day)); // 10時 06分 30秒
  }
}
```

## printf()
`System.out.printf()`を使うとformat形式で出力ができる。
```java:sample.java
public class Sample {
  public static void main(String[] args) {
    String place = "水族館";
    String str = String.format("明日は、%sに行きます。", place);
    
    System.out.println(str); // 明日は、水族館に行きます。

    System.out.printf("明日は、%sに行きます。\n", place); // 明日は、水族館に行きます。
  }
}
```
ゼロから始めるAIシステム開発 #03 「生成AI体験ワークショップ」

今回は入門書のハンズオンをやる予定でしたが変更しAWSの **「生成AI体験ワークショップ」** のレポートを書きたいと思います。
https://catalog.workshops.aws/generative-ai-use-cases-jp/ja-JP
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3885923/6c5b6f8f-89b0-0f74-6450-714fec2da915.png)
AWS上に生成AIを活用したアプリケーションを構築して、それを使ってチャットボットなどの機能を体験してみるというもの。
**＞所要時間の目安は60-90分です。**
ほんとか～～～？？
…結論から言うと90分どころか2日くらいかった。非エンジニアの素人にはちょっと難易度高めかも。
 ## 概要～事前準備
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3885923/926a9b80-6889-cf6d-26c5-ca160b971832.png)
使用するアプリケーションの機能や構成についての紹介の章。図はチャットや画像生成など、各種機能を使うのにどのサービスを使っているかの紹介。図解入りなのはありがたいのだが、エンジニア用語や略語が頻出するので検索あるいは別リンクを踏むなどして確認するのに時間を要した。用語の意味は理解してもエンジニアの概念的なコンテキストを有していないので、どういう目的をもってどういう結果を欲しているのかが推測に頼るところが多く、この理解のまま進んでよいのか迷う場面が多かった。書いてある手順を踏むだけならなるほど数分で済むだろうが、内容を理解してないと意味がないのでここに一番時間をかけたような気もする。
事前準備ではAmazon Bedrockのモデルを使えるようにアクセス権を得る。ここは簡単。
## アプリケーションの構築
AWS CloudFormationかAWS CDKを使用して構築する。正直どこがどう違うのか分からないがCDKのほうが難度が高くやれることが多いらしいので（無謀にも）CDKで進めることに。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3885923/2a641c13-4618-43f5-23b0-d1826a32e777.png)
スタックを生成してAmazon SageMakerでコードを編集していくのだが、このエディタが非常に使いづらい。僕の経験不足もあるのだろうがレイアウトが直観的によくわからないし、20分ほど離席しただけでログアウト的な処理がされて大変面倒である。おちおち飯も食べられない。
ターミナル上のコマンドを見る限りgithubからアプリをダウンロードしてインストールしているっぽい。RAG機能を使うために指定のファイルを開いてコードを編集し、ターミナルに戻ってデプロイする。書いてある通りにやればいいだけだが初心者にはしんどそう。一応プログラム経験者なので助かった。
## RAG用データの追加
RAGチャット機能を使うためのデータをAWSのストレージサービスであるS3に格納する。例えば自社の規約とかをチャット機能に聞くときのために自社の規約を教えておく、みたいなことをやる。これも指示通りやればいいだけなので簡単。やっていることが理解できていると早い。
## アプリケーションの確認
スタックに表示されているURLに行きアプリを確認する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3885923/4f1b388e-8fb9-31c7-fb73-e696364d9836.png)
アプリの外観はこんな感じ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3885923/f8c3975f-b0a9-f039-7e44-57b97dae8ea3.png)
機能は以下の通り。
- チャット
- RAGチャット
- 文章生成
- 要約
- 校正
- 翻訳
- Webコンテンツ抽出
- 画像生成

これらを一つずつ体験していく。ひとくくりにテキスト生成AIと言ってもできることは多岐にわたることがわかる。具体例が列挙されたことで今後の使用に引き出しが増えた。
## [実践]プロンプトエンジニアリング入門
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3885923/d66d659c-1ffa-9b2e-1644-a3456c23b2a9.png)
LLMに質問する時にコンテキストを添えて回答の精度を上げるというもの。コンテキストの例としては
- AIに役割やシチュエーションを与えるとそれに応じた精度になる
- XMLタグに例を書いておくとその例の中から回答してくれる
- 校正のガイドラインを書いておくとそれに応じて校正する

などなど。実例が列挙されているのが大変ありがたく、学びの多い章だった。
## [発展]IPアドレスの制限～サインアップの無効化
アプリのセキュリティを強固にする実践。サインアップの無効化はできたがIPアドレス制限はうまくいかず、このあたりは僕の目的からズレるので飛ばし。何をやっているのかさえ分かればよく、実装についてはその時が来たときに学ぶことにする。
## [発展]AIエージェントの活用
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3885923/53db05a9-b7de-3788-6ccb-92bd09f617ac.png)
「やるべきことを考える」のが人間で「やる」のがAIだが、AIエージェントは「やるべきことを考える」までもやってくれる…らしい。これはぜひ実践しておきたくてAPIキーを取得もしてきたのだが、デプロイのエラーがどうしても解消できず、今の僕のレベルでは無理と判断して終了。とりあえず概念は理解したと思う。
## 感想
内容としては大変ためになったが、「AmazonのUXは最悪」が定評らしくそれを実感した。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3885923/e52cee26-0518-16c7-f590-f4633124efdf.png)
この画面が何十回出たか分からない。別にF5で進むのだがストレスフル。
終わってまとめてみると、なんで二日もかかったんだろうという感想にもなった。つまり今現在は、開始時に分かっていなかった概念が理解できている、ということだろう。いい経験になったと思いたい。
次回こそ入門書ハンズオンの予定。