Skip to content

Vector Databases & RAG

When to Use

Use vector databases for semantic search, content similarity analysis, and RAG (Retrieval-Augmented Generation) workflows. Use when you need to find conceptually similar content, power AI chatbots with site context, or analyze content relationships.

Decision

Provider Stability Best For Scale
SQLite Stable Development, small sites < 10K documents
PostgreSQL Beta Self-hosted, familiar tech stack < 100K documents
Milvus Beta Large scale, production (most popular) 100K+ documents
Pinecone Experimental Cloud-managed, serverless Any scale
Azure AI Search Beta Microsoft ecosystem Enterprise

Setup Pattern

Step 1: Install VDB Provider Module

drush en ai_vdb_provider_milvus ai_search

Step 2: Configure VDB Connection Navigate to /admin/config/ai/vdb-providers:

# Milvus configuration example
provider: milvus
connection:
  host: localhost
  port: 19530
  database: drupal
  collection: content_embeddings
embedding:
  provider: openai
  model: text-embedding-3-large
  dimensions: 3072

Step 3: Configure AI Search The ai_search module integrates VDB with Search API:

# /admin/config/search/search-api
index_id: ai_content_index
datasources:
  - entity:node
fields:
  title: text
  body: text
  field_summary: text
  field_tags: entity_reference
processor:
  ai_embedding:
    provider: openai
    model: text-embedding-3-large
    chunk_size: 512
    chunk_overlap: 50
server:
  backend: ai_vdb
  vdb_provider: milvus

Embedding & Indexing

Text Chunking: Long content must be chunked for embedding models (token limits):

$chunker = \Drupal::service('ai.text_chunker');

// Chunk text with overlap for context preservation
$chunks = $chunker->chunkText($long_text, [
  'max_tokens' => 512,
  'overlap_tokens' => 50,
  'preserve_sentences' => TRUE,
]);

// Generate embeddings for each chunk
$embeddings = [];
foreach ($chunks as $chunk) {
  $embeddings[] = $ai_provider->embed($chunk, 'text-embedding-3-large');
}

RAG Implementation

RAG (Retrieval-Augmented Generation) combines vector search with LLM generation to provide accurate, context-aware responses.

Pattern: AI Chatbot with RAG

class RagChatbot {

  public function generateResponse(string $user_query): string {
    // Step 1: Generate query embedding
    $query_embedding = $this->aiProvider->embed(
      $user_query,
      'text-embedding-3-large'
    );

    // Step 2: Retrieve relevant content via vector search
    $vdb = \Drupal::service('ai.vdb_provider');
    $relevant_chunks = $vdb->proximitySearch($query_embedding, 5);

    // Step 3: Build context from retrieved chunks
    $context = '';
    foreach ($relevant_chunks as $chunk) {
      $context .= $chunk['text'] . "\n\n";
    }

    // Step 4: Generate response with context
    $prompt = sprintf(
      "Answer this question using ONLY the context provided. If the answer is not in the context, say 'I don't have information about that.'\n\nContext:\n%s\n\nQuestion: %s",
      $context,
      $user_query
    );

    $response = $this->aiProvider->chat([
      ['role' => 'system', 'content' => 'You are a helpful assistant that answers questions using provided context.'],
      ['role' => 'user', 'content' => $prompt]
    ], 'gpt-4');

    return $response;
  }

}

Benefits of RAG: - Reduces hallucination (AI making up facts) - Provides source attribution (can link to original content) - Keeps responses current (always uses latest indexed content) - Maintains control over knowledge base

Content Intelligence Use Cases

Similar Content Discovery:

// Find articles similar to current article
$current_embedding = $node->get('field_embedding')->value;
$similar = $vdb->proximitySearch($current_embedding, 5, [
  'filters' => [
    'content_type' => 'article',
    'exclude_id' => $node->id(),
  ],
]);

Semantic Tag Suggestions:

// Suggest tags based on content similarity
$content_embedding = $ai_provider->embed($node->body->value);
$similar_content = $vdb->proximitySearch($content_embedding, 20);

$tag_frequency = [];
foreach ($similar_content as $item) {
  foreach ($item['tags'] as $tag) {
    $tag_frequency[$tag] = ($tag_frequency[$tag] ?? 0) + 1;
  }
}

// Sort by frequency and return top 5
arsort($tag_frequency);
$suggested_tags = array_slice(array_keys($tag_frequency), 0, 5);

Common Mistakes

  • Wrong: Not chunking long content → Right: Embedding models have token limits (512-8192); long content must be chunked or truncated
  • Wrong: Using wrong similarity metric → Right: OpenAI embeddings use cosine similarity; using euclidean distance produces poor results
  • Wrong: Not handling embedding model changes → Right: Switching embedding models requires complete re-indexing; plan migrations carefully
  • Wrong: Ignoring embedding costs → Right: Embedding generation costs per token; batch processing and caching are essential at scale
  • Wrong: Trusting RAG responses without source attribution → Right: Always include source references so users can verify AI responses
  • Wrong: Not implementing RAG filtering → Right: Without filters, chatbot may pull irrelevant or outdated content; filter by date, content type, publication status

See Also

  • Content Quality & Review
  • Security & Privacy
  • Reference: /modules/contrib/ai/modules/ai_search/
  • Reference: https://www.thedroptimes.com/64433/unlocking-ai-search-in-drupal-practical-guide-vector-database-modules
  • Reference: https://www.droptica.com/blog/recommended-vector-databases-vdb-drupal-overview-ai-providers/
  • Reference: https://www.brainsum.com/blog/ai-chatbot-demo-drupal-and-rag
  • Reference: https://www.vardot.com/en-us/ideas/blog/step-step-guide-creating-rag-based-drupal-ai-chatbot