โลโก้เซเฟอร์เน็ต

ColBERT – ปรับปรุงประสิทธิภาพการดึงข้อมูลด้วยการฝังเวกเตอร์ระดับโทเค็น

วันที่:

บทนำ

การดึงข้อมูล Augmented-Generation (RAG) ได้ยึดครองโลกโดย Storm นับตั้งแต่ก่อตั้ง RAG คือสิ่งที่จำเป็นสำหรับ Large Language Models (LLM) ในการจัดหาหรือสร้างคำตอบที่ถูกต้องและเป็นข้อเท็จจริง เราแก้ไขข้อเท็จจริงของ LLM โดย RAG โดยที่เราพยายามให้ LLM มีบริบทที่คล้ายกับข้อความค้นหาของผู้ใช้ เพื่อให้ LLM ทำงานกับบริบทนี้และสร้างคำตอบที่ถูกต้องตามข้อเท็จจริง เราทำเช่นนี้โดยการแสดงข้อมูลและการสืบค้นของผู้ใช้ในรูปแบบของการฝังเวกเตอร์และดำเนินการความคล้ายคลึงโคไซน์ แต่ปัญหาก็คือว่าแนวทางดั้งเดิมทั้งหมดแสดงข้อมูลในการฝังเดียว ซึ่งอาจไม่เหมาะสำหรับผลดี ระบบการดึงข้อมูล- ในคู่มือนี้ เราจะดู ColBERT ซึ่งทำการดึงข้อมูลด้วยความแม่นยำที่ดีกว่ารุ่นเข้ารหัสคู่แบบดั้งเดิม

ColBERT - ปรับปรุงประสิทธิภาพการดึงข้อมูลบน LLM ด้วยการฝังเวกเตอร์

วัตถุประสงค์การเรียนรู้

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

บทความนี้เผยแพร่โดยเป็นส่วนหนึ่งของไฟล์ Blogathon วิทยาศาสตร์ข้อมูล

สารบัญ

RAG คืออะไร?

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

ใน RAG เรารวบรวมรายการเอกสาร/ชิ้นส่วนของเอกสารและเข้ารหัสเอกสารต้นฉบับเหล่านี้ให้เป็นการแสดงตัวเลขที่เรียกว่า vector embeddings โดยที่เวกเตอร์ฝังตัวเดียวแสดงถึงเอกสารชิ้นเดียวและจัดเก็บไว้ในฐานข้อมูลที่เรียกว่า ร้านเวกเตอร์- โมเดลที่จำเป็นสำหรับการเข้ารหัสชิ้นส่วนเหล่านี้เป็นการฝังเรียกว่าโมเดลการเข้ารหัสหรือตัวเข้ารหัสแบบไบ ตัวเข้ารหัสเหล่านี้ได้รับการฝึกฝนเกี่ยวกับคลังข้อมูลขนาดใหญ่ จึงทำให้มีประสิทธิภาพเพียงพอที่จะเข้ารหัสส่วนต่างๆ ของเอกสารในรูปแบบการฝังเวกเตอร์เพียงตัวเดียว

RAG คืออะไร?

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

ปัญหาเกี่ยวกับตัวเข้ารหัสแบบ Bi แบบดั้งเดิม

ปัญหาของตัวเข้ารหัสรุ่นดั้งเดิมเช่น all-miniLM OpenAI โมเดลการฝัง และโมเดลตัวเข้ารหัสอื่น ๆ คือพวกมันบีบอัดข้อความทั้งหมดให้เป็นการแสดงการฝังเวกเตอร์เดียว การแสดงการฝังเวกเตอร์เดี่ยวเหล่านี้มีประโยชน์เนื่องจากช่วยในการเรียกค้นเอกสารที่คล้ายกันอย่างมีประสิทธิภาพและรวดเร็ว อย่างไรก็ตาม ปัญหาอยู่ที่บริบทระหว่างแบบสอบถามและเอกสาร การฝังเวกเตอร์เดี่ยวอาจไม่เพียงพอที่จะจัดเก็บข้อมูลบริบทของก้อนเอกสาร ซึ่งทำให้เกิดปัญหาคอขวดของข้อมูล

