【無料ツール】画像をPDFに変換するPhotoPDF Appを公開しました!

Linuxエンジニアの生成AI活用 第6回:膨大なマニュアルを瞬時に検索!Linuxサーバー内「簡易RAG」の構築

こんにちは!「LINUX工房」メインライターの「リナックス先生」よ。

前回の第5回では、情報漏洩のリスクをゼロにするため、完全ローカルで動くLLM「Ollama」をサーバーに導入したわね。これで、どんな機密データでも安心してAIに見せられるようになったわ。でも、実務の現場では「AIがそもそも自社のシステム構成や社内ルールを知らない」という根本的な問題に直面するはずよ。今回は、AIに「自社のマニュアル」を読み込ませて、社内専用の最強コンサルタントを作り上げる「RAG(検索拡張生成)」という技術を、Linuxの黒い画面の中で構築するわよ!

コウ君

先生!ローカルのAIに「うちの会社のWebサーバーの再起動手順を教えて」って聞いたら、「一般的なNginxの再起動手順は…」って返ってきました。違うんです、うちの会社は独自のシェルスクリプトを通さないとダメなんです!AIって、一般的なことしか答えられないから、社内業務には使えないんじゃないですか?

リナックス先生

AIが社内のルールを知らないのは当然よ。AIは「インターネット上の公開情報」しか学習していないんだから。でも、「じゃあ使えない」と諦めるのは三流の証拠よ。プロのインフラエンジニアは、AIに回答させる直前に「社内マニュアルの該当部分」を強制的に読ませるパイプラインを作るの。今日であなたのAIを「社内事情に一番詳しいベテラン社員」に進化させるわよ!

Linuxエンジニアのための生成AIフル活用カリキュラム(全8回)

  1. 第1回:ブラウザを捨てよ!「黒い画面」からAIを呼び出すAPIとcurlの基礎
  2. 第2回:コマンド忘れはもう怖くない!ターミナル専属AIアシスタントの構築
  3. 第3回:難解なエラーログを一瞬で解読!パイプで繋ぐトラブルシューティング
  4. 第4回:手作業をゼロへ!AIに「インフラ自動化スクリプト」を書かせる極意
  5. 第5回:機密データを守れ!「Ollama」で作る完全ローカルなLLM環境構築
  6. 【今回】第6回:膨大なマニュアルを瞬時に検索!Linuxサーバー内「簡易RAG」の構築
  7. 第7回:AIを監視オペレーターにする!Cron×LLMの「自動レポートボット」
  8. 第8回:AI時代のエンジニアサバイバル!セキュリティの壁とこれからのインフラ運用

1. 幻覚(ハルシネーション)の正体とRAGの概念:AIにカンペを渡す技術

① 概念と背景(Why)

生成AI(LLM)は、インターネット上の膨大なテキストデータを学習し、言語の構造や一般的な事実関係を驚異的な精度で記憶しています。しかし、AIのこの「記憶」は、学習が行われた時点(カットオフ)で完全に凍結されています。さらに決定的な問題として、AIはあなたの会社の社内Wikiや、昨日構築したばかりの社内データベースのIPアドレス、非公開のGitリポジトリにある運用手順書といった「プライベートなデータ」を1バイトたりとも学習していません。

この「知らない」という状態に対して、AIは非常に厄介な挙動を示します。それが「ハルシネーション(幻覚)」です。LLMは本質的に「確率的にもっともらしい次の単語を予測して出力するマシーン」であるため、「わからない」と答えるよりも、一般的な知識を継ぎ接ぎして「もっともらしい嘘(架空の設定や手順)」を自信満々に生成してしまう傾向が強いのです。インフラ運用において、架空の再起動コマンドや存在しないサーバーのIPアドレスを提示されることは、システム障害を拡大させる致命的なリスクとなります。この問題を「再学習(ファインチューニング)」で解決しようとするアプローチもありますが、社内マニュアルが更新されるたびに数億円のコストと数週間の時間をかけてAIを再学習させるのは、現実的なインフラ運用とは到底呼べません。

