Upgrade to Pro — share decks privately, control downloads, hide ads and more …

生成AIを自社サービスに組み込む際の勘所・ハマりどころ

Sponsored · SiteGround - Reliable hosting with speed, security, and support you can count on.

 生成AIを自社サービスに組み込む際の勘所・ハマりどころ

株式会社バックテックの宮原です。
田町.ai #2で発表した資料です。

Avatar for Takashi Miyahara

Takashi Miyahara

August 19, 2026

More Decks by Takashi Miyahara

Other Decks in Programming

Transcript

  1. AGENDA 今日の3つ 1 セミナー動画のチャプター自動登録 2 セミナーの自動要約 3 RAGのHNSW索引が5.5ヶ月消えていた話 字幕 →

    LLM → Vimeoへ書き戻し 視聴前の要約・質問チップ、翌朝の振り返り ベクトル検索の基礎から、なぜ気づけなかったかまで 共通テーマ:チャット窓の外でAIを効かせる。そしてコードで守る。
  2. HOW 字幕 → LLM → 正規化 → Vimeoへ書き戻し Vimeo自動字幕 VTTを取得

    Redisに24hキャッシュ Claude Sonnet 5 タイムスタンプ付き字幕 → から チャプター案(秒+タイ トル) 正規化 → コードでルール適用 (次ページ) 毎時 :20 のAzure Functionsタイマー → 内部API → サーバー側で生成。1回3件 Vimeo Chapters API → プレーヤーの標準機能に 正はVimeo、DBは監査用
  3. GUARD 人の仕事と外部の正を壊さない Vimeoに手動チャプターが1件でもあれば skipped_existing (上書きしない) 生成前に status='generating' + attempts++ を書いてクレーム。並走しても二重書

    き込みしない 部分登録の途中で失敗 → ロールバック。消し残りは partial_failure として人に見せ る 12回で打ち切り。動画差し替えは自動で再生成
  4. WHY 空のチャット窓は、使われない セミナーページのAIコンパニオン:ティーザー表示 423 → 開く 46(11%)→ 質問 7 (1.7%)

    ユーザーにプロンプトを書かせる限り、価値は届かない。 → 先にこちらから「要約」と「質問の候補」を出す(YouTubeの「この動画について質問」型)
  5. HOW 字幕 → 要約+質問チップ → 視聴ページに先出し Vimeo自動字幕 1時間 ≒ 25,000字

    チャプターと同じキャッ シュを共有 Claude Sonnet 5 → 要約 400〜600字 + おすすめ質問 4件 DBに恒久保存 → 生成は1回きり 約7.5円/件 視聴ページ → 要約を先に表示 チップ1タップで質問開 始 毎時 :10(チャプターの :20 とずらす)。Flashではなく Sonnet 5 を選んだ理由:1回生成・恒久表示の医 療系コンテンツで品質優先
  6. 前提 1 / 3 ベクトル検索:「近い意味」を距離で探す 質問文 「変形性膝関節症に 効果的な運動療法は?」 埋め込み 距離を計算

    近い順に返す 1536個の数字に変換 コサイン類似度 LLMの材料に → text-embedding-3-small → 論文8万件の埋め込みと → 上位20件を PostgreSQL の拡張 pgvector を使用。列型は vector(1536) 、演算子 <=> でコサイン距離
  7. 前提 2 / 3 索引が無いと:全件と距離を計算する 80,000 × 1,536 ≒ 1.2億回

    論文 次元 の掛け算を毎クエリ B-treeは「大小」で絞れるが、多次元の「近さ」は絞れない → 全件を舐める逐次スキャ ン 実測:約2.9秒/クエリ(8万行、B2s 4GBのマネージドPostgres) 結果は正しい。ただ遅いだけ ← ここが厄介
  8. 前提 3 / 3 HNSW:多層グラフを「高 速道路→路地」の順に降りる Layer 2 入口 Layer

    1 質問ベクトル Layer 0 ★ 一番近い論文 全点をつなぐ近傍グラフを何層も重 ねる。上層ほど点が少ない 入口から「今より質問に近い隣」へ 貪欲に移動、行き止まりで1層下へ 計算量は全件比較 O(N) → O(log N) 級。8万件でもミリ秒 代償:近似(取りこぼしがあり得る) と、重いビルド
  9. PGVECTOR 使うのは1行。でもビルドは重い -- 索引を張る(コサイン距離用) CREATE INDEX "VerifiedPaper_abstractEmbedding_hnsw_idx" ON "VerifiedPaper" USING

    hnsw ("abstractEmbedding" vector_cosine_ops); -- 検索:距離だけで ORDER BY すると索引が効く SELECT id, 1 - ("abstractEmbedding" <=> $1) AS similarity FROM "VerifiedPaper" ORDER BY "abstractEmbedding" <=> $1 LIMIT 20; ビルド実測:8万行で 1分36秒・618MB(ローカル)。通常の CREATE INDEX はその間 テーブルを書込ロック 効くのは「距離だけのORDER BY」。年順など複合ソートは対象外
  10. INCIDENT 何が起きたか 2026-01-19 00:00 2026-01-19 07:11 〜 2026-07 2026-07-23 論文埋め込み導入のマイグレーションで

    HNSW索引を作成 別機能(論文収集の進捗テーブル)のマイグレーション1行目に DROP INDEX "…hnsw_idx"; が混入して本番へ 検索は「正しく、遅い」まま稼働。誰も気づかない パフォーマンス調査で発覚。約5.5ヶ月後
  11. WHY 1/2 なぜ DROP INDEX が混入したか 1 Prismaは vector 型を

    Unsupported("vector") としてしか扱えず、その列の索引を schema.prisma に書けない 2 は「DBにあるのにスキーマに無い索引」をドリフトとみな し、差分として DROP INDEX を生成する 3 別機能の開発者が migrate dev を実行 → 生成SQLの1行目に混入 → レビューをすり 抜けてマージ prisma migrate dev ORMが表現できないもの(拡張型・部分索引・トリガ)は、ORMにとって「存在しないはずのもの」に なる
  12. WHY 2/2 なぜ5.5ヶ月気づけなかったか 結果が正しい 索引は速度のためだ け。逐次スキャンでも 同じ論文が返る。エラ ーもゼロ 遅さが埋もれる AI回答全体は数十秒。

    その中の2.9秒は誰も違 和感を持たない 「壊れたら気づく」は、正しく遅い障害には通用しない CIも見ていなかった スキーマ同期チェック はこの差分を「既知差 分」として grep -v で 除外していた
  13. FIX 1/3 直すのも簡単ではなかった A 素直に CREATE INDEX をマイグレーションに書く B ロックしない

    CREATE INDEX CONCURRENTLY を書く C → 8万行で数分の書込ロック。本番はマイグレーションが起動時に走るので、起動が止まりHEALTHCHECK事故に → トランザクション内では使えない。Prismaのマイグレーションはトランザクションで走る IF NOT EXISTS で黙らせる → CONCURRENTLYが途中で失敗すると INVALID な索引が残り、IF NOT EXISTS はそれを「ある」と見なして黙る
  14. FIX 2/3 採用:手動で先に張り、マイグ レーションは「うるさく失敗」 -- 復旧マイグレーション(DOブロック、要旨) IF 有効な索引がある THEN 何もしない;

    ELSIF INVALIDな索引がある THEN RAISE EXCEPTION '作り 直して'; ELSIF 行数 >= 1000 THEN RAISE EXCEPTION '先に CONCURRENTLYで張って'; ELSE -- CI・新環境の小さなテーブルだけ CREATE INDEX ... USING hnsw (...); END IF; 本番は低トラフィック帯に手動で CREATE INDEX CONCURRENTLY (ロック 無し) 順序が重要:手動作成 → 検証 → PRマー ジ。逆だと起動時に非CONCURRENTビ ルド 手順書に「maintenance_work_memは 上げない(shm制約)」「1文ずつ実行」 まで書いた
  15. FIX 3/3 再発防止:ORMが見えないものは、CIが見る PR CIで migrate deploy 後に pg_index を照会し、存在・hnsw・

    vector_cosine_ops・indisvalid まで assert。DROPが混入したPRはマージ前に落ちる ローカルは prisma migrate dev 禁止、 migrate deploy のみ。手書きSQLでマイグレ ーションを作る ガイドライン検索側の HNSW 索引も同じCIで監視対象に