ลองนึกภาพว่ามีการบีบอัดคำ 500 คำเป็นเวกเตอร์เดียวขนาด 782 อาจไม่เพียงพอที่จะแสดงชิ้นส่วนดังกล่าวด้วยการฝังเวกเตอร์เพียงตัวเดียว ดังนั้นจึงให้ผลลัพธ์ที่ต่ำกว่ามาตรฐานในการดึงข้อมูลในกรณีส่วนใหญ่ การแสดงเวกเตอร์เดี่ยวอาจล้มเหลวในกรณีที่มีการสืบค้นหรือเอกสารที่ซับซ้อน วิธีแก้ไขประการหนึ่งคือการแสดงกลุ่มเอกสารหรือแบบสอบถามเป็นรายการเวกเตอร์ที่ฝังแทนที่จะเป็นเวกเตอร์ที่ฝังตัวเดียว นี่คือจุดที่ ColBERT เข้ามา

ColBERT คืออะไร?

ColBERT (การโต้ตอบล่าช้าตามบริบท BERT) เป็นตัวเข้ารหัสสองตัวที่แสดงข้อความในการนำเสนอแบบฝังหลายเวกเตอร์ ใช้แบบสอบถามหรือชิ้นส่วนของเอกสาร / เอกสารขนาดเล็กและสร้างการฝังเวกเตอร์ในระดับโทเค็น นั่นคือแต่ละโทเค็นจะได้รับการฝังเวกเตอร์ของตัวเอง และแบบสอบถาม/เอกสารจะถูกเข้ารหัสลงในรายการของการฝังเวกเตอร์ระดับโทเค็น การฝังระดับโทเค็นจะถูกสร้างขึ้นจากการฝึกอบรมล่วงหน้า BERT โมเดลจึงได้ชื่อว่า BERT

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

ความคล้ายคลึงกันโดยรวมในรายการโทเค็น

ในสมการข้างต้น เราจะเห็นว่าเราทำดอทโปรดัคระหว่าง Query Tokens Matrix (ที่มีการฝังเวกเตอร์ระดับโทเค็น N) และ Transpose ของ Document Tokens Matrix (ที่มีการฝังเวกเตอร์ระดับโทเค็น M) จากนั้นเราจะรับความคล้ายคลึงกันสูงสุด ข้ามโทเค็นเอกสารสำหรับโทเค็นการสืบค้นแต่ละรายการ จากนั้นเราจะนำผลรวมของความคล้ายคลึงสูงสุดเหล่านี้ทั้งหมด ซึ่งจะให้คะแนนความคล้ายคลึงกันขั้นสุดท้ายระหว่างเอกสารและแบบสอบถาม เหตุผลที่ทำให้ดึงข้อมูลได้อย่างมีประสิทธิภาพและแม่นยำก็คือ ที่นี่เรากำลังมีการโต้ตอบระดับโทเค็น ซึ่งให้พื้นที่สำหรับความเข้าใจบริบทมากขึ้นระหว่างแบบสอบถามและเอกสาร

ทำไมถึงชื่อโคลเบิร์ต?

ในขณะที่เรากำลังคำนวณรายการเวกเตอร์ที่ฝังไว้ข้างหน้าตัวมันเอง และดำเนินการเฉพาะการดำเนินการ MaxSim (ความคล้ายคลึงสูงสุด) นี้ในระหว่างการอนุมานโมเดลเท่านั้น จึงเรียกว่าขั้นตอนการโต้ตอบล่าช้า และในขณะที่เราได้รับข้อมูลเชิงบริบทมากขึ้นผ่านการโต้ตอบระดับโทเค็น จึงเรียกว่าบริบทตามบริบท การโต้ตอบล่าช้า ดังนั้นชื่อการโต้ตอบล่าช้าตามบริบท BERT หรือโคลเบิร์ต การคำนวณเหล่านี้สามารถดำเนินการแบบคู่ขนานได้ จึงสามารถคำนวณได้อย่างมีประสิทธิภาพ สุดท้าย ข้อกังวลประการหนึ่งคือพื้นที่ กล่าวคือ ต้องใช้พื้นที่จำนวนมากในการจัดเก็บรายการการฝังเวกเตอร์ระดับโทเค็น ปัญหานี้ได้รับการแก้ไขใน ColBERTv2 โดยที่การฝังจะถูกบีบอัดผ่านเทคนิคที่เรียกว่าการบีบอัดที่เหลือ ดังนั้นจึงเป็นการเพิ่มประสิทธิภาพพื้นที่ที่ใช้

