天使やカイザーと呼ばれて

Semantic Embedder APIで意味的に整理される付箋ボードを作った話

· Google

Chrome の Built-in AI に、新しく Semantic Embedder API が加わろうとしています。実は僕は最近、この API を触ってみるためのデモアプリを作り、Explainers by Googlers - github.com の Issue にフィードバックを投稿する機会がありました。ここでは、そのときに考えたことや気付いたことを、Semantic Embedder API そのものの紹介を交えつつまとめてみたいと思います。

Semantic Sticky Board のアプリ画面 - キャンバス上に複数のキーワード(アンカー)と付箋が配置され、それぞれの付箋がキーワードとの意味的な近さに応じて自動的に配置されている様子

Semantic Embedder API がやってくる

Semantic Embedder API は、その名の通り、テキストを意味的な埋め込み(embedding)ベクトルに変換するための Web API です。Chrome にすでに搭載されつつある Built-in AI シリーズの新しい仲間、というわけですね。バックエンドには EmbeddingGemma の 300M パラメータのモデルが使われていて、これがすべてユーザーのマシン上、つまりオンデバイスで動作します。詳しくは Chrome の Built-in AI - developer.chrome.com の各種ドキュメントを参照してみてください。

「テキストをベクトルにする」と言われても、なかなか使い道がイメージしにくいかもしれません。ざっくり言えば、embedding は「意味の座標」のようなものです。ある文と別の文が、意味的にどれくらい近いかを、コサイン類似度(cosine similarity)というシンプルな計算で測ることができます。これがサーバー通信なしで、しかもユーザーのブラウザの中だけで完結する、というのがこの API のインパクトかなと思っています。

なぜ Semantic Sticky Board を作ったのか

Semantic Embedder API が登場する、という話を最初に聞いたとき、「付箋を書いて、キーワードとの意味的な近さで位置が決まるボード」というアイデアがわりとすぐに思い浮かびました。単なる「意味検索」を作るだけでは面白くありません。せっかくオンデバイスで動くのだから、機密情報を扱えるような領域、それでいて開発者の日常に近い体験にしたい、というのが元々頭の中にあったからかなと思います。

そこで作ったのが Semantic Sticky Board - github.com というデモアプリです。ブレインストーミングや議事録、KJ 法的な整理といった、外に出したくない情報を扱う場面をターゲットにしています。付箋を書くたびに、意味的に近い場所へ自動でスッと配置されていく、というものです。

実際に動くデモは Semantic Sticky Board - semantic-sticky-board.yoichiro.dev で公開しています。ただし、Semantic Embedder API はまだ実験的な段階の API なので、動かすには少し準備が必要です。Chrome Canary の 153 以上を用意した上で、chrome://flags/#semantic-embedder-api からフラグを ON にしてからアクセスしてみてください。文章だけで説明するよりも、実際に触ってみるのが一番早いかなと思います。

ブレストの最中って、頭の中の断片を「まず出す」ことが大事なんですよね。分類は後回しでいい、と言いつつも、あとで整理するのはやっぱり面倒です。「書きながら勝手に整理されていってくれたら嬉しいのに」というのが、ずっと思っていたことでした。Semantic Embedder API は、その願いをオンデバイスで叶えてくれる可能性のあるものかなと思っています。

デモの仕組み

Semantic Sticky Board では、まずユーザーが 2D のキャンバス上に「キーワード」を自由に配置します。これはボードの意味的な軸、いわゆるアンカーです。「デザイン」「バックエンド」「顧客からの声」といった、その日のブレインストーミングの視点を、ユーザー自身の言葉で置いていきます。

次に付箋を書くと、その付箋のテキストが Semantic Embedder API で埋め込みベクトルに変換されます。そして各キーワード(アンカー)との類似度を計算し、類似度を重みとした加重平均で 2D 上の座標を決めています。つまり、「デザイン」に近い意味の付箋は「デザイン」の近くに、「顧客からの声」に近い意味の付箋はそちらの近くに、それぞれスッと吸い寄せられていきます。

さらにキーワードをドラッグして動かすと、すべての付箋の座標がリアルタイムで滑らかに再配置されます。この体験は、実際に触ってみるとちょっとした快感があります。UMAP や t-SNE、PCA といった次元削減の技法は、あえて使いませんでした。「なぜこの付箋がここにあるのか」を、ユーザーが自分で置いたキーワードに紐付けて説明できる、という透明性を優先したかったからです。

taskType を非対称に使うと精度が跳ね上がる話

さて、ここからは実際に作って気付いた技術的な知見を紹介していきます。Semantic Embedder API には taskType というパラメータがあり、embedding をどういう目的で使うかを指定できるようになっています。

最初は、クラスタリング用途の対称的な設定で試していたのですが、これがどうもピンときませんでした。付箋を書いても「まあ、それっぽい場所にいるかな」くらいの精度で、決め手に欠ける感じです。そこでアンカー側を retrieval-document、付箋側を retrieval-query として非対称に扱ってみたところ、精度が一気に跳ね上がりました。

