6 คะแนน โดย GN⁺ 2024-02-08 | 1 ความคิดเห็น | แชร์ทาง WhatsApp

เสิร์ชเอนจิน 80 บรรทัดที่สร้างด้วย Python

  • เมื่อเดือนกันยายนที่ผ่านมา ผู้เขียนได้เข้าร่วมงานที่ Wallapop ในตำแหน่งนักวิทยาศาสตร์ข้อมูลด้านการค้นหา และทำงานกับเสิร์ชเอนจินโอเพนซอร์สชื่อ Solr
  • เพื่อทำความเข้าใจหลักการพื้นฐานของเสิร์ชเอนจิน ผู้เขียนจึงตัดสินใจสร้างเสิร์ชเอนจินขึ้นมาเองตั้งแต่ต้นด้วย Python
  • เป้าหมายคือการแก้ปัญหา "วิกฤตการค้นพบเว็บไซต์ขนาดเล็ก" เพื่อทำให้เว็บไซต์เล็ก ๆ ที่ค้นหาไม่เจอผ่านเสิร์ชเอนจินอย่าง Google กลับมายิ่งใหญ่อีกครั้ง
  • บทความนี้อธิบายขั้นตอนการสร้างเสิร์ชเอนจินด้วย Python และสามารถดูโค้ดทั้งหมดที่เขียนไว้ได้ในรีโพซิทอรี GitHub ของ microsearch
  • เสิร์ชเอนจินที่ทำขึ้นนี้ไม่ใช่เสิร์ชเอนจินที่พร้อมใช้งานในงานจริง แต่เป็นตัวอย่างแบบของเล่นที่ใช้งานได้ ซึ่งแสดงให้เห็นว่าเสิร์ชเอนจินทำงานภายในอย่างไร

microsearch

  • สำรวจองค์ประกอบของ microsearch และดูว่าแต่ละส่วนถูกสร้างขึ้นอย่างไร: (1) crawler, (2) inverted index, (3) ranking, (4) interface

Crawler

  • ขั้นตอนแรกของการสร้างเสิร์ชเอนจินคือการเตรียมข้อมูลสำหรับใช้ค้นหา
  • ผู้เขียนสร้างเสิร์ชเอนจินจากข้อมูลของบล็อกที่ติดตามอยู่ โดยตั้งใจจะทำ "Google เวอร์ชันท้องถิ่น"
  • การ crawl ครอบคลุมกระบวนการดาวน์โหลดและจัดระเบียบโพสต์ทั้งหมดจากรายการบล็อกที่กำหนด
  • เพื่อให้เร็วขึ้น ผู้เขียนใช้ไลบรารี asyncio ของ Python ทำให้เวลาการ crawl ลดลงจาก 20 นาทีเหลือ 20 วินาที
  • ใช้ RSS feed จำนวน 642 รายการ โดยในจำนวนนี้ราว 100 รายการเป็นบล็อกที่อ่านเป็นประจำ และอีก 500 รายการนำมาจากโปรเจกต์บล็อก surprisetalk

Inverted index

  • Inverted index คือโครงสร้างข้อมูลที่แมปคีย์เวิร์ดเข้ากับเอกสาร ทำให้ค้นหาเอกสารที่มีคำใดคำหนึ่งปรากฏอยู่ได้ง่าย
  • เมื่อผู้ใช้ค้นหาคิวรี ระบบจะใช้ inverted index เพื่อดึงเอกสารทั้งหมดที่ตรงกับคีย์เวิร์ดในคิวรี
  • ตรรกะของ inverted index ถูกนิยามไว้ในคลาสชื่อ SearchEngine และทำการติดตั้งโดยการกำหนดค่าเริ่มต้นให้พจนานุกรมสองชุด

