เทคโนโลยี Contextual Retrieval
(anthropic.com)- RAG ที่ใช้ใน AI บนฐานความรู้องค์กร อาจสูญเสียบริบทอย่างชื่อบริษัทหรือช่วงเวลาในกระบวนการแบ่งเอกสารเป็นชังก์เล็ก ๆ ทำให้พลาดข้อมูลที่เกี่ยวข้องได้
- Contextual Retrieval ของ Anthropic เป็นวิธีลดอัตราความล้มเหลวในการค้นหา โดยเพิ่มคำอธิบายสั้น ๆ ตามบริบทของเอกสารทั้งฉบับไว้หน้าชังก์แต่ละชังก์ แล้วจึงสร้าง embedding และดัชนี BM25
- ในการทดลอง Contextual Embeddings ลดอัตราความล้มเหลวในการค้นหาชังก์ top-20 จาก 5.7% เหลือ 3.7% หรือลดลง 35% และการผสาน Contextual Embeddings กับ Contextual BM25 ลดลงเหลือ 2.9% หรือลดลง 49%
- เมื่อเพิ่ม การจัดอันดับใหม่ (reranking) จะนำผู้สมัคร top-150 มาให้คะแนนใหม่ และส่งต่อให้โมเดลเฉพาะ top-20 โดยอัตราความล้มเหลวในการค้นหาลดจาก 5.7% เหลือ 1.9% หรือลดลง 67%
- หากฐานความรู้มีขนาด ไม่เกิน 200,000 โทเค็น ก็สามารถใส่ทั้งหมดลงในพรอมป์ได้ แต่สำหรับฐานความรู้ที่ใหญ่กว่านั้น ควรประเมินการผสาน Contextual Retrieval กับการจัดอันดับใหม่แยกตาม use case
บริบทของเอกสารที่ RAG สูญเสียไป
- เพื่อให้โมเดล AI มีประโยชน์ในงานเฉพาะด้าน จำเป็นต้องเข้าถึง ความรู้พื้นหลัง
- แชตบอตฝ่ายสนับสนุนลูกค้าต้องการความรู้ของธุรกิจนั้น
- บอตวิเคราะห์กฎหมายต้องการความรู้เกี่ยวกับคำพิพากษาในอดีต
- โดยทั่วไปนักพัฒนาจะเสริมความรู้ให้โมเดลด้วย Retrieval-Augmented Generation(RAG)
- ค้นหาข้อมูลที่เกี่ยวข้องจากฐานความรู้
- นำข้อมูลที่ค้นหาได้ไปต่อท้ายพรอมป์ของผู้ใช้ เพื่อปรับปรุงคำตอบของโมเดล
- RAG แบบเดิมอาจ ตัดบริบทออกไป ระหว่างการแบ่งเอกสารเป็นชังก์ ทำให้หาข้อมูลที่เกี่ยวข้องไม่เจอ
- Contextual Retrieval เป็นวิธีปรับปรุงขั้นตอนการค้นหาของ RAG และสามารถใช้เทคนิคย่อย 2 อย่างร่วมกันได้
- Contextual Embeddings: สร้าง embedding จากชังก์ที่มีบริบทแนบอยู่
- Contextual BM25: สร้างดัชนี BM25 จากชังก์ที่มีบริบทแนบอยู่
- การผสานนี้ลดจำนวนการค้นหาล้มเหลวได้ 49% และเมื่อนำไปรวมกับการจัดอันดับใหม่จะลดได้ถึง 67%
- มี cookbook สำหรับนำ Contextual Retrieval ไปใช้งานด้วย Claude
ฐานความรู้ขนาดเล็กสามารถใช้พรอมป์ยาวได้
- หากฐานความรู้มีขนาด ไม่เกิน 200,000 โทเค็น หรือเล็กกว่าประมาณ 500 หน้า สามารถใส่ฐานความรู้ทั้งหมดลงในพรอมป์ได้โดยไม่ต้องใช้ RAG
- prompt caching ของ Claude ทำให้แนวทางนี้เร็วขึ้นและคุ้มค่ากว่าเดิม
- สามารถแคชพรอมป์ที่ใช้บ่อยระหว่างการเรียก API ได้
- ลด latency ได้ มากกว่า 2 เท่า
- ลดต้นทุนได้สูงสุด 90%
- ดูวิธีทำงานได้ใน prompt caching cookbook
- เมื่อฐานความรู้ใหญ่ขึ้น จำเป็นต้องมีวิธีค้นหาที่ขยายตัวได้มากกว่า และ Contextual Retrieval ถูกใช้ในจุดนี้
บทบาทของ RAG ทั่วไปและ BM25
- เมื่อฐานความรู้ขนาดใหญ่ไม่สามารถใส่ใน context window ได้ วิธีแก้ทั่วไปคือ RAG
- กระบวนการ preprocessing ของ RAG มีดังนี้
- แบ่งคลังเอกสารออกเป็นชังก์ข้อความขนาดเล็ก โดยปกติไม่เกินไม่กี่ร้อยโทเค็น
- ใช้โมเดล embedding แปลงชังก์เป็น vector embedding ที่บรรจุความหมาย
- เก็บ embedding ลงใน vector database ที่รองรับการค้นหาความคล้ายเชิงความหมาย
- ขณะรัน จะค้นหาชังก์ที่มีความหมายใกล้เคียงกับคำถามของผู้ใช้มากที่สุดจาก vector database แล้วเพิ่มชังก์ที่เกี่ยวข้องลงในพรอมป์ของโมเดลสร้างคำตอบ
- โมเดล embedding จับความสัมพันธ์เชิงความหมายได้ดี แต่อาจพลาด การตรงกันของสตริงแบบเป๊ะ ๆ
- BM25(Best Matching 25) เป็นฟังก์ชันจัดอันดับที่ใช้การตรงกันของคำศัพท์ มีประสิทธิภาพเป็นพิเศษกับคำถามที่มีตัวระบุเฉพาะหรือศัพท์เทคนิค
- BM25 อิงแนวคิด TF-IDF
- TF-IDF วัดว่าคำหนึ่ง ๆ มีความสำคัญต่อเอกสารมากเพียงใดภายในคอลเลกชัน
- BM25 คำนึงถึงความยาวเอกสาร และใช้ฟังก์ชัน saturation กับ term frequency เพื่อไม่ให้คำที่พบทั่วไปครอบงำผลลัพธ์
- ตัวอย่างเช่น เมื่อค้นหา
"Error code TS-999"ในฐานข้อมูลซัพพอร์ตเชิงเทคนิค โมเดล embedding อาจหาเอกสารเกี่ยวกับรหัสข้อผิดพลาดทั่วไปได้ แต่อาจพลาดการตรงกันแบบเป๊ะ ๆ ของ"TS-999" - BM25 จะค้นหาสตริงนั้นโดยตรงเพื่อระบุเอกสารที่เกี่ยวข้อง
RAG ที่ใช้ embedding และ BM25 ร่วมกัน
- RAG สามารถผสาน embedding กับ BM25 เพื่อค้นหาชังก์ได้แม่นยำขึ้น
- แบ่งฐานความรู้ออกเป็นชังก์เล็ก ๆ
- สร้างทั้ง TF-IDF encoding และ semantic embedding ให้แต่ละชังก์
- ใช้ BM25 ค้นหาชังก์อันดับต้น ๆ ตามการตรงกันแบบเป๊ะ ๆ
- ใช้ embedding ค้นหาชังก์อันดับต้น ๆ ตามความคล้ายเชิงความหมาย
- ผสานผลลัพธ์ด้วยเทคนิค rank fusion และลบรายการซ้ำ
- ใส่ชังก์ top-K ลงในพรอมป์เพื่อสร้างคำตอบ
- วิธีนี้สร้างสมดุลระหว่างการตรงกันของคำศัพท์แบบเป๊ะ ๆ กับความเข้าใจความหมายที่กว้างกว่า
- สามารถขยายไปถึงฐานความรู้ขนาดใหญ่มากที่ใส่ในพรอมป์เดียวไม่ได้อย่างคุ้มค่า
- แต่ระบบ RAG แบบเดิมมีข้อจำกัดคือ ทำลายบริบท เมื่อแบ่งเอกสารเป็นชังก์
- สถานการณ์ตัวอย่างคือการถามว่า
"What was the revenue growth for ACME Corp in Q2 2023?"ในฐานความรู้จากเอกสารยื่นต่อ SEC- ชังก์ที่เกี่ยวข้องอาจมีเพียง
"The company's revenue grew by 3% over the previous quarter." - จากชังก์นี้อย่างเดียว ไม่สามารถรู้ได้ว่าเป็นบริษัทใดและช่วงเวลาใด
- จึงใช้ข้อมูลที่ถูกต้องได้ยากทั้งในขั้นค้นหาและขั้นใช้งาน
- ชังก์ที่เกี่ยวข้องอาจมีเพียง
วิธีการของ Contextual Retrieval
- Contextual Retrieval เพิ่มบริบทเชิงคำอธิบายของแต่ละชังก์ไว้ด้านหน้าก่อนนำชังก์ไปสร้าง embedding และดัชนี BM25
- เมื่อนำไปใช้กับ embedding เรียกว่า Contextual Embeddings
- เมื่อนำไปใช้กับดัชนี BM25 เรียกว่า Contextual BM25
- ในตัวอย่างเอกสารยื่นต่อ SEC ชังก์เดิมเป็นดังนี้
The company's revenue grew by 3% over the previous quarter.
- ชังก์ที่เพิ่มบริบทจะเปลี่ยนเป็นดังนี้
This chunk is from an SEC filing on ACME corp's performance in Q2 2023; the previous quarter's revenue was $314 million. The company's revenue grew by 3% over the previous quarter.
- ในอดีตเคยมีการเสนอวิธีใช้บริบทเพื่อปรับปรุงการค้นหา
- วิธี เพิ่มสรุปเอกสารทั่วไปลงในชังก์ ให้ผลปรับปรุงในการทดลองอย่างจำกัดมาก
- มี hypothetical document embedding
- summary-based indexing ให้ผลการประเมินต่ำ
- วิธีเหล่านี้แตกต่างจากแนวทางของ Contextual Retrieval ที่เพิ่มบริบทเฉพาะแต่ละชังก์
การสร้างบริบทของชังก์ด้วย Claude
- การให้มนุษย์ใส่ annotation ให้ชังก์หลายพันหรือหลายล้านชังก์ด้วยตัวเองนั้นไม่ใช่เรื่องปฏิบัติได้จริง
- Anthropic เขียนพรอมป์ให้ Claude สร้าง บริบทสั้น ๆ เฉพาะแต่ละชังก์ ที่อธิบายชังก์นั้นโดยอิงบริบทของเอกสารทั้งฉบับ
- พรอมป์ที่ใช้กับ Claude 3 Haiku มีดังนี้
<document>
{{WHOLE_DOCUMENT}}
</document>
Here is the chunk we want to situate within the whole document
<chunk>
{{CHUNK_CONTENT}}
</chunk>
Please give a short succinct context to situate this chunk within the overall document for the purposes of improving search retrieval of the chunk. Answer only with the succinct context and nothing else.
- ข้อความบริบทที่สร้างได้โดยทั่วไปมีขนาด 50~100 โทเค็น และถูกนำไปต่อหน้าชังก์ก่อนใช้สร้าง embedding และดัชนี BM25
- เมื่อใช้ prompt caching ไม่จำเป็นต้องส่งเอกสารอ้างอิงซ้ำในทุกชังก์
- นำเอกสารขึ้นแคชครั้งเดียว แล้วอ้างถึงเนื้อหาที่แคชไว้ก่อนหน้า
- หากสมมติว่าชังก์มี 800 โทเค็น เอกสารมี 8k โทเค็น คำสั่งบริบทมี 50 โทเค็น และบริบทต่อชังก์มี 100 โทเค็น ต้นทุนแบบครั้งเดียวในการสร้างชังก์ที่มีบริบทคือ 1.02 ดอลลาร์ต่อเอกสาร 1 ล้านโทเค็น
วิธีทดลองและประสิทธิภาพการค้นหา
- การทดลองทำในหลายโดเมนความรู้ โมเดล embedding กลยุทธ์การค้นหา และตัวชี้วัดการประเมิน
- codebase
- นวนิยาย
- บทความ ArXiv
- บทความวิทยาศาสตร์
- ตัวอย่างคำถามและคำตอบของแต่ละโดเมนอยู่ใน Appendix II
- กราฟแสดงประสิทธิภาพเฉลี่ยของทุกโดเมนความรู้ โดยใช้ Gemini Text 004 ซึ่งเป็นการตั้งค่า embedding ระดับสูง และการค้นหาชังก์ top-20
- ตัวชี้วัดการประเมินคือ 1 - recall@20
- วัดสัดส่วนที่ไม่สามารถค้นหาเอกสารที่เกี่ยวข้องได้ภายในชังก์ 20 อันดับแรก
- จากผลรวม การผสาน embedding-source ทุกชุดที่ประเมินมีประสิทธิภาพดีขึ้นเมื่อใช้การเพิ่มบริบท
- ผลการปรับปรุงประสิทธิภาพมีดังนี้
- Contextual Embeddings: ลดอัตราความล้มเหลวในการค้นหาชังก์ top-20 จาก 5.7% → 3.7% หรือ 35%
- Contextual Embeddings + Contextual BM25: ลดอัตราความล้มเหลวในการค้นหาจาก 5.7% → 2.9% หรือ 49%
สิ่งที่ควรพิจารณาเมื่อนำไปใช้งาน
- ขอบเขตของชังก์ อาจส่งผลต่อประสิทธิภาพการค้นหา
- ขนาดชังก์
- ขอบเขตชังก์
- การซ้อนทับของชังก์
- Contextual Retrieval ปรับปรุงประสิทธิภาพในทุกโมเดล embedding ที่ทดสอบ แต่ระดับการปรับปรุงอาจแตกต่างกันตามโมเดล
- พรอมป์ทั่วไปที่ให้มาทำงานได้ดี แต่สามารถได้ผลดีกว่าด้วย พรอมป์ contextualizer แบบปรับแต่งเฉพาะ ให้เข้ากับโดเมนหรือ use case
- เช่น รวม glossary ของคำสำคัญที่นิยามไว้เฉพาะในเอกสารอื่นของฐานความรู้
- การใส่ชังก์จำนวนมากขึ้นใน context window เพิ่มโอกาสที่จะมีข้อมูลที่เกี่ยวข้อง
- แต่ยิ่งมีข้อมูลมาก โมเดลอาจเสียสมาธิได้ จึงมีข้อจำกัด
- จากการลองส่ง 5, 10 และ 20 ชังก์ พบว่า 20 ชังก์ให้ประสิทธิภาพดีที่สุด
- ใน use case จริงจำเป็นต้องทดลอง
- ในการสร้างคำตอบ การส่งชังก์ที่มีบริบทให้โมเดล และแยกให้ชัดเจนว่าอะไรคือบริบทและอะไรคือชังก์เดิม อาจช่วยปรับปรุงผลลัพธ์ได้
- ต้องทำการประเมินเสมอ
ปรับปรุงเพิ่มเติมด้วยการจัดอันดับใหม่
- การจัดอันดับใหม่ เป็นเทคนิคกรองในฐานความรู้ขนาดใหญ่ โดยส่งต่อให้โมเดลเฉพาะชังก์ที่เกี่ยวข้องที่สุดจากกลุ่มชังก์ผู้สมัครที่ค้นพบครั้งแรก
- ขั้นตอนนี้ลดปริมาณข้อมูลที่โมเดลต้องประมวลผล และอาจส่งผลต่อคุณภาพคำตอบ ต้นทุน และ latency
- ขั้นตอนมีดังนี้
- ดึงชังก์อันดับต้น ๆ ที่อาจเกี่ยวข้องจากการค้นหาขั้นต้น
- ในการทดลองใช้ top 150
- ส่งชังก์ top-N และคำถามของผู้ใช้ไปยังโมเดลจัดอันดับใหม่
- โมเดลจัดอันดับใหม่ให้คะแนนความเกี่ยวข้องและความสำคัญแก่แต่ละชังก์
- เลือกชังก์ top-K
- ในการทดลองใช้ top 20
- ใส่ชังก์ที่เลือกลงในบริบทของโมเดลเพื่อสร้างผลลัพธ์สุดท้าย
- การทดลองทำด้วย Cohere reranker
- มี Voyage reranker เช่นกัน แต่ไม่มีเวลาทดสอบ
- เมื่อเพิ่มขั้นตอนการจัดอันดับใหม่ในหลายโดเมน การค้นหาจะถูกปรับให้เหมาะสมยิ่งขึ้น
- Reranked Contextual Embedding + Contextual BM25 ลดอัตราความล้มเหลวในการค้นหาชังก์ top-20 จาก 5.7% → 1.9% หรือ 67%
สมดุลระหว่างต้นทุนกับ latency
- การจัดอันดับใหม่เพิ่มขั้นตอนระหว่าง runtime จึงเพิ่ม latency เล็กน้อยอย่างหลีกเลี่ยงไม่ได้
- แม้โมเดลจัดอันดับใหม่จะให้คะแนนทุกชังก์แบบขนานได้ ก็ยังต้องพิจารณาผลกระทบต่อ latency และต้นทุน
- การจัดอันดับชังก์ใหม่มากขึ้นอาจทำให้ประสิทธิภาพดีขึ้น แต่ต้นทุนและ latency จะเพิ่มขึ้น
- การจัดอันดับชังก์ใหม่ให้น้อยลงจะลดต้นทุนและ latency แต่การปรับปรุงประสิทธิภาพอาจน้อยลง
- สมดุลที่เหมาะสมต้องหาโดยทดลองการตั้งค่าหลายแบบใน use case เฉพาะ
ผลลัพธ์เมื่อผสานกัน
- เปรียบเทียบการผสานโมเดล embedding, การใช้ BM25 หรือไม่, การใช้ Contextual Retrieval หรือไม่, การใช้การจัดอันดับใหม่หรือไม่ และจำนวนการค้นหา top-K ในหลายประเภทชุดข้อมูล
- สรุปผลลัพธ์มีดังนี้
- Embeddings + BM25 ดีกว่าการใช้ embedding อย่างเดียว
- ในบรรดา embedding ที่ทดสอบ Voyage และ Gemini ดีที่สุด
- การส่งชังก์ top-20 ให้โมเดลมีประสิทธิผลมากกว่า top-10 หรือ top-5
- การเพิ่มบริบทให้ชังก์ช่วยปรับปรุงความแม่นยำในการค้นหาอย่างมาก
- การจัดอันดับใหม่ดีกว่าไม่ใช้การจัดอันดับใหม่
- เพื่อเพิ่มประสิทธิภาพให้มากที่สุด สามารถผสาน Contextual Embeddings ที่ใช้ Voyage หรือ Gemini, Contextual BM25, ขั้นตอนการจัดอันดับใหม่ และการเพิ่มชังก์ 20 ชังก์ลงในพรอมป์
- นักพัฒนาสามารถทดลองแนวทางนี้ได้ด้วย Contextual Retrieval cookbook
1 ความคิดเห็น
ความคิดเห็นจาก Hacker News
กำลังสร้าง RAG สำหรับองค์กร ให้หน่วยงานรัฐอยู่ เมื่อลองทำ A/B test เชิงทดลองด้วยตัวชี้วัด RAGAS พบว่าเมื่อดูจากคำถามประเมินแบบสังเคราะห์ การนำ LLM-based reranking มาต่อท้าย hybrid search (semantic search + vector) ไม่ได้ทำให้เปลี่ยนแปลงมากนัก และ HyDE ทำให้คุณภาพคำตอบกับคุณภาพการค้นหาลดลงอย่างมาก
ยังต้องประเมินด้วย RAGAS เพิ่มเติมจากคำถามของผู้เชี่ยวชาญและคำถามผู้ใช้จริง
ดังนั้นใน production/enterprise RAG การบอกว่า hybrid search มักดีก็ไม่ใช่เรื่องใหม่อะไร แต่ไม่มีวิธีไหนชนะเสมอไป ในกรณีของเรา แค่ใช้ semantic search ของ Azure AI Search เป็นวิธีที่สองควบคู่กับ vector similarity ก็เพียงพอแล้ว ที่อื่น BM25 หรือโมเดลภาษาขนาดเล็กที่ปรับจูนมาเพื่อ post-process คำค้นอาจจะดีกว่า สุดท้ายจึงต้องทดสอบต่อไปตามแต่ละ use case
ต่อไปตั้งใจจะลอง RAPTOR, SelfRAG, agentic RAG, query improvement (การขยายคำค้นและ sub-query), และ GraphRAG
บทเรียนจนถึงตอนนี้คือควรมี baseline กับกลุ่มทดลอง แล้วพยายามหักล้างสมมติฐานว่างด้วยตัวชี้วัดอย่าง RAGAS และคำถาม/คำตอบสำหรับประเมินควรใช้ 3 แบบ ได้แก่ Q&A ที่ผู้เชี่ยวชาญเขียน, คำถามผู้ใช้จริงจาก log, และ Q&A สังเคราะห์ที่สร้างจากเอกสารต้นฉบับ
สิ่งที่ชอบที่สุดในวิธีนี้คือใช้ prompt caching ได้ดี
prompt ที่อยู่ใน cache มักมีค่าใช้จ่ายราว 1/10 ของปกติ ดังนั้นทริกแบบการรันทุก chunk พร้อมกับเอกสารต้นฉบับทั้งฉบับ ซึ่งแต่ก่อนต้นทุนไม่สมเหตุสมผล ตอนนี้ทำได้แล้ว
ด้วยการลดต้นทุนจาก caching น่าจะทำให้เทคนิคดี ๆ แบบนี้เปิดทางได้มากขึ้น
บันทึกเรื่อง contextual retrieval: https://simonwillison.net/2024/Sep/20/introducing-contextual... และบันทึกเรื่อง prompt caching: https://simonwillison.net/2024/Aug/14/prompt-caching-with-cl...
น่าจะเป็นบริบทที่มีประโยชน์ในการกะว่าต้องใช้เงินเท่าไรเพื่อให้ตามโมเดลและฟีเจอร์ล่าสุดทัน
จากมุมมองคนที่มีพื้นฐานด้าน search แบบดั้งเดิม การจำกัด RAG ให้ใช้แค่โมเดล embedding สำเร็จรูปกับ vector search ดูเป็นกลยุทธ์ที่ค่อนข้างไร้เดียงสา Vector search เองไม่ได้ดีขนาดนั้น และถ้าจะปรับปรุงบริบทที่จะส่งให้ LLM ก็ต้องมีกลยุทธ์ information retrieval เพิ่มเติม สิ่งที่ทำอยู่นี่โดยเนื้อแท้ก็คืองานนั้นเอง
Microsoft เคยออก paper เรื่อง Graph RAG ซึ่งผสาน RAG กับ vector search บนฐานของ concept graph ที่สร้างจากการสกัด entity ในข้อมูลดัชนี วิธีนี้ช่วยดึงข้อมูลที่เกี่ยวข้องเชิงบริบทกับ chunk ที่ match ขึ้นมาได้
รู้สึกว่าน่าจะไปได้ไกลพอสมควรแม้ไม่ใช้ vector search ต้นทุนก็ถูกกว่ามากด้วย ใช้แค่ search engine แบบดั้งเดิมกับ query ที่ปรับจูนมาดีก็พอ แน่นอนว่าหัวใจอยู่ที่การ tune query และอาจไม่เหมาะกับกรณีใช้งานทั่วไป แต่กับกรณีเฉพาะทางมากขึ้นก็น่าจะใช้ได้
เพื่อเสริมบริบท แนวทางนี้ไม่ได้ใหม่ขนาดนั้น วิธีทั่วไปอย่างหนึ่งในการปรับปรุงผลลัพธ์ RAG คือใช้ LLM “ขยาย” chunk พื้นฐาน เพื่อเพิ่ม พื้นที่ผิวเชิงความหมาย ที่จะถูก match
ถ้าใช้ HyDE[1] เพื่อทำ query expansion ก็อาจปรับปรุงได้อีก แต่ไม่ได้ดีขึ้นเสมอไป ผมจึงใช้เป็นเส้นทางสำรอง
ไม่ค่อยแน่ใจว่า Anthropic นำเสนออะไรใหม่ในที่นี้ ดู cookbook code ก็แค่แสดงขั้นตอนการสร้างบริบทนั้น และไม่มีการเปลี่ยน API จริง ๆ สำหรับ “contextual retrieval”
สิ่งที่เปลี่ยนคือ prompt caching ที่เปิดตัวเมื่อหนึ่งเดือนก่อน ซึ่งทำให้สามารถให้เอกสารยาวทั้งฉบับเป็นบริบท เพื่อใส่บริบทที่ดีกว่าให้ chunk แต่ละชิ้นได้ในราคาถูกมาก ยอมรับว่า caching เป็นฟีเจอร์ยอดเยี่ยมที่เหมาะจะเปิดให้ developer และมีคุณค่าจริง
แต่นอกเหนือจากนั้น ดูเหมือนจะเป็นแค่ cookbook ที่สาธิต workflow RAG เฉพาะแบบหนึ่งเท่านั้น
เพิ่มเติมคือ Cohere เป็นหนึ่งใน API ที่ผมชอบที่สุดเท่าที่เคยใช้มา ไม่มีส่วนเกี่ยวข้องด้วย และ Cohere RAG API ก็ดีมากเมื่อเทียบกับ provider รายอื่น แนะนำอย่างยิ่ง
1: https://arxiv.org/abs/2212.10496
ถ้าข้อมูลมี chunk หลายหมื่นชิ้น ก็ต้องทำทั้งหมดนี้ จึงมีต้นทุนสูง การ cache เอกสารช่วยลดต้นทุนนั้นได้
ไม่ค่อยเข้ากับความต้องการ RAG ของผม และคิดว่าส่วนใหญ่ก็น่าจะเหมือนกัน เพราะ query อาจถูกเรียกใช้เดือนหน้าหรืออีก 1 ปีข้างหน้าก็ได้ ดูเหมือนนโยบายนี้ก็ไม่ได้เปลี่ยนไป จึงค่อนข้างแปลกใจที่พูดถึง Prompt Caching ในบริบทของ RAG
เราก็ทำอะไรคล้าย ๆ กันอยู่เหมือนกัน ก่อนอื่นจะแบ่งเอกสารเป็นชังก์ตามหัวข้อ h1, h2, h3 แล้วแนบเฮดเดอร์ไว้ที่ต้นชังก์เป็น บริบท
ยกตัวอย่างสมมติ ถ้าชังก์เดิมคือ “ขนาดยาทั่วไปสำหรับผู้ใหญ่คือยาเม็ดหรือแคปซูล 200mg 1–2 เม็ด วันละ 3 ครั้ง” ตอนนี้ก็จะเป็นรูปแบบที่มี
# Fever,## Treatmentแล้วตามด้วยเส้นคั่น ก่อนใส่เนื้อหาเดิมดูเหมือนจะทำงานได้ค่อนข้างดี และตอนทำดัชนีเอกสารก็ไม่จำเป็นต้องใช้ LLM ด้วย
นี่อาจเป็นที่มาของข้อถกเถียงว่า “ChatGPT ช้าลงในเดือนธันวาคม” ก็ได้ กล่าวคือเมตาดาต้า “วันที่” นั้นอาจบอก ChatGPT ในแบบที่ทำให้มันช่วยได้น้อยลง
ขั้นแรกสรุปแต่ละหน้า ตั้งชื่อ และดึงรายการหัวข้อย่อยออกมา จากนั้นรวมสรุปทั้งหมดแล้วขอให้โมเดลสร้างดัชนีแบบลำดับชั้น โมเดลจะจัดทั้งชุดให้เป็นต้นไม้ และตอนมีคำถามก็จะรวมพาธในต้นไม้เป็นบริบทเพิ่มเติม
ผมไม่ค่อยชอบเทคนิคนี้เท่าไร เห็นด้วยว่าสถานการณ์ที่ยกมาเป็นปัญหาที่พบบ่อย แต่โซลูชันที่เสนอรู้สึกฝืน ๆ
เวกเตอร์ embedding มีคุณสมบัติคล้าย การบีบอัดแบบถุงคำ และอาจถูกทำดัชนีมากเกินไปกับบล็อกข้อความก่อนขึ้นบรรทัดใหม่อันแรก ผลคือบางอินเด็กซ์ของเวกเตอร์จะเข้าใกล้ 0 มากกว่าที่ควร พอผ่านการ quantization สุดท้ายก็อาจกลายเป็น 0 ทำให้เสียความแม่นยำของเวกเตอร์หนาแน่นไปมาก การค้นหาแบบ IDF ช่วยชดเชยได้บ้าง แต่ยังไม่พอ
ถ้า “บูสต์เชิงความหมาย” ให้ embedding ขยับเข้าใกล้ชื่อเอกสาร สรุป บทคัดย่อ ฯลฯ มากขึ้น ก็จะได้ข้อดีด้าน recall ของคำนำหน้า “บริบท” นี้ โดยไม่ทำให้เวกเตอร์พื้นฐานปนเปื้อน ในเชิงการทำงานคือ weighted sum ตอนขั้นตอน augmentation หากเอกสารแมตช์เมื่อใส่ใน context window ก็สามารถฉีดชังก์สรุปเข้าไปพร้อมกันได้ด้วย โดยส่วนตัวผมคิดว่านี่เป็นวิธีแก้ที่สะอาดกว่ามาก
คำอธิบาย “semantic boost” ของ Trieve API[1]:
semantic_boost: มีประโยชน์สำหรับขยับเวกเตอร์ embedding ของชังก์ไปในทิศทางของวลีระยะทาง เช่น หากchunk_htmlเป็นiphoneก็สามารถใช้flagshipเป็นdistance_phraseและ0.25เป็นdistance_factorเพื่อผลักให้เข้าใกล้คำว่า “flagship” มากขึ้น 25% ในเชิงแนวคิดคือการลากเส้นระยะยูคลิด/L2 ระหว่างเวกเตอร์innerTextของchunk_htmlกับเวกเตอร์distance_phraseแล้วขยับเวกเตอร์chunk_htmlไปตามเส้นนั้นให้เข้าใกล้หรือไกลขึ้นเป็นระยะdistance_factorL2Distance[1]:https://docs.trieve.ai/api-reference/chunk/create-or-upsert-...
ถ้าอย่างนั้นก็หมายความว่า vector DB จะผูกกับ LLM ตัวเดียว หรือแม้แต่เวอร์ชันเดียวอย่าง Claude-3.5 Sonnet และย้ายไป 3.5 Haiku หรือ Opus ก็ไม่ได้ ถ้าจะไป ChatGPT หรือ Llama ก็ต้องทำดัชนีใหม่ใช่ไหม?
เทคนิคที่ผมมองว่ามีประโยชน์ที่สุดคือการทำ กลยุทธ์ linked list ที่ชังก์มีพอยน์เตอร์หลายตัวไปยังรายการที่อ้างอิงถึงตัวมันเอง งานนี้ทำด้วยมือ แต่ทำให้ความหลากหลายของวิธีอ้างถึงโหนดหนึ่ง ๆ เพิ่มขึ้นมาก
มองอีกแบบก็เหมือนคอมเมนต์ คอมเมนต์ทั้งหมดใต้โพสต์นี้ถือเป็นพอยน์เตอร์ที่ชี้กลับไปยังโพสต์ต้นฉบับได้ บางคอมเมนต์มีระยะทางเชิงความหมายใกล้กับโพสต์ต้นฉบับ บางอันก็ไกลกว่าเพราะการรับรู้ของผู้เขียน แต่ถ้าให้
parent_idกับแต่ละคอมเมนต์ ก็จะเพิ่มเส้นทางเข้าถึงโพสต์ต้นฉบับดูตัวอย่างของเทคนิคนี้ได้ที่นี่ [1] ไม่ต้องพยายามเดาว่าผู้ใช้ปลายทางจะถามอะไร แค่ให้ผู้ใช้พูดออกมา แล้วนำสิ่งนั้นไปทำดัชนีเป็นพอยน์เตอร์ ตัวเลือกในการแทนวัตถุหนึ่ง ๆ มีจำนวนจำกัด แต่บางการแทนก็อยู่ห่างจากความหมายของวัตถุหลักมาก มาก มากทีเดียว
[1] - https://x.com/yourcommonbase/status/1833262865194557505
คำกล่าวที่ว่าในชุดข้อมูลเล็ก ๆ แค่ยัด 200k โทเคนเข้าไปเพื่อให้ได้คำตอบที่ดีที่สุดนั้นไม่ตรงกับประสบการณ์ของผม
ผมเห็นบ่อยว่าพรอมป์ตยิ่งใหญ่ ผลลัพธ์ยิ่งมีความสม่ำเสมอน้อยลง และการทำตามคำสั่งก็แย่ลงด้วย ดูเหมือนว่าสิ่งนี้จะเกิดขึ้นแม้ในช่วงที่น้อยกว่า 25k โทเคน มาก ๆ ด้วยซ้ำ อยากรู้ว่าคนอื่นเจอเหมือนกันไหม และมีวิธีที่เป็นที่รู้จักกันดีในการหลีกเลี่ยงเรื่องนี้หรือเปล่า
น่าสนใจ ปัญหาที่ผมเจอคือการใช้ RAG เพื่อค้นหา กฎ ที่นำไปใช้ได้ ไม่ใช่ชังก์ความรู้ ต้องฉีดเข้าไปในบริบทเฉพาะกฎที่สามารถนำไปใช้กับบริบทนั้นได้เท่านั้น
ยังไม่ได้ทดลอง แต่ผมคิดว่าวิธีฝึกตัวจำแนกขนาดเล็กให้ตัดสินว่ากฎใดกฎหนึ่งสามารถนำไปใช้ได้หรือไม่น่าจะเวิร์ก ส่วน LLM หลักจะรับบทตัดสินว่ากฎนั้นนำไปใช้ได้จริงในบริบทปัจจุบันหรือไม่
ตัวอย่างเช่น สมมติว่าเราเล่นเกมดันเจี้ยนแบบผู้ใช้หลายคนด้วย LLM ก่อนหน้านี้ตัวละครเคยทำเรื่องไม่ดีเกี่ยวกับแท็กซี่ จนเกมสร้างกฎว่า “ทุกครั้งที่พยายามขึ้นแท็กซี่จะถูกไล่ลง ‘เรารู้ว่าคุณเป็นใคร และจะไม่รับคุณเป็นลูกค้าจนกว่าคุณจะขอโทษกรรมการบริษัทแท็กซี่อย่างเป็นทางการ’” ถ้าขอโทษแล้วกฎก็จะถูกลบออก กรรมการบริษัทแท็กซี่อาจเป็นผู้เล่นคนอื่น หรืออาจเป็นคนที่เริ่มเรียกใช้กฎซึ่งจะถูกบังคับใช้โดยกองรถแท็กซี่ NPC ของตัวเองก็ได้
ผมสงสัยว่าสิ่งนี้จะสเกลได้แค่ไหนเมื่อวัดจากจำนวนกฎที่ทำงานอยู่ และจะประยุกต์ RAG แบบดั้งเดิมได้มากเพียงใด งานตัดสินว่ากฎนำไปใช้ได้หรือไม่ดูเหมือนเป็นปัญหาที่เป็นนามธรรมและยากกว่าการตัดสินว่าชังก์ความรู้เกี่ยวข้องหรือไม่
โดยเฉพาะแกนสำคัญที่ทำให้ยากขึ้นคือ dependency loop ซึ่งไม่มีในการค้นหาความรู้ การจะระบุว่ากฎนำไปใช้ได้หรือไม่ ต้องค้นหากฎนั้นขึ้นมาก่อน จะแก้ปัญหานี้ได้อย่างไร?
ตัวอย่างคิวรี ถ้าเขียนโดยอาศัยความช่วยเหลือจาก LLama 3.1 8B ก็สามารถเขียนให้ละเอียดพอได้ เช่น กองทัพดาร์กเอลฟ์กำลังใกล้เข้ามา Grimgold Ironfist อยู่ในสถานการณ์คับขัน อดีตเคยเป็นสมาชิกผู้ภาคภูมิใจของกองกำลังอาสาคนแคระ แต่ตอนนี้พลังชีวิตเหลือ 35% ในอินเวนทอรีมีพลั่วเก่าคร่ำคร่า ถังน้ำ ขนมปังเก่า และเหรียญทอง 17 เหรียญ และแม้จะมี “อดีตที่มีปัญหา” กับกิลด์แท็กซี่ ก็ยังพยายามเรียกแท็กซี่บนถนน
ตัวอย่างกฎที่จะถูกดึงจาก vector store จะถูกค้นเจอเพราะเกิดความใกล้เคียงเชิงเวกเตอร์จากการกล่าวถึงชื่อตัวละคร/คุณสมบัติ รวมถึงแท็กซี่และ Taxi Guild
เป็นกฎทำนองว่า “Taxi Guild ได้กำหนดบทลงโทษอย่างเข้มงวดต่อ Grimgold ทุกครั้งที่เขาพยายามเรียกแท็กซี่ เขาจะถูกไล่ออกจากรถทันที ในกฤษฎีกาของ Guild ระบุว่า ‘Grimgold Ironfist คนแคระมีเคราชื่อเสีย จะไม่ได้รับอนุญาตให้นั่งแท็กซี่ใดๆ ที่สมาชิกดำเนินการอยู่ จนกว่าเขาจะขอโทษ Thorgrim Stonebeard กรรมการของ Golden Horse Cab Company อย่างเป็นทางการ หากไม่ปฏิบัติตาม จะถูกแบนถาวรจากบริการของเรา’”
ที่บอกว่า “ถ้าฐานความรู้มีขนาดเล็กกว่า 200,000 โทเค็น (ประมาณ 500 หน้า)” ผมอยากให้ Anthropic เปิดเผย tokenizer ออกมาเลย จะได้ไม่ต้องเดา
กำลังรอวันที่ทั้งวงการ AI หมุนกลับมาครบรอบแล้วสุดท้ายกลับไปใช้ TF-IDF อยู่