このブログに「関連記事」と「サイト内検索」を実装した。
きっかけは、自分の過去記事を探す面倒さだった。あの話はどの記事に書いたか。記事名もうっすら覚えているのに辿り着けない。タグ一覧からタイトルを眺め、「違う、これじゃない」と繰り返す。静的サイトジェネレーターにはサイト内検索も関連記事の表示もない。前から何とかしたいと思っていた。
見当違いだったらすまないが…
ある休日の朝、思い立ってAIに頼んでみた。聞きかじりの知識で「ベクトル化して類似度で関連記事を出せないか、見当違いだったらすまないが」と。
後からエージェントのログを読み返したところ、1時間8分で出来上がっていたらしい。待っている間はXを眺めていたので、体感ではもっと短かった。形態素解析で日本語を分かち書きし、TF-IDFでスコアリングし、コサイン類似度で記事間の関連度を計算する。技術選定から実装まで一通り揃っている。試してみると検索はそれらしい結果を返し、関連記事も表示される。
ここで深く確認せずに済ませることもできた。
見つけてしまった
buildersconの感想記事を開いてみる。ゲームAIやPWA、セキュリティ診断といったセッションの記録だ。PHPとは縁もゆかりもない。その関連記事に、自分がPHPerKaigiで登壇した「Laravelへの異常な愛情」が並んでいた。どちらもカンファレンスの記事だから、ということだろう。見つけてしまった。こうなると直さずにはいられない。そういう性格だと知っているので、敢えて確認しないこともある。
趣味のプロジェクトだから「一旦これで」にもできる。ただ、経験上、趣味の「次」はなかなか来ない。
足場の構造を知る
踏み込むとは、AIが選んだ要素技術を自分で理解するということだった。
TF-IDFやコサイン類似度はなぜこのスコアを出すのか。形態素解析の精度はどう効いてくるか。フロントマターの重みはどの程度が適切か。設計の意図を読み解かなければ、何を調整すべきかすら判断できない。
例えば形態素解析のストップワード。AIは「こと」「ため」「よう」といった機能語をリストで管理していた。語を追加するたびに「他にも漏れがあるのでは」と気になる。このやり方では際限がない。
AIが選んだkuromojiという形態素解析ライブラリが返す品詞の細分類を調べてみた。「非自立」「接尾」「代名詞」——これらのカテゴリで一律にフィルタすれば、個別の語を列挙する必要がなくなる。ストップワードの定義を丸ごと削除できた。
小さな改善に見えるかもしれない。ただ、そのためには形態素解析が何を返しているのかを知る必要があった。AIが架けた足場の構造を知らなければ、この選択肢には辿り着けない。
片手間の1時間で形になったものを、日が暮れるまでかけて仕上げた。品詞を1つずつ問い詰め、パラメータを段階的に試し、最終的にはTF-IDFでは越えられない壁も見えてきた。当初の構想にはなかったメタデータの部分一致を自分で設計し、組み込んだ。「見当違いだったらすまないが」と書いた人間が、半日後には自分で検索の仕組みを足している。
最初の成果物と最終的な実装の差はわずかだ。だが自分の記事なら、そのわずかな差を見分けられる。それを生むために、要素技術の理解が必要だった。
いつもの分岐点
前回の記事ではAIが書くテストの質について考えた。今回は機能実装だが、根にあるのは同じ問いだ。AIの出力を受け取ったとき、踏み込むか、受け入れるか。「これで良し」の分岐点は仕事でも日常的に現れる。コードレビューで違和感を覚えたとき、テストが通ったのに不安が消えないとき。そのたびに、立ち止まるかどうかを選んでいる。
趣味でこういう深掘りをする経験が、その嗅覚を磨いているのだと思う。締め切りがないから納得するまで続けられる。結果として理解が深まり、次に似た場面でより的確に踏み込める。
——と、きれいにまとめたが、自戒を込めて正直に書く。私だって気分や体力で判断は揺らぐ。午後だったら「一旦これで」にしていた可能性は十分ある。同じ分岐点に立ったとき、自分はいつも踏み込めているだろうか。
もっと書こう
ここまで精度にこだわっておいて何だが、このブログにはまだ35記事しかない。私には大きな違いだったが、読者にとっては目次で事足りる量かもしれない。
もっと書こう。