This guide walks you through implementing Meilisearch’s chat completions feature to create conversational search experiences in your application.

The chat completions feature is experimental and must be enabled before use. See experimental features for activation instructions.

Prerequisites

Before starting, ensure you have:

  • Meilisearch instance running (v1.15.1 or later)
  • An API key from an LLM provider (OpenAI, Azure OpenAI, Mistral, Gemini, or access to a vLLM server)
  • At least one index with searchable content
  • The chat completions experimental feature enabled

Quick start

Understanding workspaces

Think of workspaces as different “assistants” you can create for various purposes. Each workspace can have its own personality (system prompt) and capabilities. The best part? Workspaces are created automatically when you configure them – no separate creation step needed!

For example:

  • customer-support - A helpful assistant for customer queries
  • product-search - An expert at finding the perfect product
  • docs-helper - A technical assistant for documentation

Enable the chat completions feature

First, enable the chat completions experimental feature:

curl \
  -X PATCH 'http://localhost:7700/experimental-features' \
  -H 'Authorization: Bearer MASTER_KEY' \
  -H 'Content-Type: application/json' \
  --data-binary '{
    "chatCompletions": true
  }'

Configure a chat completions workspace

Create a workspace with your LLM provider settings. Here are examples for different providers:

curl \
  -X PATCH 'http://localhost:7700/chats/my-assistant/settings' \
  -H 'Authorization: Bearer MASTER_KEY' \
  -H 'Content-Type: application/json' \
  --data-binary '{
    "source": "openAi",
    "apiKey": "sk-abc...",
    "prompts": {
      "system": "You are a helpful assistant. Answer questions based only on the provided context."
    }
  }'

Send your first chat completions request

Now you can start a conversation:

curl \
  -X POST 'http://localhost:7700/chats/my-assistant/chat/completions' \
  -H 'Authorization: Bearer DEFAULT_CHAT_KEY' \
  -H 'Content-Type: application/json' \
  --data-binary '{
    "model": "gpt-3.5-turbo",
    "messages": [
      {
        "role": "user",
        "content": "What is Meilisearch?"
      }
    ],
    "stream": true
  }'

Building a chat interface with OpenAI SDK

Since Meilisearch’s chat endpoint is OpenAI-compatible, you can use the official OpenAI SDK:

import OpenAI from 'openai';

const client = new OpenAI({
  baseURL: 'http://localhost:7700/chats/my-assistant',
  apiKey: 'YOUR_MEILISEARCH_API_KEY',
});

const completion = await client.chat.completions.create({
  model: 'gpt-3.5-turbo',
  messages: [{ role: 'user', content: 'What is Meilisearch?' }],
  stream: true,
});

for await (const chunk of completion) {
  console.log(chunk.choices[0]?.delta?.content || '');
}

Error handling

When using the OpenAI SDK with Meilisearch’s chat completions endpoint, errors from the streamed responses are natively handled by the official OpenAI SDK. This means you can use the SDK’s built-in error handling mechanisms without additional configuration:

import OpenAI from 'openai';

const client = new OpenAI({
  baseURL: 'http://localhost:7700/chats/my-assistant',
  apiKey: 'YOUR_MEILISEARCH_API_KEY',
});

try {
  const stream = await client.chat.completions.create({
    model: 'gpt-3.5-turbo',
    messages: [{ role: 'user', content: 'What is Meilisearch?' }],
    stream: true,
  });

  for await (const chunk of stream) {
    console.log(chunk.choices[0]?.delta?.content || '');
  }
} catch (error) {
  // OpenAI SDK automatically handles streaming errors
  console.error('Chat completion error:', error);
}

Managing conversations

Since Meilisearch keeps your data private and doesn’t store conversations, you’ll need to manage conversation history in your application. Here’s a simple approach:

// Store conversation history in your app
const conversation = [];

// Add user message
conversation.push({ role: 'user', content: 'What is Meilisearch?' });

// Get response and add to history
const response = await client.chat.completions.create({
  model: 'gpt-3.5-turbo',
  messages: conversation,
  stream: true,
});

// Add assistant response to history
let assistantMessage = '';
for await (const chunk of response) {
  assistantMessage += chunk.choices[0]?.delta?.content || '';
}
conversation.push({ role: 'assistant', content: assistantMessage });

// Use the full conversation for follow-up questions
conversation.push({ role: 'user', content: 'Can it handle typos?' });
// ... continue the conversation

Remember: Each request is independent, so always send the full conversation history if you want the AI to remember previous exchanges.

Next steps