OmniAICreator/Qiita-1.07M huggingface dataset:
GitHub アクセストークンの作成【忘備録】　

##  この記事を作成するきっかけ

90日ごとに更新するので、忘れないためにこの記事を作成します。
期限切れ数日前に、登録のメールアドレスに通知が来ます。　

## アクセストークンの作成を始めます
1  . GitHub上Home 画面右上にある、丸いアイコンマークをクリック
　『Settings』 ボタンをクリックします。
 
 ![github スクショ1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3660800/8b4d5226-a1c5-c201-1103-c9f78983aa48.png)

2  . 次の画面で左下にある、『Developer settings』ボタンをクリックします。

![github　スクショ2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3660800/e899df0e-6ec9-4769-ca4a-515b1805f4c0.png)

3  . 次の画面で左側の『Personal access tokens』　を選択し、
『Tokens(classic)』をクリックします。

![github スクショ3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3660800/68bb2e7e-e13b-5064-515f-c9ae5eedf74d.png)


4  . 次に右側にある、『Generate new token』ボタンをクリックします。

![github スクショ4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3660800/b4d3147c-e3e9-edb1-89cb-e2c4480fd7e6.png)

5  . 『Generate new token　（classic）』を選択します。

![github スクショ5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3660800/d82e1c99-d571-d887-4ac6-f4043f4e0716.png)

6  . 『Taken name』欄に、自分で決める名前を入力し
『Expiration』欄で有効期限を選択します。今回は90日。
![githubスクショ6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3660800/f61bf3da-1a6b-4d53-a99e-2cd4285d4fd2.png)



7  .同画面下にある、権限選択を行います。repoと書いている部分を選択していきます。
選択が出来たら、緑の『Generate token』ボタンを押します。

![githubスクショラスト.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3660800/d94bc1bd-081f-565b-6c71-ae23c718507b.png)

8  . 画面が切り替わり、トークンが出てくるので控えておきます。
（ここで絶対に控えるのを忘れないこと）

##  最後に
これでアクセストークンの作成は終了です。
【合格体験記】これさえやれば受かる！ AWS Certified Cloud Practitioner に１ヶ月で合格した話

## はじめに

- 本稿は筆者が一ヶ月でAWS Certified Cloud Practitionerに合格できた際の受験までの流れと勉強法についてご紹介します。どなたかの参考になれば幸いです。
- ちなみに筆者は「CLF-C02版」を受験しました。

## 筆者のスペック
- IT系勤務（主にフロントエンド）
- AWS実務経験なし

## AWS Certified Cloud Practitionerってそもそも何？
- 本稿をご覧の方はクラウドプラクティショナーについてはご存知の方が多いかと思いますが詳しくは下記公式ページをご参照ください。（本稿での説明は割愛致します）
  - https://aws.amazon.com/jp/certification/certified-cloud-practitioner/

## やったこと
- 大きくは下記の３つです。
### ① まず試験日を決めて、申し込む！
- 本試験に限った話ではないですが、これがとても大事。なぜならゴール（試験日）を決めると人はそこを目標にモチベーションと計画性を持って挑めるからです。
  - AWSの試験予約は自身の好きな日時から選択できる上、後から予約日時の変更も可能なのでとりあえず行けそうな日で受験申し込みをしてしまうのがおすすめです。 
- 個人的には後述のUdemyの内容量などを参考に一ヶ月としました。

### ② Udemyをひたすらやる！
- 正直言います。下記のUdemyの模擬問題集をやれば十分合格は可能です。
  - https://www.udemy.com/course/aws-4260/
- 上記のコースは程よい問題数かつ種類が豊富で隙間時間でもサクサク進められます。
  - 筆者の体感では繰り返し実施することを踏まえても一ヶ月で消化するのにちょうど良い量です。
- お値段はそれなりにしますが、これさえやれば受かると思えばそこまで高くは感じないかなと思います。
  - なお私の場合は会社で申し込んでいたUdemyBusinessを使いこちらを受講しました。

:::note info
[Point]
・目安としてはこのコースの各模擬試験（計６回分）を90%以上取れるようになるまで繰り返し実施しましょう。
・また、模擬問題を進めるにあたって不正解の選択肢についてなぜ不正解なのかを頭の中で答えられるようにすることが大事です。
:::

:::note warn
こちら以外のコースや教材でももちろん良いですが、最新の受験版である「CLF-C02版」を選びましょう。（2023/2時点）
:::

### ③ 「AWS CAF」と「AWS Well-Architected Framework」は公式HPを暗記する！
- これから学習を始める方はこれらの単語は初見と思いますが、これらについて試験で多く問われるため、前述のUdemyに加えて、公式HPも併せて学習することをお勧めします。
#### AWS CAF
- 「AWS CAF」とは「AWS クラウド導入フレームワーク」といい、名前の通りクラウド導入を支援するためのフレームワークです。
  - https://docs.aws.amazon.com/ja_jp/whitepapers/latest/overview-aws-cloud-adoption-framework/welcome.html
- CAFはさらに６つのパースペクティブで構成されており、試験ではそれぞれのパースペクティブの機能について問われます。
- 全てを覚えるとかなりの量なのですが、試験対策としてはそれぞれの機能をキーワードとして覚えれば十分戦えます。
- イメージとしては上記公式サイトの「基本的な機能」に記されている６色の表を覚えるイメージです。（表は英語ですが、画像検索で日本語版もありました。）
- 「XX機能はYYパースペクティブの機能だ！」と早押しクイズの要領で答えられるレベルになればOKです。
  - もちろん機能の詳細等を問われることもありますが、基本的には上記のレベルで良いです。

#### AWS Well-Architected Framework
- AWS Well-Architected Frameworkとは、クラウドのベストプラクティスについて定めたフレームワークです。
  - https://docs.aws.amazon.com/ja_jp/wellarchitected/latest/framework/welcome.html
- こちらもAWS CAFと似ており、６つの柱から構成されるフレームワークとなっています。試験ではそれぞれの柱ごとに定められている「設計原則」について問われることが多いです。
- こちらも「XXはYYの柱の設計原則の一つだ！」と言えるようになるところがゴールです。ただし、一つ注意点として、問題によっては一言一句公式のままでは出題されないケースがあるため、ワードを丸暗記と言うよりは各設計原則の「意味合い」を理解するようにしましょう。（このあたりは前述のUdemyの模擬問題で慣れておくと良いです。）
 
## やっておいた方がいいこと
### 実際にAWS環境を構築し、サービスに触れる。
- 実際に触って動かしてみることはサービスの理解と記憶の定着に効果的ですので、お時間に余裕がある方はぜひ環境を作ってみることをお勧めします。
-  筆者はあくまで試験の合格を目標にテキストベースで学習を進めましたが、直近の実務でAWSを扱う方や普段の学習をハンズオンを中心に進める方はサービスを動かしながら学習を進めていただくと良いと思います。

## 実際どれくらいやればいいの？
- 時間で言うと、筆者の場合は平日は隙間時間をメインに平均0.5h、土日はある程度まとまった時間が確保できたので4,5hほどだったかと思います。
- 上記より勉強時間が取れない方は一ヶ月より余裕を持って計画をした方が良いかもしれません。

## 最後に
- この記事通りに学習することで合格を保証することはできませんが、本稿を参考により多くの方がAWS Certified Cloud Practitionerに合格することを願います。
trコマンド

## trコマンドとは？
trコマンドとは、文字の変換や削除をするためのコマンドです。

```terminal:usage.tr
tr [option] [元の文字列] [変換後の文字列]
```
| option | 説明 |
|:-:|:-:|
| -d  |元の文字列で指定した文字列を削除する(この場合[変換後の文字列]は必要ない)   |
| -s  |連続している同じ文字の文字列を一文字にまとめる   |

```terminal:example.tr
$tr -d abc
abcdefg <-入力を求められる
defg
$ls 
dir1 dir2
$cat dir1
iiiiiiiiiiiiiiii ABC xyz.
$cat dir1 | tr 'a-z' 'A-Z' | tr -s i //aからzの小文字を大文字に変換する。　i を一つにする。
I ABC XYZ
$cat dir1 | tr ABC xyz | tr -d i //ABCをxyzに変換。　iを削除する。
xyz xyz
```
GO＋GinのAPI開発環境構築メモ

# 背景
毎回、GoとGinによるAPIの環境構築の手順を忘れるので、ここに備忘録として残します。

# 環境
OS: macOS 13.6.4（22G513）
チップ：Apple M2 Pro
GOバージョン：go1.21.3

# 手順
## 1. GOのインストール
こちらのサイト（https://go.dev/doc/install) を参考にインストールしてください。

## 2. プロジェクト用のディレクトリを作成
以下のコマンドを使って任意の場所にプロジェクト用のディレクトリを作成して移動します。
```.zsh
mkdir back
cd back
```
## 3. goをinitする
以下のコマンドを使って、GOのmodファイルを作成します。
`{モジュール名}`は適当で良いです。
```.zsh
go mod init {モジュール名}
```
すると、以下のように表示されます。
```.zsh
go: creating new go.mod: module {モジュール名}
```