Ranking

  • เมื่อมีชุดเอกสารที่ตรงกับคิวรีแล้ว ก็จำเป็นต้องมีวิธีจัดเรียงลำดับเอกสารเหล่านั้น
  • วิธีจัดอันดับที่มีชื่อเสียงที่สุดคือ PageRank ของ Google แต่ก็ยังมีตัวเลือกอื่น เช่น BM25 ที่จัดอันดับเอกสารตามเนื้อหา
  • ผู้เขียนเติมส่วนที่ขาดหายไปของคลาส SearchEngine รวมถึงวิธีคำนวณคะแนน BM25

Interface

  • หลังจากสร้างเสิร์ชเอนจินแล้ว ผู้เขียนต้องการเปิดให้ใช้งานในรูปแบบใดรูปแบบหนึ่ง
  • จึงสร้างแอป FastAPI เพื่อเปิด endpoint สำหรับเสิร์ชเอนจิน และเรนเดอร์หน้าเว็บอย่างง่ายสำหรับทำการค้นหา
  • เพื่อให้อ่านผลลัพธ์ได้ง่าย จึงตัดสินใจเลือกแสดงเฉพาะ URL อันดับต้น ๆ จำนวน N รายการ

ฟีเจอร์ที่ยังขาด

  • หากผู้อ่านคุ้นเคยกับเสิร์ชเอนจินอยู่แล้ว ก็น่าจะสังเกตได้ว่ามีฟีเจอร์อีกมากที่ยังไม่ได้ถูกนำมาใช้
  • ที่ยังขาดอยู่ได้แก่ query operator, การทำดัชนีแบบ n-gram, การขยายคิวรีหรือเอกสาร และความสามารถในการ crawl กับ indexing ไปพร้อมกัน

บทสรุป

  • จากโปรเจกต์นี้ ผู้เขียนเข้าใจการทำงานภายในของ Solr ดีขึ้น และได้เรียนรู้ถึงความน่าทึ่งของการเขียนโค้ดแบบ asynchronous
  • ขั้นตอนถัดไปในการสร้างเสิร์ชเอนจินส่วนตัวคือการเพิ่มความสามารถด้าน semantic search ให้กับเสิร์ชเอนจิน

ความเห็นของ GN⁺

  • ประเด็นสำคัญที่สุดของบทความนี้คือ บุคคลทั่วไปสามารถสร้างเสิร์ชเอนจินขึ้นมาเองได้เพื่อปรับปรุงการค้นพบเว็บไซต์ขนาดเล็ก
  • ประสบการณ์ในการใช้ Python และไลบรารีโอเพนซอร์สเพื่อทำให้การสร้างเสิร์ชเอนจินที่มีฟังก์ชันซับซ้อนกลายเป็นเรื่องเรียบง่าย อาจเป็นแรงบันดาลใจให้วิศวกรซอฟต์แวร์ระดับเริ่มต้นได้เช่นกัน
  • บทความนี้มอบทั้งมุมมองเชิงเทคนิคและโอกาสในการเรียนรู้เชิงปฏิบัติ ด้วยการแสดงให้เห็นประสิทธิภาพของ asynchronous programming และความสำคัญของโครงสร้างข้อมูลผ่านตัวอย่างจริง

