0Pricing
AI Engineering Academy · Lekcja

Trwałe przechowywanie historii czatu w Redis i PostgreSQL

Uczestnicy będą przechowywać historię rozmów zewnętrznie za pomocą RedisChatMessageHistory i PostgresChatMessageHistory, aby pamięć przetrwała ponowne uruchomienie aplikacji i mogła być współdzielona przez wiele instancji.

Trwałe przechowywanie historii czatu w Redis i PostgreSQL to bezpłatna lekcja AI Engineering Academy na CoddyKit. To lekcja 4 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej AI Engineering Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs AI Engineering Academy zawiera 4 lekcji w sumie.

Dlaczego przechowywać historię czatu zewnętrznie?

Historia rozmowy przechowywana w pamięci aplikacji znika po ponownym uruchomieniu aplikacji lub jej skalowaniu do wielu instancji. Przechowywanie zewnętrzne rozwiązuje trzy problemy: historia przetrwa awarie, wiele instancji serwera będzie korzystać z tej samej historii, a wcześniejsze sesje będzie można wczytać dla powracających użytkowników. Redis i PostgreSQL to dwa najpopularniejsze backendy do tego celu.

Interfejs historii wiadomości czatu w LangChain

LangChain definiuje interfejs BaseChatMessageHistory z dwiema metodami: add_message(message) oraz messages (właściwość). Każdy backend przechowywania implementujący ten interfejs może służyć jako pamięć dla dowolnego łańcucha LangChain. Zarówno implementacje dla Redis, jak i PostgreSQL są zgodne z tym interfejsem.

from langchain_community.chat_message_histories import RedisChatMessageHistory

# Each unique session_id gets its own history namespace
history = RedisChatMessageHistory(
    session_id='user:alice:session:42',
    url='redis://localhost:6379'
)

# Add messages
history.add_user_message('What is RAG?')
history.add_ai_message('RAG stands for Retrieval-Augmented Generation...')

# Retrieve stored messages
for msg in history.messages:
    print(msg.type, ':', msg.content[:50])

Połączenie historii Redis z łańcuchem

Proszę opakować łańcuch za pomocą RunnableWithMessageHistory i przekazać funkcję fabrykującą, która zwraca właściwy obiekt historii dla każdej sesji. LangChain automatycznie wczytuje historię przed każdym wywołaniem i zapisuje nowe wiadomości po każdej odpowiedzi.

from langchain_core.runnables.history import RunnableWithMessageHistory
from langchain_community.chat_message_histories import RedisChatMessageHistory
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder

llm = ChatOpenAI(model='gpt-4o-mini')
prompt = ChatPromptTemplate.from_messages([
    ('system', 'You are a helpful assistant.'),
    MessagesPlaceholder(variable_name='history'),
    ('human', '{input}')
])

chain = prompt | llm

chain_with_history = RunnableWithMessageHistory(
    chain,
    lambda session_id: RedisChatMessageHistory(
        session_id=session_id,
        url='redis://localhost:6379'
    ),
    input_messages_key='input',
    history_messages_key='history'
)

Wywoływanie łańcucha z identyfikatorem sesji

Podczas wywoływania łańcucha opakowanego w historię wiadomości proszę przekazać identyfikator sesji w słowniku config, w sekcji configurable. LangChain automatycznie kieruje każde wywołanie do właściwego magazynu historii, dzięki czemu Alice i Bob mają całkowicie oddzielne historie rozmów.

# First turn for session alice-001
response = chain_with_history.invoke(
    {'input': 'My name is Alice.'},
    config={'configurable': {'session_id': 'alice-001'}}
)
print(response.content)

# Second turn — the chain remembers Alice's name from Redis
response = chain_with_history.invoke(
    {'input': 'What is my name?'},
    config={'configurable': {'session_id': 'alice-001'}}
)
print(response.content)  # Should say 'Your name is Alice.'

Projektowanie kluczy Redis dla historii czatu

Redis przechowuje wiadomości każdej sesji jako listę pod kluczem utworzonym na podstawie identyfikatora sesji. Proszę używać ustrukturyzowanego schematu kluczy, takiego jak chat:<app>:<user_id>:<session_id>, aby uniknąć kolizji kluczy między aplikacjami i umożliwić wydajne skanowanie według użytkownika. Proszę ustawić TTL dla starych kluczy sesji, aby zapobiec nieograniczonemu wzrostowi ilości przechowywanych danych.

import redis

r = redis.Redis.from_url('redis://localhost:6379')

# List all chat sessions for user alice
keys = r.keys('message_store:alice-*')
print('Active sessions:', len(keys))

# Set a 30-day TTL on a session to auto-expire old history
for key in keys:
    r.expire(key, 60 * 60 * 24 * 30)

Projektowanie tabeli historii czatu w PostgreSQL

W przypadku trwałego przechowywania danych w SQL proszę utworzyć tabelę z kolumnami identyfikatora sesji, roli wiadomości, treści i znacznika czasu. PostgreSQL sprawdza się idealnie, gdy historię czatu trzeba odpytywać, poddawać audytowi lub łączyć z danymi kont użytkowników. Pakiet langchain_postgres udostępnia gotową implementację.

-- SQL table for storing chat messages
CREATE TABLE chat_messages (
    id          SERIAL PRIMARY KEY,
    session_id  TEXT NOT NULL,
    role        TEXT NOT NULL,   -- 'human' or 'ai'
    content     TEXT NOT NULL,
    created_at  TIMESTAMPTZ DEFAULT NOW()
);

CREATE INDEX idx_chat_session ON chat_messages (session_id, created_at);

PostgresChatMessageHistory w LangChain

