0Pricing
AI Engineering Academy · บทเรียน

การแบ่งส่วนเชิงความหมายด้วยความคล้ายคลึงของเวกเตอร์ฝัง

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

การแบ่งส่วนเชิงความหมายด้วยความคล้ายคลึงของเวกเตอร์ฝัง เป็นบทเรียน 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 ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. เหตุใดการแบ่งส่วนแบบง่ายจึงทำลายการดึงข้อมูล
  2. การแบ่งส่วนเชิงความหมายด้วยความคล้ายคลึงของเวกเตอร์ฝัง
  3. การดึงข้อมูลแบบส่วนแม่-ส่วนลูกและจากเล็กไปใหญ่
  4. กลยุทธ์เฉพาะเอกสารสำหรับโค้ดและ HTML
← กลับไปที่ AI Engineering Academy