1 ความคิดเห็น

 
GN⁺ 2024-02-08
ความเห็นจาก Hacker News
  • การพัฒนาเสิร์ชเอนจิน BM25 ด้วย Pandas

    • นักพัฒนากำลังพัฒนาเสิร์ชเอนจิน BM25 ที่ทำงานบน Pandas ซึ่งมีความรวดเร็ว
    • เหตุผลที่ใช้ Pandas คือ นอกจากอัลกอริทึม BM25 แล้ว ยังสามารถผสานปัจจัยอื่น ๆ เช่น ความใหม่และความนิยมได้อย่างง่ายดาย
    • การจับคู่ข้อความมีกรณียกเว้นอยู่มาก และการบีบอัดข้อมูลตำแหน่งโดยใช้หน่วยความจำน้อยที่สุดเท่าที่เป็นไปได้เป็นสิ่งสำคัญ
  • รีวิวโค้ด: คลาส SearchEngine

    • ไม่ทราบความหมายของพารามิเตอร์ k1 และ b และในโค้ดก็ไม่มีคอมเมนต์เลย
    • คาดว่า _documents ใช้ URL เป็นคีย์ และใช้เนื้อหาของ URL นั้นเป็นค่า
    • น่าเสียดายที่โค้ดมีเอกสารประกอบไม่ดีนัก ถ้าจัดทำเอกสารไว้ดีกว่านี้ก็น่าจะเป็นสื่อการเรียนรู้สำหรับการสร้างเสิร์ชเอนจินได้อย่างมีประโยชน์
  • ความซับซ้อนของเสิร์ชเอนจิน

    • ความยากหลักของเสิร์ชเอนจินคือการจัดการกับปริมาณข้อมูล
    • ตัวตรรกะเองกลับเรียบง่ายกว่าที่คิด และโปรเจกต์นี้ก็ประสบความสำเร็จเพราะตัดส่วนที่ไม่จำเป็นออกไปเกือบทั้งหมด
    • แนวทางที่สำคัญไม่ใช่การทำให้เสิร์ชเอนจินใหญ่ขึ้น แต่คือการทำให้ข้อมูลเล็กลง หรือเพิ่มอัตราส่วนสัญญาณต่อสัญญาณรบกวน
  • ความเห็นเรื่องจำนวนบรรทัดของโค้ด

    • มีการตั้งคำถามว่าการอวดจำนวนบรรทัดโค้ดมีความหมายแค่ไหน เมื่ออยู่ในสถานการณ์ที่ใช้ external dependency
    • แม้จะไม่มีหน่วย SI สำหรับ codebase แต่ก็มีความเห็นว่าควรมีวิธีวัดภาระทางการรับรู้ไม่ทางใดก็ทางหนึ่ง
  • มุกเกี่ยวกับสำนวนในโค้ด

    • เมื่อเห็นสำนวน chunk for chunk in chunks if chunk ในโค้ด ก็ทำให้นึกถึงมุกเกี่ยวกับคนตัดไม้
  • ตัวอย่างโค้ด recommendation engine

    • มีการให้โค้ด recommendation engine ที่เขียนด้วย Python ซึ่งมีความยาวไม่ถึง 20 บรรทัด และสามารถใช้คู่กับเสิร์ชเอนจินได้
    • ระบบจะสร้างคำแนะนำจาก URL ที่ถูกคลิกใน session log
    • หากนำ query ที่ถูกป้อนใน log มาผสมกับ URL ที่ถูกคลิก ก็ยังสามารถใช้เพื่อสร้างคำแนะนำการตรวจสะกดได้ด้วย
  • การเปรียบเทียบประสิทธิภาพของไลบรารี parsing

    • มีการกล่าวถึงว่า lxml.html และ lxml.html.clean อาจเร็วกว่า BeautifulSoup มาก
  • คำแนะนำเรื่องการใช้คีย์เวิร์ด

    • แนะนำให้ใช้ 2-gram และ 3-gram แทน 1-gram เพื่อยกระดับคุณภาพของผลการค้นหาเป็นภาษาอังกฤษ
    • n-gram ช่วยรักษาบริบทได้
  • ความเห็นต่อโปรเจกต์เชิงการศึกษา

    • โปรเจกต์นี้เท่มากและให้คุณค่าด้านการเรียนรู้ แต่แนะนำว่าไม่ควรนำไป deploy ใช้งานจริง
    • สำหรับโปรเจกต์ขนาดใหญ่กว่าที่ต้องจัดการเอกสารระดับหลายหมื่นรายการ คำตอบคือการใช้ FTS5 ของ SQLite
  • ข้อสงสัยเกี่ยวกับการใช้ Python กับการประมวลผลข้อมูลขนาดใหญ่

    • มีการตั้งคำถามว่าการใช้ Python ซึ่งเป็นภาษาที่ช้า กับงานที่ต้องประมวลผลข้อมูลขนาดใหญ่ให้รวดเร็ว เป็นความคิดที่ดีจริงหรือไม่