## 4. ginをインストールする
以下のコマンドを使って、ginに必要なものをインストールします。
```.zsh
go get -u github.com/gin-gonic/gin
```

## 5. main.goファイルを作成する。
GOの基本ファイルとなる、`main.go`ファイルを作成します。
```.zsh
touch main.go 
```

## 6. 最初のAPIを記述する。
以下の内容をmain.goファイルに記述します。
```main.go
package main

import "github.com/gin-gonic/gin"

func main() {
	r := gin.Default()
	r.GET("/ping", func(c *gin.Context) {
		c.JSON(200, gin.H{
			"message": "pong",
		})
	})
	r.Run() // 0.0.0.0:8080 でサーバーを立てます。
}


```

## 7. サーバを立ち上げる。
以下のコマンドを使って、サーバを立ち上げます。
```.zsh
go run main.go
```

## 8. ブラウザからサーバにアクセスする。
ブラウザから`localhost:8080/ping`にアクセスします。
ブラウザで以下のようにJSONが帰ってくれば、環境構築は完了です。

<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2724591/b36e1116-4b0c-c82f-7366-c13ebb43e952.png">

## 完了
お疲れ様でした。これで環境構築完了です。
2/17 tecHub（LT＋懇親会）を開催しました！

![tecHub0217_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3670233/28a7077f-90ce-d994-65e5-69414ce0a285.png)

2/17にtecHubを神田で開催しました。
参加者は約80名となり大盛況でした！
日付：2/17(土)　14:00～17:00
場所：ワイム貸会議室 神田 Room7A
参加者：78名
内容：一部：LT、二部：懇親会

<h3>LT（ライトニングトーク）</h3>
tecHub（LT＋懇親会）では、前半は「働き方」をテーマに、外部スピーカーも招きつつLT、プレゼンテーションを実施しています。
<br>後半は懇親会で自由に会話を楽しんでいただいています。懇親会にはプレゼンターも参加し、発表内容をさらに掘り下げてディスカッションをすることも可能です！</br>
<br>いろんな立場の方が自由に意見・情報交換をできる場となっています。</br>
<br>LTありのtecHubも、毎回80名近くの規模で開催しており人気のイベントとなっております。</br>

![tecHub0217.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3670233/b260d0a3-55a2-d218-713e-58ee79c6c8ff.png)

<h3>参加者の声</h3>
今回も、参加者は幅広い分野のIT関係者が集まり会社員からフリーランスエンジニア、法人化されている人まで様々な人が参加していました。
<br>幅広い分野と様々なキャリアの人がいることで、キャリアアップを考えている人が転職やフリーランス転向など今後の働き方をイメージできたようでした。</br>
<br>「参加してよかった」、「勉強になった」などの声もいただいています。</br>
<br>終始、会話が弾み盛り上がっていました。</br>
<br>さらにIT業界に興味ある他業界の方も参加しており、IT業界の話が聞けて良かったとの声もありました。</br>

<h3>今後について</h3>
tecHubは、今後も毎月イベントを開催していきます。
<br>他にもITエンジニアがより活躍し、理想のキャリアを切り拓けるように新たな取り組みをしていく予定です。</br>
<br>今後もtecHubをよろしくお願いいたします。</br>

<h3>次回の開催</h3>
次回の開催は以下の日程を予定しております。

日時：3/9(土)　14:00～16:30
場所：LIFORK秋葉原Ⅱ1階ラウンジ
内容：IT交流会
詳細とお申込みは以下をご確認ください。

www.navi56.com

※イベントの申込みにはコミュニティに参加が必要になります。tecHubコミュニティに参加後にサイト内のイベントからお申込みください。
Windows 11 の メモ帳 が 右寄せされる！なんで？

Windows 11 の メモ帳 (notepad) が、書いていると
突然 右寄せ になる
という怪現象に遭い困っている。

いまさっき家で何気なく使っていたら、発生し、そして*戻った!!*
なんでや！

いじってみたら、
Ctrl + 右シフト で右寄せ
Ctrl + 左シフト で元の左寄せ
になる、ようである。

これでメモ帳しかない環境でもなんとか作業ができそうだ。
[Swift] 数値の大きさ（絶対値）を得る

## abs()じゃないの？
もちろん`abs()`でいいです。
しかし、Swiftのすべての数値型にはプロパティとして大きさ(magnitude)を備えています。
**ドキュメントにもmagnitudeは絶対値であると明記されています。**

## 使う

```swift
let i: Int = -1
let f: Float = -5.3
let d: Double = -3.0918

print(i.magnitude)  // prints 1
print(f.magnitude)  // prints 5.3
print(d.magnitude)  // prints 3.0918
```

結果は大きさ（絶対値）です。

```swift
let i: Int = 1
let f: Float = 5.3
let d: Double = 3.0918

print(i.magnitude)  // prints 1
print(f.magnitude)  // prints 5.3
print(d.magnitude)  // prints 3.0918
```

正数でもおなじです。

そして、
```swift
let ui: UInt = 1
let ui8: UInt8 = 1
let ui16: UInt16 = 1
let ui32: UInt32 = 1
let ui64: UInt64 = 1

print(ui.magnitude)  // prints 1
print(ui8.magnitude)  // prints 1
print(ui16.magnitude)  // prints 1
print(ui32.magnitude)  // prints 1
print(ui64.magnitude)  // prints 1
```

符号無し整数も`magnitude`プロパティをもっています。

## なにもの？
この`magnitude`プロパティは`Numeric`プロトコルが持っています。
`Numeric`プロトコルは全ての数値型が適合すべきプロトコルです。
`Numeric`プロトコルには加減乗算が含まれておりまさしく数値型の基本となっています。（除算はありません。）

しかし、この`magnitude`プロパティは元の数値型と違う型である可能性があります。
たとえば実数ベクトル型を考えた場合、その大きさは実数であるためこのような措置がとられています。
このためはジェネリックな型や関数で使用する場合問題が発生することが予想されます。

なので**絶対値を取得したい場合は`abs()`を使いましょう**。

## え？
いかがでしたか？

数値型から数値の大きさを取得する方法を見てきました。

数値型は`Numeric`プロトコルに適合する型だということが分かりました。

また`Numeric`プロトコルがもつ`nagmitude`プロパティがその**大きさ**を示すものであることがわかりました。

また`nagmitude`プロパティの型が元の方と異なる場合があるためジェネリックな対象での使用には問題が発生する可能性があることも分かりました。

そのため絶対値を求めたい場合は通常`abs()`を使うことが推奨されていることも分かりました。

`nagmitude`はその大きさが必要な時のみの使用にとどめましょう。

## え？

え？
Kindle Cloud Readerでランダムにページを表示していくスクリプト

<h3>Kindle Cloud Readerでランダムにページを表示していくスクリプト</h3>
ブラウザのKindle Cloud Readerで本のページをランダムに表示していくスクリプトをPowershellで作りました。

<hr>
<h3>使い方</h3>
以下に記載したPGMのコメントでkindle Cloud Readerを最大表示したときの、各A,B,Cの座標を
githubのスクリーンショット(scnshot1.jpg, scnshot2.jpg)を参考にして,各自pc毎に設定してからスクリプトを実行します。


githubURL:https://github.com/NanjoMiyako2/kindleCloudReaderRandomPages


<hr>
<h3>参考にしたサイト</h3>
<a href="https://it-study.info/powershell/ps-mouse-cursor-position/">マウスカーソルの座標を取得する | ITStudy</a><br>
<a href="https://it-study.info/powershell-mouse-click/">PowerShellでマウス操作をやってみた | ITStudy</a><br>


<hr>
<h3>PGM内容</h3>

```powershell

#SendKeysを使うため、System.Windows.Forms名前空間読込
Add-Type -AssemblyName System.Windows.Forms

#読み出し時間(秒)
$ReadSecond = 60
#何ページ分繰り返すか
$CountLength = 30
#読み出す本の最大ページ数
$BookPages = 95





# .NET Frameworkの宣言
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")

# Windows APIの宣言
$signature=@'
[DllImport("user32.dll",CharSet=CharSet.Auto,CallingConvention=CallingConvention.StdCall)]
public static extern void mouse_event(long dwFlags, long dx, long dy, long cButtons, long dwExtraInfo);
'@
$SendMouseClick = Add-Type -memberDefinition $signature -name "Win32MouseEventNew" -namespace Win32Functions -passThru

echo "ランダム読み出し開始"
#この間にトップ画面をkindleにする
Start-Sleep -s 60
echo "Start"


for($i=0; $i -lt $CountLength; $i++){

# 変数設定
#---A---
$x = 1888
$y = 140


# マウスカーソル移動
[System.Windows.Forms.Cursor]::Position = New-Object System.Drawing.Point($x, $y)

Start-sleep -s 1

# 左クリック
$SendMouseClick::mouse_event(0x0002, 0, 0, 0, 0);

Start-sleep -s 1

$SendMouseClick::mouse_event(0x0004, 0, 0, 0, 0);


Start-Sleep -s 5

# 変数設定
#---B---
$x = 1821
$y = 276

# マウスカーソル移動
[System.Windows.Forms.Cursor]::Position = New-Object System.Drawing.Point($x, $y)

Start-sleep -s 1

# 左クリック
$SendMouseClick::mouse_event(0x0002, 0, 0, 0, 0);

Start-sleep -s 1

$SendMouseClick::mouse_event(0x0004, 0, 0, 0, 0);

Start-Sleep -s 2
$page = Get-Random -Maximum $BookPages -Minimum 1
[System.Windows.Forms.SendKeys]::SendWait($page)
Start-Sleep -s 2

# 変数設定
#---C---
$x = 1064
$y = 632

# マウスカーソル移動
[System.Windows.Forms.Cursor]::Position = New-Object System.Drawing.Point($x, $y)

Start-sleep -s 1

# 左クリック
$SendMouseClick::mouse_event(0x0002, 0, 0, 0, 0);

Start-sleep -s 1

$SendMouseClick::mouse_event(0x0004, 0, 0, 0, 0);

Start-Sleep -s $ReadSecond


}

```
Aurora Serverlessの障害調査時に役立つ情報