Klasa PostgresChatMessageHistory z pakietu langchain_postgres działa tak samo jak wersja dla Redis, ale przechowuje wiadomości w bazie PostgreSQL. Proszę przekazać ciąg połączenia i identyfikator sesji, a klasa automatycznie zajmie się utworzeniem tabeli i serializacją wiadomości.

from langchain_postgres import PostgresChatMessageHistory
import psycopg

CONNECTION_STRING = 'postgresql://user:pass@localhost:5432/mydb'

# Create history object for a session
history = PostgresChatMessageHistory(
    table_name='chat_messages',
    session_id='alice-001',
    connection=psycopg.connect(CONNECTION_STRING)
)

history.add_user_message('Tell me about embeddings.')
history.add_ai_message('Embeddings are dense vector representations...')

print(f'Stored {len(history.messages)} messages')

Wczytywanie poprzednich sesji powracających użytkowników

Gdy użytkownik wróci do aplikacji po jej zamknięciu, można przywrócić jego ostatnią sesję, wczytując historię z Redis lub PostgreSQL. Proszę wyświetlić użytkownikowi podsumowanie miejsca, w którym przerwał, albo płynnie kontynuować rozmowę, wstrzykując zapisaną historię do kolejnego promptu.

def get_or_create_history(user_id: str, session_id: str):
    history = RedisChatMessageHistory(
        session_id=f'{user_id}:{session_id}',
        url='redis://localhost:6379'
    )
    if history.messages:
        print(f'Resuming session with {len(history.messages)} messages.')
    else:
        print('Starting a new session.')
    return history

Skracanie historii w bazie danych

Długotrwałe sesje mogą zgromadzić tysiące wiadomości. Proszę wdrożyć strategię skracania historii, która usuwa wiadomości starsze niż określony punkt graniczny albo pozostawia w bazie tylko ostatnie N wiadomości. Dzięki temu pobieranie pozostaje szybkie, a okna kontekstu nie przepełniają się podczas wczytywania historii.

# Keep only the last 20 messages per session in PostgreSQL
CLEAN_SQL = '''
    DELETE FROM chat_messages
    WHERE session_id = %s
    AND id NOT IN (
        SELECT id FROM chat_messages
        WHERE session_id = %s
        ORDER BY created_at DESC
        LIMIT 20
    )
'''

def trim_session(conn, session_id: str, keep_last: int = 20):
    with conn.cursor() as cur:
        cur.execute(CLEAN_SQL, (session_id, session_id))
    conn.commit()

Wybór między Redis a PostgreSQL

Oba backendy są gotowe do użycia w środowisku produkcyjnym, ale mają różne zalety. Redis zapewnia odczyt w czasie krótszym niż milisekunda, dzięki czemu idealnie nadaje się do czatów działających w czasie rzeczywistym, gdzie najważniejsze są opóźnienia. PostgreSQL oferuje pełne możliwości odpytywania za pomocą SQL, transakcje ACID oraz łatwą integrację z istniejącą bazą danych użytkowników na potrzeby analityki i audytu. Wiele systemów produkcyjnych używa Redis jako głównej pamięci podręcznej, a PostgreSQL do trwałej archiwizacji.

Bezpieczeństwo: izolowanie historii w środowisku wielodostępnym

W aplikacjach wielodostępnych należy zagwarantować, że użytkownicy nie będą mogli uzyskać dostępu do historii innych osób. Zawsze proszę uwzględniać identyfikator użytkownika w kluczu sesji, sprawdzać przed wczytaniem historii, czy identyfikator sesji należy do uwierzytelnionego użytkownika, i nigdy nie ujawniać surowych kluczy sesji w adresach URL ani plikach cookie po stronie klienta.

  • Dobry klucz: chat:app1:user:42:session:abc
  • Zły klucz: session:abc (możliwy do odgadnięcia, bez zakresu użytkownika)

Szybkie sprawdzenie

Proszę sprawdzić swoją wiedzę na temat zewnętrznego utrwalania historii czatu.

Podsumowanie lekcji

W tej lekcji dowiedzieli się Państwo, że: RedisChatMessageHistory przechowuje historię czatu w Redis, używając kluczy przypisanych do sesji, PostgresChatMessageHistory umożliwia trwałe przechowywanie danych, które można odpytywać za pomocą SQL, a RunnableWithMessageHistory łączy dowolny backend z łańcuchem za pomocą funkcji fabrykującej session_id. Następnie zajmiemy się frameworkiem ReAct do budowania agentów rozumujących i wykonujących działania.

Często zadawane pytania

Czy lekcja „Trwałe przechowywanie historii czatu w Redis i PostgreSQL” jest bezpłatna?

Tak — pełny tekst „Trwałe przechowywanie historii czatu w Redis i PostgreSQL” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu AI Engineering Academy, przejdź na CoddyKit PRO. Kurs AI Engineering Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „Trwałe przechowywanie historii czatu w Redis i PostgreSQL”?

Uczestnicy będą przechowywać historię rozmów zewnętrznie za pomocą RedisChatMessageHistory i PostgresChatMessageHistory, aby pamięć przetrwała ponowne uruchomienie aplikacji i mogła być współdzielona… Ćwiczysz AI Engineering Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć AI Engineering Academy?

Nie wymagamy żadnego doświadczenia. AI Engineering Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 4 z 4.

Ile czasu zajmuje lekcja „Trwałe przechowywanie historii czatu w Redis i PostgreSQL”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji AI Engineering Academy?

Tak. Każda lekcja AI Engineering Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Dlaczego bezstanowe LLM-y potrzebują pamięci zewnętrznej
  2. Pamięć buforowa i okno kontekstu
  3. Pamięć podsumowań i skracanie uwzględniające tokeny
  4. Trwałe przechowywanie historii czatu w Redis i PostgreSQL
← Powrót do AI Engineering Academy