このジレンマを美しく解決する現代の最適解が「RAG(Retrieval-Augmented Generation:検索拡張生成)」というアーキテクチャです。RAGの仕組みは、例えるなら「試験会場にいる優秀だが記憶喪失の受験生(AI)に、試験官(あなた)が質問に関連する教科書のページ(検索結果)をカンペとして渡し、『このページの内容だけを根拠にして答えなさい』と指示する」ようなものです。AI自身の凍結された記憶には頼らず、外部のデータベースやテキストファイルから「検索(Retrieval)」してきた最新・正確な情報を、プロンプトの一部として「拡張(Augmented)」して渡し、その上で回答を「生成(Generation)」させます。これにより、ハルシネーションを極限まで抑え込み、完全に社内事情に特化したAIアシスタントを、再学習コストゼロで稼働させることができるのです。

② 実践手順と完全なコード(How)

RAGの概念を理解するために、まずは「AIが知らない社内情報」を質問し、見事に幻覚を起こす様子を確認します。その後、全く同じ質問に「カンペ(コンテキスト)」を与えて、正しい回答を導き出すプロンプトの違いをターミナルで体験します。(※前回のOllamaとaichatが構築済みの前提です)

# 1. 外部情報なしで、AIの内部記憶だけに依存して質問する(高確率で幻覚が起きる)
aichat "社内の決済システムのデータベースサーバーのホスト名とIPアドレスを教えてください。"

# 2. 検索してきた(という設定の)テキストデータをカンペとして与え、厳格な条件をつけて質問する(RAGの基礎)
aichat --role "system" "あなたは社内システムの案内役です。以下の【社内情報】のみを根拠に回答し、情報がない場合は必ず『マニュアルに記載がありません』と答えてください。" \
"【社内情報】
・決済DBサーバー: host=pay-db-prod01.local, IP=192.168.100.50
・認証DBサーバー: host=auth-db-prod01.local, IP=192.168.100.51

【質問】
社内の決済システムのデータベースサーバーのホスト名とIPアドレスを教えてください。"

③ プロによるコードの「1行・1オプション」徹底解説

  • aichat “社内の決済システムの…”:何も前提条件を与えずに質問を投げています。AIは「一般的な決済システムの例ですが…」と前置きして架空のIPを答えたり、「私はAIなので社内情報にはアクセスできません」と謝絶したりします。これがLLMの素の挙動です。
  • aichat –role “system” “…”:AIに対して「ロール(役割)」と「絶対のルール」を強制的に設定します。ここで「【社内情報】のみを根拠に回答し…」という強力な制約(グラウンディング)をかけることが、RAGにおいてAIの暴走を防ぐ最大の防波堤となります。
  • “【社内情報】…”:ここがRAGにおける「Retrieval(検索)」によって本来システムが自動で差し込むべきテキスト部分です。インフラエンジニアはこの部分をいかに正確に、自動で抽出してくるかというパイプラインの構築に全力を注ぎます。
  • “【質問】…”:ユーザーが実際に知りたいクエリ(質問)です。情報と質問を明確な記号(【】など)で分離することで、AIの理解精度が飛躍的に向上します。

④ 現場のリアル(失敗談とノウハウ)

RAGを構築した新人がよく陥る罠が、「検索したテキストを渡したのに、AIがそれを無視して自分の知識で答えてしまう」という現象です。これはプロンプトの指示が弱い(システムプロンプトによる強制力がない)場合に発生します。また、「情報がない場合は『わからない』と答えろ」という指示を忘れると、検索結果に該当情報が含まれていないにも関わらず、AIが「文脈から推測」して勝手に架空のパスワードを生成してしまう事故が起きます。現場のプロは、AIを信用せず、常に「与えられたコンテキスト以外からの回答を厳禁する」という強い制約をプロンプトの先頭と末尾に二重に配置するほどの慎重さを持っています。RAGの成否は、検索の精度だけでなく、AIの手綱を握るプロンプトエンジニアリングの厳格さにかかっているのよ!


2. コンテキスト・スタッフィング:最も原始的で強力なマニュアル注入

① 概念と背景(Why)