ColBERT - ปรับปรุงประสิทธิภาพการดึงข้อมูลด้วยการฝังเวกเตอร์

ColBERT แบบลงมือปฏิบัติพร้อมตัวอย่าง

ในส่วนนี้ เราจะได้ลงมือปฏิบัติจริงกับ ColBERT และแม้แต่ตรวจสอบประสิทธิภาพการทำงานของมันกับโมเดลการฝังทั่วไป

ขั้นตอนที่ 1: ดาวน์โหลดไลบรารี

เราจะเริ่มต้นด้วยการดาวน์โหลดไลบรารี่ต่อไปนี้:

!pip install ragatouille langchain langchain_openai chromadb einops sentence-transformers tiktoken
  • รากาตูย: ไลบรารีนี้ช่วยให้เราทำงานกับวิธีการดึงข้อมูลที่ทันสมัย ​​(SOTA) เช่น ColBERT ในวิธีที่ง่ายต่อการใช้งาน โดยมีตัวเลือกในการสร้างดัชนีบนชุดข้อมูล การสืบค้นชุดข้อมูล และแม้กระทั่งช่วยให้เราสามารถฝึกโมเดล ColBERT กับข้อมูลของเราได้
  • แลงเชน: ไลบรารีนี้จะช่วยให้เราทำงานกับโมเดลการฝังโอเพ่นซอร์ส เพื่อให้เราสามารถทดสอบว่าโมเดลการฝังอื่นๆ ทำงานได้ดีเพียงใดเมื่อเปรียบเทียบกับ ColBERT
  • langchain_openai: ติดตั้ง หลังเชน การพึ่งพาสำหรับ OpenAI เราจะทำงานร่วมกับโมเดล OpenAI Embedding เพื่อตรวจสอบประสิทธิภาพเทียบกับ ColBERT
  • โครมาดีบี: ไลบรารีนี้จะให้เราสร้างร้านค้าเวกเตอร์ในสภาพแวดล้อมของเรา เพื่อให้เราสามารถบันทึกการฝังที่เราสร้างขึ้นในข้อมูลของเรา และทำการค้นหาเชิงความหมายระหว่างแบบสอบถามและการฝังที่เก็บไว้ในภายหลัง
  • einops: ไลบรารีนี้จำเป็นสำหรับการคูณเมทริกซ์เทนเซอร์ที่มีประสิทธิภาพ
  • หม้อแปลงประโยค และ ติ๊กต๊อก จำเป็นต้องมีไลบรารีเพื่อให้โมเดลการฝังโอเพ่นซอร์สทำงานได้อย่างถูกต้อง

ขั้นตอนที่ 2: ดาวน์โหลดโมเดลที่ได้รับการฝึกล่วงหน้า

ในขั้นตอนถัดไป เราจะดาวน์โหลดโมเดล ColBERT ที่ได้รับการฝึกล่วงหน้า สำหรับสิ่งนี้โค้ดจะเป็น

from ragatouille import RAGPretrainedModel

RAG = RAGPretrainedModel.from_pretrained("colbert-ir/colbertv2.0")
  • ก่อนอื่นเราจะนำเข้าคลาส RAGPretrainedModel จากไลบรารี RAGatouille
  • จากนั้นเราเรียก .from_pretrained() และตั้งชื่อโมเดล เช่น “colbert-ir/colbertv2.0”

การรันโค้ดด้านบนจะสร้างอินสแตนซ์ของโมเดล ColBERT RAG ตอนนี้เรามาดาวน์โหลดหน้า Wikipedia และทำการดึงข้อมูลจากหน้านั้น สำหรับสิ่งนี้ รหัสจะเป็น:

from ragatouille.utils import get_wikipedia_page

