5.1さらうどん

@giginetの技術ブログ。ゲーム開発、iOS開発、その他いろいろ

はてなブログのエントリをCursorで執筆する

はてなブログをAI補完で書きたい!

ここ1〜2年、ブログ執筆の気概が出てきている。ちゃんとブログを書くために、はてなブログのProプランにも契約したし、ある程度継続できている。

とはいえ、はてなブログも老舗になってきており、Webエディタを使い続けることの制約が強くなってきた。一番大きな点は、近年話題のAIを使った執筆補助を受けることが難しいことだ。

AIを使ったドキュメンテーションライティングには興味があり、活用していくためにCursorを使ってブログ執筆ができる環境を構築してみた。

はてなブログの記事をローカルで管理する

まず、記事をCursor上で執筆するために、はてなブログの記事をファイルシステムと同期することにした。APIを用いて自分で開発しても良かったが、gimonfuという既存のツールでやりたいことが大分実現できた。

gimonfuは、はてなブログの記事をMarkdown形式としてローカルにダウンロードできるツールだ。pullで既存エントリーを全てダウンロードしてgit管理した後、newで新規エントリを作成し、pushで下書きに自動同期できる。

画像の扱いだけ少し煩雑で、現状ははてなブログに同期後、Web上のUIでフォトライフに画像を添付しそれをpullするのが良さそうだ。

ついでにGitHub Actionも設定して*1リポジトリの更新時に自動ではてなブログに同期するようにした。これで特に面倒なく簡単にローカルで記事を執筆する準備が整った。

ブログ用のAI Ruleを導入する

いよいよ、ブログ記事をCursorで執筆していく。Cursorには、プロジェクト全体に校正ルールをプロンプトとして与えることができる。しかし、このルールの定義方法が朝令暮改といった感じで、ベストプラクティスがコロコロ変わる。

あまりCursorを使いこなせているわけではないが、.cursorrulesを用いたルール指定はもう古いらしく、今回はProject Rulesを設定した。

.cursor/rules/guideline.mdc を作成し、そこになんとなくプロンプトを書いてみた。

# My Blog Article

このリポジトリは過去のブログエントリを格納するものです。過去のエントリを参考に文体を学習してください

## 挙動のルール

- すでに書いてある文章の修正だけに留め、書いてある文章を削除しないでください
- 漢字の誤用やtypoは指摘し、修正してください
- コードブロック(``` ```で囲まれた部分)の中身は変更しないでください。削除も禁止です。

## 文章ルール

- 一人称は僕
- 文末は常態で終わらせる(× です ○ だ)
- 表現は校正時に減らす
    - 「など」
    - 「のような」
- 文章はゆるくして、口語的な表現も許容する

このルールで意味があるんだろうか。現段階では洗練されていないが、今後、執筆を続けながら改善していこうと思う。

最近はNotepadsという機能を使う手法もあるようで、Cursor初心者なのでなんもわからん。

これはProject Rulesと異なり、チャットから能動的にルールを呼び出して適用できる機能のようだ。校正ルールだけここにまとめておき、最後に記事をチェックする際にNotepadsを呼び出す方法も効果的かもしれない。

最後に校正する

ここまで準備が整ったので、ガッと書いた後に校正してみる。漢字の使い方のミスなど、細かいところには使えそう。

実際に漢字のミスを教えてくれた

一方で、自分で狙って書いているゆるい文体を勝手に修正してしまったりするので、Ruleの調整は今後も必要そうだ。

わりとお節介

時代はAIライティング

実際どれぐらい執筆効率が上がるかは不明だが試してみようと思う。記事の大部分は、gimonfuがよくできているという話で終わりそうなので、この場を借りて作者にお礼をさせていただきたい。

また、今回自分の過去記事が参照できる環境が整ったことで、今後はこの記事のようなVibe Authoringみたいなことも実現できるかも。

*1:これもClineで書いた

分離式キーボードをErgodox EZからDygma Raise 2に乗り換えた

Ergodox EZ

Ergodox EZというキーボードを7年ぐらい使っている。自宅用と職場用で2台所持しており、長年使っていたのでもはや分離式キーボードしかまともに使えない体になっていた。

歴戦を経て年季が入っている

Ergodox EZは概ね最高なのだが、以下のポイントが微妙で

  • キー数が多すぎて実際こんなに使わない
  • キー配置が独特すぎる
    • ほかのキーボードが使いづらくなる
    • キーキャップの選択肢が乏しい
  • 端子がUSB mini-Bでケーブルの入手性が悪い*1

長年、乗り換え先を探していたが、しっくりしたものになかなか出会えず使い続けていた。そんな中、Dygmaという分割キーボードのシリーズを見つけた。

Dygma

