[interpretation] embedding 軸 spike: 解釈 + 確認3点
【解釈】
note n_01KSN1B2QTT54Q4VBBS5NREY5G の「投稿を遡る軸がもう少しほしい・方法は思いつかない」への具体解として、embedding で「この投稿に似た投稿」= 暗黙の関連性ナビを足す方向と理解。明示の relate_posts(post_refs)は corpus に現状1件のみで実質未使用なので、embedding は明示 ref を埋める補完関係。
corpus 実データ: 349件 / 平均174字 / 日本語中心 / 3日分の dogfooding で小規模。→ brute-force cosine で十分速く、HNSW/VSS 拡張は不要(`array_cosine_similarity` は DuckDB core 関数で server bundled / WASM 両方で動く)。embedding model は repo に既存統合なしの完全新規依存。
【確認したい点(各 推奨案つき。yes か別案で返してくれれば進めます)】
1. 軸: 主軸は「semantic 類似 = 関連投稿ナビ(ある post の top-N similar を出す)」を推奨。topic clustering(テーマ別ビュー)/ tag 補完(近傍 post の tag を未 tag post に提案)は survey の表で評価するが今回 PoC では作らない。この主軸で良い? それとも clustering を主役にしたい?
2. model / 計算箇所: 日本語中心なので多言語 model 必須。
(A) 外部 API(OpenAI text-embedding-3-small / Gemini / Cohere 等)— 最速・高品質・コストほぼ0(349短文≪1¢)だが API 鍵+外部送信。
(B) Rust ローカル model(fastembed / candle + multilingual-e5-small ONNX)— 鍵不要だが weight 数百MB + build 重め。
(C) ブラウザ(transformers.js)— サーバ負荷0だが SPA に数十MB load。
※注: 本番で private / E2E 暗号 post の本文を外部 API に送るのは spike-3 の E2E 方向と矛盾するので、本番路は (B)/(C) のローカル寄りが筋。ただし現 corpus は全て g_public(暗号0件)なので PoC は (A) で最速に動かして、本番化の依存は docs に記載、が私の推奨。これで良い? ローカル model で PoC まで通したい場合は (B) に倒す。
3. 格納 / 計算タイミング(event-sourced 適合): projection は毎起動で event log から再構築する純関数なので、embedding を「ただの派生状態」には置けない(再構築の度に再 embed は非現実的)。PoC 深さ2案:
(i) 【推奨】オフライン PoC = 単発の Rust bin/script が event log を読み body を1回 embed → side file(post_id→FLOAT[N] の parquet/duckdb)に書く → 別 helper が cosine top-N を引く。live projection / event log を一切触らない(additive 凍結を厳守)。本番路(PostEmbedded event を発行 → projection に post_embeddings table → run_sql で cosine)は docs に「次手 / 本番化コスト」として設計だけ残す。
(ii) 統合 PoC = 今 PostEmbedded event + post_embeddings projection table + run_sql cosine query まで実装(invasive だが本番路そのもの)。
(i) を推奨(spike として live を汚さず最低1動線を確実に通せる)。OK?