開発serverのdocker環境の監視用に、Diun、Trivyを設定

大きなNewsにもなっているPHPのセキュリティ問題(PHP2Shell)。

楽天やGMOをはじめ、いくつかの大手サービスが軒並みメンテでSTOPしていた。

自分の開発ではPHPは使わなのでinstallもしてなかったけど、 その後に Node.js でも問題が見つかったとかで、 一応、開発serverにdocker環境の自動scan、通知を仕込んだ。

項目 Diun Trivy
バージョン 4.33.0(digest固定) 0.75.0(digest固定)
役割 イメージの新版を検出する イメージ内の既知の脆弱性を検出する
実行タイミング 毎日 9:00 毎週月曜 8:00
起動方法 Docker コンテナ diun(常駐) systemd タイマー trivy-scan.timer
監視対象 稼働中コンテナの公開イメージ、images.yml に書いたベースイメージ 稼働中コンテナの全イメージ
通知条件 同じタグで新しい digest が公開されたとき HIGH/CRITICAL で修正版があるもの(毎回送信)
通知方法 Brevo SMTP でメール送信 Brevo SMTP でメール送信
設置場所 /opt/update-watch/(compose.yaml、diun.yml、images.yml) /opt/update-watch/(trivy_scan.py、reports/)
更新の適用 しない(手動で docker compose pull) しない(手動で再ビルド・pull)

メールはBrevo SMTP経由で自分宛に送信。初回の監視でhitした、優先度が高い以下をupdate対応。

Django 5.2.6 → 5.2.18。DRF(Django REST Framework) 3.16.1 → 3.18.3、nginx 1.27 → 1.30-alpine(1.30.6)。ビルド用のnode 20 → 24、nginx 1.27 → 1.30-alpine

AIに回答のエビデンスを明確に示させるための仕組みをPoC実装してみた

ChatGPT(OpenAI API)に回答のエビデンスを明確に示させるための仕組みをPoC実装してみた。

GitHub - tadano-akira/openai-query-app · GitHub

課題

というのも、ChatGPT(OpenAI API)の回答には、根拠となる参照先のURLは出ていても、 参照先のどこを根拠にしたのかまでは示されておらず、 自力で参照先のWebPageないしPDF内を検索して確かめるしかない。

これは不便なので、根拠となる情報までハイライトさせて、 一発で目視確認できるようにできないかと思い、構想・実装してみた。

前提として、企業の決算情報を扱った。 各企業IRサイトやEDINET、TDNETなど根拠に足りる原本が しっかり管理されているので。

結果は以下。

結論

結論から言おうと、PoCレベルの実装は出来たのだが、いろいろ課題が多い。

上記では、「トヨタの直近の有利子負債はいくら?」 という質問にたいして、トヨタIRで公開されているPDFを参照して、 根拠となる箇所にダイレクトリンクしてハイライト表示もしている。 ここまでは便利な道具がそろっているので、すぐに実装できた。

エビデンスの担保

問題はエビデンスの担保から。

まず、エビデンスの確かさは、人間でないと判断できない。

というか、公式サイトやEDINET、TDNETからの情報なら信頼できるけど、 YouTubeだの株予想系のWebなどは根拠にならないが、AIはかまわず、そうしたソースも提示する。

そうした情報を根拠にした回答が混じると、幻視まではいかないが、 ビジネスシーンで求められる正確性、信頼性が担保できない。

おのすと、情報源は公的なものに絞られる。

データの構造化問題

また、PDFが情報ソースの場合、PDF内の情報構造を予め解析して、 位置情報も含めたMETA DB の整備が必要になる。

つまり公開情報を取り込んで事前解析したDB検索対象としたRAG SYSTEMになる。

ここが一番重い。データの構造化問題だ。整備・維持コストがきつい。専任担当が欲しいレベル。

META DBさえできていれば、あとはPDF内の参照元をハイライトしてダイレクトリンクさせるだけなのだが ここでも問題がある。根拠が複数の場合だ。

あとえば「トヨタの直近の有利子負債はいくら?」という質問に対して、 有利子負債が2つのデータの合算なケースなどがある。 (流動負債分と非流動負債分の合計)