document = get_wikipedia_page("Elon_Musk")
print("Word Count:",len(document))
print(document[:1000])

RAGatouille มาพร้อมกับฟังก์ชันที่มีประโยชน์ที่เรียกว่า get_wikipedia_page ซึ่งรับสตริงและรับหน้า Wikipedia ที่เกี่ยวข้อง ที่นี่เราดาวน์โหลดเนื้อหา Wikipedia บน Elon Musk และจัดเก็บไว้ในเอกสารตัวแปร มาพิมพ์จำนวนคำที่มีอยู่ในเอกสารและสองสามบรรทัดแรกของเอกสารกัน

RAG บน LLM โดยใช้ ColBERT

ที่นี่เราสามารถเห็นผลลัพธ์ในรูป เราจะเห็นได้ว่ามีคำศัพท์ทั้งหมด 64,668 คำในหน้า Wikipedia ของ Elon Musk

ขั้นตอนที่ 3: การสร้างดัชนี

ตอนนี้เราจะสร้างดัชนีในเอกสารนี้

RAG.index(
   # List of Documents
   collection=[document],
   # List of IDs for the above Documents
   document_ids=['elon_musk'],
   # List of Dictionaries for the metadata for the above Documents
   document_metadatas=[{"entity": "person", "source": "wikipedia"}],
   # Name of the index
   index_name="Elon2",
   # Chunk Size of the Document Chunks
   max_document_length=256,
   # Wether to Split Document or Not
   split_documents=True
   )

ที่นี่เราเรียก .index() ของ RAG เพื่อสร้างดัชนีเอกสารของเรา เราผ่านสิ่งต่อไปนี้:

  • คอลเลกชัน: นี่คือรายการเอกสารที่เราต้องการจัดทำดัชนี ที่นี่เรามีเอกสารเพียงฉบับเดียว ดังนั้นจึงเป็นรายการเอกสารฉบับเดียว
  • document_ids: แต่ละเอกสารต้องการรหัสเอกสารที่ไม่ซ้ำกัน ต่อไปนี้เราจะตั้งชื่อว่า elon_musk เพราะเอกสารเกี่ยวกับ Elon Musk
  • document_metadata: แต่ละเอกสารมีข้อมูลเมตาของมัน นี่เป็นรายการพจนานุกรมอีกครั้ง โดยแต่ละพจนานุกรมจะมีข้อมูลเมตาของคู่คีย์-ค่าสำหรับเอกสารหนึ่งๆ
  • ดัชนี_ชื่อ: ชื่อของดัชนีที่เรากำลังสร้าง ตั้งชื่อมันว่า Elon2 กันเถอะ
  • สูงสุด_เอกสาร_ขนาด: นี้จะคล้ายกับขนาดก้อน เราระบุจำนวนเอกสารแต่ละชิ้นว่าควรมีจำนวนเท่าใด ในที่นี้เราจะให้ค่าเป็น 256 หากเราไม่ระบุค่าใดๆ 256 จะถือเป็นขนาดเริ่มต้นของก้อน
  • split_documents: เป็นค่าบูลีน โดยที่ True ระบุว่าเราต้องการแยกเอกสารตามขนาดก้อนที่กำหนด และ False บ่งชี้ว่าเราต้องการจัดเก็บเอกสารทั้งหมดเป็นชิ้นเดียว

การรันโค้ดด้านบนจะแบ่งเอกสารของเราเป็นชิ้นขนาด 256 ชิ้นต่อชิ้น จากนั้นฝังเอกสารเหล่านั้นผ่านโมเดล ColBERT ซึ่งจะสร้างรายการของการฝังเวกเตอร์ระดับโทเค็นสำหรับแต่ละชิ้น และสุดท้ายจัดเก็บไว้ในดัชนี ขั้นตอนนี้จะใช้เวลาสักครู่ในการรันและสามารถเร่งความเร็วได้หากมี GPU สุดท้ายจะสร้างไดเร็กทอรีที่เก็บดัชนีของเรา ที่นี่ไดเรกทอรีจะเป็น “.ragatouille/colbert/indexes/Elon2”

