AI Engineering Academy · บทเรียน

กลยุทธ์การอยู่ภายในขอบเขตบริบท

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

บทเรียน 4 จาก 413 ขั้นตอน

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

ปัญหาบทสนทนาที่ขยายตัวขึ้น

ทุกข้อความที่แลกเปลี่ยนกันในบทสนทนาแบบแชตจะเพิ่มจำนวนโทเคนของการเรียกเอพีไอครั้งถัดไป ในเซสชันสนับสนุนลูกค้าที่ยาวนานหรือเซสชันเขียนโค้ดที่กินเวลาหลายชั่วโมง ประวัติบทสนทนาที่สะสมไว้อาจมีมากกว่า 20,000–50,000 โทเคนได้อย่างง่ายดาย และคุณต้องส่งโทเคนทั้งหมดนี้ไปยังเอพีไอในทุกเทิร์น พร้อมจ่ายเงินซ้ำสำหรับโทเคนที่ประมวลผลไปแล้ว

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

กลยุทธ์ที่ 1: หน้าต่างเลื่อน (N ข้อความล่าสุด)

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

import openai

client = openai.OpenAI()

class SlidingWindowConversation:
    def __init__(self, system_prompt, window_size=10):
        self.system = system_prompt
        self.window_size = window_size
        self.history = []

    def chat(self, user_message):
        self.history.append({'role': 'user', 'content': user_message})

        # Keep only the last N messages
        windowed = self.history[-self.window_size:]
        messages = [{'role': 'system', 'content': self.system}] + windowed

        response = client.chat.completions.create(
            model='gpt-4o-mini',
            messages=messages
        )
        reply = response.choices[0].message.content
        self.history.append({'role': 'assistant', 'content': reply})
        print(f'Context: {len(windowed)} messages ({len(self.history)} total)')
        return reply

conv = SlidingWindowConversation('You are a helpful assistant.', window_size=6)
print(conv.chat('Hello! My name is Alice.'))
print(conv.chat('What is the capital of France?'))
print(conv.chat('What is my name?'))  # Might forget if window is small

กลยุทธ์ที่ 2: การตัดตามจำนวนโทเคน

แทนที่จะตัดตามจำนวนข้อความ การตัดตามจำนวนโทเคนจะนำข้อความออกจนกว่าจำนวนโทเคนทั้งหมดจะต่ำกว่าขีดจำกัด วิธีนี้แม่นยำกว่า เพราะข้อความมีความยาวแตกต่างกันมาก ขีดจำกัดจำนวนข้อความอาจรวมข้อความสั้น 10 ข้อความหรือข้อความยาวมาก 3 ข้อความ ซึ่งมีค่าใช้จ่ายด้านโทเคนแตกต่างกันอย่างมาก

import tiktoken

def trim_to_token_budget(
    messages, system_prompt, model='gpt-4o-mini', max_input_tokens=8000
):
    enc = tiktoken.encoding_for_model(model)

    def count(msgs):
        return sum(len(enc.encode(m.get('content',''))) + 4 for m in msgs) + 3

    # System prompt token count
    system_tokens = len(enc.encode(system_prompt)) + 4
    budget = max_input_tokens - system_tokens

    # Trim from the oldest messages until we fit
    trimmed = list(messages)
    while trimmed and count(trimmed) > budget:
        trimmed.pop(0)  # Remove oldest message

    removed = len(messages) - len(trimmed)
    if removed:
        print(f'Trimmed {removed} old messages to stay within {max_input_tokens} tokens')
    return trimmed

กลยุทธ์ที่ 3: การสรุปบทสนทนา

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

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

import openai

client = openai.OpenAI()

def summarize_conversation(messages_to_summarize, model='gpt-4o-mini'):
    summary_prompt = [
        {'role': 'system', 'content': 'You summarize conversations. Be concise but preserve key facts, decisions, and any specific information the user shared (names, numbers, preferences).'},
        {'role': 'user', 'content': 'Summarize this conversation:\n' + '\n'.join(
            f"{m['role'].upper()}: {m['content']}" for m in messages_to_summarize
        )}
    ]
    resp = client.chat.completions.create(model=model, messages=summary_prompt, max_tokens=500)
    return resp.choices[0].message.content

def compress_history(history, keep_recent=4):
    if len(history) <= keep_recent:
        return history
    to_summarize = history[:-keep_recent]
    summary = summarize_conversation(to_summarize)
    summary_msg = {'role': 'system', 'content': f'Earlier conversation summary: {summary}'}
    return [summary_msg] + history[-keep_recent:]

print('Summarization strategy compresses old turns into a single summary message')

กลยุทธ์ที่ 4: หน่วยความจำเอนทิตี

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

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

import openai
import json

client = openai.OpenAI()

