Skip to content

Conversation Memory

Rumen Damyanov edited this page Oct 3, 2025 · 1 revision

Conversation Memory

Store and retrieve conversation history across multiple interactions, enabling context-aware AI responses.


Table of Contents


Overview

Conversation Memory allows your chatbot to remember previous interactions, maintaining context across multiple messages. This enables:

  • Context-aware responses: AI models can reference earlier parts of the conversation
  • Multi-turn dialogues: Build complex conversations with follow-up questions
  • Session isolation: Keep different users' conversations separate
  • History management: Automatically trim old messages to control token usage
  • Flexible storage: Choose between file, Redis, or database storage

Quick Start

Enable Memory

use Rumenx\PhpChatbot\PhpChatbot;

$chatbot = new PhpChatbot(
    apiKey: 'your-api-key',
    provider: 'openai',
    enableMemory: true,
    maxHistory: 20
);

// First message
$response = $chatbot->ask('My name is Alice', sessionId: 'user-123');
// "Nice to meet you, Alice!"

// Follow-up message - chatbot remembers the name
$response = $chatbot->ask('What is my name?', sessionId: 'user-123');
// "Your name is Alice."

Basic Memory Operations

// Ask with memory (automatically stores messages)
$response = $chatbot->ask('Hello!', sessionId: 'user-123');

// Get conversation history
$history = $chatbot->getConversationHistory('user-123');
foreach ($history as $message) {
    echo "{$message['role']}: {$message['content']}\n";
}

// Clear conversation history
$chatbot->clearConversationHistory('user-123');

Storage Backends

Choose the storage backend that best fits your infrastructure and requirements.

File Storage

Best for: Small to medium applications, simple deployments, development.

Configuration

$config = [
    'memory' => [
        'enabled' => true,
        'max_history' => 20,
        'storage' => 'file',
        'file_storage' => [
            'path' => '/path/to/conversations',
        ],
    ],
];

$chatbot = new PhpChatbot(
    apiKey: 'your-api-key',
    provider: 'openai',
    config: $config
);

Features

  • ✅ No external dependencies
  • ✅ Thread-safe with file locking
  • ✅ JSON format for easy debugging
  • ✅ Automatic directory creation
  • ⚠️ Not suitable for high-concurrency scenarios
  • ⚠️ Limited scalability across multiple servers

Manual Usage

use Rumenx\PhpChatbot\Support\Storage\FileStorage;
use Rumenx\PhpChatbot\Support\ConversationMemory;

$storage = new FileStorage('/path/to/conversations');
$memory = new ConversationMemory($storage, maxHistory: 20);

// Store messages
$memory->addMessage('user-123', 'user', 'Hello!');
$memory->addMessage('user-123', 'assistant', 'Hi there!');

// Retrieve history
$messages = $memory->getHistory('user-123');

Redis Storage

Best for: High-performance applications, distributed systems, auto-expiring sessions.

Requirements

Install either:

  • PHP Redis extension: pecl install redis
  • Predis library: composer require predis/predis

Configuration

$config = [
    'memory' => [
        'enabled' => true,
        'max_history' => 20,
        'storage' => 'redis',
        'redis_storage' => [
            'host' => '127.0.0.1',
            'port' => 6379,
            'password' => null,
            'database' => 0,
            'key_prefix' => 'chatbot:memory:',
            'ttl' => 86400, // 24 hours (0 = no expiration)
        ],
    ],
];

$chatbot = new PhpChatbot(
    apiKey: 'your-api-key',
    provider: 'openai',
    config: $config
);

Features

  • ✅ Extremely fast read/write operations
  • ✅ Perfect for distributed/load-balanced setups
  • ✅ Automatic expiration with TTL
  • ✅ Built-in support for high concurrency
  • ⚠️ Requires Redis server
  • ⚠️ Data is volatile (lost on server restart unless configured)

Manual Usage with Redis Extension

use Rumenx\PhpChatbot\Support\Storage\RedisStorage;
use Rumenx\PhpChatbot\Support\ConversationMemory;

$redis = new Redis();
$redis->connect('127.0.0.1', 6379);

$storage = new RedisStorage(
    redis: $redis,
    keyPrefix: 'chatbot:',
    ttl: 86400 // 24 hours
);

$memory = new ConversationMemory($storage, maxHistory: 20);

Manual Usage with Predis

use Predis\Client;
use Rumenx\PhpChatbot\Support\Storage\RedisStorage;
use Rumenx\PhpChatbot\Support\ConversationMemory;

$redis = new Client([
    'scheme' => 'tcp',
    'host'   => '127.0.0.1',
    'port'   => 6379,
]);

$storage = new RedisStorage($redis, 'chatbot:', 86400);
$memory = new ConversationMemory($storage, maxHistory: 20);

Database Storage