# 概要
実務で扱っているAurora Serverlessがダウンしてしまい、原因の調査で右往左往してしまったため、調査時に役立ったメトリクス、ログ等をまとめておきたいと思います。

serverlessのv1を前提に話しますが、v2でも基本的には同様かと思います。

:::note warn
Serverless(v1)は2024年末をもってサポート終了となるため、年内にv2へのアップデートが必要になるそうです。([参考URL](https://www.infoq.com/jp/news/2024/01/aurora-serverless-v1-retirement/))
:::

# 調査フロー
### 0. 障害発生
RDSに何らかの異常があったことを知らせるエラー通知が飛んできました。

メトリクス `EngineUptime`にて、RDSインスタンスの総稼働時間を確認できます。
正常に稼働していれば以下のように一直線に伸びていきます。
![スクリーンショット 2024-02-18 19.49.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2453728/156086ee-72b1-319e-aade-1f70f8e3faf8.png)


もし直線が一度0に落ちている(リセットされた)場合は、何か起きたのだという察しがつきます。


なお`EngineUptimeがリセットされた=障害`というわけではありません。以下の場合にも0に戻ります。
 - ACUがオートスケールした場合
オートスケールしたかどうかは、`ACUUtilization`や`ServerlessDatabaseCapacity`というメトリクスから判断できます。
 - 設定に基づき自動停止した場合
v1の場合、一定時間アクセスがない場合は自動停止してくれるオプションが存在します。自動停止した場合はWebコンソールの最近のイベント等で確認できます。

今回は上記に当てはまらず、障害起因でAuroraインスタンスがダウンしてしまったという前提で話を進めます。

### 1. まずはエラーログを確認
Aurora ServerlessのログをCloudWatchに出力することができます。

参考

https://dev.classmethod.jp/articles/uploading-to-cloudwatch-aurora-serverless/

障害発生時刻のエラーログを確認してみましょう。
例えば、以下のようなログが出力されている場合はメモリ不足に陥っていたことを示します。
```
Available memory is low. Trying to avoid OOM crash...(省略)
```

ここでは上記のエラーメッセージが出力されていたという前提で進めていきます。

### 2. エラー内容に応じてメトリクスを確認
エラー内容に応じて、Auroraのメトリクスを確認しましょう。例えばメモリの枯渇が怪しい場合は、`FreeableMemory`でメモリの空き状況の推移を確認しましょう。

![スクリーンショット 2024-02-18 19.54.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2453728/654d832f-15c9-6d87-47dc-76b1530580cf.png)


ここでは障害発生時に空きメモリが急激に減少していた(メモリの枯渇がAuroraのダウンを引き起こしてそうだ)という前提で進めます。

### 3. メモリ枯渇原因の調査
`FreeableMemory`では、メモリ枯渇の原因が何かまでは特定できません。
これを特定するのに役立つメトリクスが以下になります。
 - ReadIOPS
 - ReadThroughput
 - WriteIOPS
 - WriteThroughput

上記はそれぞれ文字通り読み込み、書き込みのIOPS、スループットを示します。
例えばメモリ枯渇と同時間帯に`ReadIOPS`も急上昇している場合は、急激な読み込み回数の上昇に着いていけずメモリが枯渇してしまったのでは、といったような推測がつきます。
IOPSの上昇はなく、`ReadThroughput`や`WriteThroughput`が急上昇している場合は、大量の読み込み、書き込みを行う非効率な処理の実装が原因かもしれません。

:::note warn
**AuroraServerlessはメモリ枯渇をトリガーにオートスケールしてくれない**
メモリ枯渇が原因と分かった際に、ACUは最大までスケールアウトしているのか、その上でメモリが足りていないのかを確認しようとしました。(そうであればオートスケール設定の見直しが必要な可能性が高いため)
しかしACUは最小の状態で、一切スケールアウトした形跡もありませんでした。
調べたところ、どうやらACUのスケールアウトのトリガーにメモリの空き状況が含まれないようです。

参考：[Aurora Serverless v1 の仕組み](https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/AuroraUserGuide/aurora-serverless-v1.how-it-works.html#aurora-serverless.how-it-works.auto-scaling)
:::


# 最後に
以上、簡単ですが原因調査の流れと参考になったメトリクス、ログのまとめでした。(原因への対策についてはこれから検討していきます。)
もし何か他にも確認すべき項目等あればご教授いただけると幸いです！

ちなみにこの辺りの記事もモニタリングや障害調査時に役立ちそうです！
https://aws.amazon.com/jp/blogs/news/making-better-decisions-about-amazon-rds-with-amazon-cloudwatch-metrics/
SQLAlchemyにおけるサブクエリの使い方(ケースごと)

SQLAlchemyにおけるサブクエリの使い方についての議事録です。
サブクエリを使用することで、複雑なクエリを1度のクエリで実行することができます。

## ケース1：レコードの最新バージョンの取得

想定するシナリオは、各レコードには複数のバージョンがあり、最新バージョンのすべてのレコードを取得したいとします。
VersionedItem テーブルを仮定します。
`item_version` はアイテムの異なるバージョンを追跡し、`item_id` は各アイテムを一意に識別します。
#### VersionedItem テーブルのデータ:
| item_id | item_version |
|:-:|:-:|
| 1  | 1  |
| 2  | 1  |
| 3  | 2  |
| 4  | 2  |
| 5  | 3  |
| 6  | 3  |

### ステップ1: 最新バージョンを見つけるためのサブクエリの作成

まず、VersionedItem テーブルから最も高いバージョン番号（つまり、最新バージョン）を返すサブクエリを作成する必要があります。SQLAlchemyでは以下のように記載します。
```python
from sqlalchemy import func

# 最新バージョンを見つけるためのサブクエリを定義する
latest_version_subquery = db.session.query(
    func.max(VersionedItem.item_version).label('latest_version')
).subquery()
```
このサブクエリは、SQLAlchemyの `func.max()` を使用して item_version カラムの最大値を見つけ、最新バージョンを取得します。
`label()` メソッドは、集約関数の結果に名前をつけ、外部クエリで参照しやすくします。

### ステップ2: メインクエリの作成
次に、このサブクエリを使用して、VersionedItem テーブルからこの最新バージョンのすべてのレコードを取得することができます。

```python
# 最新バージョンに一致するすべてのアイテムを取得する
latest_version_items = db.session.query(VersionedItem).filter(
    VersionedItem.item_version == latest_version_subquery.c.latest_version
).order_by(
    VersionedItem.item_id
).all()
```
このクエリでは、`latest_version_subquery.c.latest_version` はサブクエリから計算された最新バージョンを参照します。
VersionedItem レコードを、その item_version がこの最新バージョンと一致するものに絞り込んでいます。
最後に、結果を item_id で並べ替えています。

:::note info
latest_version_subquery.c.latest_versionにおける.cは、SQLAlchemyにおけるColumn（カラム）の略です。SQLAlchemyの文脈において、.cはサブクエリやテーブルのカラム属性にアクセスするために使用されます。
:::

## ケース2: 特定の条件にマッチするアイテムの選択

想定するシナリオは、ある商品テーブルから、特定の条件に一致する商品のIDリストに基づいて、商品詳細を取得するものです。
Product テーブルと Order テーブルがあり、特定の注文状態にある商品のみを抽出したいとします。

#### Product テーブルのデータ:
| id | name | price | category | stock |
|:-:|:-:|:-:|:-:|:-:|
|1	|スマートフォン|	70000|	電子機器|	50|
|2	|タブレット|	40000|	電子機器|	30|
|3  |ノートパソコン|	120000|	コンピュータ|	20|
|4	|イヤホン|	15000|	アクセサリ|	60|
|5	|コーヒーメーカー|	25000|	家電|	15|

#### Order テーブルのデータ:
| id | product_id | quantity | status | order_date |
|:-:|:-:|:-:|:-:|:-:|
|1	|1	|1	|shipped	|2024-01-15|
|2	|2	|2	|pending	|2024-01-16|
|3	|1	|1	|cancelled	|2024-01-17|
|4	|3	|1	|shipped	|2024-01-18|
|5	|4	|3	|pending	|2024-01-19|
|6	|5	|1	|shipped	|2024-01-20|
|7	|2	|1	|shipped	|2024-01-21|
|8	|4	|2	|shipped	|2024-01-22|

### ステップ1: 注文状態で絞り込むサブクエリの定義
まず、注文状態が「出荷済み」の商品IDを抽出するサブクエリを定義します。
```python
# 出荷済みの商品IDを抽出するサブクエリを定義
shipped_order_subquery = db.session.query(Order.product_id).filter(
    Order.status == 'shipped'
).subquery()
```
このサブクエリはOrderテーブルからstatusが「shipped」（出荷済み）のproduct_idを選択します。

### ステップ2: IN句を使用したメインクエリの作成
次に、上記のサブクエリを使用して、Productテーブルから該当する商品を選択します。

```python
# `IN`句を使用して、出荷済みの商品の詳細を取得する
shipped_products = db.session.query(Product).filter(
    Product.id.in_(shipped_order_subquery)
).all()
```
ここで、.in_()メソッドはSQLのIN句に相当し、サブクエリの結果（出荷済みの商品ID）に含まれるIDを持つProductテーブルのレコードを選択します。

:::note info
.c 属性は主にサブクエリのカラムにアクセスする際に使用されますが、テーブルの直接のカラムにアクセスする場合は、.c 属性は必要ありません
:::
appendメソッドで文字列の連結ができないとき

# 初めに

RExの問題を解いていて、appendメソッドを使用して文字列を結合しようとする問題に出会ったので書いていきます。

# 問題

```ruby

a = "今日も"
b = "最高の1日に。"

p a.append b # NoMethodError

```

# 解決方法

今回は```String<<```で解決しました。

```ruby
a = "今日も"
b = "最高の1日に。"

p a << b # 今日も最高の1日に。
```

appendメソッドは、Arrayクラスのメソッドで配列に要素を追加するときに使用されるようです。

# 終わりに

今日はRExの1度解いた問題を繰り返し解いてみたら、点数が上がっていたので良かったです。
関数について

関数とは
---
関数は入力として引数、出力として戻り値を持つ特定の処理を一つのまとまりにしたもの。

定義方法
---
関数はfuncで宣言し、次のように定義します。*↓*
```
func 関数名(引数名1: 型, 引数名2: 型...) -> 戻り値の値{
   関数呼び出し時に実行される文
   必要に応じてreturn文で戻り値を返却する
}
```
引数は()の中に 引数名: 型　で区切り定義。戻り値は()のあとの -> に続けて定義します。
戻り値を返す際にはreturn文を使用します。
例
```
func double(number: Int) -> Int {
    let result = number * 3
    return result
}

let originNumber = 10
let doubleNumber = double(number: originNumber)
print(doubleNumber) //30
```

実行方法
---
関数は関数名に()をつけて、()の中に入力となる引数と引数名を、区切りで記述して実行します。
```
関数名(関数名1: 引数1, 関数名2: 引数2...)
```
戻り値は変数や定数に代入することができます。
```
let 定数名　＝　関数名(関数名1: 引数1, 関数名2: 引数2...)
```
戻り値が定義されてる関数を呼び出す場合は、戻り値を変数や定数に代入します。
Xcodeでは戻り値の代入を省略するとエラーが出るので、戻り値が不要なさいは _ の代入によって戻り値を無視することができる。

引数
---
引数-関数への入力を表され引数は名前と型で構成されます。
### 仮引数と実引数
関数の引数は、<INS>(1)関数の定義時に宣言するものを指す場合</INS>と、<INS>(2)関数の呼び出し時に指定するものを指す場合</INS>の2通りある。前者(1)が引数、後者(2)が実引数と言う。

```
func printInt(_ int: Int) {
   print(int)
   }

printInt(1)   
```
⬆️上記のコードでは、関数の定義時に宣言しているintが仮引数になり、関数の呼び出し時に指定している1が実引数です。

戻り値
---
戻り値-関数の出力を表す値です。関数宣言時に定義し呼び出し側は定義された戻り値の値を出力として受け取ることができます。

### 戻り値がない関数
戻り値の型の指定は必須ではないため、戻り値が不要な場合は関数宣言時に戻り値の型の定義を省略することができます。
```
func greet(user: String) {
   print("Hello,\(user)!")
}

greet(user: "Arakawa")
```
```:実行結果
Hello,Arakawa!
```
⬆️上記のgreet(user:)関数は、print(_:)関数を用いて文字を出力しているだけで呼び出し元には何も返していません。

### コンパイラによる戻り値チェック
関数宣言で定義されている戻り値の型と実際の戻り値の方が一致するかは、
コンパイラによってチェックされる。
定義された戻り値の型と一致しない型を返すプログラムはエラーになります。
例
```
func test() -> Int {
    let string = "Hello!"
    return string   // コンパイルエラー
}

test()
```
エラー
↪︎ Cannot convert return expression of type 'String' to return type 'Int'
内容-「String」型の戻り式を「Int」型に変換できません

### 暗黙的なreturn
関数の実装が戻り値の返却のみで実装されている場合は、returnキーワードを省略することができます。この仕様のことを<font color="#ff0066">**暗黙的なreturn**</font>と言い、戻り値の返却のみで実装されている関数はこのような関数になります。
```
func test() -> Int {
    100 + 100
}

print(test())

実行結果
２00
```
⬆️上記のコードでは、100 + 100の結果が返却できる型の値と別の処理が書かれていないので暗黙的なreturnが行われる

:::note info
インフォメーション
100 + 100 以外の処理を書くときはreturnキーワードが必要になります
:::

今回は学習の復習と見直しを兼ねて記事にしました！
間違っているところあれば連絡ください！
業務を効率化するPython入門【１１．実行ファイル化（.exe）する】

```console
pip install pyinstaller
```

```python
pyinstaller filename.py

pyinstaller filename.py --onefile # 1つの.exeファイルにまとめる
pyinstaller filename.py --noconsole # .exe実行時にコンソールを表示しない
pyinstaller filename.py --onefile --noconsole # 上記両方

```



## Next：業務を効率化するPython入門【１２．定期実行】
https://qiita.com/altcoms-creative/private/dfba35f8ff22f2db1dc9
MUIのDate Pickerに関する日本語の問題対処


### メモ

githubに欲しかった回答があったけども
日本語で探してなかったので、これから困る誰かのためにメモをしておきます

### 本題

PickersCalendarHeaderは基本的に `MM YYYY` の順に設定されている。

日本人からすると `YYYY MM` に並べたい問題が生じる。


そこでの対応がこちら

https://github.com/mui/mui-x/issues/4463

### 全体感

上記の箇所以外にも並び替えがしたかったので以下の設定に行き着いた

```
const CustomDatePickerToolbar = (props: any) => {
  const { date, changeYear, changeMonth, isLandscape, onChange, ...other } = props
  return (
    <DatePickerToolbar
      toolbarFormat="YYYY年MM月" // スマホ用の画面で出るツールバーの順番を整備
      isLandscape={isLandscape}
      onChange={onChange}
      value={date}
      view={date}
      {...other}
    />
  )
}


<LocalizationProvider dateAdapter={AdapterDayjs} dateFormats={{ monthAndYear: "YYYY年 MM月" }}> //　inputの箇所の並び替え
... react-hook-formのラッピング
            <DemoItem label={label}>
              <DatePicker
                {...field}
                {...rest}
                disabled={disabled}
                defaultValue={dayjs('2000-01')}
                disableFuture={true}
                views={['year', 'month']}
                openTo="year" // 年から選べるようにする
                format="YYYY年MM月" // input後のform内の表示を変える
                onChange={(newValue: dayjs.Dayjs | null) =>
                  onChange(newValue ?? dayjs(newValue).format('YYYY-MM'))
                }
                slots={{
                  toolbar: CustomDatePickerToolbar,
                }}
              />
            </DemoItem>
...
</LocalizationProvider>
```
遅ればせながらLangchainを試してみようとしたところOpenAIのAPIトークンが使えなかったので、Google Geminiにお世話になりました


## 内容

PythonでLangchainからGoogle Geminiに問い合わせを行う  

## 背景

- Langchain、試すぞい。
- OpenAIのAPIトークンを発行したが、429エラーだ。
- この記事と同じ状況だ...API使えない。[ChatGPT-API Error Code 429の解決方法 #ChatGPT - Qiita](https://qiita.com/Keichan_15/items/b1aac09f77c6f8580113)
- では、Google GeminiのAPIを試すか。

## 環境

- Ubuntu 22.04.3 LTS (WSL on Windows 11 home)
- Python 3.10.12
- VScode

## 準備

仮想環境はvenv派です。  
```
python3 -m venv .venv
```

Pythonの環境をVScode側で指定

`ctrl + shift + p` `Python: Create Environment` で.venv配下の環境を指定。  



Python のライブラリをインストール

```
pip install --upgrade --quiet  langchain-google-genai pillow
```

```
pip install python-dotenv
```

## directory  

```
.
├── .venv/
├── .env
├── hello_langchain.py
└── requirements.txt
```

## メインの処理　hello_langchain.py


```python
from dotenv import load_dotenv
from langchain_google_genai import ChatGoogleGenerativeAI

load_dotenv()  # load environmental variable "GOOGLE_API_KEY" from .env


prompt = "what is your name? And what can you do?"

llm = ChatGoogleGenerativeAI(model="gemini-pro")
result = llm.invoke(prompt)
print(result.content)
```

### LangchainからGeminiへの問い合わせ

主な内容は以下のLangchainによるチュートリアルそのままです。
[Google AI chat models | 🦜️🔗 Langchain](https://python.langchain.com/docs/integrations/chat/google_generative_ai)  
APIトークンの生成もチュートリアル内に載っています。



### doteenv

`.env`というファイルを同一ディレクトリ内に置いて環境変数を読み込む際に便利です。  
みんな、トークンをコードにベタ書きしちゃだめだぞ~  
[python-dotenv · PyPI](https://python.langchain.com/docs/integrations/chat/google_generative_ai)

`.env`の中身はこんな感じです
```python
GOOGLE_API_KEY="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" # 実際には生成したトークンを記述
```

Gitを使う場合、`.env`をしっかり.gitignoreに入れておくことを忘れずに。

## 実行結果

成功！
普通にWebブラウザから問い合わせるのと同じような回答が得られました。  

```
I am a multi-modal AI language model developed by Google. I don't have a name, as I am not a person.

I am designed to understand and generate human language, answer questions, and provide information on a wide range of topics. I can also perform many other tasks, such as:

* **Translate languages**
* **Write different kinds of creative content**
* **Summarize long pieces of text**
* **Answer your questions in a comprehensive way**
* **Help you with your research**
* **Provide you with definitions and other information**
* **Play games with you**
```


## 感想

- Langchain、簡単で便利!
- 次はRAGの構築もしてみたい。
Geminiにcolaboratoryで質問とか会話してみた流れ

# 参考1
https://ai.google.dev/tutorials/python_quickstart

# 前準備
まず↓からAPI keyを取得した（2024/2/18時点では無料とのこと）
（参考1の「Get an API key」のリンク先と行き着く先は最終的に同じ）

https://ai.google.dev/pricing?hl=ja

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545173/2714af26-b6e0-53c5-4f09-c3652249622d.png)

colabの鍵マークを選択し下のように入力する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545173/dbb0ec2d-fb3b-87e6-8a5d-c6b0a683e786.png)
* 「名前」に「GOOGLE_API_KEY」
* 「値」に「取得したAPI key」

# Geminiに質問するまでの諸々
参考1の内容をコピペする（エラー出たのでpip → !pipに変更）
```python
!pip install -q -U google-generativeai

import pathlib
import textwrap

import google.generativeai as genai

from IPython.display import display
from IPython.display import Markdown


def to_markdown(text):
  text = text.replace('•', '  *')
  return Markdown(textwrap.indent(text, '> ', predicate=lambda _: True))

from google.colab import userdata

model = genai.GenerativeModel('gemini-pro')

GOOGLE_API_KEY=userdata.get('GOOGLE_API_KEY')
genai.configure(api_key=GOOGLE_API_KEY)
```

# 質問する
```python
response = model.generate_content("日本とアメリカの面積と人口を比較して？")
to_markdown(response.text)
#---回答↓--
#面積
#日本: 約377,975 平方キロメートル
#アメリカ: 約9,833,517 平方キロメートル
#アメリカは日本の約26倍の面積を持っています。

#人口
#日本: 約1億2,542万人（2023年1月）
#アメリカ: 約3億3,152万人（2023年1月）
#アメリカは日本の約2.6倍の人口を持っています。

#人口密度
#人口密度も大きく異なります。
#日本: 約330人/平方キロメートル
#アメリカ: 約34人/平方キロメートル
#日本はアメリカよりもはるかに人口密度が高く、都市部では特に密集しています。
```
大体あってる

# Chat（会話してみる）
```python
chat = model.start_chat(history=[])
response = chat.send_message("私が好きな食べ物は唐揚げです。あなたは？")
to_markdown(response.text)
#私はAIアシスタントなので、食べ物を食べることはできません。

response = chat.send_message("仮に食事ができる体だったとしたら何が好きになりそうですか？")
to_markdown(response.text)
#もし私が食事をすることができたとしたら、さまざまな料理や風味を体験できることを楽しみにしています。皆様のお勧めの料理を教えて頂けましたら幸いです。

response = chat.send_message("私が好きな食べ物を覚えていますか？")
to_markdown(response.text)
#はい、あなたの好きな食べ物は唐揚げです。
```
唐揚げが好きなことを覚えている。

#### 会話の履歴を表示する
```Python
for message in chat.history:
  display(to_markdown(f'**{message.role}**: {message.parts[0].text}'))

#user: 私が好きな食べ物は唐揚げです。あなたは？
#model: 私はAIアシスタントなので、食べ物を食べることはできません。
#user: 仮に食事ができる体だったとしたら何が好きになりそうですか？
#model: もし私が食事をすることができたとしたら、さまざまな料理や風味を体験できることを楽しみにしています。皆様のお勧めの料理を教えて頂けましたら幸いです。
#user: 私が好きな食べ物を覚えていますか？
#model: はい、あなたの好きな食べ物は唐揚げです。  
```

# 今後
* RAGとかファインチューニングとかする
React Hook Form で動的フォームを作る

# 1. やりたいこと
React Hook Formを使ったフォームにおいて、動的に増加するインプット要素に対応したものを作りたい
useFieldArrayを使って、「add」ボタンを押下するとCareersにインプット要素が増えていくフォームを実現する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326452/5e8c6331-6e30-fa97-ccc0-181d7f3fe3d2.png)

# 2. コード
```tsx:Form.tsx
import { Input, VStack, Select } from '@chakra-ui/react'
import { FormProvider, useForm } from "react-hook-form";
import { Careers } from './careers';

enum GenderEnum {
    female = "female",
    male = "male",
    other = "other",
}

interface IFormInput {
    firstName: string
    lastName: string
    backGround: {
        careers: { value: string }[]
    }
    gender: GenderEnum
}
export function PersonalForm() {
    const methods = useForm<IFormInput>({
        defaultValues: {
            firstName: "",
            lastName: "",
            backGround: {
                careers: [
                    { value: "" }
                ],
            },
            gender: GenderEnum.female
        }
    })

    return (<>
        <FormProvider {...methods}>
            <form >
                <VStack align='stretch'>
                    <div>
                        <label>Name</label>
                        <VStack align='stretch'>
                            <Input {...methods.register("firstName")} placeholder="first name" />
                            <Input {...methods.register("lastName")} placeholder="last name" />
                        </VStack>
                    </div>
                    <div>
                        <Careers />
                    </div>

                    <div>
                        <label>Gender Selection</label>
                        <Select {...methods.register("gender")}>
                            <option value="female">female</option>
                            <option value="male">male</option>
                            <option value="other">other</option>
                        </Select>
                    </div>
                </VStack>

            </form>
        </FormProvider>
    </>
    );
}

```

```tsx:Career.tsx
import { Input, Button, VStack } from '@chakra-ui/react'
import { useFieldArray, useFormContext } from "react-hook-form";

export function Careers() {
    const { register, control } = useFormContext()

    const { fields, append } = useFieldArray({
        name: "backGround.careers",
        control: control,
    });

    return (<>
        <label>Careers</label>
        <VStack align='stretch'>
            {fields.map((field, index) => (
                <Input
                    key={field.id}
                    {...register(`backGround.careers.${index}.value`)}
                />
            ))}
        </VStack>
        <Button size={"xs"} onClick={() => { append({ value: "" }) }} style={{ float: "right", marginTop: "5px" }}>add</Button>
    </>
    );
}
```
RAGの精度向上手法：Rerankについて

昨日、llamaindexが公開したRerankに関する記事を読みました。
Rerankは非常に興味深いトピックなので、共有したいと思います。

## 1.Rerankとは
Rerankとは、RAGによって返された結果を再度並べ替えることで精度を高める手法です。

精度を高められる理由は、RAGがベクトル間の類似度を比較して検索結果を決定する際に、データベース内のデータ量が膨大であるため、各ベクトル間の類似度をすべて計算してから決めるとものすごい時間がかかります。そのため、基本的にはクイックソートで、ある程度の類似度（例えば99%,95%）を持つチャンクならすべて抽出し、そこからランダムにいくつ（パラメーターで指定された返す件数）を選ぶというやり方となっています。これにより処理速度は向上しますが、当然精度もその分落ちてしまいます。そこで、Rerankすると、得られた結果を再度並べ替えるので、RAGの精度を向上させることも可能です。


## 2.Rerankの評価指標

Rerankの精度を評価する指標にはHit-RateとMRR（Mean Reciprocal Rank）があります。
Hit-Rateは名前の通りに、検索文書の中で正解を見つけ出せる（上位X件から）割合です。
MRRは、検索結果における適合文書が上位から数えて何番目にあるかを示す指標です。
計算方法は最初に見つかった適合文書のランクの逆数をスコアとします：
1位なら1/1=1.0、2位なら1/2=0.5、複数個あれば最後平均値を計算してその結果をMRRスコアにします。(1+0.5)/2=0.75

Llamaindexの調査結果から見ると、基本的にはすべてのRAGに対して、Rerankをすればある程度精度上げられます。
HitRateは4%から最大で10%まで向上し、MRRはさらに最大で20%以上の向上が可能です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556459/2b1b3750-c432-b69e-0b04-2b6abd48191c.png)

## 3.Rerank実験

私も簡単なRAGを実装し、Rerankの効果を試しました。
まず最初に、RAGのテスト用データをChatGPTに作成してもらいました。
生成されたデータは、「スマホを初期状態に戻すために必要な処理」という質問と、それに対する数十個の回答です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556459/a7e37fbc-85fc-4fb1-f7fb-768623480b2a.png)



RAGで検索した結果、top5の回答が以下になりました。
確かに正解（3番目）は含まれていましたが、完全に間違っている内容も混じっていますね。（例えば、2番と5番は正解とあまり関係ないと思いますが）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556459/bb1f643d-81dc-e8e6-a009-c78b80c2d74a.png)