分離式キーボードのDygmaはRaise 2とDefy、2種類のバリエーションがある。 Raise 2は一般的な60%キーボードの配置に近く、連結して使うこともできる。一方でDefyは、よりErgodoxに近くキー数が多く、独特の親指キーが特徴。基本スペックは大きく変わらなさそうなので、好みの問題になるだろう。価格も一緒。

詳しく知りたい場合は、公式がYouTubeチャンネルを出しており、おねーさんが茶番を交えてキーボードについていろいろ教えてくれる。

日本語情報はあまりないが、Defyについてはレビュー動画もある。

既製品だとほかにそれほど選択肢も無いので、あまり悩まずにRaise2を購入。Defyは独特なキー配置でさらにカスタマイズ性が下がりそうなのを懸念して、Raise2を選択した。

価格はカスタム無しで$369、オプションでtentとUnderglowをつけると$529だった。なかなか高価。ちなみに無線モデルもあるが、技適の関係で国内では使用できない。ご注意を。

届いた!

開封の儀

注文してから1週間弱で届いた。キャリーバッグやケーブル類なども一式ついていて高級感がある。僕は刻印モデルを購入したが、もちろん無刻印も選択できる。

QMKからのマイグレーション

今まで何個かキーボードを買っているが、基本的にはQMK Firmware互換で、カスタマイズ性には事欠かなかった。Dygmaシリーズは、QMKを使ったキープロファイリングではなく、専用のGUIアプリケーション『Bazecor』が付属している。

ここの移行が懸念事項だったが、このGUIアプリ、良くできていて、キー配置はもちろん大体の設定ができる。 QMKでは、あるキーをタップした場合と、ホールドした場合で挙動を変えるという設定ができたが、Bezecorでも同様にサポートしているし、ある程度のマクロも組めるようだ。少なくとも、僕が使っている範囲では秘伝のQMKから移行するにあたって、特に支障は無さそうだった。

例えば左crtlはタップしたときにtab、ホールドしたときにctrlになるという設定をそのまま継承できた

デフォルト値では、QMKとはホールドの判定の閾値が異なっていて、ctrlを打ちたい場面でtabが暴発して困ったりもしたが、なんと細かく閾値も設定できて解決した。至れり尽くせり。

設定はちゃんとファームウェアに書き込んでくれるので複数台で使うのも安心。レイヤーも10層持てるので、WindowsとMacで共有したいといったケースにも対応できるだろう。

キーキャップ

今回、キーボードを買い換えた理由の1つとして、キーキャップの選択肢を増やしたいのもあった。Ergodox EZはキャップを変えたい場合は、実質的にDSAプロファイルしか選択できず入手性も悪かった。Dygma Raise2は、スペースと親指を除けば、ほぼ60%キーボードの配置を踏襲しているので、キーキャップの選択肢も豊富になった。

というわけで、前から気になっていたセラミックキーキャップのCera Keyを購入した。

一般的な60%キーボードより、スペースバーの分だけ若干キー数が多いので、微妙にキーが足りなかった。具体的には1.5Uと1.75Uが1組足りない。そのため、その2つのキーのために結局もう1セット買った。キーボードはお金がかかる趣味だ。macOS用の追加キーを購入すると、コマンドキーやオプションキーも刻印にできる。お好みに併せてどうぞ。

ロープロファイルキーキャップのCherry MX化

Raise2の親指のキーはロープロファイルになっていて、形も独特なため、キーキャップを換装する場合は統一が難しい。スイッチもここだけKailhのロープロファイルスイッチになっている。

Kailh Chocスイッチとロープロファイルキーキャップ

しばらく運用していたところ、あまりにも不格好なのでどうにかならないか調べてみたところ、Low Profile Converterというものを発見した。

これを噛ませることで、Kailh ChocのキースイッチをCherry MXに変換することができて、全てのキーキャップを統一できた。

買っていて付けてなかったキーキャップも付けた

キースイッチ

今回は特に変更せずに、デフォルトのcliky軸であるKailh Box Whiteをそのまま使っている。もちろんホットスワップなので後で気が向いたら替えるかもしれない。

マイグレーションが大変だった

購入して3週間ぐらい使用して、ようやっと従来と同じ精度でキータイプができるようになってきた。なるべく元のキー配置を踏襲してカスタムしたが、互換性を保つには無理があり、大きくキー配置を見直して体に叩き込んだ。

キーボードは道楽

10万円以上かかったが、良い感じに刷新できて良かった。

購入前にいろいろ調べたが全然情報がなかったので、この記事が購入検討している方の役に立てば幸い。こういうのはDiscordで情報収集した方が良いのかも。

ついでにCherry MX to LEGO Converterなるものも買ったが、こちらはあまり活用できていない

*1:ちなみに最新のモデルではちゃんとType-C化しているようだ

Swift Evolutionについて質問応答するModel Context Protocolサーバーを立てた

