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

กลยุทธ์การแบ่งข้อความยาวเป็นส่วน

แนวทางแบ่งแบบขนาดคงที่ ตามขอบเขตประโยค และตามความหมาย

กลยุทธ์การแบ่งข้อความยาวเป็นส่วน เป็นบทเรียน AI Prompt Engineering ฟรีบน CoddyKit นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน AI Prompt Engineering และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส AI Prompt Engineering มีบทเรียนทั้งหมด 4 บทเรียน

เหตุใดเอกสารยาวจึงเป็นความท้าทาย

LLM มี หน้าต่างบริบท ซึ่งเป็นจำนวนโทเคนสูงสุดที่สามารถประมวลผลได้ในครั้งเดียว GPT-4 รองรับ 128,000 โทเคน และโคลดรองรับ 200,000 โทเคน แต่เอกสารจำนวนมากมีขนาดเกินขีดจำกัดเหล่านี้ ที่สำคัญกว่านั้น งานวิจัยแสดงให้เห็นว่าความแม่นยำของโมเดลมักลดลงเมื่อบริบทยาวมาก การแบ่งเป็นส่วนย่อย คือการแบ่งเอกสารออกเป็นชิ้นเล็กลงก่อนประมวลผล

การแบ่งเป็นส่วนย่อยขนาดคงที่

การแบ่งเป็นส่วนย่อยขนาดคงที่จะแบ่งข้อความทุก ๆ N โทเคน (หรืออักขระ) โดยไม่คำนึงถึงขอบเขตของเนื้อหา นี่เป็นกลยุทธ์ที่ง่ายที่สุดและไม่จำเป็นต้องเข้าใจความหมาย

ขนาดส่วนย่อยที่ใช้โดยทั่วไป: 500–1,000 โทเคน ส่วนย่อยเหล่านี้จัดทำดัชนีและดึงข้อมูลได้ง่าย แต่ประโยคอาจถูกตัดกลางคัน ทำให้ความหมายบริเวณขอบเขตสูญหาย

import tiktoken

def fixed_chunk(text, max_tokens=1000):
    enc = tiktoken.get_encoding('cl100k_base')
    tokens = enc.encode(text)
    chunks = []
    for i in range(0, len(tokens), max_tokens):
        chunk_tokens = tokens[i:i + max_tokens]
        chunks.append(enc.decode(chunk_tokens))
    return chunks

chunks = fixed_chunk(long_document)
print(f'Total chunks: {len(chunks)}')

ข้อแลกเปลี่ยนของการแบ่งเป็นส่วนย่อยขนาดคงที่

ข้อดี:

  • นำไปใช้งานได้ง่าย — ไม่ต้องใช้การประมวลผลภาษาธรรมชาติ
  • ขนาดส่วนย่อยคาดการณ์ได้ — จัดการค่าใช้จ่ายของส่วนเชื่อมต่อโปรแกรมได้ง่ายกว่า
  • ประมวลผลได้รวดเร็ว

ข้อเสีย:

  • ตัดข้ามขอบเขตประโยคและย่อหน้า
  • ประโยคที่ถูกแบ่งข้ามส่วนย่อยจะสูญเสียบริบทเมื่อดึงข้อมูล
  • ไม่เหมาะกับการสรุป — ส่วนย่อยอาจจบลงกลางข้อโต้แย้ง

การแบ่งเป็นส่วนย่อยตามขอบเขตประโยค

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

ใช้เครื่องตัดแบ่งประโยค (spaCy หรือ NLTK) เพื่อตรวจหาขอบเขต จากนั้นจัดกลุ่มประโยคจนกว่าส่วนย่อยจะมีขนาดถึงเป้าหมาย

import spacy

nlp = spacy.load('en_core_web_sm')

def sentence_chunk(text, max_tokens=1000):
    doc = nlp(text)
    sentences = [sent.text.strip() for sent in doc.sents]
    chunks, current, count = [], [], 0
    for sent in sentences:
        word_count = len(sent.split())
        if count + word_count > max_tokens and current:
            chunks.append(' '.join(current))
            current, count = [], 0
        current.append(sent)
        count += word_count
    if current:
        chunks.append(' '.join(current))
    return chunks

การแบ่งเป็นส่วนย่อยตามความหมาย

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

เมื่อความคล้ายคลึงลดลงต่ำกว่าเกณฑ์ ให้แทรกขอบเขตของส่วนย่อย วิธีนี้ทำให้ได้ส่วนย่อยที่มีเนื้อหาเป็นกลุ่มหัวข้อเดียวกัน เหมาะอย่างยิ่งสำหรับการสร้างแบบเสริมด้วยการดึงข้อมูล (RAG)