そうした定義も設定していくと、データの構造化をしていく作業がとにかく重い。 ある程度は自動化できるだろうが、最終的な正確性・信頼性の担保は、 人間による確認・承認プロセスに頼ざるおえない。

やはり、まともに運用するとなると担当者が欲しい感じ。

アーキテクチャ:

flowchart TD
  UI[React UI] --> API[FastAPI]
  API --> DB[(PostgreSQL)]
  API --> FILES[原本・抽出成果物]
  WORKER[バックグラウンドワーカー] --> DB
  WORKER --> FILES
  WORKER --> PARSER[PyMuPDF解析]
  WORKER --> MODEL[LLM・埋め込みAPI]
  UI --> VIEW[PDF.js・HTMLビューア]
  VIEW --> API

採用コンポーネント

層 採用案 責務
Web UI React + TypeScript + Vite 資料管理、質問、根拠確認
PDF表示 PDF.js 原本描画、ズーム、回転、ページ移動
API FastAPI + Pydantic 認証、入力検証、根拠解決、履歴
PDF解析 PyMuPDF 文字・行・座標・表候補抽出
DB PostgreSQL + pg_trgm + pgvector 永続化、字句・ベクトル検索
ORM / migration SQLAlchemy + Alembic スキーマ・トランザクション
ジョブ PostgreSQLのjobsテーブル + 専用Pythonワーカー 再実行可能な非同期処理
数値処理 Python Decimal 加算・減算・単位変換
LLM接続 プロバイダーアダプター 構造化JSON生成、使用量計測
配布 Docker Compose ローカル実行

本格実装時の規模感

今回のPoCではLangChain / LangGraph / Difyなどは利用せず、明示的なPythonの処理段階で実装。 PoCから本格実装時には、運用コストも勘案すると、LangChain、LangGraph、Difyなども活用すべき。 HNSW索引なども入れたい。

対象を全上場企業にすると、DBやストレージサイズが1.4TBくらいに膨らむ。 仮に100名のアナリストが利用すると想定して、 systemを1台のServerに収めるとすれば、 32コア・256GB メモリ・NVMe 8TB 級が望ましい。

AWSだとr7i.8xlarge+EBS gp3 8TBで、月額3000ドル(50万円弱)。

かなりのインフラがないと稼働は厳しい。個人でどうにかする規模ではない。

OpenAI にSecurity keysなどの機密情報を送信する前に検知し、自動ブロックしてアラートする

OpenAI API を利用した自分用ChatGPT風 アプリ に、access token や Security keysなどの機密情報を送信する前に検知し、自動ブロックしてアラートする仕組みを入れた。

Microsoft の Presidio というOSSを利用。 参考記事: Microsoft製のPII検出・匿名化SDK「Presidio」でテキストの個人情報をマスクしてみる | DevelopersIO

疲れているとき、寝ぼけてコピペミスで、ChatGPTやClaude に投げてはいけない文字列を入れて送らないように、送信前にブロックする仕掛け。ヒヤリハット防止。

ChatGPTやClaude に投げたあとに怒られることはあるけど、それは後の祭りなので、クラウド側に出る前、水際で防がないと意味がない。

maskして投稿することもできるけど、そもそも投稿しちゃダメなのもので( log とか json をそのまま貼り付ける場合が該当するだろう)、maskせず止めるだけにした。

実装後の画面:

上記はいずれも、本物っぽくしたdammyの値だけど、検知できている。 接頭辞のないランダムなトークン、key文字列も検知するようにした。 検知の記録も残している。

appとは別dockerで動いているので、VS code の cluade code からの投稿も、Proxyさせて止めることも可能。

Langfuseを3系から最新4系にupdateするさいの調査観点

Langfuseはapp本体とは別コンテナとしてselfhostで稼働。

「アプリと別コンテナだから影響がない」ということはなく、 「アプリとLangfuseの接続部分に互換性があるか」を中心に調べるのが適切。

まず公式情報を確認すると、v3→v4にはSDK・APIの破壊的変更があり、既存アプリへの影響はあり得る。

Migrate Langfuse v3 to v4 (self-hosted) - Langfuse

ただし、移行用の legacy/dual モードで従来の動作を維持し、段階的に移行できます。

Langfuse調査は、次の観点で整理するとよい。

