Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Ai Cache Message Store Laravel Package

symfony/ai-cache-message-store

PSR-6 cache-backed message store for Symfony AI Chat. Persist and retrieve chat messages using any PSR-6 cache pool for lightweight conversation history across requests. Part of the Symfony AI ecosystem.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Install the Package Require the package in your Laravel project:

    composer require symfony/ai-cache-message-store
    
  2. Configure PSR-6 Cache Ensure your Laravel cache driver (Redis, database, etc.) is properly set in .env:

    CACHE_DRIVER=redis
    
  3. Create a Laravel-Compatible Wrapper Since this package is Symfony-focused, create a Laravel service provider to bridge the gap:

    // app/Providers/AiCacheServiceProvider.php
    namespace App\Providers;
    
    use Illuminate\Support\ServiceProvider;
    use Symfony\Component\AI\Chat\CacheMessageStore;
    use Symfony\Component\AI\Chat\MessageStoreInterface;
    use Symfony\Contracts\Cache\CacheInterface;
    
    class AiCacheServiceProvider extends ServiceProvider
    {
        public function register()
        {
            $this->app->singleton(MessageStoreInterface::class, function ($app) {
                return new CacheMessageStore(
                    $app->make(CacheInterface::class)
                );
            });
        }
    }
    

    Register the provider in config/app.php.

  4. First Use Case: Caching AI Chat Messages Use the message store to persist and retrieve chat messages:

    use Symfony\Component\AI\Chat\Message;
    use Symfony\Component\AI\Chat\MessageStoreInterface;
    
    $messageStore = app(MessageStoreInterface::class);
    
    // Save a message
    $message = new Message('user', 'Hello, AI!');
    $messageStore->save($message, 'chat_id_123');
    
    // Retrieve messages
    $messages = $messageStore->findAll('chat_id_123');
    

Implementation Patterns

Core Workflows

  1. Hybrid Storage Integration Combine cache with a database for durability:

    // app/Services/HybridMessageStore.php
    use Symfony\Component\AI\Chat\CacheMessageStore;
    use Symfony\Component\AI\Chat\MessageStoreInterface;
    use Illuminate\Support\Facades\Cache;
    
    class HybridMessageStore implements MessageStoreInterface
    {
        public function __construct(
            private CacheMessageStore $cacheStore,
            private \App\Models\ChatMessage $model
        ) {}
    
        public function findAll(string $chatId): array
        {
            $cached = $this->cacheStore->findAll($chatId);
            if ($cached) return $cached;
    
            $messages = $this->model->where('chat_id', $chatId)->get();
            $this->cacheStore->saveMany($messages, $chatId);
            return $messages;
        }
    
        public function save(\Symfony\Component\AI\Chat\Message $message, string $chatId): void
        {
            $this->cacheStore->save($message, $chatId);
            $this->model->create([
                'chat_id' => $chatId,
                'role' => $message->getRole(),
                'content' => $message->getContent(),
            ]);
        }
    }
    
  2. Cache Warming for Performance Preload frequently accessed chat histories:

    // app/Console/Commands/WarmAiCache.php
    use Illuminate\Console\Command;
    use Symfony\Component\AI\Chat\MessageStoreInterface;
    
    class WarmAiCache extends Command
    {
        protected $signature = 'ai:cache:warm';
        protected $description = 'Preload active chat histories into cache';
    
        public function handle(MessageStoreInterface $messageStore)
        {
            $activeChats = \App\Models\Chat::active()->pluck('id');
            foreach ($activeChats as $chatId) {
                $messageStore->findAll($chatId);
            }
        }
    }
    
  3. TTL-Based Message Expiration Dynamically set TTLs based on message age:

    // app/Services/DynamicTtlMessageStore.php
    use Symfony\Component\AI\Chat\CacheMessageStore;
    
    class DynamicTtlMessageStore extends CacheMessageStore
    {
        public function save(\Symfony\Component\AI\Chat\Message $message, string $chatId, ?int $ttl = null): void
        {
            $defaultTtl = $this->calculateTtl($message);
            parent::save($message, $chatId, $defaultTtl ?? 3600);
        }
    
        private function calculateTtl(\Symfony\Component\AI\Chat\Message $message): ?int
        {
            if ($message->getRole() === 'system') return 86400; // 24h for system messages
            if (str_contains($message->getContent(), 'urgent')) return 300; // 5min for urgent
            return null; // Use default
        }
    }
    

