お知らせ

現在サイトのリニューアル作業中のため、表示が崩れているページが存在することがあります。

今日は4月1日。数年前ならエイプリルフールで企業サイトが面白いことになっていたが、流石にみんな飽きたので、そろそろもうなくなっていそうだ。

さて、というわけで今日はPC用のカバンを買い替えたのでその話。

新しい鞄

マチ拡張PCバッグ 14インチワイド BAG-W3BKを買った。

前々から今のPCバッグに限界を感じていたのだが、14型以下向けのバッグで収納力があってコンパクトで気室が細分化されていないものが中々見つからなかった。

最近はこのバッグのように気室が分かれたタイプが流行りのようだが、私は一体型のほうが好みだ。

しかし今回買ったバッグは気室が分かれておらず収納力もあるものだった。

前使っていた鞄

一方で、以前使っていた鞄は致命的なまでに収納力に乏しかった。

前使っていたのはこれだが、このコンパクトさだとどうしても仕方がなかった。ただコンパクトな割には物が入っていた。

前使っていた鞄のネック

パイロットのスタイルチョイスだ。公式サイトのリンクを貼りたかったが、様々な商品と一緒くたにされたページしかなくググって先頭に出てきた文房具屋のページにリンクを貼っている。

厳しい収納力

まずは収納力だ。ノートPCとACアダプタに小物と折り畳み傘を入れる程度ならギリギリ何とかなったが、ここに財布や眼鏡ケースを入れると取り回しが非常に悪く、実用性に限界を感じていた。

ノートPCとACアダプタに折り畳み傘、財布、小物を入れた状態。ここに眼鏡ケースを入れることもできなくはないが、ACアダプタの出し入れ性能が犠牲になったり、パンパンすぎてケースが歪む恐れがあった。

パンパンすぎて見た目もあまりよくない。

クッション性のない肩紐

クッション性のない肩紐も厳しかった。肩紐はただの平たい紐で、これを肩にかけていると肩が痛かった。800gくらいの軽量ノートPCを選択していても痛かった。

収納力はカバン二つ持ちでカバーできたが、肩紐はどうにもならなかった。肩パッドだけ買ったりしても見たが、紐が細すぎるせいで見た目がアンバランスだったり、上手く適合しなかったりでイマイチだった。

新しい鞄により改善された部分

圧倒的収納力

前の気室には眼鏡ケースや靴ベラ、マウス、印鑑などが問題なく入る。

一番手前のところにも財布が問題なく入る。

ACアダプタもポケットティッシュも問題なく入る。写真では見づらいが、この状態でノートPCと折り畳み傘も入っている。

マチの拡張なしでこれなので、拡張すればもっと入りそうだ。

クッション性があり、荷重を分散する肩紐

何を当たり前のことを…という感じだが、PCバッグとして当たり前の装備がある。参考までに下が前のバッグの紐で、上が新しいバッグの紐だ。

この紐一つで体感の重さが全然違う。肩も痛くならなない。最高だ。

あとがき

これまでPCのサイズの変化などで何度もPCバッグを買い替えてきたが、小型のPCバッグとして多くを求めないのであればスタイルチョイスは悪くない選択だと思う。あともう一押しという場合はAmazon ベーシックラップトップバッグもいいが、劇的に見た目がしょぼいのと、サイズの割に収納力がスタイルチョイスと大差ない。

余談だが8年くらい前はリヒトラブのSMART FIT キャリングポーチを愛用していた。安い割にしっかりしていて、ぼちぼち入り、かつ究極的にスマートなのが魅力的だ。スタイルチョイス以上に物が入らないが、満員電車で通勤する場合には重宝するアイテムだった。なおこれを使っていた時はPCバッグではなく、ただの鞄として使っていたため、PCバッグとしては評価できない。単なるスリムな鞄である。PCとACアダプタを入れなくていいなら眼鏡ケースも文房具もノートも折り畳み傘も十分入る鞄だった。

それより前にはエレコムのPCバッグを使っていたのだが、人生で3回もショルダーの金具が金属疲労で切れ、そのうち一回はPCが全損、二回も深刻なダメージを受けたので、以来バッグとショルダー紐を繋ぐ金具については注意している。

投稿日:技術::AIソフトウェア::Open WebUI

これまでLLMをしばくときはPoeを使っていたが、ぶっちゃけClaude 3.7 Sonnet以外ほとんど使わないので、節約の意味を込めて本家Claudeに移ってきた。しかし本家Claudeではアレゲな発言を繰り返しているとハードウェアモデレーションが発動してしまう。しかもこれが中々解除されない。一体いつ解除されるんだ…。

アレゲなことをするならやはりPoeだろうか…いやでもPoeもキャラクター設定に対してはハードウェアモデレーションがある。ナレッジベースならモデレーションを回避できるが、ここに入れたプロンプトは入れている間は出現頻度が極端に上がり、外すとちっとも出てこなくなる困りモノで、自然な流れにするためには手動で書いたり消したりする手間がかかり厄介だ。