調査観点 確認すること 想定される影響
① SDKの互換性 アプリに入っているPython/JS SDKのバージョン、利用メソッド 計測データを送れない、SDK更新によるコード修正
② APIの互換性 LangfuseのAPIを直接呼び出している箇所、データ取得・集計処理 APIエラー、独自の集計画面が動かない
③ アプリの依存範囲 計測データの送信だけか、プロンプト取得などにも使っているか 計測欠損だけで済むか、回答生成まで止まるか
④ 計測結果の整合性 トークン数、処理時間、エラー、会話ID・ユーザーIDの紐付け アプリは動くが、計測値や集計が変わる
⑤ 障害時の挙動 Langfuse停止・通信失敗時の例外、タイムアウト、再送 応答遅延、アプリ側エラー、メモリ増加
⑥ 保存データと関連機能 過去のトレース、評価、エクスポートの移行 過去データが見えない、評価・出力が止まる
⑦ 稼働環境と復旧 DBの対応バージョン、移行中の負荷、バックアップと戻し方 同じホスト上のアプリへの負荷、復旧時間の増加

v3→v4で特に押さえる具体的な変更は、以下。

  • サーバーとSDKのバージョン番号は別物。ここは勘違いしやすいので注意。 「Langfuseサーバーがv3」だけでは互換性を判断できません。公式の移行準備ガイドでは、Python SDK 4.7.0以上、JS/TS SDK 5.4.0以上への更新を案内しています。Versions & Compatibility - Langfuse
  • v4標準の events_only に切り替えると、旧SDKや旧APIの一部が使えなくなります。 コンテナイメージの変更と、互換性を切り替えるタイミングを分けて検討する必要があります。
  • 評価・エクスポートも確認対象です。 利用していれば、旧方式からの移行が必要。

Prepare Your Project for the v4 Upgrade - Langfuse

  • 元のv3イメージに戻すだけではロールバックできません。 DB移行を伴うため、復旧手順も事前検証が必要。

実際の検証では、同じアプリ・同じテスト入力で、更新前後を比較すると判断しやすくなります。 1. 現行のサーバー、SDK、連携ライブラリ、設定を記録する。 2. DB・ストレージを分離した検証環境で、アップグレードを再現する。 3. 通常回答、ストリーミング、APIエラー、会話継続を実行する。 4. アプリの動作とLangfuseに記録された内容を別々に確認する。 5. Langfuse停止時の動作と、復旧手順を確認する。

まずは compose.yaml、requirements.txt/pyproject.toml または package.json、Langfuse連携コードがあれば、「今回のアプリに関係する変更」を具体的に絞り込めます。

チャット UI から OpenAI APIで 会話・各応答の処理時間/トークン使用量/エラーを観測する個人用アプリ

ChatGPT 風のチャット UI から OpenAI Responses API(Web 検索ツール付き)を呼び出し、 会話・各応答の処理時間/トークン使用量/エラーを観測する個人用の技術検証アプリを作った。

ChatGPTの設定からだと、大まかな利用状況しかわからないし、openAI Platformでも全体でのトークン使用量しかとれないので、個人で実装した。

区分 内容
フロント React 19 + TypeScript + Vite 8 + Tailwind v4 + shadcn/ui
バックエンド FastAPI + SQLAlchemy 2 (async) + Alembic + OpenAI Python SDK
アプリ DB PostgreSQL 17
観測 Langfuse v4(セルフホスト、別 Compose プロジェクト)
実行環境 Windows + Docker Desktop(ソースは Windows 側、コンテナは Linux)

  • 会話ごとに、トークンや応答時間、推計料金の表示。使用model も指定できる。5.6-Lunaをデフォに。5.5より安い。
  • 連続した会話での計測にも対応。セッションごとの累計トークン、平均応答時間なども計測。これで、普段の会話が、どのくらいの処理量かを追跡できる。

  • モード切替も実装(トークン節約と、丁寧なビジネスと、わかりやすく解説してくれる易しいモード/いちいちPromptで支持しなくて済む)

  • claude.md のように、基本ルールを定義するbase.mdも実装。GUIではなくcodeで管理してgitにmerge/pushしてデプロイする形だけど。
  • model別×モード別の実績画面も追加。これで比較がしやすい。

おそろしいことに、テストで行った、いくつかの簡単な会話で 320,895トークン/$1.31(約200円)も使ったこと。

