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

หน่วยความจำแบบสรุปและการตัดข้อความโดยคำนึงถึงโทเคน

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

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

ค่าใช้จ่ายโทเค็นของประวัติทั้งหมด

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

หน่วยความจำแบบสรุปทำงานอย่างไร

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

  • รอบเก่า: แทนที่ด้วยสรุป
  • รอบล่าสุด: เก็บไว้ตามเดิม
  • ผลลัพธ์สุทธิ: บีบอัดได้อย่างมีความหมายโดยสูญเสียข้อมูลน้อยที่สุด

LangChain ConversationSummaryMemory

LangChain มี ConversationSummaryMemory ซึ่งจะสรุปโดยอัตโนมัติเมื่อบัฟเฟอร์มีขนาดใหญ่เกินไป คุณส่ง LLM ไปยังวัตถุหน่วยความจำ เพื่อให้วัตถุดังกล่าวเรียกโมเดลเพื่อสร้างสรุปตามต้องการได้

from langchain.memory import ConversationSummaryMemory
from langchain_openai import ChatOpenAI

llm = ChatOpenAI(model='gpt-4o-mini')

memory = ConversationSummaryMemory(
    llm=llm,
    return_messages=True
)

# Add messages manually
memory.save_context(
    {'input': 'My name is Alice and I am building a RAG system.'},
    {'output': 'Great, I can help you build a RAG system, Alice.'}
)

print(memory.load_memory_variables({}))

หน่วยความจำแบบบัฟเฟอร์สรุป: รวมข้อดีของทั้งสองแบบ

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

from langchain.memory import ConversationSummaryBufferMemory
from langchain_openai import ChatOpenAI

llm = ChatOpenAI(model='gpt-4o-mini')

memory = ConversationSummaryBufferMemory(
    llm=llm,
    max_token_limit=500,  # Summarize when older turns exceed 500 tokens
    return_messages=True
)

# As the conversation grows, old turns get summarized automatically
print('Moving summary:', memory.moving_summary_buffer)

การนับโทเค็นก่อนการตัดทอน

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

import tiktoken

def count_tokens(messages: list, model: str = 'gpt-4o') -> int:
    encoding = tiktoken.encoding_for_model(model)
    total = 0
    for msg in messages:
        # Each message has overhead tokens for role framing
        total += 4
        total += len(encoding.encode(msg.get('content', '')))
    total += 2  # Reply primer
    return total

messages = [
    {'role': 'user', 'content': 'Explain RAG to me.'},
    {'role': 'assistant', 'content': 'RAG stands for Retrieval-Augmented Generation...'}
]
print('Token count:', count_tokens(messages))

การตัดทอนที่คำนึงถึงโทเค็นด้วยตนเอง

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

def truncate_to_budget(messages: list, budget: int, model: str = 'gpt-4o') -> list:
    '''Remove oldest non-system messages until under budget.'''
    import tiktoken
    encoding = tiktoken.encoding_for_model(model)

    def token_count(msgs):
        total = 2
        for m in msgs:
            total += 4 + len(encoding.encode(m.get('content', '')))
        return total

    result = list(messages)
    while token_count(result) > budget and len(result) > 1:
        # Never remove the system prompt at index 0
        if result[0]['role'] == 'system':
            del result[1]
        else:
            del result[0]
    return result

การสร้างพรอมต์สำหรับสรุป

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

from openai import OpenAI

client = OpenAI()

def summarize_history(old_summary: str, new_turns: list) -> str:
    turns_text = '\n'.join(
        f'{m["role"].capitalize()}: {m["content"]}' for m in new_turns
    )
    prompt = f'''Current summary:\n{old_summary}\n\nNew conversation turns:\n{turns_text}\n\nWrite an updated summary that captures key facts, user preferences, and open questions.'''

    resp = client.chat.completions.create(
        model='gpt-4o-mini',
        messages=[{'role': 'user', 'content': prompt}]
    )
    return resp.choices[0].message.content

การผสานสรุปเข้ากับพรอมต์ระบบ

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

def build_messages_with_summary(summary: str, recent_turns: list, user_input: str) -> list:
    system_content = (
        'You are a helpful AI assistant.'
        + ('\n\n[Conversation summary]\n' + summary if summary else '')
    )

    messages = [{'role': 'system', 'content': system_content}]
    messages.extend(recent_turns)
    messages.append({'role': 'user', 'content': user_input})
    return messages

การเรียกใช้การสรุปโดยอัตโนมัติ

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

class SummaryBufferChat:
    def __init__(self, max_tokens=2000):
        self.summary = ''
        self.recent_turns = []
        self.max_tokens = max_tokens

    def chat(self, user_message: str) -> str:
        from openai import OpenAI
        client = OpenAI()

        messages = build_messages_with_summary(self.summary, self.recent_turns, user_message)
        resp = client.chat.completions.create(model='gpt-4o', messages=messages)
        reply = resp.choices[0].message.content

        self.recent_turns.append({'role': 'user', 'content': user_message})
        self.recent_turns.append({'role': 'assistant', 'content': reply})

        if count_tokens(self.recent_turns) > self.max_tokens:
            to_summarize = self.recent_turns[:-2]
            self.recent_turns = self.recent_turns[-2:]
            self.summary = summarize_history(self.summary, to_summarize)

        return reply

การรักษาสิ่งที่มีชื่อเฉพาะไว้ในสรุป

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

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

ข้อแลกเปลี่ยน: หน่วยความจำแบบสรุปเทียบกับแบบหน้าต่าง

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

ตรวจสอบความเข้าใจอย่างรวดเร็ว

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

ทบทวนบทเรียน

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

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

บทเรียน “หน่วยความจำแบบสรุปและการตัดข้อความโดยคำนึงถึงโทเคน” ฟรีหรือไม่

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

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

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

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

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

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

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

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

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

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

  1. เหตุใด LLM แบบไร้สถานะจึงต้องใช้หน่วยความจำภายนอก
  2. หน่วยความจำแบบบัฟเฟอร์และหน้าต่าง
  3. หน่วยความจำแบบสรุปและการตัดข้อความโดยคำนึงถึงโทเคน
  4. การเก็บประวัติการสนทนาใน Redis และ PostgreSQL
← กลับไปที่ AI Engineering Academy