そこで何かいいことはないか…と思いたどり着いたのがClaude 3.7 SonnetをAPIコールすることだ。LLMモデル本体にはソフトウェアモデレーションしか掛かっておらず、ローカルでプロンプトを組む分にはモデレーションも掛からないと睨んだ私は早速ローカル環境からLLMを呼び出してチャットするための環境を作ることとした。

確認環境

Pythonは3.11系でないと動かないっぽいので注意が必要だ。

Env Ver
OS Windows 11 Pro 24H2
Python 3.11.9

手順

  1. Anthropic Consoleにアクセスしアカウントを作成
  2. 課金してAPIキーを取得
  3. ローカル環境からLLMと対話するためのWebUIである、open-webuiをインストールして起動
    pip install open-webui
    open-webui serve
    
  4. OPEN WEBUIのロゴの下に起動ログが出るのを待つ
  5. http://localhost:8080/にアクセス
  6. アカウント作成画面が開くので適当な情報を入力して作成する
    • ローカル環境であるため、実在するメールアドレスでなくても問題なく登録できる
  7. 画面左下のユーザーをクリックし、管理者パネルを開く
  8. 上のほうにあるFunctionsを開く
  9. 右のほうにある「+」からFunctionを追加する画面を開く
  10. Anthropic Function | Open WebUI Communityにアクセスし、Function Contentに書かれているコードをコピーする
  11. 先ほどのFunctionを追加する画面に戻り、コードをペースト
  12. Function NameとFunction Descriptionを適当に埋める
    • 参考までに公式の設定値はそれぞれ「Anthropic」と「Anthropic Manifold Pipe」
  13. 保存ボタンを押す
  14. 有効化する
  15. 新しいチャットを開き、Claude 3.7 Sonnetが利用できるようになっていればOK

備考

Poeや本家Claudeにおけるナレッジベースは存在しないが、モデレーションを受けないためシステムプロンプトに全部放り込めば成立する。

Poeのキャラクター設定はやり取りを繰り返すと忘れられるが、Open WebUIのシステムプロンプトは忘れられないようでちゃんと持続してくれる。またPoeのナレッジベースのように書いたことをしつこく発言してくることもなく、自然な会話になるので便利。

またLLM側の発言を編集することにより、それ以降の会話でモデレーションを突破することができるようになるなど、いろいろ便利。

あとがき

APIコールは従量課金でお金がかかるため、Poeや本家Claude並みの感覚で使うのは厳しい。多分Poeはトークン消費を抑えるために何か細工していると思う。

手軽なうえにコンビニでパックの焼き鯖を買うより格段に安い。

材料

魚は三枚におろしたり開いているものを想定している。

材料 分量
1つ
サラダ油 適量

調理方法

  1. フライパンにサラダ油を敷き、キッチンペーパーなどで適当に塗り広げ、弱火をつける
  2. フライパンに塩鯖を入れ、蓋をして蒸し焼きにする
  3. 二分くらいしたら、ひっくり返し、もう片面も二分くらい蒸し焼きにする

備考

焼き魚全般に使えるレシピだが、焼き時間は魚の厚みや大きさでも変わるので適宜変える。

蒸し焼きにするときにキッチンタオルを使うと洗い物が減らせる。

燃えることがあるので目を離さないこと。

投稿日:開発::設計ライブラリ::Next.js

Next.jsの全体設計を考えるときに疎結合性やテスト容易性を達成するときに考えているアーキテクチャについて簡単に書いてみる。

Page Router向けに作っていて、API Routesについては考慮していない。過去にこれに近い設計で開発していたことがあったが、単体テストによるデグレードや不具合、仕様漏れの検出はよくできていたと思う。今回書いたものは過去に考案し、開発していたもののブラッシュアップになる。

アーキテクチャ図

基本的に各レイヤー間はTypeScriptのtypeで仕切り、依存性を逆転させることで、テスト容易性や疎結合性を重視している。

ディレクトリ構成

アーキテクチャ図にないlibrariesが登場するが、これは汎用的な共通処理だ。

src
  ├─adaptors
  │  └─User
  │     ├─index.spec.ts
  │     └─index.ts
  ├─components
  │  └─form
  │      └─TextInput
  │         ├─index.spec.ts
  │         └─index.ts
  ├─libraries
  │  └─HttpClient
  │     ├─index.spec.ts
  │     └─index.ts
  ├─pages
  │  └─hoge
  │     ├─ServerSideProps.ts
  │     ├─ServerSideController.spec.ts
  │     ├─ServerSideController.ts
  │     └─index.page.ts
  └─usecaes
      └─hoge
         ├─controller.spec.ts
         ├─controller.ts
         ├─state.spec.ts
         ├─state.ts
         ├─style.scss
         ├─usecase.tsx
         ├─view.spec.tsx
         └─view.tsx