最後、この五つの回答をRerankしました。（使用したRerankモデルは、現時点で精度が最も高いOSSモデルの”bge-reranker-large”です）

Rerankの結果は以下の通りです。数字が大きいほど質問との関連性が高いということです。大きい順に並ぶと31452です。
3が最も適切な回答であることは判断できましたね。あと、関連性が低い2と5のスコアもかなり低くつけましたので、Rerankは確かに効果ありますね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556459/21bf451c-bf8c-9560-05a9-c6322372a598.png)



## 【参照先】

LlamaindexのRerank記事：

https://blog.llamaindex.ai/boosting-rag-picking-the-best-embedding-reranker-models-42d079022e83

Rerankモデル（bge-reranker）：

https://huggingface.co/BAAI/bge-reranker-large
Embeddingモデルを使ったベクトル検索

# はじめに
ベクトル検索の一連の流れを確認し、各プロセスの処理内容と登場する用語の意味を解説します。次に、各プロセスで使用される機械学習モデルやアルゴリズムの例を挙げ、それらの特徴について一覧化しました。
この記事の続きとして後日、紹介した機械学習モデルとアルゴリズムの一部を使った実験の結果を共有しようと思います。

# ベクトル検索とは？
ベクトル検索はテキストや画像、音声などの非構造化データを分散表現（ベクトル）に変換することによって、関連性の高いコンテンツを探し出す検索手法の一つです。従来のキーワード検索ではその事柄を説明でき、理解していたとしても、語彙が分からない場合に検索精度が思うように出ない可能性があります。一方、ベクトル検索は意味内容からコンテンツを検索できることから、これらの制約を受けづらいという特徴があります。