RAGの「検索(Retrieval)」部分を実装する前に、インフラエンジニアが知っておくべき最もシンプルで暴力的な手法があります。それが「コンテキスト・スタッフィング(Context Stuffing:文脈の詰め込み)」です。これは、検索システムを一切作らず、「マニュアルのテキストファイル全体を丸ごとプロンプトに結合してAIに読み込ませる」という荒業です。

なぜこのような原始的な手法が現場で重宝されるのでしょうか。現代のローカルLLM(Llama 3など)は、「コンテキストウィンドウ」と呼ばれる「一度に読み込める文字数(トークン数)の限界」が飛躍的に拡大しています。初期のAIは数千文字しか読めませんでしたが、現在では8,000トークン(日本語で約1万文字以上)から、モデルによっては128,000トークン(文庫本一冊分)ものテキストを一度のプロンプトで飲み込むことができます。もしあなたの会社が運用しているサーバーの「障害対応手順書」がMarkdown形式で数千文字程度にまとまっているのであれば、複雑な検索システムを構築する時間と労力をかけるのは無駄です。ファイルをそのまま `cat` してAIの入力にぶち込むだけで、完璧に社内事情を把握したAIが即座に誕生するのです。

コンテキスト・スタッフィングの最大のメリットは「検索漏れ(Retrieval Failure)が絶対に起きない」ことです。テキスト全体をAIの脳内に一時的に展開するため、複数の手順を横断するような複雑な質問であっても、AIは文書全体を俯瞰して正確な回答を導き出します。Linuxの標準コマンドである `cat` とパイプ `|` さえあれば、今すぐこの瞬間からサーバー上で簡易RAGを稼働させることができる、極めてLinux哲学に合致したアプローチと言えます。

② 実践手順と完全なコード(How)

サーバー内に仮想の社内マニュアルファイルを作成し、それをまるごとAIに読み込ませて質問する完全なシェルコマンドを実行します。

# 1. サーバー構成や再起動手順を記した社内マニュアル(Markdown形式)を作成する
cat << 'EOF' > internal_server_manual.md
# 社内インフラ運用マニュアル

## Webサーバー群
- **web-prod-01**: IP 10.0.1.11, 用途: メインWebフロント
- **web-prod-02**: IP 10.0.1.12, 用途: サブWebフロント

## サービス再起動の独自ルール
当社のWebサーバーでは、標準の `systemctl restart nginx` は**絶対に使用禁止**です。
セッションの切断を防ぐため、必ず以下の独自スクリプトをフルパスで実行してください。
実行コマンド: `/opt/scripts/graceful_restart_web.sh`
実行前に必ずSlackの #infra-alerts チャンネルに「再起動開始」と通知すること。
EOF

# 2. catでマニュアル全体を読み込み、パイプでaichatに渡して質問する
cat internal_server_manual.md | aichat --role "system" "あなたはインフラ保守AIです。入力されたマニュアルの内容に完全に従って回答してください。" \
"Webサーバーの挙動がおかしいので再起動したいです。どのようなコマンドを打てばいいですか?手順を教えてください。"

③ プロによるコードの「1行・1オプション」徹底解説

  • cat << ‘EOF’ > internal_server_manual.md:ヒアドキュメントを用いて、社内の独自ルールが記載されたマニュアルファイルを生成しています。このようにマークダウン(`#` や `-` を使った構造化テキスト)で記述すると、AIは見出しや箇条書きの構造を論理的に理解しやすくなります。
  • 実行コマンド: `/opt/scripts/…`:AIが絶対に知らない、自社固有のスクリプトパスです。これを正しく回答させることがスタッフィングの目的です。
  • cat internal_server_manual.md:マニュアルファイルの中身を標準出力に展開します。
  • | (パイプ):展開されたマニュアルの全テキストを、AIのコンテキスト(前提知識)として強制的に注入します。
  • aichat –role “system” “…”:パイプから流れてきた数千文字のマニュアル情報をバックグラウンドで保持しつつ、ユーザーからの「Webサーバーを再起動したい」という質問に対して、マニュアル内のルールを適用して回答を生成します。

④ 現場のリアル(失敗談とノウハウ)