def extract_entities(messages, model='gpt-4o-mini'):
    prompt = [
        {'role': 'system', 'content': 'Extract key facts from this conversation as JSON: {"user_name": null, "preferences": [], "key_facts": []}'},
        {'role': 'user', 'content': '\n'.join(f"{m['role']}: {m['content']}" for m in messages)}
    ]
    resp = client.chat.completions.create(
        model=model,
        messages=prompt,
        response_format={'type': 'json_object'}
    )
    return json.loads(resp.choices[0].message.content)

conversation = [
    {'role': 'user', 'content': 'Hi, I am Alice and I prefer Python over JavaScript.'},
    {'role': 'assistant', 'content': 'Great to meet you, Alice! Python is an excellent choice.'},
    {'role': 'user', 'content': 'I am building a REST API for my e-commerce startup.'}
]
entities = extract_entities(conversation)
print(json.dumps(entities, indent=2))

เมื่อใดควรใช้แต่ละกลยุทธ์

เลือกกลยุทธ์ตามลักษณะของแอปพลิเคชัน:

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

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

RAG เป็นทางเลือกแทนการยัดข้อมูลลงในบริบท

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

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

การจัดการข้อผิดพลาดบริบทสูงสุดอย่างเหมาะสม

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

import openai
import tiktoken

client = openai.OpenAI()

def chat_with_context_guard(messages, model='gpt-4o-mini', max_tokens=100000):
    enc = tiktoken.encoding_for_model(model)
    total = sum(len(enc.encode(m.get('content',''))) + 4 for m in messages) + 3

    while total > max_tokens and len(messages) > 2:
        # Remove the second message (keep system prompt)
        removed = messages.pop(1)
        total -= len(enc.encode(removed.get('content',''))) + 4
        print(f'Trimmed a message. New total: {total} tokens')

    try:
        return client.chat.completions.create(model=model, messages=messages)
    except openai.BadRequestError as e:
        if 'context_length' in str(e):
            return {'error': 'Message history too long. Please start a new conversation.'}
        raise

การคงบริบทข้ามเซสชัน

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

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

การติดตามการเติบโตของบริบทในระบบที่ใช้งานจริง

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

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

การผสานกลยุทธ์: รูปแบบสำหรับระบบที่ใช้งานจริง

ระบบจัดการบริบทสำหรับการใช้งานจริงที่แข็งแกร่งจะผสานหลายกลยุทธ์เป็นชั้น ๆ:

  1. ก่อนประกอบบริบท: ตรวจสอบงบประมาณโทเคนและบันทึกไว้
  2. ใช้การแยกเอนทิตี: แทรกบล็อกหน่วยความจำแบบมีโครงสร้างที่มีข้อเท็จจริงสำคัญ
  3. เพิ่มประวัติล่าสุด: ใส่ข้อความ 6–10 ข้อความล่าสุดตามตัวอักษร
  4. สรุปประวัติเก่า: หากมีประวัติเก่า ให้แทรกสรุปที่อัปเดตต่อเนื่อง
  5. ตรวจสอบตัวป้องกัน: หากยังเกินงบประมาณ ให้ตัดข้อความเก่าที่ใส่ตามตัวอักษรออก

แนวทางแบบหลายชั้นนี้ช่วยรักษาข้อมูลที่สำคัญที่สุดไว้ (หน่วยความจำเอนทิตีและบริบทล่าสุด) พร้อมลดทอนประวัติเก่าอย่างเหมาะสมให้เป็นสรุป และตัดทิ้งเฉพาะเมื่อเป็นทางเลือกสุดท้าย

ตรวจสอบความเข้าใจ

ทดสอบความเข้าใจแนวคิดวิศวกรรม AI จากบทเรียนนี้

สรุปบทเรียน

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

เริ่มต้นได้ฟรี

เรียนรู้ Python ด้วย AI tutor — ฟรี

เขียนและเรียกใช้โค้ดจริงในเบราว์เซอร์ของคุณ รับความช่วยเหลือทันทีจาก AI tutor 24/7 และเรียนรู้ต่อจากที่คุณหยุดบนเว็บหรือในแอป

คอร์ส
30
บทเรียน
120

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

บทเรียน “กลยุทธ์การอยู่ภายในขอบเขตบริบท” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “กลยุทธ์การอยู่ภายในขอบเขตบริบท” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ 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 ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน

บทเรียน “กลยุทธ์การอยู่ภายในขอบเขตบริบท” ใช้เวลานานแค่ไหน

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

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

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

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

  1. โทเคนคืออะไร
  2. หน้าต่างบริบท: ขนาดและนัยสำคัญ
  3. การคำนวณและคาดการณ์ค่าใช้จ่าย API
  4. กลยุทธ์การอยู่ภายในขอบเขตบริบท
← กลับไปที่ AI Engineering Academy