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 Meilisearch Message Store Laravel Package

symfony/ai-meilisearch-message-store

Meilisearch Message Store integrates Meilisearch as a persistent message store for Symfony AI Chat. Index and query chat messages using Meilisearch APIs, with support for async task handling and configurable index settings via Meilisearch.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Install the Package

    composer require symfony/ai-meilisearch-message-store meilisearch/meilisearch-php
    

    For Laravel compatibility, ensure symfony/http-client is replaced with Laravel’s Http facade or Guzzle via a custom adapter (see Implementation Patterns).

  2. Configure Meilisearch Add to .env:

    MEILISEARCH_HOST=http://localhost:7700
    MEILISEARCH_API_KEY=your-api-key
    MEILISEARCH_INDEX=chat_messages  # Default index name
    
  3. Register the Message Store In AppServiceProvider or a dedicated service provider:

    use Symfony\Component\Ai\Chat\MessageStore\MeilisearchMessageStore;
    use Meilisearch\Client;
    
    public function register()
    {
        $this->app->singleton(\Symfony\Component\Ai\Chat\MessageStore\MessageStoreInterface::class, function ($app) {
            $client = new Client(
                env('MEILISEARCH_HOST'),
                env('MEILISEARCH_API_KEY')
            );
            return new MeilisearchMessageStore($client, env('MEILISEARCH_INDEX'));
        });
    }
    
  4. First Use Case: Store and Retrieve Messages

    use Symfony\Component\Ai\Chat\Message;
    use Symfony\Component\Ai\Chat\MessageStore\MessageStoreInterface;
    
    // Store a message
    $message = new Message(
        'conv-123',
        'user-456',
        'What is Laravel?',
        'user',
        'Laravel is a PHP framework...',
        ['timestamp' => now()->toDateTimeString()]
    );
    
    $store = app(MessageStoreInterface::class);
    $store->save($message);
    
    // Retrieve messages
    $messages = $store->findByConversationId('conv-123');
    
  5. Verify with Tinker

    php artisan tinker
    
    >>> $store = app(\Symfony\Component\Ai\Chat\MessageStore\MessageStoreInterface::class);
    >>> $messages = $store->findByConversationId('conv-123');
    >>> dd($messages);
    

Implementation Patterns

1. Adapter Layer for Laravel

Since the package is Symfony-focused, create a Laravel-compatible adapter:

// app/Providers/MeilisearchServiceProvider.php
namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Meilisearch\Client;
use Symfony\Component\Ai\Chat\MessageStore\MeilisearchMessageStore;

class MeilisearchServiceProvider extends ServiceProvider
{
    public function register()
    {
        $this->app->singleton(\Symfony\Component\Ai\Chat\MessageStore\MessageStoreInterface::class, function ($app) {
            $client = new Client(
                config('meilisearch.host'),
                config('meilisearch.api_key')
            );
            return new MeilisearchMessageStore($client, config('meilisearch.index'));
        });
    }
}

Configure in config/meilisearch.php:

return [
    'host' => env('MEILISEARCH_HOST', 'http://localhost:7700'),
    'api_key' => env('MEILISEARCH_API_KEY'),
    'index' => env('MEILISEARCH_INDEX', 'chat_messages'),
];

2. Message Serialization

Customize how messages are serialized/deserialized for Meilisearch:

// app/Services/MeilisearchMessageMapper.php
namespace App\Services;

use Symfony\Component\Ai\Chat\Message;
use Symfony\Component\Ai\Chat\MessageStore\MessageStoreInterface;

class MeilisearchMessageMapper
{
    public function toArray(Message $message): array
    {
        return [
            'id' => $message->getId(),
            'conversationId' => $message->getConversationId(),
            'role' => $message->getRole(),
            'content' => $message->getContent(),
            'createdAt' => $message->getCreatedAt()?->format('Y-m-d\TH:i:sP'),
            'metadata' => $message->getMetadata() ?? [],
        ];
    }