コンテキスト・スタッフィングは強力ですが、致命的な弱点があります。それは「Lost in the middle(真ん中の消失)現象」です。人間と同じように、AIも「渡された文章の最初と最後」はよく覚えていますが、文章が数万文字に膨れ上がると「真ん中あたりに書かれていた重要な制約事項」をすっぽりと忘れて幻覚を起こす特性があります。何十ページにも及ぶ巨大なPDFやWikiの全ページを無理やり `cat` で流し込んでも、AIは混乱し、推論の処理速度(メモリ消費)も劇的に悪化してタイムアウトを引き起こします。「ファイルサイズが1万文字(約10KB)を超えたら、スタッフィングを諦めて『検索(Retrieval)』を導入する」。これが、インフラエンジニアがシステムを設計する際の明確な境界線となるのよ!


3. LinuxネイティブRAGの実装:grep検索とAI生成の華麗なる連携

① 概念と背景(Why)

マニュアルが肥大化し、数万行に及ぶログや数百個のMarkdownファイル群となった時、前項のコンテキスト・スタッフィングは機能しなくなります。ここでいよいよRAGの「R(Retrieval:検索)」を実装する必要があります。一般的に、RAGの検索システムを構築するにはPythonの高度なライブラリや専用のベクトルデータベース(ChromaDBなど)が必要だと思われがちですが、私たちはLinuxインフラエンジニアです。Linuxの環境下において、テキストの高速検索を行う最強のネイティブツールが既に存在しています。それが「`grep` コマンド」です。

LinuxネイティブRAGのアーキテクチャは非常にシンプルかつ堅牢です。ユーザーから質問(クエリ)を受け取った際、シェルスクリプトがその質問文から「重要なキーワード」を抽出し、`grep` コマンドを使って社内のマニュアルディレクトリ全体(何百ものテキストファイル)を高速スキャンします。そして、キーワードがヒットした行とその前後の文脈(`-C` オプション)だけを切り出し、極限まで圧縮された「純度の高い関連テキスト」として生成AIのプロンプトに注入するのです。

この手法の美しさは、外部のデータベースやPythonの依存ライブラリを一切必要とせず、Bashと標準コマンドだけで完結する点にあります。何年も前からインフラエンジニアが日常的に行ってきた「ログを `grep` して調べる」という一連の思考プロセスを、シェルスクリプトで自動化し、最後にAIという「解釈エンジン」に通すだけです。これこそが、Unix哲学である「小さなツールを組み合わせて大きな価値を生む」を体現した、最も美しく実用的な簡易RAGの姿なのです。

② 実践手順と完全なコード(How)

指定したディレクトリ内の全ドキュメントから、質問に関連するキーワードを `grep` で検索し、ヒットした文脈だけを抽出して `aichat` に渡す、完全動作するBashベースのRAGスクリプトを作成します。

#!/bin/bash
# ファイル名: bash_rag.sh
# 実行権限を付与してください: chmod u+x bash_rag.sh

set -euo pipefail

# 知識ベースとなるドキュメントが保存されているディレクトリ
KNOWLEDGE_DIR="/var/company_docs"
# 検索する際、前後の文脈を何行取得するか
CONTEXT_LINES=5

# ユーザーからの質問(引数)を受け取る
QUESTION="${1:-}"
if [[ -z "${QUESTION}" ]]; then
    echo "エラー: 質問を引数として渡してください。"
    echo "使用例: ./bash_rag.sh 'データベースのパスワードは何ですか?'"
    exit 1
fi

# 【簡易的なキーワード抽出】
# 質問文から助詞などを除き、名詞などの検索キーワードを手動または単純なパターンで決定します
# ここでは実用上、スクリプト実行時に第2引数で明示的なキーワードを渡す設計とします
KEYWORD="${2:-}"
if [[ -z "${KEYWORD}" ]]; then
    echo "エラー: 第2引数で検索用のキーワードを指定してください。"
    echo "使用例: ./bash_rag.sh 'DBのパスワードを教えて' 'データベース'"
    exit 1
fi

echo "[INFO] 知識ベース (${KNOWLEDGE_DIR}) から '${KEYWORD}' を検索しています..."