普段つかっている、ChatGPT Plus や Claude PRO コースのコスパがいかに良いかを感じる。 仕事だと、契約先が用意したaccountで、遠慮なしにつかっているけど、考えるの怖い。。。

Qwen3.8-27Bをmem16GBのWindows-Note PCで試した

この記事を見て、

Qwen3.8-27Bを8GBに凝縮!メモリ16GBのノートで動く「Saluki 27B」 (PC Watch)

Qwen3.8-27Bをmem16GBのWindows-Note PCで試してみた。 (Ryzen 7 5825U / RAM16GB / GPUなし)

ollama pull hf.co/ConwayResearch/Underdog-Saluki-27B-1.0 2>&1 | Select-Object -Last 5

マニフェスト登録時に「file does not exist」エラーが出てモデル一覧に表示されず。 取得済みファイルからModelfileで直接登録。

項目 値
モデル読み込み 19秒(初回のみ)
生成速度 約2.1 tokens/秒
メモリ使用量 8.9GB(コンテキスト長 8K のとき)

動くには動いたが、さすがに遅い。 文字が出力されるのを目で追っていけるlevel。

memも余裕なし。system + app(EDGE、VScode)で7GBくらい使っているので、 Qwen3.8-27Bの実行中は16GBを使い切る感じになる。

ちょっと長いpromptなら、終わるまで10分とかかるので、 別のことができる感じ(トイレ行ったり、コンビ二行ったり)

ただ、出力結果はかなり良い。system開発で普段使いできそう。

ただし、このモデルにはWeb検索機能がないので、調査で「web_search」ツールを呼び出そうとするとSTOPする。

試したprompt:

Shadcn/up を調べて、どんなものか教えて。ただし、web_searchツールは使えないので、知っている範囲で日本語で答えて。

結果:

Shadcn/ui

Shadcn/ui(読み:シャドシエーユーアイ)は、React + Tailwind CSS + Radix UI の組み合わせで 構築した、コピー&ペースト型の UI コンポーネントライブラリです。

概要

何を提供しているか

コンポーネント例 用途
Button 各種ボタン
Input / Textarea 入力フォーム
Card カード型コンテナ
Dialog / AlertDialog モーダル
Dropdown / Select 選択メニュー
Table / DataTable テーブル(ソート・フィルタ・ページネーション付き)
Chart Recharts 系チャート
Form フォーム(Zod 連携)
Sidebar / Navigation 側バー・ナビゲーション
Skeleton ローディング表示
Toast トースト通知
ほか多数 Slider, Switch, Tabs, Tooltip, Progress 等

特徴

  1. コピー&ペースト方式

    • npm パッケージとして import するのではなく、コンポーネントのソースを自分のプロジェクトにコ ピーして使う。
    • 依存関係を最小限に抑え、カスタマイズ自由度が高い。
  2. Radix UI ベース

    • Radix UI の無依存・アクセシブルなプリミティブをベースにしているため、キーボード操作・スク リーンリーダー対応などアクセシビリティが担保されている。
  3. Tailwind CSS でスタイル

    • CSS を書かずに Tailwind のユーティリティクラスでスタイルを調整する。
  4. ダークモード対応

    • dark: プリフィックスや CSS 変数でダークテーマを簡単に切り替え可能。
  5. TypeScript 完全対応

    • 型定義(.d.ts)が完備されており、型安全で開発できる。
  6. CLI による生成

    • npx shadcn@latest add button のように、CLI で必要なコンポーネントをプロジェクトに追加でき る。
    • 初期設定(shadcn init)でテーマ、カラー、パス別などを選ぶ。

使い方(例)

# 1. 初期設定
npx shadcn@latest init

# 2. コンポーネント追加
npx shadcn@latest add button card dialog

# 3. 生成されたファイルを src/components/ui/ 下に配置
import { Button } from "@/components/ui/button"

export function App() {
  return (
    <Button variant="outline">Click me</Button>
  )
}

類似ライブラリとの違い

