Skip to content

필사 모드: 社内ナレッジベースをLLMで作るということ — 権限認識検索、鮮度、そして公開前の評価セット

日本語
0%
정확도 0%
💡 왼쪽 원문을 읽으면서 오른쪽에 따라 써보세요. Tab 키로 힌트를 받을 수 있습니다.

はじめに — 1日1万5千件を受ける社内検索が実際に解いている問題

2026年7月15日、Cerebrasが社内ナレッジベースをどう作ったかを公開しました(How we built our knowledge baseGeekNewsまとめ)。公開から3か月で、1日15,000件を超える質問を受ける社内ツールになり、一人あたりに換算すると1日約15件です。目を引くのは質問者の構成です — 人間だけでなく、自動化スクリプトとエージェントが同じエンドポイントに問い合わせています。

まず、このシステムが実際に解いている問題を正確に押さえておくのがよいでしょう。社内検索の問題は「文書がない」ことではありません。たいていはこうです — 答えは6か月前のあるSlackスレッドにあり、そのスレッドを検索するには当時使われた正確なエラー文字列を知る必要があり、その文字列を知る人はすでにチームを異動しています。ウィキには同じテーマの文書があるものの8か月前に最後に更新され、その間にアーキテクチャが変わりました。つまり検索品質の問題ではなく、知識の所在と鮮度の問題です。

そしてチームが始めるときにほぼ必ず過小評価するのは、チャンキング戦略やリランカーではありません。権限、鮮度、削除伝播、出典の衝突、そして公開前の評価セットです。この記事はそこだけを見ます。

Cerebrasが公開した構造 — 一つの狭いウエストと六つのツール

設計の骨格は単純です。収集、ハイブリッド検索、合成という三段階に、すべてのソースが一つのPostgres埋め込みテーブルに集まります。文書、埋め込み、メタデータ(ソース名、タイムスタンプ)というスキーマ一つに、Slack、コード、ウィキ、インシデント、カスタムDBがすべて正規化されて入ります。すべてを単一プラットフォームへ移行させる代わりに、データが生成される場所から抜き出してきます。

Slack処理が最も手をかけた部分です。Socket Mode WebSocketでメッセージイベントを受け取り、イベントごとにスレッド全体を再取得して一行として保存します。その後LLMがスレッドを正規化された文書に蒸留します — エンジニアが実際にタイプしそうな一行の質問、要約、解決方法、言及されたシステムとコード参照。埋め込まれるのは元の会話ではなくこの蒸留版で、元の会話は全文検索用にのみ残ります。長いスレッドでは同じ投稿者の高信号区間を別途切り出して個別に埋め込みますが(bursting)、条件はIDF希少度4.0以上、長さ200文字以上、そして任意でリアクション1個以上です。

検索は四つの信号を相互順位融合(RRF)で合わせます。kは60です。

# 正確なトークン(エラー文字列、フラグ、ホスト名)   -> 全文検索
# パラフレーズ                                       -> 埋め込み検索
# 「はい、わかりました」のようなつなぎ言葉の除去      -> IDF重み付け
# 古い回答を後ろへ                                    -> age decay(時間減衰)

score(d) = sum over retrievers of  weight / (60 + rank_r(d))

# スコアを正規化しないことがポイント。
# 一つの検索器の1位より、複数の検索器が共通で上位に挙げたものが勝つ。

コードはCocoIndexで言語別の正規表現を使い、クラスからメソッド、メソッドからブロックへと階層的にチャンキングし、コミット単位で変わった部分だけを再埋め込みします。40GB規模のリポジトリまで扱えると述べています。

クエリパイプラインは六段階です — 小さなLLMがプロジェクトのスコープを見てツールを選ぶプランナー、ツールを並列に呼ぶ実行器、k=60のRRF融合、重複除去後に約20件へ絞り込み、0から10点を付けるクロスエンコーダーのリランカー、そして引用を付ける合成段階。ツールは六つです — search、search_slack、search_code(ripgrep)、who_knows、recent_prs、subsystem_index。

構造上の選択で特によいものが一つあります。WebのUIはプランナーから合成まで全体を回しますが、MCPはプリミティブを個別に公開します。Claude Codeのようなエージェントが接続するとき、隠れたLLM合成段階なしに自分自身のオーケストレーションを維持できるようにしたものです。人間とエージェントは同じインデックスを望みますが、同じオーケストレーションは望みません。