# grepでドキュメント群を検索し、結果を変数に格納する
# -r: 再帰的検索, -i: 大文字小文字無視, -C: ヒット行の前後行も抽出
SEARCH_RESULT=$(grep -r -i -C "${CONTEXT_LINES}" "${KEYWORD}" "${KNOWLEDGE_DIR}" 2>/dev/null || true)

# 検索結果が空の場合のエラーハンドリング
if [[ -z "${SEARCH_RESULT}" ]]; then
    echo "[WARN] 知識ベース内に '${KEYWORD}' に関する情報が見つかりませんでした。"
    echo "AIは一般的な知識のみで回答します。"
    CONTEXT_PROMPT="社内情報は見つかりませんでした。一般的な知識で回答してください。"
else
    echo "[INFO] 関連情報を抽出しました。AIに解析させています..."
    CONTEXT_PROMPT="以下の【社内ドキュメントの検索結果】を最も優先的な根拠として、ユーザーの【質問】に回答してください。
【社内ドキュメントの検索結果】
${SEARCH_RESULT}"
fi

# 抽出したコンテキストと質問を結合し、aichatの標準入力へパイプで流し込む
echo -e "${CONTEXT_PROMPT}\n\n【質問】\n${QUESTION}" | aichat --role "system" "あなたはインフラ運用アシスタントです。提供された情報を元に、正確かつ簡潔に回答してください。"

③ プロによるコードの「1行・1オプション」徹底解説

  • set -euo pipefail:インフラスクリプトの命綱です。エラー時に処理を即座に停止し、予期せぬ破壊的挙動を防ぎます。
  • KEYWORD=”${2:-}”:BashネイティブRAGの最大の課題は「自然言語の質問文からどうやって `grep` 用のキーワードを抽出するか」です。今回はスクリプトを堅牢にするため、ユーザーに明示的にキーワード(第2引数)を指定させる設計にしています。
  • grep -r -i -C “${CONTEXT_LINES}”:RAGにおける Retrieval(検索)のコアエンジンです。`-r` でディレクトリ内の全ファイルを調べ、`-C 5` でヒットした行の前後5行も抽出します。この「前後の文脈」がないと、AIは設定値の背景や警告文を読み落とすため、RAGにおいては `-C`(または `-B` `-A`)オプションが絶対必須となります。
  • || true:`grep` は検索結果がゼロ件だった場合、終了ステータス `1` を返します。冒頭の `set -e` によってスクリプトが異常終了してしまうのを防ぐため、`|| true` を付与して強制的に正常終了扱いにし、後続の `if` 文で空文字判定を行って安全に処理を分岐させています。
  • echo -e “…” | aichat:変数に格納した検索結果(コンテキスト)と質問文を美しいフォーマットで結合し、パイプを通じてAIの脳内へ注入します。

④ 現場のリアル(失敗談とノウハウ)

`grep` を用いたBashネイティブRAGは爆速で動作しますが、「表記揺れ」という致命的な弱点を抱えています。ユーザーが「DBのIPを教えて」と質問し、検索キーワードに「DB」を指定したとします。しかし、社内マニュアルには「Databaseサーバー」あるいは「データベース」としか書かれていなかった場合、`grep` は完全に空振りし、AIは「情報がありません」と答えてしまいます。現場ではこの欠点を補うため、`grep -E “DB|Database|データベース”` のように正規表現(`-E`)を用いて複数の同義語を力技で検索する泥臭い工夫が必須になります。キーワードの完全一致に依存する限界、それが「文字列検索」の壁なのです。


4. Pythonによる意味検索(Semantic Search)と完全手組みベクトルRAG

① 概念と背景(Why)

前項の `grep` による検索は、文字の形が完全に一致しなければ情報を取り出せないという限界がありました。しかし、人間は「パスワードを忘れた」という質問に対して、「認証エラーの復旧手順」というマニュアルを提示してほしいと望みます。この「文字の形は違うが、意味(セマンティクス)は同じ」という高度な検索を実現するのが、現代のRAGの主流である「ベクトル検索(Semantic Search)」です。

