สร้าง Search ของตัวเองด้วย Python CLI + Vector Database
สวัสดีครับเพื่อนๆ โปรแกรมเมอร์ ทุกคน
วันนี้ผมจะมาคุยเรื่องสนุกๆ ที่จะช่วยให้เราค้นหาข้อมูลจากกองไฟล์ text จำนวนมาก ๆ ได้อย่างฉลาดขึ้นกันนะครับ นั่นก็คือการสร้างระบบ Search ของตัวเองง่ายๆ ด้วย Python CLI พร้อมใช้ Vector Database มาช่วยจัดการข้อมูลนี่แหละครับ มันไม่ยากอย่างที่คิด เลยนะ ลองมาดูกัน
เตรียมข้อมูลจากไฟล์ของเราก่อน
อันดับแรกสุด เลยนะครับ เราต้องมีไฟล์ text ที่อยากจะค้นหาก่อน เช่น ไฟล์เอกสาร ไฟล์บันทึก หรืออะไรก็ได้นะครับ สมมติว่าผมมีไฟล์ doc1.txt กับ doc2.txt ที่มีเนื้อหาประมาณนี้นะ
# doc1.txt
# บทความนี้พูดถึงการเขียนโปรแกรม Python สำหรับจัดการไฟล์\
# และใช้ Context Manager เพื่อความปลอดภัย
# doc2.txt
# การค้นหาข้อมูลด้วย AI และ Vector Database กำลังเป็นที่นิยมมาก\
# มันช่วยให้เราเจอสิ่งที่ต้องการได้รวดเร็ว
จากนั้น นะครับ เราก็เขียนโค้ด Python CLI ง่ายๆ เพื่ออ่านไฟล์พวกนี้เข้ามา แบบนี้ครับ
import os
def read_text_files(directory):
texts = []
filenames = []
for filename in os.listdir(directory):
if filename.endswith(".txt"):
filepath = os.path.join(directory, filename)
with open(filepath, "r", encoding="utf-8") as f:
texts.append(f.read())
filenames.append(filename)
return texts, filenames
if __name__ == "__main__":
# สมมติว่าไฟล์ของเราอยู่ในโฟลเดอร์ 'data' นะครับ
data_directory = "data"
if not os.path.exists(data_directory):
os.makedirs(data_directory)
# สร้างไฟล์ตัวอย่าง
with open(os.path.join(data_directory, "doc1.txt"), "w", encoding="utf-8") as f:
f.write("บทความนี้พูดถึงการเขียนโปรแกรม Python สำหรับจัดการไฟล์และใช้ Context Manager เพื่อความปลอดภัย")
with open(os.path.join(data_directory, "doc2.txt"), "w", encoding="utf-8") as f:
f.write("การค้นหาข้อมูลด้วย AI และ Vector Database กำลังเป็นที่นิยมมาก มันช่วยให้เราเจอสิ่งที่ต้องการได้รวดเร็ว")
all_texts, all_filenames = read_text_files(data_directory)
print("อ่านข้อมูลได้แล้ว:", len(all_texts), "ไฟล์")
# Output: อ่านข้อมูลได้แล้ว: 2 ไฟล์
แปลงข้อความเป็น Vector (Embedding)
พอเรามีข้อความแล้วนะครับ ขั้นตอนต่อไปคือการแปลงข้อความพวกนี้ให้เป็นตัวเลขที่คอมพิวเตอร์เข้าใจ ซึ่งเราเรียกมันว่า "Embedding" หรือ "Vector" นั่นเองครับ การทำแบบนี้จะช่วยให้คอมรู้ว่าข้อความไหนมีความหมายคล้ายกันนะ ในตัวอย่างนี้ ผมจะใช้ไลบรารีง่ายๆ อย่างsentence-transformers มาช่วยนะครับ ถ้าไม่มีก็ pip install sentence-transformers ได้เลย
from sentence_transformers import SentenceTransformer
model = SentenceTransformer('all-MiniLM-L6-v2') # โหลดโมเดลสำหรับสร้าง Embedding
def get_embeddings(texts):
embeddings = model.encode(texts)
return embeddings
if __name__ == "__main__":
# ... โค้ดอ่านไฟล์ด้านบน ...
all_texts, all_filenames = read_text_files(data_directory)
text_embeddings = get_embeddings(all_texts)
print("แปลงข้อความเป็น Embedding ได้แล้ว:", text_embeddings.shape)
# Output: แปลงข้อความเป็น Embedding ได้แล้ว: (2, 384) (ถ้ามี 2 ไฟล์และโมเดลสร้าง 384 มิติ)
เก็บ Embedding ใน Vector Database (แบบง่ายๆ)
ทีนี้ เรามี Vector ของข้อความแต่ละอันแล้วนะครับ เราก็จะเอาไปเก็บไว้ในที่ที่เหมาะสม ซึ่งก็คือ Vector Database นั่นเองครับ ในโลกจริงเราอาจจะใช้ Faiss, Pinecone, Weaviate อะไรพวกนี้ แต่วันนี้เราจะทำแบบง่ายๆ ใน Memory ไปก่อน เพื่อให้เห็นภาพนะครับ แบบนี้นะ
from sklearn.metrics.pairwise import cosine_similarity # ต้องมี scikit-learn: pip install scikit-learn
class SimpleVectorDB:
def __init__(self):
self.vectors = []
self.metadatas = [] # เก็บชื่อไฟล์ หรือข้อมูลอื่นๆ ที่เกี่ยวข้อง
def add_vector(self, vector, metadata):
self.vectors.append(vector)
self.metadatas.append(metadata)
def search(self, query_vector, top_k=1):
# ค้นหา vector ที่ใกล้ที่สุด โดยใช้ Cosine Similarity
similarities = cosine_similarity([query_vector], self.vectors)[0]
# เรียงลำดับตามความคล้ายมากไปน้อย
sorted_indices = similarities.argsort()[::-1]
results = []
for i in sorted_indices[:top_k]:
results.append({
"score": similarities[i],
"metadata": self.metadatas[i],
# "vector": self.vectors[i] # อาจจะแสดง vector ด้วยก็ได้
})
return results
if __name__ == "__main__":
# ... โค้ดอ่านไฟล์และสร้าง Embedding ด้านบน ...
all_texts, all_filenames = read_text_files(data_directory)
text_embeddings = get_embeddings(all_texts)
my_vector_db = SimpleVectorDB()
for i, emb in enumerate(text_embeddings):
my_vector_db.add_vector(emb, {"filename": all_filenames[i], "text_sample": all_texts[i][:50] + "..."})
print("เก็บ Embedding เข้า DB แล้ว")
ค้นหาข้อมูลด้วยคำถามของเรา
มาถึงขั้นตอนสุดท้าย แล้วนะครับ พอเรามี Vector Database ที่พร้อมใช้งาน เราก็สามารถเอาคำถามที่เราอยากจะค้นหาแปลงเป็น Vector เหมือนกัน แล้วเอาไปเทียบกับ Vector ที่เราเก็บไว้ใน DB เพื่อหาว่าอันไหนมีความหมายใกล้เคียงกับคำถามของเรามากที่สุดครับ
if __name__ == "__main__":
# ... โค้ดสร้าง DB ด้านบน ...
query_text = "การเขียนโปรแกรมที่ปลอดภัย"
query_embedding = get_embeddings([query_text])[0] # แปลงคำถามเป็น Vector
search_results = my_vector_db.search(query_embedding, top_k=2)
print("\
ผลลัพธ์การค้นหาสำหรับคำถาม:", query_text)
for result in search_results:
print(f"- ไฟล์: {result['metadata']['filename']}, คะแนนความคล้าย: {result['score']:.4f}")
print(f" เนื้อหาบางส่วน: {result['metadata']['text_sample']}")
# ตัวอย่างผลลัพธ์ (อาจแตกต่างกันขึ้นอยู่กับโมเดลและข้อมูล)
# ผลลัพธ์การค้นหาสำหรับคำถาม: การเขียนโปรแกรมที่ปลอดภัย
# - ไฟล์: doc1.txt, คะแนนความคล้าย: 0.7890
# เนื้อหาบางส่วน: บทความนี้พูดถึงการเขียนโปรแกรม Python สำหรับจัดกา...
# - ไฟล์: doc2.txt, คะแนนความคล้าย: 0.3540
# เนื้อหาบางส่วน: การค้นหาข้อมูลด้วย AI และ Vector Database กำลังเป...
เห็นไหมครับ ไม่ยากเลยใช่ไหม แค่นี้เราก็ได้ระบบค้นหาข้อมูลแบบ Semantic Search ง่ายๆ ด้วย Python CLI แล้วนะครับเพื่อนๆ ลองเอาไปปรับใช้กับโปรเจกต์ ของตัวเองได้เลยนะ ผมว่ามันมีประโยชน์มากๆ เลยแหละครับ ลองโหลดโค้ดไปเล่นดูนะครับ ถ้าติดตรงไหน ก็ถามมาได้เลยนะ