具体的には、あるテスト用の付箋で、対称モードでは支配的な重みが 47% と曖昧だったものが、非対称モードでは 100% ではっきりと最も近いアンカーを指すようになりました。これは「検索」と「クラスタリング」の違いを実感する場面でした。公式の explainer にも、対称モードだけでなくこの非対称パターンを併記して紹介してくれると嬉しいなと思っています。

日本語のベースライン類似度問題

もう一つ、非英語圏のエンジニアには特に共有しておきたい話があります。それは、日本語の文同士のコサイン類似度は、平均でおよそ 0.70 前後という高い値からスタートするという事実です。

これは「意味的に無関係な 2 つの日本語文を投げても、類似度は 0.70 くらい出てしまう」ということでもあります。この状態で類似度をそのまま重みに使うと、どの付箋も似たり寄ったりの位置に配置されてしまい、キャンバスの中央にダンゴ状に固まってしまいます。「せっかくの意味的な差が、ぜんぜん見えない!」となってしまうんですね。

対策として、Semantic Sticky Board では、まず類似度の最小値を引くことでベースラインをキャンセルし、さらに 8 乗して差を強調する、という重み計算を採用しました。式で書くと pow(max(0, sim - min(sims)), 8) という素朴なものです。

素の類似度で加重すると付箋が中央にダンゴ状に固まるのに対し、pow(max(0, sim - min(sims)), 8) で差を強調するとキャンバス全体にバラけて配置される、加工前後の比較図

これによって、意味的な差がしっかりと座標に反映されるようになり、付箋がキャンバス上でバラけて配置されるようになりました。日本語や中国語のような、embedding のベースライン類似度が高い言語を扱う開発者にとって、ここは非対称 taskType と並ぶ重要な落とし穴かなと思います。

実装のハマりどころ

これ以外にも、実装を進める中でいくつかハマりどころがありました。せっかくなので、これから触る方のために、まとめて紹介しておきます。

まず、create() メソッドをユーザーのジェスチャなしで呼ぶと NotAllowedError が返ってきます。これは availability()downloadabledownloading を返す状況、つまりモデルのダウンロードが必要な最初の一回目に発生します。Semantic Sticky Board では、明示的な「モデルをダウンロードする」ボタンを設けることで解決しました。この挙動、explainer にサンプルコードとして載っていると初見での戸惑いが減るかなと思います。

次に、Permissions Policy の適用範囲です。Semantic Embedder API はトップレベルフレームと同一オリジンの iframe からしか使えず、サンドボックス付きのクロスオリジン iframe からは呼び出せません。これは、たとえば Anthropic の Artifact のような「埋め込みプレビュー環境」でデモを共有しようとすると、ちょっと不便な部分です。「ページを保存して、ローカルの Canary で開いてみてください」と説明する場面が発生してしまいます。

もう一点、出力次元数について。EmbeddingGemma がそのまま返す次元数は 768 ですが、一部のドキュメントには 256 や 300 と書かれている記述があります。これは Matryoshka Representation Learning という手法によって、より短い次元に切り詰めた variants がある、ということかなと理解しています。実装者向けドキュメントで、このあたりが明示されていると、混乱が減りそうです。

Built-in AI で広がる可能性

Semantic Sticky Board は、あくまでブレスト用のボードとして作ってみたものです。ただ、この「ユーザー自身が意味の軸を定義し、コンテンツをその軸に沿って可視化する」という設計は、いろいろな場面に応用できるんじゃないかなと思っています。

たとえば、議事録や研究メモの半自動テーマタグ付け。あるいは、顧客インタビューの発話を、自分で選んだテーマ軸に沿って可視化するツール。さらには、個人ジャーナルを、ユーザー自身が定義した「軸」に対して並べ直して自己内省を促すツール。どれも、ユーザーの言葉で軸を作れて、しかも書いた内容が絶対に外に出ない、というオンデバイス AI ならではの価値が活きる領域かなと思います。

もちろん、これはサーバーサイドの LLM や embedding API でも技術的にはできることです。ただ、「情報を外に出せないから、そもそも試せなかった」という領域にリーチできる、という点で、Built-in AI の意味は大きいのかなと感じています。

まとめ

今回は、Chrome の Built-in AI に加わろうとしている Semantic Embedder API と、それを使って作ってみた Semantic Sticky Board、そして開発を通じて気付いた技術的な知見について紹介してみました。ここで挙げた taskType の非対称利用、日本語のベースライン類似度問題、そして実装上のハマりどころは、これから Semantic Embedder API を触る方にとって、少しでも近道になれば嬉しいなと思っています。

Semantic Embedder API はまだこれから正式に登場していく API ですが、日本語コンテンツを扱う開発者にとっては、特に応用の余地が大きいテーマだと思っています。本エントリが Semantic Embedder API を試してみるきっかけとして、少しでも参考になれば幸いです。


Ready
© 2005-2026 Yoichiro Tanaka