0Pricing
AI Agents · บทเรียน

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

จัดเก็บและโหลดการตั้งค่าผู้ใช้ ประวัติการสนทนา และสถานะงาน

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

เหตุใดจึงต้องคงบริบทไว้

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

SQLite สำหรับสถานะเซสชัน

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

import sqlite3
from datetime import datetime

def init_db(db_path: str = 'agent_memory.db') -> sqlite3.Connection:
    conn = sqlite3.connect(db_path, check_same_thread=False)
    conn.row_factory = sqlite3.Row  # Dict-like access
    
    conn.executescript('''
        CREATE TABLE IF NOT EXISTS sessions (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            session_id TEXT UNIQUE NOT NULL,
            user_id TEXT NOT NULL,
            started_at TEXT,
            last_active TEXT
        );
        
        CREATE TABLE IF NOT EXISTS messages (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            session_id TEXT NOT NULL,
            role TEXT NOT NULL,
            content TEXT NOT NULL,
            timestamp TEXT NOT NULL
        );
        
        CREATE TABLE IF NOT EXISTS user_facts (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            user_id TEXT NOT NULL,
            fact_key TEXT NOT NULL,
            fact_value TEXT NOT NULL,
            created_at TEXT,
            UNIQUE(user_id, fact_key)
        );
    ''')
    conn.commit()
    return conn

conn = init_db()
print('Database initialized')

การบันทึกและโหลดข้อความ

ควรบันทึกข้อความของผู้ใช้และคำตอบของเอเจนต์ทุกข้อความพร้อม ID ของเซสชัน เมื่อกลับมาใช้เซสชันต่อ ให้โหลดข้อความล่าสุดจำนวน N ข้อความเพื่อกู้คืนบริบทการสนทนา

import sqlite3
from datetime import datetime

def save_message(conn: sqlite3.Connection, session_id: str, role: str, content: str):
    conn.execute(
        'INSERT INTO messages (session_id, role, content, timestamp) VALUES (?, ?, ?, ?)',
        (session_id, role, content, datetime.utcnow().isoformat())
    )
    conn.commit()

def load_recent_messages(conn: sqlite3.Connection, session_id: str, limit: int = 20) -> list:
    rows = conn.execute(
        'SELECT role, content FROM messages WHERE session_id = ? ORDER BY id DESC LIMIT ?',
        (session_id, limit)
    ).fetchall()
    # Reverse to get chronological order
    return [{'role': r['role'], 'content': r['content']} for r in reversed(rows)]

def load_all_session_messages(conn: sqlite3.Connection, user_id: str, days: int = 30) -> list:
    from datetime import timedelta
    since = (datetime.utcnow() - timedelta(days=days)).isoformat()
    rows = conn.execute(
        'SELECT m.role, m.content, m.timestamp FROM messages m '
        'JOIN sessions s ON s.session_id = m.session_id '
        'WHERE s.user_id = ? AND m.timestamp >= ? ORDER BY m.id',
        (user_id, since)
    ).fetchall()
    return [dict(r) for r in rows]

if __name__ == '__main__':
    conn = sqlite3.connect(':memory:')
    conn.row_factory = sqlite3.Row
    conn.execute('CREATE TABLE messages (id INTEGER PRIMARY KEY, session_id TEXT, role TEXT, content TEXT, timestamp TEXT)')
    save_message(conn, 'sess1', 'user', 'Hello agent')
    save_message(conn, 'sess1', 'assistant', 'Hi! How can I help?')
    for msg in load_recent_messages(conn, 'sess1'):
        print(f"{msg['role']}: {msg['content']}")

Redis สำหรับสถานะเซสชัน

สำหรับเอเจนต์บนเว็บหรือการนำระบบไปใช้งานบนหลายเซิร์ฟเวอร์ Redis เหมาะกว่า SQLite ให้จัดเก็บข้อมูลเซสชันเป็น JSON พร้อม TTL เพื่อให้เซสชันเก่าถูกล้างโดยอัตโนมัติ

import redis
import json
from datetime import datetime

r = redis.Redis(host='localhost', port=6379, decode_responses=True)
SESSION_TTL = 3600 * 24 * 7  # 7 days

def save_session_state(session_id: str, state: dict):
    key = f'session:{session_id}'
    state['last_updated'] = datetime.utcnow().isoformat()
    r.setex(key, SESSION_TTL, json.dumps(state))

def load_session_state(session_id: str) -> dict:
    key = f'session:{session_id}'
    raw = r.get(key)
    if not raw:
        return {}
    state = json.loads(raw)
    # Refresh TTL on access
    r.expire(key, SESSION_TTL)
    return state

def append_to_session_history(session_id: str, role: str, content: str):
    state = load_session_state(session_id)
    history = state.get('history', [])
    history.append({'role': role, 'content': content})
    # Keep last 50 messages
    state['history'] = history[-50:]
    save_session_state(session_id, state)