ขั้นตอนที่ 4: แบบสอบถามทั่วไป

ตอนนี้เราจะเริ่มการค้นหา สำหรับสิ่งนี้โค้ดจะเป็น

results = RAG.search(query="What companies did Elon Musk find?", k=3, index_name='Elon2')
for i, doc, in enumerate(results):
   print(f"---------------------------------- doc-{i} ------------------------------------")
   print(doc["content"])
  • อันดับแรก เราเรียกเมธอด .search() ของอ็อบเจ็กต์ RAG
  • ในการนี้ เราให้ตัวแปรที่มีชื่อแบบสอบถาม k (จำนวนเอกสารที่จะดึงข้อมูล) และชื่อดัชนีที่จะค้นหา
  • ที่นี่เราให้คำถาม "บริษัทใดบ้างที่ Elon Musk พบ" ผลลัพธ์ที่ได้จะอยู่ในรายการรูปแบบพจนานุกรมซึ่งประกอบด้วยคีย์ต่างๆ เช่น เนื้อหา คะแนน อันดับ document_id Passage_id และ document_metadata
  • ดังนั้นเราจึงทำงานร่วมกับโค้ดด้านล่างเพื่อพิมพ์เอกสารที่ดึงมาได้อย่างเรียบร้อย
  • ที่นี่เราจะดูรายการพจนานุกรมและพิมพ์เนื้อหาของเอกสาร

การรันโค้ดจะให้ผลลัพธ์ดังต่อไปนี้:

RAG บน LLM ที่มีความแม่นยำดีกว่า ColBERT รุ่นเข้ารหัสสองตัวแบบดั้งเดิม

ในภาพ เราจะเห็นว่าเอกสารฉบับแรกและฉบับสุดท้ายครอบคลุมถึงบริษัทต่างๆ ที่ก่อตั้งโดย Elon Musk ทั้งหมด ColBERT สามารถดึงข้อมูลชิ้นส่วนที่เกี่ยวข้องซึ่งจำเป็นต่อการตอบคำถามได้อย่างถูกต้อง

ขั้นตอนที่ 5: แบบสอบถามเฉพาะ

ตอนนี้เรามาดูขั้นตอนต่อไปและถามคำถามที่เฉพาะเจาะจงกัน

