PHP code example of bherila / genai-laravel

1. Go to this page and download the library: Download bherila/genai-laravel library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

bherila / genai-laravel example snippets


use Bherila\GenAiLaravel\GenAiRequest;
use Bherila\GenAiLaravel\Clients\GenAiClientFactory;

$client = GenAiClientFactory::make('anthropic'); // or 'bedrock', 'gemini'

$response = GenAiRequest::with($client)
    ->system('You are a financial analyst.')
    ->withFile(base64_encode(file_get_contents($path)), 'application/pdf')
    ->prompt('Extract key figures.')
    ->generate();

echo $response->text;
// or
foreach ($response->toolCalls as $call) {
    // ['name' => 'extract_data', 'input' => [...]]
}

// Different tenants, different providers — call site is identical
$client = match ($user->ai_provider) {
    'anthropic' => new AnthropicClient(apiKey: $user->anthropic_key, model: 'claude-sonnet-4-6'),
    'bedrock'   => new BedrockClient(apiKey: $creds->key, modelId: $creds->model, region: 'us-east-1'),
    default     => new GeminiClient(apiKey: $user->gemini_key),
};

$response = GenAiRequest::with($client)
    ->system($systemPrompt)
    ->withFiles($files)   // [['base64' => '...', 'mimeType' => 'application/pdf'], ...]
    ->prompt($userPrompt)
    ->tools($toolConfig)
    ->generate();

use Bherila\GenAiLaravel\Schema;
use Bherila\GenAiLaravel\ToolChoice;
use Bherila\GenAiLaravel\ToolConfig;
use Bherila\GenAiLaravel\ToolDefinition;