# Test
save_session_state('sess-abc', {'user_name': 'Alice', 'history': []})
append_to_session_history('sess-abc', 'user', 'Hello!')
state = load_session_state('sess-abc')
print('Session state:', state)

การโหลดการตั้งค่าของผู้ใช้เมื่อเริ่มต้น

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

import sqlite3

def load_user_preferences(conn: sqlite3.Connection, user_id: str) -> dict:
    rows = conn.execute(
        'SELECT fact_key, fact_value FROM user_facts WHERE user_id = ?',
        (user_id,)
    ).fetchall()
    return {row['fact_key']: row['fact_value'] for row in rows}

def build_system_prompt_with_preferences(base_prompt: str, user_id: str, conn: sqlite3.Connection) -> str:
    prefs = load_user_preferences(conn, user_id)
    
    if not prefs:
        return base_prompt
    
    pref_lines = []
    if 'name' in prefs:
        pref_lines.append(f'The user\'s name is {prefs["name"]}.')
    if 'timezone' in prefs:
        pref_lines.append(f'The user is in timezone {prefs["timezone"]}.')
    if 'language' in prefs:
        pref_lines.append(f'Respond in {prefs["language"]}.')
    if 'profession' in prefs:
        pref_lines.append(f'The user is a {prefs["profession"]}.')
    
    prefs_text = ' '.join(pref_lines)
    return f'{base_prompt}\n\nUser context: {prefs_text}'

conn = init_db()
enhanced_prompt = build_system_prompt_with_preferences(
    'You are a helpful assistant.',
    'user-42',
    conn
)
print('System prompt:', enhanced_prompt)

การจัดเก็บสรุปการสนทนา

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

import openai

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

def summarize_conversation(messages: list) -> str:
    if not messages:
        return ''
    
    conversation_text = '\n'.join([
        f'{m["role"].upper()}: {m["content"]}'
        for m in messages
    ])
    
    response = client.chat.completions.create(
        model='gpt-4o-mini',
        messages=[{
            'role': 'user',
            'content': (
                'Summarize this conversation in 2-3 sentences, '
                'focusing on key facts, decisions, and user preferences revealed:\n\n'
                f'{conversation_text}'
            )
        }]
    )
    return response.choices[0].message.content

def compress_old_history(conn: sqlite3.Connection, session_id: str, keep_recent: int = 10):
    all_messages = load_recent_messages(conn, session_id, limit=1000)
    if len(all_messages) <= keep_recent:
        return
    
    old_messages = all_messages[:-keep_recent]
    summary = summarize_conversation(old_messages)
    
    # Store summary as a special message
    save_message(conn, session_id, 'summary', f'[Previous conversation summary]: {summary}')
    print(f'Compressed {len(old_messages)} old messages into summary')

การดึงและจัดเก็บข้อเท็จจริงของผู้ใช้

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

import openai
import json

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

def extract_user_facts(message: str) -> dict:
    response = client.chat.completions.create(
        model='gpt-4o-mini',
        messages=[{
            'role': 'user',
            'content': (
                f'Extract any personal facts the user revealed in this message: "{message}"\n'
                'Return JSON with fields: name, location, profession, preferences, or other relevant facts. '
                'Return empty dict {{}} if no facts were revealed.'
            )
        }],
        response_format={'type': 'json_object'}
    )
    return json.loads(response.choices[0].message.content)

def store_user_facts(conn: sqlite3.Connection, user_id: str, facts: dict):
    for key, value in facts.items():
        if value:  # Skip empty values
            conn.execute(
                'INSERT OR REPLACE INTO user_facts (user_id, fact_key, fact_value, created_at) VALUES (?, ?, ?, ?)',
                (user_id, key, str(value), __import__('datetime').datetime.utcnow().isoformat())
            )
    conn.commit()
    if facts:
        print(f'Stored {len(facts)} facts for user {user_id}: {list(facts.keys())}')

conn = init_db()
facts = extract_user_facts('I am a software engineer in Berlin working on AI projects')
store_user_facts(conn, 'user-42', facts)
print('Facts extracted:', facts)

การโหลดบริบทที่เกี่ยวข้องสำหรับรอบการโต้ตอบปัจจุบัน

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

def build_agent_context(conn: sqlite3.Connection, session_id: str, user_id: str, new_message: str) -> list:
    messages = []
    
    # Step 1: System prompt with user preferences
    prefs = load_user_preferences(conn, user_id)
    system_content = 'You are a helpful personal AI assistant.'
    if prefs:
        facts_text = ', '.join([f'{k}: {v}' for k, v in prefs.items()])
        system_content += f' User context: {facts_text}'
    messages.append({'role': 'system', 'content': system_content})
    
    # Step 2: Load conversation history (last 15 messages)
    history = load_recent_messages(conn, session_id, limit=15)
    messages.extend(history)
    
    # Step 3: Add the new user message
    messages.append({'role': 'user', 'content': new_message})
    
    return messages