from sentence_transformers import SentenceTransformer
from sklearn.metrics.pairwise import cosine_similarity
import numpy as np

model = SentenceTransformer('all-MiniLM-L6-v2')

def semantic_chunk(sentences, threshold=0.75):
    embeddings = model.encode(sentences)
    chunks, current = [], [sentences[0]]
    for i in range(1, len(sentences)):
        sim = cosine_similarity(
            [embeddings[i-1]], [embeddings[i]]
        )[0][0]
        if sim < threshold:
            chunks.append(' '.join(current))
            current = []
        current.append(sentences[i])
    if current:
        chunks.append(' '.join(current))
    return chunks

การเปรียบเทียบกลยุทธ์ทั้งสาม

ต่อไปนี้คือการเปรียบเทียบแบบเคียงข้างกันเพื่อช่วยให้คุณเลือก:

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

ในทางปฏิบัติ การแบ่งเป็นส่วนย่อยตามความหมายเพิ่มความหน่วงเนื่องจากต้องคำนวณการฝังเวกเตอร์ ให้เลือกตามข้อกำหนดด้านความแม่นยำของการดึงข้อมูล

การแบ่งเป็นส่วนย่อยสำหรับงานดึงข้อมูล

สำหรับ การสร้างแบบเสริมด้วยการดึงข้อมูล (RAG) ส่วนย่อยจะกลายเป็นหน่วยของการค้นหา คำค้นของผู้ใช้จะถูกแปลงเป็นเวกเตอร์ จากนั้นจึงดึงส่วนย่อยที่คล้ายกันมากที่สุดมาใส่ในพรอมต์

ส่วนย่อยขนาดเล็ก (200–400 โทเคน) ช่วยเพิ่มความแม่นยำในการดึงข้อมูล — แต่ละส่วนย่อยมีแนวคิดหลักเพียงหนึ่งเรื่อง ส่วนย่อยขนาดใหญ่ (800–1,000 โทเคน) ให้บริบทมากกว่า แต่อาจมีเนื้อหาที่ไม่เกี่ยวข้องปะปนกับข้อความที่เกี่ยวข้อง

import openai
import numpy as np

client = openai.OpenAI(api_key='sk-...')

def embed(text):
    resp = client.embeddings.create(
        model='text-embedding-3-small',
        input=text
    )
    return np.array(resp.data[0].embedding)

def retrieve(query, chunks, top_k=3):
    q_emb = embed(query)
    scores = [(i, np.dot(q_emb, embed(c))) for i, c in enumerate(chunks)]
    scores.sort(key=lambda x: x[1], reverse=True)
    return [chunks[i] for i, _ in scores[:top_k]]

การแบ่งเป็นส่วนย่อยสำหรับงานสรุป

สำหรับ การสรุป ส่วนย่อยควรมีขนาดใหญ่พอที่จะครอบคลุมข้อโต้แย้งหรือส่วนเนื้อหาหนึ่งส่วนได้อย่างครบถ้วน ส่วนย่อยตามขอบเขตประโยคขนาด 600–800 โทเคนทำงานได้ดี

แต่ละส่วนย่อยจะถูกสรุปแยกกัน (ขั้นตอน แมป) จากนั้นจึงรวมบทสรุปเข้าด้วยกันเป็นบทสรุปสุดท้าย (ขั้นตอน ลดรูป) นี่คือรูปแบบ แมป-ลดรูป แบบดั้งเดิม ซึ่งจะกล่าวถึงในบทเรียนถัดไป

การซ้อนทับ: เชื่อมขอบเขตของส่วนย่อย

เทคนิคที่ใช้ได้จริงเพื่อลดข้อผิดพลาดบริเวณขอบเขตคือการเพิ่ม การซ้อนทับ ระหว่างส่วนย่อย โดยทำซ้ำโทเคน 100–200 รายการสุดท้ายของส่วนย่อย N ไว้ที่จุดเริ่มต้นของส่วนย่อย N+1

การซ้อนทับช่วยให้ประโยคที่พาดผ่านขอบเขตปรากฏครบถ้วนในส่วนย่อยอย่างน้อยหนึ่งส่วน วิธีนี้สำคัญอย่างยิ่งสำหรับการดึงข้อมูล เพราะคำค้นเกี่ยวกับหัวข้อที่พาดผ่านขอบเขตจะตรงกับส่วนย่อยที่มีการซ้อนทับ

