- วัตถุประสงค์
- 1. Vector Database คืออะไร?
- 2. สถาปัตยกรรม
- 3. สิ่งที่ต้องเตรียม
- 4. เปิด Qdrant ด้วย Docker Compose
- 5. ติดตั้ง Python Libraries
- 6. เขียนโปรแกรมสร้าง Embedding, จัดเก็บ และค้นหา
- 7. ทดลองปรับคำถาม
- 8. การค้นหาแบบ Metadata Filtering
- 9. ต่อยอดเป็น RAG
- 10. แบบฝึกหัด
- 11. ข้อควรระวังสำหรับ Production
- 12. สรุป
- เอกสารอ้างอิง
#วัตถุประสงค์
เวิร์กช็อปนี้สอนการจัดเก็บและค้นหาข้อมูลด้วยเวกเตอร์ (embeddings) โดยใช้ Qdrant เป็น Vector Database, Sentence Transformers สร้าง embedding และ Python เรียก API เหมาะสำหรับต่อยอดระบบ Semantic Search และ Retrieval-Augmented Generation (RAG)
#1. Vector Database คืออะไร?
Vector Database จัดเก็บเวกเตอร์ตัวเลขที่แทนความหมายของข้อความ รูปภาพ หรือข้อมูลอื่น ๆ และค้นหารายการที่มีความใกล้เคียงกันทางความหมาย (vector similarity search) ต่างจาก keyword search ที่อาศัยคำตรงกันเป็นหลัก
องค์ประกอบหลัก:
- Embedding model: แปลงข้อความเป็นเวกเตอร์ที่มีจำนวนมิติคงที่
- Collection: กลุ่มข้อมูลเวกเตอร์ในฐานข้อมูล
- Point: ID + vector + payload (metadata)
- Similarity metric: เช่น Cosine similarity
- ANN index: ช่วยค้นหาเพื่อนบ้านใกล้เคียงอย่างรวดเร็ว เช่น HNSW
#2. สถาปัตยกรรม
flowchart LR A[เอกสารภาษาไทย] --> B[Embedding Model] B --> C[(Qdrant Vector DB)] U[คำถามผู้ใช้] --> E[Embedding Model] E --> C C --> R[Top-k Similar Documents] R --> O[ผลการค้นหา / RAG Context]
#3. สิ่งที่ต้องเตรียม
- Docker และ Docker Compose
- Python 3.10 ขึ้นไป
- พื้นที่ว่างสำหรับดาวน์โหลด embedding model ครั้งแรก
โครงสร้างโปรเจกต์:
vector-db-workshop/
├── compose.yaml
├── requirements.txt
└── app.py
#4. เปิด Qdrant ด้วย Docker Compose
สร้างไฟล์ compose.yaml:
services:
qdrant:
image: qdrant/qdrant:v1.15.5
ports:
- "127.0.0.1:6333:6333"
volumes:
- qdrant_data:/qdrant/storage
volumes:
qdrant_data:
หมายเหตุ: เวอร์ชัน image เป็นตัวอย่างที่ระบุชัดเจนเพื่อให้ทำซ้ำได้ ควรตรวจสอบรุ่นที่ยังได้รับการสนับสนุนก่อนใช้งานจริง และไม่ควรเปิด Qdrant API สู่สาธารณะโดยไม่มีการควบคุมการเข้าถึง
docker compose up -d
curl http://localhost:6333/healthz
Qdrant Dashboard (เฉพาะเครื่อง): http://localhost:6333/dashboard
#5. ติดตั้ง Python Libraries
requirements.txt:
qdrant-client>=1.15,<2
sentence-transformers>=5,<6
python -m venv .venv
# macOS/Linux
source .venv/bin/activate
# Windows PowerShell: .venv\Scripts\Activate.ps1
pip install -r requirements.txt
#6. เขียนโปรแกรมสร้าง Embedding, จัดเก็บ และค้นหา
สร้างไฟล์ app.py:
from qdrant_client import QdrantClient, models
from sentence_transformers import SentenceTransformer
COLLECTION = "thai_software_docs"
MODEL_NAME = "sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2"
client = QdrantClient(url="http://localhost:6333")
model = SentenceTransformer(MODEL_NAME)
documents = [
"Docker ใช้สร้างและรันแอปพลิเคชันภายในคอนเทนเนอร์",
"Kubernetes ช่วยจัดการการทำงานและการขยายระบบคอนเทนเนอร์",
"GitHub Actions ใช้สร้าง CI/CD pipeline เพื่อทดสอบและ deploy",
"Vector Database ใช้จัดเก็บ embeddings และค้นหาข้อมูลที่มีความหมายใกล้เคียง",
"Retrieval-Augmented Generation ใช้ข้อมูลที่ค้นคืนมาเป็นบริบทให้ LLM",
]
vectors = model.encode(documents, normalize_embeddings=True).tolist()
dim = len(vectors[0])
if not client.collection_exists(COLLECTION):
client.create_collection(
collection_name=COLLECTION,
vectors_config=models.VectorParams(size=dim, distance=models.Distance.COSINE),
)
client.upsert(
collection_name=COLLECTION,
points=[
models.PointStruct(id=i + 1, vector=vector, payload={"text": text, "topic": "software"})
for i, (text, vector) in enumerate(zip(documents, vectors))
],
wait=True,
)
question = "ฐานข้อมูลที่ใช้ค้นหาข้อความตามความหมายคืออะไร"
query_vector = model.encode(question, normalize_embeddings=True).tolist()
results = client.query_points(
collection_name=COLLECTION,
query=query_vector,
limit=3,
with_payload=True,
).points
print(f"คำถาม: {question}")
for rank, point in enumerate(results, start=1):
print(f"{rank}. score={point.score:.4f} | {point.payload['text']}")
รัน:
python app.py
ผลที่คาดหวัง: โปรแกรมแสดงเอกสารที่เกี่ยวข้อง 3 รายการ พร้อม similarity score โดยข้อความเกี่ยวกับ Vector Database ควรอยู่ในกลุ่มผลลัพธ์อันดับต้น ๆ (อันดับจริงอาจแตกต่างตามโมเดลและข้อมูล)
#7. ทดลองปรับคำถาม
เปลี่ยนตัวแปร question เป็น:
question = "เครื่องมือสำหรับจัดการ container จำนวนมาก"
ทดลองอีกครั้ง:
question = "ทำระบบอัตโนมัติเพื่อทดสอบและส่งขึ้น production"
เปรียบเทียบอันดับและคะแนนของผลลัพธ์ อธิบายว่าทำไมคำที่ไม่ตรงกันจึงอาจค้นเจอเอกสารที่เกี่ยวข้องได้
#8. การค้นหาแบบ Metadata Filtering
เพิ่มเงื่อนไข filter ให้คำสั่ง query_points:
results = client.query_points(
collection_name=COLLECTION,
query=query_vector,
query_filter=models.Filter(
must=[models.FieldCondition(key="topic", match=models.MatchValue(value="software"))]
),
limit=3,
with_payload=True,
).points
ในระบบจริงสามารถใช้ payload เช่น department, document_type, tenant_id และ updated_at เพื่อกรองข้อมูล โดยต้องใช้ authorization ในระดับแอปพลิเคชันร่วมด้วย ไม่ถือว่า filter เพียงอย่างเดียวเป็นระบบรักษาความปลอดภัย
#9. ต่อยอดเป็น RAG
ลำดับการทำงาน:
- แยกเอกสารเป็น chunks พร้อม metadata และ source
- แปลงแต่ละ chunk เป็น embedding
- บันทึกลง Qdrant
- แปลงคำถามเป็น embedding และค้น top-k chunks
- ส่ง chunks พร้อมคำถามไปยัง LLM เพื่อสร้างคำตอบอ้างอิงข้อมูล
- ตรวจสอบความถูกต้อง การอ้างอิง และการปฏิเสธเมื่อข้อมูลไม่เพียงพอ
Vector Database เป็นส่วน Retrieval ไม่ใช่ตัว LLM และคะแนน similarity ไม่ใช่ความน่าจะเป็นว่าคำตอบถูกต้อง
#10. แบบฝึกหัด
- เพิ่มข้อมูลเป็น 20 เอกสารและแบ่งหมวดหมู่
backend,devops,ai - เพิ่ม filter ค้นหาเฉพาะหมวด
devops - เปรียบเทียบ
top-kเท่ากับ 1, 3 และ 5 - สร้างชุดคำถาม 10 ข้อพร้อมเอกสารที่เกี่ยวข้อง (ground truth)
- คำนวณ Recall@k และ MRR เพื่อประเมินคุณภาพ retrieval
#11. ข้อควรระวังสำหรับ Production
- กำหนด API key, TLS, network isolation และ backup
- เลือก embedding model ให้เหมาะกับภาษาและโดเมน และใช้โมเดลเดียวกันสำหรับเอกสารและคำถาม
- กำหนดกลยุทธ์ chunking, deduplication, versioning และ re-index เมื่อเปลี่ยนโมเดล
- ตรวจสอบ latency, throughput, recall, disk/RAM และความสามารถในการขยายระบบ
- พิจารณา hybrid search (dense + sparse) และ reranking สำหรับข้อมูลจริง
- ประเมินสิทธิ์เข้าถึงเอกสารก่อนส่งบริบทให้ LLM
#12. สรุป
Workshop นี้แสดงวงจรพื้นฐานของ Vector Database ตั้งแต่สร้าง embedding, บันทึกเวกเตอร์พร้อม metadata, ค้นหาแบบ semantic similarity ไปจนถึงการต่อยอดเป็นระบบ RAG โดย Qdrant ทำหน้าที่จัดเก็บและค้นคืนเวกเตอร์ ส่วน Sentence Transformers ทำหน้าที่แปลงข้อความเป็น embeddings
#เอกสารอ้างอิง
- Qdrant Documentation: https://qdrant.tech/documentation/
- Qdrant Python Client: https://python-client.qdrant.tech/
- Sentence Transformers: https://sbert.net/