Reviewed & tested by the community
Project:
OpenAI Provider
Version:
1.2.x-dev
Component:
Code
Priority:
Normal
Category:
Feature request
Assigned:
Unassigned
Issue tags:
Reporter:
Created:
21 Jan 2026 at 00:22 UTC
Updated:
11 May 2026 at 11:07 UTC
Jump to comment: Most recent, Most recent file
Comments
Comment #3
paulsheldrake commentedComment #4
a.dmitriiev commentedComment #5
abarrioAdding patch from mr to be used in a project.
Comment #6
abarrioAdding it with patch extension
Comment #7
csakiistvanstart testing
Comment #8
csakiistvanTesting report for #3568659 — Support Batched Embeddings (OpenAI Provider)
Environment:
aimodule (current 1.x-dev),ai_provider_openai(current 1.x-dev)text-embedding-3-smallas default embeddings modelStep 1 — Check patch status
Inspected both modules via
git log. Theai_provider_openaimodule already contained the batch embeddings commits:e2bfe8e add support for batch embeddings594d8e7 Add error handling to batch embeddings methodHowever, the dependent patch for the
aibase module (#3568648) was not yet applied. TheEmbeddingsInputclass was missing theisBatch()andgetPromptCount()methods that the OpenAI provider was already calling.Step 2 — Apply the ai module patch manually
Modified
web/modules/contrib/ai/src/OperationType/Embeddings/EmbeddingsInput.phpbased on the MR !1126 diff:private string $prompt→private string|array $promptgetPrompt(),setPrompt()to acceptstring|arrayisBatch(): bool— returnsTRUEwhen prompt is an arraygetPromptCount(): int— returns count of prompts (1 for single)toString()to join batch prompts with newlines'is_batch' => $this->isBatch()totoArray()Step 3 — Unit test the patch via drush
ddev drush php:eval " use Drupal\ai\OperationType\Embeddings\EmbeddingsInput; \$single = new EmbeddingsInput('Hello world'); echo 'Single isBatch: ' . (\$single->isBatch() ? 'TRUE' : 'FALSE') . PHP_EOL; echo 'Single count: ' . \$single->getPromptCount() . PHP_EOL; \$batch = new EmbeddingsInput(['Hello', 'World', 'Test']); echo 'Batch isBatch: ' . (\$batch->isBatch() ? 'TRUE' : 'FALSE') . PHP_EOL; echo 'Batch count: ' . \$batch->getPromptCount() . PHP_EOL; echo 'Batch toString: ' . \$batch->toString() . PHP_EOL; echo 'toArray is_batch: ' . (\$batch->toArray()['is_batch'] ? 'TRUE' : 'FALSE') . PHP_EOL; "Result: All assertions passed.
isBatch(),getPromptCount(),toString(), andtoArray()all behave correctly for both single and batch inputs.Step 4 — Attempt live API call
Attempted an actual embeddings API call:
ddev drush php:eval " use Drupal\ai\OperationType\Embeddings\EmbeddingsInput; \$batch = new EmbeddingsInput(['The quick brown fox', 'jumps over the lazy dog', 'Hello world']); \$result = \Drupal::service('ai.provider')->createInstance('openai')->embeddings(\$batch, 'text-embedding-3-small'); echo count(\$result->getNormalized()) . ' embeddings returned' . PHP_EOL; "Step 5 — Bug found: RateLimitException not properly caught
While investigating the rate limit error, discovered a pre-existing bug affecting all operation types in
OpenAiProvider.php, including the newembeddings()method.The OpenAI PHP SDK throws
OpenAI\Exceptions\RateLimitException(with the message"Request rate limit has been exceeded.") on HTTP 429 responses. The catch blocks in the provider only check for the string"Too Many Requests"— which never matches — so the exception falls through to the generic\Exceptionhandler and gets re-wrapped asAiRequestErrorExceptionbyProviderProxy. This means callers cannot distinguish a rate limit from a general error.Fixed in both affected locations:
embeddings()try/catch blockmoderationEndpoints()try/catch block (runs before every embeddings call when moderation is enabled)Added a specific catch before the generic one:
catch (OpenAiRateLimitException $e) { throw new AiRateLimitException($e->getMessage()); }After the fix and a cache rebuild, the exception is correctly propagated as
AiRateLimitException.Summary
EmbeddingsInputpatch applied and unit testedRateLimitExceptioncorrectly typedThe batch embeddings logic is correctly implemented. A paid OpenAI API key (Tier 1+) is needed to fully verify the end-to-end batch API response handling.