$toolConfig = new ToolConfig(
    tools: [
        new ToolDefinition(
            name: 'extract_invoice',
            description: 'Extract invoice fields',
            inputSchema: Schema::object([
                'vendor'  => Schema::string('Vendor name'),
                'amount'  => Schema::number('Total amount due'),
                'due_date' => Schema::string('Due date in YYYY-MM-DD'),
            ], 

$messages = [['role' => 'user', 'content' => [ContentBlock::text($prompt)]]];

// Note the parameter: an arrow function captures by value at definition, so a
// closure over $messages would resend the first turn forever.
$ask = static fn (array $history) => GenAiRequest::with($client)
    ->messages($history)
    ->tools($toolConfig)
    ->generate();

$response = $ask($messages);

while ($response->hasToolCalls()) {
    $messages[] = $response->assistantMessage();

    $results = [];
    foreach ($response->toolCalls as $call) {
        $results[] = ContentBlock::toolResultFor($call, $myTools->run($call['name'], $call['input']));
    }

    $messages[] = ['role' => 'user', 'content' => $results];
    $response = $ask($messages);
}

echo $response->text;

Schema::string('Optional description')
Schema::number()
Schema::integer()
Schema::boolean()
Schema::object(['field' => Schema::string()], // wrap raw JSON Schema

ToolChoice::auto()          // model decides whether to call a tool
ToolChoice::any()           // model must call at least one tool
ToolChoice::none()          // model must not call any tool
ToolChoice::tool('my_fn')   // model must call this specific tool

$fileRef = $client->uploadFile($stream, 'application/pdf', 'report.pdf');

try {
    $response = GenAiRequest::with($client)
        ->withFileRef($fileRef, 'application/pdf')
        ->prompt('Summarise this report.')
        ->generate();

    echo $response->text;
} finally {
    $client->deleteFile($fileRef);
}

->messages([[
    'role' => 'user',
    'content' => [
        ContentBlock::fileReference($fileRef, 'application/pdf'),
        ContentBlock::document($smallBase64, 'application/pdf'),
        ContentBlock::text('Which figures changed?'),
    ],
]])

// AppServiceProvider
$this->app->singleton(GenAiClient::class, fn () => GenAiClientFactory::make());

use Bherila\GenAiLaravel\Contracts\GenAiClient;

class MyService
{
    public function __construct(private readonly GenAiClient $ai) {}

    public function analyse(string $text): string
    {
        return GenAiRequest::with($this->ai)
            ->prompt($text)
            ->generate()
            ->text;
    }
}

use Bherila\GenAiLaravel\Facades\GenAi;

$raw = GenAi::converse($system, $messages, $toolConfig);   // $system is a string
$text = GenAi::extractText($raw);
$usage = GenAi::extractUsage($raw);

use Bherila\GenAiLaravel\Clients\GenAiClientFactory;
use Bherila\GenAiLaravel\Credentials\AnthropicCredentials;
use Bherila\GenAiLaravel\Credentials\BedrockCredentials;
use Bherila\GenAiLaravel\Credentials\GeminiCredentials;

$client = GenAiClientFactory::make(
    credentials: new GeminiCredentials(apiKey: $user->gemini_key),
);

// Region and model travel with the credentials where they need to:
$client = GenAiClientFactory::make(
    credentials: new BedrockCredentials(
        apiKey: $tenant->bedrock_token,
        region: $tenant->aws_region,
        model: $tenant->bedrock_model,
    ),
);

$client = GenAiClientFactory::make(
    credentials: new AnthropicCredentials(apiKey: $tenant->anthropic_key),
);

$response = GenAiRequest::with($client)->prompt('...')->generate();

$response->usage->inputTokens;              // non-cached prompt tokens
$response->usage->outputTokens;             // completion tokens
$response->usage->totalTokens;
$response->usage->cacheReadInputTokens;     // served from prompt cache
$response->usage->cacheCreationInputTokens; // written to prompt cache
$response->usage->raw;                      // provider-specific payload

// Estimate cost in USD given per-million-token prices for the model you used.
$cost = $response->usage->estimatedCostUsd(
    inputPerMillion: 3.00,
    outputPerMillion: 15.00,
    cacheReadPerMillion: 0.30,
    cacheCreationPerMillion: 3.75,
);

use Bherila\GenAiLaravel\Http\RetryStrategy;

new AnthropicClient(
    apiKey: '...',
    retry: new RetryStrategy(maxAttempts: 1), // disable retries
);

$client = GenAiClientFactory::make('anthropic'); // or 'bedrock', 'gemini'

foreach ($client->listModels() as $model) {
    $model->id;                          // call-ready identifier
    $model->name;                        // human-readable display name
    $model->provider;                    // "anthropic" | "bedrock" | "gemini"
    $model->description;                 // free-form, when provided
    $model->inputTokenLimit;             // context window, when advertised
    $model->outputTokenLimit;            // max completion tokens, when advertised
    $model->inputCostPerMillionTokens;   // null — no provider returns pricing
    $model->outputCostPerMillionTokens;  // null — no provider returns pricing
    $model->raw;                         // provider-specific entry
}

use Bherila\GenAiLaravel\PricingBook;

$book = PricingBook::fromArray([
    'anthropic' => [
        'claude-sonnet-4-6' => ['input' => 3.0, 'output' => 15.0, 'cache_read' => 0.3, 'cache_creation' => 3.75],
    ],
    'bedrock' => [
        'us.anthropic.claude-haiku-4-5-20251001-v1:0' => ['input' => 0.8, 'output' => 4.0],
    ],
    'gemini' => [
        'gemini-3.6-flash' => ['input' => 0.1, 'output' => 0.4],
    ],
]);

// Decorate listModels() output with prices
$models = $book->enrichAll($client->listModels());

// Compute cost for a specific call
$cost = $book->estimateCost($response->usage, $client->provider(), $client->model());

$client::maxInlineFileBytes('application/pdf'); // decoded bytes for one inline block
$client::maxUploadedFileBytes();                // decoded bytes via the File API, null when there is none
$client::maxInlineBlocksPerMessage($mime);      // blocks of that kind per message, null when uncapped
$client::maxRequestBytes();                    // whole serialized request, null when uncapped
$client::supportsFileApi();                     // whether uploadFile() will work at all

use Bherila\GenAiLaravel\Clients\AnthropicClient;
use Bherila\GenAiLaravel\FileConversion\ConversionLimits;
use Bherila\GenAiLaravel\FileConversion\SpreadsheetToText;

$limits = new ConversionLimits(maxInputBytes: 8 * 1024 * 1024, maxSeconds: 15.0);

// One conversion.
SpreadsheetToText::convert($base64, $mime, $limits);

// Every conversion this client runs on your behalf.
$client = new AnthropicClient(apiKey: $key, conversionLimits: $limits);

use Bherila\GenAiLaravel\GenAiRequest;
use Bherila\GenAiLaravel\Mcp\EnqueueOptions;
use Bherila\GenAiLaravel\Mcp\McpClientFactory;
use Bherila\GenAiLaravel\Mcp\StoredAttachment;

$client = app(McpClientFactory::class)->forMailbox($mailbox);

$pending = GenAiRequest::with($client)
    ->system('You are a financial analyst.')
    ->withStoredAttachment(new StoredAttachment(
        name: 'report.pdf',
        mimeType: 'application/pdf',
        size: $document->size,
        sha256: $document->sha256,
        hostReference: "document:{$document->id}",
    ))
    ->prompt('Extract the key figures.')
    ->tools($toolConfig)
    ->enqueue(new EnqueueOptions(
        queue: 'documents',
        idempotencyKey: "report:{$report->id}",
        priority: 10,
    ));

$pending->id;
$pending->status();
$pending->response(); // null until completed, then a normal GenAiResponse

$plain = app(McpTokenService::class)->issue(
    mailbox: $mailbox,
    name: 'Personal Codex client',
    expiresAt: now()->addMonths(3),
);
// Display $plain once. Later: app(McpTokenService::class)->revoke($tokenModel);

use Illuminate\Support\Facades\Schedule;

Schedule::command('genai:mcp:deliver')->everyMinute()->withoutOverlapping();
Schedule::command('genai:mcp:prune')->daily();
bash
php artisan vendor:publish --tag=genai-config