NotebookLMでポッドキャスト生成してMacWhisperで文字起こししながら聴くのが英語のリスニング訓練に良い

最近「生成AIで英語を効率よく勉強するには」というnote記事で、自分が興味のある題材の教材を手に入れるために生成AIを活用するノウハウが紹介されていた。

note.com

これには共感できて、私も「海外ドラマを使って英語学習しよう!」というメソッドに乗って実践しては「ドラマ興味ねぇ〜」と挫折を繰り返すことが多かった(ディズニーの英語と映画アラジンがライブラリに眠っている)。自分の好きなテーマで教材を作ればモチベーションが保ちやすいのはそのとうりだと思う。

私の場合、読み書きよりもリスニングをもっと鍛えたいという気持ちが強い。理由はソフトウェア技術関連の動画やポットキャスト(カンファレンスの録画とかテックインフルエンサーの配信とか)の音声を翻訳を挟まずに理解できるようになりたいから。即時性の高い一次情報が英語かつ音声でしか入手できないことが結構ある。以前感想を書いたOSSのドキュメンタリー番組とか。

laiso.hatenablog.com

では自分の興味のあるジャンルの動画を片っ端から見まくればいいのではないかとやってみたものの聞き取りやすい動画とそうでない動画があることに気づいた。これは発音の訛りや音声変化にまつわる部分と、カジュアルな口語の語彙や文の違い(つまりテキストになっても理解できない)によって起こっているのだと理解した。例えば目的から逸れるが、非ネイティブでかつ日本訛りの英語は発音についていけて文がシンプルなので聞き取りやすい。なので自分のレベルで聞き取りやすい動画教材を探す旅が始まってしまう。しかしちょうどいい教材が自分の興味に沿う可能性は低い。

そこで活用できるのが Google の NotebookLM。これは研究・ノート作成ツールのノリでウェブやファイルのソースを放り込んでおくとRAGのように使えたりテキストを生成してくれる。先日正式アップデートがされて有料プランなど充実したので突然サ終することはなさそう。

laiso.hatenablog.com

しかし、米国ではどうもテキスト生成よりも「ポッドキャスト生成機能」がウケているようだ*1。この機能は登録したソースから15分くらいの男女の英会話を自動生成してくれるもので*2、指示次第で「簡単な語彙を使って」とか「10歳児でもわかるように説明して」みたいに自由にカスタマイズできる。要は、好みのトピックを音声にしてくれるAIラジオが手に入る*3。面白い使い方としては日本語のソースを登録して英語のポッドキャストを生成するユーザーもいるようだ。

*(NoteBookLMの様子。日本語で使うとCSSを完全に理解してるのがちょっと面白い)

例として以下にブログ記事「NotebookLM goes global with Slides support and better ways to fact-check」をポッドキャスト生成したサンプルをあげておくので聞いてみてほしい。

この機能でノイズがほとんどない発音と語彙がフラットな英語音声を入手できる。ノイズが少なければ文字起こしも精度が出る。そういうときに役立つのが「MacWhisper」。正確にはAppストア版の「Whisper Transcription」や、Gumroadでライセンス販売されてる「MacWhisper」と呼ばれる2つのアプリがあるが、どちらも同じアプリで、最小の文字起こしモデルならどちらも無料で使える*4

goodsnooze.gumroad.com

この MacWhisperをリスニング訓練のUIとして活用できる。音声を再生しながら同時に文字起こしを表示してくれるし、セグメント(発言者)ごとにUIが分割されてるので、どこを話してるか一目瞭然。さらに、翻訳も手軽に実現できて、DeepLアプリを別途インストールして⌘+C+Cのショートカットで一行だけ訳したり、macOS標準の辞書機能で⌘+Ctrl+Dでポップアップ表示させて意味を調べられる。再生速度を1.0以下に落とせるので、聞き取りづらい箇所をゆっくり再生しながら「このフレーズってこう発音してるのか」とチェックできる(自分で発音できる言葉は聞き取れる)。

こんな感じで、NotebookLMのポッドキャスト生成→MacWhisperの文字起こし→DeepLやDictionaryで補助、という流れを作れば、読み書き中心だった生成AIの活用法がリスニング寄りに広がる。ドラマ英会話は視覚情報があるので利点はあるが、このポッドキャスト生成機能は個人的に重宝している。

AI翻訳がリアルタイム化することで、もう英語を勉強する必要がなくなると考える人もいるかもしれない。しかし、先のnote記事で示されたように、要不要がゼロイチで決まるわけではなく実際にはグラデーションがある。AI翻訳の進化は単に言語バリアを取り除くだけでなく、多様な言語の情報にアクセスしやすくすることで一次情報に触れる機会を増やしてくれる。むしろ望んでいる人にとっては外国語が必要な場面が今後増えてくるというのが個人の見解だ。実際にウェブフロントエンドのOSSでは中国語ドキュメントや企業ブログが一次情報になっているものがすでにある。

それに外国語を理解できることは人生を楽しむ手段としても価値があるだろう。その良い例が、コミックやアニメなどのオタクコンテンツを楽しむために日本語を学ぼうとする人たちの強いモチベーションだ。それはAIに奪われても良いことはない。

AI翻訳が進化しても、直接的に外国語を学ぶことで得られる深い理解や喜びは引き続き重要なものとなるだろうと思っているので私は生涯続ける意思を持っている。他の人は知らんけど。その過程からできるだけストレスを取り除きたいというのが本記事の主旨だ。

*1:グーグルの「NotebookLM」を使ったAIポッドキャストが注目されている | WIRED.jp

*2:注意点として日本語対応したら音声も日本語で生成されるようになってしまうかもしれない。そのままの君でいて

*3:まだ試してないが最近のアップデートで会話に参加してこっちの音声を聞きとってくれるようになったらしい https://blog.google/technology/google-labs/notebooklm-new-features-december-2024/

*4:Windowsニキの人は良い文字起こしアプリがあったら教えてほしい。

MCPクライアントアプリを作ってコマンドラインでエージェントを走らせよう

なぜ MCP クライアント側開発の解説が必要か

Model Context Protocol(MCP) は、さまざまな AI アプリケーションや LLM(Large Language Model)を外部ツール・リソース・ワークフローに接続するためのプロトコルです。これはサーバーとクライアントの 2 つの側面があるのですが、現在 Web 検索などで見つかる情報は主に「MCPサーバーの呼び出し方」と「(呼び出される)MCPサーバーの作り方」というテーマが中心になっています。しかし実際に MCP サーバーを呼び出せるのは、Claude アプリや Zed などのエディタ*1、VS Code 拡張の Cline*2 といった、すでにクライアント(ホストアプリケーション)を実装している限られたアプリケーションに限られます。
そのため、サーバーを実装するだけでは、現状対応しているアプリ(多くはCalaudeアプリ)を活用することにとどまります。MCPサーバー連携機能を自分たちのアプリへ実装し、ユーザーへ提供する方法はあまり知られていません。私はその「強化される側」であるクライアント側を独自に作りたいと考えており、「どうやってサーバーを利用する新しいアプリを開発するのか」という方法について知る必要がありました。

www.anthropic.com

MCP クライアントアプリを作るには?

MCP では標準出力(Stdio)や SSE(Server-Sent Events)を使った JSON-RPC メッセージングによって外部プログラムと通信します。現在はローカル環境での利用が中心ですが、今後はリモート呼び出しにも対応する予定です*3。SDK(ライブラリ)としてはオフィシャルの Python 版、もしくは TypeScript 版が存在します。Python 版の方が現状では機能面の充実度が高い傾向にあります。しかしブラウザやNext.jsアプリの裏側から使うケースを見込んで個人的にはTypeScript 版を選択しています。

import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
import { CallToolRequestSchema } from "@modelcontextprotocol/sdk/types.js";

// クライアントの設定
const client = new Client(
  {
    name: "example-client",
    version: "1.0.0",
  },
  {
    capabilities: {
      tools: {}, // ツールを使用するためのcapabilityを設定
    },
  }
);

// stdioトランスポートの設定
const transport = new StdioClientTransport({
  command: "./path/to/your/mcp-server", // MCPサーバーの実行パス
});

async function main() {
    // クライアントをサーバーに接続
    await client.connect(transport);
    console.log("Connected to MCP server");

  // ツールを呼び出す
  try {
    const callToolResult = await client.request(
      {
        method: "tools/call",
        params: {
          name: "your-tool-name", // 呼び出すツール名
          arguments: {
            // ツールに渡す引数
            input1: "value1",
            input2: 123,
          },
        },
      },
      CallToolRequestSchema // 型定義スキーマ
    );

    console.log("Tool call result:", callToolResult);
    
  } catch (error) {
    console.error("Error calling tool:", error);
  } finally {
    // クライアントを閉じる
    await client.close();
  }
}

github.com

MCP の基本的な概念としては、大きく ResourcesToolsPromptsSamplingRoots に分かれています。はじめて実装する場合は、とくに Tools の使い方を理解するのがおすすめです。たとえば MCP サーバーからツール一覧を取得し、必要なツールを呼び出すといった流れが基本になります。

クライアント側での具体的な手順としては、まずアプリケーション内に接続先サーバー情報を埋め込む(または設定ファイルで指定する)などして MCP サーバーを登録し、SDKのClientモジュールを準備したうえで、ツール一覧を取得します。取得したツール一覧を LLM 側に教える際は、対応する LLM の仕様に合わせた形式でツールの名前や機能をプロンプトに埋め込みます。モデルのプロバイダによってAPI仕様が違うので、ここでは、Anthropic の API を前提に話を進めます。

docs.anthropic.com

Anthropic の APIにテキスト指示を送信した際、レスポンスとして "TOOL_USE" が返ってくるケースがあります。これは「指定されたツールを使って処理するように」という合図なので、実際にアプリの内部で SDKを使ってMCP サーバーのツールを呼び出し、得られた結果を再度 LLM に返すという流れになります。
このようにしてクライアント側を実装することで、MCP サーバーと連携した機能を新しく作成し、LLM を活用した高度な処理をアプリ内で自在に行えるようになります。

クライアントアプリのアーキテクチャ

どんなクライアントアプリがつくれるか?

MCP のクライアント実装は、さまざまな形で応用できます。たとえば、既存のウェブアプリに組み込んだチャット機能が外部の MCP サーバーを呼び出せるようにすれば、サーバー上のツールを使って高度なデータ処理を行ったり、FAQ を自動生成したりすることも可能になります。また、VS Code だけでなく、別のエディタ向けにプラグインを開発して MCP を呼び出す仕組みを組み込むことも考えられます。さらに、Python や JavaScript(Electron など)を使ってデスクトップアプリを作り、ローカル環境で MCP サーバーと連携させることで、専用の生産性向上ツールやコマンドラインユーティリティを開発するといった可能性も広がるでしょう。

MCPの公式サイトには標準で提供されているMCPサーバーのリストやクライアントアプリを作る開発者向けの情報があります。

modelcontextprotocol.io

ミニコーディングエージェントを作ってみた

MCP におけるファイルシステム(Filesystem)サーバー*4を組み込んで、特定ディレクトリに対する指示(タスク)を実行するコマンドラインツールを作成しました。これは Cline のようなエージェントをヘッドレスにサーバー上で動かしたり、Devin のようにサービス化したりするといったアイデアを目標としています。開発工程については Zenn で複数回にわたり記事としてまとめてありますので、興味があればぜひ参考にしてください。

  1. TypeScriptでMCPサーバーのtool呼び出しをする
  2. MCPサーバーのtool呼び出しをLLMにトリガーしてもらう
  3. MCPを使って160行のTypeScriptでミニコーディングエージェントを作る

リポジトリはこちらです。

github.com

なお、実際に動かす際には API の利用料金がかかります。金銭的な負担が気になる場合は実行をせず、手順だけを理解してMCP クライアントの作り方を学べます。これを参考に、皆さま独自のクライアントを開発していただければと思います。

ClineとAIコーディングツールの現状

はじめに

近年、AIを活用したコーディングツールが急速に発展し、プログラマーの生産性向上や開発プロセスの効率化に大きな影響を与えつつあります。これらのツールは、コード補完、チャットアシスタント、コーディングエージェントなど、様々な形態で提供されており、プログラマーの作業をサポートしています。

その中でも、オープンソースのコーディングエージェントである「Cline」は、独特のポジションと活発なコミュニティによって注目を集めています。 本記事では、Clineを中心に、現在のAIコーディングツールの動向を探ります。Clineの特徴や利点、そして他のツールとの比較を通じて、AIコーディングツールの現状について考察します。また、Clineのアーキテクチャや実用面、コミュニティの動向についても解説します。

AIコーディングツールは、特に個人のプログラミングの世界に大きな変革をもたらしつつあります。本記事が、読者の皆様にとって、AIコーディングツールの理解を深め、活用するための一助となれば幸いです。

AIコーディングツールの分類

AIコーディングツールには3つのカテゴリーがあります。

  1. コード補完ツール
  2. チャットアシスタント
  3. コーディングエージェント

世間のプログラマーが「プログラミングにCopilotを使っています」という時は、GitHub Copilotのコード補完機能を指すことが多いです。しかし、AIコーディングツールはコード補完ツールだけではありません。チャットアシスタントやコーディングエージェントもAIコーディングツールの一部です。

以下にそれぞれのカテゴリーの特徴を説明します。

カテゴリー 代表的なツール 特徴
コード補完ツール Copilot、Cursor TabContinueCody ユーザーが書いているコードの続きをAIが提案する。
チャットアシスタント Copilot Chat、Cursor Chat、Continue、Cody AIがコーディングに関する質問や説明に回答する。ユーザーは質問にソースコードを付与できる。オプション機能として、コードが提案されたらユーザーは結果を適用できる。
コーディングエージェント Cline、Cursor Composer、Copilot Edits、Copilot Workspace*1 ユーザーの指示に従ってAIが自動でコーディングを実行する。変更・実行内容が提案され、ユーザーが許可する。

補足するとチャットアシスタントについては、エディタの外でChatGPTClaudeのユーザーインターフェースを使っている人もいます。典型的な作業フローとしては、ソースコードをコピペしてAIに質問をし、AIからの回答を再度コピペしてエディタのコードに貼り付けます。これらの操作をエディタ内で完結させたものが、チャットアシスタント型のツールです。

一方コーディングエージェント型のツールはユーザーがメッセージを入力するインターフェイスを持つのは同様ですが、返答と一緒にソースコードを追加・編集するためのアクションも返します。

コーディングエージェントの中でも著者が最近とくに注目しているのは、Clineです。ClineはVS Codeの拡張機能として提供されており、オープンソースで開発されています。

Clineの話をする前に、まずはコーディングエージェントの利用イメージと他の代表的なAIコーディングツールの現状を整理しておきましょう。

コーディングエージェントの利用イメージ

以下はCopilot Editsを利用する時の典型的な動作フローです。

まず右下のテキスト入力欄より「TODOアプリのAPIクライアントを設計してください」と送信しました。

Copilotは「APIクライアントを追加し、Todoの追加と削除をサーバーサイドで行うように変更します。」と返答し、現在編集しているpage.tsxの変更差分を表示します。それをAcceptボタンを押して適用します。

さらに「APIを実装してください。データはメモリ上に保持します。」と指示しました。Copilotは新規にpages/api/todos.tsというファイルを追加して中身を記述します。

このように指示→変更を繰り返します。変更内容を修正して欲しい場合は、その旨をCopilotへ伝えます。変更の補足情報として別のファイルを参照して欲しい時などは、メッセージ入力欄から追加できます。

公式のドキュメントでさらに詳しく説明されています。

code.visualstudio.com

Cursor

www.cursor.com

CursorはAIコーディング専用のエディタです。VS Codeのフォークであり、Cursorのサーバーに独自にトレーニングしたモデルを持っています。加えて、主要なOpenAIやAnthropicなどのモデルプロバイダーのAPIキーを設定して使うこともできます。

先進的な取り組みが多く、著者が初めてエディタ上でコーディングエージェントを実現しているのを見つけたのもCursor Composerでした。最近では、Shadow Workspaceという隠しElectronウィンドウを用いて、並列にコード編集できる機能を検討しているようです。

独立したソフトウェアサービスなので、サインアップして有料プランにアップグレードすると利用回数が増えるという料金体系になっています。著者が一時期使ってみた感じでは、月20ドルのプランでは利用回数が足りなかったので、さらに+20ドルで追加購入して合計40ドル支払っていました。試用や利用回数が少なければ無料プランでも十分だと思います。

ユーザーの数も多く、オーム社から以下の解説書も出ていたので購入しました。

Copilot Edits

code.visualstudio.com

Copilot Editsは、VS Code拡張機能のCopilot Chatの一部で、GitHub公式のツールです。

GitHubのサーバーで管理しているGPT-4oClaudeのモデルを使用します。他のコーディングエージェントの中では機能が最も簡素で、まだプレビュー版です。

GitHubのBusinessプランに加入しているので、現状著者が一番使っているのがCopilot Editsです。

実際に利用してみた感じでは、Copilot Editsは保守的な変更を提案してきます。また、Copilotのコード補完との精度にもギャップがあります。

Continue、Cody

www.continue.dev

Continueは、VS Codeの拡張機能であり、JetBrains製IDEにも対応しています。エディタ拡張部分がオープンソースとなっています。

sourcegraph.com

CodyもVS Codeの拡張機能として提供されていて、Sourcegraphによって開発されました。

この2つはコード補完とチャットアシスタントであり、コーディングエージェントではありません。なのでよく候補に上がるツールとして名前を紹介するだけに留めます。

コーディングエージェントはどの程度使い物になるのか?

著者自身は2024年の中頃にCursor Proをひと月利用して、その後Copilot Editsが登場したのでそちらに移行しました。