# ベクトル検索のフロー
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3456978/57429f57-65a2-96a6-2c51-c2841cc03f70.png)


1. ***非構造化データのベクトル化***
テキストや画像、音声といった非構造化データを分散表現（ベクトル）に変換する処理のことを***Embedding***と呼びます。このプロセスでは予めインデックスに登録するためのデータに対してベクトル化（Embedding）します。Embeddingの処理にはそれ専用の機械学習モデル（***Embeddingモデル***）が必要で、モデルによってベクトルの次元数が異なる場合もあります。この工程で作成したベクトルをここでは"コンテンツベクトル"と呼ぶことにします。
1. ***インデックスの定義***
インデックスとは、情報検索を効率化するためのデータ構造です。DBや検索エンジンなど、膨大なデータの中から素早くデータを探し出したいときに登場します。今回もベクトル化（Embedding）したテキストや画像、音声はインデックスに登録し、検索時に利用します。
1. ***検索クエリの作成***
ユーザが該当データを探すためのヒントとなる情報を作成します。ベクトル検索のユースケースとして有名な RAG（Retrieval Augmented Generation）などではチャットボットへの質問文がこれにあたります。
1. ***検索クエリをベクトルに変換する***
ユーザが入力した検索クエリをEmbeddingして分散表現（ベクトル）に変換します。ここで使用するEmbeddingモデルはインデックスに登録するデータに対して使用したものと同じものを使います。この工程で作成したベクトルはインデックスに登録してあるコンテンツベクトルと区別するために"クエリベクトル"と呼ぶことにします。
1. ***インデックスから該当データを探す***
クエリベクトルと類似性の高いコンテンツベクトルをインデックスの中から探します。この類似性を測るための尺度と、該当データをインデックスの中から効率的に探索するアルゴリズムを併せて、***最近某探索***という最適化の問題として学術的に扱われています。類似性の高いコンテンツベクトルがどれか分かれば、元の非構造化データの中のどれを指し示しているかは明白です。

