การแบ่งส่วนเชิงความหมายด้วยความคล้ายคลึงของเวกเตอร์ฝัง
สร้างการแบ่งส่วนเชิงความหมายที่ตัดข้อความ ณ จุดซึ่งมีระยะห่างทางความหมายสูงสุดระหว่างประโยคต่อเนื่อง โดยคงเนื้อหาที่อยู่ในประเด็นเดียวกันไว้ด้วยกัน
การแบ่งส่วนเชิงความหมายด้วยความคล้ายคลึงของเวกเตอร์ฝัง เป็นบทเรียน AI Engineering Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน AI Engineering Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส AI Engineering Academy มีบทเรียนทั้งหมด 4 บทเรียน
การแบ่งส่วนเชิงความหมายคืออะไร
การแบ่งส่วนเชิงความหมาย คือเทคนิคที่แบ่งข้อความตรงจุดที่หัวข้อเปลี่ยนแปลงอย่างมีนัยสำคัญ แทนที่จะใช้จำนวนอักขระตายตัว แทนที่จะถามว่า 'ครบ 500 โทเค็นหรือยัง' วิธีนี้จะถามว่า 'ประโยคถัดไปอยู่ในหัวข้อเดียวกับส่วนปัจจุบันหรือไม่' — โดยใช้ความคล้ายคลึงของการฝังเพื่อตอบคำถามนั้น
แนวคิดหลัก: ระยะห่างของการฝัง
อัลกอริทึมทำงานโดยฝังประโยคแต่ละประโยค (หรือกลุ่มประโยคขนาดเล็ก) แล้วคำนวณความคล้ายคลึงโคไซน์ระหว่างการฝังของประโยคที่อยู่ติดกัน เมื่อความคล้ายคลึงลดลงอย่างรวดเร็ว ซึ่งหมายความว่าหัวข้อเปลี่ยนไป อัลกอริทึมจะแทรกขอบเขตส่วน ประโยคที่กล่าวถึงแนวคิดเดียวกันจะอยู่รวมกันในส่วนเดียว
ขั้นตอนที่ 1: การฝังระดับประโยค
ขั้นตอนแรกคือแบ่งเอกสารออกเป็นประโยคแต่ละประโยคโดยใช้ตัวแยกประโยค จากนั้นฝังแต่ละประโยคด้วยโมเดลการฝังที่รวดเร็ว คุณต้องใช้การฝังระดับประโยค ไม่ใช่ระดับเอกสาร เพื่อให้ตรวจจับการเปลี่ยนหัวข้อเฉพาะที่ขณะเคลื่อนผ่านข้อความได้
from openai import OpenAI
from nltk.tokenize import sent_tokenize
import numpy as np
client = OpenAI()
def embed_sentences(text):
sentences = sent_tokenize(text)
response = client.embeddings.create(
model='text-embedding-3-small',
input=sentences
)
vectors = [item.embedding for item in response.data]
return sentences, np.array(vectors)ขั้นตอนที่ 2: การคำนวณความคล้ายคลึงของประโยคที่อยู่ติดกัน
เมื่อมีการฝังประโยคแล้ว ให้คำนวณความคล้ายคลึงโคไซน์ระหว่างแต่ละคู่ที่อยู่ติดกัน ได้แก่ ประโยคที่ i และประโยคที่ i+1 ผลลัพธ์คือรายการคะแนนความคล้ายคลึง โดยมีหนึ่งคะแนนต่อขอบเขตประโยค คะแนนต่ำบ่งชี้ว่าประโยคที่อยู่ติดกันกล่าวถึงคนละหัวข้อ จุดเหล่านี้คือจุดแบ่งที่เป็นไปได้
def cosine_similarity_adjacent(vectors):
similarities = []
for i in range(len(vectors) - 1):
a = vectors[i]
b = vectors[i + 1]
sim = np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))
similarities.append(sim)
return similaritiesขั้นตอนที่ 3: การตรวจหาจุดแบ่ง
จุดแบ่ง คือขอบเขตประโยคที่ความคล้ายคลึงลดลงต่ำกว่าเกณฑ์ คุณสามารถใช้เกณฑ์ตายตัว (เช่น 0.6) หรือเกณฑ์ตามเปอร์เซ็นไทล์ที่ปรับตามเอกสารได้ เช่น แบ่งทุกครั้งที่ความคล้ายคลึงต่ำกว่าเปอร์เซ็นไทล์ที่ 25 ของคะแนนความคล้ายคลึงทั้งหมดในเอกสารนั้น
def find_breakpoints(similarities, percentile=25):
threshold = np.percentile(similarities, percentile)
breakpoints = []
for i, sim in enumerate(similarities):
if sim < threshold:
breakpoints.append(i + 1) # split AFTER sentence i
return breakpointsขั้นตอนที่ 4: การประกอบส่วน
เมื่อระบุจุดแบ่งแล้ว คุณสามารถประกอบส่วนต่าง ๆ โดยเชื่อมประโยคที่อยู่ติดกันระหว่างจุดแบ่งแต่ละจุด แต่ละส่วนที่ได้จะมีลำดับประโยคที่สอดคล้องกันและกล่าวถึงหัวข้อเดียวกัน ขอบเขตของส่วนจะสอดคล้องกับการเปลี่ยนหัวข้อตามธรรมชาติในเอกสารต้นฉบับ
def assemble_chunks(sentences, breakpoints):
chunks = []
start = 0
for bp in breakpoints:
chunk = ' '.join(sentences[start:bp])
chunks.append(chunk)
start = bp
chunks.append(' '.join(sentences[start:])) # last chunk
return chunksตัวอย่างตัวแบ่งเชิงความหมายฉบับเต็ม
เมื่อนำทุกอย่างมารวมกันเป็นฟังก์ชันเดียว: ฝังประโยค คำนวณความคล้ายคลึงของประโยคที่อยู่ติดกัน ค้นหาจุดแบ่ง และประกอบส่วน ผลลัพธ์คือรายการกลุ่มข้อความที่สอดคล้องกันในเชิงความหมาย พร้อมสำหรับการฝังเป็นส่วนทั้งหมดและจัดเก็บในฐานข้อมูลเวกเตอร์
def semantic_chunk(text, percentile=25):
sentences, vectors = embed_sentences(text)
similarities = cosine_similarity_adjacent(vectors)
breakpoints = find_breakpoints(similarities, percentile)
chunks = assemble_chunks(sentences, breakpoints)
return chunks
chunks = semantic_chunk(my_document)
print(f'Produced {len(chunks)} semantic chunks')
for i, c in enumerate(chunks):
print(f'Chunk {i+1}: {len(c)} chars')การเลือกเกณฑ์เปอร์เซ็นไทล์
เกณฑ์เปอร์เซ็นไทล์จะควบคุมระดับความละเอียดของส่วน เปอร์เซ็นไทล์ต่ำ (เช่น ลำดับที่ 10) หมายความว่าจะแบ่งเฉพาะเมื่อหัวข้อเปลี่ยนอย่างมาก จึงได้ส่วนน้อยลงแต่ยาวขึ้น เปอร์เซ็นไทล์สูง (เช่น ลำดับที่ 40) จะแบ่งถี่ขึ้น จึงได้ส่วนเล็กจำนวนมากที่เน้นประเด็นอย่างมาก ปรับค่านี้โดยอิงกับชุดประเมิน hit rate ของการค้นคืน
LangChain SemanticChunker
LangChain มี SemanticChunker ในตัวซึ่งใช้อัลกอริทึมนี้ โดยรับโมเดลการฝังและชนิดเกณฑ์จุดแบ่ง วิธีนี้ช่วยให้คุณไม่ต้องเขียนอัลกอริทึมตั้งแต่ต้น และผสานการทำงานโดยตรงกับตัวโหลดเอกสารและคลังเวกเตอร์ของ LangChain
from langchain_experimental.text_splitter import SemanticChunker
from langchain_openai import OpenAIEmbeddings
embeddings = OpenAIEmbeddings(model='text-embedding-3-small')
chunker = SemanticChunker(
embeddings,
breakpoint_threshold_type='percentile',
breakpoint_threshold_amount=25
)
chunks = chunker.create_documents([long_document_text])
print(f'{len(chunks)} semantic chunks created')ข้อแลกเปลี่ยนเมื่อเทียบกับการแบ่งส่วนขนาดตายตัว
การแบ่งส่วนเชิงความหมายให้ส่วนที่มีคุณภาพสูงกว่าและมีความสอดคล้องของหัวข้อดีกว่า แต่มีค่าใช้จ่ายสูงกว่า: ต้องฝังทุกประโยคเพียงเพื่อกำหนดขอบเขตส่วน ก่อนที่ส่วนต่าง ๆ จะถูกจัดทำดัชนีเสียอีก สำหรับเอกสาร 100 หน้า นี่หมายถึงการเรียกใช้การฝังหลายพันครั้งเพื่อการแบ่งส่วนเพียงอย่างเดียว ใช้การแบ่งส่วนเชิงความหมายเมื่อคุณให้ความสำคัญกับคุณภาพการค้นคืนมากกว่าความเร็วในการจัดทำดัชนี
ควรใช้การแบ่งส่วนเชิงความหมายเมื่อใด
การแบ่งส่วนเชิงความหมายเหมาะอย่างยิ่งกับเนื้อหาแบบเรื่องเล่ายาว เช่น บล็อก งานวิจัย เอกสารทางกฎหมาย และหนังสือ ซึ่งหัวข้อเปลี่ยนไปตามธรรมชาติ แต่จำเป็นน้อยกว่าสำหรับเอกสารที่มีโครงสร้างชัดเจน เช่น แค็ตตาล็อกสินค้า รายการ FAQ หรือไฟล์โค้ด ซึ่งเหมาะกับตัวแบ่งที่คำนึงถึงเอกสารและเคารพโครงสร้างโดยตรงมากกว่า
ตรวจสอบความเข้าใจอย่างรวดเร็ว
ทดสอบความเข้าใจเกี่ยวกับการแบ่งส่วนเชิงความหมายจากบทเรียนนี้
สรุปบทเรียน
ในบทเรียนนี้ คุณได้เรียนรู้ว่า การแบ่งส่วนเชิงความหมายใช้ความคล้ายคลึงของการฝังเพื่อตรวจจับการเปลี่ยนหัวข้อ เกณฑ์เปอร์เซ็นไทล์ควบคุมระดับความละเอียด และ SemanticChunker ของ LangChain ใช้งานอัลกอริทึมนี้ได้ทันที ต่อไปเราจะสำรวจการแบ่งส่วนแบบแม่-ลูก ซึ่งผสานส่วนขนาดเล็กที่แม่นยำเข้ากับข้อความแม่ขนาดใหญ่ที่มีบริบทครบถ้วน
คำถามที่พบบ่อย
บทเรียน “การแบ่งส่วนเชิงความหมายด้วยความคล้ายคลึงของเวกเตอร์ฝัง” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “การแบ่งส่วนเชิงความหมายด้วยความคล้ายคลึงของเวกเตอร์ฝัง” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส AI Engineering Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส AI Engineering Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “การแบ่งส่วนเชิงความหมายด้วยความคล้ายคลึงของเวกเตอร์ฝัง”
สร้างการแบ่งส่วนเชิงความหมายที่ตัดข้อความ ณ จุดซึ่งมีระยะห่างทางความหมายสูงสุดระหว่างประโยคต่อเนื่อง โดยคงเนื้อหาที่อยู่ในประเด็นเดียวกันไว้ด้วยกัน คุณปฏิบัติ AI Engineering Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน AI Engineering Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน AI Engineering Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน
บทเรียน “การแบ่งส่วนเชิงความหมายด้วยความคล้ายคลึงของเวกเตอร์ฝัง” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน AI Engineering Academy นี้ได้ไหม
ได้ บทเรียน AI Engineering Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- เหตุใดการแบ่งส่วนแบบง่ายจึงทำลายการดึงข้อมูล
- การแบ่งส่วนเชิงความหมายด้วยความคล้ายคลึงของเวกเตอร์ฝัง
- การดึงข้อมูลแบบส่วนแม่-ส่วนลูกและจากเล็กไปใหญ่
- กลยุทธ์เฉพาะเอกสารสำหรับโค้ดและ HTML