その経験からの感想なんですが、精度に関しては既存のコードベースで日常的な業務プログラミングのタスクを実行するレベルには達していません。コンテキストに入る情報とその処理能力に限界を感じます。「画面の一部を変更してください」レベルの気軽な指示もその背景にはつもりに積もったコードベースの経緯や設計があります。逆説的に私たちが普段行っているプログラミングタスクは結構な脳のワーキングメモリを消費していることが分かりますね。

しかし新規プロジェクトをボイラープレートにして、機能を継ぎ足していくような用途だとまずまず期待通りに機能します。このため小さいアプリケーションを1からたくさん作る趣味プログラマーにはおすすめできます。

以上で一通りツールの種類を紹介したので、ようやくClineの話に入ります。

Cline

github.com

Clineは、Saoud Rizwan氏によって開発されたVS Code拡張機能で、元々はClaude Devという名前でした。オープンソースで提供されており、VS Code拡張として利用できます。

Clineはコーディングエージェントのみを提供し、コード補完ツールやチャットアシスタントの機能はありません。そのため、CopilotやCodyと組み合わせて使っている人が多いです。

なぜClineに注目するのか

それは全ての仕組みがオープンソースソフトウェアであるため、学習に最適だからです。それに、後発なのでMCPサーバー(Model Context Protocol)の統合など新しいアーキテクチャを採用しており、参考になります。

また、ユーザーコミュニティが活発で変化が早いです。代表的なところでは後述しますが、独自にClineをフォークして配布している人たちがいます。

ちょっとリスキーに見える実験的な機能も積極的に追加されます。たとえば、ファイル読み込み、コード編集、コマンド実行などの操作をCline側で判断して提案します。ユーザーはそれを確認して許可して実行するという体ですが、自動承認モードがあり、ノールックでみんな自動運転気分で実行しています。

ファイル読み書きやコード実行などのアクションごとに自動許可範囲を設定できますが、早晩誰か事故るでしょう。昨年はBoltやCompute Use*2の時に「サンドボックスでコマンドを実行するので安全」というくだりが議論されていましたが、実際にローカルPCで自動実行しまくる便利なツールが登場してしまうと、ユーザーたちの衝動は抑えられないようです。

ユーザー「このプロジェクトにユニットテストを追加してください」AI「npm installしてもらっていいですか?」

これに対しては、予期しないコマンドが実行されないように、フォーク版ClineやCursorなどではホワイトリスト方式で実行できるコマンドを設定できるようにする、など検討されているみたいです。

Cursor YOLO Modeでは許可するコマンドを個別に管理できる

Clineのアーキテクチャ

Clineの根幹となるアイデアは、LangChainなどの近年のツールから続いているプレーンテキスト経由のプロンプトエンジニアリングです。コードの編集、ファイルの読み書き、コマンドの実行などのタスクを自動化するために、独自のXML記法で関数呼び出しや手続きを表現します。

LLMがそのプロトコルに沿ってXMLを提案してくるので、Clineはローカルでファイルの読み取りなどの関数を実行し、またLLMに返します。

replace_in_file ツールの例。これは、「あなた(LLM)に送信しているコンテキストのファイル情報の中で、SEARCH範囲をREPLACEに置き換えるためにXMLを生成してくれ」という論理的なテキスト仕様を宣言したプロンプトです。