## ベクトル検索を支える技術
### Embeddingモデル
前述のとおり、Embeddingモデルを使って、非構造化データを分散表現（ベクトル）に変換していきます。このEmbeddingモデル選びはベクトル検索の精度と性能に大きく関わってきます。

| No. | モデル名 | 詳細 |
| --- | --- | --- |
| 1 | Word2Vec | Googleのトマス・ミコロフらによって2013年に提案された、単語の分散表現を得るためのモデル群である。浅い2層ニューラルネットワークを使って大きなコーパスから1つのベクトル空間を生成する。|
| 2 | GloVe | GloVeはスタンフォード大学のマニングらの研究室から提案された、より局所的な単語間の共起関係と、大域的な単語間の共起関係の両方を考慮できる学習モデルである。 |
| 3 | BERT | 2018年にGoogleが公開した自然言語処理モデルである。Transformerと呼ばれる深層学習モデルを採用し、双方向タスクを可能したことで話題となった。 |
| 4 | SimCSE | Dropout層を利用した対象学習と呼ばれる学習手法が特徴的な言語モデルである。BERTの抱える異方性の問題を解決するアイデアが学習時に施されています。 |
| 5 | text-embedding-ada-002 | OpenAI社が提供するEmbeddingモデルであり、以前まで提供されていた「davinci」よりも多くのタスクで性能が上回っている。 |

### 類似性尺度
Embeddingモデルによって分散表現になったデータを、似ているか似ていないか判断するためには ***類似性尺度*** というものを使います。例えば、分散表現によって数値化されたデータをそれぞれ１つの点として考え、データ点がお互いにどのくらい近しいかによって判断する方法があります。
| No. | 名称 | 詳細 |
| --- | --- | --- |
| 1 | ユークリッド距離 | 2つのデータをそれぞれ点として考え、いわゆる「通常の」2点間の距離を計算する。2つのデータA、Bの距離は、AとBの分散表現の各次元の差を二乗和平方根にして計算する。 |
| 2 | コサイン類似度 | 2つのデータをベクトルとして考え、2つのベクトルのなす角を計算する。扱えるベクトルは零でないものに限り、とりえる値の範囲は-1～1までと決まっている。 |

### 探索アルゴリズム
インデックスに登録した膨大なデータすべてに対して類似性尺度の計算するのはとてもコストがかかってしまいます。なるべく効率的に所望データを見つけるためのアイデアが探索アルゴリズムです。

| No. | 名称 | 詳細 |
| --- | --- | --- |
| 1 | HNSW | 階層型のグラフ構造を持たせたインデックスによって効率的にクエリベクトルと近しいコンテンツベクトルを探索するアルゴリズムである。階層の上位レイヤーを使って目的のコンテンツベクトルまで大まかに接近し、下位レイヤーで詳細に迫るという手順を踏む。 |
| 2 | IVF | ベクトル空間をセル分割し、各セルの代表値（もしくは代表となるベクトル）とクエリベクトルとの類似性を比較することで大まかに対象を絞り込む。その後、対象セル内のコンテンツベクトルから詳細に所望のコンテンツベクトルを探索する。 |

# まとめ
ベクトル検索は、 ***Embeddingモデル*** によって分散表現（ベクトル化）されたデータを、 ***類似性尺度*** と ***探索アルゴリズム*** によって効率的に検索する仕組みのことでした。この記事で紹介した要素技術の組み合わせによってベクトル検索の精度は変化します。
こうしたベクトル検索の仕組みを実際に試してみるときは、ぜひこの記事で紹介したような要素技術に対して、パラメータをちょうせいしてみたり、採用するアルゴリズムやモデルを変更してみるなど試行錯誤を加えてみてください。
firefoxが起動しない (Ubuntu 22.04.4 LTS)