def fixed_chunk_with_overlap(text, max_tokens=1000, overlap=200):
    enc = tiktoken.get_encoding('cl100k_base')
    tokens = enc.encode(text)
    chunks = []
    step = max_tokens - overlap
    for i in range(0, len(tokens), step):
        chunk_tokens = tokens[i:i + max_tokens]
        chunks.append(enc.decode(chunk_tokens))
        if i + max_tokens >= len(tokens):
            break
    return chunks

การเพิ่มข้อมูลกำกับให้แต่ละส่วนย่อย

แต่ละส่วนย่อยควรมี ข้อมูลกำกับ เพื่อให้ขั้นตอนถัดไปสามารถอ้างอิงแหล่งที่มาได้:

  • source: ชื่อไฟล์หรือที่อยู่เว็บ
  • page: หมายเลขหน้า
  • chunk_index: ตำแหน่งในเอกสาร
  • section: บทหรือหัวข้อ

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

def chunk_with_metadata(text, source='doc.pdf', page=1):
    chunks = fixed_chunk_with_overlap(text)
    return [
        {
            'text': chunk,
            'metadata': {
                'source': source,
                'page': page,
                'chunk_index': i
            }
        }
        for i, chunk in enumerate(chunks)
    ]

การเลือกกลยุทธ์ที่เหมาะสม

แนวทางตัดสินใจอย่างรวดเร็ว:

  • ให้ความสำคัญกับความเร็ว และเนื้อหาเป็นร้อยแก้ว: การแบ่งเป็นส่วนย่อยตามขอบเขตประโยค
  • ความแม่นยำในการดึงข้อมูลเป็นสิ่งสำคัญอย่างยิ่ง: การแบ่งเป็นส่วนย่อยตามความหมายโดยใช้ส่วนย่อยขนาดเล็ก (300 โทเคน)
  • การสรุปหนังสือหรือรายงาน: แบ่งตามขอบเขตประโยค ใช้ส่วนย่อยขนาดใหญ่ (800 โทเคน) และใช้การแมป-ลดรูป
  • เอกสารกฎหมายหรือเอกสารทางเทคนิค: แบ่งเป็นส่วนย่อยตามความหมายเพื่อให้ข้อกำหนดอยู่รวมกัน

ให้วัดค่าการเรียกคืนของการดึงข้อมูลกับชุดคำค้นที่เป็นตัวแทนก่อนตัดสินใจใช้กลยุทธ์ใดกลยุทธ์หนึ่งเสมอ

ตรวจสอบความรู้

กลยุทธ์การแบ่งข้อความใดจะแบ่งข้อความเมื่อความคล้ายคลึงแบบโคไซน์ระหว่างเวกเตอร์ฝังตัวของประโยคที่อยู่ติดกันลดลงต่ำกว่าเกณฑ์?

สรุป: กลยุทธ์การแบ่งข้อความ

คุณได้เรียนรู้กลยุทธ์หลักในการแบ่งข้อความสามรูปแบบ:

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

เพิ่มการซ้อนทับระหว่างชิ้นข้อความเพื่อลดข้อผิดพลาดที่ขอบเขต และแนบข้อมูลเมตา (แหล่งที่มา หน้า ดัชนี) ไว้เสมอ เพื่อให้สามารถอ้างอิงและตรวจสอบย้อนกลับได้ บทเรียนถัดไปจะครอบคลุมรูปแบบการสรุปแบบแมป-รีดิวซ์

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

บทเรียน “กลยุทธ์การแบ่งข้อความยาวเป็นส่วน” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “กลยุทธ์การแบ่งข้อความยาวเป็นส่วน” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส AI Prompt Engineering ให้อัปเกรดเป็น CoddyKit PRO คอร์ส AI Prompt Engineering มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “กลยุทธ์การแบ่งข้อความยาวเป็นส่วน”

แนวทางแบ่งแบบขนาดคงที่ ตามขอบเขตประโยค และตามความหมาย คุณปฏิบัติ AI Prompt Engineering ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน AI Prompt Engineering หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน AI Prompt Engineering บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน

บทเรียน “กลยุทธ์การแบ่งข้อความยาวเป็นส่วน” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน AI Prompt Engineering นี้ได้ไหม

ได้ บทเรียน AI Prompt Engineering ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

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

  1. กลยุทธ์การแบ่งข้อความยาวเป็นส่วน
  2. รูปแบบการสรุปแบบ Map-Reduce
  3. การสรุปแบบลำดับชั้น
  4. การรักษาบริบทระหว่างส่วนต่าง ๆ
← กลับไปที่ AI Prompt Engineering