results = RAG.search(query="How much Tesla stocks did Elon sold in 
Decemeber 2022?", k=3, index_name='Elon2')


for i, doc, in enumerate(results):
   print(f"---------------
   ------------------- doc-{i} ------------------------------------")
   print(doc["content"])
RAG บน LLM ที่มีความแม่นยำดีกว่า ColBERT รุ่นเข้ารหัสสองตัวแบบดั้งเดิม

ในโค้ดด้านบนนี้ เรากำลังถามคำถามเฉพาะเจาะจงเกี่ยวกับมูลค่าหุ้นของ Tesla Elon ที่ขายได้ในเดือนธันวาคม 2022 เราสามารถดูผลลัพธ์ได้ที่นี่ เอกสาร-1 มีคำตอบสำหรับคำถาม Elon ขายหุ้นของเขาใน Tesla มูลค่า 3.6 พันล้านดอลลาร์ ขอย้ำอีกครั้งว่า ColBERT สามารถดึงข้อมูลส่วนที่เกี่ยวข้องสำหรับข้อความค้นหาที่กำหนดได้สำเร็จ

ขั้นตอนที่ 6: ทดสอบรุ่นอื่น ๆ

ตอนนี้เรามาลองคำถามเดียวกันกับโมเดลการฝังอื่นๆ ทั้งแบบโอเพ่นซอร์สและแบบปิดที่นี่:

from langchain_community.embeddings import HuggingFaceEmbeddings
from transformers import AutoModel

model = AutoModel.from_pretrained('jinaai/jina-embeddings-v2-base-en', trust_remote_code=True)

model_name = "jinaai/jina-embeddings-v2-base-en"
model_kwargs = {'device': 'cpu'}

embeddings = HuggingFaceEmbeddings(
   model_name=model_name,
   model_kwargs=model_kwargs,
)

  • เราเริ่มต้นด้วยการดาวน์โหลดโมเดลก่อนผ่านคลาส AutoModel จากไลบรารี Transformers
  • จากนั้นเราจะจัดเก็บ model_name และ model_kwargs ไว้ในตัวแปรตามลำดับ
  • ตอนนี้เพื่อทำงานกับโมเดลนี้ใน LangChain เราจะนำเข้า HuggingFaceEmbeddings จาก หลังเชน และตั้งชื่อรุ่นและ model_kwargs

การรันโค้ดนี้จะดาวน์โหลดและโหลดโมเดลการฝัง Jina เพื่อให้เราสามารถทำงานกับมันได้

ขั้นตอนที่ 7: สร้างการฝัง

ตอนนี้ เราต้องเริ่มแยกเอกสารของเรา จากนั้นสร้างการฝังจากเอกสารนั้น และจัดเก็บไว้ใน Chroma vector store เพื่อสิ่งนี้ เราทำงานกับโค้ดต่อไปนี้:

from langchain_community.vectorstores import Chroma
from langchain_text_splitters import RecursiveCharacterTextSplitter

text_splitter = RecursiveCharacterTextSplitter.from_tiktoken_encoder(
    chunk_size=256, 
    chunk_overlap=0)
splits = text_splitter.split_text(document)
vectorstore = Chroma.from_texts(texts=splits,
                                embedding=embeddings,
                                collection_name="elon")
retriever = vectorstore.as_retriever(search_kwargs = {'k':3})
  • เราเริ่มต้นด้วยการนำเข้า Chroma และ RecursiveCharacterTextSplitter จากไลบรารี LangChain
  • จากนั้นเราสร้างตัวอย่าง text_splitter โดยการเรียก .from_tiktoken_encoder ของ RecursiveCharacterTextSplitter แล้วส่งต่อเป็น chunk_size และ chunk_overlap
  • ที่นี่เราจะใช้ chunk_size เดียวกันกับที่เราให้ไว้กับ ColBERT
  • จากนั้นเราจะเรียกเมธอด .split_text() ของ text_splitter นี้ และมอบเอกสารที่มีข้อมูล Wikipedia เกี่ยวกับ Elon Musk ให้กับมัน จากนั้นจะแยกเอกสารตามขนาดชิ้นที่กำหนด และสุดท้าย รายการชิ้นส่วนเอกสารจะถูกจัดเก็บไว้ในการแยกตัวแปร
  • สุดท้ายนี้ เราเรียกฟังก์ชัน .from_texts() ของคลาส Chroma เพื่อสร้างที่เก็บเวกเตอร์ สำหรับฟังก์ชันนี้ เราให้การแยก โมเดลการฝัง และ collection_name
  • ตอนนี้เราสร้างรีทรีฟเวอร์ขึ้นมาโดยการเรียกใช้ฟังก์ชัน .as_retriever() ของอ็อบเจ็กต์ vector store เราให้ 3 สำหรับค่า k

การเรียกใช้โค้ดนี้จะนำเอกสารของเรามาแยกออกเป็นเอกสารขนาดเล็กขนาด 256 ต่อชิ้น จากนั้นฝังชิ้นเล็กๆ เหล่านี้ด้วยโมเดลการฝัง Jina และจัดเก็บเวกเตอร์ที่ฝังเหล่านี้ไว้ในที่เก็บเวกเตอร์โครมา

ขั้นตอนที่ 8: การสร้างรีทรีฟเวอร์

ในที่สุดเราก็สร้างรีทรีฟเวอร์ขึ้นมา ตอนนี้เราจะทำการค้นหาเวกเตอร์และตรวจสอบผลลัพธ์

docs = retriever.get_relevant_documents("What companies did Elon Musk find?",)

for i, doc in enumerate(docs):
 print(f"---------------------------------- doc-{i} ------------------------------------")
 print(doc.page_content)
"
  • เราเรียกฟังก์ชัน .get_relevent_documents() ของอ็อบเจ็กต์ตัวดึงข้อมูล และให้คำค้นหาเดียวกัน
  • จากนั้นเราจะพิมพ์เอกสารที่ดึงมา 3 อันดับแรกอย่างเรียบร้อย
  • ในภาพ เราจะเห็นว่า Jina Embedder แม้ว่าจะเป็นโมเดลการฝังที่ได้รับความนิยม แต่การดึงข้อมูลสำหรับการสืบค้นของเรายังทำได้ไม่ดี ไม่สามารถรับชิ้นส่วนเอกสารที่ถูกต้องได้

เราสามารถมองเห็นความแตกต่างได้อย่างชัดเจนระหว่าง Jina ซึ่งเป็นโมเดลการฝังที่แสดงถึงแต่ละชิ้นเป็นการฝังเวกเตอร์เดียว และโมเดล ColBERT ซึ่งแสดงถึงแต่ละชิ้นเป็นรายการของเวกเตอร์การฝังระดับโทเค็น ColBERT มีประสิทธิภาพเหนือกว่าอย่างชัดเจนในกรณีนี้

ขั้นตอนที่ 9: ทดสอบโมเดลการฝังของ OpenAI

ตอนนี้เรามาลองใช้โมเดลการฝังแบบโอเพนซอร์ส เช่น โมเดลการฝัง OpenAI

import os

os.environ["OPENAI_API_KEY"] = "Your API Key"

from langchain_openai import OpenAIEmbeddings

embeddings = OpenAIEmbeddings()

text_splitter = RecursiveCharacterTextSplitter.from_tiktoken_encoder(
              model_name = "gpt-4",
              chunk_size = 256,
              chunk_overlap  = 0,
              )

splits = text_splitter.split_text(document)
vectorstore = Chroma.from_texts(texts=splits,
                                embedding=embeddings,
                                collection_name="elon_collection")

retriever = vectorstore.as_retriever(search_kwargs = {'k':3})

โค้ดที่นี่คล้ายกับโค้ดที่เราเพิ่งเขียนไปมาก

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

การรันโค้ดนี้จะนำเอกสารของเราอีกครั้ง แบ่งเป็นเอกสารขนาดเล็กขนาด 256 จากนั้นฝังลงในการแสดงการฝังเวกเตอร์เดี่ยวด้วยโมเดลการฝัง OpenAI และสุดท้ายจะจัดเก็บการฝังเหล่านี้ใน Chroma Vector Store ตอนนี้เรามาลองดึงเอกสารที่เกี่ยวข้องไปยังคำถามอื่นกัน

docs = retriever.get_relevant_documents("How much Tesla stocks did Elon sold in Decemeber 2022?",)

for i, doc in enumerate(docs):
  print(f"---------------------------------- doc-{i} ------------------------------------")
  print(doc.page_content)
  • เราเห็นว่าคำตอบที่เราคาดหวังนั้นไม่พบภายในส่วนที่ดึงมา
  • ชิ้นนี้มีข้อมูลเกี่ยวกับหุ้นของ Tesla ในปี 2022 แต่ไม่ได้พูดถึงการขายหุ้นของ Elon
  • สิ่งเดียวกันนี้สามารถเห็นได้จากเอกสารอีกสองชิ้นที่เหลือ ซึ่งข้อมูลที่มีอยู่ในนั้นเกี่ยวกับ Tesla และหุ้นของบริษัท แต่นี่ไม่ใช่ข้อมูลที่เราคาดหวัง
  • ส่วนที่ดึงข้อมูลมาข้างต้นจะไม่ให้บริบทสำหรับ LLM ในการตอบคำถามที่เราให้ไว้

แม้แต่ที่นี่ เราก็สามารถเห็นความแตกต่างที่ชัดเจนระหว่างการแสดงแบบฝังเวกเตอร์เดี่ยว กับการแสดงแบบฝังหลายเวกเตอร์ การแสดงการฝังหลายรายการจะจับการสืบค้นที่ซับซ้อนได้อย่างชัดเจน ซึ่งส่งผลให้สามารถเรียกค้นข้อมูลได้แม่นยำยิ่งขึ้น

สรุป

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

ประเด็นที่สำคัญ

  • RAG แก้ไขปัญหาภาพหลอนใน LLM โดยการให้ข้อมูลเชิงบริบทสำหรับการสร้างคำตอบตามข้อเท็จจริง
  • ตัวเข้ารหัสแบบคู่แบบดั้งเดิมประสบปัญหาคอขวดของข้อมูลเนื่องจากการบีบอัดข้อความทั้งหมดเป็นการฝังเวกเตอร์เดี่ยว ส่งผลให้ได้รับความแม่นยำต่ำกว่ามาตรฐาน
  • ColBERT ซึ่งมีการแสดงการฝังระดับโทเค็น ช่วยให้เข้าใจบริบทระหว่างข้อความค้นหาและเอกสารได้ดีขึ้น ซึ่งนำไปสู่ประสิทธิภาพการดึงข้อมูลที่ดีขึ้น
  • ขั้นตอนการโต้ตอบล่าช้าใน ColBERT รวมกับการโต้ตอบระดับโทเค็น ช่วยเพิ่มความแม่นยำในการดึงข้อมูลโดยการพิจารณาความแตกต่างทางบริบท
  • ColBERTv2 เพิ่มประสิทธิภาพพื้นที่จัดเก็บข้อมูลผ่านการบีบอัดส่วนที่เหลือในขณะที่ยังคงประสิทธิภาพในการดึงข้อมูล
  • การทดลองภาคปฏิบัติแสดงให้เห็นถึงความเหนือกว่าของ ColBERT ในด้านประสิทธิภาพในการดึงข้อมูล เมื่อเปรียบเทียบกับโมเดลการฝังแบบดั้งเดิมและแบบโอเพ่นซอร์ส เช่น Jina และ OpenAI Embedding

คำถามที่พบบ่อย

ไตรมาสที่ 1 ปัญหาของตัวเข้ารหัสแบบคู่แบบดั้งเดิมคืออะไร?

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

ไตรมาสที่ 2 ColBERT คืออะไร?

A. ColBERT (การโต้ตอบล่าช้าตามบริบท BERT) คือโมเดลตัวเข้ารหัสสองตัวที่แสดงข้อความโดยใช้การฝังเวกเตอร์ระดับโทเค็น ช่วยให้มีความเข้าใจบริบทที่เหมาะสมยิ่งขึ้นระหว่างการสืบค้นและเอกสาร ปรับปรุงความแม่นยำในการเรียกค้น

ไตรมาสที่ 3 โคลเบิร์ตทำงานอย่างไร?

A. ColBERT สร้างการฝังระดับโทเค็นสำหรับการสืบค้นและเอกสาร ดำเนินการคูณเมทริกซ์เพื่อคำนวณคะแนนความคล้ายคลึงกัน จากนั้นเลือกข้อมูลที่เกี่ยวข้องมากที่สุดตามความคล้ายคลึงกันสูงสุดระหว่างโทเค็นต่างๆ ซึ่งช่วยให้สามารถดึงข้อมูลได้อย่างมีประสิทธิภาพด้วยความเข้าใจตามบริบท

ไตรมาสที่ 4 ColBERT เพิ่มประสิทธิภาพพื้นที่อย่างไร

A. ColBERTv2 ปรับ Space ให้เหมาะสมด้วยวิธีการบีบอัดส่วนที่เหลือ ช่วยลดความต้องการพื้นที่จัดเก็บข้อมูลสำหรับการฝังระดับโทเค็น ในขณะที่ยังคงความแม่นยำในการดึงข้อมูล

คำถามที่ 5 ฉันจะใช้ ColBERT ในทางปฏิบัติได้อย่างไร

A. คุณสามารถใช้ไลบรารีเช่น RAGatouille เพื่อทำงานกับ ColBERT ได้อย่างง่ายดาย ด้วยการจัดทำดัชนีเอกสารและการสืบค้น คุณสามารถดำเนินการดึงข้อมูลได้อย่างมีประสิทธิภาพ และสร้างคำตอบที่แม่นยำซึ่งสอดคล้องกับบริบท

สื่อที่แสดงในบทความนี้ไม่ได้เป็นของ Analytics Vidhya และถูกใช้ตามดุลยพินิจของผู้เขียน

จุด_img

ข่าวกรองล่าสุด

จุด_img