    public function toMessage(array $data): Message
    {
        return new Message(
            $data['conversationId'],
            $data['role'] === 'user' ? 'user' : 'assistant',
            $data['content'],
            $data['role'],
            null,
            $data['metadata'] ?? []
        );
    }
}

Inject the mapper into MeilisearchMessageStore via constructor or setter.

3. Async Operations

Handle Meilisearch’s async tasks (e.g., index updates) with Laravel queues:

// app/Services/MeilisearchAsyncHandler.php
namespace App\Services;

use Illuminate\Support\Facades\Queue;
use Meilisearch\Client;
use Meilisearch\Tasks\Task;

class MeilisearchAsyncHandler
{
    public function handleTask(Client $client, string $taskUid): void
    {
        Queue::dispatch(function () use ($client, $taskUid) {
            $task = $client->waitForTask($taskUid);
            if (!$task->getStatusData()['completed_at']) {
                $this->handleTask($client, $taskUid); // Retry
            }
        });
    }
}

Use in MeilisearchMessageStore:

public function save(Message $message)
{
    $data = $this->mapper->toArray($message);
    $task = $this->client->index($this->index)->addDocuments([$data]);
    $this->asyncHandler->handleTask($this->client, $task->getTaskUid());
}

4. Search Optimization

Customize search queries for Laravel use cases:

// app/Services/MeilisearchSearcher.php
namespace App\Services;

use Symfony\Component\Ai\Chat\MessageStore\MeilisearchMessageStore;

class MeilisearchSearcher
{
    public function searchByQuery(MeilisearchMessageStore $store, string $query, int $limit = 10)
    {
        return $store->client->index($store->index)->search($query, [
            'limit' => $limit,
            'attributesToRetrieve' => ['content', 'role', 'createdAt'],
            'filter' => ['role = user'], // Example: Only search user messages
        ]);
    }
}

5. Multi-Tenancy Support

Isolate message stores per tenant:

// app/Services/TenantAwareMeilisearchStore.php
namespace App\Services;

use Illuminate\Support\Facades\Auth;
use Symfony\Component\Ai\Chat\MessageStore\MeilisearchMessageStore;

class TenantAwareMeilisearchStore extends MeilisearchMessageStore
{
    public function __construct(MeilisearchMessageStore $store)
    {
        $tenantId = Auth::guard('tenant')->id();
        parent::__construct($store->client, "tenant_{$tenantId}_{$store->index}");
    }
}

Register in AppServiceProvider:

$this->app->singleton(MessageStoreInterface::class, function ($app) {
    return new TenantAwareMeilisearchStore(
        $app->make(MeilisearchMessageStore::class)
    );
});

6. Hybrid Search (Keyword + Semantic)

Combine Meilisearch’s keyword search with vector similarity:

// app/Services/HybridSearcher.php
namespace App\Services;

use Symfony\Component\Ai\Chat\MessageStore\MeilisearchMessageStore;

class HybridSearcher
{
    public function search(MeilisearchMessageStore $store, string $query, array $vector)
    {
        // Keyword search
        $keywordResults = $store->client->index($store->index)->search($query, [
            'limit' => 5,
        ]);

        // Vector search (requires Meilisearch with vector module)
        $vectorResults = $store->client->index($store->index)->search($vector, [
            'limit' => 5,
            'using' => 'vector', // Requires Meilisearch 1.0+
        ]);

        // Merge results (custom logic)
        return array_merge($keywordResults['hits'], $vectorResults['hits']);
    }
}

Gotchas and Tips

Pitfalls

  1. Async Task Timeouts

    • Meilisearch tasks may take seconds to complete. Always handle async operations with retries or callbacks.
    • Fix: Use Laravel queues with exponential backoff (e.g., laravel-queue-retries package).
  2. Index Schema Mismatches

    • Meilisearch requires consistent schemas. Changing message structures mid-flight can corrupt data.
    • Fix: Version your indexes (e.g., chat_messages_v1, `chat_messages_v2
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.
terminal42/code-quality-tools
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky