「探す」のをやめて「見つける」体験を:KhojとDockerでプライベートAI検索をセルフホストする

AI tutorial - IT technology blog
AI tutorial - IT technology blog

午前2時15分のドキュメント行き詰まり

時刻は午前2時15分。私はレガシーなデプロイ環境で発生した 504 Gateway Timeout エラーをじっと見つめていました。半年前に全く同じ問題を解決した記憶があります。

解決策となった特定のNginxバッファ設定を書き留めたことさえ覚えています。しかし、1,200個ものMarkdownファイルから「Nginx timeout」を検索しても、無関係な結果が大量に返されるだけ。grep も役に立ちません。元のメモでは「timeout」ではなく「latency(遅延)」という言葉を使っていた可能性があったからです。私の個人ナレッジベースは、価値はあるものの整理のつかない「デジタルの屋根裏部屋」と化していました。

こうした不満こそが、セマンティック検索(意味検索)が不可欠になりつつある理由です。Notion AIやObsidian Copilotのようなツールは、単なる文字の一致ではなく、ユーザーの「意図」に基づいて情報を見つけ出します。しかし、個人の知的財産をサードパーティのクラウドに提供することは、大きなプライバシーリスクを伴います. 私はデータの流出を心配することなく、大規模言語モデル(LLM)の知能を利用したいと考えました。プライバシーを重視したその探求の末に、Khojにたどり着いたのです。

今の検索が「使い物にならない」と感じる理由

標準的な検索はリテラル(逐一的)です。例えば「database performance」で検索した場合、基本的なツールは「Scaling Postgres Queries」というタイトルのメモを無視します。単に文字が一致しないからです。この硬直したアプローチのせいで、数ヶ月前に自分がどのように思考を言語化したかを正確に覚えていなければならなくなります。

セマンティック検索は、ベクトル埋め込み(Vector embeddings)を使用して異なる仕組みで動作します。これを人間の言語を数学的な地図にしたものだと考えてください。

テキストをその意味を表す一連の数値(ベクトル)に変換します。「サイトを速くするには?」と尋ねると、システムはその概念に数学的に「近い」メモを探し、キャッシュ、CDN、画像圧縮に関するドキュメントを表示します。Khojはこの負荷の高い処理をローカルで管理し、自然言語を使用してPDF、Markdown、さらにはGitHubリポジトリまでクエリできるようにします。

Khoj:プライバシー優先のAIアシスタント

Khojは、自身のハードウェア上で動作するように設計されたオープンソースのAIアシスタントです。単なる検索以上のことが可能です。長い研究論文を要約したり、ノートと対話して矛盾を見つけたり、自分の執筆スタイルに基づいた新しいコンテンツを生成したりすることもできます。Dockerを使用してKhojをデプロイすることで、環境のポータビリティを確保し、システムの他の部分から隔離された状態を保てます。

ハードウェア要件

  • Docker & Docker Compose: 最新バージョンが動作していることを確認してください。
  • RAM: 最小8GBですが、ローカルLLMを実行する場合は16GBを推奨します。
  • ストレージ: ベクトルデータベースとモデルの重み用に、少なくとも10GBの空き容量が必要です。
  • モデルの選択: 速度を重視する場合はOpenAIのAPIキー、100%ローカル・オフライン環境で利用する場合はOllamaインスタンスを使用します。

DockerによるKhojのデプロイ

私は、セットアップの再現性が高く更新も簡単なDocker Composeを好んで使用します。設定を永続化しつつ、Khojコンテナがローカルファイルを参照できるように構成する必要があります。以下は、開始するための信頼できる docker-compose.yml です。

version: '3.8'

services:
  khoj:
    image: khoj/khoj:latest
    container_name: khoj
    volumes:
      - ./khoj_config:/home/khoj/.khoj
      - /home/user/my_notes:/home/khoj/data:ro
    ports:
      - "42110:42110"
    environment:
      - KHOJ_DOMAIN=localhost
    restart: unless-stopped

ボリュームマッピングの /home/user/my_notes:/home/khoj/data:ro に注目してください。最初のパスを、実際のObsidianの保管庫(Vault)やPDFフォルダの場所に置き換えてください。:ro(読み取り専用)フラグを使用することを強くお勧めします。これにより、AIがオリジナルのファイルを誤って変更したり削除したりするリスクを排除しつつ、あなたの思考を読み取ってインデックス化できるようになります。

インスタンスの起動

ターミナルを起動して、以下を実行します。

docker-compose up -d

コンテナが初期化されたら、ブラウザで http://localhost:42110 を開きます。初回実行時、Khojはファイルのインデックス作成を開始します。2,000ファイル以上の大規模なライブラリがある場合、データの数学的マップを作成するため、15分から30分ほどかかることを覚悟しておいてください。

ナレッジベースの接続

ウェブインターフェース内の「Content Sources」設定に移動します。ここで、Khojが実際に何を参照するかを微調整します。ローカルディレクトリ、特定のGitHubリポジトリ、あるいはクラウドからの移行途中であればNotionワークスペースをリンクすることも可能です。

完全にローカルな体験を維持するには、Khojの接続先をOllamaインスタンスに向けます。この設定により、データがネットワーク外に出ることはありません。設定でモデルプロバイダーを「Ollama」に変更し、URLを http://host.docker.internal:11434 に設定します。これにより、Dockerコンテナがホストマシン上で動作しているOllamaサービスと通信できるようになります。

検索の関連性の最適化

最初の検索結果は、.git フォルダや node_modules からのノイズで散らかっていました。これを解決するには、データディレクトリに .khojignore ファイルを作成します。.gitignore と同様に、このファイルはAIにスキップすべきフォルダを伝えます。ログファイルや依存関係フォルダを除外することで、ベクトルデータベースが軽量になり、検索速度が大幅に向上します。

パフォーマンスとリソース管理

ローカルAIの実行はCPUに負荷をかける可能性があります。ファンの音が大きすぎたり、システムの動作が重く感じたりする場合は、ComposeファイルでDockerのリソース消費を制限できます。

deploy:
  resources:
    limits:
      cpus: '4'
      memory: 6G

セキュリティの観点から見ると、このアーキテクチャは大きな勝利です。たとえチャットインターフェースにOpenAIのモデルを使用することを選択したとしても、RAG(検索拡張生成)の「検索(Retrieval)」部分は自分のマシン上で行われます。ライブラリ全体ではなく、関連するごく一部のテキスト断片のみがコンテキストとしてLLMに送信されます。Ollamaを使用すれば、プライバシーは絶対的なものになります。

最後に

午前3時までには、ローカルのKhojインスタンスのインデックス作成が完了しました。「Nginxのプロキシタイムアウトはどうやって直した?」と尋ねると、昨年のプロジェクトフォルダに埋もれていた正確な proxy_read_timeout の設定が即座に表示されました。もうスクロールし続ける必要も、推測する必要もありません。

セマンティック検索システムへの移行は、自身のデータとの向き合い方を根本的に変えるものです。それは、静的なメモの山を、自分を真に理解してくれるインタラクティブな「第二の脳」へと変貌させます。プライバシーと時間を大切にしたいのであれば、CTRL+F を叩くのはやめて、自分専用のローカルAI検索エンジンの構築を始めましょう。

Share: