Install the Package
composer require async-aws/bedrock-runtime
Ensure your Laravel project meets the PHP 8.2+ requirement.
Configure AWS Credentials
Use Laravel’s .env or the aws config file (if using async-aws/core):
AWS_ACCESS_KEY_ID=your_access_key
AWS_SECRET_ACCESS_KEY=your_secret_key
AWS_REGION=us-east-1 # Required for BedrockRuntime
First Use Case: Invoke a Model
use AsyncAws\BedrockRuntime\BedrockRuntimeClient;
use AsyncAws\BedrockRuntime\ValueObject\InvokeModelRequest;
$client = new BedrockRuntimeClient();
$request = InvokeModelRequest::create()
->withModelId('anthropic.claude-v2') // Replace with your model ID
->withBody('{"prompt": "Hello, world!"}');
$response = $client->invokeModel($request);
echo $response->getBody()->getContent();
Key Resources
Use for simple, one-off requests (e.g., chatbot prompts, text generation):
$response = $client->invokeModel($request);
$output = json_decode($response->getBody()->getContent(), true);
For real-time interactions (e.g., chat apps, live analysis):
use AsyncAws\BedrockRuntime\ValueObject\InvokeModelWithBidirectionalStreamRequest;
$streamRequest = InvokeModelWithBidirectionalStreamRequest::create()
->withModelId('anthropic.claude-v2')
->withBody('{"prompt": "Explain async-aws..."}');
$stream = $client->invokeModelWithBidirectionalStream($streamRequest);
foreach ($stream->getBody() as $chunk) {
echo $chunk->getContent(); // Process chunks as they arrive
}
Configure harmful content detection (Bedrock Guardrails):
$request = InvokeModelRequest::create()
->withModelId('anthropic.claude-v2')
->withBody('{"prompt": "..."}')
->withGuardrailsConfig([
'harmfulContentDetection' => [
'enabled' => true,
'level' => 'STANDARD', // or 'STRICT'
],
]);
Catch AWS-specific exceptions:
try {
$response = $client->invokeModel($request);
} catch (\AsyncAws\Core\Exception\BedrockRuntimeException $e) {
// Handle Bedrock-specific errors (e.g., model throttling, invalid input)
logger()->error($e->getMessage());
}
Bind the client in AppServiceProvider for dependency injection:
public function register()
{
$this->app->singleton(BedrockRuntimeClient::class, function ($app) {
return new BedrockRuntimeClient();
});
}
Offload long-running invocations to Laravel queues:
use AsyncAws\BedrockRuntime\BedrockRuntimeClient;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
class GenerateTextJob implements ShouldQueue
{
use Dispatchable, Queueable;
public function handle(BedrockRuntimeClient $client)
{
$response = $client->invokeModel($this->request);
// Store/process response...
}
}
Cache frequent model responses (e.g., FAQs) using Laravel’s cache:
$cacheKey = "bedrock_{$modelId}_{$promptHash}";
$response = cache()->remember($cacheKey, now()->addHours(1), function () use ($client, $request) {
return $client->invokeModel($request);
});
Store model IDs in config/database for easy updates:
// config/bedrock.php
return [
'models' => [
'claude' => 'anthropic.claude-v2',
'llama' => 'meta.llama3-8b',
],
];
HTTP/2 Requirement for Streaming
invokeModelWithBidirectionalStream only works with HTTP/2. Ensure your server (e.g., Laravel Valet, Forge) supports it.invokeModelWithResponseStream (HTTP/1.1) for unidirectional streaming if HTTP/2 is unavailable.Payload Size Limits
InvokeModel. For larger inputs:
InvokeModelWithBidirectionalStream for incremental processing.Model-Specific Quirks
$request->withBody(json_encode(['prompt' => '...', 'max_tokens' => 100]));
inputText instead of prompt.Rate Limiting
use AsyncAws\Core\Exception\BedrockRuntimeException;
use Symfony\Component\RateLimiter\RateLimiterInterface;
try {
$response = $client->invokeModel($request);
} catch (BedrockRuntimeException $e) {
if ($e->getStatusCode() === 429) {
$this->rateLimiter->waitForToken(); // Custom implementation
retry();
}
}
Enum Mismatches
UNKNOWN_TO_SDK), handle it gracefully:
$status = $response->getModelInvocationOutput()->getStatus();
if ($status === 'UNKNOWN_TO_SDK') {
logger()->warning("Unknown Bedrock status: {$status}");
}
Enable Verbose Logging Configure the AsyncAws logger to debug API calls:
$client = new BedrockRuntimeClient([
'logger' => new \Monolog\Logger('bedrock', [
new \Monolog\Handler\StreamHandler(storage_path('logs/bedrock.log')),
]),
'debug' => true, // Enable HTTP request/response logging
]);
Validate Input/Output
Use PHP’s json_last_error() to catch malformed payloads:
$body = json_encode($request->getBody());
if (json_last_error() !== JSON_ERROR_NONE) {
throw new \InvalidArgumentException("Invalid JSON: " . json_last_error_msg());
}
Test with Minimal Payloads
Start with a simple prompt (e.g., "Hello") to isolate issues before scaling.
Custom Middleware Add request/response transformations:
$client = new BedrockRuntimeClient([
'middleware' => [
new class implements \AsyncAws\Core\Middleware\MiddlewareInterface {
public function handle($request, callable $next) {
// Modify request (e.g., add headers)
return $next($request);
}
},
],
]);
Event Dispatching Trigger Laravel events for model invocations:
event(new \App\Events\BedrockInvoked($response));
Mocking for Tests
Use AsyncAws\Core\Exception\ExceptionFactory to simulate failures:
$factory = new ExceptionFactory();
$factory->createBedrockRuntimeException(400, 'Invalid model ID');
Service Tier Support
Specify a service tier (e.g., DEV, PROD) for cost optimization:
$request->withServiceTier('DEV'); // For testing
How can I help you explore Laravel packages today?