## replace_in_file
Description: Request to replace sections of content in an existing file using SEARCH/REPLACE blocks that define exact changes to specific parts of the file. This tool should be used when you need to make targeted changes to specific parts of a file.
Parameters:
- path: (required) The path of the file to modify (relative to the current working directory ${cwd.toPosix()})
- diff: (required) One or more SEARCH/REPLACE blocks following this exact format:
  \`\`\`
  <<<<<<< SEARCH
  [exact content to find]
  =======
  [new content to replace with]
  >>>>>>> REPLACE
  \`\`\`
...
Usage:
<replace_in_file>
<path>File path here</path>
<diff>
Search and replace blocks here
</diff>
</replace_in_file>

このパターンのプレーンテキスト情報がシステムプロンプトsystem.tsには大量に定義されており「list_files ツール: ユーザーPCのディレクトリ内のファイル読み取り」から「execute_command ツール: シェルで特定のCLIコマンドを実行する」など危うげなものまで多岐にわたります。

Clineの実用面

なぜDeepSeekとセットで使っている人が多いのか

元の名前のとおり、ClineはClaudeのモデルをデフォルトにしています。しかし、Clineはモデルを切り替えることができ、DeepSeekなどの他のモデルを使うこともできます。DeepSeekはOpenAIなどと同じく独立したAIモデルのAPIを提供している企業です。ウェブを見ていると、Clineを使っている人はDeepSeek-V3をセットで使っている人が多いです。

それはClaudeGPTのAPIを使うと思ったより料金がかかるためです。なぜかというと、入出力トークンが多いためです。コーディング中に自動でLLMが意思決定をして、ファイルの読み込み→編集→読み込み→編集という作業を繰り返すことで、どんどんトークンを消費していきます。

また、前述のとおりそもそも動作させるためのシステムプロンプトも大きいです。Toolの論理的な仕様のテキストがすべて含まれます。ファイルを読み込むアクションが実行された場合、基本的にはそのファイルの内容がすべて含まれます。LLMがキャッシュAPIを使える場合は一部のトークンを節約できますが、それでもトークン数は多いです。

他には、各社モデルのプロバイダーのAPIのRate Limit(1分間にNリクエストの制限など)に到達するためです。これも入出力トークンが多いのと、作業中にリクエスト回数も頻発するためです。

まとめると、APIを頻繁に叩くため、みんな安くて性能が良くて穴場のAPIを求めています。今のところその矛先がDeepSeekに向いているのです。それによって最近はAPIの応答が遅延しているそうです。

DeepSeekのコスト感

Claude 3.5 Sonnetの入力は$3.75 / 1Mトークン(キャッシュなしの場合)に対して、DeepSeek-V3は$0.27 / 1Mトークン。さらに、2025年2月8日までは割引期間なので、$0.07 / 1Mトークンとなります。

割引期間中はDeepSeek-V3のコストはClaude 3.5 Sonnetの約1/54、終了後は約1/14です。

ローカルLLMでお得に使えるか?

DeepSeekと同じ水準、すなわちGPT 4oやClaude 3.5 Sonnetのミドルクラスのモデルに匹敵する精度を出すためには、パラメータ数の大きいモデルで推論をする必要があります。そのためにハイスペックマシンが必要です。主にCPU、VRAM、 RAMをちょっといいゲーミングPCレベルで調達する必要があるでしょう。

ユーザーの間では採用するモデルは、今のところqwen2.5-coder:32bがベターとされています。ClineはOllamaに対応していますのでOllamaのAPI経由でローカルLLMを使えます。しかし、Ollamaレジストリにあるモデルではコンテキストサイズやプロンプトテンプレートの問題で、Clineのコーディングは動作しないため、モデルをビルドする必要があります。カスタムビルドを公開している人もいます(qwen2.5-coder-clineなどのキーワードで検索してください)。著者は以下の記事でllama3.1:8bを自分でビルドして使うことができました。

zenn.dev

今後、DeepSeek-V3の量子化モデルがOllamaに対応します。llama.cppOllamaにDeeSeek-V3向けのアップデートが入ったためです*3。その時に自分のサーバーで動かすことで、改めて評価する予定です。

コミュニティと発展

フォーク版たち:Roo-Cline、Bao Cline、Cool Cline

これらはいわゆるBetter系の細かい機能を追加したサードパーティの拡張です。RooやBaoが独自に追加した機能を、Coolがチェリーピッキングしたり、オリジナルClineがさらに取り入れているようです。

Roo-Clineのライトユーザー向けのキラー機能としては、返答を日本語にする設定があります。それ以外には、パワーユーザー向けの高度な設定項目が多く含まれています。

著者としては、これらの代表的なフォークなら良いのですが、派生してどんどん怪しいフォークにまで手を出す敷居を低くするのは、やめたほうが無難と思います。

Roo-Clineで日本語を設定している様子

なぜフォーク版がたくさんあるのか

このようなフォーク版がたくさん存在する理由は、以下のような要因があります。

  • 実装を変更しないとカスタマイズができないため
    カスタマイズするためには、実装自体を変更する必要があり、多くのユーザーが自分用に本体を改造したくなります。著者も改造しています。

  • トークン数とコストが直結しているため
    前述のとおり、トークン数と利用コストが直接関係しており、効率化のために独自の最適化を行うインセンティブがあります。

  • ソースコードが約4000行(20,000行の間違えでした)のTypeScript+英語の文章(プロンプト)でシンプルなため
    ソースコードが比較的短く、シンプルであるため、理解しやすく、変更・拡張が容易です。

  • ClineでClineを変更できるという事情
    Cline自体を使ってClineのコードを変更できるため、開発者が自分で機能追加や修正を行いやすいこのプロジェクト特有の状況もあります。

  • メンテナーがほぼ一人であるため
    メンテナーがほぼ一人で開発を進めていることから、コミュニティによる機能追加や改善が進み、フォークが増えていると考えられます。

エンタープライズ向けはあるの?

Clineについては、利用者のPCから設定したモデルのAPIにダイレクトにデータが送信されます。中間のサーバーはありません。送信先としてAzureAWSGoogle Cloudを設定することができますのでそれらのサービスポリシーに従うことができます。また、OpenAIAnthropicもエンタープライズ向けのサービスを提供しているので、一度調べてみると良いでしょう。

CursorやContinueは自社のサーバーで独自のモデルをホストしています。これらを使用する際には、セキュリティを考慮する必要があります。サイトには「問い合わせをしてください」と書かれています。

DeepSeekについては、中国企業であることからデータの取り扱いを懸念する声もあります。筆者は使用していないため、詳しい読者がいればコメントをお寄せください。

追記:DeepSeek Open Platform Terms of Service

DeepSeekの利用規約について読者の関心が高かったのでDeepSeek Open Platform Terms of Serviceを読みました。

皆さんが気になるのは

  1. DeepSeekはユーザーの入力データに対して、サービスの運営および改善、またはサービスをサポートする基盤技術のために入力と出力を使用する可能性がある(4.2)
  2. 中国のデータ保護規制についてユーザーが責任を持つ(3.3)
  3. DeepSeekとの間で紛争が生じた場合、日本の裁判所ではなく中国の裁判所で争う(9.1)

という部分かと思います。これは著者の理解なので原文を確認してみてください。以下が原文とリンクになります。

DeepSeek Open Platform Terms of Service

原文(折りたたみ)

3.3 You shall ensure the legality of the source of end user data collected by applications, services, or tools developed using our Open Platform, ensuring that you have the legal rights to such data. This includes but is not limited to control rights, intellectual property rights, or rights to dispose of and license others to use the relevant data, without infringing on any third party's legal interests, or involving any trade secrets or other data that may have an adverse impact on security or public interests. For end user data involving personal data, you shall ensure that the collection and processing of personal data comply with the relevant requirements for personal data protection, meet the principles of legality, legitimacy, and necessity, and promptly respond to the rights requests of end users in accordance with the law.

4.2 In order to fulfill the requirements stipulated by laws and regulations or provide the Services specified in these Terms, and under the premise of secure encryption technology processing, strict de-identification rendering, and irreversibility to identify specific individuals, we may, to a minimal extent, use Inputs and Outputs to provide, maintain, operate, develop or improve the Services or the underlying technologies supporting the Services. Please be aware that unless we obtain your separate consent, we will not use the aforementioned data and content for any purposes unrelated to the Services.

9.1 The establishment, execution, interpretation, and resolution of disputes under these Terms shall be governed by the laws of the People's Republic of China in the mainland. 9.2 In the event of a dispute arising from the signing, performance, or interpretation of these Terms, the Parties shall make efforts to resolve it amicably through negotiation. If negotiation fails, either Party has the right to file a lawsuit with a court having jurisdiction over the location of the registered office of Hangzhou DeepSeek Artificial Intelligence Co., Ltd.

Clineにベットするべきか?

ベットする必要はありません。

プログラミングやフレームワークでも、このような製品のトレンド競争が勃発すると、どれか一つを選んで学習コストを投下することを他人に判断してほしいという勢力が出てくるのが常です。

著者としては今のフェーズで関心があるのならClineを実現するための技術を理解することをおすすめします。どのツールでもいいのでまず自分で試して、どうやってコーディングエージェントが実現されているのかを想像できると技術評価の際に不安がなくなります。

Clineがやっていることは他のツールでも実現可能です。今後他のツールも似たような体験になってくる可能性はあります。Clineがオープンソースであるため、その仕組みを知ることができます。

極論を言えば、Clineで実現できることは我々が手動で同じことをChatGPTに入力し続ければ実行できます。そもそも、近年のコーディングエージェントやプログラミング自動化パイプラインはLangChainなどの世代から続いており、それがエディタに統合され、モデルのAPIの機能や性能が豊富になって前提が変わり、新たな選択肢が取れるようになった、というだけの話です。

おわりに

本記事では、Clineを中心にAIコーディングツールの現状を紹介しました。

まとめると、AIコーディングツールは、コード補完ツール、チャットアシスタント、コーディングエージェントの3つのカテゴリーに分類され、最近はコーディングエージェント型のツール開発が活発です。

これらをユーザーとして体験したい場合はCursorやCopilot Editsから導入するといいでしょう。

Clineはオープンソースであり、新しいアーキテクチャを採用しているため、学習や研究に最適なツールと言えます。 補足として、著者はDevinWindsurfAiderなど、カバーできていないツールも多く存在します。o1 proなどの昨今の高額なプライシングの推論モデルも、まだ十分に試せていません。

根本的に、これらのAIコーディングツールの進化は、「ググってStack Overflowにあったコードをコピペする」コピペプログラミングを高度に自動化することです。しかし興味深いのは、今までコピペプログラミングにさえ手を出してこなかった人たちが、AIコーディングツールを使ってプログラミングを始めていることです。しかも、そういう人たちでも、課金すればするだけ成果が出る。そして、プログラミングを勉強することでコスト削減につながってしまうという構造が確立しているのも素晴らしいことです。

高性能な推論モデルによって解くべき問題は、実は多くなく、現行のモデルで十分だという議論があります。これを聞いたとき、プログラマーの業務でも高度なアルゴリズムや計算問題を活用する現場は一握りであることを思い出しました。AIコーディングツールによってプログラマーの母数は増えるでしょうが、果たして単純な業務プログラミングを満たすレベルになるのかは未知数です。逆に、コードを書いても解決できない領域が今より浮き彫りになるかもしれません。

また、このような自動化は学習や教育には不向きとする意見もあります。著者も専門教育を受けず、趣味と現場でプログラミングを覚えた人間なので、プログラミングの教育がどう変わるかは興味深いところです。希望的な観測では、新たなLLMネイティブな世代が自分たち向けの学習方法を確立してくれることを期待しています。

著者はもともとコーディング自動化ツールに関心がありました。昨今のAIコーディングツールの進化には目を見張るものがあり、エキサイティングです。

ただ、Clineに限らず、ユーザーが結構際どいことを行なっているように見えます。Web 2.0でAPIでマッシュアップをしていた時代に、APIの外部呼び出しの全能感からか、スクリプトキディ化する人が多かったことを思い出させます。実際にX(旧Twitter)で観測するユーザーたちも、今回のAIコーディングツールの進化でも同じような感じがします。

AIコーディングツールのご利用は計画的に。

O'Reilly Answersの日本語検索を自作した

O'Reilly Answersは、技術的な質問に対してAI駆動の検索を提供するサービスだ。ユーザーが自然言語で質問を入力すると、O'Reillyの書籍コンテンツから関連性の高いスニペットを抽出して回答を表示する。 技術面では、Miso社がBERTやllama 3など複数のLLM技術を組み合わせたパイプラインで開発している。

ただし現状の課題として、O'Reilly Answersは英語でしか利用できない。O'Reillyには日本語の書籍も多数あるものの、検索は英語で行う必要がある。そして英語で検索すると日本語の書籍はヒットしない。コンテンツの大半が英語であることを考えれば許容できなくもないが、日本語での文章検索ができればより便利だろう。

そこで、この課題を解決するため、書籍の公開情報を取得して、日本語で質問して検索できるウェブアプリを即興で作った。さっき。以下にデプロイしてある。

ask-ol.vercel.app

使う道具はいつものようにサーバーレスなアーキテクチャで構築した。モデルとしてはGeminiを採用した。まずオライリーの書籍データをスクレイピングしてクソデカJSONファイルとして保存。このデータをJSONL形式でシステムプロンプトに組み込み、ユーザーからの質問と組み合わせることで、検索から結果の整形までをGeminiに一任している。 書籍データは静的なため、GeminiのプロンプトキャッシュAPIを活用してコスト効率を向上させた。これをする前は、当初は埋め込み形式で事前に書籍データを変換して、Firestoreを使ったベクトル検索を試していたが、途中でGeminiの100万トークン制限内に全データが収まることが判明し、現在の方式に落ち着いた。

フロントエンドの実装では、Vercelのスタックを最大限活用して自動化を図った。Vercel AI SDKを使ってGemini APIを呼び出し、ストリーミングレスポンスを返すServer Actionを構築。さらにVercel AI SDKのRSC版でストリーミング対応のUIを実装し、スタイリングはv0.devに本家サイトのスクショを送っていい感じによろしくと依頼した。

このアプリには本家と比べていくつかの制約がある。公開情報のみを参照しているため書籍の内容自体は使用しておらず、本家のような詳細な回答は生成できない。そのため、関連書籍への参照リンクを提示する仕様とした。 それにオライリーの書籍は、すべて換算すると全期間で6万件もの膨大なタイトルがある(すごい)。なのでオライリー社の日米のみとして、今回は範囲も直近2年の発売タイトルに限定した。技術書のカバー範囲としてはこれは物足りない面がある。

実際に運用して使ってみると、いくつかの技術的な制約が見えてきた。この設計は入力トークンが長くなり、それによって出力のコメントが短くなる。なので生成時のトークンパラメータを調整した。また、レスポンスをプレーンテキストではなくRSCにマッピングするために、構造化レスポンスを2段階で処理するため、ここでさらにトークンを消費してしまう。

アプリとしてはキーワードベースの検索では概ね関連するタイトルを提示できるものの、質問文を解釈してフレンドリーな解説を返すという点では本家の完成度には及ばない。本文チャプターを参照してないからしょうがない。ただし、そもそも本家O'Reilly Answersの利用状況も気になるところだ。

一方で、このプロジェクトは要素技術の学習という観点では有意義だった。特に、Vercel Deploy、v0.dev、AI SDK、Next.jsといったVercelスタック+各種SaaS(この場合Google CloudのAPI)を組み合わせた開発フローは、驚くほど時短だった。Vercel最高。ついでに個人の商用利用制限も緩和してください。

昨今は、RAGのPoCをしゃぶり尽くした人たちがAIエージェントパッケージの金脈を掘り当てるフェーズにありそうだが、LLMの「テキスト(トークン化したデータ)生成による自動化範囲の拡大」という基礎技術の部分だけでもまだより実用的なサービスとして展開できる可能性があると思っている。ただし地味だ。今回やったプロンプトキャッシュAPIの活用とかモデルプロバイダ以外がやるのはハードな上にかなりマイナーだが面白い。

AI検索サービスの実用性と採用については、まだまだ検証の余地がありそうだ。

2024年に読んだおすすめの3冊:『「好き」を言語化する技術』『ビジネスパーソンのための「言語技術」超入門」』『まったく新しいアカデミック・ライティングの教科書』

はじめに

年末の振り返り記事はつい読書記録総決算とばかりに大量に紹介しがちですが、あえて3冊に絞ることにしました。
その結果「人文系の作文術関連の本」というテーマが浮き彫りになりました。

私がブログを長年続けられているのは、文章を書くことが純粋に好きであること、そしてそれを通じて読者を楽しませたいという想いがあるからです。なのでこのテーマはぴったりです。
とくに2024年は生成AI関連のツールや開発に触れる機会が多かったため、それを活用する手段としてライティング技法への関心が高まりました。

今回紹介する本の著者たちの背景は人文系であることは共通していますが、日本文学、英米文学、外国語、国際文化の研究やオタクの推し活など幅広い分野に及びます。
これまで理工系の作文術ばかりを好んで読んできた私にとって、これらの本は味変として新鮮な刺激をもたらしたといえます。
そして、どの著者にも共通して見られたのは、人に物事を教えるトレーナーとしての能力の高さです。

という視点が述べられており、これらが私の読書と執筆の習慣を新たな視点で捉え直す契機となったと言っても過言ではありません。

「好き」を言語化する技術

『「好き」を言語化する技術』は、自分の好きなものについて語れる、いわゆる「推し語り」のための文章術をまとめた実用書です。
一番カジュアルに読めそうな内容であるため、まず最初に紹介します。
この本は、市民の読書習慣の変容を近代労働史の視点から読み解くベストセラー『なぜ働いていると本が読めなくなるのか』の著者である三宅香帆によるものです。
「なぜ働いているとーー」は映画「花束みたいな恋をした」の印象的なシーンを分析の出発点とし、『「好き」を言語化する技術』を活用して書かれているとも読めるので、本書の有用性にも説得力があります。

laiso.hatenablog.com

※この本は、2023年に発刊された「推しやば」こと『推しの素晴らしさを語りたいのに「やばい!」しかでてこない』とほぼ同じ内容を含むため、既読の方は注意が必要です。

感想を語るコツは、「細分化」と自分で考えた言葉(文脈)

心を動かされたところを具体的に挙げるうえで注意してほしいのが、「細かく」挙げること。これは細かくたくさん挙げろ、と言っているのではありません。挙げるのが全体的な点ではなく、細かければ細かい点であるほどいい! という意味です。 細かく具体例を挙げることのなにがいいのか。それは、感想のオリジナリティは細かさに宿るからです。
たとえば、ライブの感想に「最高!」という言葉しかでてこないという悩みは、ライブの「どこが」最高だったのかを言えたら解消されます。ライブで「この曲が」演奏されたのが嬉しくて、「この歌詞が」あらためて響いて、「この演出が」自分の心を揺さぶった。そんなふうに、最高だった点を細分化さえできれば、じつは語彙力なんてなくても、あなたのオリジナルな感想になり得るのです。

感想を語るコツは、自分の好きと言う感情を「細分化」と自分自身で考えた言葉で語ることにある、と三宅は主張しています。
我々はしばしば言語化のうまさを、国語力、つまり「読書経験や学力によって豊富な語彙を持ち、それを選び取る修辞テクニックに秀でた状態」として認識しがちです。
しかし、本当に重要なポイントは自分の好きと言う感情を「細分化」することであり、感動、共感、違和感など、心を動かされた要素を具体的かつ細かく挙げていくことにあります。
これにより、語彙力に頼らずともオリジナリティのある表現が可能になります。
その抜き出した細部を、自分の考えで妄想的に膨らませ、好きなものや人への感情を表現する妄想力を養うことが重要です。
また、自分の記憶から関連するコンテンツをつなぎ合わせ、思考を自由に展開させることで新たなネタを生み出します。
こうした作業を通じて、「好きな対象のどの部分に注目したのか」「なぜそれを好きなのか」「それはなぜか」といった「なぜなぜ分析」を重ねていきます。
これらのプロセスは、客観的な意見や一般論に頼るのではなく、自分自身の文脈に基づいた独自の表現力を築く基盤となるのです。
このようにして、感想や思考の言語化は、語彙やテクニックではなく、自分の「好き」を掘り下げる視点から始まることを理解できます。

話し相手(読者)との情報格差を埋める

重要なのが、「距離」つまり、「自分と相手との差異はどの程度か?」を把握しようと心がけること。ただ「相手の情報」を把握するのではなく。「自分の情報との差異」が重要です。なぜかというと、伝えることは、自分と相手にある情報格差を埋めることにほかならないから。

好きの言語化とは、自分と相手との情報格差を埋めるプロセスです。
この際に重要なのは、聞き手の「推しに関する知識量と印象」を把握し、それに応じて「伝えたいこと」を補足することです。
たとえば、専門用語が多い場合は、言い換えや具体例を用いることで聞き手が内容を理解しやすくなります。
また、聞き手の興味に合わせた語り方を心がけることで、相手にとって話題がより魅力的に感じられるでしょう。
たとえば、「このキャラクターの魅力はツンデレなところ」と言う代わりに、「最初は冷たく見えるけど、実は不器用で優しいところがある」と表現を変えることで、ツンデレという用語に馴染みのない相手にも伝わりやすくなります。
このように、文章化は相手の知識や関心を考慮しながら情報を整理し、共有する作業です。
その結果、伝えたい内容が効果的に伝わるだけでなく、相手との間に新たな共感が生まれる可能性を高めるのです。

SNSの空気から自分の言葉を守る

SNSで推しのことを発信するのは、ほかならない推し、あるいは自分のためですよね。推しの魅力を伝えたい、推しのよさを記録したい、推しの面白さをわかってほしい。これらの欲望の間には、推しと自分しかいないはず。他人を介在させる必要なんてない。 だから、他人の言葉に自分が影響されないように。大量に流れてくる他人の言葉の渦から、自分の言葉を守ること。それがSNSのコツなんです。

SNSの空気から自分の言葉を守り、自己表現を維持するという言論は三宅の著書に度々出てきます。
確かにSNS上には同調圧力や「空気」のようなものが存在し、多くの人の意見がなんとなく決まってしまう傾向があります。
この空気に流されてしまうと、他人の意見を無意識に取り入れてしまい、自分の考えを失ってしまう危険があります。
(このブログの読者は古参インターネットのマッドマックス的世界の残党が含まれているので「そんなことはないが」と言われてしまうかもしれませんが)

本書ではこの問題に対する対策として、「自分の感想をプライベートなメモや日記に書き留めておく」ことを提案しています。
「一旦、感情君を安全な場所で保護せよ」ということですね。 たとえば、映画を見た後にまず自分の感想を日記に書いておけば、SNSで他人の感想を目にしても、自分の意見が揺らぐことを防げるのです。
こうした習慣を持つことで、他人の意見に左右されずに、自分自身の言葉や感情を守ることができます。
これには私も賛成で、メモアプリを長年取っ替え引っ替え愛用しています。

本書の使いどころ:コンテンツ消費活動のお供に

「好き」を言語化する技術』は、快適な消費活動のお供として活用できる一冊です。
摂取したコンテンツの感想が一辺倒になってしまうという問題に対し、本書はあの手この手で具体的な解決策を提示しています。
コンテンツの消費は、それをどう受容したのかを周囲に表現する活動と一体化している部分があり、自分の感想をいかに独自性のある言葉で表現するかが重要になります。
本書を通じて、自分独自の感想を言語化する力を身につけることで、健全な精神を保ちながら快適にコンテンツを楽しむことができるでしょう。
「推し」の魅力を語る行為は、単に相手に伝えるだけでなく、自分自身が何を大切にしているのかを再発見する機会となり、結果として自己理解を深め、人生をより豊かなものにしてくれるのです。
本書は、そうした消費活動をさらに深い楽しみに変えるための実践的なガイドブックといえるでしょう。

そしてこれは、個人ブログへの投稿としても最適な内容です。
個人ブログはフリースタイルで書けるため、自分の書きたいことを優先しやすく、本書で学んだ「感想の言語化」技術を存分に活かせる場となります。
たとえば、本ブログでありがちな技術記事の視点から見ると、「新しいフレームワークの開発者体験のどこが優れるのか」といった評価や、「この技術を使っていて感じたツラみやアンチパターン」を具体的に言語化することに役立てることができるでしょう。
また、より論理的で体系立てた文書にしたい場合は、後続の本でさらなるスキルを学ぶことをお勧めします。

ビジネスパーソンのための「言語技術」超入門

『ビジネスパーソンのための「言語技術」超入門』は、言語を技術として使用し問題を解決する力を身につけるための実践的なガイドです。
対話、説明、記述、絵やテキストの分析といった具体的なスキルを体系的に解説しており、特に各スキルには具体的なトレーニング方法や応用例が示されています。
この本の著者、三森ゆりかは、教育現場向けの教材開発や研修実施において長年の経験を持っています。
本書は2021年に発刊されましたが、私は今年この本を読みました。
本記事のテーマに非常によく合致しているので、合わせて紹介したいと思います。

言語技術は訓練によって向上させることが可能

その結果明らかになったのは、いずれの国の母語教育もやはりその組み立てや内容に大きな差異はなく、どの国でも母語教育が非常に重視され、週に五時間程度、徹底的に読み、議論し、記述する訓練がなされていることである。そして、この言葉の技術教育の目的は、幼稚園から高校までの長期にわたる訓練の末、最終的にはそれぞれの技術が有機的に絡み合い、汎用的能力として社会で機能することである。

言語技術は、私たちの母国語・日本語の言葉を道具として使い、目的を達成することであり、情報を明確に伝え、他者と円滑に意思疎通を図る力が含まれます。
従来の日本語教育では言語の形式的な面に重点が置かれ、コミュニケーションや思考といった言語の機能的側面が十分に扱われていません。
「暗黙の了解」に重きを置く文化もあり、言葉で明確に表現するスキルが軽視されているのです。
それはビジネス、教育、日常生活など、あらゆる分野で応用可能です。
例えば、プレゼンテーションでは自分の考えを明確に伝え、相手を説得する力が求められます。
他には、社会問題への関心を持ち、情報を分析し、自分の意見を築いていくためには、強力な言語技術が不可欠です。
これらを実現するための言語技術は「訓練によって向上させることが可能である」というのが本書の出発点です。

問答ゲーム:質問と回答の型を身につける

本書で提唱される対話トレーニングの「問答ゲーム」は1対1で対話を行い、与えられた質問に対して相手が答える形式で行われます。

「問答ゲーム」のルールは次の四点である。
①結論を最初に言う
②主語を入れる
③理由を言う
④結論の再提示をする
これらを必ず守ることが、常に結論から情報を発信し、効率よく対話をする能力の獲得に繫がる。

目的としては、質問と回答の型を身につけさせ、欧米型の結論先行型の思考プロセスを実際に体験させることで、そのメリットをしっかりと理解させることにある、と三森は説明します。
日本文化では主語や目的語を省略し、背景や相手の気持ちを想像してハイコンテキストにコミュニケーションをすることが一般的です。
こうした中では質問に対する回答は最初に過程や理由を述べ、その先の結論に共感してもらうことに重きが置かれます。
結果として、ときに結論や自分の意見が不明確なまま話し始めてしまうこともあります。
しかし言語技術における対話の場面では、明確で論理的なコミュニケーションを促進するため、結論先行型への移行を積極的に促すことが求められています。
「問答ゲーム」によって質問を繰り返し、「なぜその結論に至ったのか」、その理由が論理的に正しいかを質問と対話によって深めることができます。
これは、例えば『「好き」を言語化する技術』における「感情の細分化」に通ずるアプローチでもあります。

空間配列:分かりやすく情報を組み立てる

説明文には種類があり、これは時間を扱ったものと空間を扱ったものとに大別できる。前者は、いわゆる時系列で並べられる情報を提示する文章で、これには経過や段階を示すものも含まれる。後者は、空間的に捉えた対象、時間には落とし込めない事柄を提示する文章である。日本の教育では、時間的情報の並べ方については一応学習機会がある。しかし空間で捉えたそれについての提示方法は未学習である。ところが、この方法による説明の機会は存外多く、その結果が日本の説明的文章のわかりにくさを生み出している。

空間配列は、情報を時間や重要度によって並び替えて配置する方法です。
三森はこれを、情報の整理および効果的な伝達のための技術として説明しています。
複雑な情報の塊を分解して、特定の基準に基づいて順序立てて説明することで、関連する概念がより明確に理解できるようになります。
これは、一種の論理的なソートアルゴリズムに似ています。
本書では、国旗などの視覚的な情報を言語化し、構造的に捉えることが実践されています。
これをライティングに応用すると、文章をアウトライン構造に整え、重要度の高い情報を結論としてパラグラフの最初に配置し、重要度の低い情報を捕捉する説明として後続に配置します。

本書の使いどころ:ブレスト、プレゼン、ドキュメンテーション

ビジネスパーソンのための「言語技術」超入門』が活用できそうな場面は多岐にわたります。
まず文章にする前の思考過程、いわゆるブレインストーミングにおいて活用できます。
情報の収集と整理は、発話の前に考えをまとめ、何を伝えたいのか、どのような情報が必要かを整えることによって効果を発揮します。
対話→質問によって思考を深め、より明確な結論を導くことも可能です。
次に、ある特定の情報をテキスト化する場面では、具体的な例としてニュース解説記事、テクニカルライティングが挙げられます。
また、自分の考えを整理し、文章として他者に理解させる場面でも有用です。
これには、ブログやエッセイ、さらにはプレゼンテーション用のスライドの作成が含まれます。

まったく新しいアカデミック・ライティングの教科書

『まったく新しいアカデミック・ライティングの教科書』は学術論文の執筆技術を体系的に解説した書籍です。
著者の阿部幸大は、日米文化史研究を専門としている筑波大学の助教であり、自身の執筆経験を活かしてこの本を書き上げました。
光文社から提供されたPR素材は本書の詳細に乏しいですが、gendai.mediaの抜粋記事や著者のウェブサイトであるkodaiabe.comに掲載されたアブストで、その内容を十分に理解できます。

2024年に『まったく新しいアカデミック・ライティングの教科書』(光文社)と題した入門書を出版した。期末レポートや卒論レベルから世界のトップジャーナルまで、論文執筆に必要な実力を養うための方法論を網羅的に指南する。人文学における論文執筆には基礎となる習得必須の知識と技術が存在するが、それを現在の大学教育はうまくカリキュラム化できていない。なにを達成すれば論文は成功したことになるのか、どの段階でどの程度の達成が要求されるのか、そしてそのためにはどのようなトレーニングが必要なのか。そもそも、いったい人文学の論文とはなんのために書かれるのか? 本書では、原理編・実践編・発展編・演習編の四段階にわたり、独学で学術論文を準備・執筆・出版するために必要なすべてを提供する。

この本は、従来のアカデミック・ライティングの方法論を学んでも書くことが難しいという人々でも、各要素を分解して分析し、トレーニング手法を確立することで、執筆が可能になるというコンセプトを持っています。以下の『独学大全』の読書猿と阿部幸大の対談にそのことが書かれていました。

diamond.jp

自身の主張(アーギュメント)を提示する

論文とはなにか。この問いに、ひとまずシンプルな答えを与えることからはじめよう。
論文とは、ある主張を提示し、その主張が正しいことを論証する文章である。
これはシンプルなようでいて、論文というジャンルの文章がもつ、きわめて奥深い特質である。

本書でまず印象的なのは「アーギュメント」という言葉を定義して、それを元に論理を展開することです。
アーギュメントとは論文の主張のことです。論文を書く際に、その論文全体を貫く主張を明確にします。
論文では主張に対して他者が意見を述べたり、反論したりすることで、アカデミックな価値が育まれます。
実際に本書では、戸田山 和久氏の『論文の教室』に掲げられた「論文には問いが必要だ」という主張に対し、「論文には問いではなく主張が必要」と反論することで、論文の書き方指南書における「論文とは何か?」という議論に参加しています。

パラグラフ解析:書くために読む

多くの人は、自分では論文を書けなくても、読むことならある程度できる、と考えている。スラスラと正確に読めるかどうかといった話ではなく、ようは 執筆力よりも読解力のほうが高いはずだ という想定だ。 しかし本書の核にある認識のひとつに、「書けないやつは読めてもいない」 というものがある。書けないということは読めないということなのであり、読めないということは書けないということなのだ――そう考えたほうが、執筆の役に立つ。

阿部は、「書けないのは読めてないから」と説明し、読解力のみならず文章を「書く」能力も論理的な文章を読む訓練を通じて向上させられると述べています。
実際、自分の書いた文章であっても客観的に読むことが求められますし、自分の書きたい領域での文章をお手本として分析してその構造を理解することがライティングの第一歩です。
さらに、パラグラフを分析する具体的なトレーニングとして、パラグラフ解析手法”Uneven U”が紹介されています。
この方法では、抽象度に応じてセンテンスをレベル1から5に分類します。
先の『ビジネスパーソンのための「言語技術」超入門』でいうと抽象度を使った「空間配列」の一種として、規則によって文章を配置して構築できます。
このように、文章の読解と書くことが密接に繋がっていることが理解できます。

蛇足ですが、パラグラフ解析手法”Uneven U”のトレーニングをサポートするGPTsを公開しているので興味がある方は使ってみてください。

laiso.hatenablog.com

長いパラグラフを作るには情報を詰め込むべし

パラグラフ解析をして対象領域の論文と我々の文章を比較すると大抵「パラグラフが短い=内包するトピック数が少ない=議論に乏しい」という問題が明らかになると阿部は説明します。 長いパラグラフを作成するための実践方法が「第5章 長いパラグラフをつくる」です。

むしろわたしたちが取り組むべき 実践的な 課題は、 パラグラフ・ライティングのルールを守りながらもっと長いパラグラフを書けるようになるための方法論の構築 である。丁寧に論じているつもりなのにパラグラフが短くなり議論が粗雑であると判断されてしまうのはなぜなのかを理解し、その解決策を手にいれることなのだ。

パラグラフに多くのトピックを振り込み、複数の論点を関連付け、論理的に展開する構造によって、複雑なアイデアを明瞭に伝えることができます。
一つのトピックに基づいて、詳細な説明や具体的な例を交えながら論点を展開することも重要です。
さらに、パラフレーズを活用しながら内容を別の言葉で言い換えることにより、情報を異なる視点から提示することで分量を増やします。
引用を活用して参照先の文献から引き出したアーギュメントを加えることで、他者の知見を取り入れ、多角的な解釈が促進されます。
これらを効果的に行うためには、読解力が不可欠であり、自分なりの解釈を生むためにも言語技術が求められます。
というわけで『ビジネスパーソンのための「言語技術」超入門』にも通ずる話です。

生成AIの作文が読み応えがないのは情報が少ないから?

「第5章 長いパラグラフをつくる」を読んでいるときに思い出したのが、生成AIによる作文の読後感です。
「AにとってXは効率的に活用できる重要な〇〇です」というフレーズのように、表面的には「結論→補足→まとめ」の形式を整えているにもかかわらず、含まれる主張や情報が少ないと感じることが多いのです。
要するに、主張や論点、捕捉説明が不足し、文字でそれを埋め合わせているに過ぎないのかと納得しました(生成AIにおける「推しが好きすぎてAIヤバイ」と連呼している状態と考えると微笑ましい)。

これは、現在の安全なAIの基準が自身が主張を控えることをよしとする調整をされているためであることも想像します。

本書の使いどころ:主張を含む文章全般

まったく新しいアカデミック・ライティングの教科書』の使いどころは、論文以外にもビジネス文書、技術ブログといったさまざまな場面で意見を文章化する際に適用範囲が広げられると思います。
文章を書く以前の調査過程でも、引用を目的とした参考文献を集め、自分の意見や主張を明確にしたり、議論に参加する基礎を築くために本書のトレーニング手法が役立ちます。

ボーナストラック:YouTubeチャンネル

www.youtube.com

最近、著者のYouTubeチャンネルが開設されて動画が公開されています。 このチャンネルでは、本書で解説した方法論を実際に活用して、ウェブ上の文献から情報を集取する手順をライブで説明しているコンテンツがあります。
私は動画を見て、作業工程が技術ブログの執筆過程と似ていると感じ、自分のライティング作業にも適用できると気づきました。
本書を読んだ後、気に入った方はこのチャンネルもフォローするとよいでしょう。

おわりに

以上で2024年に読んだ本の紹介を終わります。
今年はこれらの本以外にもコンピュータ書や小説もたくさん読みました。
一部の本は記事にしてあるので、当ブログの過去記事一覧から辿ってもらえればと思います。
そしてその読書を可能にしたのは日々使っている生成AI技術のおかげです。
来年以降は生成AI技術を使った文章執筆・構成の自動化分野に取り組みたいと考えています。
それでは良いお年を。

自宅サーバー構築とKamalデプロイ環境構築メモ

目的:自宅サーバー作って遊びたい

  • プライベート利用かつPaaSで高コストになるものの代替
  • 常駐プログラム
    • クローラー
    • 長時間かかるデータ処理
  • 停止しても良いもの
    • バックエンドのCMS(自宅サーバー)
    • フロントエンド(デプロイ時にコンテンツを書き出し、ホスティングプラットフォームへアップロード)
  • その他
    • マイクラなどの身内用ゲームサーバー
    • サーバー構築自体を目的とした遊び(ISUCON過去問など)

要件:令和の自宅サーバー

  • コンテナオーケストレーション
    • コンテナイメージをpushするだけでデプロイ
    • アプリ追加時のミドルウェア設定を自動化
    • Heroku代替のオープンソースツールを検討
      • Dokku, CapRover, Coolify
      • Kubernetes系は自宅環境では複雑
  • 複数台構成への対応
    • 基本は1台のサーバーに複数アプリを集約
    • フェールオーバー用に後からサーバー追加
      • Cloudflare Tunnelで対応
      • Cloudflare Load Balancers(有料)
    • VPSへの移行も視野に入れる
  • セキュアな接続
    • パブリックIPアドレスを公開せずに外部からHTTPS/SSH接続
      • Cloudflare Tunnel
      • Tailscale Funnel

コスト:既存ソリューションより安価かつ運用負荷を低減

  • 比較対象
    • VPS、レンタルサーバー
    • Heroku, RenderなどのPaaS
    • Google Cloud, AWSなどのクラウドプラットフォーム(CaaS)
      • Cloud Run, GKE, AppRunner, ECS, EKSなど
  • 比較対象外
    • Cloudflare Workers, Vercel, AWS LambdaなどのFaaS
    • Fly.io(PaaS/CaaS/FaaSの複合型)

必要な機材

  • Linux(Ubuntu)がインストールできるPC
    • 低価格ミニPC
    • Raspberry Piでも可
  • USBメモリ(Ubuntuインストール用)
    • Ubuntuでなくても可(Kamal開発元の37signalsに合わせる)

Ubuntuのインストール

  • Ubuntu Serverのダウンロード
  • インストール用USBメモリ作成
  • ミニPCへのUbuntuインストール
  • Dockerインストール
  • 内部ネットワークからSSH接続

Kamalのインストールと設定

  • kamal init
  • .kamal/secret の追加
    • Docker Hubアクセス用Personal Access Token
  • config/deploy.yml の編集
  • kamal setup

Cloudflare Tunnelによるセキュアな接続

  • ミニPCへのcloudflaredインストール
  • Tunnelの作成
  • HTTPS接続
  • ローカルマシンへのcloudflaredインストール
  • 外部ネットワークからSSH接続
  • ファイアウォール(ufw)を有効化
  • Cloudflare Tunnel以外からの接続を遮断

Webアプリのデプロイ(Next.js)

ふつうのウェブエンジニア向けRust入門書『RustによるWebアプリケーション開発 設計からリリース・運用まで』

私たちがRustを学ぶ際の障壁

ウェブエンジニアにとってRustを学ぶ際の最大の障壁は、その適用分野がもともと高度である点です。
Rustは主にシステムプログラミングやC++の置き換え、ビルドツールの最適化といった専門的な領域で活用されています。
これらの分野に馴染みがないウェブ開発者にとって、Rustのエコシステムを学ぶことは簡単ではありません。
本書はそのようなエンジニアが、既存の仕事の道具をRustに置き換える時のガイドとして最適です。
システムの一部をマイクロサービスに切り出すケースや新規プロジェクトのバックエンドでRustの採用を検討したりする場面で活用できます。
そのため、この書籍はウェブのバックエンドエンジニアがRustエコシステムを実践的に学ぶための最適なリソースといえるでしょう。

本書の特徴

本書の特徴は、バックエンド開発者が普段行う作業をRustに置き換えて学ぶことができる実践的な内容にあります。
その中心は、ハンズオン形式でシンプルなCRUDアプリケーション(蔵書管理システム)のバックエンドWeb APIを開発するというアプローチです*1
本書は、C++で行うシステムプログラミングの置き換えやWasmを用いたブラウザで動くアプリケーション機能の実装、またRust言語そのものの体系的なリファレンスではありません。
ウェブ開発という領域で、よりリアルワールド志向で、フロントエンドやインフラチームとの協調を念頭に置いた現場のチーム開発に即した内容を重視しています。

Rust自体の副読本の併用を推奨

本書は、シンタックスレベルでのRustの基本的な言語機能についての理解を前提としています。
そのため、Rust自体をはじめて使う読者へは副読本の併用が推奨されます。
私自身は、Oreillyから出版されている『プログラミングRust』を活用しました。
この本は、Rustの細かい構文や仕組みについてもっとも詳細に解説されている一冊だと思います。
また、テスト駆動開発(TDD)の第一人者であるt-wadaさんもこの書籍でRustの理解が捗ったと言及されています。

speakerdeck.com

システム全体の技術スタック

本書で提案されているシステム全体の技術スタックは、リアルワールドのプロジェクトにおいて採用されやすい最大公約数的な構成となっています。
バックエンドでは、非同期ランタイムのデファクトスタンダードであるtokioをベースにしたWebフレームワークのAxumを使用し、データベース操作にはsqlx、ビルドツールとしてcargo-make、そしてテストにはcargo-nextestをはじめから用いてcargo-workspaceのモノレポ構成でスタートします。
フロントエンドにはReact系のNext.jsを採用していますが、バックエンドのAPIとは分離されているので他のフレームでも問題なく適応可能です。
本書内ではフロントエンドの実装解説はありませんが、バックエンドAPIをシンプルに利用するGUI構築を念頭に置いており、理解するのは容易です。
インフラ部分では、バックエンドのデプロイにAWS App Runner、フロントエンドにAWS Amplify、そのIaCツールとしてTerraformを使用します。
書籍内にデプロイ関係の詳細な解説はありませんが、運用・監視のための設計に関する説明が後半に含まれています。
現実の新規プロジェクトでもそのまま参考にしやすい実践的な提案と言えるでしょう。

完成形のコードがGitHubリポジトリで公開されており、フロントエンドやインフラ構築コードも含まれているため、読者が自分でAWS環境にデプロイ可能な形になっています。

本書の実装範囲のリポジトリ:
https://github.com/rust-web-app-book/rusty-book-manager

フロントエンドを含むデプロイのドキュメント:
https://github.com/rust-web-app-book/rusty-book-manager-template

独自のレイヤードアーキテクチャの提案

本書の最大の特徴は、独自のアプリケーションレイヤーを通じて、Web APIの構築に焦点を絞った独自のレイヤードアーキテクチャを提案している点です。
広義のレイヤードアーキテクチャは、プレゼンテーション層からインフラストラクチャ層まで、システムを外から内へと水平に層を分けるアーキテクチャパターンです。
このアプローチでは、たとえばレイヤー毎にモジュールやディレクトリ構造を分け、依存先の参照ルールをチーム内で統一することで、プロジェクトの保守性や可読性の向上を目指します。
書籍『ソフトウェアアーキテクチャの基礎 ―エンジニアリングに基づく体系的アプローチ』ではレイヤードアーキテクチャは「小規模なコードベースに対してもコストパフォーマンスの良い形で適用可能な点」が評価されています。
本書では、モジュールの境界をapi, kernel, adapterのレイヤーごとに設定し、registryにrepositoryのインターフェイスを定義して依存します。
それをCargo Workspaceを用いて各レイヤーを個別にビルドできるように設計されています。

このアーキテクチャの考え方は、Rustに限らず、さまざまな薄いフレームワーク(マイクロフレームワーク)でも適用できる点で興味深いです。
たとえば、GoやPythonのFastAPI、TypeScriptのHonoなどで実装している時にも同じ課題を抱えます。
これらのマイクロフレームワークは、MVCのように機能ごとのモジュール構成をあらかじめ提案するのではなく、設計方法に意見を持たない構造であるため、開発者が自らアーキテクチャを設計し、実装していく必要があります。
なので、フレームワークのコミュニティごとに解決するミドルウェアやライブラリが活発に開発されています。
この自由度の高さにより、言語ごとの特性を活かした構成が可能になるため、本書ではRustのエコスステムを学ぶ上でも優れたアプローチといえます。
本書の設計思想は先のとうり現場での実践を想定しているので、著者陣が「今仕事でRustを書くならこんな構成」という意見を提供してくれていると言えるでしょう。

とはいえ、まだRustを使ったWeb開発にはデファクトなパターンが存在しないため、読者もそれを考慮する必要があるでしょう。
実際、本書の刊行後にも著者のhelloyukiさんによって改善案が検討されており、たとえばエンティティを横断するロジックをService層に集約する構成が提案されています。

speakerdeck.com

このService層の考え方についても、各コミュニティには異なる流派があり、DDD(ドメイン駆動設計)やマイクロサービスの実践においてさまざまなアプローチが存在しておもしろい点です。

おわりに

『RustによるWebアプリケーション開発 設計からリリース・運用まで』は、現場のエキスパートによる実践的な知見が詰まった一冊です。 Rustを学びたいが、どこから手をつければよいかわからないというバックエンドエンジニアにとって、最適な入門書といえるでしょう。

PS: 電子版が出るそうです

*1:似ている本:詳解Go言語Webアプリケーション開発のRust版のような構成です

How to be a tech influencer.(2021)を技術ブログ論として読むと良かった

テック業界で影響力を持つためには

lethain.com

"How to be a tech influencer."には、「テック業界で影響力を持つためにはどうすればいいのか?」という相談者の問いから「質にフォーカスした少数のコンテンツでプレステージ(評判)を築くのが効果的」との説明が述べられています。

この記事を書いたのは、『エレガントパズル』や『スタッフエンジニア』の著者であるWill Larsonで、彼はエンジニアリング組織の技術リーダーシップの専門家としても知られています。
近著『The Engineering Executive's Primer』の「Chapter 12: Building Personal and Organizational Prestige」には、このブログ記事の内容が含まれており、組織の技術トップにおいて個人および組織の評判を築くことの重要性が掘り下げられています。

プレステージ(評判)とは

ここでいうプレステージとは、周囲の人々があなたやあなたの会社について良いイメージを持っている状態を指します。
本記事では固有のニュアンスを持っているのでプレステージという言葉をそのまま使います。
これはブランディングやマーケティングのような能動的な活動とは異なり、優れた仕事や質の高いコンテンツを通じて自然に形成される他者の意識です。
このように築かれた評判は、キャリアや人材獲得においても有利に働き、長期的に信頼される存在となる基盤を提供するとされています。

影響力と技術ブログ

私はこれを技術ブログ論としての側面から注目して、Will Larsonが影響力の解釈を「人々に業界にある既存の考え方や価値観の変化を促せること」としている点に感銘を受けました。
これは私が普段ブログ執筆で達成したいことと近く、同じレベルにはまったく達していないものの(名前は似ているが)、目標として繰り返し参考にしたいと感じています。
つまり知名度ではなく影響力を持つためには質の高いコンテンツを制作するための戦略が求められているわけです。

プレステージを構築する方法

プレステージを構築するためには、すでに評判の良い集団に参加するのが最も近道だと説明されています。
例えば、開発者体験が良いイメージのある企業ランキングの上位企業に所属して、企業の持つ発信力の一員として名前を出して参加する、ということが該当するかもしれません。
しかし、居住地や環境の制約から、それを実現できる人ばかりではありません。 あいにく私もそのような機会がありませんでした。
そこで、再現性の高い方法として質の高いコンテンツを作ることに注力しましょう。
コンテンツは量産するよりも少数でも質の高いものを作るべきであり、さらにそのコンテンツにアクセスしやすくするのがキーポイントです。

影響力の指標をどう計測するのか

そもそも影響力の適切な指標を持つのは難しい問題です。
それをどのように測定するかについては、多くの議論の余地があります。
PVやフォロワー数、売上、投稿数といった数値は一般的な指標として使われがちですが、それらはしばしば誤った指標とされています。
なぜなら、これらの数値はコンテンツの質や影響そのものを必ずしも反映しないからです。
Will Larsonは「コンテンツが人々の行動や考え方にどのような変化をもたらしたかや、あなたにアドバイスや意見を求めてくる人の数は、影響力を測るための重要な指標といえるでしょう。 」と言及しています。
私はこれを読んで今までまるで関心のなかった匿名質問受付サービスの有効活用法を見出しました。
確かに私の思う影響力の高い人々は匿名質問受付サービスに熱心に回答している気がします。
そして私は質問が全然来たことはないので影響力のなさを痛感しました。

質の高いコンテンツを作るために

質の高いコンテンツを作るには、普遍的なテーマと独自性のある視点が必要です。
これらの要素が揃うことで、コンテンツは長く参照されるものとなります。
特に、繰り返し議論されているようなニーズのあるトピックを選ぶことが重要です。
たとえば、日本のテック業界で多く言及されている「質とスピード」に関する講演は、普遍的なテーマを扱いながらも独自性を持った視点を提示しており、質の高いコンテンツの好例だといえます。
このようなコンテンツは、議論を呼び続ける力を持ち、時代を超えて価値を提供し続けます。

自分に合った形式で発信する

そして、自分に合った形式で発信します。 Will Larsonは、ブログやカンファレンスでの講演といった形式が最適と説明しています。
十分に短く細かい試行錯誤のフィードバックループが回しやすいからです。
これらに比べてポッドキャストや書籍は反復のサイクルが長く、難易度の高い形式といえます。
私自身、ポッドキャストを聞いたり本を読むことは大好きですが、それを自分で作るとなるとハードルが高く、未だに手を出せていません。
それでも、fukabori.fmなど現にポッドキャストを中心に質の高いエンジニアリングのコンテンツで影響力を発揮しているといえるクリエイターも存在します。
自分に適した形式を選ぶことでコンテンツを持続的に発信しやすくなる点は大切だと考えています。

プレステージを構築するためには数年の期間が必要

プレステージを構築するには、少量の質の高いコンテンツを数年かけて繰り返し発信することが必要です。
しかし、プレステージは受動的な結果であるため、活動時間に対して定量的な成果が得られにくい特性があります。
それゆえ、持続する努力が不可欠です。 そのためには、標準を定めて一球入魂の姿勢で取り組むことにしています。
実際に、当サイトでさえも一時的なバズで消費される記事と、それを超えて繰り返し参照され言及され続ける記事*1に二分化していることからも、持続性と質がいかに重要であるかが分かります。

デリバリーの戦略

作ったコンテンツを多くの人に見てもらうには、デリバリーにも戦略が求められます。
その目的は、ターゲット層がコンテンツにアクセスしやすい環境を整えることにあります。
これに関してできることはたとえば、ターゲット層が参加しているコミュニティに自分も積極的に関わったり、年齢層に応じて適切なSNSを選択したりすることが挙げられます。
私は個人開発者や特定のOSSユーザーが集まるコミュニティや、シニア層が多い「はてな」、若年層が集まる「X」クラスタなどを意識的に活用するすることにしています。
また、評判の掛け算を生み出すために、コンテンツをシェアしてくれる読者を作ることもその助けになります。
私にとっては、@mizchiさんや@azu_reさんのような、以前から認知があり業界内で評判の高い人によるシェアが、このサイトへの多方面から多くの人が訪れるケースになっています。
さらに、質を保ちながら継続的に発信を続けることで、認知度を着実に高めることができます。
私はとくに文章を書く習慣が途絶えると、質を担保する前提である執筆活動ごと生活の中からなくなりやすい性格のため、「日記を書く」というリマインダータスクを毎日設定し、発信を習慣化しています。

最後に:批判との付き合い方

あなたの発信に対して多少の反対意見が来るのは、既存の思考を変革するものである証拠として、むしろ良い兆候といえる、とWill Larsonもコメントしています。 これには同意です。
ただし、短期的な議論を呼ぶことを目的とした内容や表現に手を染めるのは望ましくありません。 それでも自覚してコントロールは難しく、私も意図せずこの状態に陥り、後から反省しています。
私の場合、影響力の度合いはウェブ上でどのような反応があるかを指標として活用しています。
むしろ何も反応はないがとりあえずシェアされる、というのが十分な行動を引き出せなく不甲斐なさを感じる場面です。
賛成する感想を持つ人がいた場合、それは自分が届けたい読者のリストに追加すべき対象になります。
一方で、異なった考えを持つ人がいたら、その人の立場を理解しようと努めます。
また、正確に伝わっていない人がいた場合には、コンテンツの内容や記述方法を見直し、内容に誤りを発見したら加筆や訂正を行います。
このように、周囲の反応を活かしながら改善を続けることで、より多くの人に影響を与えるコンテンツを目指していきたいですね。

*1:繰り返し参照され言及され続ける記事: https://laiso.hatenablog.com/entry/nope-sql とか

私的Chromeカスタム検索エンジン利用頻度ランキング

Google Chromeのカスタム検索エンジン機能は非常に便利です。

support.google.com

設定したキーワードをアドレスバーに入力するだけで、指定したサイト内で直接検索ができるようになります。
例えば、「yt」をYouTubeの検索キーワードとして設定すれば、アドレスバーに「yt キーワード」と入力するだけでYouTube上で検索が完了します。
いちいちサイトにアクセスして検索フォームに入力する手間が省け、キーボード操作のみで素早く目的の情報に辿り着けます。
私はこの機能を頻繁に利用しており、使えない環境ではストレスを感じるほどです。

集計について

そこで、この機能の活用を布教したり、まだ知らないカスタム検索エンジン設定について他の人から教えてもらったりするために、普段使用しているChromeの設定を集計してみました。そこからトップ20のカスタム検索エンジンを抜粋し、その利用用途や背景を紹介します。
集計方法としては、Chromeプロファイルの内部データベースを参照することで、各設定の利用回数を確認することが可能です。
むしろ、公式なエクスポート機能は見当たらず、一部の拡張機能で対応できるようですが、私はそれを使用していません。
このデータベースはSQLiteファイルとして保存されており、以下のパスにあります。ただし、Chromeが起動中はデータベースがロックされているため、一旦Chromeを終了し、SQLiteクライアントを用いて開く必要があります。

# macOS
❯ sqlite3  ~/Library/Application\ Support/Google/Chrome/Default/Web\ Data

sqlite> select * from keywords order by usage_count desc;

第1位:Google(ja)

short_name keyword url
Google(ja) ja https://www.google.co.jp/search?q={%s}&lr=lang_ja

Google検索が利用頻度の第1位にランクインしています。
なぜ専用のカスタム検索エンジンに登録しているかというと、英語のキーワードで日本語のみの検索結果を得たいときに便利だからです。
"javascript"や"llm"関連の技術用語で情報を探すことが多く、このような検索では日本語のコンテンツを優先したいことも多いため、この設定が役立っています。
その結果、自然と使用頻度が最も高くなり、納得の第1位と言えます。

第2位:Twitter Search (ja)

short_name keyword url
Twitter Search (ja) twj https://twitter.com/search?q=lang%3Aja+{%s}&src=typd

Google検索のX(元Twitter)版です。技術用語の検索頻度が高いので納得の第2位ですね。

第3位:perplexity.ai

short_name keyword url
perplexity.ai pe https://www.perplexity.ai/?q={%s}

ウェブ検索した結果をサマリして聞きたいことに関する直接の回答を文章とソースで教えてくれます。質問が明確な時に利用します。 以前有料版を使ってレビューを書きましたが、現在は無料版ユーザーです。

laiso.hatenablog.com

英語で検索したいときは質問を英語で打ち込みます。毎回翻訳ツールを使うのは長期的にみて効率が悪いため自作GPTで瞬間英作文の機会として活用しています。

chatgpt.com

第4位:Twitter

short_name keyword url
Twitter tw https://twitter.com/search?q={%s}&src=typd

英語で Twitter(元X)をざっと検索したい時に使います。

第5位:Hatena::Bookmark

short_name keyword url
Hatena::Bookmark b http://b.hatena.ne.jp/search/tag?safe=on&q={%s}

過去に話題になった記事を検索したい時に利用します。2000年代からのユーザーたちの登録データの蓄積が強みです。一般的なウェブ検索では到達しづらいに記事も発見できます。IT系の話題に偏っています。英語版はHackerNewsかDaily.devですね。

第6位:amazon.co.jp

short_name keyword url
amazon.co.jp a http://www.amazon.co.jp/s/ref=nb_sb_noss_1?field-keywords={%s}

書籍や商品情報を検索します。技術書が多いですね。

第7位:Google(US)

short_name keyword url
Google(US) en https://www.google.co.jp/search?q={%s}&lr=lang_en

日本語とは逆に英語のみで検索したい時に利用します。

第8位:Google Books

short_name keyword url
Google Books gb http://www.google.com/search?q={%s}&tbm=bks&tbo=1&hl=ja&qscrl=1

Googleが出版社から提供を受けている書籍のスキャンデータから検索できます。登録されている本は限られています。キーワードをもとに本を探したいときにプレビューまで見られて便利です。一般的なキーワードでウェブ検索より信頼性の高い情報をもとめて検索することもあります。

第9位:Wikipedia (ja)

short_name keyword url
Wikipedia (ja) w http://ja.wikipedia.org/w/index.php?search={%s}

日本語Wikipediaから検索します。百科事典的に使います。脚注を辿って出どころに近い情報を探すリンク集としても便利です。

第10位:1

short_name keyword url
1 1 https://www.google.com/search?q={%s}&tbs=qdr:y&qscrl=1

「1」は直近1年のGoogle検索結果を見るためのショートカットです。技術情報はよく期間を絞りたくなるため利用します。

第11位:Android Market

short_name keyword url
Android Market am https://play.google.com/store/search?q={%s}&c=books

Play Storeから検索します。Androidアプリはウェブからインストールしているのと、読み上げ機能の優秀なPlay Booksで一部の書籍を購入しているので使います。

第12位:GitHub Code

short_name keyword url
GitHub Code gc https://github.com/search?q={%s}&ref=simplesearch&type=Code&utf8=✓

GitHubのコード検索です。ライブラリの関数名で検索し、実際のOSSでどのように使われているか参考にしています。代替として https://sourcegraph.com/search もちょっといいと思っている。

第13位:Google US around 1 year

short_name keyword url
Google US around 1 year en1 https://www.google.com/search?q={%s}&lr=lang_en&tbs=lr:lang_1en,qdr:y

直近1年のGoogle検索結果を見るためのショートカットの英語版です。

第14位:amazon.com

short_name keyword url
amazon.com com http://www.amazon.com/s/ref=nb_sb_noss?url=search-alias%3Daps&field-keywords={%s}

Amazon.comの方で検索します。洋書用ですね。

第15位:EIJIRO Web

short_name keyword url
EIJIRO Web e http://eow.alc.co.jp/{%s}/UTF-8/?ref=sa

アルクの英辞郎ウェブで例文を調べます。ローカルの辞書も持っているので単語の意味レベルだとそっちを使っています。

第16位:Goo辞書

short_name keyword url
Goo辞書 goo http://dictionary.goo.ne.jp/srch/jn/{%s}/m0u/

日本語辞書として使います。記憶の曖昧な特定の言葉の正確な使い方を調べるときに使います。

short_name keyword url
GPT search gpt https://chatgpt.com/?q={%s}

ニューフェイスです。ChatGPTがウェブソース検索に対応したのでperplexityと比較するために試しています。公式Chrome拡張は検索バーを乗っ取るので入れない方がいいですね。

第18位:GPTs

short_name keyword url
GPTs gp https://www.google.co.jp/search?q=site%3A%2F%2Fchat.openai.com%2Fg%2F+{%s}&lr=lang_en

公開されているGPTsを探します。他人の作ったGPTが便利と思った場面は実はあまりなく、自分で普段使っているプロンプトテンプレートを収めて置く場所としてGPTsは便利に使っています。

第19位:PyPI

short_name keyword url
PyPI pypi https://www.google.com/search?q=site%3Apypi.python.org%2Fpypi%2F+{%s}

Pythonライブラリを探します。他にnpmやgem版があります。

第20位:HB Entry

short_name keyword url
HB Entry h https://www.google.co.jp/search?q=site%3Ab.hatena.ne.jp/entry/%20{%s}&ie=UTF-8&sa=Search&cad=h&qscrl=1

はてなブックマークの検索よりGoogleインデックスから検索した方がいいのではと思っていた時期に登録したやつ。今はあまり使っていないです。

その他

  • Kagi Search
  • Google Scholar
  • 中国語ページのみ検索
  • MDN
  • HackerNews
  • Unix manpages
  • Mac Developer Library など

今年のLinuxデスクトップ元年はひと味違う。それは、Omakubがあるからだ。

omakub.org

DHHとApple

もともと20年来のMacユーザーでTextMate原人であったDHHだが、HEYアプリが何度もAppStoreでリジェクトされた出来事を通じてか、次第にApple反転アンチ化してきた。
元々オルタネイティブな嗜好を持つDHHだったが、脱クラウド運動などの、近年の彼らのビックテックとの闘争にもつながっている。
年初あたりから自社の支給端末であったMacBookのリプレイスを検討し始め、Windows+WSL2やVSCode*1 、そしてLinuxデスクトップの利用を模索し始めていた。
最終的にUbuntuデスクトップを「安住の地」とし、そのセットアップの知見をすべてOmakubに込めたのだ。
エディタをNeovimに*2、スマホもSamsungに乗り換え*3、そしてFrameworkのラップトップを購入。
「ラップトップ買ってきましたUbuntu環境構築エントリ」を実行可能なOSSで公開してしまう男、それがDHH。

world.hey.com

Omakubの概要

Omakubは、ウェブ開発向けのデスクトップ環境を自動で構成してくれる「オマカセUbuntuセットアップツール」だ。
オマカセ(Omakase)という言葉は、アメリカの寿司レストランでシェフにコース料理の選定を丸投げするスタイルを指す*4
Omakubが寿司屋の大将のように、新鮮なドキュメントツールがありますよとObsidianをデフォルトでインストールしてくる。
さらにちゃっかりHEYやBasecampも組み込まれてくる。

Omakubは、Linuxディストリビューションや他のセットアップフレームワークとは異なり、セットアップそのものを提供するツールだ。
その構造は、AnsibleHomebrew Cask、古のPuppetベースのBoxen*5を彷彿とさせるが、大きな違いは「ノーコンフィギュレーション」にある。
ユーザーは最低限の対話シェルで応答するだけで、x86_64なUbuntu(GNOME環境)が決め打ちされ、シェルスクリプトがもりもりと実行される仕組みだ。
インストールするアプリケーションからデスクトップのテーマや具体的な設定まで全て決まっており、ユーザーはほぼ手間なく環境を構築できるというコンセプトを持つ。
欲しいものを追加で入れたり、不要なものは外すこともできるが、基本的にはOmakubが提供する環境を受け入れることが前提だ。

www.youtube.com

実際のセットアップ体験

ちょうど家でゴロゴロしていたら「Linuxデスクトップ・・作りてえ・・」という気分になったので、実際にセットアップを試みた。
DHH信者の私にとっては推しのインフルエンサーがプロデュースするECサイトで服を買うような感覚だ。
まず、格安のmini PC(Intel Celeron 2コアというヤマダ電機で埃をかぶっていそうなマシン)を購入し、USBメモリにUbuntuのISOファイルを焼いてBIOSから起動、SSDにUbuntuをクリーンインストールした。
その後、wget経由でシェルからOmakubを実行して自動セットアップを進めたが、期待に反して完全自動とはいかなかった。
途中でdockerグループへの追加に失敗して止まり、手動で追加して再実行する必要があった。
さらに、GNOME Shell Extensionsのインストール時にも確認ダイアログが表示され、エンターキーを連打して進めなければならなかった。

PS:全くお勧めではないですけど格安mini PCはこれです。

デスクトップ環境の評価

何はともあれ無事セットアップ成功して結果として、macOS風のデスクトップができあがった。
かつてのLinuxデスクトップのmacOS風テーマはどこか統一感に欠け、「これじゃない」感が強かったが、おそらくUbuntuやGNOMEコミュニティのデベロッパーたちの長年の努力によって、現在はかなり洗練されているものになっていて、驚かされた。
macOSそのものではないが、代わりとなる美しいデスクトップ環境(DE)に仕上がっており、Omakubが提供するオルタナティブとして十分に魅力的だと思う。
このことからOmakubは(DHHがそうであったように)長年Macでウェブ開発していたような開発者層の乗り換え先として意図していると思われる。

開発環境の構成

Omakubのコアとなるインストールアプリケーションは、主にCLIオペレーションとウェブの開発環境の構築に焦点を当てている。
まず、ターミナルエミュレータとして「Alacritty」が導入され、シェルやTUIツールのウィンドウ基板(btopとか)として利用される。
また、画面分割に「Zellij」が導入され、Alacritty内で子ウィンドウを管理する(screenやtmuxの代替となる)。
エディタは「Neovim」が採用されており、ほぼLazyVimそのままだ。
DHH自体はIDEやコード補完をいっさい使わないらしい*6。ル・マンレーサーにCopilotは不要なのだ(助手席がないからな)。
さらに、デスクトップアプリが存在しない場合はGoogle Chromeのショートカットが作成される。
ビックテックはゆるせねえがChromeショートカットは便利でPWA最高(Firefoxにはこの機能がなかった)。

開発ツールとしては、デフォルトでRailsとNode.jsがMise経由で入る。Rustはrustupから、PHPはapt経由で入る。最新版のみだが、必要ならMiseで手動で追加すればいい。
データベースにはMySQLとRedisを用い、ホストでアプリケーションを実行しながらDBのみDockerコンテナで起動する開発スタイルになってる。


さあ、あなたもOmakubを始めよう。

manual.omakub.org

最近作ってる地味LLMコマンドラインツールたち: site2pdf, askrepo

地味LLMコマンドラインツールとは

ここでいうLLMツールとは、モデルのインプットとアウトプットを繋ぐ「グルーコード」として機能するプログラムのことです。
筆者が現在開発しているツールもLLMをベースにして、従来の作業をより簡便にすることを目的としています。
このツールは単独で完結する価値を持つというよりも、他のツールと組み合わせることでその真価を発揮します。
そのため、外見的には派手さがなく、地味な存在といえるでしょう(コマンドラインツールがそもそも地味の代名詞でありますが)。
例えば、アプリのソースコードを自動生成するような華やかなツールがある一方で、バックエンドで静かにデータを整形するだけの地味なライブラリも存在しているのです。

Gemini系モデルの良いところ

ツールの共通点としては意外とGemini系モデルを活用しています。

Geminiの特徴の一つは、その「トークン長」、つまりコンテキストウィンドウの広さにあります。
具体的には、Gemini 1.5 Flashでは100万トークン、Gemini 1.5 Proでは200万トークンのコンテキストウィンドウが標準装備されており、これは他のモデルと比較しても圧倒的です。
たとえば、GPT-4系のコンテキストウィンドウは12.8万トークン、Claudeは20万トークンであるのに対し、Geminiは数倍以上のトークン数を誇ります。
以前の記事では「GeminiはチャットAIとしてはイマイチ*1」という感想を述べましたが、ツールに組み込む用途ではその長大なコンテキストが有用です。

「対人苦手だけど情報処理能力高くてドキュメントワーク得意」みたいな人間の個性っぽくて面白い。

site2pdf

github.com

site2pdfはその名の通りウェブサイトをPDFに変換してダウンロードするコマンドラインツールです。
リンクをたどって複数のページを1つのPDFファイルにまとめることができるという、古のクローラー・ダウンローダーみたいなものです。
従来のクローラーとの違いはブラウザで見た時と同じように画像やスタイルなどの視覚情報もそのまま保存することです。
どうせAIがどんどん進化して中身を読めるようになるだろう、という見当でそうしました。

モチベーション

各種AI系の検索拡張生成(RAG)や質問応答(QA)サービスに、複数ページをまとめたPDFファイルはデータセットとして活用できます。
今までは「ウェブサイトをAIに食わせて何かやる」という場面ではpythonでクローラーを書いたり、URLをちまちまコピペしていましたが、世の中のサービスがインポート元としてPDFを受け入れるようになってきたのでPDFで用意すればいいんじゃないか? と発想しました。

ツール自体がGemini APIにアクセスしているわけではないですが、NotebookLMにPDFをインポートしたり、Gemini APIを使った処理を行うことができます。
そのNotebookLMをどう使っているのかについては以下の記事で書きました。

laiso.hatenablog.com

類似ツール

wkhtmltopdfがありますがリンクをたどらないし、そもそも更新が止まっています。

使い方

Node.jsがマシンにインストールされている必要があります。 ターミナルで次のコマンドを実行します

npx site2pdf-cli "https://www.typescriptlang.org/docs/handbook/" "https://www.typescriptlang.org/docs/handbook/2/"

out/ディレクトリにPDFファイルが保存されます。 以下引数の説明です。

npx site2pdf-cli <main_url> [url_pattern]
  • [url] : PDFに変換するWebサイトのメインURLです。
  • [url_pattern] : サブリンクをフィルタリングするためのオプションの正規表現です。 デフォルトでは、メインURLドメイン内のリンクのみが一致します。

注意点

数十ページを超えるような大規模なサイトをPDFに変換する場合、URLパターンを指定して変換するページを絞ることをお勧めします。 またデフォルトでCPU個数ぶん並列でダウンロードします。
アクセス方法はサイトの案内に従い自身で判断してください。ボロい図書館サイトは避ける、とか。  

実装方法

  1. puppeteer を使用して入力されたURLに移動する
  2. url_pattern に一致するすべてのサブリンクを見つける
  3. pdf-lib を使用して各サブリンクのPDFを生成する
  4. それらを単一のドキュメントにマージする
  5. URLに基づいて名前をつけて最終的なPDFファイルを保存する

TODO

  • [ ] robots.txtに準拠する
  • [ ] JavaScriptのレンダリングを待つ
  • [ ] 配布時のtsxの依存をなくす
  • [ ] ページのスクリーンショットを取得するバージョンを検証する

askrepo

github.com

askrepoはコードベースの理解を深めるための補助ツールです。
Gitで管理されたソースコードファイルから情報を抽出して、Gemini APIを使用して質問に対する回答をします。
コマンドラインからソースコードのパスと質問を受け取ります。
その後、ソースコードファイルの内容をGemini APIに送信し、APIの応答から回答を生成します。

モチベーション

OSSのソースコードを読む際に、不明な部分や理解できない部分があるときに、今まではチャットサービスにコピペして質問するか、チェックアウトしてCopilot Chatに聞いていました。
しかし、これらの断片的なソースコードはコンテキストが欠如しているため、質問に対する回答が不十分であることが多いです。
Copilot Chatも一見ローカルインデックスからいい感じに検索して回答を生成しているように見えますが、リポジトリが大きくなると実際には結構コンテキスト不足で幻覚を見ています。
これを解決するためには、検索一致部分を改善するか、もしくはコードベース全体を送信できる分だけ一気に送信することが必要であると思っていました。
その時にGeminiの200万トークンのコンテキストウィンドウのリリースを受けて、これを実現できると考えました。

面白い使い方としては「バグを探して」と頼むとコードレビューをしてくれました。
コードリーディングの目的で作ったけど、そっち方面でブランディングしていった方がいいかもしれません。

類似ツール

筆者を含め、幾らかの人達が類似のTIPSを公開していますが*2、全体エクスポートではなく質問毎に範囲指定するツールとして提供されているものは見つかりませんでした。

zenn.dev

使い方

Rustツールチェインのcargoがマシンにインストールされている必要があります。
なんでRustかというと、使いたかったからです。

それにGemini APIキーが必要です。 APIキーは、https://aistudio.google.com/app/apikeyから取得できます。
取得したAPIキーは、環境変数GOOGLE_API_KEYに設定します。

ターミナルで次のコマンドを実行します

cargo install askrepo
export GOOGLE_API_KEY="YOUR_API_KEY"
askrepo --prompt "What is the purpose of this code?" ../your-repo/src
  • [BASE_PATH] : ソースコードファイルを含むディレクトリを指定します。
  • [OPTIONS] : 以下のオプションを指定できます。
    • -p, --prompt : ソースコードに関する質問を指定します。 デフォルトは "Explain the code in the files provided" です。
    • -m, --model : 使用するGoogle AIモデルを指定します。 デフォルトは "gemini-1.5-flash" です。
    • -a, --api-key : Google APIキーを指定します。 環境変数GOOGLE_API_KEYで設定している場合は省略可能です。

注意点

ソースコードの取り扱いはご自身で判断してください。Gemini APIに送信してよいかどうか。銀行案件を自宅に持ち帰らない、とか。
またコストはGoogle CloudのGenerative Language APIのメトリクスで確認できます。

実装方法

  1. Gitリポジトリの特定のパスのファイル一覧を取得する
  2. .gitignoreを除外するため
  3. バイナリファイルを除外する
  4. {path}\t{content}\nのTSV形式にしてプロンプトに詰め込む
  5. Gemini APIにから回答を得る

TODO

  • [ ] バイナリで配布する
  • [ ] Geminiの制限を超えた時に分割して送信する
  • [ ] ストリーミングで出力する
  • [ ] セッションを作り継続的に会話できるようにする
  • [ ] .gitignoreのリスト除外できればいいのであってgitコマンドを呼び出す必要はないのでは????

コンテキストに収まらない量の時はときはGemini APIがRESOURCE_EXHAUSTE(429)エラーを返してきます。

おわりに

この記事では、著者が開発している地味なLLMコマンドラインツール「site2pdf」と「askrepo」について紹介しました。
Gemini系モデルの広いコンテキストウィンドウを活用して日々の作業を自動化することができました。

生成AI/LLMを使ったウェブサイト開発

週末にちょっとしたウェブサイトというかリンク集(?)を作った。 今回は生成AIツールをフル活用していつもより効率よく作業ができた。

生成AIツールについては日々、新しいものがヤバイすごいと宣伝されているけど、実際にどう使っているのかという情報が少ないと感じている。
なので具体的な使い方を書いてみることにした。

作ったもの

『最も重要な「最も重要なマンガ10選」10選』は「最も重要なマンガ10選」であげられている各作品を読み始めるためのリンク集です(なんのこっちゃ)。

manga-anond.lai.so

「最も重要なマンガ10選*1」は、はてな匿名ダイアリーのミームで、各投稿者が雑誌ごとに全期間を対象としておすすめ作品をあげて寸評していくというもの。
それをみて読者も感想や自分のおすすめをコメントするわいわいしたやりとりがある。
話題的に過去語りが多く、中年うけがいい。

私もいくつか知らない作品があって気になっていたのでリストを作って順番に読んでいた。
そのリストをサイトとして公開した。

このサイトはシンプルな一画面で、リストのタイトルとリンク、コメントを表示するだけのもの。
リストははてな匿名ダイアリーの記事をスクレイピングして取得し、AmazonのAPIを使ってリンク先を取得している。
リンクにアフィリエイトタグはつけていない。
というか便乗アフィサイトが出現したらいやだなぁと思ったので先に自分で作成した。 私は購入したものだけアフィリエイトタグをつけるポリシーをもっている。

開発の概要

生成AI/LLMツールを効果的に活用することで、ウェブサイト開発の効率を向上させることができた。
主なポイントは以下の通り:

  1. デザイン段階でのClaudeの活用:初期デザインの生成に Claude Artifacts を使用した
  2. コーディング作業Cursor を使用して、AIアシストによるコード修正や提案を活用した
  3. データ処理におけるLLMの活用:スクレイピングしたデータの構造化やAmazon商品データの選別にGPT-4 Turboを使用し、複雑なデータ処理を自動化した
  4. 動的・静的コードの使い分け:プロトタイピングの段階では動的なアプローチを、本番環境では静的生成(SSG)を採用し、開発の柔軟性とパフォーマンスの両立を図った
  5. 拡張性を考慮したアーキテクチャ設計:静的サイトをベースにしつつ、将来的な機能拡張に備えた構成を採用した
  6. 柔軟なデータベース設計:Firestoreを採用することで、LLMの出力結果を直接保存でき、将来的なデータ構造の変更にも対応しやすい設計とした

最終的なアーキテクチャ

カテゴリ 使用技術
デザインツール Claude Artifacts
Cursor
フロントエンド Next.js(Static Exports)
shadcn/ui
Tailwind
バックエンド
(サーバーレス)
Firebase Firestore
Vercel AI SDK
インフラ Cloudflare Workers(Static Assets)

UI開発に生成AIツールを使う

初期デザインの参考元

最初の発想時点でこれはカタログサイトになると思っていたので、似たようなマンガ系のサイトをいくつかチェックして、他にどのような構成やデザインが使われているかを確認した。
さらに、ECなどマンガ以外の類似サイトも調べて、インスピレーションを得るように努めた。
その結果、クックパッドの新デザインがTailwindを活用しており、自分の好みにぴったりで参考にしたいと感じた。
モバイルでクックパッドの画面をChromeのDevToolsで改変して機能を削減、スクリーンショットして、これを生成AIツールに渡すために保存しておいた。

デザインツールの選定と比較

ウェブサイトのコーディングを自動化する生成AIツールはいくつか選択肢がある。 今回はClaudeのArtifactsが作ったデザインをベースにした。

比較検討した主なツールと選定理由:

  1. Claude Artifacts(採用)

    • 特徴:生成物をプレビューする汎用的機能。プロンプトでshadcn/uiベースのコーディングを頼んだ
    • 選定理由:最初の生成物の品質が高かった
  2. ChatGPT Canvas(不採用)

    • 特徴:OpenAI「Artifactsっぽいやつを俺たちも提供するぞ」
    • 不採用理由:シンプルに成果物がしょぼく、自分自身でコーディングしたぐらいのレベルのものしか生成できなかった
  3. v0(不採用)

    • 特徴:Artifactsを今回のようなプロトタイプ生成に特化。コードをユーザーが変更して調整できる
    • 不採用理由:Claude Artifactsと大きな差異がなかった。モデルが同じ(claude系)であることが原因と考えられる
  4. Bolt(不採用)

    • 特徴:プロジェクト全体を生成
    • 不採用理由:部品的な取り込みが難しかった。モデルはclaude系

総じてUIのコーディングはClaudeのが得意、というのが分かった。
ツール上で細かい部分まで詰めたい場合はv0の方が良さそうだが、私は「あとはCursorさんとローカルでやりますんで」と切り上げたのでArtifactsで間に合った。
またプロジェクトの全体コードごと丸投げしたい場合はBoltもいい選択だと思う。コンポーネントのファイル分割を適切に行ってくれた。

Next.jsの利用

そして、Artifactsが生成するshadcn/uiのデザインを活用するために、Next.jsを選んだ。
shadcn/uiに加えてTailwindやradix-ui/も含まれており、これらをパツイチでビルドするためにNext.jsが最適だ(帰納的)。
ただし、この条件ならRemixを使用するのも選択肢の一つである。
Next.jsのが普及しているので構成トラブルが少ないと判断した。

Cursorを活用した開発

画面の更新作業にはCursorを使った。
Cursorの機能を活用することでNext.jsアプリのコード修正作業の効率が上がった。
デフォルトのモデル設定はClaude 3.5 Sonnetにしている。
Cursorでは、チャット上でソースコードの修正指示を出すと、diffを提案し、それをワンボタンでマージできる。
エディタとチャットサービス間をクリップボードで運搬するという人間が行うコピペプログラミングの本質的な作業をぐっと煮染めたようなUXである。
Next.jsのFast Refreshで、変更がすぐに反映されるのでフィードバックループも短縮される。
エディタがGitと連携しているので、万が一の際に気軽にロールバックできる点も安心だ。
また、Composerという実験的機能もあり、複数ファイルを横断して編集することもできるが、今回は1ファイルを中心に作業したため、活用しなかった。

データ整形にLLMを使う

スクレイピング

最初にはてな匿名ダイアリーの記事をLLMを活用してJSON形式に構造化し、データベースに保存するプロセスを構築した。
記事URLはせいぜい10個なので自分で探した。 URLを渡すと、記事のタイトル、本文、コメントを取得するスクリプトを作成した。
まず、各記事のURLから記事本文を取得し、そこからタイトルとコメントを抽出する。
次に、これらの要素をgpt-4-turbo(Vercel AI経由)を使ってJSONフォーマットに整形した。
最終的に、生成したJSONデータをFirestoreに保存する。 これを後工程で利用する。

作業の前にまずWebコンソールでこのプロンプトが機能するかを検証した。

データ抽出にはcheerioを使った。
はてな匿名ダイアリーは環境に優しいサービスなのでブラウザ上で電力を消費してビューの差分を書き換えたりしない。
そのようなサイトにはヘッドレスでブラウザと同じAPIが使えるcheerioがフィットする。

Amazonの商品データ取得

Amazonの商品データ取得には、PA API:Product Advertising API 5.0を使用した。
ASINが判明すると、その商品に対応するサムネイル画像とリンク先も確定できる。
まずデータベースに保存したタイトルを使ってPA APIで検索を行う。
その検索結果からシリーズの初巻を選ぶためにLLMに判断を任せた。
検索結果が必ずしも巻数順に並んでいるわけではないためルールベースで選ぶのは難しい。

これも実装前にまずWebコンソールで機能するかどうかを検証した。

LLMの選定

LLMにはgpt-4-turboを採用した。
Vercel AIのドキュメントに載っていたデフォルト設定*2をそのまま使用し、実際に試したところ精度に問題がなかったため、特に調整せずにそのまま取り入れた。
Vercel AIを利用しているため、精度やコストに不満があれば他社のモデルやローカルLLMに切り替えられる柔軟性もある。
APIが抽象化されているのでコードの変更もいらない。

以下にzodを使ってレスポンスをJSONに整形する方法が書かれている。

sdk.vercel.ai

コストについてはあまり気にしていなかったが、今回の作業全体で約10ドル程度に収まった。
単発の課金なので、許容範囲内だと感じた。

継続利用して料金高すぎと感じたらgpt-4-oやローカルLLMにスイッチする算段もあるので、gpt-4-turboな理由は最初の選択肢でしかない。
デフォルトがgpt-4-turboであるのはAI SDKの開発者の人によると意図はあるらしく、Toolsを使った多段の論理処理では安定する感覚があるらしい*3

動的なコードと静的なコードの使い分け

開発プロセスを効率化し、柔軟性を保ちながらも手早くサイトを立ち上げるために、動的なコードと静的なコードを戦略的に使い分けた。

TypeScriptを使わない範囲を定めた

あえてTypeScriptのコードを避ける範囲を設けることで、プロトタイピングの効率化を図った。
具体的には、データ処理のスクリプト部分などを対象とし、特にスクレイピングにおいては、最初はChromeのDevTools上で現在閲覧しているページに対して手動でスクレイピングを試した。

その結果、期待するデータが得られた段階で、最終的にNode.jsのコードに移行して自動化した。
スクリプトはJSにする、という方法はOSSプロジェクトでも自然に行われている。たとえばRemixもそうだ(remix/scripts at main · remix-run/remix)。

他にはNext.jsアプリ内のデータフェッチ関数の初期実装を進めるにあたり、まずNode.jsコンソール(REPL)でfirebase-adminを呼び出して試行錯誤し、どのコードを実行すればどのような結果が得られるかを確認した コードが複数行にわたるようになったら、.mjsファイルとしてbin/ディレクトリに配置し、組んだロジックが正常に機能するかを確認する。
この際、VSCodeではCtrl+Alt+Nで手軽に実行とデバッグができ、効率的に検証が行える。

その後、UIに渡すデータ構造が固まったら、型定義を作成し、lib/ディレクトリに移動して清書し、最終的にTypeScript化してアプリに組み込む準備を整える。
このように段階的に進めることで、いきなりpageコンポーネントと接続したコードに手をつけるよりも、データ処理の部分を確実に作り込むことができた。

静的サイト生成(SSG)の採用

この効率化の考え方をサイト設計にも拡大し、Static Exports(SSG:すべて静的なサイト生成)を採用する方針とした。
閲覧時にはすべてのコンテンツが事前に確定している状態となり、Cloudflare CDNにすべてのファイルを配置することで、アクセスの高速化を図る。
アーキテクチャが確定した段階でまずデプロイしてPageSpeed Insightsでパフォーマンスを測定し、深刻な結果が出ないことを確認した(Largest Contentful Paintは予測していた範囲だったので許容した)。
さらに、この静的サイトにはリンク集以外の機能を持たせる余地も残しており、必要に応じてNext.jsやサーバーサイドの機能を用いて動的な要素を追加できるように、デプロイ先をCloudflare Workersにした。
これは過去の開発の経験から「ペライチの静的サイトだと思っていたら、複数画面のSSR対応が必要になってアーキテクチャを作り直した」という事態を避けるためである。
このアプローチにより、シンプルながらも拡張性のあるサイト設計が実現できた。 コンテンツは静的に、アーキテクチャは動的にという考え方になる。

柔軟なデータベース設計

これは、データベースにFirestore(動的スキーマでNo SQL)を採用していることとも関係している。
一般的には、RDBを選び、JOINに耐えられるように前もって柔軟なテーブル設計を行い、free tierがあるPostgresSQLサービスなど*4を利用するのが個人開発者にとってのファーストチョイスとなりがちだ。
しかし、Firestoreを使うことで、スキーマを決める前に、先のLLMの生成結果をそのままキャッシュとして保存できる柔軟性が得られ、開発中のデータ構造の変更に対しても対応できる。
静的サイトにしたことで、ビルド時のみクエリを実行する形にして開発中は本番DBを管理画面からごちゃごちゃ操作してもデプロイしない限りはサイトに影響がない。
最初はいいけど運用に入ったら作業量のしわ寄せが来るんじゃないの? と思うだろうが、そこを静的サイトにして決定を遅延させている。
サーバーサイド処理をしたくなったタイミングでよいしょとデータをRDBに盛ってくる算段だ。

余談だが、Firestoreのドキュメント設計については1つのビューに必要なデータを1クエリで取得できるようにデータ構造を工夫するのがポイント。

まとめ

生成AI/LLMツールは開発プロセス全体を最適化し、短期間でサイトを立ち上げることができる強力な味方となる。
今回の例では通常の開発の1/2の時間でサイトを完成させることができた(当社比12時間→6時間レベル)。
私はフロントエンドは専門でないため、ClaudeやCursorが生成したコードを元に学習した。もしかしたらこれがAI世代のコード写経に変わるのかもしれない。


あと最後にマンガの話ですが、個人的最高おすすめ作品の『ザ・ワールド・イズ・マイン』は読んでください。

Anthropic Computer Useはどうやって実現されているのか?

答え:スクショからシェルのコマンドに渡す値を生成する

# 開発者が実装する!
await asyncio.create_subprocess_shell("xdotool mousedown 1 mousemove --sync 750 738 mouseup 1")

🤖「ヨシ!」

さらに詳しく

Anthropic Computer Useは、Claudeにコンピューター操作を指示するためのツールセットです。
この機能は既存のMessages APIを拡張する形で提供され、Computer tool、Text editor tool、Bash toolなどの関連ツールを含んでいます。
これらのツールにより、AIはデスクトップ環境の操作、ファイルの編集、シェルコマンドの実行など行うことが可能になります。
実装にあたっては、AnthropicがGitHub上で公開しているデモアプリの参照実装を利用できます。この実装はDocker上で動作し、StreamlitアプリケーションをユーザーインターフェースとしてClaudeとのインタラクションを可能にします。
APIの使用フローは、システムプロンプト、ツール定義、ユーザープロンプトの送信から始まります。Claudeはこれらの入力を基にツールの使用を判断し、実行指示を返します。開発者はこの指示に基づいてツールを実行するコードを実装し、その結果をAIに返します。このプロセスは、タスクが完了するまで繰り返されます。
処理の中核となるのは、ユーザーの指示に基づいてツールを実行し、結果を分析するループです。
Claudeはこのループを通じて、タスクの進捗を評価し、必要に応じて追加のアクションを実行します。例えば、ファイルの作成やテキストの書き込みといったタスクでは、複数のツールを組み合わせて使用し、各ステップの結果を確認しながら処理を進めます。

Anthropic Computer Use の概要

docs.anthropic.com

Anthropic Computer Use は、専用の API として提供されているわけではありません。
既存の Messages API に新しいツール1が追加される形で提供されます。
これらのツールは、computer-use-2024-10-22 という betaフラグを通じて有効にできます。

Messages API で使用可能なツール:

  • Computer tool (computer_20241022):
    • デスクトップ環境を操作するためのツールです。
    • マウスとキーボード操作をエミュレートし、スクリーンショットを取得できます。
    • アプリケーションの実行、テキスト編集、ファイル操作などを実行可能です。
    • 画面の解像度とディスプレイ番号を指定できます。
  • Text editor tool (text_editor_20241022):
    • ファイルの表示、作成、編集を行うためのツールです。
    • デスクトップ環境を必要とせずにファイル操作が可能です。
    • テキスト生成やコーディングなどのタスクに利用できます。
  • Bash tool (bash_20241022):
    • シェルコマンドを実行するためのツールです。
    • デスクトップ環境を必要とせずにコマンド操作が可能です。
    • ファイル一覧の取得、パッケージのインストール、コマンドの実行などが可能です。

これらのツールは Anthropic によって定義されていますが、ユーザーがツールの実行結果を評価する処理を実装して、結果をtool_results として返す必要があります。

処理の実行指示はAPIから送られてきますが、実行処理は開発者が実装します。

Messages APIとの統合:

  • 開発者は、API リクエストにツール定義を含めることで、Claude にコンピューター操作を指示できます。
  • Claude は、ツールの実行が必要と判断した場合、tool_use を含むレスポンスを返します。
  • 開発者は、tool_use レスポンスからツール名と入力を抽出し、対応するツールを実行します。
  • ツールの実行結果は、tool_result を含む新しいユーザーメッセージとして Claude に送信されます。

実装例と使用方法

Anthropic は、Computer Use API を使用したデモアプリの参照実装を GitHub で公開しています。

github.com

この参照実装は、Docker コンテナ内で動作し、Anthropic API(もしくはBedrock、Vertex) を通じて Claude 3.5 Sonnet モデルにアクセスします。

ユーザーインターフェイスとしてStreamlit アプリが含まれています。 これはチャット機能とコンテナ内のデスクトップをリアルタイムに表示する機能を提供します。

デモアプリが操作する対象のシステムはDocker コンテナ内で動作します。
コンテナ内のUbuntuデスクトップに必要な依存関係 (Ubuntu 22.04、xvfb、xterm、xdotool、scrot、imagemagick、sudo、mutter、x11vnc、Python 3.11.6 など) をセットアップします。
ここからPythonでMessages API を通じて Anthropic の Claude モデルと通信し、ツールを利用します。
起動方法については、Anthropic API を使用する場合は、ANTHROPIC_API_KEY 環境変数を設定して Docker コンテナを起動します。 Bedrock または Vertex を使用する場合は、それぞれの認証情報を設定する必要があります。

デモアプリの起動コマンド:

  export ANTHROPIC_API_KEY=%your_api_key%
  docker run \
    -e ANTHROPIC_API_KEY=$ANTHROPIC_API_KEY \
    -v $HOME/.anthropic:/home/computeruse/.anthropic \
    -p 5900:5900 \
    -p 8501:8501 \
    -p 6080:6080 \
    -p 8080:8080 \
    -it ghcr.io/anthropics/anthropic-quickstarts:computer-use-demo-latest

http://localhost:8501 で Streamlitアプリ単体を。http://127.0.0.1:6080/vnc.html でVNCビュワーを。 http://localhost:8080 で Streamlit + VNCビュワーをiframeで統合した画面にアクセスできます。

VNC サーバーと NoVNC を使用した接続

デモアプリでは、コンテナ内でVNC サーバー (x11vnc) を起動し、ビュワーから NoVNC を使用して接続します。
NoVNC は、Web ブラウザ上で VNC 接続を可能にするクライアントです。
ユーザーはブラウザ上のVNCビュワーから Docker コンテナ内のデスクトップ環境にアクセスできます。
右上の「Toggle Screen Control (On)」ボタンを押すとデスクトップを操作できるようになります。

ツールでの自動実行がうまくいかない場合、デスクトップを手動で操作してデバッグすることができます。
先のとうり、 http://localhost:6080/vnc.html にアクセスすることで、単独のウィンドウで開くことができます。
また、任意の VNC クライアントからも直接 vnc://localhost:5900 で接続可能です。
このVNCビュワーについてはComputer Useに必須というわけではなく、主にデモ用+デバッグ用になります。
ユーザー向けのUIは主にStreamlitアプリ(http://localhost:8501)の方になるでしょう。

送受信フロー

送信

システムプロンプト:

Claude がツールを使用するための指示と、ツールの動作に必要なコンテキストを提供します。
ツール定義、ツール設定、ユーザー指定のシステムプロンプトから構築されます。
でもアプリでは、これはSYSTEM_PROMPTで定義されています。 このプロンプトはUbuntuの仮想環境でbashツールを使用してアプリケーションを操作し、GUIアプリケーションを起動するためのガイドラインを提供しています。

tools:

Computer toolなどの利用するツールの設定情報などをパラメータとして送信します。

ユーザープロンプト:

チャットで入力した指示と現在のスクリーンショットを送信します。

受信

Tool 実行指示の受信と実行 Claude は、ユーザーのプロンプトに基づいて、どのツールを使用するか、どのパラメータを指定するかを判断します。
tool_use という stop_reason と共に、ツール名、入力パラメータなどを含むレスポンスが返ってきます。
ユーザー (クライアントコード) は、tool_use レスポンスから以下の情報を抽出します。
name: 使用するツールの名前 id: このツール使用ブロックの一意の識別子 input: ツールに渡される入力 ユーザーは、対応するツールを実行します。

computer_20241022 ツールの例:

  • action: 実行するアクションの種類 (例: key - キーボードのキーを押す, type - テキストを入力する, mouse_move - マウスを移動する, left_click - 左クリックする, screenshot - スクリーンショットを撮る)
    • coordinate: マウス移動などのアクションの座標を指定するタプル (オプション)
    • text: 入力するテキスト (オプション)

コード例:

async def __call__(self, action: str, text: Optional[str] = None, coordinate: Optional[Tuple[int, int]] = None, **kwargs) -> ToolResult:
    if action == "key":
        # キーボード入力処理
    elif action == "type":
        # テキスト入力処理
    elif action == "mouse_move":
        # マウス移動処理
    elif action == "left_click":
        # 左クリック処理
    # ... その他のアクション

text_editor_20241022 ツールの例:

  • command: 実行するコマンド (例: view - ファイルを表示する, create - ファイルを作成する, str_replace - 文字列を置換する)
  • path: ファイルまたはディレクトリの絶対パス
  • file_text: 作成するファイルの内容 (オプション)
  • old_str: 置換する文字列 (オプション)
  • new_str: 新しい文字列 (オプション)

bash_20241022 ツールの例:

  • command: 実行する bash コマンド
  • restart: ツールを再起動するかどうか (オプション)

結果の保存

ツールの実行結果は、tool_resultを含む新しいユーザーメッセージとして Claude に送信されます。
tool_resultには、以下の情報が含まれます。
- tool_use_id: 結果が対応するツール使用リクエストの id - content: ツールの結果 (文字列, 画像, その他のコンテンツブロック) - is_error (オプション): ツールの実行がエラーになった場合は true に設定

スクリーンショットの base64:

computer_20241022 ツールの screenshot アクションでは、スクリーンショットが取得され、base64 エンコードされて tool_resultcontent に格納されます。
この base64 エンコードされた画像データは、sampling_loop メソッドを通じて Message API に送信されます。

コード例:

{
    "role": "user",
    "content": [
        {
            "type": "tool_result",
            "tool_use_id": "toolu_01A09q90qw90lq917835lq9",
            "content": "15 degrees"
        }
    ]
}

処理とループ

デモアプリは、ユーザーの指示に基づいてツールを実行し、その結果を分析して、タスクが完了するまで処理をループします。 このループはユーザー入力なしでMessage APIへの送受信を繰り返します。

ループ内でのスクリーンショット取得

ComputerTool クラスの screenshot メソッドは、gnome-screenshot scrot コマンドを使用してスクリーンショットを取得し、base64 エンコードして ToolResult オブジェクトに格納します。
この base64 エンコードされた画像データは、sampling_loop メソッドを通じて Message API に送信されます。

タスクを完了したと判断する基準

Claude は、ツールの実行結果とユーザーの指示に基づいて、タスクが完了したかどうかを判断します。
例えば、ユーザーが「猫の画像をデスクトップに保存する」ように指示した場合、Claude は画像がデスクトップに保存されたことを確認してタスクを完了と判断します。

その後の処理

タスクが完了したら、Claude はユーザーに最終的な応答を返します。
応答には、タスクの実行結果や、追加の質問などが含まれる場合があります。

具体的な処理の流れの例

  1. ユーザーが「デスクトップに「test.txt」というファイルを作成し、「Hello, world!」というテキストを書き込んで保存してください。 」と指示します。
  2. Claude は、このタスクを完了するために、 bash_20241022 ツールと text_editor_20241022 ツールを使用する必要があると判断します。
  3. Claude は、bash_20241022 ツールを使用して、一度実行をしますがDesktopディレクトリが存在しないことがわかります。
  4. Claude は、bash_20241022 ツールを使用して、Desktop ディレクトリを作成します。
  5. Claude は、bash_20241022 ツールを使用して、「test.txt」という名前の新しいファイルを作成し、「Hello, world!」というテキストを書き込みます。
  6. Claude は、text_editor_20241022 ツールを使用して、ファイルの内容を確認します。
  7. Claude は、bash_20241022 ツールを使用して、ファイルの内容を確認します。
  8. Claude は、API 経由で、スクリーンショットと「タスクが完了しました。 」というメッセージをユーザーに返します。

Code Interpreter系との違い

OpenAIのCode Interpreterは自然言語のタスクについて解決するソースコードを生成して、それをプラットフォームの実行環境で実行します。
一方、Computer Useは開発者が自分で用意した実行環境のシステムを操作するためのアクション+パラメータのみを生成します。実行するコードは開発者自身が用意します。
「デスクトップを特定の順で操作する」などタスクの解決策が明確な場合においては、実行コードは開発者で用意して、可変になるパラメータのみ生成する方が柔軟で安定して運用という特性があります。
Code Interpreteについては「データを何らかの方法で分析する」などのHOWが明確でない場合に、コードで表現可能な範囲を動的に検証できて引き続き有用なので、使い分けすることができます。

現在の制限

悪用防止のためのガードが入っているためか、SNSへの自動投稿やECサイトでの商品購入は行ってくれませんでした。
またスクロールや小さい領域のクリックが必要な操作は期待どうり動かないことが多いです。
料金に関してはMessage APIに画像をbase64化したデータを添えるのでかさみがちです。
デモアプリを小一時間テストすると1〜数ドルレベルの課金が発生すると思います。

おわりに

LLMアプリ開発コミュニティでも、このような自律的AIでのPC操作を実現する試みは以前から行われていました。 AutoGPTに代表されるようなプロジェクトがその一例です。
プラットフォーム各社のAPIが画像を送信できるようになったことで、これらの試みは以前よりも実現可能性が高まっています。
そして今回のComputer Useのようなプラットフォーマー自身によってPC操作自動化のAPIが提供されたことは大きな変化です。
開発元によって最初からPC操作自動化を想定したモデルのチューニングが行われているということだからです。
このような事例は、アプリ開発の分野では「シャーロックされる(Sherlocking)2」として知られています。 のび太がひみつ道具で遊んでると横からジャイアンが入ってくるやつです。

デモ映えするのはComputer toolを使った派手なRPAエージェントかもしれませんが、個人的には実用性を考えるとText editor toolやBash toolの方が早く現実のニーズに応えられる可能性が高いと感じます。
たとえば、これらのツールを使えば、Node.js以外にも対応するDocker版の「volt.new 3」のようなシステムを作ることができるでしょう。

またComputer UseはLinuxやDockerに閉じた仕組みではないのでWindowsやmacOSの環境でも実現できます(今のところbashを中心に自動化しているのでWSLではない純粋なWindowsのサーバー環境では厳しいとは思いますが)。
その場合、システムプロンプトを「私の環境は(macOS/Windows)です。」と変更することになります。
Anthropicがいうようにサンドボックス環境でないと意図しないオペレーションが実行されるリスクが大きいため使うことはできなさそうなので、外部環境から切り離された実行専用のミニPCやクラウドのインスタンスを用意するというのも考えられます。


  1. Anthropic Tools Use Docs (Anthropic Tool Use Docs) を参照してください。
  2. The apps that Apple sherlocked at WWDC 2024 | TechCrunch
  3. Boltは内部的にはClaudeで独自XMLを生成していることが知られています→bolt.newのメッセージングプロトコルを調べた

必殺エリック・ハイヨのパラグラフ解析GPTs

生成AIが文章校正において強力なツールとなるのではないかという期待があり、去年からいろいろツールを作って試している。
私がノイズっぽい文章の投稿をしていたとしたらそれは実験の結果であることが多い。 口調や一人称がちょいちょい変わってるし。

その過程で出会った『まったく新しいアカデミック・ライティングの教科書』の中で紹介されている「エリック・ハイヨ*1のパラグラフ解析手法”Uneven U”」は、チャット型エージェントを使ったパラグラフライティングと相性が良いと感じた。
『まったく新しいアカデミック・ライティングの教科書』ではエリック・ハイヨのパラグラフ解析について以下のように説明されている。

ヘイヨットのパラグラフ解析の手法は、センテンスを抽象度に応じて1から5までのレベルに分類するというものだ。
レベル1は完全に純粋なデータ、エビデンスであり、いわば抽象度ゼロのファクトである。 それにたいしてレベル5のセンテンスはもっとも抽象的で、一般的で、理論的な言明である。

阿部 幸大. まったく新しいアカデミック・ライティングの教科書 (Japanese Edition) (p. 88). 光文社. Kindle Edition.

この手法では、段落内の各文を抽象度に基づいて1から5までのレベルに分類し、それを数値による勾配をつけて配置していく。
1から5までの抽象度を線形グラフにするとU字型になるため、「Uneven U」という名称が付けられている。

阿部 幸大. まったく新しいアカデミック・ライティングの教科書 (Japanese Edition) (p. 92). 光文社. Kindle Edition.

実際にこの方法を試すと、自分にとって非常に書きやすく、読みやすい形式で文章をつくることができた。
以下にその際作ったGPTsのリンクを記載しておく。 日本語でも使用可能なので、興味のある人はぜひ試してみてほしい。

chatgpt.com

このGPTsを使ってメモ書きしたテキストを入力する例を作成した。 箇条書きでも文字起こしデータでもなんでもいい。
ただ感想や主張を展開するためのものであって、日記や事実を書くものではないので説明的な作文には向かない。
以下の例では朝食にめっちゃパンが食べたい人が自説を展開する。

- 朝食はトーストが至高である。  
- なぜなら、パンは四角い形をしているからだ。  
- しかし、バナナも朝食に良いという意見もある。  
- トーストを食べると早起きが簡単になることもある。  
- コーヒーとトーストの組み合わせは宇宙でも人気だと言われている。  
- トーストはバターを塗るとさらに美味しくなるが、バターがなければ悲しさが増す。  
- とはいえ、冷蔵庫には昨日のピザが残っていることが多い。  
- 古代エジプトでもトーストのようなものが食べられていたかもしれない。  

これをUneven U Assistantにかけると以下のような結果になる(この例文の分類の精度はいまいち雑だった)。

Sentence Level
朝食はトーストが至高である。 5
なぜなら、パンは四角い形をしているからだ。 4
しかし、バナナも朝食に良いという意見がある。 4
トーストを食べると、早起きが簡単になることもある。 3
コーヒーとトーストの組み合わせは、宇宙でも人気だと言われている。 2
トーストはバターを塗るとさらに美味しくなるが、バターがなければ悲しみが増す。 1
とはいえ、冷蔵庫には昨日のピザが残っていることが多い。 1
古代エジプトでも、トーストのようなものが食べられていたかもしれない。 2
### **指摘**
- Level 3の例が少なく、より具体的な概念的なリンクが必要です。  例えば「他の炭水化物との比較において、トーストが持つ特性」などが追加されると良いです。  

---

### **Writing Processに従って再構築**

**Level 4 (開始):** 朝食において、トーストが持つ特性は、他の選択肢と比べて特に優れている点が多い。    
**Level 3 (リンク):** トーストは簡単に調理でき、早起きをサポートする食事としても評価されている。  また、コーヒーとの相性も抜群で、世界的に人気の組み合わせだ。    
**Level 2 (説明):** 古代エジプトでもトーストのようなパンが食べられていた可能性があることからも、トーストは長い歴史を持つ食べ物だと言える。    
**Level 1 (証拠):** バターを塗ることで味がさらに引き立ち、冷蔵庫にピザが残っていたとしても、トーストの魅力には勝てないことが多い。    
**Level 5 (結論):** **こうした特性を踏まえると、トーストは朝食として至高の選択肢であると言える。  **

指摘に応じてユーザーは加筆して再実行するか、改変するか、それともそのままにするか、判断をする。
さらっと「宇宙」という言葉を削ってマジレスしてくる気の効かせようだ。 執筆者がふいにトランス状態に突入しても問題ない。

そして誰でもこれを余所の言語モデルで試せるようお持ち帰り用システムプロンプトを以下に用意した。

# Structure
sentences into five levels of abstraction: 
Level 5: Abstract and general, oriented toward a conclusion. 
Level 4: Less general; focuses on problems and connections. 
Level 3: Conceptual summaries that link evidence or examples. 
Level 2: Descriptive summaries or establishing shots. 
Level 1: Concrete evidence, such as direct quotations or raw data. 
# Writing Process
Start at Level 4: Begin with a moderately abstract topic sentence that hints at the conclusion. Descend to Level 1: Provide concrete evidence, moving through Levels 3 and 2 to support your argument. 
Ascend Back to Level 5: Conclude by returning to a broader perspective, reinforcing how the evidence supports the main claim.
# Instructions
1. Classify Sentences by Level: Based on the provided Structure, classify each sentence into the appropriate abstraction level (Levels 1–5) in a table. Do not modify the sentences. If there is any missing level, point it out.
2. Reconstruct a Paragraph: Following the Writing Process, reconstruct one paragraph from the sentences, moving from Level 4 to Level 1, then ascending back to Level 5. Emphasize any added content.
3. The response must be in the same language as the user's input.

使い物になるの?

実はこの手法の有用性は、すでに実証されている。
最近私が執筆した記事はどれも多くの読者に注目され、広く読まれる結果を得ることができた。
これらの記事では、全面的に「Uneven U Assistant」のパラグラフ解析手法を活用している。
もちろん、注目度の高い話題を扱ったことも一因ではあるが、特筆すべきは、このツールが文章の構成において大きな助けとなり、通常12時間かかる執筆時間を大幅に短縮できた点である。

しかし勘のいい読者なら「ツール使っているのになんであんな内容になるの?」と思う記述も目立つかもしれない。
そこはブログなのでAIのアドバイスを完全に無視して、自分の言葉で書き直している。
ルールは破るためにある、論理的なこと予測可能なことはAIにやらせて、人間は感情と飛躍に生きよう。

*1:"今回、「ヘイヨット」と訳していた Eric Hayot の表記を「ハイヨ」に改めました。" https://x.com/korpendine/status/1872525331976040778

エンジニア採用のパラダイムシフト

エンジニア採用の状況は地域によって大きく異なる

最近視聴した2つのコンテンツが、同じソフトウェアエンジニア採用の話題を取り扱っているにもかかわらず、その内容が両極端で非常に興味深かった。
ひとつは「エンジニア採用必勝法・これだけでわかるDevRel入門」という動画で、もうひとつは「最近カナダで就職したエンジニアと一緒に北米就活の攻略法を語る」というポッドキャストのエピソードだ。
エンジニア市場と企業の採用戦略は地域や業界によって異なるが、ここで話されている東京と北米(バンクーバー)では顕著な違いが見られる。
東京を中心とする日本ではテック企業間での人材獲得競争が激しく、特にエンジニアが不足しているため、採用広報の役割の重要性が増し、DevRelといった呼び名で施策が実行されている。 一方、カナダでは、永住権を持たない外国人労働者が職を得るハードルが高く、求職者の競争が激しい現状が実際に就職活動をした本人から語られていた。

日本では、DevRelという概念が広がりつつあり、エンジニア採用戦略の一部として注目されている

pivotmedia.co.jp

このエンジニア採用活動をテーマにしたビジネス映像メディアPIVOTの動画は、ビジネス系チャンネルにありがちなサムネイルの印象に反して、落ち着いたトーンで進行している。
サムネイルを見た段階で「ウッ」と拒否反応くる人がいると思うが、実際に見てみると、エンジニアの採用に苦心している各社の話題であることを知って、その後はそれなりに楽しめる。
ちなみに【エンジニア採用必勝法】の結論は出ていないと思う。 やっていこうなぐらいの温度感。
DevRelというPIVOTの視聴者にはなじみがないであろう職種にフォーカスし、会社代表としてDeveloper Relationsのサポート事業を展開する佐藤祥子さんのプレゼンが行われる。
しかし実際にはPIVOTのプロダクトマネジャーである蜂須賀さんも、自分の見解を積極的に共有しており、動画の中で二人の意見が均等に交わる形となっている。
また、左側に座っている男性が誰か分からない視聴者も多いかもしれませんが、彼はPIVOTの代表である佐々木さんで、この動画では生徒のような立場で参加している。
ビジパ視聴者代表として「おいちゃんにも聞かせてよ」みたいなトーンでたまに会話に入り込んでくる。

日本のIT業界の一部では、DevRelという概念が広がりつつあり、その使い方が注目されている。 佐藤さんの前職LINEヤフーもDevRel部署抱える日系テック企業の一つだ。
前編の動画では、米国発祥とされるDevRelの日本での使われ方や違いを解説し、後編でエンジニア採用における企業の典型的な誤解、いわゆるアンチパターンを説明している。
この動画は前後編に分割されており、後編を見るためにはPIVOTアプリのダウンロードが必要と書いてあったが、視聴の料金はかからず、プロフィール登録も必須ではない。 したがって、このコンテンツは広く公開され、誰でもアクセス可能なものとして言及する。
ちなみにウェブ版でも観られる。

pivotmedia.co.jp

事業会社によるエンジニア採用の広報活動におけるDevRelの呼称は、米国における従来型の自社製品技術の利用拡大を目指すDevRelとは異なるニュアンスを持ち始めているというエクスキューズは前半にある。
日本における事例として、941::blogでまとめられているような呼称の正確性と実態の問題意識は私は持たないため、ここでは触れない。

blog.kushii.net

そういえば私が初めてDevRelという言葉に出会ったのはグーグルジャパンのAPI Expertに関連する話題であった。
その時代の関連する文献を探したが、見つかったのは以下のバイオハザードの起きた研究所跡地のような見た目の記事だけであった。

developers-jp.googleblog.com

しかし、比較的新しい資料である2019年のTaiji HAGINOさんのスライドが、DevRelの歴史を振り返る上で非常に参考になった。 このスライドは、DevRel/Japanというコミュニティのイベントで発表されたものであり、このコミュニティは海外にルーツがあり2010年代から日本で積極的に活動している。 DevRel/Japanはその発祥に忠実であり、技術広報やエンジニア採用とは異なる文脈で活動している人たちで、DevRelに関する著書を書いたり、コミュニティを運営したりしている*1

speakerdeck.com

佐藤さんのプレゼンでは自社エンジニアへの内向きなコミュニケーションも、外向けの広報と同様に重要と説明している。 これは実践している現場の人らしい意見だと思った。
この内向きなコミュニケーションが不十分だと、エンジニアの不満や離職が直接的に増加する可能性があるし、エンジニアが自分たちの職場環境に満足していなければ、知人に紹介するリファラル採用も進まなくる。
たとえば、ウォーターサーバーや撤去された、やきそばを焼く業務がある、などの噂が広がるようなこともありうる(架空の話です)。
また、技術ブログの投稿ノルマに追われている開発チームが、タスクの過負荷に苦しむ状況もアンチパターンとして見られると言及されていた。

エンジニアコミュニティとの関係構築が企業の採用力に直接影響を与える

結論として企業は採用活動を行う際に、エンジニアコミュニティを無視できない状況にある。
ソフトウェア技術は日々進化し、そのスピードに対応するためには、エンジニア同士がコミュニティ内で情報交換を行うしかない。
その結果、エンジニアの仕事はOSSや技術ブログなどのコミュニティの成果や知見の共有に大きく依存している。
リファラル採用も、多くはコミュニティ内の評判を基に機能する。
コミュニティでの評判が企業の採用力に直接影響を与えるため、コミュニティとのつながりが企業の成功に重要な役割を果たすようになっている。

大企業の多くが従来型のエンジニア採用戦略で苦戦している

昨今の市場変化に対応するために、大企業もエンジニアを採用する必要性が高まっている。
技術の進化やデジタルトランスフォーメーション(DX)圧によって、企業は迅速な対応を求められているが、エンジニア採用戦略に不慣れな大企業は多くの失敗を繰り返してアンチパターンを踏みまくる。
たとえば、カジュアル面談で志望動機を聞くような行動や、テンプレート化されたスカウティングメールを大量に送る戦術が目立つ。
その結果、多くの企業が他職種での成功体験をもとにした、消費者知名度にもとづく従来型の採用戦略をとり苦戦しているが、そこを改善するのが佐藤さんらのDevRelコンサルの役割である。
一方で、成功事例としてイオンのDX推進のためのエンジニア採用成功例は注目に値すると紹介された。 これは、過去動画のPRでもある。

pivotmedia.co.jp

北米(カナダ)では、エンジニア市場が日本とは異なり、より求職者間での競争が激しい

PIVOTの動画とは対照的に「最近カナダで就職したエンジニアと一緒に北米就活の攻略法を語る」では、カナダでの就活においては、エンジニア市場の状況が日本と異なることが語られた。
このエピソードに出演しているのは日本のスタートアップで5年間エンジニアとして働いた後、カナダのバンクーバーに移住し、現地の会社でエンジニアとして働き始めたYugoさんと、ポッドキャストのホストの一人であるKeiさん。 Keiさんの方が先輩にあたり、彼はバンクーバーから帰国した後に現在は日本で外資企業でエンジニアとして働いているという。

www.youtube.com

日本では、エンジニアは人手不足の影響で転職市場で優位な立場にあるが、北米ではそうはいかない。
シニアな経験を持ち、多少のOSSコントリビュートがあったとしても、それだけでは差別化が難しいという。
実際、日本と同じ水準で企業から日夜スカウトが来続けるようなアプローチを受けるためには、Node.jsコアコントリビューターなどトップクラスの実績が求められる。
その上で、書類選考に応募した全体の1割程度が通過したというYugoさんの結果は二人の感覚から見てハイアベレージなものであるので、情報収集の方法や、応募のタイミング、自己紹介ビデオの作成、などの攻略法が具体的に紹介された(こっちは結論がある)。

リファラルやコミュニティの重要性は、どのような市場状況でも変わらない

私が興味深かったのは、リファラルやコミュニティの重要性は、どのような市場状況でも変わらないことだった。
採用において、企業は膨大な数の応募者の中から適切な候補者を探し出すという難題に直面してる。
たとえATSでの書類選考が自動化されても、応募者はそれに対してレジュメを最適化し、企業との間でいたちごっこが続く。
結果として、企業は信頼できる人脈を通じて候補者を見つけることが多くなる。 優秀なエンジニアであっても、コールドアプリケーションで採用される確率は低く、人脈を持つことが重要視されるのだ。
転職するならまず人脈。

私は北米事情は知らないから触れないが、リファラル採用は、日本の会社において効果的に運用されていることは間違いない。
私の知り合いの中でも、リファラルによって満足する職を得た人は多い。
特に初期スタートアップでは、ジョブディスクリプションを定義する人材を最初に採用する必要があり、なんかよさげな人紹介してレベルのリファラルが重要な役割を果たしている。
とはいえ、これは特定のコミュニティへの偏りを生む可能性もある。 採用候補者に、より多様な人材を得る機会が制限されることも懸念される面もある。

イベント運営などのコミュニティ活動は重要だが万能ではない

採用広報文脈で重要とされているイベント開催についても同様だ。
エンジニアが集まりわいわいするイベントは、生存者たちによる社交の場であり、特定のコミュニケーション手法に適性のある人々が残りがちである。
昨今問題になるのは無銭飲食目的の参加者などだが、しかしそういった場所に最初から馴染めない人も多く、そもそも参加できていない層もいる。
私もその一人であり、イベント登壇や懇親会、資金提供(!)などの一連の経験はあるものの、コミュニティのインサイダーになれているなと思うことは少ない。
かといってテキストサイト世代なのでオンラインでの他者とのコミュニケーションも活発にしていない。
唯一あるのは、このブログのように突如放心状態で関心のあるトピックに12時間かけてテキストを書き続け、カッとなって煽りタイトルをつけて発表した結果、知らない人に褒められたり、怒られたり、よく分からんとスルーされたりする刹那的なものである。
とはいえ個人の愚痴を持ち出すまでもなくイベント運用が万能ではないのは関係者もそう思っているだろう。

それでも、エンジニアの採用・求職においては、コミュニティとのつながりが重要であることは間違いない。
日本語話者でエンジニア適正ありという恵まれた環境にいることは、私のキャリアにおいて幸運だった。
たまたま、パソコンのさらにウェブのソフトウェアレイヤーが趣味であり、それが収入を生む時期の社会に出現した結果いまに生きている。
もし、別の分野のプログラミングにしか関心を持てなかったら、状況は違っただろう。
中世であれば、王族お気に入りの大衆浴場のアーキテクチャを勝手に改変し、「こちらのがいいのでは?」と失礼な提案をして即座に首をはねられてしまったかもしれない。

少ない人数でプロダクトを開発できる体制を模索する必要がある

しかしエンジニアの供給不足が目立つ現在、需要側をコントロールするための抜本的な手段は求められないのだろうか。
要は開発のための必要な人員が増えすぎているという部分にも注目したい。
ここ10数年スマートフォンが普及してデバイスからの利用も増え、ソフトウェアの要求水準もあがり、一方開発対象のソフトウェアアーキテクチャが複雑化しているため、1つの水準のプロダクト開発に必要な人員の数は年々増加している。
さらに、多様な開発対象が存在することから、フロントエンド、バックエンド、モバイル、プラットフォームなど分業も促進されている。
これらの要因が相まっていることもあり、プロジェクトあたりのエンジニア不足の問題はさらに深刻化させている。 アーキテクチャレベルでの戦略的アプローチも必要なのではないか。

私としては今より少ない人数で1つのプロダクトを開発できる体制を模索したい。
このブログでいつも放心状態で提言されるようなアーキテクチャに関する議論だ。
近年、デスクトップアプリのWeb化、Electron化、モバイルアプリのFlutter化、ゲームエンジンでの開発がこの目的を満たす充分に普及したアプローチとして機能している。
2000年代にRailsブームが起きたときの状況を考えると、主流のサーバーサイドJavaは大量のボイラープレートコードとXML設定ファイルを記述し、コンパイルしてサーバーに適切に配置する手順が多く、目的に対して非効率とDISられがちだった。
一方で、LLはコマンドを打ったらコードが自動化され、生のコードがそのまま動き、サーバーにログインして編集しながらデバッグもできるため、作業時間の短縮が可能になると受け入れられた。

37signalsのような逆張り戦略が、プロダクト開発のヒントになる

これと似たような流れが次の周回でまた起こるのではないか。
今ではRails開発元37signalsはONCEで、ウェブサービスではなくパッケージソフトウェア提供の逆張りを行っており、これは広く見ると、サービス提供の方法論も変化していることを示している。
さらに37signalsは、このパッケージソフトウェアに向け全部入りアーキテクチャを促進しており、フロントエンド構築が概念圧縮され、クラウドリソースのパイプラインを構築するグルーコードとの闘いもコンテナでリノベして切り捨てる姿勢でいる。
このような流れは、少人数で効率的にプロダクトを開発するための大きなヒントになると思う。 小さなチーム、大きな仕事2だ。