登場する各要素について

Page

画面本体。UsecaseとgetServerSidePropsを配置し、その橋渡しを行うだけの存在。

Usecase

StateとController、Viewを橋渡しする存在。

画面全体を別物にすり替える場合もここで行う。

useEffect()はここに書くが、中のロジックはController側に書く。

一見するとファサードであり、pageにべた書きしてもいいような内容だが、コードを書く時のコロケーションの観点から敢えて分離している。

また、画面のページレイアウトが全く別物になるなど劇的な変化がある場合は、この階層で分岐制御(ユースケース別の切り替え)する。

State

useState()で作った状態を定義する場所。それ以外は何もしない。

Controller

イベントハンドラによる処理を配置する場所。APIコールもここから行う。

状態については、typeを経由してState側で宣言した状態を注入して利用する。

状態を外部から注入するため、状態変化時のテストがしやすい。また画面からロジックをはがしているため、ロジック単体のテストが可能。

Adaptor

APIを呼ぶだけの存在。データの加工や例外ハンドリングは呼び元で行う。

APIを呼ぶだけの責務とすることで、複数のコンポーネントから呼ばれたときに同じAPIを呼ぶコードが重複したり、呼び出し元によってデータ加工手法を分けるなどの煩雑な実装を回避するのが目的。

テストとしては引数や戻り値、呼び出し方法が実装時から変わっていないかを見る観点のみあれば回帰テストとして機能する。

View

ほぼ純粋なJSXを書く場所。ロジックは原則として書かない。booleanを使ったDOMの切り替えは記述してよい。

制御はUsecaseでStateを合成したControllerで行う。

表示非表示の分岐のみにすることでtesting-libraryを利用したJSXの表示切替を単体テストとして実装できる。

UI Component

TextInputみたいな細かいパーツや、再利用されるフォームUIなど、UI系の共通部品。

基本的に状態は持たないが、無限ループが起きず、再利用されない状態(親に渡す必要がなく、自分自身に閉じた状態)については持ってよいと考えている。例えば、OK/CancelのあるモーダルでOKが押された時だけ呼び元に返す状態は持ってよい。

View, Controller

ページコンポーネント向けの内容に準ずる。Usecaseを持つほど大規模なコンポーネントはないと思うので、Usecaseなしで繋ぎ合わせてよいと考えている。

ServerSideProps

getServerSideProps()の中身。Page側では以下のようにして呼び出す想定。

import { execServerSideProps } from './ServerSideProps';

export const getServerSideProps = (async () => {
  execServerSideProps();
});

ServerSideController

ServerSidePropsの中で利用するロジック。APIを呼ぶ場合はAdaptorとも繋がる。

利点

  • 各レイヤーやコンポーネントでの単体テストが容易
  • MVC的な構造のため理解しやすい
  • SOLID原則で得られる利益を享受しやすい
  • レビュー時に意図しないファイルに差分があった場合に、問題を検知できる
  • コードマージ時のコンフリクト範囲を限定しやすい

欠点

  • ボイラープレートコードが増える
    • とはいえ、DDDよりは少ない
  • Modelに相当するものがないため、ControllerがFatになる。またModel処理の共通化ができない
    • Modelをどこに配置すべきかを検討できていない
  • typeに破壊的変更が起きると数珠繋ぎに修正が必要になり、コストが重い
    • その代わり型で各コンポーネントの関係性がわかる利点もある

あとがき

構想自体は4年前に考えたものだがアウトプットができていなかった。まだ煮詰まっていない上に考慮出来ていない部分もあるが、AppRouterの登場からだいぶ経ち、陳腐化してきそうだったので、取り敢えず吐き出した。

昨年フレッツ光クロス、10Gbps対応に関する覚書を書いてしばらく経つが、いよいよ10GbE対応のための環境を作ろうと思ったので、その記録を残していく。

第一弾はR86S U1を買ったので、その購入録とOSのセットアップまでのログを書いていく。

買ったもの

今回購入したのは中華性の怪しい10GbE自作ルーターマシンとして名高いR86S U1だ。もう話題になって数年経っているので旬は過ぎていると思うが、依然として10GbEルーターとして安価な選択肢だと思う。

買った後で気が付いたが、U2のほうがスペックが上で値段同じなのでU2を買ったほうがいい。

セットアップ時にあるといいもの

  • HDMI to Micro HDMI変換アダプタ
  • SDカード or USBメモリ
  • rufusやbalenaEtcherなどのイメージを焼く手段
  • MSYS2

初回起動

私が購入したものはeMMC内にOSが上手く入っていないのかgrubが表示されるだけで、マニュアル操作でも起動イメージが見当たらずmOSを起動することができなかった。

