AIの最大の弱点「知らないことは嘘をつく」を克服せよ
こんにちは!「LINUX工房」管理人の「リナックス先生」です。
前回の第3回では、PHPとMariaDB(MySQL)を連携させて、AIに過去の会話履歴を記憶させる「セッション管理」を実装しましたね。
これで立派なチャットボットの土台が完成しましたが、実業務にAIを導入しようとすると、すぐに「もう一つの巨大な壁」に直面します。
先生、うちの会社の就業規則についてAIに質問してみたら、全然違う会社のルールをさも本当かのように答えられちゃいました!
あと、「昨日の社内イベントの結果は?」って聞いても「私はAIなので最新の情報は分かりません」って言われます。これじゃ社内FAQシステムとして使えないですよ……。
良い失敗ね、コウ君。それがAIの「ハルシネーション(幻覚)」と呼ばれる現象よ。
AIモデルは「学習した時点までのデータ」しか持っていないし、インターネットに公開されていない「社外秘データ」は当然知らないわ。
知らないことを聞かれた時、AIを賢く回答させるための特効薬が、今回学ぶ「RAG(検索拡張生成)」という技術なのよ!
本記事では、AlmaLinux 9上に構築したLAMP環境を使い、AIモデル本体を再学習(ファインチューニング)させることなく、社内文書や最新データをAIに回答させる「RAG」の基礎的な仕組みと、PHPによる実装手法を解説します。
📚 本連載のカリキュラム(全8回)
目次
1. RAG(Retrieval-Augmented Generation)の仕組み
RAG(ラグ)を日本語に訳すと「検索(Retrieval)によって拡張(Augmented)された生成(Generation)」となります。
なんだか難しそうな名前ですが、やっていることは人間の「カンニング」や「辞書引き」と全く同じです。
RAGの3つのステップ
- 検索(Retrieval): ユーザーからの質問を受け取ったら、まずAIに渡す前に、自社のデータベース(MySQLなど)から質問に関連しそうな文書を検索して抽出します。
- 拡張(Augmented): 抽出した自社文書のテキストを、ユーザーの質問と一緒にプロンプト(指示文)の中に埋め込みます(カンニングペーパーを渡すイメージ)。
- 生成(Generation): 「この参考資料だけを読んで、ユーザーの質問に答えて」とAIに指示を出し、回答を生成させます。
AI自体に会社のルールを覚えさせる(学習させる)のは数千万円のコストと膨大なGPUサーバーが必要になりますが、RAGを使えば、AlmaLinux 9で動くWebサーバー1台とAPIの通信費だけで、自社専用のAIシステムが構築できてしまうのです。
2. 実装ステップ①:知識データベースの設計(MariaDB)
まずは、AIに読みませる「社内文書(ナレッジ)」を保存するテーブルを作成します。
本格的なRAGシステムでは「ベクトルデータベース(PineconeやMilvusなど)」を用いて意味検索を行いますが、今回は初心者向けの第一歩として、既存のLAMP環境であるMariaDB(MySQL)のフルテキスト検索機能(Ngram)を利用した簡易RAGを構築します。
-- MariaDBにログインし、前回作成した ai_chat_db を使用します
USE ai_chat_db;
-- 知識(ドキュメント)を保存するテーブルの作成
CREATE TABLE company_documents (
id INT AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(255) NOT NULL, -- 文書のタイトル
content TEXT NOT NULL, -- 文書の本文(チャンク)
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
-- contentカラムに対してフルテキストインデックスを作成(Ngramパーサー使用)
FULLTEXT INDEX ft_idx_content (content) WITH PARSER ngram
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- テストデータの挿入
INSERT INTO company_documents (title, content) VALUES
('就業規則_第10条', '出社時間は午前9時00分、退社時間は午後6時00分とする。昼休憩は午後12時から1時間とする。'),
('経費精算フロー', '交通費の精算は、毎月月末までに経理部門へ所定のエクセルフォーマットで提出すること。領収書の原本は必ず添付すること。'),
('システム障害対応', 'AlmaLinux 9サーバーで障害が発生した場合は、速やかにシステム管理者のリナックス先生(内線:1024)に連絡すること。');
※MariaDBのNgramフルテキスト検索は、日本語の文章を数文字ずつ区切って高速に検索(MATCH AGAINST句)できる強力な機能です。
3. 実装ステップ②:テキストのチャンク化(分割)の重要性
ここで重要な概念が「チャンク化(Chunking)」です。
例えば、100ページある会社の就業規則のPDFデータを、そのまま全部AIのプロンプトに突っ込むことはできません。APIの「一度に送れる文字数(トークン制限)」に引っかかってエラーになるか、処理できてもAPIの利用料金が数千円単位で飛んでいきます。
そのため、長い文書はあらかじめ「意味のある300〜500文字程度の塊(チャンク)」に分割してデータベース(contentカラム)に保存しておくのがRAGの鉄則です。
今回の company_documents テーブルのテストデータは、すでに短く分割されたチャンクとして登録されていると仮定して進めます。
絵で見てわかるLinuxカーネルの仕組み 【電子書籍】[ 市川 正美 ] 価格:3058円 |
4. 実装ステップ③:PHPで検索とプロンプト結合を行う
それでは、Webサーバー側のPHPを実装します。
ユーザーからの質問を受け取り、DBを検索し、その結果をAIのプロンプトに埋め込んで呼び出す一連のスクリプトを作成します。
<?php
// /var/www/html/rag_chat.php
header('Content-Type: application/json; charset=UTF-8');
require_once 'db_connect.php'; // 第3回で作成したDB接続ファイル
$api_key = "あなたの_API_KEY";
$api_url = "https://api.example.com/v1/generate";
// ユーザーからの質問を受け取る
$inputJSON = file_get_contents('php://input');
$input = json_decode($inputJSON, TRUE);
$user_question = $input['question'] ?? '経費の精算方法を教えてください';
// ==========================================
// 1. 検索(Retrieval):MariaDBから関連文書を探す
// ==========================================
// ユーザーの質問からキーワードを抽出する(本来は形態素解析等を使いますが今回は簡易的に直接検索)
$sql = "SELECT title, content
FROM company_documents
WHERE MATCH(content) AGAINST(? IN BOOLEAN MODE)
LIMIT 2"; // 関連度が高い上位2件のみ取得
$stmt = $pdo->prepare($sql);
// Ngram用にキーワードを調整して検索(例として質問文そのままを入れていますが、実運用では単語分割推奨)
$stmt->execute([$user_question]);
$documents = $stmt->fetchAll();
// 検索結果のテキストを結合する
$reference_text = "";
foreach ($documents as $doc) {
$reference_text .= "【" . $doc['title'] . "】\n" . $doc['content'] . "\n\n";
}
// 関連文書が見つからなかった場合の処理
if (empty($reference_text)) {
$reference_text = "関連する社内データは見つかりませんでした。";
}
// ==========================================
// 2. 拡張(Augmented):システムプロンプトの構築
// ==========================================
// ここがRAGの最も重要なプロンプトエンジニアリングです
$system_prompt = "
あなたは優秀な社内FAQアシスタントです。
以下の【参考資料】の情報のみを使用して、ユーザーの質問に答えてください。
参考資料に書かれていないことについては、「分かりません」と正直に答えてください。自身の知識(嘘)を勝手に推測して答えてはいけません。
【参考資料】
" . $reference_text . "
";
// APIに送信するメッセージ配列の構築
$messages = [
["role" => "system", "content" => $system_prompt],
["role" => "user", "content" => $user_question]
];
// ==========================================
// 3. 生成(Generation):AI APIへリクエスト
// ==========================================
$post_data = json_encode([
"model" => "high-performance-model",
"messages" => $messages,
"temperature" => 0.0 // 勝手な創作を防ぐため温度を0にする
]);
$ch = curl_init($api_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/json',
'Authorization: Bearer ' . $api_key
]);
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response, true);
$ai_reply = $result['choices'][0]['message']['content'] ?? 'APIエラーが発生しました';
// 結果をJSONで出力
echo json_encode([
"question" => $user_question,
"retrieved_data" => $documents, // 何のデータをカンニングしたかも見れるようにしておく
"reply" => $ai_reply
], JSON_UNESCAPED_UNICODE);
?>
5. グラウンディング:AIを「参照データ」に縛り付ける
上記のPHPコードのハイライトは、システムプロンプト内で指示した「参考資料の情報のみを使用してください」「書かれていないことは『分かりません』と答えてください」という部分です。
これをAI業界の専門用語で「グラウンディング(Grounding:根拠付け)」と呼びます。
パラメーターの temperature を 0.0 に設定することと合わせて、AIの暴走(ハルシネーション)を物理的に封じ込めるサーバーサイド技術の要です。
なるほど!AIに直接答えさせるんじゃなくて、「僕がデータベースから探してきたこの資料を読んで、分かりやすく要約してよ」ってお願いする仕組みなんですね。
これなら、会社の機密情報を学習されちゃう心配もないし、回答の根拠もはっきりします!
その通り!コウ君、システムの本質を見抜いたわね。
RAGの心臓部は「AIの頭の良さ」ではなく、実は「いかにユーザーの質問に対して、DBから的確なデータを検索(Retrieval)できるか」という検索アルゴリズムの精度にかかっているの。
だからこそ、MySQL等のDBチューニングが得意な私たちインフラ・サーバーサイドエンジニアのスキルがAI開発でも大活躍するのよ。
総まとめ:RAGは「検索」と「要約」の合わせ技
第4回の解説、お疲れ様でした。
今回は、生成AIの実業務活用で最もニーズの高い「RAG」の基礎を、AlmaLinux 9上のMariaDBとPHPを使って実装しました。高額なAI専用データベースを用意しなくても、既存のWebシステムの技術の延長線上で十分にAIを使いこなせることが理解できたと思います。
次回、【第5回】画像生成AI APIの統合とサーバー内ストレージ管理 では、テキストを離れ、画像を生成してLinuxサーバーのディレクトリにセキュアに保存・管理する手法に挑戦します。Webアプリケーションの表現の幅が一気に広がりますよ!
お楽しみに!LINUX工房の「リナックス先生」でした。
▼ 自社AI開発のためのサーバー環境を構築 ▼
RAGシステムのデータベース運用に!
「超高速SSD搭載VPS」
AI×DB連携のスキルを活かそう
「ITエンジニア専門転職」

コメント