-
-
Notifications
You must be signed in to change notification settings - Fork 1
Conversation Memory
Store and retrieve conversation history across multiple interactions, enabling context-aware AI responses.
- Overview
- Quick Start
- Storage Backends
- Configuration
- Usage Examples
- Session Management
- Best Practices
- Performance Considerations
- API Reference
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
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."// 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');Choose the storage backend that best fits your infrastructure and requirements.
Best for: Small to medium applications, simple deployments, development.
$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
);- ✅ 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
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');Best for: High-performance applications, distributed systems, auto-expiring sessions.
Install either:
- PHP Redis extension:
pecl install redis - Predis library:
composer require predis/predis
$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
);- ✅ 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)
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);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);Best for: Enterprise applications, persistent storage, complex querying.
- PDO extension enabled
- Database driver (MySQL, PostgreSQL, or SQLite)
$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
);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',
]- ✅ 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)
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);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
);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
);$chatbot = new PhpChatbot(
apiKey: 'your-api-key',
provider: 'openai',
enableMemory: true,
maxHistory: 20,
storageDriver: 'file'
);$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."$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?"// 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.$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);// 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 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();// 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."With Redis storage, sessions automatically expire:
$config = [
'memory' => [
'storage' => 'redis',
'redis_storage' => [
'ttl' => 3600, // 1 hour
],
],
];
// Sessions older than 1 hour are automatically deleted// 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
// ✅ 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";// 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);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);
}$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.";
}| 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)
// Smaller history = faster API calls + lower costs
$chatbot = new PhpChatbot(
apiKey: 'key',
provider: 'openai',
maxHistory: 15 // Instead of 50
);// Redis is 10-100x faster than file/database for read/write
$config = [
'memory' => [
'storage' => 'redis',
'redis_storage' => [
'host' => '127.0.0.1',
'ttl' => 3600,
],
],
];// 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];
}
}// 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 oncepublic function ask(
string $message,
array $options = [],
?string $sessionId = null
): stringAsk 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');public function getConversationHistory(string $sessionId): arrayRetrieve conversation history for a session.
Parameters:
-
$sessionId- Session identifier
Returns: Array of messages with 'role' and 'content'
Example:
$history = $chatbot->getConversationHistory('user-123');public function clearConversationHistory(string $sessionId): boolClear conversation history for a session.
Parameters:
-
$sessionId- Session identifier
Returns: True on success
Example:
$chatbot->clearConversationHistory('user-123');public function getMemory(): ?ConversationMemoryGet the ConversationMemory instance.
Returns: ConversationMemory or null if disabled
public function setMemory(?ConversationMemory $memory): voidSet or disable conversation memory.
Parameters:
-
$memory- ConversationMemory instance or null to disable
public function addMessage(
string $sessionId,
string $role,
string $content
): voidAdd a message to the conversation.
Parameters:
-
$sessionId- Session identifier -
$role- Message role ('user', 'assistant', 'system') -
$content- Message content
public function getHistory(string $sessionId): arrayGet conversation history.
Returns: Array of messages
public function clearHistory(string $sessionId): voidClear conversation history for a session.
public function getFormattedHistory(string $sessionId): arrayGet history formatted for AI model APIs.
Returns: Array of messages with 'role' and 'content' keys
public function getMessageCount(string $sessionId): intGet number of messages in a session.
Returns: Message count
public function getStorage(): MemoryStorageInterfaceGet the underlying storage backend.
Returns: Storage implementation
All storage backends implement MemoryStorageInterface:
public function store(string $sessionId, array $data): boolStore conversation data.
public function retrieve(string $sessionId): ?arrayRetrieve conversation data.
public function delete(string $sessionId): boolDelete conversation data.
public function clear(): boolClear all conversation data.
public function exists(string $sessionId): boolCheck if conversation exists.
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']);// 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();
}// 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
)
");// Check directory permissions
$path = '/path/to/conversations';
if (!is_writable($path)) {
chmod($path, 0755);
}