สร้าง 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 แล้วนะครับเพื่อนๆ ลองเอาไปปรับใช้กับโปรเจกต์ ของตัวเองได้เลยนะ ผมว่ามันมีประโยชน์มากๆ เลยแหละครับ ลองโหลดโค้ดไปเล่นดูนะครับ ถ้าติดตรงไหน ก็ถามมาได้เลยนะ

แหล่งที่มา

Read more

Google ส่ง Gemini ลง Mac แบบ Native พร้อมตัวช่วย AI สุดล้ำ ยกระดับงานเดสก์ท็อป

Google ส่ง Gemini ลง Mac แบบ Native พร้อมตัวช่วย AI สุดล้ำ ยกระดับงานเดสก์ท็อป

Google เปิดตัว Gemini เวอร์ชัน Native บน Mac พร้อมฟีเจอร์ AI ล้ำสมัย ช่วยเพิ่มประสิทธิภาพการทำงาน ปลดล็อกความคิดสร้างสรรค์ และเชื่อมต่อข้อมูลส่วนตัวได้อย่างชาญฉลาด

By ทีมงาน devdog
เจาะลึก UEFA Champions League: สุดยอดความตื่นเต้นที่แฟนบอลทั่วโลกรอคอย

เจาะลึก UEFA Champions League: สุดยอดความตื่นเต้นที่แฟนบอลทั่วโลกรอคอย

เจาะลึก UEFA Champions League การแข่งขันระดับโลกที่แฟนบอลรอคอย พร้อมติดตามข่าวสารรอบโลกและการถ่ายทอดสดสุดพิเศษ ไม่พลาดทุกความมันส์!

By ทีมงาน devdog
Google อัปเกรด Chrome ครั้งใหญ่ เพิ่มฟีเจอร์ "Skills" ให้ AI จำคำสั่งโปรดของคุณ

Google อัปเกรด Chrome ครั้งใหญ่ เพิ่มฟีเจอร์ "Skills" ให้ AI จำคำสั่งโปรดของคุณ

อัปเกรด Chrome ด้วยฟีเจอร์ Skills ใหม่ ให้ AI จดจำและเรียกใช้คำสั่งโปรดของคุณได้ทันที ไม่ต้องพิมพ์ซ้ำ พร้อมเชื่อมต่อ Gemini ทั่วระบบ

By ทีมงาน devdog
CARTIER Santos-Dumont โฉมใหม่: เมื่อออบซิเดียนผสานตำนานนักบิน สู่ความงามเหนือกาลเวลา

CARTIER Santos-Dumont โฉมใหม่: เมื่อออบซิเดียนผสานตำนานนักบิน สู่ความงามเหนือกาลเวลา

คาร์เทียร์เปิดตัว Santos-Dumont หน้าปัดออบซิเดียน หินภูเขาไฟธรรมชาติผสานดีไซน์นักบินระดับตำนาน สะท้อนงานฝีมือร่วมสมัยและความหรูหรา

By ทีมงาน devdog