สร้างระบบถาม-ตอบอัจฉริยะด้วย Gemini API และ Embeddings จากฐานข้อมูลของคุณ
บทความนี้จะนำคุณไปสู่ขั้นตอนการสร้างระบบถาม-ตอบอัจฉริยะ โดยใช้ประโยชน์จากพลังของ Gemini API ในการทำความเข้าใจภาษา และ Embeddings ในการค้นหาข้อมูลที่เกี่ยวข้องจากฐานข้อมูลของคุณ เพื่อให้ได้คำตอบที่อิงกับข้อมูลของคุณเอง
ขั้นตอนการทำงานหลัก
- สร้าง Embeddings จากข้อมูลในฐานข้อมูล แปลงเนื้อหาของบทความหรือเอกสารในฐานข้อมูลของคุณให้เป็น Vector Embeddings
- จัดเก็บ Embeddings บันทึก Embeddings เหล่านี้กลับเข้าไปในฐานข้อมูล (หรือ Vector Database)
- ค้นหาบทความที่เกี่ยวข้อง เมื่อผู้ใช้ถามคำถาม ให้สร้าง Embedding ของคำถามนั้น และค้นหา Embeddings ของบทความที่ใกล้เคียงที่สุดในฐานข้อมูล
- ใช้ Gemini API สร้างคำตอบ นำบทความที่เกี่ยวข้องมาเป็น Context พร้อมกับคำถามของผู้ใช้ แล้วส่งให้ Gemini API สร้างคำตอบที่อิงกับข้อมูลเหล่านั้น
ขั้นตอนที่ 1 สร้าง Embeddings
ขั้นตอนนี้เราจะดึงข้อมูลจากฐานข้อมูล สร้าง Embeddings โดยใช้ Gemini Embedding API และอัปเดต Embeddings กลับเข้าไปในฐานข้อมูล
โค้ดตัวอย่าง (PHP)
<?php
// --- ฟังก์ชันสำหรับสร้าง Embedding ---
function getEmbedding($text) {
$api_key = 'YOUR_GEMINI_API_KEY';
$url = 'https://generativelanguage.googleapis.com/v1beta/models/embedding-001:embedContent?key=' . $api_key;
$data = [
'model' => 'embedding-001',
'content' => ['parts' => [['text' => $text]]]
];
$payload = json_encode($data);
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response, true);
return $result['embedding']['values'] ?? null;
}
// --- เชื่อมต่อฐานข้อมูล MySQL ---
$host = 'localhost';
$dbname = 'your_database';
$user = 'your_username';
$password = 'your_password';
try {
$pdo = new PDO("mysql:host=$host;dbname=$dbname;charset=utf8", $user, $password);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
die("ไม่สามารถเชื่อมต่อฐานข้อมูลได้: " . $e->getMessage());
}
// --- ดึงข้อมูลและสร้าง Embeddings ---
$sql_select = "SELECT id, detail FROM your_table WHERE embedding IS NULL"; // ดึงเฉพาะรายการที่ยังไม่มี Embedding
$stmt_select = $pdo->query($sql_select);
while ($row = $stmt_select->fetch(PDO::FETCH_ASSOC)) {
$id = $row['id'];
$detail = $row['detail'];
$embedding = getEmbedding($detail);
if ($embedding) {
$embedding_json = json_encode($embedding);
$sql_update = "UPDATE your_table SET embedding = :embedding WHERE id = :id";
$stmt_update = $pdo->prepare($sql_update);
$stmt_update->bindParam(':embedding', $embedding_json);
$stmt_update->bindParam(':id', $id, PDO::PARAM_INT);
if ($stmt_update->execute()) {
echo "อัปเดต Embedding สำหรับ ID: " . $id . " สำเร็จ\n";
} else {
echo "ไม่สามารถอัปเดต Embedding สำหรับ ID: " . $id . "\n";
print_r($stmt_update->errorInfo());
}
sleep(1); // ป้องกัน Rate Limiting
} else {
echo "ไม่สามารถสร้าง Embedding สำหรับ ID: " . $id . "\n";
}
}
echo "กระบวนการสร้างและจัดเก็บ Embeddings เสร็จสิ้น\n";
คำแนะนำ
- ตรวจสอบให้แน่ใจว่าตารางของคุณ (
your_table
) มีคอลัมน์สำหรับจัดเก็บ Embedding (เช่นembedding
เป็น JSON หรือVECTOR
ใน MySQL 9.0+) - แทนที่
'YOUR_GEMINI_API_KEY'
, ข้อมูลการเชื่อมต่อฐานข้อมูล, และชื่อตารางให้ถูกต้อง
ขั้นตอนที่ 2 ค้นหาบทความที่เกี่ยวข้อง
เมื่อผู้ใช้ถามคำถาม เราจะสร้าง Embedding ของคำถามนั้นและเปรียบเทียบกับ Embeddings ที่จัดเก็บไว้เพื่อหาบทความที่เกี่ยวข้อง
โค้ดตัวอย่าง (PHP)
<?php
// --- ฟังก์ชัน getEmbedding() จากขั้นตอนที่ 1 ---
// --- ฟังก์ชันคำนวณ Cosine Similarity ---
function cosineSimilarity($vecA, $vecB) {
$dotProduct = 0;
$normA = 0;
$normB = 0;
for ($i = 0; $i < count($vecA); $i++) {
$dotProduct += $vecA[$i] * $vecB[$i];
$normA += pow($vecA[$i], 2);
$normB += pow($vecB[$i], 2);
}
if ($normA == 0 || $normB == 0) {
return 0;
}
return $dotProduct / (sqrt($normA) * sqrt($normB));
}
// --- เชื่อมต่อฐานข้อมูล MySQL (เหมือนขั้นตอนที่ 1) ---
$host = 'localhost';
$dbname = 'your_database';
$user = 'your_username';
$password = 'your_password';
try {
$pdo = new PDO("mysql:host=$host;dbname=$dbname;charset=utf8", $user, $password);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
die("ไม่สามารถเชื่อมต่อฐานข้อมูลได้: " . $e->getMessage());
}
// --- ฟังก์ชันค้นหาบทความที่เกี่ยวข้อง ---
function findRelatedDocuments($question, $pdo, $tableName = 'your_table', $limit = 3) {
$questionEmbedding = getEmbedding($question);
if (!$questionEmbedding) {
return "ไม่สามารถสร้าง Embedding สำหรับคำถามได้";
}
$sql_select = "SELECT id, topic, detail, embedding FROM $tableName WHERE embedding IS NOT NULL";
$stmt_select = $pdo->query($sql_select);
$results = [];
while ($row = $stmt_select->fetch(PDO::FETCH_ASSOC)) {
$documentEmbedding = json_decode($row['embedding'], true);
if ($documentEmbedding) {
$similarity = cosineSimilarity($questionEmbedding, $documentEmbedding);
$results[] = [
'id' => $row['id'],
'topic' => $row['topic'],
'detail' => $row['detail'],
'similarity' => $similarity
];
}
}
usort($results, function($a, $b) {
return $b['similarity'] <=> $a['similarity'];
});
return array_slice($results, 0, $limit);
}
// --- ตัวอย่างการใช้งาน ---
$question = "วิธีติดตั้ง Widget บนเว็บไซต์";
$relatedDocuments = findRelatedDocuments($question, $pdo);
echo "คำถาม: " . $question . "\n\n";
echo "บทความที่เกี่ยวข้อง:\n";
if (is_array($relatedDocuments)) {
foreach ($relatedDocuments as $doc) {
echo "ID: " . $doc['id'] . ", หัวข้อ: " . $doc['topic'] . ", ความคล้ายคลึง: " . $doc['similarity'] . "\n";
echo "เนื้อหาบางส่วน: " . mb_substr($doc['detail'], 0, 200) . "...\n\n";
}
} else {
echo $relatedDocuments . "\n";
}
ขั้นตอนที่ 3 ใช้ Gemini API สร้างคำตอบ
นำบทความที่เกี่ยวข้องจากขั้นตอนที่ 2 มาใช้เป็น Context ให้กับ Gemini API เพื่อสร้างคำตอบที่อิงกับข้อมูลของคุณ
โค้ดตัวอย่าง (PHP)
<?php
// --- ฟังก์ชัน getEmbedding(), cosineSimilarity(), findRelatedDocuments() จากขั้นตอนก่อนหน้า ---
// --- ฟังก์ชันสำหรับส่งคำถามและบทความที่เกี่ยวข้องไปยัง Gemini Pro ---
function askGeminiPro($question, $relatedDocuments) {
$gemini_api_key = 'YOUR_GEMINI_API_KEY';
$url = 'https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent?key=' . $gemini_api_key;
$context = "อ้างอิงจากข้อมูลต่อไปนี้เพื่อตอบคำถาม: ";
foreach ($relatedDocuments as $doc) {
$context .= "\n\nหัวข้อ: " . $doc['topic'] . "\nเนื้อหา: " . mb_substr($doc['detail'], 0, 500) . "..."; // ใช้เนื้อหาบางส่วน
}
$prompt = $context . "\n\nคำถาม: " . $question . "\n\nโปรดให้คำตอบที่กระชับและตรงประเด็น";
$data = [
'contents' => [
[
'parts' => [['text' => $prompt]]
]
]
];
$payload = json_encode($data);
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response, true);
return $result['candidates'][0]['content']['parts'][0]['text'] ?? "ไม่สามารถสร้างคำตอบได้";
}
// --- ขั้นตอนการทำงานหลัก ---
$userQuestion = "วิธีติดตั้ง Widget บนเว็บไซต์ทำอย่างไร";
$relevantDocs = findRelatedDocuments($userQuestion, $pdo);
echo "คำถาม: " . $userQuestion . "\n\n";
echo "บทความที่เกี่ยวข้อง:\n";
if (is_array($relevantDocs)) {
foreach ($relevantDocs as $doc) {
echo "ID: " . $doc['id'] . ", หัวข้อ: " . $doc['topic'] . ", ความคล้ายคลึง: " . $doc['similarity'] . "\n";
echo "เนื้อหาบางส่วน: " . mb_substr($doc['detail'], 0, 200) . "...\n\n";
}
$answer = askGeminiPro($userQuestion, $relevantDocs);
echo "\nคำตอบจาก AI:\n" . $answer . "\n";
} else {
echo $relevantDocs . "\n";
}
การนำไปใช้งาน
- รัน Script แรกเพื่อสร้างและจัดเก็บ Embeddings ในฐานข้อมูลของคุณ (ทำเพียงครั้งแรก หรือเมื่อมีการอัปเดตข้อมูล)
- เมื่อผู้ใช้ถามคำถาม ให้รัน Script ที่สอง (ส่วนของการค้นหาและตอบคำถาม) เพื่อดึงบทความที่เกี่ยวข้องและใช้ Gemini API สร้างคำตอบ
หากต้องการนำไปใช้งานจริง ควรมีอะไรต้องเพิ่มเติม หรือต้องทำอะไร ใช้เครื่องมืออะไรบ้าง
การนำระบบถาม-ตอบอัจฉริยะนี้ไปใช้งานจริงในสภาพแวดล้อม Production จำเป็นต้องมีการพัฒนาและพิจารณาในหลายด้านเพิ่มเติม เพื่อให้ระบบมีความเสถียร, ประสิทธิภาพสูง, และใช้งานได้ง่าย
สิ่งที่ต้องเพิ่มเติม/พัฒนา
-
การจัดการฐานข้อมูล Embeddings ที่มีประสิทธิภาพ
- Vector Database พิจารณาใช้ Vector Database โดยเฉพาะ เช่น Pinecone, Weaviate, ChromaDB เพื่อการจัดเก็บและค้นหา Embeddings ที่รวดเร็วและมีประสิทธิภาพสูงกว่าการใช้ MySQL เพียงอย่างเดียว (โดยเฉพาะกับข้อมูลขนาดใหญ่)
- Indexing หากยังคงใช้ MySQL ควรมีการพิจารณาการสร้าง Index ที่เหมาะสมเพื่อเพิ่มประสิทธิภาพในการค้นหา
-
การปรับปรุงประสิทธิภาพการค้นหา
- Algorithm การค้นหา Nearest Neighbors ใน Vector Database จะมี Algorithm ที่ optimized สำหรับการค้นหา Nearest Neighbors (ANN) ซึ่งเร็วกว่าการวนลูปคำนวณในตัวอย่าง
- การกรอง (Filtering) หากข้อมูลมี Metadata (เช่น หมวดหมู่, วันที่) ควรมีกลไกในการกรองผลการค้นหา Embeddings
-
การจัดการ Context และ Prompt ที่ซับซ้อน
- การเลือกส่วนของเนื้อหาที่เกี่ยวข้องที่สุด หากบทความที่เกี่ยวข้องมีขนาดยาว อาจต้องมีกลไกในการเลือกเฉพาะส่วนที่เกี่ยวข้องกับคำถามมากที่สุดเพื่อใส่ใน Context ของ Prompt
- การจัดการจำนวน Token ระมัดระวังเรื่องจำนวน Token สูงสุดที่ LLM รองรับ อาจต้องมีการสรุปเนื้อหาก่อนส่ง หรือใช้เทคนิคอื่นๆ ในการจัดการ Context
- การออกแบบ Prompt ที่มีประสิทธิภาพ ปรับปรุง Prompt ให้ LLM เข้าใจบริบทและให้คำตอบในรูปแบบที่ต้องการ
-
ระบบ User Interface (UI) และ User Experience (UX)
- สร้าง UI ที่ใช้งานง่ายสำหรับผู้ใช้ในการป้อนคำถามและดูคำตอบ
- พิจารณาการแสดงแหล่งที่มาของข้อมูลที่ใช้ในการตอบคำถาม
-
การจัดการ Error และ Logging
- มีระบบจัดการ Error ที่ดี เพื่อให้ระบบทำงานได้อย่างราบรื่นแม้เกิดข้อผิดพลาด
- มีระบบ Logging เพื่อติดตามการทำงานของระบบและวิเคราะห์ปัญหา
-
ความปลอดภัย
- ตรวจสอบและป้องกันการโจมตีต่างๆ ที่อาจเกิดขึ้นผ่าน Input ของผู้ใช้
เครื่องมือและเทคโนโลยีที่ควรพิจารณา
- Vector Databases Pinecone, Weaviate, ChromaDB, Milvus
- Framework สำหรับ LLM LangChain, LlamaIndex (ช่วยในการจัดการ Data Loading, Indexing, Retrieval, และ Generation)
- Web Framework (สำหรับ UI) เช่น Flask (Python), Laravel (PHP), React, Vue.js
สรุป
ตัวอย่างที่เราได้ทำไปเป็นเพียงจุดเริ่มต้นที่ดีในการทำความเข้าใจหลักการทำงานของการใช้ AI ตอบคำถามจากข้อมูลของเรา หากต้องการนำไปใช้งานจริง จะต้องมีการพัฒนาในหลายส่วนเพิ่มเติม โดยเฉพาะในเรื่องของประสิทธิภาพการจัดการข้อมูล, ความแม่นยำในการค้นหา, และประสบการณ์ผู้ใช้งาน