Drupal AI provider module for Quant Cloud platform (QuantCDN & QuantGov Cloud).
This module provides a standard Drupal AI provider that connects to Quant Cloud AI services, giving you access to AWS Bedrock models (Claude, Nova, Titan) through the Quant Cloud platform.
A provider module is a connector between Drupal and external AI services. It implements standard Drupal AI interfaces so that other modules can use AI capabilities without worrying about the underlying API.
This module provides:
- ✅ Chat completions (multi-turn conversations)
- ✅ Streaming responses (real-time chat)
- ✅ Function calling / Tool execution (with auto-execute support)
- ✅ Embeddings generation (for semantic search)
- ✅ VectorDB provider (semantic search with AI Search module)
- ✅ Text-to-image generation (AWS Bedrock Nova Canvas)
- ✅ Image-to-image transformations (variations, inpainting, outpainting, background removal)
- ✅ Structured output (JSON Schema validation)
- ✅ Dynamic model discovery from Quant Cloud API
- ✅ OAuth2 authentication
- ✅ Automatic request routing through Quant Cloud Dashboard
This module does NOT include:
- ❌ User interface components (chatbots, forms)
- ❌ Content generation features
- ❌ Business logic
For features, install consumer modules such as:
ai_automator- Automated content generationai_content- AI-powered content tools- Or build your own custom modules using the Drupal AI API
- Drupal 10.3+ or Drupal 11+
- AI module
- Key module
- Active Quant Cloud account (QuantCDN or QuantGov Cloud)
composer require drupal/ai drupal/key
drush en -y ai key
# Enable this module (when installed in custom/modules)
drush en -y ai_provider_quant_cloud- Go to Configuration > System > Keys
- Click "Add key"
- Fill in:
- Key name: "Quant Cloud Access Token"
- Key type: "Authentication"
- Key provider: "Configuration"
- Key value: Your OAuth token from the Quant Cloud dashboard
- Go to Configuration > AI > Quant Cloud AI
- Select your platform (QuantCDN or QuantGov Cloud)
- Choose authentication method:
- OAuth (recommended): Click "Connect to Quant Cloud" to authorize
- Manual Token: Select the access token key you created
- Select your organization from the dropdown
- Save configuration
After saving, the module will:
- Validate your access token
- Fetch available AI models from Quant Cloud
- Cache model information for 1 hour
- Display connection status on the configuration page
Configure additional options in the "Advanced Settings" section:
- Enable Request/Response Logging: Turn on detailed logging for debugging
- Streaming Timeout: Adjust timeout for streaming responses (default: 60s)
- Image Generation Options:
- Default resolution (512x512 to 2048x2048)
- Quality preset (standard/premium)
- Visual style (photorealistic, digital-art, illustration, etc.)
- Negative prompts for unwanted elements
- Model Parameters:
- Temperature (0.0 - 1.0)
- Max tokens (1 - 4096)
- Top P sampling
<?php
// Get the AI provider service
$provider = \Drupal::service('ai.provider')->createInstance('quant_cloud');
// Simple string input
$response = $provider->chat(
'What is Drupal?',
'amazon.nova-lite-v1:0'
);
// Get the response text
$text = $response->getNormalized()->getText();
// Display
\Drupal::messenger()->addMessage($text);<?php
use Drupal\ai\OperationType\Chat\ChatInput;
use Drupal\ai\OperationType\Chat\ChatMessage;
// Create conversation
$messages = [
new ChatMessage('user', 'What is Drupal?'),
new ChatMessage('assistant', 'Drupal is a powerful open-source CMS...'),
new ChatMessage('user', 'What are its main features?'),
];
$input = new ChatInput($messages);
$response = $provider->chat($input, 'anthropic.claude-3-5-sonnet-20241022-v2:0');
$text = $response->getNormalized()->getText();<?php
use Drupal\ai\OperationType\Chat\ChatInput;
use Drupal\ai\OperationType\Chat\ChatMessage;
// Create chat input
$messages = [new ChatMessage('user', 'Tell me a story about Drupal')];
$input = new ChatInput($messages);
// Stream the response
$stream = $provider->streamedChat($input, 'anthropic.claude-3-5-sonnet-20241022-v2:0');
// Iterate through chunks as they arrive
foreach ($stream as $message) {
echo $message->getText(); // Print each chunk in real-time
}<?php
use Drupal\ai\OperationType\Embeddings\EmbeddingsInput;
// Single text
$response = $provider->embeddings(
'This is a test document',
'amazon.titan-embed-text-v2:0'
);
// Multiple texts
$texts = [
'Government services',
'Tax information',
'Healthcare resources',
];
$input = new EmbeddingsInput($texts);
$response = $provider->embeddings($input, 'amazon.titan-embed-text-v2:0');
// Get embedding vectors
$vectors = $response->getEmbeddings();
// Returns: Array of 1024-dimensional vectors<?php
use Drupal\ai\OperationType\TextToImage\TextToImageInput;
// Generate an image
$input = new TextToImageInput('A beautiful sunset over mountains');
$response = $provider->textToImage($input, 'amazon.nova-canvas-v1:0');
// Get generated images
$images = $response->getImages();
foreach ($images as $image) {
$file = $image->getFile(); // Drupal file entity
// Use $file->getFileUri() to get the file path
}<?php
use Drupal\ai\OperationType\ImageToImage\ImageToImageInput;
use Drupal\file_mdm\FileMetadataInterface;
// Load source image
$file = \Drupal::entityTypeManager()
->getStorage('file')
->load($fid);
// Create image transformation input
$input = new ImageToImageInput(
$file,
'Make this photo look like a watercolor painting',
'image_variation' // or 'inpainting', 'outpainting', 'background_removal'
);
$response = $provider->imageToImage($input, 'amazon.nova-canvas-v1:0');
// Get transformed images
$images = $response->getImages();<?php
use Drupal\ai\OperationType\Chat\ChatInput;
use Drupal\ai\OperationType\Chat\ChatMessage;
use Drupal\ai\OperationType\Chat\ToolsInput;
use Drupal\ai\OperationType\Chat\Tools\ToolsFunctionInput;
// Define a custom function/tool
$get_weather = new ToolsFunctionInput(
'get_weather',
'Get current weather for a location',
[
'type' => 'object',
'properties' => [
'location' => [
'type' => 'string',
'description' => 'City name',
],
'unit' => [
'type' => 'string',
'enum' => ['celsius', 'fahrenheit'],
],
],
'required' => ['location'],
]
);
$tools = new ToolsInput([$get_weather]);
// Ask a question that requires the tool
$messages = [new ChatMessage('user', 'What is the weather like in Sydney?')];
$input = new ChatInput($messages);
$input->setChatTools($tools);
$response = $provider->chat($input, 'anthropic.claude-3-5-sonnet-20241022-v2:0');
// Check if AI wants to call a function
if ($response->getNormalized()->getTools()) {
foreach ($response->getNormalized()->getTools() as $tool_call) {
$function_name = $tool_call->getName();
$arguments = $tool_call->getInput();
// Execute your function
if ($function_name === 'get_weather') {
$weather_data = my_weather_api_call($arguments['location']);
// Send result back to AI
$messages[] = new ChatMessage('assistant', '', $response->getNormalized()->getTools());
$messages[] = new ChatMessage('tool_result', json_encode($weather_data), [], ['tool_call_id' => $tool_call->getId()]);
$input = new ChatInput($messages);
$input->setChatTools($tools);
$final_response = $provider->chat($input, 'anthropic.claude-3-5-sonnet-20241022-v2:0');
echo $final_response->getNormalized()->getText();
// "The weather in Sydney is currently 22°C and sunny."
}
}
}<?php
use Drupal\ai\OperationType\Chat\ChatInput;
use Drupal\ai\OperationType\Chat\ChatMessage;
// Define JSON Schema
$schema = [
'type' => 'object',
'properties' => [
'name' => ['type' => 'string'],
'age' => ['type' => 'integer'],
'email' => ['type' => 'string', 'format' => 'email'],
],
'required' => ['name', 'age'],
];
// Request structured output
$messages = [new ChatMessage('user', 'Extract: John Doe, 35 years old, john@example.com')];
$input = new ChatInput($messages);
$response = $provider->chat(
$input,
'amazon.nova-pro-v1:0',
['json_schema' => $schema]
);
// Parse JSON response
$data = json_decode($response->getNormalized()->getText(), TRUE);
// Returns: ['name' => 'John Doe', 'age' => 35, 'email' => 'john@example.com']Models are dynamically fetched from the Quant Cloud API. Here are the commonly available models:
amazon.nova-lite-v1:0- Fast and affordable, great for most tasksamazon.nova-micro-v1:0- Ultra-fast for simple queriesamazon.nova-pro-v1:0- Advanced capabilities, vision supportanthropic.claude-3-5-sonnet-20241022-v2:0- Latest Claude (recommended)anthropic.claude-3-5-sonnet-20240620-v1:0- Claude 3.5anthropic.claude-3-sonnet-20240229-v1:0- Claude 3anthropic.claude-3-haiku-20240307-v1:0- Claude Haiku (fast)
amazon.titan-embed-text-v2:0- Text embeddings (256/512/1024 dimensions)cohere.embed-english-v3- English text embeddingscohere.embed-multilingual-v3- Multilingual embeddings
amazon.nova-canvas-v1:0- Text-to-image, image-to-image, inpainting, outpainting, background removalamazon.titan-image-generator-v2:0- Alternative image generation model
Note: Available models and features may vary by region and Quant Cloud plan. The module automatically fetches and displays available models for your account.
The module provides two levels of VectorDB integration:
The main module includes QuantCloudVectorDbClient for direct API access to Quant Cloud's vector database. This works without Search API and enables:
- Creating/managing collections
- Uploading documents with automatic embedding
- Text-based semantic search
- Vector-based search with pre-computed embeddings
For full Drupal AI Search integration, enable the included submodule:
# Install dependencies
composer require drupal/search_api
drush en -y search_api ai_search
# Enable the VDB submodule
drush en -y ai_provider_quant_cloud_vdbThen create a Search API server at Configuration > Search and metadata > Search API:
- Backend: "AI Search"
- Vector Database provider: "Quant Cloud VectorDB"
Configure the VDB provider:
- Enter database name and collection name
- Choose similarity metric
- Create a Search API index and start indexing content
<?php
// Get the VectorDB client service (no Search API needed)
$client = \Drupal::service('ai_provider_quant_cloud.vectordb_client');
// Create a collection
$response = $client->createCollection(
'my-knowledge-base',
'Documentation and guides', // description
'amazon.titan-embed-text-v2:0', // embedding model
1024 // dimensions
);
$collection_id = $response['collection']['collectionId'];
// Upload documents (embeddings generated automatically)
$documents = [
[
'content' => 'Drupal is a powerful CMS for government sites...',
'metadata' => ['title' => 'About Drupal', 'url' => '/about'],
],
[
'content' => 'Install modules using composer require...',
'metadata' => ['title' => 'Installing Modules', 'url' => '/install'],
],
];
$client->uploadDocuments($collection_id, $documents);
// Text-based search (server generates embeddings)
$results = $client->queryByText(
$collection_id,
'How do I install modules?',
10, // limit
0.7 // threshold
);
foreach ($results['results'] as $result) {
echo "Score: {$result['similarity']} - {$result['content']}\n";
}
// Vector-based search (with pre-computed embedding)
$ai_provider = \Drupal::service('ai.provider')->createInstance('quant_cloud');
$embedding = $ai_provider->embeddings('install modules', 'amazon.titan-embed-text-v2:0');
$vector = $embedding->getNormalized()[0];
$results = $client->queryByVector($collection_id, $vector, 10, 0.7);
// Manage collections
$collections = $client->listCollections();
$details = $client->getCollection($collection_id);
$client->deleteCollection($collection_id);| Model | Dimensions | Best For |
|---|---|---|
amazon.titan-embed-text-v2:0 |
1024 | General purpose (recommended) |
amazon.titan-embed-text-v1 |
1536 | Legacy compatibility |
cohere.embed-english-v3 |
1024 | English-only content |
cohere.embed-multilingual-v3 |
1024 | Multi-language content |
┌─────────────────────────────────────┐
│ Your Feature Modules │
│ (content generator, chatbot, etc) │
└──────────────┬──────────────────────┘
│ Uses AI API
▼
┌─────────────────────────────────────┐
│ Drupal AI Module │
│ (Plugin Manager, Interfaces) │
└──────────────┬──────────────────────┘
│ Implements
▼
┌─────────────────────────────────────┐
│ ai_provider_quant_cloud (THIS) │
│ - QuantCloudProvider │
│ - QuantCloudClient │
│ - OAuth2 Authentication │
└──────────────┬──────────────────────┘
│ HTTPS (Dashboard API)
▼
┌─────────────────────────────────────┐
│ Quant Cloud Platform │
│ - QuantCDN / QuantGov │
│ - AWS Bedrock Models │
└─────────────────────────────────────┘
drush cr
drush ev "print_r(\Drupal::service('plugin.manager.ai_provider')->getDefinitions());"- Check that your access token is valid in the Quant Cloud dashboard
- Verify organization ID is correct
- Try reconnecting with OAuth
- Check Drupal logs:
drush watchdog:show --type=ai_provider_quant_cloud
"Image too large" errors:
- The module automatically resizes images to meet Nova Canvas limits (4MP max, 2048px sides)
- If you see this error, ensure the Sharp PHP extension is installed:
composer require drupal/image_effects
"No image models available":
- Verify your Quant Cloud plan includes Bedrock image generation
- Check that
image_generationfeature is enabled in your organization - Clear model cache: Go to Configuration > AI > Quant Cloud AI and click "Clear Model Cache"
Image quality issues:
- Try using
premiumquality in configuration for better results - Adjust the
similarity_strengthparameter (0.2-1.0) for image variations - Use more detailed prompts for better control
- Ensure your PHP version supports Server-Sent Events (SSE)
- Check that your web server doesn't buffer responses (disable mod_deflate compression for SSE endpoints)
- Increase
streaming_timeoutin advanced settings if timeouts occur - Enable logging to see streaming debug information
- Clear cache:
drush cr - Check file permissions
- Verify Key module is enabled
- Model caching: Models are cached for 1 hour - adjust in code if needed
- Logging: Disable request/response logging in production
- Streaming: Use streaming for long responses to improve perceived performance
- Embeddings batch: Process embeddings in batches for better throughput
# PHPUnit
vendor/bin/phpunit modules/custom/ai_provider_quant_cloud/tests/
# PHPStan
vendor/bin/phpstan analyze modules/custom/ai_provider_quant_cloud/# Check standards
vendor/bin/phpcs --standard=Drupal modules/custom/ai_provider_quant_cloud/
# Fix automatically
vendor/bin/phpcbf --standard=Drupal modules/custom/ai_provider_quant_cloud/For issues and feature requests:
GPL-2.0-or-later
- Quant Cloud - https://quantcdn.io