Best for: Enterprise applications, persistent storage, complex querying.

Requirements

  • PDO extension enabled
  • Database driver (MySQL, PostgreSQL, or SQLite)

Configuration

$config = [
    'memory' => [
        'enabled' => true,
        'max_history' => 20,
        'storage' => 'database',
        'database_storage' => [
            'driver' => 'mysql',
            'host' => '127.0.0.1',
            'port' => 3306,
            'database' => 'chatbot',
            'username' => 'root',
            'password' => 'secret',
            'table_name' => 'chatbot_conversations',
        ],
    ],
];

$chatbot = new PhpChatbot(
    apiKey: 'your-api-key',
    provider: 'openai',
    config: $config
);

Supported Databases

MySQL

'database_storage' => [
    'driver' => 'mysql',
    'host' => '127.0.0.1',
    'port' => 3306,
    'database' => 'chatbot',
    'username' => 'root',
    'password' => 'secret',
]

PostgreSQL

'database_storage' => [
    'driver' => 'pgsql',
    'host' => '127.0.0.1',
    'port' => 5432,
    'database' => 'chatbot',
    'username' => 'postgres',
    'password' => 'secret',
]

SQLite

'database_storage' => [
    'driver' => 'sqlite',
    'database' => '/path/to/database.sqlite',
]

Features

  • ✅ Persistent, durable storage
  • ✅ ACID transactions
  • ✅ Complex querying capabilities
  • ✅ Backup and replication support
  • ✅ Auto-creates table on first use
  • ⚠️ Slightly slower than Redis
  • ⚠️ Requires database server (except SQLite)

Manual Usage

use Rumenx\PhpChatbot\Support\Storage\DatabaseStorage;
use Rumenx\PhpChatbot\Support\ConversationMemory;

$pdo = new PDO(
    'mysql:host=127.0.0.1;dbname=chatbot',
    'root',
    'secret'
);

$storage = new DatabaseStorage($pdo, 'chatbot_conversations');
$memory = new ConversationMemory($storage, maxHistory: 20);

Table Schema

The table is automatically created with this schema:

CREATE TABLE chatbot_conversations (
    session_id VARCHAR(255) PRIMARY KEY,
    data TEXT NOT NULL,
    updated_at TIMESTAMP NOT NULL
);

Configuration

Complete Configuration Example

use Rumenx\PhpChatbot\PhpChatbot;

$config = [
    'memory' => [
        // Enable/disable conversation memory
        'enabled' => true,
        
        // Maximum messages to keep (0 = unlimited)
        // Recommended: 10-50 depending on model context window
        'max_history' => 20,
        
        // Storage backend: 'file', 'redis', or 'database'
        'storage' => 'file',
        
        // File storage options
        'file_storage' => [
            'path' => sys_get_temp_dir() . '/chatbot_conversations',
        ],
        
        // Redis storage options
        'redis_storage' => [
            'host' => '127.0.0.1',
            'port' => 6379,
            'password' => null,
            'database' => 0,
            'key_prefix' => 'chatbot:memory:',
            'ttl' => 86400, // 24 hours in seconds (0 = no expiration)
        ],
        
        // Database storage options
        'database_storage' => [
            'driver' => 'mysql',
            'host' => '127.0.0.1',
            'port' => 3306,
            'database' => 'chatbot',
            'username' => 'root',
            'password' => 'secret',
            'table_name' => 'chatbot_conversations',
        ],
    ],
];

$chatbot = new PhpChatbot(
    apiKey: 'your-api-key',
    provider: 'openai',
    config: $config
);

Constructor Shorthand

$chatbot = new PhpChatbot(
    apiKey: 'your-api-key',
    provider: 'openai',
    enableMemory: true,
    maxHistory: 20,
    storageDriver: 'file'
);

Usage Examples

Basic Conversation

$chatbot = new PhpChatbot(
    apiKey: 'your-api-key',
    provider: 'openai',
    enableMemory: true
);

$sessionId = 'user-' . $userId;

// First interaction
$response = $chatbot->ask('My favorite color is blue', sessionId: $sessionId);

// Later interaction - chatbot remembers
$response = $chatbot->ask('What is my favorite color?', sessionId: $sessionId);
// Response: "Your favorite color is blue."

Multi-Turn Dialogue

$sessionId = 'order-12345';

// Build context over multiple messages
$chatbot->ask('I want to order a pizza', sessionId: $sessionId);
// "Great! What size would you like?"

$chatbot->ask('Large', sessionId: $sessionId);
// "What toppings would you like on your large pizza?"

$chatbot->ask('Pepperoni and mushrooms', sessionId: $sessionId);
// "Perfect! A large pizza with pepperoni and mushrooms. Anything else?"

Inspecting History

// Get all messages in conversation
$history = $chatbot->getConversationHistory($sessionId);

