AI Engineering Academy · Lezione

Persistenza della cronologia chat in Redis e PostgreSQL

Memorizzerà esternamente la cronologia delle conversazioni usando RedisChatMessageHistory e PostgresChatMessageHistory, così che la memoria sopravviva ai riavvii dell'applicazione e possa scalare su più istanze.

Lezione 4 di 413 passaggi

Persistenza della cronologia chat in Redis e PostgreSQL è una lezione AI Engineering Academy gratuita su CoddyKit. Questa è la lezione 4 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento AI Engineering Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso AI Engineering Academy include 4 lezioni in totale.

Perché rendere persistente la cronologia delle chat esternamente?

La cronologia delle conversazioni in memoria scompare quando l'applicazione viene riavviata o distribuita su più istanze. La persistenza esterna risolve tre problemi: la cronologia sopravvive agli arresti anomali, più istanze del server condividono la stessa cronologia e le sessioni precedenti possono essere caricate per gli utenti che tornano. Redis e PostgreSQL sono i due backend più utilizzati a questo scopo.

Interfaccia della cronologia dei messaggi delle chat di LangChain

LangChain definisce un'interfaccia BaseChatMessageHistory con due metodi: add_message(message) e messages (proprietà). Qualsiasi backend di archiviazione che implementi questa interfaccia può essere utilizzato come memoria per qualunque chain LangChain. Sia le implementazioni per Redis sia quelle per PostgreSQL seguono questa interfaccia.

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])

Collegare la cronologia Redis a una chain

Avvolga la Sua chain con RunnableWithMessageHistory e fornisca una funzione factory che restituisca l'oggetto cronologia corretto per ogni sessione. LangChain carica automaticamente la cronologia prima di ogni chiamata e salva i nuovi messaggi dopo ogni risposta.

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'
)

Invocare la chain con un ID di sessione

Quando invoca una chain avvolta con una cronologia dei messaggi, passi l'ID di sessione nel dizionario config, sotto configurable. LangChain indirizza automaticamente ogni chiamata verso l'archivio della cronologia corretto, così le cronologie delle conversazioni di Alice e Bob rimangono completamente separate.

# 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.'

Progettare le chiavi Redis per la cronologia delle chat

Redis memorizza i messaggi di ogni sessione come un elenco associato a una chiave derivata dall'ID di sessione. Utilizzi uno schema strutturato per le chiavi, ad esempio chat:<app>:<user_id>:<session_id>, per evitare conflitti tra applicazioni e consentire una scansione efficiente per utente. Imposti un TTL sulle chiavi delle sessioni meno recenti per impedire una crescita illimitata dello spazio di archiviazione.

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)

Progettare la tabella PostgreSQL per la cronologia delle chat

Per la persistenza basata su SQL, crei una tabella con colonne per l'ID di sessione, il ruolo del messaggio, il contenuto e il timestamp. PostgreSQL è ideale quando la cronologia delle chat deve essere interrogata, sottoposta ad audit o collegata ai dati degli account utente. Il pacchetto langchain_postgres fornisce un'implementazione pronta all'uso.

-- 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 in LangChain

La classe PostgresChatMessageHistory di langchain_postgres funziona proprio come la versione per Redis, ma memorizza i messaggi nel database PostgreSQL. Passi una stringa di connessione e un ID di sessione: la classe gestirà automaticamente la creazione della tabella e la serializzazione dei messaggi.

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')

Caricare le sessioni precedenti per gli utenti di ritorno

Quando un utente torna nella Sua app dopo averla chiusa, può ripristinare l'ultima sessione caricando la cronologia da Redis o PostgreSQL. Può mostrare all'utente un riepilogo del punto in cui si era fermato oppure proseguire senza interruzioni inserendo la cronologia memorizzata nel prompt successivo.

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

Ridurre la cronologia nel database

Le sessioni di lunga durata possono accumulare migliaia di messaggi. Implementi una strategia di riduzione che elimini i messaggi più vecchi di una determinata soglia oppure conservi nel database solo gli ultimi N messaggi. In questo modo il recupero rimane rapido e si evita di superare le finestre di contesto quando si carica la cronologia.

# 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()

Scegliere tra Redis e PostgreSQL

Entrambi i backend sono pronti per la produzione, ma presentano punti di forza diversi. Redis offre letture in meno di un millisecondo, risultando ideale per le chat in tempo reale in cui la latenza è il fattore più importante. PostgreSQL offre la possibilità di eseguire query SQL complete, transazioni ACID e una facile integrazione con il database utenti esistente per analisi e audit. Molti sistemi di produzione usano Redis come cache primaria e PostgreSQL per l'archiviazione duratura.

Sicurezza: isolare le cronologie dei diversi tenant

Nelle applicazioni multi-tenant, deve assicurarsi che gli utenti non possano accedere alle cronologie altrui. Includa sempre l'ID utente nella chiave di sessione, verifichi che l'ID di sessione appartenga all'utente autenticato prima di caricare la cronologia e non esponga mai le chiavi di sessione grezze negli URL o nei cookie lato client.

  • Chiave corretta: chat:app1:user:42:session:abc
  • Chiave errata: session:abc (prevedibile, senza ambito utente)

Verifica rapida

Verifichi la Sua comprensione della persistenza esterna della cronologia delle chat.

Riepilogo della lezione

In questa lezione ha imparato che: RedisChatMessageHistory memorizza la cronologia delle chat in Redis con chiavi specifiche per sessione, PostgresChatMessageHistory abilita un'archiviazione duratura interrogabile tramite SQL e RunnableWithMessageHistory collega qualsiasi backend alla Sua chain tramite una factory basata su session_id. Ora passeremo al framework ReAct per creare agenti capaci di ragionare e agire.

Gratis per iniziare

Impara Python con un tutor IA — gratis

Scrivi ed esegui vero codice nel tuo browser, ricevi aiuto istantaneo da un tutor IA disponibile 24/7, e riprendi da dove hai lasciato sul web o nell'app.

Corsi
30
Lezioni
120

Domande Frequenti

La lezione «Persistenza della cronologia chat in Redis e PostgreSQL» è gratuita?

Sì — il testo completo di «Persistenza della cronologia chat in Redis e PostgreSQL» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso AI Engineering Academy, passa a CoddyKit PRO. Il corso AI Engineering Academy include 4 lezioni in totale.

Cosa imparerò in «Persistenza della cronologia chat in Redis e PostgreSQL»?

Memorizzerà esternamente la cronologia delle conversazioni usando RedisChatMessageHistory e PostgresChatMessageHistory, così che la memoria sopravviva ai riavvii dell'applicazione e possa scalare su… Eserciti AI Engineering Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare AI Engineering Academy?

Non è richiesta alcuna esperienza precedente. AI Engineering Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 4 di 4.

Quanto tempo richiede la lezione «Persistenza della cronologia chat in Redis e PostgreSQL»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione AI Engineering Academy?

Sì. Ogni lezione AI Engineering Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. Perché gli LLM stateless hanno bisogno di memoria esterna
  2. Memoria a buffer e a finestra
  3. Memoria basata sui riepiloghi e troncamento consapevole dei token
  4. Persistenza della cronologia chat in Redis e PostgreSQL
← Torna a AI Engineering Academy