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