Registering a Custom Embedding Usage
A usage is a named search capability — semantic_text_search, image_dedup, and so on — that
usages.<name> in the configuration maps to a model. The bundle
ships four usages; register your own when a bundle or app needs a capability of its own (e.g. a
data-hub-simple-rest index owner adding a domain-specific search).
Implement the interface
<?php
declare(strict_types=1);
namespace App\Embedding;
use Pimcore\Bundle\BackendPowerToolsBundle\Contracts\Embedding\EmbeddingUsageDefinitionInterface;
final readonly class ProductSimilarityUsage implements EmbeddingUsageDefinitionInterface
{
public function getName(): string
{
return 'product_similarity';
}
public function getElementTypes(): array
{
return ['object'];
}
public function getTranslationKey(): string
{
return 'embedding-configuration.usage.product_similarity';
}
}
No service tagging is needed: EmbeddingUsageDefinitionInterface carries
#[AutoconfigureTag('pimcore.bpt.embedding_usage')], so any service implementing it is registered
automatically as long as your bundle or app has autoconfiguration enabled (the Symfony default).
What each method controls
getName()is the canonical,snake_casename — the exact stringusages.<name>refers to in configuration, and what the Studio Usages tab lists once your definition is registered. Registration requires the name to match/^[a-z][a-z0-9_]*$/(snake_case, no dashes); dashes are canonicalized to underscores only during lookups (has(), config validation).getElementTypes()—'asset','object', or both — decides which element types this usage is even considered for.getTranslationKey()is the Studio UI label. Add the key to your bundle'stranslations/studio.*.yaml(or the app's, e.g.translations/studio.en.yaml) — a missing key falls back to the raw key text.
Consuming the mapped model
Once usages.<name> maps your usage to a model, read it through
EmbeddingModelRegistryInterface::getModelForUsage() (documents) and getQueryModelForUsage()
(incoming queries) — the same seam the built-in usages use. Check hasUsage() first: an unmapped
usage means the capability is switched off, not an error, so gate on it rather than catching the
exception getModelForUsage() throws for an unmapped or unknown-model usage.
Embeddings are an experimental feature. EmbeddingUsageDefinitionInterface is public API for this
extension point, but may still change in breaking ways between releases.