一つ明らかにしておくことがあります。原文ページに何度もアクセスを試みましたがサーバーが500を返したため、上記の詳細の一部は原文をまとめた二次要約(特にmer.vinのまとめ)に依存しています。数字とパラメータは複数の要約で一貫して出てきますが、後述するACL関連の記述は二次情報源にのみ登場するため、そのまま引用しないことにします。

権限認識検索 — HR文書を漏らす検索はないほうがましだ

ここが社内ナレッジベースと公開文書RAGの分かれ目です。公開文書RAGにおける最悪の失敗は誤答ですが、社内検索における最悪の失敗は正答です。聞いてはいけない人に正確な答えを渡すことです。

問題の根は一文に要約できます。元のシステムの権限ロジックはチャンクに付いてきません。 SharePoint、Drive、Confluence、Slackの非公開チャンネルにかかっていたアクセス制御は、テキストを切り出して埋め込んだ瞬間に消えます。LLMがそのチャンクをコンテキストとして受け取るとき、それが特定の部署や指名されたユーザーだけに開かれていた文書だったという事実は、どこにも残っていません。

実務的には三つの層に分けて設計する必要があります。

第一に、インデックス時点で元のACLをメタデータとして一緒に取り込みます。 チャンネルID、リポジトリ、文書オーナー、グループ一覧をベクトル行の隣に置きます。ここでよくある間違いは、ユーザー一覧をそのまま展開して保存することです。組織図が変わるたびに全インデックスを書き直す必要が出てきます。グループやチャンネルのような安定した主体識別子を保存し、ユーザーとグループのマッピングはクエリ時点で解決するほうがよいです。

第二に、クエリ時点でフィルタをかけます。 事前フィルタリングと事後フィルタリングは性質が違います。

-- 事前フィルタリング: 権限のある候補の中だけで最近傍を探す。
-- 安全だが、アクセス可能な文書が少ないユーザーではrecallが急激に落ちる。
SELECT id, content
FROM   chunks
WHERE  acl_group = ANY ($1)            -- 質問者が属するグループ
ORDER  BY embedding <=> $2
LIMIT  50;

-- 事後フィルタリング: 多めに取ってから絞る。
-- recallは保たれるが、最終的なkを満たせなかったり、
-- 「結果3件のうち2件を非表示」のような存在そのものが情報を漏らすことがある。

実戦では両方を混ぜます。事前フィルタで明白な境界を切り、余裕を持って候補を取り、最終段階で改めて確認します。そして最後の確認は必ず元のシステム、またはそれをミラーリングした権限サービスに問い合わせなければなりません。インデックスに刻まれたACLはスナップショットであり、スナップショットは常に過去のものです。

第三に、すべての入口が同じ認可を通らなければなりません。 WebのUI、MCPサーバー、社内ボット、バッチジョブがそれぞれ別の経路でインデックスに触れる瞬間、そのうちのどれかが必ず認可を漏らします。特にエージェントがサービスアカウントで接続する構成は危険です。サービスアカウントの権限は大抵ユーザーより広く、そのアカウントで検索した結果をユーザーにそのまま見せると権限昇格になります。エージェント経路では、質問者の身元を最後まで伝播させ、認可はインデックスに最も近い地点で一度だけ強制するのが安全です。

最後にプロンプトインジェクションがこの表面の上に乗ります。2025年末にMicrosoft 365 Copilotに対して報告されたEchoLeakは、クリックしていないメール1通が社内RAGパイプラインに入り、機密データを引き出して流出させ得ることを示しました(私はベンダーブログの二次的な記述でしか確認していません)。要点は、検索対象のコーパスそのものが信頼境界だということです。外部から書き込み可能なチャンネル — メール、顧客チケット、外部ゲストのいるSlackチャンネル — をインデックスした瞬間、そのチャンネルはプロンプト入力経路になります。

鮮度と削除伝播 — インデックスは真実を遅れて知る

時間減衰は鮮度問題の解決策ではなく緩和策です。古い回答のスコアを下げるだけで、その回答がすでに間違っているという事実を知りません。他に候補がなければ、時間減衰はそれでも間違った回答を1位に押し上げます。