### 自分用メモ
os(ubuntu)インストール後にfirefoxが起動しない,,  
調べると X Window System関連の問題だそう．  
単純に使ってるグラフィックボードのNVIDIAドライバがなくて起動できないとのこと.  
以下，エラーメッセージ  
```bash
christopher@Chris-Gaming-Linux:~$ env BAMF_DESKTOP_FILE_HINT=/var/lib/snapd/desktop/applications/firefox_firefox.desktop /snap/bin/firefox %u
Gtk-Message: 18:41:59.114: Failed to load module "canberra-gtk-module"
Gtk-Message: 18:41:59.115: Failed to load module "canberra-gtk-module"
ATTENTION: default value of option mesa_glthread overridden by environment.
ATTENTION: default value of option mesa_glthread overridden by environment.
ATTENTION: default value of option mesa_glthread overridden by environment.

(firefox:60465): Gdk-WARNING **: 18:42:01.096: The program 'firefox' received an X Window System error.
This probably reflects a bug in the program.
The error was 'BadAlloc'.
  (Details: serial 505 error_code 11 request_code 146 (unknown) minor_code 7)
  (Note to programmers: normally, X errors are reported asynchronously;
   that is, you will receive the error a while after causing it.
   To debug your program, run it with the GDK_SYNCHRONIZE environment
   variable to change this behavior. You can then get a meaningful
   backtrace from your debugger if you break on the gdk_x_error() function.)
Exiting due to channel error.
```
##### 以下，解決法（NVIDIAドライバへの切り替え）  
まずは利用可能なドライバをリスト  
```bash
$ sudo ubuntu-drivers devices
```
distro non-free recommended と書かれたドライバを見つけ, インストールする  
```bash
$ sudo apt-get install (ドライバ名)
```
再起動すると使用可能になるはず  

解決しない場合は，safe modeで起動してキャッシュをクリアする？


[参考](https://askubuntu.com/questions/1402752/firefox-stopped-working-with-a-badalloc-x-window-system-error-on-ubuntu-21-10)
基準画像を生成する【道具としての OpenCV 画像認識】

# 本記事でできること
真っ黒なカラー画像を生成して画面に表示します。
![black_image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37698/4f426ce2-2c00-dcbe-d764-f9f36f06ef07.png)


# 想定シーン
## ロボットをビジュアルフィードバック制御する
カメラを使ったロボットアームの制御方法を、ビジュアルフィードバック制御といいます。ここでは、ビジュアルフィードバック制御を使った自動化システムを開発する際に必要となる画像認識プログラムをまとめています。

## 基準画像を生成する
ビジュアルフィードバック制御をする際に、マスク画像をつくったり、背景画像をつくったり、撮影した画像以外の基準画像を作成したいことがあります。本記事では、サイズを指定して、真っ黒なカラー画像を作成する手順を掲載します。


# 実行環境
- OS：Ubuntu 22.04 LTS
- 言語：C++
- クルーボ：v5.1.0

## クルーボについて
ロボットアプリケーション開発には、株式会社チトセロボティクスのロボット制御ソフトウェア「クルーボ」を使用します。本記事のプログラムは、クルーボがインストールされた制御コンピュータ上で動作します。

- クルーボの製品サイト：https://chitose-robotics.com/product

## プログラム抜粋
```c++
const cv::Size image_size(640, 480);
const cv::Mat black_image = cv::Mat::zeros(image_size.height, image_size.width, CV_8UC3);
```

## 全体プログラム
```c++
#include <iostream>
#include <opencv2/opencv.hpp>

int main(void) {
    const cv::Size image_size(640, 480);
    const cv::Mat black_image = cv::Mat::zeros(image_size.height, image_size.width, CV_8UC3);

    cv::imshow("black_image", black_image);
    cv::waitKey(0);
}
```

## おわりに
人手作業をロボットアームで自動化するために、カメラを使ったロボット制御＝ビジュアルフィードバック制御が大切です。
ロボット制御用の画像認識でも中身のひとつひとつはシンプルなので、要素に分解して解説していきたいと思います。
CloudFormationでJupyterNotebook環境を構築する(for DeepRacerログ分析)

## はじめに
AWS DeepRacerはレーシングカーの強化学習モデルを作成するサービスです。

モデルを作成した後は報酬関数やハイパーパラメータをチューニングし、さらにトレーニングをします。
トレーニングや評価時のログ分析をすることで、ラップごとの完走率や報酬の推移などを細かく把握し、チューニングの参考にすることができます。

ログ分析環境は色々選択肢がありますが、SageMakerだとログの連携が楽なのでSageMaker上にJupyter Notebookを立てて分析をしています。(分析には公開されているサンプルコードを使っています)

分析用のサンプルコード

https://github.com/aws-solutions-library-samples/guidance-for-training-an-aws-deepracer-model-using-amazon-sagemaker/tree/master

以前JupyterNotebook環境を手組みしたら権限関連で引っ掛かってなかなか作れなかったので、CloudFormationのテンプレートで権限設定とリポジトリの設定もまとめてやってみました。
テンプレの実行時間も数分で手組みより楽だったので記事に残しておきます。

## 1. JupyterNotebook環境を用意する

### CloudFormationでNotebookインスタンスを立てる

CloudFormationのテンプレートは以下のサンプルをベースにしました。
プロパティのDefaultCodeRepositoryには分析に使うサンプルコードのGitHubリポジトリを指定しました。
インスタンスタイプなどはお好みで変えてください。

https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-notebookinstance.html


せっかくインスタンスを立てたのでコードも実行してみましょう。

## 2. 実行例:完走率と得た報酬のグラフを出力する

グラフが右上がりの場合、さらにトレーニングするとモデル改善が期待できると言われていますが…
このモデルは報酬関数やハイパーパラメータのチューニング無しにトレーニングしてもあまり改善が見込めなさそうです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3458266/b563d15d-5700-965f-4f9d-94bb63504cbb.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3458266/f2c65bc5-a8c6-c209-dcfa-136f827f7f50.png)


## おわりに
同僚とDeepRacerのログ分析用にJupyterNotebook環境を立てたときに手組みはちょっとめんどくさいねという話をしたので、今回のCFnテンプレートは社内に展開しようかなーと思います。
aboutLibrariesに手動でライセンスを追加する

# はじめに
今回は前回書いたaboutLibrariesというライセンス画面用のライブラリを使って手動でライセンスを追加する方法を紹介していきます。
一応以前に同じ記事を書いたのですが、もっと詳しく書いておこうと思ったので今回は詳細を書いていきます
### 本文
まず、プロジェクト直下に適当な名前でフォルダを作ります。
次に作ったフォルダの中で`libraries`と`licenses`というフォルダを作ります
`licenses`にはそのライブラリのライセンスが描かれたJsonを配置します。
```json:hoge_license
{
  // ライセンスの中身
  "content": "content",
  // どのライブラリのライセンスなのかを判断するためのハッシュ
  "hash": "flutter_secure_storage",
  // ライセンスのURL
  "url": "https://github.com/mogol/flutter_secure_storage/blob/develop/LICENSE",
  // ライセンス画面で表示されるライセンス名
  "name": "License"
}
```
`libraries`にはライブラリの作者やサイトなどのURLを書いたJsonを配置します。
```json:hoge_library
{
  // 名前の通り一意のID
  "uniqueId": "hoge",
  // 使ってるライブラリのバージョン
  "artifactVersion": "1.0.0",
  // 作者情報、基本的にはnameのみ表示されるのでnameさえあれば問題なし
  "developers": [
    {
      "name": "fuga"
    }
  ],
  // 詳細説明
  "description": "description",
  "name": "hoge",
  // ライセンス情報、ここで先ほどのhoge_licenseにあるハッシュを入力
  "licenses": [
    "license"
  ]
}
```
最後にAppのbuild.gradleに下記のように参照先を記述して終了です
```gradle
aboutLibraries {
    configPath = "プロジェクト直下に作ったフォルダ名"
}
```
### 最後に
今回はaboutLibrariesでの手動でライセンスを追加する方法を紹介しました
複数個追加する場合は`libraries`と`licenses`に各種Jsonファイルを作らないといけないのでご注意ください
画像を回転させる【道具としての OpenCV 画像認識】

# 本記事でできること
画像を読み込んで、回転させたあと、画面に表示します。
![rotated_image_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37698/2eb67ea7-fa53-bcc3-c3b4-576ab86e5ffc.png)


# 想定シーン
## ロボットをビジュアルフィードバック制御する
カメラを使ったロボットアームの制御方法を、ビジュアルフィードバック制御といいます。ここでは、ビジュアルフィードバック制御を使った自動化システムを開発する際に必要となる画像認識プログラムをまとめています。

## 画像を回転させる
ビジュアルフィードバック制御で使用するカメラの配置が、ロボットの向きとずれている場合があります。この状態で開発をすると、首かしげながら画像認識プログラムを制作することになり、ちょっとつらいです。本記事では、画像を回転させるプログラムを掲載します。掲載したプログラムでは、直角回転以外の場合には、画像の一部が欠けてしまうことがありますので、ご注意ください。ただ、ロボット制御の場合、カメラは90度ずつ回転させる場合が多く、中途半端な角度に回転させることはほとんどありません。

# 実行環境
- OS：Ubuntu 22.04 LTS
- 言語：C++
- クルーボ：v5.1.0

## クルーボについて
ロボットアプリケーション開発には、株式会社チトセロボティクスのロボット制御ソフトウェア「クルーボ」を使用します。本記事のプログラムは、クルーボがインストールされた制御コンピュータ上で動作します。

- クルーボの製品サイト：https://chitose-robotics.com/product