foreach ($history as $message) {
    echo "{$message['role']}: {$message['content']}\n";
}

// Output:
// user: My favorite color is blue
// assistant: That's a great choice!
// user: What is my favorite color?
// assistant: Your favorite color is blue.

Manual Message Management

$memory = $chatbot->getMemory();

// Add custom messages
$memory->addMessage($sessionId, 'system', 'You are a helpful assistant.');
$memory->addMessage($sessionId, 'user', 'Hello!');

// Get message count
$count = $memory->getMessageCount($sessionId);

// Get formatted history for API
$formatted = $memory->getFormattedHistory($sessionId);
// Returns: [['role' => 'system', 'content' => '...'], ...]

// Clear specific session
$memory->clearHistory($sessionId);

Session Cleanup

// Clear specific user's history
$chatbot->clearConversationHistory('user-123');

// Clear all conversations (if storage supports it)
$memory = $chatbot->getMemory();
$storage = $memory->getStorage();
$storage->clear();

Session Management

Session IDs

Session IDs isolate conversations between different users or contexts. Best practices:

// User-based sessions
$sessionId = 'user-' . $userId;

// Thread-based sessions (e.g., support tickets)
$sessionId = 'ticket-' . $ticketId;

// Context-based sessions
$sessionId = 'order-' . $orderId;

// Temporary sessions (anonymous users)
$sessionId = 'guest-' . session_id();

Session Isolation

// User 1's conversation
$chatbot->ask('My name is Alice', sessionId: 'user-1');

// User 2's conversation (completely separate)
$chatbot->ask('My name is Bob', sessionId: 'user-2');

// Each user's context is isolated
$chatbot->ask('What is my name?', sessionId: 'user-1');
// Response: "Your name is Alice."

$chatbot->ask('What is my name?', sessionId: 'user-2');
// Response: "Your name is Bob."

Session Expiration

With Redis storage, sessions automatically expire:

$config = [
    'memory' => [
        'storage' => 'redis',
        'redis_storage' => [
            'ttl' => 3600, // 1 hour
        ],
    ],
];

// Sessions older than 1 hour are automatically deleted

Best Practices

1. Choose Appropriate History Limits

// Short context for simple Q&A
$chatbot = new PhpChatbot(
    apiKey: 'key',
    provider: 'openai',
    maxHistory: 10
);

// Longer context for complex discussions
$chatbot = new PhpChatbot(
    apiKey: 'key',
    provider: 'openai',
    maxHistory: 50
);

// Unlimited history (use with caution)
$chatbot = new PhpChatbot(
    apiKey: 'key',
    provider: 'openai',
    maxHistory: 0
);

Recommendations by model:

  • gpt-4o-mini: 20-40 messages
  • claude-3-5-sonnet: 30-50 messages
  • gemini-1.5-flash: 40-60 messages

2. Use Meaningful Session IDs

// ✅ Good: Descriptive and unique
$sessionId = "user-{$userId}-chat";
$sessionId = "support-ticket-{$ticketId}";
$sessionId = "order-{$orderId}-questions";

// ❌ Bad: Generic or non-unique
$sessionId = "session";
$sessionId = "chat-1";
$sessionId = "user";

3. Clean Up Old Sessions

// Implement periodic cleanup for file/database storage
function cleanupOldSessions(ConversationMemory $memory, int $daysOld = 7) {
    $storage = $memory->getStorage();
    
    // Implementation depends on storage backend
    // For file storage:
    $files = glob('/path/to/conversations/*.json');
    foreach ($files as $file) {
        if (filemtime($file) < time() - ($daysOld * 86400)) {
            unlink($file);
        }
    }
}

// Run via cron job
cleanupOldSessions($chatbot->getMemory(), 7);

4. Handle Memory Gracefully

try {
    $response = $chatbot->ask($message, sessionId: $sessionId);
} catch (\Exception $e) {
    // Log error but continue without memory
    error_log("Memory error: " . $e->getMessage());
    
    // Fallback to stateless mode
    $chatbot->setMemory(null);
    $response = $chatbot->ask($message);
}

5. Monitor Memory Usage

$memory = $chatbot->getMemory();
$count = $memory->getMessageCount($sessionId);

if ($count > 100) {
    // Warn user about large conversation
    echo "Note: This conversation is getting long. Consider starting a new chat.";
}

Performance Considerations

Storage Backend Comparison

Feature File Redis Database
Speed Medium Very Fast Medium-Fast
Scalability Low Very High High
Persistence High Medium* Very High
Setup Complexity Very Low Medium Medium-High
Best For Development Production Enterprise
Concurrent Users Low (10s) Very High (1000s+) High (100s)

*Redis persistence depends on configuration (RDB/AOF)

Optimization Tips

1. Limit History Size