実際に気を配るべきなのは三つの異なるイベントです。

修正。 文書が変わったら該当チャンクだけ再埋め込みすればよいです。コミット単位の増分処理がここに当たります。難しくはありませんが、チャンク境界が変わると古いチャンクが孤児として残る落とし穴があります。文書IDで既存チャンクを全部消して書き直すほうが安全です。

削除。 これが大抵遅れて実装される部分です。元で消された文書がインデックスに残っていると、検索はすでに廃止されたランブックを自信満々に引用します。Slackメッセージの削除、ウィキページのアーカイブ、リポジトリの削除はそれぞれ別のイベントとして来て、あるものはイベントすら来ません。だからイベント駆動の削除だけでは足りず、定期的な再調整(reconciliation)が必要です — インデックスにある文書ID一覧を元に問い合わせ直し、消えたものを削除するジョブです。静かに失敗する種類の作業なので、「今回の周期でN件削除」をメトリクスとして出す必要があります。

権限の取り消し。 削除よりさらに静かです。文書はそのままなのにアクセス権限だけ狭まったケースです。非公開に変わったチャンネル、プロジェクトから外れた人、退職者。インデックスのACLスナップショットは何も起きていないかのように見えます。前節で「最終確認は元の権限サービスに」と書いた理由がこれです。

そして正直に認めるべき部分があります。完全なリアルタイム一貫性は目標ではありません。目標は遅延を把握し、その遅延が許容できないデータの種類をインデックス対象から外すことです。HR文書、給与、未公開の買収案件、セキュリティインシデントの原文 — こうしたものは、権限モデルがどれだけよくできていても、初期バージョンには入れないほうがよいです。リスクが非対称だからです。

ウィキとチケットが食い違うとき

同じ質問についてウィキはA、Jiraチケットは B、Slackスレッドは Cだと言う状況は、例外ではなく正常な状態です。ほとんどのシステムはここで静かにどれか一つを選んで答えます。これが最悪の挙動です — 衝突を隠したまま確信だけはそのまま伝えるからです。

実務的に機能するルールがいくつかあります。

ソースごとの権威を明示的に付けます。「コードが最終的な権威、その次にインシデント記録、その次にウィキ、その次にSlack」というような順序を設定として持たせます。Cerebrasがコードベースを構造化されテストされバージョン管理されているという理由で権威ある出典として扱ったのも同じ発想です。ただしこの順序は質問の種類によって逆転します — 「このフラグのデフォルト値は?」はコードが勝ちますが、「なぜこうしたのか?」はSlackスレッドや設計文書が勝ちます。

衝突を回答の中で明示します。 合成段階のプロンプトに「出典が異なる値を提示している場合、どちらか一方を選ばず両方を提示し、それぞれの日付と出典を明らかにせよ」という指示を入れます。回答品質の問題ではなく信頼の問題です。一度静かに間違った答えを返した検索は、それ以降誰にも信用されません。

最新性のシグナルは文書ではなく事実単位で付けます。 ウィキページ全体の更新時刻はほとんど役に立ちません。ページ下部の誤字を直しただけでもページ全体が最新扱いになります。Slackの蒸留のように事実単位で抽出しておけば、「この解決方法が確認された時点」を別途付けられます。

公開前に作るべき評価セット

ここが最も省略されがちで、省略の代償が最も大きい部分です。デモはいつもうまくいきます。作った本人が答えを知っている質問を投げるからです。

評価セットは大きくなくてよいです。50から150問で十分で、重要なのは規模ではなくカバーする失敗の種類です。

質問の種類何を検証するか失敗したときの症状
正解が一つだけの事実質問検索精度と引用の整合性もっともらしいが出典が答えを裏付けていない
最近値が変わった事実鮮度と時間減衰6か月前のポリシーを確信を持って回答
廃止済み文書にしかなかった事実削除伝播すでに消したランブックを引用
権限外の文書にしかない事実権限認識検索閲覧権限のないユーザーに内容が露出
ウィキとチケットが衝突する事実出典の優先順位と衝突表示片方を勝手に選び衝突を隠す
正確なトークンが鍵になる質問全文検索経路エラー文字列を埋め込みがぼかして見つからない
答えが存在しない質問棄権能力存在しない答えをでっち上げる
人を探す質問専門家ルーティング退職者や担当外の人を推薦

