aimeos / prisma
A powerful PHP package for integrating media related Large Language Models (LLMs) into your applications
Requires
- php: ^8.2
- ext-fileinfo: *
- ext-gd: *
- guzzlehttp/guzzle: ^7.0
Requires (Dev)
- firebase/php-jwt: ^7.0
- phpstan/phpstan: ^2.1
- phpunit/phpunit: ^11.5||^12.4
- vlucas/phpdotenv: ^5.6
- dev-master
- 0.4.x-dev
- 0.4.0
- 0.3.x-dev
- 0.3.1
- 0.3.0
- 0.2.x-dev
- 0.2.0
- 0.1.x-dev
- 0.1.0
- dev-rename_structured
- dev-ollama_text_provider
- dev-relicense
- dev-xai_text_structured
- dev-perplexity_text_structured
- dev-openrouter_text_structured
- dev-mistral_text_structured
- dev-groq_text_structured
- dev-gemini_text_structured
- dev-deepseek_text_structured
- dev-cohere_text_structured
- dev-bedrock_text_structured
- dev-anthropic_text_structured
- dev-alibaba_text_structured
- dev-schema_filter
- dev-openai_structured
- dev-simplifications
- dev-improve_methods
- dev-client_retry
- dev-value_objects
- dev-citations
- dev-update_models
- dev-budget_tokens
- dev-provider_tooling
- dev-simplify_phpstan
- dev-openai_base
- dev-calls_tools
- dev-tools_reason
- dev-base_provider
- dev-tool_infrastructure
- dev-google_write
- dev-groq_audio_describe
- dev-groq_audio_transcribe
- dev-groq_audio_speak
- dev-elevenlabs_audio_speak
- dev-elevenlabs_audio_transcribe
- dev-openai_audio_speak
- dev-openai_audio_describe
- dev-openai_audio_transcribe
- dev-mistral_audio_transcribe
- dev-gemini_audio_describe
- dev-blackforestlabs
- dev-voyageai_vectorize
- dev-cohere_vectorize
- dev-bedrock_inpaint
- dev-bedrock_isolate
- dev-bedrock_imagine
- dev-bedrock_vectorize
This package is auto-updated.
Last update: 2026-05-23 08:23:59 UTC
README
Light-weight PHP package for integrating multi-media and text related Large Language Models (LLMs) into your applications using a unified interface.
Supported providers API usage- ensure: Ensures that the provider has implemented the method
- has: Tests if the provider has implemented the method
- model: Use the model passed by its name
- withClientOptions: Add options for the Guzzle HTTP client
- withClientRetry: Configure automatic retry for failed HTTP requests
- withSystemPrompt: Add a system prompt for the LLM
- withMaxTokens: Set the maximum number of output tokens
- withThinkingBudget: Set the thinking/reasoning budget in tokens
- Response objects: How data is returned by the API
- Citations: Source references from provider responses
- Finish reason: Why generation stopped
- Tool steps: Inspect tool call history
- Rate limit: Rate limit information from providers
- Building schemas: Define tool parameters using the fluent Schema builder
- From arrays: Create schemas from JSON Schema arrays
- Type reference: Available types and their methods
- Creating tools: Create tools using the Tools facade
- Provider tools: Built-in tools executed server-side
- Tool state: Check a tool's remaining call budget
- Error handling: Customize how tool errors are returned
- Concurrent tools: Run tools in parallel
- Decorating tools: Wrap tools with additional behavior
- demix: Separate an audio file into its individual tracks
- denoise: Remove noise from an audio file
- describe: Describe the content of an audio file
- revoice: Exchange the voice in an audio file
- speak: Convert text to speech in an audio file
- transcribe: Converts speech of an audio file to text
- background: Replace background according to the prompt
- describe: Describe the content of an image
- detext: Remove all text from the image
- erase: Erase parts of the image
- imagine: Generate an image from the prompt
- inpaint: Edit an image area according to a prompt
- isolate: Remove the image background
- relocate: Place the foreground object on a new background
- repaint: Repaint an image according to the prompt
- uncrop: Extend/outpaint the image
- upscale: Scale up the image
- vectorize: Creates embedding vectors from images
- structure: Generate structured output from a prompt and schema
- translate: Translate texts from one language to another
- write: Generate text from the given prompt
- describe: Describe the content of a video
Supported providers
- Alibaba
- Anthropic
- AudioPod AI
- Bedrock Titan (AWS)
- Black Forest Labs
- Clipdrop
- Cohere
- DeepL
- Deepgram
- Deepseek
- ElevenLabs
- Gemini (Google)
- Google Translate
- Groq
- Ideogram
- Mistral
- Murf
- Ollama
- OpenAI
- Openrouter
- Perplexity
- RemoveBG
- StabilityAI
- VertexAI (Google)
- VoyageAI
- xAI
Audio
| demix | denoise | describe | revoice | speak | transcribe | |
|---|---|---|---|---|---|---|
| Alibaba | - | - | - | - | yes | - |
| AudioPod | yes | yes | - | yes | yes | yes |
| Deepgram | - | - | - | - | yes | yes |
| ElevenLabs | - | - | - | yes | yes | yes |
| Gemini | - | - | yes | - | - | - |
| Groq | - | - | yes | - | yes | yes |
| Mistral | - | - | yes | - | - | yes |
| Murf | - | - | - | yes | yes | - |
| OpenAI | - | - | yes | - | yes | yes |
Image
| background | describe | detext | erase | imagine | inpaint | isolate | recognize | relocate | repaint | uncrop | upscale | vectorize | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Alibaba | - | - | - | - | yes | - | - | - | - | - | - | - | yes |
| Bedrock Titan | - | - | - | - | yes | yes | yes | - | - | - | - | - | yes |
| Black Forest Labs | - | - | - | - | beta | beta | - | - | - | - | beta | - | - |
| Clipdrop | yes | - | yes | yes | yes | - | yes | - | - | - | yes | yes | - |
| Cohere | - | - | - | - | - | - | - | - | - | - | - | - | yes |
| Gemini | - | yes | - | - | yes | - | - | - | - | yes | - | - | - |
| Groq | - | yes | - | - | - | - | - | - | - | - | - | - | - |
| Ideogram | beta | beta | - | - | beta | beta | - | - | - | beta | - | beta | - |
| Mistral | - | - | - | - | - | - | - | yes | - | - | - | - | - |
| OpenAI | - | yes | - | - | yes | yes | - | - | - | - | - | - | - |
| RemoveBG | - | - | - | - | - | - | yes | - | yes | - | - | - | - |
| StabilityAI | - | - | - | yes | yes | yes | yes | - | - | - | yes | yes | - |
| VertexAI | - | - | - | - | yes | yes | - | - | - | - | - | yes | yes |
| VoyageAI | - | - | - | - | - | - | - | - | - | - | - | - | yes |
Text
| structure | translate | write | citations | custom tools | provider tools | system prompt | thinking budget | |
|---|---|---|---|---|---|---|---|---|
| Alibaba | yes | yes | - | yes | yes | yes | - | |
| Anthropic | yes | yes | yes | yes | yes | yes | yes | |
| Bedrock | yes | yes | - | yes | yes | yes | ||
| Cohere | yes | yes | - | yes | yes | - | ||
| Deepseek | yes | yes | - | yes | yes | - | ||
| DeepL | yes | |||||||
| Gemini | yes | yes | yes | yes | yes | yes | yes | |
| yes | ||||||||
| Groq | yes | yes | - | yes | yes | - | ||
| Mistral | yes | yes | - | yes | yes | yes | - | |
| Ollama | beta | beta | - | yes | yes | - | ||
| OpenAI | yes | yes | yes | yes | yes | yes | yes | |
| Openrouter | yes | yes | - | yes | yes | yes | - | |
| Perplexity | beta | beta | yes | yes | yes | - | ||
| xAI | beta | beta | yes | yes | yes | yes | yes |
Video
| describe | |
|---|---|
| Gemini | yes |
Installation
composer req aimeos/prisma
API usage
Basic usage:
use Aimeos\Prisma\Prisma; $image = Prisma::image() ->using( '<provider>', ['api_key' => 'xxx']) ->model( '<modelname>' ) // if model can be selected ->ensure( 'imagine' ) // make sure interface is implemented ->imagine( 'a grumpy cat' ) ->binary(); $texts = Prisma::text() ->using( 'deepl', ['api_key' => 'xxx']) ->ensure( 'translate' ) ->translate( ['Hello'], 'de' ) ->texts();
ensure
Ensures that the provider has implemented the method.
public function ensure( string $method ) : self
- @param string
$methodMethod name - @return Provider
- @throws \Aimeos\Prisma\Exceptions\NotImplementedException
Example:
\Aimeos\Prisma\Prisma::image() ->using( '<provider>', ['api_key' => 'xxx']) ->ensure( 'imagine' );
has
Tests if the provider has implemented the method.
public function has( string $method ) : bool
- @param string
$methodMethod name - @return bool TRUE if implemented, FALSE if absent
Example:
\Aimeos\Prisma\Prisma::image() ->using( '<provider>', ['api_key' => 'xxx']) ->has( 'imagine' );
model
Use the model passed by its name.
Used if the provider supports more than one model and allows to select between the different models. Otherwise, it's ignored.
public function model( ?string $model ) : self
- @param string|null
$modelModel name - @return self Provider interface
Example:
\Aimeos\Prisma\Prisma::image() ->using( '<provider>', ['api_key' => 'xxx']) ->model( 'dall-e-3' );
withClientOptions
Add options for the Guzzle HTTP client.
public function withClientOptions( array `$options` ) : self
- @param array<string, mixed>
$optionsAssociative list of name/value pairs - @return self Provider interface
Example:
\Aimeos\Prisma\Prisma::image() ->using( '<provider>', ['api_key' => 'xxx']) ->withClientOptions( ['timeout' => 120] );
withClientRetry
Configure automatic retry for failed HTTP requests.
public function withClientRetry( int `$maxAttempts` = 3, \Closure|int `$delayMs` = 100, ?\Closure `$when` = null ) : self
- @param int
$maxAttemptsTotal number of attempts including the initial request - @param \Closure|int
$delayMsFixed delay in ms or closure: fn(int $attempt, ?ResponseInterface $response): int - @param \Closure|null
$whenRetry condition: fn(ResponseInterface $response, int $attempt): bool - @return self Provider interface
By default, retries on status codes 429, 500, 502, 503, 504 and connection exceptions.
Examples:
// Fixed delay of 200ms between retries \Aimeos\Prisma\Prisma::text() ->using( '<provider>', ['api_key' => 'xxx']) ->withClientRetry( 3, 200 ); // Exponential backoff \Aimeos\Prisma\Prisma::text() ->using( '<provider>', ['api_key' => 'xxx']) ->withClientRetry( 3, fn( $attempt, $response ) => 100 * pow( 2, $attempt ) ); // Custom retry condition \Aimeos\Prisma\Prisma::text() ->using( '<provider>', ['api_key' => 'xxx']) ->withClientRetry( 3, 100, fn( $response, $attempt ) => $response->getStatusCode() === 429 );
withSystemPrompt
Add a system prompt for the LLM.
It may be used by providers supporting system prompts. Otherwise, it's ignored.
public function withSystemPrompt( ?string $prompt ) : self
- @param string|null
$promptSystem prompt - @return self Provider interface
Example:
\Aimeos\Prisma\Prisma::image() ->using( '<provider>', ['api_key' => 'xxx']) ->withSystemPrompt( 'You are a professional illustrator' );
withMaxTokens
Set the maximum number of output tokens for the response.
public function withMaxTokens( ?int $tokens ) : self
- @param int|null
$tokensMaximum output tokens - @return self Provider interface
Example:
\Aimeos\Prisma\Prisma::text() ->using( '<provider>', ['api_key' => 'xxx'] ) ->withMaxTokens( 4096 ) ->write( 'Tell me a story' );
withThinkingBudget
Set the thinking/reasoning budget in tokens for models that support extended thinking. The budget is mapped to each provider's native format automatically: token counts for Anthropic, OpenAI, Gemini and Bedrock; effort levels for other OpenAI-API providers (≤ 1024 → low, ≤ 8192 → medium, > 8192 → high).
public function withThinkingBudget( ?int $budget ) : self
- @param int|null
$budgetThinking budget in tokens - @return self Provider interface
Example:
$response = \Aimeos\Prisma\Prisma::text() ->using( '<provider>', ['api_key' => 'xxx'] ) ->withThinkingBudget( 5000 ) ->withMaxTokens( 4096 ) ->write( 'Solve this step by step' ); // Access the model's reasoning (if returned by the provider) $thinking = $response->meta()['thinking'] ?? null;
Response objects
The methods return a FileResponse, TextResponse or VectorResponse object that contains the returned data with optional meta/usage/description information.
FileResponse objects:
$base64 = $response->base64(); // first base64 data, from binary, base64 and URL, waits for async requests $file = $response->binary(); // first binary data, from binary, base64 and URL, waits for async requests $url = $response->url(); // first URL, only if URLs are returned, otherwise NULL $mime = $response->mimeType(); // image mime type, waits for async requests $text = $response->description(); // image description if returned by provider $bool = $response->ready(); // FALSE for async APIs until file is available $file = $response->first(); // first available file object $array = $response->files(); // all available file objects // loop over all available files foreach( $response as $name => $file ) { $file->binary() }
URLs are automatically converted to binary and base64 data if requested and conversion between binary and base64 data is done on request too.
TextResponse objects:
$text = $response->text(); // first text content (non-streaming) $text = $response->first(); // first available text $texts = $response->texts(); // all texts (non-streaming) // loop over all available texts foreach( $response as $text ) { echo $text; }
VectorResponse objects:
$vector = $response->first(); // first embedding vector if only one file has been passed $vectors = $response->vectors(); // embedding vectors for the passed files in the same order // loop over all available vectors foreach( $response as $vector ) { print_r( $vector ); }
Included meta data (optional):
$meta = $response->meta();
It returns an associative array whose content totally depends on the provider.
Included usage data (optional):
$usage = $response->usage();
It returns an associative array whose content depends on the provider. If the provider returns
usage information, the used array key is available and contains a number. What the number
represents depdends on the provider too.
Citations
TextResponse objects include citations when returned by providers that support them (Anthropic, Gemini, OpenAI, Perplexity, xAI). Each citation is a normalized array with four fields:
$response = Prisma::text() ->using( 'openai', ['api_key' => 'xxx'] ) ->write( 'What is the capital of France?' ); $citations = $response->citations(); // array of Citation objects foreach( $citations as $citation ) { $citation->title(); // string|null — source title $citation->url(); // string|null — source URL $citation->text(); // string|null — output text that references the source $citation->source(); // string|null — verbatim quote from the source document }
The text field contains the snippet from the model's output that cites the source
(populated by OpenAI, xAI, Gemini). The source field contains a verbatim quote from the
input/source document (populated by Anthropic). For Perplexity, only url is available.
Anthropic requires opting in via options:
$response = Prisma::text() ->using( 'anthropic', ['api_key' => 'xxx'] ) ->write( 'Summarize this document', $files, ['citations' => true] );
Finish reason
TextResponse objects include a finish reason indicating why the model stopped generating:
$response = Prisma::text() ->using( 'openai', ['api_key' => 'xxx'] ) ->withTools( [$tool] ) ->withMaxSteps( 5 ) ->write( 'What is the weather in Berlin?' ); $reason = $response->reason(); // 'stop', 'tool', 'length', 'content', 'error', or 'unknown'
| Reason | Meaning |
|---|---|
stop |
The model finished normally (reached a natural end or stop sequence) |
tool |
The model stopped to request tool calls; returned when withMaxSteps() is exhausted mid-loop |
length |
Output was truncated because it hit the max token limit |
content |
Output was blocked or truncated by a safety/content filter |
error |
The provider returned an error during generation |
unknown |
The provider returned an unrecognized finish reason |
Tool steps
After a tool-using request completes, inspect the full history of tool calls and their results via steps():
$response = Prisma::text() ->using( 'openai', ['api_key' => 'xxx'] ) ->withTools( [$tool] ) ->withMaxSteps( 5 ) ->write( 'What is the weather in Berlin?' ); foreach( $response->steps() as $step ) { $step->id(); // tool call ID from the provider $step->name(); // tool name (e.g. 'weather') $step->arguments(); // arguments the model passed (e.g. ['city' => 'Berlin']) $step->result(); // result string returned to the model }
Rate limit
TextResponse and FileResponse objects can include rate limit information from the provider:
$rateLimit = $response->rateLimit(); // RateLimit object or null $rateLimit->limit(); // int|null — request limit $rateLimit->remaining(); // int|null — remaining requests $rateLimit->reset(); // string|null — reset timestamp $rateLimit->retryAfter(); // int|null — retry after seconds
Returns null if the provider does not return rate limit headers.
Schemas
Schemas define the parameters that tools accept. They are used by Tools::make() to tell the LLM what arguments a tool expects.
Building schemas
Use the fluent Schema builder to define tool parameters:
use Aimeos\Prisma\Schema\Schema; $schema = Schema::for( 'search', [ 'query' => Schema::string()->description( 'Search query' )->required(), 'limit' => Schema::integer()->description( 'Max results' )->min( 1 )->max( 100 ), ] );
Schema::for() creates a named schema with an object type. The first argument is the schema name, the second is an associative array of property names to types.
Nested objects:
$schema = Schema::for( 'create_event', [ 'title' => Schema::string()->required(), 'location' => Schema::object( [ 'city' => Schema::string()->required(), 'country' => Schema::string(), ] )->required(), ] );
Arrays:
$schema = Schema::for( 'tag', [ 'tags' => Schema::array()->items( Schema::string() )->min( 1 )->max( 10 )->required(), 'scores' => Schema::array()->items( Schema::number() ), ] );
Enums:
$schema = Schema::for( 'sort', [ 'order' => Schema::string()->enum( ['asc', 'desc'] )->required(), ] ); // Or from a BackedEnum: $schema = Schema::for( 'sort', [ 'order' => Schema::string()->enum( SortOrder::class )->required(), ] );
Strict mode and no additional properties (for providers that support it, e.g. OpenAI):
$schema = Schema::for( 'search', [ 'query' => Schema::string()->required(), ] )->strict()->withoutAdditionalProperties();
From arrays
If you already have a JSON Schema array, use Schema::fromArray():
$schema = Schema::fromArray( 'search', [ 'type' => 'object', 'properties' => [ 'query' => ['type' => 'string', 'description' => 'Search query'], 'limit' => ['type' => 'integer'], ], 'required' => ['query'], ] );
Type reference
All types support these common methods: description(), required(), nullable(), title(), enum().
| Factory method | Type | Additional methods |
|---|---|---|
Schema::string() |
String | min(), max(), pattern(), format(), default() |
Schema::integer() |
Integer | min(), max(), multipleOf(), default() |
Schema::number() |
Number (float) | min(), max(), multipleOf(), default() |
Schema::boolean() |
Boolean | default() |
Schema::array() |
Array | items(), min(), max(), unique(), default() |
Schema::object() |
Object | withoutAdditionalProperties(), default() |
Tools
Tools enable LLMs to call functions during text generation. Prisma supports both custom tools (executed locally) and provider tools (executed server-side by the LLM provider).
Creating tools
Create tools using the Tools facade:
From scratch:
use Aimeos\\Prisma\\Schema\\Schema; use Aimeos\\Prisma\\Tools; $tool = Tools::make( 'search', 'Search the web', Schema::for( 'search', [ 'query' => Schema::string()->description( 'Search query' )->required(), ] ), fn( $args ) => file_get_contents( 'https://api.example.com/search?q=' . $args['query'] ) );
From a Laravel AI / Prism tool:
$tool = Tools::laravel( new MyLaravelTool() );
The object must have name(), description(), and toArray() methods. Execution uses __invoke() or handle().
From a Symfony #[AsTool] class:
$tool = Tools::symfony( MySymfonyTool::class ); // or with a specific tool name when the class has multiple #[AsTool] attributes: $tool = Tools::symfony( MySymfonyTool::class, 'tool-name' );
Using tools with a provider:
use Aimeos\Prisma\Prisma; use Aimeos\\Prisma\\Schema\\Schema; use Aimeos\\Prisma\\Tools; $tool = Tools::make( 'weather', 'Get current weather', Schema::for( 'weather', [ 'city' => Schema::string()->description( 'City name' )->required(), ] ), fn( $args ) => json_encode( ['temp' => '22°C', 'city' => $args['city']] ) ); $response = Prisma::text() ->using( 'openai', ['api_key' => 'xxx'] ) ->withTools( [$tool] ) ->withMaxSteps( 5 ) ->write( 'What is the weather in Berlin?' );
withMaxSteps() controls the maximum number of tool calls performed (default is unlimited).
Note: Tool handlers can return any value. Strings are passed through as-is; all other return types (arrays, objects, numbers) are automatically JSON-encoded.
Tool choice:
withToolChoice() controls whether the model must use tools:
| Constant | Description |
|---|---|
Provider::AUTO |
Model decides (default) |
Provider::REQ |
Must use a tool |
Provider::NONE |
No tools |
use Aimeos\Prisma\Providers\Base as Provider; ->withToolChoice( Provider::REQ )
Limiting tool calls:
$tool = Tools::make( ... )->max( 3 ); // This specific tool can only be called 3 times
Provider tools
Provider tools are built-in tools executed server-side by the LLM provider (e.g., web search, code execution). They don't require local function handlers. Create them using Tools::provider():
use Aimeos\Prisma\Prisma; use Aimeos\Prisma\Tools; $response = Prisma::text() ->using( 'anthropic', ['api_key' => 'xxx'] ) ->withTools( [ Tools::provider( 'web_search' ), Tools::provider( 'code_execution' ), ] ) ->write( 'Search for the latest PHP version and write code to check it' );
Available provider tools:
| Tool name | Providers |
|---|---|
web_search |
Anthropic, OpenAI, Gemini, Mistral, xAI, OpenRouter, Alibaba |
web_search_premium |
Mistral |
code_execution |
Anthropic, OpenAI, Gemini, Mistral, xAI |
web_fetch |
Anthropic |
file_search |
OpenAI |
image_generation |
Mistral |
document_library |
Mistral |
Provider tool names not supported by the chosen provider are silently ignored. Providers without any provider tool support (e.g. Bedrock, Cohere, Deepseek, Perplexity) ignore all provider tools.
Custom and provider tools can be mixed in a single withTools() call:
$response = Prisma::text() ->using( 'anthropic', ['api_key' => 'xxx'] ) ->withTools( [ $customTool, Tools::provider( 'web_search' ), Tools::provider( 'code_execution' ), ] ) ->withMaxSteps( 5 ) ->write( 'Search and analyze' );
Pass provider-specific options using with():
Tools::provider( 'web_search' )->with( [ 'allowed_domains' => ['example.com', 'docs.example.com'], 'blocked_domains' => ['spam.com'], ] )
Unknown or unsupported options are silently ignored by each provider.
Normalized options (translated automatically per provider):
| Option | Description | Supported by |
|---|---|---|
allowed_domains |
Only include results from these domains | Anthropic, OpenAI, OpenRouter |
blocked_domains |
Exclude results from these domains | Anthropic, xAI, OpenRouter |
search_context_size |
Search depth: "low", "medium", "high" |
OpenAI, xAI |
user_location |
User location object for localized results | OpenAI, Anthropic |
Provider-specific options:
| Option | Provider | Tool | Description |
|---|---|---|---|
max_uses |
Anthropic | web_search, web_fetch | Max server-side uses (also set via ->max()) |
search_engine |
OpenRouter | web_search | "auto", "native", "exa" |
container |
OpenAI | code_execution | Container config (['type' => 'auto']) |
vector_store_ids |
OpenAI | file_search | Vector store IDs to search |
max_num_results |
OpenAI | file_search | Max results returned |
library_ids |
Mistral | document_library | Document library IDs |
Tool state
Check a tool's remaining call budget using:
$tool = Tools::make( ... )->max( 3 ); $tool->counter(); // 3 — remaining calls $tool->can(); // true — still callable // after the model has called the tool 3 times: $tool->counter(); // 0 $tool->can(); // false
Error handling
By default, when a tool handler throws an exception, the error message is returned to the model as "Error: {message}" instead of propagating the exception. You can override this with a custom error handler using failed():
$tool = Tools::make( 'search', 'Search the web', $schema, fn( $args ) => doSearch( $args ) ) ->failed( function( \Throwable $e, array $arguments ) : string { Log::error( 'Tool failed', ['error' => $e->getMessage(), 'args' => $arguments] ); return 'Search is currently unavailable, please try a different approach.'; } );
The handler receives the thrown exception and the original arguments, and must return a string that is sent back to the model.
Concurrent tools
Tools marked as concurrent run in parallel when the auto-detected concurrency strategy supports it (Fork when PHP pcntl extension is available, otherwise Sequential):
$schema = Schema::for( 'tool' ); $search = Tools::make( 'search', 'Search the web', $schema, fn( $args ) => '...' )->concurrent(); $weather = Tools::make( 'weather', 'Get weather', $schema, fn( $args ) => '...' )->concurrent(); $save = Tools::make( 'save', 'Save to database', $schema, fn( $args ) => '...' ); // sequential (default)
When the LLM calls multiple tools in a single step, concurrent tools run in parallel while sequential tools run one after another. You can also disable concurrency again:
$tool->concurrent( false );
Concurrency strategy:
Prisma auto-detects the best concurrency strategy: Fork (parallel via pcntl_fork) when available, otherwise Sequential. You can set a different strategy:
use Aimeos\Prisma\Tools\Concurrency\Sequential; $response = Prisma::text() ->using( 'openai', ['api_key' => 'xxx'] ) ->withConcurrency( new Sequential() ) ->withTools( [$search, $weather] ) ->write( 'Search and get weather for Berlin' );
Custom concurrency strategy:
Implement the Concurrency interface to use your own execution strategy (e.g., async I/O, thread pools, or framework-specific solutions):
use Aimeos\Prisma\Tools\Concurrency\Concurrency; use Aimeos\Prisma\Tools\Step; class ReactConcurrency implements Concurrency { public function run( array $steps ) : array { foreach( $steps as $step ) { if( $tool = $step->tool() ) { $step->complete( $tool( $step->arguments() ) ); } } return $steps; } }
Each $steps entry is a Step object with tool(), arguments(), id(), name(), and result(). Call $step->complete() with the result string.
Note: Read-only tools that don't modify state should be marked as concurrent.
Decorating tools
Use the Decorator abstract class to wrap tools with additional behavior:
use Aimeos\\Prisma\\Tools\Adapter\Decorator; use Aimeos\\Prisma\\Tools\Adapter\Adapter; class LoggingTool extends Decorator { private $logger; public function __construct( Adapter $adapter, $logger ) { parent::__construct( $adapter ); $this->logger = $logger; } public function __invoke( array $arguments ) : string { $this->logger->info( 'Tool called: ' . $this->name(), $arguments ); return parent::__invoke( $arguments ); } } $tool = new LoggingTool( Tools::make( 'search', 'Search', $schema, fn( $args ) => '...' ), $logger );
Decorators delegate all Adapter interface methods to the wrapped tool. Override any provider method to add custom behavior.
Audio API
demix
Separate an audio file into its individual tracks.
public function demix( Audio $audio, int $stems, array $options = [] ) : FileResponse
- @param Audio
$audioInput audio object - @param int
$stemsNumber of stems to separate into (e.g. 2 for vocals and accompaniment) - @param array<string, mixed>
$optionsProvider specific options - @return FileResponse Audio file response
Supported options:
- AudioPod
denoise
Remove noise from an audio file.
public function denoise( Audio $audio, array $options = [] ) : FileResponse
- @param Audio
$audioInput audio object - @param array<string, mixed>
$optionsProvider specific options - @return FileResponse Audio file response
Supported options:
describe
Describe the content of an audio file.
public function describe( Audio $audio, ?string $lang = null, array $options = [] ) : TextResponse
- @param Audio
$audioInput audio object - @param string|null
$langISO language code the description should be generated in - @param array<string, mixed>
$optionsProvider specific options - @return TextResponse Response text
Supported options:
- Gemini
- Groq
- OpenAI
revoice
Exchange the voice in an audio file.
public function revoice( Audio $audio, string $voice, array $options = [] ) : FileResponse;
- @param Audio
$audioInput audio object - @param string
$voiceVoice name or identifier - @param array<string, mixed>
$optionsProvider specific options - @return FileResponse Audio file response
Supported options:
- AudioPod
- ElevenLabs
- Murf
speak
Converts text to speech.
public function speak( string $text, ?string $voice = null, array $options = [] ) : FileResponse;
- @param string
$textText to be converted to speech - @param string|null
$voiceVoice identifier for speech synthesis - @param array<string, mixed>
$optionsProvider specific options - @return FileResponse Audio file response
Supported options:
transcribe
Converts speech to text.
public function transcribe( Audio $audio, ?string $lang = null, array $options = [] ) : TextResponse
- @param Audio
$audioInput audio object - @param string|null
$langISO language code of the audio content - @param array<string, mixed>
$optionsProvider specific options - @return TextResponse Transcription text response
Supported options:
Image API
Most methods require an image object as input which contains a reference to the image that should be processed. This object can be created by:
use \Aimeos\Prisma\Files\Image; $image = Image::fromUrl( 'https://example.com/image.php', 'image/png' ); $image = Image::fromLocalPath( 'path/to/image.png', 'image/png' ); $image = Image::fromBinary( 'PNG...', 'image/png' ); $image = Image::fromBase64( 'UE5H...', 'image/png' ); // Laravel only: $image = Image::fromStoragePath( 'path/to/image.png', 'public', 'image/png' );
The last parameter of all methods (mime type) is optional. If it's not passed, the file content will be retrieved to determine the mime type if reqested.
Note: It's best to use fromUrl() if possible because all other formats (binary and base64) can be derived from the URL content but URLs can't be created from binary/base64 data.
background
Replace image background with a background described by the prompt.
public function background( Image $image, string $prompt, array $options = [] ) : FileResponse
- @param Image
$imageInput image object - @param string
$promptPrompt describing the new background - @param array<string, mixed>
$optionsProvider specific options - @return FileResponse Response file
Supported options:
- Clipdrop
- Ideogram
Example:
use Aimeos\Prisma\Prisma; use \Aimeos\Prisma\Files\Image; $image = Image::fromUrl( 'https://example.com/image.png' ); $fileResponse = Prisma::image() ->using( '<provider>', ['api_key' => 'xxx']) ->background( $image, 'Golden sunset on a caribbean beach' ); $image = $fileResponse->binary();
describe
Describe the content of an image.
public function describe( Image $image, ?string $lang = null, array $options = [] ) : TextResponse
- @param Image
$imageInput image object - @param string|null
$langISO language code the description should be generated in - @param array<string, mixed>
$optionsProvider specific options - @return TextResponse Response text
Supported options:
- Gemini
- Groq
- Ideogram
- OpenAI
Example:
use Aimeos\Prisma\Prisma; use \Aimeos\Prisma\Files\Image; $image = Image::fromUrl( 'https://example.com/image.png' ); $textResponse = Prisma::image() ->using( '<provider>', ['api_key' => 'xxx']) ->describe( $image, 'de' ); $text = $textResponse->text();
detext
Remove all text from the image.
public function detext( Image $image, array $options = [] ) : FileResponse
- @param Image
$imageInput image object - @param array<string, mixed>
$optionsProvider specific options - @return FileResponse Response file
Supported options:
- Clipdrop
Example:
use Aimeos\Prisma\Prisma; use \Aimeos\Prisma\Files\Image; $image = Image::fromUrl( 'https://example.com/image.png' ); $fileResponse = Prisma::image() ->using( '<provider>', ['api_key' => 'xxx']) ->detext( `$image` ); $image = $fileResponse->binary();
erase
Erase parts of the image.
public function erase( Image $image, Image $mask, array $options = [] ) : FileResponse
- @param Image
$imageInput image object - @param Image
$maskMask image object - @param array<string, mixed>
$optionsProvider specific options - @return FileResponse Response file
The mask must be an image with black parts (#000000) to keep and white parts (#FFFFFF) to remove.
Supported options:
Example:
use Aimeos\Prisma\Prisma; use \Aimeos\Prisma\Files\Image; $image = Image::fromUrl( 'https://example.com/image.png' ); $mask = Image::fromBinary( 'PNG...' ); $fileResponse = Prisma::image() ->using( '<provider>', ['api_key' => 'xxx']) ->erase( $image, $mask ); $image = $fileResponse->binary();
imagine
Generate an image from the prompt.
public function imagine( string $prompt, array $images = [], array $options = [] ) : FileResponse
- @param string
$promptPrompt describing the image - @param array<int, \Aimeos\Prisma\Files\Image>
$imagesAssociative list of file name/Image instances - @param array<string, mixed>
$optionsProvider specific options - @return FileResponse Response file
Supported options:
- Alibaba Qwen/Wan/Z-Image
- Bedrock
- Black Forest Labs
- Clipdrop
- Gemini
- Ideogram
- VertexAI
- OpenAI GPT image 1
- OpenAI Dall-e-3
- OpenAI Dall-e-2
- StabilityAI Core
- StabilityAI Ultra
- StabilityAI Stable Diffusion 3.5
Example:
use Aimeos\Prisma\Prisma; $fileResponse = Prisma::image() ->using( '<provider>', ['api_key' => 'xxx']) ->imagine( 'Futuristic robot looking at a dashboard' ); $image = $fileResponse->binary();
inpaint
Edit an image by inpainting an area defined by a mask according to a prompt.
public function inpaint( Image $image, Image $mask, string $prompt, array $options = [] ) : FileResponse
- @param Image
$imageInput image object - @param Image
$maskInput mask image object - @param string
$promptPrompt describing the changes - @param array<string, mixed>
$optionsProvider specific options - @return FileResponse Response file
The mask must be an image with black parts (#000000) to keep and white parts (#FFFFFF) to edit.
Supported options:
- Bedrock
- Black Forest Labs
- Ideogram
- VertexAI
- OpenAI GPT image 1
- OpenAI Dall-e-3
- OpenAI Dall-e-2
- StabilityAI
Example:
use Aimeos\Prisma\Prisma; use \Aimeos\Prisma\Files\Image; $image = Image::fromUrl( 'https://example.com/image.png' ); $mask = Image::fromBinary( 'PNG...' ); $fileResponse = Prisma::image() ->using( '<provider>', ['api_key' => 'xxx']) ->inpaint( $image, $mask, 'add a pink flamingo' ); $image = $fileResponse->binary();
isolate
Remove the image background.
public function isolate( Image $image, array $options = [] ) : FileResponse
- @param Image
$imageInput image object - @param array<string, mixed>
$optionsProvider specific options - @return FileResponse Response file
Supported options:
Example:
use Aimeos\Prisma\Prisma; use \Aimeos\Prisma\Files\Image; $image = Image::fromUrl( 'https://example.com/image.png' ); $fileResponse = Prisma::image() ->using( '<provider>', ['api_key' => 'xxx']) ->isolate( `$image` ); $image = $fileResponse->binary();
recognize
Recognizes the text in the given image (OCR).
public function recognize( Image $image, array $options = [] ) : TextResponse;
- @param Image
$imageInput image object - @param array<string, mixed>
$optionsProvider specific options - @return TextResponse Response text object
Supported options:
Example:
use Aimeos\Prisma\Prisma; use \Aimeos\Prisma\Files\Image; $image = Image::fromUrl( 'https://example.com/image.png' ); $textTesponse = Prisma::image() ->using( '<provider>', ['api_key' => 'xxx']) ->recognize( `$image` ); $text = $textResponse->text();
relocate
Place the foreground object on a new background.
public function relocate( Image $image, Image $bgimage, array $options = [] ) : FileResponse
- @param Image
$imageInput image with foreground object - @param Image
$bgimageBackground image - @param array<string, mixed>
$optionsProvider specific options - @return FileResponse Response file
Supported options:
Example:
use Aimeos\Prisma\Prisma; use \Aimeos\Prisma\Files\Image; $image = Image::fromUrl( 'https://example.com/image.png' ); $bgimage = Image::fromUrl( 'https://example.com/background.png' ); $fileResponse = Prisma::image() ->using( '<provider>', ['api_key' => 'xxx']) ->relocate( $image, $bgimage ); $image = $fileResponse->binary();
repaint
Repaint an image according to the prompt.
public function repaint( Image $image, string $prompt, array $options = [] ) : FileResponse
- @param Image
$imageInput image object - @param string
$promptPrompt describing the changes - @param array<string, mixed>
$optionsProvider specific options - @return FileResponse Response file
Supported options:
Example:
use Aimeos\Prisma\Prisma; use \Aimeos\Prisma\Files\Image; $image = Image::fromUrl( 'https://example.com/image.png' ); $fileResponse = Prisma::image() ->using( '<provider>', ['api_key' => 'xxx']) ->repaint( $image, 'Use a van Goch style' ); $image = $fileResponse->binary();
uncrop
Extend/outpaint the image.
public function uncrop( Image $image, int $top, int $right, int $bottom, int $left, array $options = [] ) : FileResponse
- @param Image
$imageInput image object - @param int
$topNumber of pixels to extend to the top - @param int
$rightNumber of pixels to extend to the right - @param int
$bottomNumber of pixels to extend to the bottom - @param int
$leftNumber of pixels to extend to the left - @param array<string, mixed>
$optionsProvider specific options - @return FileResponse Response file
Supported options:
- Black Forest Labs
- Clipdrop
- StabilityAI
Example:
use Aimeos\Prisma\Prisma; use \Aimeos\Prisma\Files\Image; $image = Image::fromUrl( 'https://example.com/image.png' ); $fileResponse = Prisma::image() ->using( '<provider>', ['api_key' => 'xxx']) ->uncrop( $image, 100, 200, 0, 50 ); $image = $fileResponse->binary();
upscale
Scale up the image.
public function upscale( Image $image, int $factor, array $options = [] ) : FileResponse
- @param Image
$imageInput image object - @param int
$factorUpscaling factor between 2 and the maximum value supported by the provider - @param array<string, mixed>
$optionsProvider specific options - @return FileResponse Response file
Supported options:
- Clipdrop
- Ideogram
- VertexAI
- StabilityAI
Example:
use Aimeos\Prisma\Prisma; use \Aimeos\Prisma\Files\Image; $image = Image::fromUrl( 'https://example.com/image.png' ); $fileResponse = Prisma::image() ->using( '<provider>', ['api_key' => 'xxx']) ->upscale( $image, 4 ); $image = $fileResponse->binary();
vectorize
Creates embedding vectors of the images' content.
public function vectorize( array $images, ?int $size = null, array $options = [] ) : VectorResponse
- @param array<int, \Aimeos\Prisma\Files\Image>
$imagesList of input image objects - @param int|null
$sizeSize of the resulting vector or null for provider default - @param array<string, mixed>
$optionsProvider specific options - @return VectorResponse Response vector object
Supported options:
Example:
use Aimeos\Prisma\Prisma; use \Aimeos\Prisma\Files\Image; $images = [ Image::fromUrl( 'https://example.com/image.png' ), Image::fromUrl( 'https://example.com/image2.png' ), ]; $vectorResponse = Prisma::image() ->using( '<provider>', ['api_key' => 'xxx']) ->vectorize( $images, 512 ); $vectors = $vectorResponse->vectors();
Text API
structure
Generate structured output from the given prompt and schema. The response JSON is parsed and available via the structured() method on the response object.
public function structure( string $prompt, Schema $schema, array $files = [], array $options = [] ) : TextResponse
- @param string
$promptInput prompt for structured text generation - @param Schema
$schemaSchema definition for the structured output - @param array<int, File>
$filesFiles for multimodal input (images, audio, documents) - @param array<string, mixed>
$optionsProvider specific options - @return TextResponse Response text with structured data
Supported options:
- Alibaba
- Anthropic
- Bedrock
- Cohere
- Deepseek
- Gemini
- Groq
- Mistral
- Ollama
- OpenAI
- Openrouter
- Perplexity
- xAI
Example:
use Aimeos\Prisma\Prisma; use Aimeos\Prisma\Schema\Schema; $schema = Schema::for( 'person', [ 'name' => Schema::string(), 'age' => Schema::integer(), ] ); $textResponse = Prisma::text() ->using( 'openai', ['api_key' => 'xxx'] ) ->ensure( 'structure' ) ->structure( 'Extract the person from: John is 30 years old', $schema ); $data = $textResponse->structured(); // ['name' => 'John', 'age' => 30] $json = $textResponse->text(); // '{"name":"John","age":30}'
translate
Translate one or more texts from one language to another.
public function translate( array $texts, string $to, ?string $from = null, ?string $context = null, array $options = [] ) : TextResponse
- @param array<string>
$textsInput texts to be translated - @param string
$toISO language code to translate the text into - @param string|null
$fromISO language code of the input text (optional, auto-detected if omitted) - @param string|null
$contextContext for the translation (optional) - @param array<string, mixed>
$optionsProvider specific options - @return TextResponse Response text
Supported options:
Example:
use Aimeos\Prisma\Prisma; $textResponse = Prisma::text() ->using( 'deepl', ['api_key' => 'xxx']) ->ensure( 'translate' ) ->translate( ['Hello', 'World'], 'de', 'en' ); $texts = $textResponse->texts(); // ['Hallo', 'Welt']
write
Generate text from the given prompt with optional multimodal file inputs (images, audio, documents).
public function write( string $prompt, array $files = [], array $options = [] ) : TextResponse
- @param string
$promptInput prompt for text generation - @param array<int, File>
$filesFiles for multimodal input (images, audio, documents) - @param array<string, mixed>
$optionsProvider specific options - @return TextResponse Response text
Supported options:
- Alibaba
- Anthropic
- Bedrock
- Cohere
- Deepseek
- Gemini
- Groq
- Mistral
- Ollama
- OpenAI
- Openrouter
- Perplexity
- xAI
Example:
use Aimeos\Prisma\Prisma; $textResponse = Prisma::text() ->using( 'openai', ['api_key' => 'xxx']) ->ensure( 'write' ) ->write( 'Summarize the benefits of renewable energy' ); $texts = $textResponse->texts(); // ['Renewable energy offers...']
Video API
describe
Describe the content of a video file.
public function describe( Video $video, ?string $lang = null, array $options = [] ) : TextResponse
- @param Video
$videoInput video object - @param string|null
$langISO language code the description should be generated in - @param array<string, mixed>
$optionsProvider specific options - @return TextResponse Response text
Supported options:
- Gemini