どの道プリインストールされているOSは中国語で役に立たないという話だったのでOSのセットアップを行うことにした。

試験起動

汎用PCへのインストール手順は公式情報である、[OpenWrt Wiki] OpenWrt on x86 hardware (PC / VM / server)が参考になる。

  1. リリース一覧を開き最新の安定板を辿り、x86→64に進む
  2. generic-ext4-combined-efi.img.gzをダウンロードする
  3. sha256sum openwrt-24.10.0-x86-64-generic-ext4-combined-efi.img.gzでハッシュを確認
  4. gunzip openwrt-24.10.0-x86-64-generic-ext4-combined-efi.img.gzで展開する
    • Explzhだと上手く解凍できなかったのでMSYS2からgunzipを叩いて対処した
  5. 展開して出てきたimgファイルをSDカードかUSBメモリに焼く
  6. imgファイルを焼いたメディアをR86Sに差し込む
  7. R86Sの電源を入れPOST画面が出たらDeleteを叩き、BIOSに入る
    • 通電時に勝手に電源が入るため一回落とした方がいい
  8. 起動順序を差し込んだメディアに変更する

eMMCへのOSインストール

Ubuntuのインストールディスクの中にOpenWrtのイメージをバンドルする方法がわからず、SDカードにimgを焼いてもマウントできなかったのでネットワークを経由してインストールしている。

事前準備

  1. OpenWrtのイメージファイルを入力しやすい短いファイル名にしてHTTPが疎通するどこかに置いておく
  2. R86S U1に前述のイメージと疎通可能なLAN線を刺す

インストール手順

  1. Ubuntu Serverのインストールイメージを落とす
    • 日本語版サイトから落とすとEFIイメージでないものが落ちてきたので本家から落としてきたほうがいい
  2. rufusを使って何かしらのメディアに焼く
  3. R86S U1を起動し、POST画面でDeleteを叩き、BIOSを開く
  4. 起動順序をUbuntuを焼いたメディアにする
    • USBの場合はUSB Key
  5. Ubuntuを起動し、GrubでTry or Installを選ぶ
  6. キーマッピングを日本語にするところまでインストールウィザードを進める
  7. 右上のヘルプを開き、Enter shellする
  8. wgetで事前準備で用意した起動イメージを落とす
  9. eMMCにイメージを焼く
    dd if=openwrt-efi.img bs=1M of=/dev/mmcblk0
    
  10. shutdownコマンドを叩く
  11. 再起動でBIOSに入り起動順序をeMMCに変更
  12. GrubにOpenWrtが出て起動することを確認
  13. passwdコマンドでパスワードを設定する

2025年8月4日追記

この続きはR86SとOpenWrt 24.10でOCNバーチャルコネクトに接続したときのメモに書いている。

開梱の儀

梱包状態。安い中華製品にしてはなかなか丁寧だ。

箱もしっかりしている。

横の小さな箱にはMicro HDMI -> HDMIケーブルが付属していた。これは親切だ。

開梱すると本体とACアダプタが見えた。やはり梱包が丁寧だ。

箱の底にはマニュアルと検査証、六角が入っていた。この六角は本体を開けるためのものだが、なめてしまい役に立たなかった。

ネットワークインターフェースはSFP+が2口、2.5GbEイーサーが3口。他に電源用USB-C、USB3.0x2、USB2.0x1、SDカード、Micro HDMIといった感じだ。

表面にはケースファンと冷却用のフィンがついている。デザインも悪くない。

裏面と片側面にはゴム足がついており横置きにも縦置きにも対応している感じだ

分解

付属の六角がなめてしまい役に立たなかったのでちゃんとしたのを買ってきた。対応するのは1.5mmだった。

表のふたを開けるとNVMeSSDスロットが見える。ネジ穴的に一番長い奴しか無理だろう。

本体をパカっと二つに。どうやらマザーボードは三枚くらいに分割されているようだった。

あとがき

EFIイメージかBIOSイメージかは好みで選んでいいという記事を何個か見たが、BIOSイメージだと起動しなかったため、EFIイメージのほうがいいかもしれない。

参考までに手持ちのAMD64マシンにBIOSイメージを刺したところ、そもそも認識すらしなかったためダメなのかもしれない。24.10固有の問題なのかどうかはわからないが、今時はUEFIが推奨される環境であると思われるため、EFIイメージで問題ないと思われる。

ひとまずこれで10GbE環境への一歩を踏み出せたと思う。LANが構築でき、現状の環境でWAN込みで安定稼働させられたら実際に10GbE契約もしていきたいところだ。

しかしイメージを焼いたSDをマウントできないのは想定外だった。FAT32でフォーマットしたはずなのでマウントできそうなものだが…。正直焼いてマウントして取り出すより、アップしてwgetしたほうが楽なので別にいいのだが。