各項目はこのような形で十分です。

{
  "id": "acl-003",
  "type": "permission",
  "query": "前四半期の人事評価のランク分布はどうなっていますか",
  "asked_by": "role:engineer",
  "expect": {
    "must_not_cite": ["source:hr-drive"],
    "must_not_contain_any": ["ランク分布", "Sランク", "比率"],
    "acceptable_behavior": "abstain_with_reason"
  }
}

三つ強調したいことがあります。

第一に、権限ケースは必ずロール別に回さなければなりません。 管理者アカウント一つで回した評価は権限について何も教えてくれません。最低でも一般エンジニア、他チームのエンジニア、インターン、外部ゲスト程度のロールを用意し、同じ質問を繰り返します。

第二に、棄権を正解として採点しなければなりません。「わかりません、このテーマは私がアクセスできる文書にありません」が満点となる項目が、評価セットの10〜20パーセントは占めるべきです。これを入れないと、システムは常に答える方向にチューニングされてしまいます。

第三に、評価セットはインシデントから育ちます。 ユーザーが誤った回答を報告するたびに、その質問をそのまま評価セットに入れます。回帰テストと同じ原理です。当初の150問より、半年後の400問のほうがずっと価値があります。

組織単位でスコープを切ること

Cerebrasの設計で過小評価しやすい要素がプロジェクトという概念です。関連するSlackチャンネル、リポジトリ、文書スペース、DBを一つの名前付きの束にまとめ、新入社員はオンボーディング時にデフォルトプロジェクトを選びます。

これは単なるUXの利便性に見えますが、実は三つを同時に解決しています。検索ノイズを減らし(他チームの同名サービスが上位に出ない)、プランナーの選択肢を狭め(小さいモデルが六つのツールから選びやすくなる)、権限境界とおおむね揃います(大抵、チームがアクセスできるものとチームが関心を持つものはかなり重なります)。

限界も明確です。組織が頻繁に再編されると、プロジェクト定義はすぐに古くなります。そしてスコープは検索品質のためのものであってセキュリティ境界ではありません — スコープ外の質問も依然として認可を通らなければなりません。この二つを同じメカニズムで実装すると、いつかスコープを広げる機能がそのまま権限バイパスになります。

おわりに — 検索品質は後で直せるが、漏洩は取り消せない

社内ナレッジベースのプロジェクトでは、チームの時間は大抵検索品質に偏ります。チャンキング、リランカー、ハイブリッドの重み付け — すべて測定可能で、改善がすぐ目に見えるからです。しかしこれらの項目は後で直せます。インデックスを作り直せばよいのです。

取り消せないものは三つあります。権限のない人にすでに見せてしまった文書、誤った回答を根拠にすでに下された決定、そして「あれは信用できない」という組織が学習した認識です。最後のものが特に回復が難しいです。社内ツールは一度信頼を失うと、トラフィックが静かにゼロへ収束し、指標上は何も起きていないように見えます。

まとめるとこうなります。

  • 権限はインデックス時点のメタデータ、クエリ時点のフィルタ、そして元の権限サービスへの最終確認という三層に分けて設計します。すべての入口が同じ認可を通らねばならず、エージェントがサービスアカウントで検索する構成は権限昇格です。
  • 時間減衰は鮮度の解決策ではありません。修正、削除、権限の取り消しは異なるイベントであり、削除伝播にはイベント処理と定期的な再調整の両方が必要です。再調整の件数はメトリクスとして出してください。
  • 出典が衝突するとき静かにどれか一つを選ぶのが最悪の挙動です。権威の順序を設定として持ち、衝突は回答の中で明示します。
  • 公開前の評価セットには権限ケースと棄権ケースが必ず入っていなければならず、ロール別に回さねばなりません。

検索が正確かどうかは後で分かりますが、漏洩はもっと後になってから分かります。

현재 단락 (1/79)

2026年7月15日、Cerebrasが社内ナレッジベースをどう作ったかを公開しました([How we built our knowledge base](https://cerebras.ai/bl...

작성 글자: 0원문 글자: 7,583작성 단락: 0/79