// Smaller history = faster API calls + lower costs
$chatbot = new PhpChatbot(
    apiKey: 'key',
    provider: 'openai',
    maxHistory: 15 // Instead of 50
);

2. Use Redis for High Traffic

// Redis is 10-100x faster than file/database for read/write
$config = [
    'memory' => [
        'storage' => 'redis',
        'redis_storage' => [
            'host' => '127.0.0.1',
            'ttl' => 3600,
        ],
    ],
];

3. Implement Caching

// Cache frequently accessed sessions in memory
class CachedMemory {
    private array $cache = [];
    
    public function getHistory(string $sessionId): array {
        if (!isset($this->cache[$sessionId])) {
            $this->cache[$sessionId] = $this->memory->getHistory($sessionId);
        }
        return $this->cache[$sessionId];
    }
}

4. Batch Operations

// Instead of multiple calls
foreach ($sessions as $sessionId) {
    $chatbot->clearConversationHistory($sessionId); // Slow
}

// Use storage backend directly for batch operations
$storage = $chatbot->getMemory()->getStorage();
$storage->clear(); // Clears all at once

API Reference

PhpChatbot Methods

ask()

public function ask(
    string $message,
    array $options = [],
    ?string $sessionId = null
): string

Ask a question with optional conversation memory.

Parameters:

  • $message - The user's message
  • $options - Additional options (temperature, max_tokens, etc.)
  • $sessionId - Session identifier for conversation memory

Returns: AI model's response

Example:

$response = $chatbot->ask('Hello!', sessionId: 'user-123');

getConversationHistory()

public function getConversationHistory(string $sessionId): array

Retrieve conversation history for a session.

Parameters:

  • $sessionId - Session identifier

Returns: Array of messages with 'role' and 'content'

Example:

$history = $chatbot->getConversationHistory('user-123');

clearConversationHistory()

public function clearConversationHistory(string $sessionId): bool

Clear conversation history for a session.

Parameters:

  • $sessionId - Session identifier

Returns: True on success

Example:

$chatbot->clearConversationHistory('user-123');

getMemory()

public function getMemory(): ?ConversationMemory

Get the ConversationMemory instance.

Returns: ConversationMemory or null if disabled

setMemory()

public function setMemory(?ConversationMemory $memory): void

Set or disable conversation memory.

Parameters:

  • $memory - ConversationMemory instance or null to disable

ConversationMemory Methods

addMessage()

public function addMessage(
    string $sessionId,
    string $role,
    string $content
): void

Add a message to the conversation.

Parameters:

  • $sessionId - Session identifier
  • $role - Message role ('user', 'assistant', 'system')
  • $content - Message content

getHistory()

public function getHistory(string $sessionId): array

Get conversation history.

Returns: Array of messages

clearHistory()

public function clearHistory(string $sessionId): void

Clear conversation history for a session.

getFormattedHistory()

public function getFormattedHistory(string $sessionId): array

Get history formatted for AI model APIs.

Returns: Array of messages with 'role' and 'content' keys

getMessageCount()

public function getMessageCount(string $sessionId): int

Get number of messages in a session.

Returns: Message count

getStorage()

public function getStorage(): MemoryStorageInterface

Get the underlying storage backend.

Returns: Storage implementation


Storage Interface Methods

All storage backends implement MemoryStorageInterface:

store()

public function store(string $sessionId, array $data): bool

Store conversation data.

retrieve()

public function retrieve(string $sessionId): ?array

Retrieve conversation data.

delete()

public function delete(string $sessionId): bool

Delete conversation data.

clear()

public function clear(): bool

Clear all conversation data.

exists()

public function exists(string $sessionId): bool

Check if conversation exists.


Troubleshooting

Memory Not Working

Check if memory is enabled:

$memory = $chatbot->getMemory();
if ($memory === null) {
    echo "Memory is disabled. Enable with enableMemory: true";
}

Verify storage backend:

$config = $chatbot->getConfig();
var_dump($config['memory']);

Redis Connection Failed

// Test Redis connection
try {
    $redis = new Redis();
    $redis->connect('127.0.0.1', 6379);
    $redis->ping();
    echo "Redis connected!";
} catch (Exception $e) {
    echo "Redis error: " . $e->getMessage();
}

Database Table Not Created

// Manually create table
$pdo = new PDO('mysql:host=127.0.0.1;dbname=chatbot', 'root', 'secret');
$pdo->exec("
    CREATE TABLE chatbot_conversations (
        session_id VARCHAR(255) PRIMARY KEY,
        data TEXT NOT NULL,
        updated_at TIMESTAMP NOT NULL
    )
");

File Permission Issues

// Check directory permissions
$path = '/path/to/conversations';
if (!is_writable($path)) {
    chmod($path, 0755);
}

See Also

Clone this wiki locally