https://github.com/aimeos/prisma
Light-weight PHP package for integrating multi-media related Large Language Models (LLMs) using a unified interface
https://github.com/aimeos/prisma
api llm media multimedia
Last synced: 5 months ago
JSON representation
Light-weight PHP package for integrating multi-media related Large Language Models (LLMs) using a unified interface
- Host: GitHub
- URL: https://github.com/aimeos/prisma
- Owner: aimeos
- License: lgpl-2.1
- Created: 2025-10-28T10:25:24.000Z (8 months ago)
- Default Branch: master
- Last Pushed: 2026-02-11T17:42:18.000Z (5 months ago)
- Last Synced: 2026-02-11T22:05:23.438Z (5 months ago)
- Topics: api, llm, media, multimedia
- Language: PHP
- Homepage: https://php-prisma.org
- Size: 1.21 MB
- Stars: 61
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# PHP Prisma
Light-weight PHP package for integrating multi-media related Large Language Models (LLMs) into your applications using a unified interface.
-
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 -
withSystemPrompt: Add a system prompt for the LLM -
Response objects: How data is returned by the API
-
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
-
describe: Describe the content of a video
## Supported providers
- [AudioPod AI](https://audiopod.ai/)
- [Bedrock Titan (AWS)](https://docs.aws.amazon.com/bedrock/latest/userguide/titan-models.html)
- [Black Forest Labs](https://docs.bfl.ai/quick_start/introduction)
- [Clipdrop](https://clipdrop.co/apis)
- [Cohere](https://docs.cohere.com/docs/the-cohere-platform)
- [Deepgram](https://deepgram.com/)
- [ElevenLabs](https://elevenlabs.io/docs/overview/intro)
- [Gemini (Google)](https://aistudio.google.com/models/gemini-2-5-flash-image)
- [Groq](https://groq.com/)
- [Ideogram](https://ideogram.ai/api)
- [Mistral](https://docs.mistral.ai/api)
- [Murf](https://murf.ai/api)
- [OpenAI](https://openai.com/api/)
- [RemoveBG](https://www.remove.bg/api)
- [StabilityAI](https://platform.stability.ai/)
- [VertexAI (Google)](https://cloud.google.com/vertex-ai/generative-ai/docs)
- [VoyageAI](https://docs.voyageai.com/)
### Audio
| | demix | denoise | describe | revoice | speak | transcribe |
| :--- | :---: | :---: | :---: | :---: | :---: | :---: |
| **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 |
| :--- | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: |
| **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 |
### Video
| | describe |
| :--- | :---: |
| **Gemini** | yes |
## Installation
```
composer req aimeos/prisma
```
## API usage
Basic usage:
```php
use Aimeos\Prisma\Prisma;
$image = Prisma::image()
->using( '', ['api_key' => 'xxx'])
->model( '' ) // if model can be selected
->ensure( 'imagine' ) // make sure interface is implemented
->imagine( 'a grumpy cat' )
->binary();
```
### ensure
Ensures that the provider has implemented the method.
```php
public function ensure( string $method ) : self
```
* @param **string** `$method` Method name
* @return **Provider**
* @throws \Aimeos\Prisma\Exceptions\NotImplementedException
**Example:**
```php
\Aimeos\Prisma\Prisma::image()
->using( '', ['api_key' => 'xxx'])
->ensure( 'imagine' );
```
### has
Tests if the provider has implemented the method.
```php
public function has( string $method ) : bool
```
* @param **string** `$method` Method name
* @return **bool** TRUE if implemented, FALSE if absent
**Example:**
```php
\Aimeos\Prisma\Prisma::image()
->using( '', ['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.
```php
public function model( ?string $model ) : self
```
* @param **string|null** `$model` Model name
* @return **self** Provider interface
**Example:**
```php
\Aimeos\Prisma\Prisma::image()
->using( '', ['api_key' => 'xxx'])
->model( 'dall-e-3' );
```
### withClientOptions
Add options for the Guzzle HTTP client.
```php
public function withClientOptions( array `$options` ) : self
```
* @param **array<string, mixed>** `$options` Associative list of name/value pairs
* @return **self** Provider interface
**Example:**
```php
\Aimeos\Prisma\Prisma::image()
->using( '', ['api_key' => 'xxx'])
->withClientOptions( ['timeout' => 120] );
```
### withSystemPrompt
Add a system prompt for the LLM.
It may be used by providers supporting system prompts. Otherwise, it's
ignored.
```php
public function withSystemPrompt( ?string $prompt ) : self
```
* @param **string|null** `$prompt` System prompt
* @return **self** Provider interface
**Example:**
```php
\Aimeos\Prisma\Prisma::image()
->using( '', ['api_key' => 'xxx'])
->withSystemPrompt( 'You are a professional illustrator' );
```
### Response objects
The methods return a *FileResponse*, *TextResponse* or *VectorResponse* object that
contains the returned data with optional meta/usage/description information.
**FileResponse** objects:
```php
$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:
```php
$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:
```php
$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):
```php
$meta = $response->meta();
```
It returns an associative array whose content totally depends on the provider.
Included **usage data** (optional):
```php
$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.
## Audio API
### demix
Separate an audio file into its individual tracks.
```php
public function demix( Audio $audio, int $stems, array $options = [] ) : FileResponse
```
* @param **Audio** `$audio` Input audio object
* @param **int** `$stems` Number of stems to separate into (e.g. 2 for vocals and accompaniment)
* @param **array<string, mixed>** `$options` Provider specific options
* @return **FileResponse** Audio file response
**Supported options:**
* AudioPod
### denoise
Remove noise from an audio file.
```php
public function denoise( Audio $audio, array $options = [] ) : FileResponse
```
* @param **Audio** `$audio` Input audio object
* @param **array<string, mixed>** `$options` Provider specific options
* @return **FileResponse** Audio file response
**Supported options:**
* [AudioPod](https://docs.audiopod.ai/api-reference/noise-reduction)
### describe
Describe the content of an audio file.
```php
public function describe( Audio $audio, ?string $lang = null, array $options = [] ) : TextResponse
```
* @param **Audio** `$audio` Input audio object
* @param **string|null** `$lang` ISO language code the description should be generated in
* @param **array<string, mixed>** `$options` Provider specific options
* @return **TextResponse** Response text
**Supported options:**
* Gemini
* Groq
* [OpenAI](https://platform.openai.com/docs/api-reference/audio/createTranscription)
### revoice
Exchange the voice in an audio file.
```php
public function revoice( Audio $audio, string $voice, array $options = [] ) : FileResponse;
```
* @param **Audio** `$audio` Input audio object
* @param **string** `$voice` Voice name or identifier
* @param **array<string, mixed>** `$options` Provider specific options
* @return **FileResponse** Audio file response
**Supported options:**
* AudioPod
* [ElevenLabs](https://elevenlabs.io/docs/api-reference/speech-to-speech/convert)
* [Murf](https://murf.ai/api/docs/api-reference/voice-changer/convert)
### speak
Converts text to speech.
```php
public function speak( string $text, string $voice = , array $options = [] ) : FileResponse;
```
* @param **string** `$text` Text to be converted to speech
* @param **string|null** `$voice` Voice identifier for speech synthesis
* @param **array<string, mixed>** `$options` Provider specific options
* @return **FileResponse** Audio file response
**Supported options:**
* [AudioPod](https://docs.audiopod.ai/api-reference/text-to-speech#generate-speech)
* [Deepgram](https://developers.deepgram.com/reference/text-to-speech/speak-request)
* [ElevenLabs](https://elevenlabs.io/docs/api-reference/text-to-speech/convert)
* Groq
* [Murf](https://murf.ai/api/docs/api-reference/text-to-speech/generate)
* [OpenAI](https://platform.openai.com/docs/api-reference/audio/createSpeech)
### transcribe
Converts speech to text.
```php
public function transcribe( Audio $audio, ?string $lang = null, array $options = [] ) : TextResponse
```
* @param **Audio** `$audio` Input audio object
* @param **string|null** `$lang` ISO language code of the audio content
* @param **array<string, mixed>** `$options` Provider specific options
* @return **TextResponse** Transcription text response
**Supported options:**
* [AudioPod](https://docs.audiopod.ai/api-reference/speech-to-text)
* [Deepgram](https://developers.deepgram.com/reference/text-to-speech/speak-request)
* [ElevenLabs](https://elevenlabs.io/docs/api-reference/speech-to-text/convert)
* Groq
* [Mistral](https://docs.mistral.ai/api/endpoint/audio/transcriptions)
* [OpenAI](https://platform.openai.com/docs/api-reference/audio/createTranscription)
## 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:
```php
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.
```php
public function background( Image $image, string $prompt, array $options = [] ) : FileResponse
```
* @param **Image** `$image` Input image object
* @param **string** `$prompt` Prompt describing the new background
* @param **array<string, mixed>** `$options` Provider specific options
* @return **FileResponse** Response file
**Supported options:**
* Clipdrop
* [Ideogram](https://developer.ideogram.ai/api-reference/api-reference/replace-background-v3#request)
* [VertexAI](https://docs.cloud.google.com/vertex-ai/generative-ai/docs/model-reference/imagen-product-recontext-api#parameters)
**Example:**
```php
use Aimeos\Prisma\Prisma;
use \Aimeos\Prisma\Files\Image;
$image = Image::fromUrl( 'https://example.com/image.png' );
$fileResponse = Prisma::image()
->using( '', ['api_key' => 'xxx'])
->background( $image, 'Golden sunset on a caribbean beach' );
$image = $fileResponse->binary();
```
### describe
Describe the content of an image.
```php
public function describe( Image $image, ?string $lang = null, array $options = [] ) : TextResponse
```
* @param **Image** `$image` Input image object
* @param **string|null** `$lang` ISO language code the description should be generated in
* @param **array<string, mixed>** `$options` Provider specific options
* @return **TextResponse** Response text
**Supported options:**
* Gemini
* Groq
* [Ideogram](https://developer.ideogram.ai/api-reference/api-reference/describe#request)
* OpenAI
**Example:**
```php
use Aimeos\Prisma\Prisma;
use \Aimeos\Prisma\Files\Image;
$image = Image::fromUrl( 'https://example.com/image.png' );
$textResponse = Prisma::image()
->using( '', ['api_key' => 'xxx'])
->describe( $image, 'de' );
$text = $textResponse->text();
```
### detext
Remove all text from the image.
```php
public function detext( Image $image, array $options = [] ) : FileResponse
```
* @param **Image** `$image` Input image object
* @param **array<string, mixed>** `$options` Provider specific options
* @return **FileResponse** Response file
**Supported options:**
* Clipdrop
**Example:**
```php
use Aimeos\Prisma\Prisma;
use \Aimeos\Prisma\Files\Image;
$image = Image::fromUrl( 'https://example.com/image.png' );
$fileResponse = Prisma::image()
->using( '', ['api_key' => 'xxx'])
->detext( `$image` );
$image = $fileResponse->binary();
```
### erase
Erase parts of the image.
```php
public function erase( Image $image, Image $mask, array $options = [] ) : FileResponse
```
* @param **Image** `$image` Input image object
* @param **Image** `$mask` Mask image object
* @param **array<string, mixed>** `$options` Provider 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:**
* [Clipdrop](https://clipdrop.co/apis/docs/cleanup)
* [StabilityAI](https://platform.stability.ai/docs/api-reference#tag/Edit/paths/~1v2beta~1stable-image~1edit~1erase/post)
**Example:**
```php
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( '', ['api_key' => 'xxx'])
->erase( $image, $mask );
$image = $fileResponse->binary();
```
### imagine
Generate an image from the prompt.
```php
public function imagine( string $prompt, array $images = [], array $options = [] ) : FileResponse
```
* @param **string** `$prompt` Prompt describing the image
* @param **array<int, \Aimeos\Prisma\Files\Image>** `$images` Associative list of file name/Image instances
* @param **array<string, mixed>** `$options` Provider specific options
* @return **FileResponse** Response file
**Supported options:**
* [Bedrock](https://docs.aws.amazon.com/bedrock/latest/userguide/model-parameters-titan-image.html)
* [Black Forest Labs](https://docs.bfl.ai/api-reference/models/generate-or-edit-an-image-with-flux2-[pro])
* Clipdrop
* [Gemini](https://ai.google.dev/gemini-api/docs/image-generation#optional_configurations)
* [Ideogram](https://developer.ideogram.ai/api-reference/api-reference/generate-v3#request)
* [VertexAI](https://docs.cloud.google.com/vertex-ai/generative-ai/docs/model-reference/imagen-api#generate_images)
* [OpenAI GPT image 1](https://platform.openai.com/docs/guides/image-generation?image-generation-model=gpt-image-1#customize-image-output)
* [OpenAI Dall-e-3](https://platform.openai.com/docs/guides/image-generation?image-generation-model=dall-e-3#customize-image-output)
* [OpenAI Dall-e-2](https://platform.openai.com/docs/guides/image-generation?image-generation-model=dall-e-2#customize-image-output)
* [StabilityAI Core](https://platform.stability.ai/docs/api-reference#tag/Generate/paths/~1v2beta~1stable-image~1generate~1core/post)
* [StabilityAI Ultra](https://platform.stability.ai/docs/api-reference#tag/Generate/paths/~1v2beta~1stable-image~1generate~1ultra/post)
* [StabilityAI Stable Diffusion 3.5](https://platform.stability.ai/docs/api-reference#tag/Generate/paths/~1v2beta~1stable-image~1generate~1sd3/post)
**Example:**
```php
use Aimeos\Prisma\Prisma;
$fileResponse = Prisma::image()
->using( '', ['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.
```php
public function inpaint( Image $image, Image $mask, string $prompt, array $options = [] ) : FileResponse
```
* @param **Image** `$image` Input image object
* @param **Image** `$mask` Input mask image object
* @param **string** `$prompt` Prompt describing the changes
* @param **array<string, mixed>** `$options` Provider 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](https://docs.aws.amazon.com/bedrock/latest/userguide/model-parameters-titan-image.html)
* [Black Forest Labs](https://docs.bfl.ai/api-reference/models/generate-an-image-with-flux1-fill-[pro]-using-an-input-image-and-mask)
* [Ideogram](https://developer.ideogram.ai/api-reference/api-reference/edit-v3#request)
* [VertexAI](https://docs.cloud.google.com/vertex-ai/generative-ai/docs/model-reference/imagen-api-edit#parameters)
* [OpenAI GPT image 1](https://platform.openai.com/docs/guides/image-generation?image-generation-model=gpt-image-1#customize-image-output)
* [OpenAI Dall-e-3](https://platform.openai.com/docs/guides/image-generation?image-generation-model=dall-e-3#customize-image-output)
* [OpenAI Dall-e-2](https://platform.openai.com/docs/guides/image-generation?image-generation-model=dall-e-2#customize-image-output)
* [StabilityAI](https://platform.stability.ai/docs/api-reference#tag/Edit/paths/~1v2beta~1stable-image~1edit~1inpaint/post)
**Example:**
```php
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( '', ['api_key' => 'xxx'])
->inpaint( $image, $mask, 'add a pink flamingo' );
$image = $fileResponse->binary();
```
### isolate
Remove the image background.
```php
public function isolate( Image $image, array $options = [] ) : FileResponse
```
* @param **Image** `$image` Input image object
* @param **array<string, mixed>** `$options` Provider specific options
* @return **FileResponse** Response file
**Supported options:**
* [Bedrock](https://docs.aws.amazon.com/bedrock/latest/userguide/model-parameters-titan-image.html)
* [Clipdrop](https://clipdrop.co/apis/docs/remove-background)
* [RemoveBG](https://www.remove.bg/api#api-reference)
* [StabilityAI](https://platform.stability.ai/docs/api-reference#tag/Edit/paths/~1v2beta~1stable-image~1edit~1remove-background/post)
**Example:**
```php
use Aimeos\Prisma\Prisma;
use \Aimeos\Prisma\Files\Image;
$image = Image::fromUrl( 'https://example.com/image.png' );
$fileResponse = Prisma::image()
->using( '', ['api_key' => 'xxx'])
->isolate( `$image` );
$image = $fileResponse->binary();
```
### recognize
Recognizes the text in the given image (OCR).
```php
public function recognize( Image $image, array $options = [] ) : TextResponse;
```
* @param **Image** `$image` Input image object
* @param **array<string, mixed>** `$options` Provider specific options
* @return **TextResponse** Response text object
**Supported options:**
* [Mistral](https://docs.mistral.ai/api/endpoint/ocr#operation-ocr_v1_ocr_post)
**Example:**
```php
use Aimeos\Prisma\Prisma;
use \Aimeos\Prisma\Files\Image;
$image = Image::fromUrl( 'https://example.com/image.png' );
$textTesponse = Prisma::image()
->using( '', ['api_key' => 'xxx'])
->recognize( `$image` );
$text = $textResponse->text();
```
### relocate
Place the foreground object on a new background.
```php
public function relocate( Image $image, Image $bgimage, array $options = [] ) : FileResponse
```
* @param **Image** `$image` Input image with foreground object
* @param **Image** `$bgimage` Background image
* @param **array<string, mixed>** `$options` Provider specific options
* @return **FileResponse** Response file
**Supported options:**
* [RemoveBG](https://www.remove.bg/api#api-reference)
**Example:**
```php
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( '', ['api_key' => 'xxx'])
->relocate( $image, $bgimage );
$image = $fileResponse->binary();
```
### repaint
Repaint an image according to the prompt.
```php
public function repaint( Image $image, string $prompt, array $options = [] ) : FileResponse
```
* @param **Image** `$image` Input image object
* @param **string** `$prompt` Prompt describing the changes
* @param **array<string, mixed>** `$options` Provider specific options
* @return **FileResponse** Response file
**Supported options:**
* [Gemini](https://ai.google.dev/gemini-api/docs/image-generation#optional_configurations)
* [Ideogram](https://developer.ideogram.ai/api-reference/api-reference/remix-v3#request)
**Example:**
```php
use Aimeos\Prisma\Prisma;
use \Aimeos\Prisma\Files\Image;
$image = Image::fromUrl( 'https://example.com/image.png' );
$fileResponse = Prisma::image()
->using( '', ['api_key' => 'xxx'])
->repaint( $image, 'Use a van Goch style' );
$image = $fileResponse->binary();
```
### uncrop
Extend/outpaint the image.
```php
public function uncrop( Image $image, int $top, int $right, int $bottom, int $left, array $options = [] ) : FileResponse
```
* @param **Image** `$image` Input image object
* @param **int** `$top` Number of pixels to extend to the top
* @param **int** `$right` Number of pixels to extend to the right
* @param **int** `$bottom` Number of pixels to extend to the bottom
* @param **int** `$left` Number of pixels to extend to the left
* @param **array<string, mixed>** `$options` Provider specific options
* @return **FileResponse** Response file
**Supported options:**
* [Black Forest Labs](https://docs.bfl.ai/api-reference/models/expand-an-image-by-adding-pixels-on-any-side)
* Clipdrop
* [StabilityAI](https://platform.stability.ai/docs/api-reference#tag/Edit/paths/~1v2beta~1stable-image~1edit~1outpaint/post)
**Example:**
```php
use Aimeos\Prisma\Prisma;
use \Aimeos\Prisma\Files\Image;
$image = Image::fromUrl( 'https://example.com/image.png' );
$fileResponse = Prisma::image()
->using( '', ['api_key' => 'xxx'])
->uncrop( $image, 100, 200, 0, 50 );
$image = $fileResponse->binary();
```
### upscale
Scale up the image.
```php
public function upscale( Image $image, int $factor, array $options = [] ) : FileResponse
```
* @param **Image** `$image` Input image object
* @param **int** `$factor` Upscaling factor between 2 and the maximum value supported by the provider
* @param **array<string, mixed>** `$options` Provider specific options
* @return **FileResponse** Response file
**Supported options:**
* Clipdrop
* [Ideogram](https://developer.ideogram.ai/api-reference/api-reference/upscale#request)
* [VertexAI](https://docs.cloud.google.com/vertex-ai/generative-ai/docs/model-reference/imagen-upscale-api#parameters)
* [StabilityAI](https://platform.stability.ai/docs/api-reference#tag/Upscale)
**Example:**
```php
use Aimeos\Prisma\Prisma;
use \Aimeos\Prisma\Files\Image;
$image = Image::fromUrl( 'https://example.com/image.png' );
$fileResponse = Prisma::image()
->using( '', ['api_key' => 'xxx'])
->upscale( $image, 4 );
$image = $fileResponse->binary();
```
### vectorize
Creates embedding vectors of the images' content.
```php
public function vectorize( array $images, ?int $size = null, array $options = [] ) : VectorResponse
```
* @param **array<int, \Aimeos\Prisma\Files\Image>** `$images` List of input image objects
* @param **int|null** `$size` Size of the resulting vector or null for provider default
* @param **array<string, mixed>** `$options` Provider specific options
* @return **VectorResponse** Response vector object
**Supported options:**
* Bedrock
* [Cohere](https://docs.cohere.com/reference/embed#request)
* VertexAI
* [VoyageAI](https://docs.voyageai.com/reference/multimodal-embeddings-api)
**Example:**
```php
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( '', ['api_key' => 'xxx'])
->vectorize( $images, 512 );
$vectors = $vectorResponse->vectors();
```
## Video API
### describe
Describe the content of a video file.
```php
public function describe( Video $video, ?string $lang = null, array $options = [] ) : TextResponse
```
* @param **Video** `$video` Input video object
* @param **string|null** `$lang` ISO language code the description should be generated in
* @param **array<string, mixed>** `$options` Provider specific options
* @return **TextResponse** Response text
**Supported options:**
* Gemini
## Custom providers
### Base skeleton
```php
header( '', $config['api_key'] );
// base url for all requests (no paths)
$this->baseUrl( '' );
}
```
Depending on the provider type (Audio, Image or Video), you can implement one or
more of the available interfaces for that provider type:
- [Audio](https://github.com/aimeos/prisma/tree/master/src/Contracts/Audio)
- [Image](https://github.com/aimeos/prisma/tree/master/src/Contracts/Image)
- [Video](https://github.com/aimeos/prisma/tree/master/src/Contracts/Video)
For example:
```php
namespace Aimeos\Prisma\Providers\Image;
use Aimeos\Prisma\Contracts\Image\Describe;
use Aimeos\Prisma\Exceptions\PrismaException;
use Aimeos\Prisma\Files\Image;
use Aimeos\Prisma\Providers\Base;
use Aimeos\Prisma\Responses\TextResponse;
class Myprovider extends Base implements Describe
{
public function describe( Image $image, ?string $lang = null, array $options = [] ) : TextResponse
{
// ...
}
}
```
### Requests
There are a few support methods available to simplify building requests which
are sent by the Guzzle client to the server of the AI provider.
First, you should validate and limit the passed options to the ones supported
by the AI API. The *allow()* and *sanitze()* methods filter out unsupported
values because different APIs have different parameters but users of the
Prisma API should be able to pass parameters for several AI providers at once.
Therefore, get only supported parameters and values using:
```php
// filter key/value pairs in $options and use the ones allowed by the API
$allowed = $this->allow( $options, ['', '', /* ... */] );
// filter values to pass only allowed option values (optional)
$allowed = $this->sanitize( $allowed, ['' => ['', '', '']])
```
If the user can choose between several LLM models when using the API, the
*modelName()* method will return the users choice or the passed default value:
```php
$model = $this->modelName( 'gemini-2.5-flash' );
```
To build the request in the correct format (form key/value pairs, multipart or
JSON data), the *request()* method transforms parameters and files for form and
multipart requests. JSON data is specific to the API and you must create it
yourself:
```php
// Form data request
$data = $this->request( params );
// Multipart request
$data = ['multipart' => $this->request( params, ['image_key' = $image->binary()] )];
// JSON request
$data = ['json' => ['image_key' = array_map( fn( $image ) => $image->base64()] + params];
```
Then, you can send the request using the Guzzle client, validate the response
and get the returned content:
```php
// use Guzzle to send the request and get the response from the server
$response = $this->client()->post( 'relative/api/path', $data );
// validates HTTP status codes, overwrite if needed
$this->validate( $response );
// get binary content or JSON content
$content = $response->getBody()->getContents();
```
A full example would be:
```php
use Aimeos\Prisma\Files\Image;
use Aimeos\Prisma\Responses\TextResponse;
public function describe( Image $image, ?string $lang = null, array $options = [] ) : TextResponse
{
$model = $this->modelName( 'flash' );
$allowed = $this->allow( $options, ['version'] );
$params = ['language' => $lang] + $allowed;
$data = ['multipart' => $this->request( params, ['file' = $image->binary()] )];
$response = $this->client()->post( 'relative/api/path', $data );
$this->validate( $response );
$content = $response->getBody()->getContents();
// return a response
}
```
### Responses
There are several response types available, which can be returned depending on
the implemented interfaces:
* FileResponse
* TextResponse
* VectorResponse
#### File response
A FileResponse can contain one or more files, either as binary or base64 data,
or as remote URL. Passing the mime type is optional but prevents guessing the
file type later:
```php
use Aimeos\Prisma\Responses\FileResponse;
$response = FileResponse::fromBinary( '...', 'image/png' );
$response = FileResponse::fromBase64( '...', 'image/png' );
$response = FileResponse::fromUrl( '...', 'image/png' );
```
You can also add more than one file by using the *add()* method:
```php
use Aimeos\Prisma\Files\File;
$response->add( File::fromBinary( '...', 'image/png' ) );
```
If the API processes requests asynchronously, the *fromAsync()* method accepts
a closure function and the optional timeout between requests as second parameter:
```php
$client = $this->client();
$response = FileResponse::fromAsync( function( FileResponse $fr ) uses ( $client ) {
// download or add file(s) to file response object
$fr->add( File::fromUrl( '...', 'image/png' ) );
}, 3 );
```
#### Text response
The TextResponse can contain one or more texts and is created by using:
```php
use Aimeos\Prisma\Responses\TextResponse;
$response = TextResponse::fromText( '...' );
$response->add( '...' ); // add more texts
```
TextResponse objects also support *fromAsync()* for asynchronous APIs using a
closure function and the optional timeout between requests as second parameter:
```php
$client = $this->client();
$response = TextResponse::fromAsync( function( FileResponse $fr ) uses ( $client ) {
// download and add texts to text response object
$fr->add( '...' );
}, 3 );
```
#### Vector response
The *vectorize()* method returns a *VectorResponse* object which contains the
vector of float numbers representing the input:
```php
use Aimeos\Prisma\Responses\VectorResponse;
$response = VectorResponse::fromVectors( [
[0.27629, 0.89271, 0.98265, /* ... */],
/* ... */
] );
```
#### Meta data
All response objects support adding usage information and meta data if they are
returned by the provider API. Use the *withUsage() and *withMeta()* methods to
pass that information as part of the response object:
```php
$response->withUsage( // optional
100, // used tokens, credits, etc. if available or NULL
[] // arbitrary key/value pairs for the rest of the usage information
);
$response->withMeta( // optional
[] // arbitrary meta data as key/value pairs, can be nested
);
```
TextResponse objects can store structured data e.g. returned when audio files
are transcribed:
```php
$response->withStructured( [
// for transcriptions
['start' => 0.0, 'end' => 1.0, 'text' => 'This is a test.'],
// ...
] );
```
Transcriptions must always contain the keys *start* and *end* in seconds as well
as *text* for the content in each entry (but there can be more key/value pairs
if available).
The FileResponse object also supports *withDescription()* to attach the file
description as string to the response object:
```php
$response->withDescription( '...' );
```
### Examples
#### Audio provider
```php
header( 'x-api-key', $config['api_key'] );
$this->baseUrl( 'https://ai.com' );
}
public function describe( Audio $audio, ?string $lang = null, array $options = [] ) : TextResponse
{
$allowed = $this->allow( $options, ['version'] );
$model = $this->modelName( 'flash' );
$params = ['language' => $lang, 'model' => model] + $allowed;
$data = ['multipart' => $this->request( params, ['file' = $audio->binary()] )];
$response = $this->client()->post( 'relative/api/path', $data );
$this->validate( $response );
$data = $this->fromJson( $response );
return TextResponse::fromText( @$data['text'] )
->withStructured( // optional
$data['segments'] ?? []
)
->withUsage( // optional
@$data['usage']['total'],
$data['usage'] ?? []
)
->withMeta( // optional
$data['meta'] ?? []
);
}
}
```
### Image provider
```php
header( 'x-api-key', $config['api_key'] );
$this->baseUrl( 'https://ai.com' );
}
public function describe( Image $audio, ?string $lang = null, array $options = [] ) : TextResponse
{
$allowed = $this->allow( $options, ['version'] );
$model = $this->modelName( 'flash' );
$params = ['language' => $lang, 'model' => model] + $allowed;
$data = ['multipart' => $this->request( params, ['file' = $audio->binary()] )];
$response = $this->client()->post( 'relative/api/path', $data );
$this->validate( $response );
$data = $this->fromJson( $response );
return TextResponse::fromText( @$data['text'] )
->withStructured( // optional
$data['segments'] ?? []
)
->withUsage( // optional
@$data['usage']['total'],
$data['usage'] ?? []
)
->withMeta( // optional
$data['meta'] ?? []
);
}
}
```
### Video provider
```php
header( 'x-api-key', $config['api_key'] );
$this->baseUrl( 'https://ai.com' );
}
public function describe( Video $video, ?string $lang = null, array $options = [] ) : TextResponse
{
$allowed = $this->allow( $options, ['version'] );
$model = $this->modelName( 'flash' );
$params = ['language' => $lang, 'model' => model] + $allowed;
$data = ['multipart' => $this->request( params, ['file' = $video->binary()] )];
$response = $this->client()->post( 'relative/api/path', $data );
$this->validate( $response );
$data = $this->fromJson( $response );
return TextResponse::fromText( @$data['text'] )
->withStructured( // optional
$data['segments'] ?? []
)
->withUsage( // optional
@$data['usage']['total'],
$data['usage'] ?? []
)
->withMeta( // optional
$data['meta'] ?? []
);
}
}
```