ベクトル検索の概念は、テキストをAIの力を使って「高次元空間の座標(数値の配列)」に変換することから始まります。これを「Embedding(埋め込み)」と呼びます。例えば、「りんご」という単語と「みかん」という単語は、文字は全く違いますが「果物」という概念が近いため、AIが計算した座標空間上では非常に近い距離に配置されます。同様に、「DBに繋がらない」という質問の座標と、「データベースのネットワーク障害対応」というマニュアルの座標は、意味が近いために空間上で接近します。この二つの座標間の角度(コサイン類似度)を数学的に計算することで、キーワードが一切一致していなくても、意味的に最も関連性の高いドキュメントを抽出できるのです。

本格的なRAGシステムでは「ChromaDB」などの重厚なベクトルデータベースライブラリを導入しますが、ブラックボックス化したツールを使うだけではインフラエンジニアとしての真の理解は得られません。実は、ベクトル検索は外部ライブラリを一切インストールしなくても、Pythonの標準ライブラリ(数学モジュールと標準のHTTP通信)だけで完全に自作することが可能です。Ollamaの「Embedding API」を呼び出してテキストを数値化し、Pythonの計算式で類似度を比較して、最も意味の近いテキストを抽出してAIに渡す。この一連の「ゼロからの本格RAG構築」を通して、AIが内部でどのように知識を検索しているのか、その本質を理解しましょう。

② 実践手順と完全なコード(How)

外部のPipライブラリ(numpyやchromadb等)を一切使用せず、Pythonの標準機能とローカルのOllama APIだけで「意味検索」と「回答生成」を行う、完全手組みの本格RAGスクリプトです。

#!/usr/bin/env python3
# ファイル名: semantic_rag.py
# 実行権限: chmod u+x semantic_rag.py

import json
import urllib.request
import math

# --- 1. 知識ベースの準備(本来はファイルから読み込みますが、今回は配列で定義) ---
KNOWLEDGE_BASE = [
    "Webサーバー(Nginx)の再起動は、必ず /opt/scripts/restart_web.sh を使用すること。",
    "データベースのバックアップは毎晩深夜3時に実行され、/backup/db/ に保存される。",
    "社員用Wi-Fiのゲストパスワードは 'guest2026' である。",
    "VPNに接続できない場合は、まず社内ポータルから証明書を再発行すること。"
]

OLLAMA_EMBED_URL = "http://localhost:11434/api/embeddings"
OLLAMA_CHAT_URL = "http://localhost:11434/api/generate"
MODEL_NAME = "llama3.1"

# --- 2. テキストをベクトル(数値の配列)に変換する関数 ---
def get_embedding(text):
    data = json.dumps({"model": MODEL_NAME, "prompt": text}).encode("utf-8")
    req = urllib.request.Request(OLLAMA_EMBED_URL, data=data, headers={"Content-Type": "application/json"})
    with urllib.request.urlopen(req) as response:
        result = json.loads(response.read().decode("utf-8"))
        return result["embedding"]

# --- 3. 2つのベクトル間の近さ(コサイン類似度)を計算する数学関数 ---
def cosine_similarity(v1, v2):
    # 内積を計算
    dot_product = sum(a * b for a, b in zip(v1, v2))
    # 各ベクトルの大きさを計算
    magnitude1 = math.sqrt(sum(a ** 2 for a in v1))
    magnitude2 = math.sqrt(sum(a ** 2 for a in v2))
    if magnitude1 == 0 or magnitude2 == 0:
        return 0.0
    return dot_product / (magnitude1 * magnitude2)