Shadcn/ui Mantine MUI (Material UI) Chakra UI
形式 コピー&ペースト npm パッケージ npm パッケージ npm パッケージ
スタイル Tailwind CSS-in-JS / Mantine CSS-in-JS / Material CSS-in-JS / Chakra
プリミティブ Radix UI Mantine MUI Chakra
カスタマイズ自由度 非常に高い(ソースを触れる) 中程度 中程度 中〜高
アクセシビリティ 高(Radix) 高 高 高

まとめ

  • React + Tailwind + Radix UI の組み合わせで「すぐに使える、かつ自由にカスタマイズできる」コ ンポーネントライブラリ。
  • コピー&ペースト方式のため、プロジェクトごとにコンポーネントを最適化しやすい。
  • 近年の React プロジェクト(Next.js、Vite、Remix など)で非常によく使われており、デファクトス タンダード的な存在になりつつある。

何か具体的な使い方やカスタマイズ方法などについて詳しく知りたい点があれば、お気軽にどうぞ!

手軽な規模のlocal LLM環境で最強なのは?

大きなmodelだとmemに乗りかが速度に大きな影響を及ぼすが、 (swapで極端に重くなる)

この規模だとmem にのっているので、

そうなると生成速度を律速しているのは、主にmem帯域らしい。 今のPCはDDR4-3200 8GB×2で理論値 51.2GB/s。

GPUが早いのは専用memの帯域が速いから。 memをCPUと共有するtypeだと遅い。

なぜメモリ帯域か

  • 1トークン生成するたびに、モデルの重み約7.9GBをすべてメモリから読み出す。
  • 27Bはdenseモデルなので、毎回全パラメータを使う。
  • 速度の上限は、だいたい「帯域 ÷ モデルサイズ」で決まるらしい。
  • 今のPCでの理論値は 51.2 ÷ 7.9 ≒ 6.5 tokens/秒。
  • 実効帯域は理論値の7割程度なので、現実的な上限は 4〜4.5 tokens/秒。
  • 実測は1.6〜2.1 tokens/秒で、上限の半分ほど。残りの差はCPU側の負荷差。
  • IQ2のような2bitの量子化形式は、読み出した値をCPUで展開する計算が重くなる。そのため、帯域を使い切る前に計算が追いつかない。
  • プロンプト処理(実測7 tokens/秒前後)は、ほぼ純粋にCPUの演算性能で決まる。

メモリ帯域・価格を軸に、比較してみた。コストはどの選択でもそれなりに高額になるが・・・

メモリ帯域・価格の比較表(2026年10月時点)

機種 メモリ帯域 メモリ容量 Saluki 27B推定速度 価格の目安 帯域1GB/sあたりの価格
MacBook Pro M5 Max(40コアGPU、128GB) 614GB/s 128GB 約50 tokens/秒 約85〜95万円(推定) 約1,500円
Mac mini(M5 Pro、64GB) 307GB/s 64GB 約27 tokens/秒 約48万円(Apple Store) 約1,550円
Mac mini(M5 Pro、48GB) 307GB/s 48GB 約27 tokens/秒 約40万円(Apple Store) 約1,300円
Mac mini(M5 Pro、24GB) 307GB/s 24GB 約27 tokens/秒 約30万円(Apple Store) 約1,000円
RTX Spark ノート(N1X) 約273〜300GB/s(推定) 機種による 約25 tokens/秒 約45〜50万円〜(リーク) 約1,600円
Ryzen AI Max+ 395(128GB)ノート 256GB/s 128GB 約20 tokens/秒 約45〜60万円 約2,000円
Ryzen AI Max+ 395(128GB)ミニPC 256GB/s 128GB 約20 tokens/秒 約35万円〜 約1,400円
Mac mini(M6、32GB) 170GB/s 32GB 約12〜15 tokens/秒 約22万円(Apple Store) 約1,300円
参考:Ryzen 7 5825U ノート(DDR4-3200) 51.2GB/s 16GB 約2 tokens/秒(実測) — —
  • Saluki 27B:Qwen3.8-27Bを約2bitに量子化したモデル(7.9GB)。
  • 推定速度:「メモリ帯域 ÷ モデルサイズ7.9GB × 実効7割」で算出した目安。
  • 価格:Mac mini(M6、M5 Pro)はApple Storeの価格。それ以外は1ドル=150円で換算した推定値。米国価格・リーク情報・中古相場をもとにしている。
  • M5 Proのメモリ帯域は、メモリ容量によらず307GB/s。
  • RTX Sparkのメモリ帯域はNVIDIA未公表。DGX Spark(GB10)の273GB/sからの推定値。