Laravel-Specific Patterns

  1. Cache Tagging for Invalidation Use Laravel's cache tags to invalidate related messages:

    $cache = Cache::store('redis')->getAdapter();
    $messageStore = new CacheMessageStore($cache);
    
    // Save with tags
    $messageStore->save($message, 'chat_id_123', 3600, ['chat:123', 'user:456']);
    
    // Invalidate on user update
    Cache::tags(['user:456'])->flush();
    
  2. Event-Driven Cache Updates Listen to model events to keep cache in sync:

    // app/Providers/EventServiceProvider.php
    use App\Models\ChatMessage;
    use Symfony\Component\AI\Chat\MessageStoreInterface;
    
    protected $listen = [
        ChatMessage::class => [
            'deleted' => ['App\Listeners\InvalidateChatCache'],
        ],
    ];
    
  3. Queue-Based Cache Population Offload cache population to queues for long-running operations:

    // app/Jobs/PopulateChatCache.php
    use Symfony\Component\AI\Chat\MessageStoreInterface;
    
    class PopulateChatCache implements ShouldQueue
    {
        public function handle(MessageStoreInterface $messageStore)
        {
            $chat = \App\Models\Chat::find($this->chatId);
            $messages = $chat->messages()->get();
            $messageStore->saveMany($messages, $chat->id);
        }
    }
    

Gotchas and Tips

Common Pitfalls

  1. Serialization Issues

    • Problem: Complex message objects may fail to serialize.
    • Fix: Implement JsonSerializable or use a custom serializer:
      class Message implements JsonSerializable
      {
          public function jsonSerialize(): array
          {
              return [
                  'role' => $this->role,
                  'content' => $this->content,
                  'timestamp' => $this->timestamp->getTimestamp(),
              ];
          }
      }
      
  2. Cache Key Collisions

    • Problem: Default key generation may cause collisions.
    • Fix: Customize the key prefix or strategy:
      $messageStore = new CacheMessageStore($cache, 'ai_chat_');
      
  3. TTL Misconfiguration

    • Problem: Messages disappearing unexpectedly.
    • Fix: Set appropriate TTLs and monitor cache stats:
      redis-cli info stats | grep keyspace_hits
      
  4. Symfony Dependency Conflicts

    • Problem: Version mismatches with Symfony components.
    • Fix: Pin versions in composer.json:
      "require": {
          "symfony/ai": "^0.8",
          "symfony/cache": "^6.0"
      }
      

Debugging Tips

  1. Cache Miss Analysis Use Laravel's cache debugging:

    Cache::remember('debug:cache_stats', 60, function () {
        return Cache::store('redis')->getAdapter()->getStats();
    });
    
  2. Message Store Logging Add debug logging to track cache operations:

    $messageStore = new CacheMessageStore($cache);
    $messageStore->setLogger(new \Monolog\Logger('ai_cache', [
        new \Monolog\Handler\StreamHandler(storage_path('logs/ai_cache.log'))
    ]));
    
  3. Redis Memory Monitoring Track memory usage to prevent evictions:

    redis-cli info memory
    

Extension Points

  1. Custom Cache Adapter Extend the message store to support custom cache logic:

    class CustomCacheMessageStore extends CacheMessageStore
    {
        public function findAll(string $chatId): array
        {
            $key = $this->getKey($chatId);
            $item = $this->cache->getItem($key);
    
            if (!$item->isHit()) {
                $messages = $this->fetchFromDatabase($chatId);
                $item->set($messages);
                $this->cache->save($item);
            }
    
            return $item->get();
        }
    }
    
  2. Event Dispatching Trigger events for cache operations:

    class EventfulMessageStore extends CacheMessageStore
    {
        public function save(\Symfony\Component\AI\Chat\Message $message, string $chatId, ?int $ttl = null):
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
nexmo/api-specification
capell-app/block-library
axium/identity
cetria/laravel-dummy-models
cetria/reflection-helper
agropredict/sso-auth-bundle
evolvestudio/spam-protection
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
ecotone/kafka
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php
splash/sonata-admin
splash/metadata