最近、Model Context Protocol(MCP)驚き屋が世を騒がせている。興味のある技術なので、実際に何かサーバーを立ててみることにした。

いつも技術検証をする際のネタに最適なのが、Swift Evolutionを使うこと。ある程度正規化された自然言語の技術文書が大量に用意されていて、データベースとしてちょうど良い。

今回は、このSwift Evolutionを元に質問応答をしてくれるMCPサーバーを立ててみた。

MCP自体の解説はほかの記事を参照してほしい。たくさんの日本語記事も出てくるし、可能であればAnthropicの公式ドキュメントを読むのが一番良い。

ベクトルデータベースによるRAGの構築

Swift Evolutionのような、大量の自然言語の技術文書を効率よくデータベース化する手法として、ベクトルデータベースの利用に着目した。いろいろ調べてみたところ、ChromaDBというベクトルデータベースが良さそうだったので、これを使ってみることにした。

今回はこれといって特にやることはなく、単にMarkdownをChromaDBのAPIを使ってデータベースに格納するだけだった。クエリしやすいように、プロポーザルIDやタイトル、実装状況などをメタデータとして与えている。

マジで何もしていないが、ソースは以下に置いてある。

MCPサーバーの構築

次にMCPサーバーの構築。今回は自作のMCPサーバーを実装してみようと思っていた*1が、すでにchroma-mcpという既存のものがあったのでこれを使う。

Claude DesktopからのMCPサーバーへの接続は、chroma-mcpのREADMEにあるように、uvx経由でエントリーポイントを起動するだけであとは特にやることがない。

ClaudeにはProjectという概念があり、複数のチャットに共通のプロンプトを与えてまとめて管理できる。今回は以下のような簡単なプロンプトを与えている。

You answer the question about Swift Evolution.

You can use MCP to search all Swift Evolutions using `get_documents` or `query_documents` MCP tools.

Proposal Number `SE-XXXX` is provided as IDs for each document.

The result should be a document rather than a chat response.
Answer must be Japanese.

swift-evolution-mcp

このような手順でswift-evolution-mcpができた。早速動かしてみると、Region based Isolationのような、難しい概念についても日本語で説明してくれた。知識のカットオフもないため、最新のプロポーザルについてもバッチリ。

プロポーザルの要約のみならず、プロポーザルを元に架空の実装を試してもらうということもしてみた。例えば、SE-0450で実装されたPackage Traitsをベースに、テストライブラリをTraitで導入するというユースケース。

なんかそれっぽく動いているのがわかる。まだ試しに触ってみただけなので、今後実用に耐えうるかは試していきたい。

一方で、「Swift 6.1の新機能をまとめて」といったように、広範なプロポーザルを要約してもらうのはあまり精度が良くないようだ。Statusのような定型的な情報をメタデータとして与えてみたが、あまり改善せず。今回はプロポーザルIDをメタデータとして与えているので、「SE-0414について教えて」といった聞き方の方が精度高く回答してくれた印象。

リモートMCPの公開

現在の最大の使いづらさは、ユーザーがローカル環境にMCPサーバーを立てる必要があることだ。たしかに、ファイルシステムやチャットログの参照といった秘匿性の高いデータを扱う場合には適しているが、今回のようなパブリックデータのRAG化には、どこかのサーバーに接続するだけで勝手に使えるようになってほしい。

Anthropicが公開している今後のRoadmapでは、リモートMCPのサポートが予定されている。近い将来、これらの規格について整備されれば、デスクトップクライアントから簡単に複数のリモートMCPを利用できるようになるだろう。

現状で似たようなことをするには、mcp-remoteという、ローカルからリモートサーバーにProxyするだけのサーバーをローカルで動かす必要がある。今回のswift-evolution-mcpを公開するには、永続化したデータとchroma-mcpを動かすだけのコンテナをどっかにおいておいて、mcp-remoteから接続するだけで良さそう。

現状のRemote MCPの構築はCloudflareのブログで紹介されている。

そもそも、MCPをプロジェクトごとに持たせられなかったり、設定の煩雑さなどClaude DesktopなどのMCPクライアント側の使い勝手の悪さも目立つが、これらはそのうち改善していくだろう。

ここ1年の変化が早すぎる

実は、同様のコンセプトのものは2023年の11月頃に開発合宿の機会があったので試してみていた。当時はOpenAI GPT-3.5にLangChainを使ってMarkdownを流し込むだけ、という素朴な作りになっていて、大して実用的なものにはなっていなかった。

ここから、わずか1年半ほどしか経っていないが、GPT-3.5と現行のモデルの間には雲泥の差があるし、とりまく開発ツールも大きく変わったなあと感慨深い。(LangChainなんてもはや一瞬で廃れてしまった)

今回実装したのはトイプロジェクトだけど、ベクトルデータベースを使った自然言語のRAG化は応用の範囲が広そう。

*1:最近公式のSwift SDKも出た