BrevoとCloudflareで無料でサーバレスの独自ドメインmail boxを立てた

BrevoとCloudflareでサーバレスの独自ドメインmail boxを立てた。 仕組みは以下の通り。無料だけど、送信には1日300通までのBrevo側の制限がある。

  • 受信:Cloudflare Email Routing。MX を受けて転送するだけで、メールを保管しない。
  • 保管・閲覧:Gmail。メールボックスの実体は Gmail 。
  • 送信:Brevo。@独自ドメイン名 の DKIM 署名を付けて送る。

つまり、普段つかっているgmail で、info@独自ドメイン名 なmail が送受信できる。

smtp serverがついたレンタルサーバやVPSがなくても運用できる。 もちろん、自前serverにsmto立てて運用でのいいけど、手軽さが違う。

独自ドメインのメールを運用する方法の比較

方式の凡例:

  • ① 今回:Cloudflare Email Routing + Gmail + Brevo
  • ② 有料サービス:Google Workspace など
  • ③ レンタル:レンタルサーバー付属のメール
  • ④ VPS:VPS に自前構築(Postfix/Dovecot など)
  • ⑤ 自宅:自宅サーバーに自前構築 + 送信は中継サービス

1. 費用と構成

項目 ① 今回 ② 有料サービス ③ レンタル ④ VPS ⑤ 自宅
月額 0円 約1,000円/人 数百〜1,500円 数百〜2,000円 電気代+中継
自前サーバー 不要 不要 不要 必要 必要
メール保管場所 Gmail サービス側 業者サーバー 自サーバー 自サーバー
ユーザー分離 弱い ※1 完全 あり あり あり
障害が起きる箇所 3社 1社 1社 自サーバー 自宅+中継

2. 送受信

項目 ① 今回 ② 有料サービス ③ レンタル ④ VPS ⑤ 自宅
送信上限/日 300通 ※2 約2,000通/人 数百〜数千通 実質なし 中継次第
到達率 高い 非常に高い 普通 低い ※3 中継次第
受信サイズ 25MiB/通 制約なし プラン次第 容量次第 容量次第
迷惑メール対策 Gmail 任せ 強力 業者任せ 自分で構築 自分で構築
スマホアプリ Gmail で可 可 可 可 難しい ※4

3. 運用

項目 ① 今回 ② 有料サービス ③ レンタル ④ VPS ⑤ 自宅
運用の手間 ほぼなし ほぼなし 少ない 多い 最も多い
管理画面 2か所に分散 ※5 統合 業者の画面 自分で用意 自分で用意
向いている用途 個人・窓口 組織 サイトと一緒に 学習・自己管理 学習・趣味

注記

  • ※1 全アドレスが1つの Gmail に集まる。各自の Gmail に転送すれば分けられる。
  • ※2 Brevo の無料枠。同じアカウントの他の用途と共有する。
  • ※3 新しい IP は評判がなく、迷惑メール扱いされやすい。ブラックリスト対策も必要。
  • ※4 IMAP ポートの公開が必要。自宅回線は25番ポートが塞がれていることも多い。
  • ※5 転送ルールは Cloudflare、送信元の登録は Gmail で管理する。

① 今回の方式の仕組み

  • 受信:Cloudflare Email Routing が MX を受けて転送する。メールは保管しない。
  • 保管・閲覧:Gmail。メールボックスの実体は Gmail になる。
  • 送信:Brevo が独自ドメインの DKIM 署名を付けて送る。

自前の SMTP サーバーも、VPS やレンタルサーバーも使わない。厳密には「独自ドメインの窓口を Gmail につなぐ」方式である。

① の注意点

  • Brevo は通知・配信向けのサービスである。
  • 送ったメールに開封トラッキングと配信停止ヘッダーが付く。

別の方式を考えるべき条件

  • 独立したメールボックスを他の人に渡したい場合は、② が適している。
  • 送信数が増えた場合や、トラッキングを避けたい場合は、送信だけを Amazon SES などに替えればよい。受信と Gmail はそのまま使える。

※ 費用と送信上限は目安。最新の値は各サービスで確認すること。