# --- 4. メイン処理:意味検索とRAGの実行 ---
def main():
    user_query = "ネットワークの外から社内システムに入れないんだけど、どうすれば直る?"
    print(f"[INFO] ユーザーの質問: {user_query}")

    # 質問をベクトルに変換
    query_vector = get_embedding(user_query)

    best_match = ""
    highest_score = -1.0

    print("[INFO] 知識ベースと意味の近さ(類似度)を計算中...")
    for doc in KNOWLEDGE_BASE:
        doc_vector = get_embedding(doc)
        score = cosine_similarity(query_vector, doc_vector)
        print(f"  - スコア: {score:.4f} | テキスト: {doc}")
        
        # 最もスコアが高い(意味が近い)ドキュメントを記録
        if score > highest_score:
            highest_score = score
            best_match = doc

    print(f"\n[INFO] 最も関連性の高い情報(コンテキスト): {best_match}\n")

    # --- 5. 検索結果(ベストマッチ)を含めたプロンプトを構築してAIに回答させる ---
    prompt = f"""あなたは親切な社内ヘルプデスクAIです。
以下の【社内情報】のみを根拠にして、ユーザーの【質問】に回答してください。

【社内情報】
{best_match}

【質問】
{user_query}
"""
    
    print("[INFO] AIによる回答を生成中...\n")
    data = json.dumps({"model": MODEL_NAME, "prompt": prompt, "stream": False}).encode("utf-8")
    req = urllib.request.Request(OLLAMA_CHAT_URL, data=data, headers={"Content-Type": "application/json"})
    with urllib.request.urlopen(req) as response:
        result = json.loads(response.read().decode("utf-8"))
        print(f"AIの回答:\n{result['response']}")

if __name__ == "__main__":
    main()

③ プロによるコードの「1行・1オプション」徹底解説

  • OLLAMA_EMBED_URL:Ollamaが標準で提供している、テキストを数値化(Embedding)するための隠しAPIエンドポイントです。
  • json.dumps(…).encode(“utf-8”):Pythonの辞書データをJSON文字列に変換し、さらにHTTP通信で送れるようにバイト列(バイナリ)にエンコードする必須の手続きです。
  • def cosine_similarity(v1, v2)::外部ライブラリの `numpy` を使わずに、標準の `math` モジュールだけでコサイン類似度を実装した極めて教育的な関数です。2つの配列の各要素を掛け合わせて足す(内積)ことで、空間上での角度の近さを割り出します。スコアが `1.0` に近いほど、AIにとって「意味が完全に同じ」と判定されています。
  • highest_score = score:すべての知識ベースの文章と質問文のスコアを総当たりで計算し、最も高いスコアを叩き出した「意味的に正解の文章」だけを `best_match` として抽出します。これがベクトル検索エンジン(ChromaDBなど)が裏で行っている処理の完全な正体です。

④ 現場のリアル(失敗談とノウハウ)

⚠️ トラブルシューティング / 注意点:ベクトル計算の処理負荷とDB化の必要性
この純粋なPythonスクリプトはベクトル検索の本質を学ぶには最高の教材ですが、実際の現場で知識ベースが「数万行のマニュアルファイル」になった場合、検索のたびに数万回のEmbedding API通信と総当たりの数学計算が発生し、回答までに数時間かかるという地獄を見ます。現場のプロは、マニュアルが更新されたタイミングで事前に全テキストをEmbedding(ベクトル化)して結果を保存しておく「ベクトルデータベース(ChromaDBやQdrant)」を導入し、検索時の計算負荷をゼロにするアーキテクチャを組みます。「原理を理解してからツールを使う」、これこそがブラックボックスに依存しないインフラエンジニアの流儀よ!

コウ君

先生、感動しました!「外から入れない」という質問に対して、「VPN」という単語が含まれたマニュアルをAIが数学の力で見つけ出してくれたんですね!文字列の一致じゃなくて「意味」で検索するって、こういう仕組みだったのか……。これで社内マニュアルを全部AIに読み込ませて、最強のヘルプデスクが作れそうです!

リナックス先生

その理解の深さ、素晴らしいわ!あなたはもう、ただAIを使うだけのユーザーではなく、AIの思考回路をシステムに組み込むアーキテクトに成長したのよ。さて、ターミナル作業の効率化と社内情報の検索は完璧ね。次回は、あなたが寝ている間もAIに働いてもらう仕組み。CronとLLMを組み合わせて、毎朝サーバーの健康状態を報告してくれる『自動レポートボット』を構築するわよ!

▼ AI検索エンジンを本格構築するならハイパワーなVPSで ▼

メモリ大容量でAIも快適
「おすすめVPS」

VPSランキングを見る

最先端のAIスキルを活かす
「ITエンジニア転職」

転職エージェントを見る

コメント