## プログラム抜粋
```c++
cv::Mat rotate_image(const cv::Mat& image, const float rotate_angle) {
    cv::Mat rotated_image;
    if ((int)rotate_angle == 90) {
        cv::rotate(image, rotated_image, cv::ROTATE_90_CLOCKWISE);
    } else if ((int)rotate_angle == 180) {
        cv::rotate(image, rotated_image, cv::ROTATE_180);
    } else if ((int)rotate_angle == 270) {
        cv::rotate(image, rotated_image, cv::ROTATE_90_COUNTERCLOCKWISE);
    } else {
        cv::Point2f rotate_center_point((float)image.cols / 2.f, (float)image.rows / 2.f);
        cv::Mat rotate_matrix = cv::getRotationMatrix2D(rotate_center_point, rotate_angle, 1.0);
        cv::warpAffine(image, rotated_image, rotate_matrix, cv::Size(image.cols, image.rows));
    }
    return rotated_image;
}
```

## 全体プログラム
```c++
#include <iostream>
#include <opencv2/opencv.hpp>
cv::Mat load_image(const std::string file_path) {
    cv::Mat loaded_image = cv::imread(file_path, 1);
    if (loaded_image.empty()) {
        throw std::runtime_error("画像を正常に読み込めませんでした。");
    }
    return loaded_image;
}

cv::Mat rotate_image(const cv::Mat& image, const float rotate_angle) {
    cv::Mat rotated_image;
    if ((int)rotate_angle == 90) {
        cv::rotate(image, rotated_image, cv::ROTATE_90_CLOCKWISE);
    } else if ((int)rotate_angle == 180) {
        cv::rotate(image, rotated_image, cv::ROTATE_180);
    } else if ((int)rotate_angle == 270) {
        cv::rotate(image, rotated_image, cv::ROTATE_90_COUNTERCLOCKWISE);
    } else {
        cv::Point2f rotate_center_point((float)image.cols / 2.f, (float)image.rows / 2.f);
        cv::Mat rotate_matrix = cv::getRotationMatrix2D(rotate_center_point, rotate_angle, 1.0);
        cv::warpAffine(image, rotated_image, rotate_matrix, cv::Size(image.cols, image.rows));
    }
    return rotated_image;
}

int main(void) {
    std::string file_path = "../data/fuji.jpg";
    const cv::Mat loaded_image = load_image(file_path);

    const float rotate_angle = 90.f;
    const cv::Mat rotated_image = rotate_image(loaded_image, rotate_angle);

    cv::imshow("loaded_image", loaded_image);
    cv::imshow("rotated_image", rotated_image);
    cv::waitKey(0);
}
```

## おわりに
人手作業をロボットアームで自動化するために、カメラを使ったロボット制御＝ビジュアルフィードバック制御が大切です。
ロボット制御用の画像認識でも中身のひとつひとつはシンプルなので、要素に分解して解説していきたいと思います。
PleasanterのスクリプトをTypeScriptで書きたい

## PleasanterのスクリプトをTypeScriptで書きたい

### 概要
- PleasanterのスクリプトをTypeScriptで書きたいですよね?
- 実現するための環境設定を用意しました
- 型定義が必用だったので、型定義を作成して[DefinitelyTyped](https://www.npmjs.com/package/@types/pleasanter-web-script)にも登録しました

---

### 使い方

#### 0.環境

Node.jsがインストールされている必要があります。

#### 1.取得

リポジトリにひな形となるプロジェクトが格納されています。
リポジトリに格納されているテンプレートプロジェクトをダウンロードしてください。

[Pleasanter-TypeScript-DevEnv](https://github.com/yamada28go/Pleasanter-TypeScript-DevEnv)

#### 2.必用なライブラリ取得

コンパイルに必用なライブラリをダウンロードします。
`package.json`ファイルが存在するディレクトリまで移動します。
該当ディレクトリで以下コマンドを実行してください。

```bash
npm install
```

#### 3.コード実装

'src/index.ts' というファイルがエントリポイントになります。
このファイルから参照されているファイルが自動的にビルド対象となります。
@typesで型定義がされているので、$pの下から各種データにアクセスすることが出来ます。

なお、型定義が間違っていたら教えてください...。

```typescript
 $p.apiGet({
  id: 1545,
  done: (data) => {
    console.log(data);

    // サンプルコード
    $p.setMessage(
       "#Message",
      JSON.stringify({
         Css: "alert-success",
         Text: "処理が正常に終了しました。",
       }as SetMessageArgumentType)
     );

  },
});
```

#### 4.コードフォーマット

コードを整形するコマンドです。

```
npm run format
```


#### 5.ビルド

コードをビルドするコマンドです。変更があるたびに自動でビルドが実行されます。
ビルド結果は'dist/index.js'に出力されます。
該当ファイルの内容物をスクリプトページに貼り付けてください。
このコマンドで出力されたコードは、デバッグ用のmapファイルを含んでいます。
このため、chromeデバッガーなどでコードを見ながらデバッグする事が出来ます。

```
npm run build
```


#### 6. リリースビルド

リリース用のビルドコマンドです。コードが最適化されてビルドされます。
minifyが適用され、デバッグ用のマップファイルは含まれません。ここからデバッグするのは大変です。


```
npm run release
```



## 感謝

この開発環境は、Oooooomin2様のECMAScript環境をTypeScriptに変換したものです。感謝いたします。

[Oooooomin2/Pleasanter_ECMAScript](https://github.com/Oooooomin2/Pleasanter_ECMAScript)
Kubernetes: Upgrading Argo CD

Argo CD の version up について。個人的な memo として。

Argo CD の maintenance が滞っていたため、Argo CD の version up と cluster の version up に対応する。

下記の warning によって自動更新が止まっていた。

https://cloud.google.com/kubernetes-engine/docs/deprecations/podsecuritypolicy?hl=ja

## Upgrading Argo CD and Ingress
### Upgrading　Argo CD

- `stable` を apply する。

```bash
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
```

https://argo-cd.readthedocs.io/en/stable/operator-manual/upgrading/overview/

### Recreate Ingress

- `argocd-server` の manifest が変更になっているため service discovery を含め、再作成する。
- `argocd-server` の TLS の対応を行う。configmap で `server.insecure: "true"` を設定する。edit 後、`argocd-server` の rollout も忘れずに。
    > **Disable internal TLS**
    First, to avoid internal redirection loops from HTTP to HTTPS, the API server should be run with TLS disabled.
    Edit the --insecure flag in the argocd-server command of the argocd-server deployment, or simply set server.insecure: "true" in the argocd-cmd-params-cm ConfigMap [as described here](https://argo-cd.readthedocs.io/en/stable/operator-manual/server-commands/additional-configuration-method/).

https://argo-cd.readthedocs.io/en/stable/operator-manual/ingress/#google-cloud-load-balancers-with-kubernetes-ingress

### Deprecated resource warning

- API `/apis/policy/v1beta1/podsecuritypolicies` が削除された。1.25 において。
以下の message が表示される。

:::note warn
過去 30 日間に、クラスタ内の API クライアントが、Kubernetes 1.25 で削除された API を呼び出そうとしました。現在、これらの API は利用できません。これらの API を使用する機能は、正常に動作しないおそれがあります。
:::

- configmap `argocd-cm` に設定を追加する。`PodSecurityPolicy` を監視から除外する。edit 後、`argocd-application-controller` の rollout も忘れずに。

https://github.com/argoproj/argo-cd/issues/12382

https://argo-cd.readthedocs.io/en/latest/operator-manual/declarative-setup/#resource-exclusioninclusion

```yaml: argocd-cm
  resource.exclusions: |
    - apiGroups:
      - policy
      kinds:
      - PodSecurityPolicy
      clusters:
      - "*"
```

### Update Cluster
- cluster を manual で update する。

## BTW
single-tenant で運用すると cluster の数だけ maintenance が発生する cons がある。
一方、multi-tenant だと maintenance は一発で終わるが、影響が大きい。
悩ましい。
画像処理を使った結晶粒度の測定

## はじめに
JIS G0551（2020） 鋼－結晶粒度の顕微鏡試験方法の切断法に準じて粒度番号を求めるプログラムをご紹介します。このプログラムでは、結晶粒界を現出させた金属組織画像を読み込み、画像に3個の同心円を表示させ、その同心円を通る結晶粒界の個数をカウントします。
結晶粒界が明瞭でない組織画像については、誤って結晶粒界をカウントするため、それを左右のマウスボタンをクリックすることにより修正する機能も付いています。
プログラムは画像処理のライブラリOpenCVを用いてPython言語で作成しています。

## 作成したプログラム
以下に格納しております。使い方はREADMEをお読みください。

https://github.com/repositoryfiles/Apparent_grain_size

## 終わりに
結晶粒界が明瞭な組織画像であれば、結晶粒界の修正が少なくて済むと思います。
皆様に試していただき、より実用的なプログラムにしていただけたらと思っています。
Android ビルドタイプによってアプリケーションIDを変える方法

ビルドタイプによってアプリケーションIDを変える方法です。

`buildTypes`の設定したいビルドタイプに対して`applicationIdSuffix`の設定をします。

```build.gradle
debug {
   　applicationIdSuffix = ".debug"
}
```

`applicationIdSuffix`に設定した値が後ろに追加されます。
今回の場合は、.debugが後ろに設定されます。


# 公式リファレンス

https://developer.android.com/build/build-variants?hl=ja#change-app-id