conn = init_db()
context = build_agent_context(conn, 'sess-abc', 'user-42', 'What should I work on today?')
print(f'Context assembled: {len(context)} messages')
for m in context:
    print(f'  {m["role"]}: {m["content"][:60]}...')

การเรียกคืนหน่วยความจำข้ามเซสชัน

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

import openai
import chromadb

client = openai.OpenAI(api_key='sk-...')
chroma = chromadb.Client()
memory_collection = chroma.get_or_create_collection('user_memory')

def store_memory(user_id: str, content: str, metadata: dict):
    emb_response = client.embeddings.create(
        model='text-embedding-3-small', input=content
    )
    embedding = emb_response.data[0].embedding
    
    import hashlib
    doc_id = f'{user_id}_{hashlib.md5(content.encode()).hexdigest()[:8]}'
    
    memory_collection.add(
        ids=[doc_id],
        embeddings=[embedding],
        documents=[content],
        metadatas=[{'user_id': user_id, **metadata}]
    )

def retrieve_relevant_memories(user_id: str, current_query: str, top_k: int = 3) -> list:
    emb_response = client.embeddings.create(
        model='text-embedding-3-small', input=current_query
    )
    query_embedding = emb_response.data[0].embedding
    
    results = memory_collection.query(
        query_embeddings=[query_embedding],
        n_results=top_k,
        where={'user_id': user_id}
    )
    return results['documents'][0] if results['documents'] else []

print('Cross-session memory retrieval defined')

ความเป็นส่วนตัวและการจัดการข้อมูล

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

import sqlite3
from datetime import datetime, timedelta

def delete_user_data(conn: sqlite3.Connection, user_id: str):
    '''Fully delete all data for a user (right to erasure).'''
    conn.execute(
        'DELETE FROM messages WHERE session_id IN (SELECT session_id FROM sessions WHERE user_id = ?)',
        (user_id,)
    )
    conn.execute('DELETE FROM sessions WHERE user_id = ?', (user_id,))
    conn.execute('DELETE FROM user_facts WHERE user_id = ?', (user_id,))
    conn.commit()
    print(f'All data deleted for user {user_id}')

def purge_old_messages(conn: sqlite3.Connection, retention_days: int = 90):
    '''Remove messages older than retention period.'''
    cutoff = (datetime.utcnow() - timedelta(days=retention_days)).isoformat()
    cursor = conn.execute(
        'DELETE FROM messages WHERE timestamp < ?', (cutoff,)
    )
    conn.commit()
    print(f'Purged {cursor.rowcount} messages older than {retention_days} days')

# Run nightly retention cleanup
conn = init_db()
purge_old_messages(conn, retention_days=90)
print('Retention policy applied')

การตรวจสอบความต่อเนื่องของเซสชัน

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

import sqlite3
from datetime import datetime, timedelta

def get_session_gap_context(conn: sqlite3.Connection, session_id: str) -> str:
    row = conn.execute(
        'SELECT last_active FROM sessions WHERE session_id = ?',
        (session_id,)
    ).fetchone()
    
    if not row or not row['last_active']:
        return ''
    
    last_active = datetime.fromisoformat(row['last_active'])
    gap = datetime.utcnow() - last_active
    
    if gap < timedelta(minutes=30):
        return ''  # Recent session, no gap context needed
    elif gap < timedelta(hours=12):
        return f'Note: The user was last active {int(gap.total_seconds() / 3600)} hours ago.'
    elif gap < timedelta(days=7):
        return f'Note: The user was last active {gap.days} days ago.'
    else:
        return f'Note: The user returns after {gap.days} days away. Welcome them back warmly.'

conn = init_db()
gap = get_session_gap_context(conn, 'sess-abc')
if gap:
    print('Gap context:', gap)
else:
    print('No gap context needed')

ตรวจสอบความรู้: การคงบริบท

ทดสอบความเข้าใจเกี่ยวกับการคงบริบทข้ามเซสชันของเอเจนต์

สรุปการคงบริบท

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

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

บทเรียน “การคงอยู่ของบริบทข้ามเซสชัน” ฟรีหรือไม่

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

คุณจะเรียนรู้อะไรในบทเรียน “การคงอยู่ของบริบทข้ามเซสชัน”

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

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

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

บทเรียน “การคงอยู่ของบริบทข้ามเซสชัน” ใช้เวลานานแค่ไหน

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

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

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

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

  1. รูปแบบการออกแบบเอเจนต์ที่ทำงานตลอดเวลา
  2. ระบบการแจ้งเตือนและการเตือนเชิงรุก
  3. การคงอยู่ของบริบทข้ามเซสชัน
  4. การสร้างเอเจนต์สรุปข้อมูลประจำวัน
← กลับไปที่ AI Agents