> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# Laravel AI SDK용 Amazon Bedrock 드라이버

> Laravel AI SDK용 Amazon Bedrock 드라이버. 텍스트 생성, 스트리밍, 툴 사용, 구조화된 출력, 파일 첨부, 대화 이력, 임베딩, 이미지 생성, 음성(TTS), 리랭킹을 지원합니다.

## 개요

[revolution/laravel-amazon-bedrock](https://github.com/invokable/laravel-amazon-bedrock)은 [Laravel AI SDK](https://laravel.com/docs/ai-sdk)에서 Amazon Bedrock을 사용하기 위한 드라이버입니다. Bedrock의 여러 모델을 Laravel AI SDK의 통일된 API로 다룰 수 있습니다.

| 기능                     | Bedrock API 키만으로 이용 가능 | 지원 모델 / 서비스                                                                                   |
| ---------------------- | ---------------------- | --------------------------------------------------------------------------------------------- |
| 텍스트 생성 / 스트리밍          | ✅                      | Anthropic Claude, Amazon Nova, 그 외 대부분의 Bedrock 모델(모두 Converse API 경유)                        |
| 툴 사용(Function Calling) | ✅                      |                                                                                               |
| 구조화된 출력                | ✅                      |                                                                                               |
| 파일 첨부                  | ✅                      | 이미지, 문서, 음성, 동영상을 Converse API 경유로 첨부(모델마다 지원 형식이 다름)                                         |
| 이미지 생성                 | ✅                      | Stability AI(기본값), Amazon Nova Canvas(권장하지 않음)                                                |
| 음성(TTS)                | ⚠️                     | Amazon Polly(generative / neural / long-form / standard 엔진)                                   |
| 음성 인식(STT)             | ❌                      | 미지원                                                                                           |
| 임베딩                    | ✅                      | Amazon Titan Embeddings V2(기본값), Cohere Embed English/Multilingual V3, Cohere Embed V4(배치 지원) |
| 리랭킹                    | ⚠️                     | Cohere Rerank 3.5, Amazon Rerank 1.0                                                          |
| 파일                     | ✅                      | 텍스트 생성에서 로컬 파일 첨부 지원. 서버 측 업로드나 `fromId()`는 미지원                                               |

<Info>
  표의 `⚠️`는 "기능 자체가 미지원"이 아니라 "Bedrock API 키만으로는 이용할 수 없음"을 나타냅니다.
</Info>

<Info>
  Laravel AI SDK v0.6.3에서 Bedrock API 키를 사용한 Text·Image·Embeddings 공식 지원이 추가되었습니다. 이 패키지는 Amazon Polly를 이용한 음성(TTS)이나 리랭킹 등 공식 통합에서는 이용할 수 없는 기능도 지원하므로, 계속해서 공개를 이어가고 있습니다.
</Info>

주요 특징은 다음과 같습니다.

* **인증**: Bedrock API 키, AWS IAM 자격 증명(SigV4), 기본 AWS 자격 증명 체인(IAM 역할, 인스턴스 프로파일 등)에서 선택할 수 있습니다.
* **페일오버**: AI SDK의 멀티 프로바이더 페일오버를 지원. 속도 제한(429), 과부하(503, 529), 크레딧 관련 오류는 페일오버 가능한 예외로 매핑됩니다.
* **캐시 제어**: [Bedrock Converse API](https://docs.aws.amazon.com/bedrock/latest/userguide/conversation-inference.html)의 시스템 프롬프트에 ephemeral 캐시를 항상 활성화.
* **통일된 API**: Anthropic Claude, Amazon Nova, Meta Llama, Mistral 등 모든 모델을 Bedrock Converse API를 통해 통일된 인터페이스로 다룰 수 있습니다.

## 필수 요건

* PHP >= 8.3
* Laravel >= 12.x

## 설치

<Steps>
  <Step title="패키지 설치">
    ```bash theme={null}
    composer require revolution/laravel-amazon-bedrock
    ```
  </Step>

  <Step title="AI SDK 설정 파일 공개">
    ```bash theme={null}
    php artisan vendor:publish --provider="Laravel\Ai\AiServiceProvider"
    ```
  </Step>
</Steps>

## 설정

`config/ai.php`에 `amazon-bedrock` 프로바이더를 추가합니다. 필요에 따라 기본 프로바이더도 Bedrock으로 전환합니다.

```php theme={null}
'default' => 'amazon-bedrock',
'default_for_images' => 'amazon-bedrock',
'default_for_audio' => 'amazon-bedrock',
'default_for_embeddings' => 'amazon-bedrock',
'default_for_reranking' => 'amazon-bedrock',
```

### 옵션 1: Bedrock API 키

```php theme={null}
'providers' => [
    'amazon-bedrock' => [
        'driver' => 'amazon-bedrock',
        'key'    => env('AWS_BEDROCK_API_KEY', ''),
        'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
    ],
],
```

```dotenv theme={null}
AWS_BEDROCK_API_KEY=your_api_key
AWS_DEFAULT_REGION=us-east-1
```

Bedrock API 키는 AWS 관리 콘솔에서 발급받습니다.

<Warning>
  Bedrock API 키는 Bedrock Runtime API 전용입니다. `bedrock-agent-runtime`을 사용하는 리랭킹이나 Amazon Polly(TTS)에서는 사용할 수 없습니다. 이들은 SigV4 또는 기본 AWS 자격 증명 체인을 사용하세요.
</Warning>

### 옵션 2: AWS IAM 자격 증명(SigV4)

[Signature Version 4](https://docs.aws.amazon.com/general/latest/gr/signature-version-4.html)로 서명하는 AWS 액세스 키와 시크릿 키를 사용합니다.

```php theme={null}
'providers' => [
    'amazon-bedrock' => [
        'driver' => 'amazon-bedrock',
        'key'    => env('AWS_ACCESS_KEY_ID'),
        'secret' => env('AWS_SECRET_ACCESS_KEY'),
        'token'  => env('AWS_SESSION_TOKEN'),
        'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
    ],
],
```

```dotenv theme={null}
AWS_ACCESS_KEY_ID=AKIA...
AWS_SECRET_ACCESS_KEY=wJalr...
AWS_SESSION_TOKEN= # 선택(STS 임시 자격 증명용)
AWS_DEFAULT_REGION=us-east-1
```

<Info>
  `AWS_SESSION_TOKEN`은 임시 자격 증명(STS)을 사용하는 경우에만 설정합니다.
</Info>

### 옵션 3: 기본 AWS 자격 증명 체인(IAM 역할)

EC2 / ECS / Lambda 등 IAM 역할이 있는 환경에서는 `key`와 `secret`을 생략하고 [기본 AWS 자격 증명 프로바이더 체인](https://docs.aws.amazon.com/sdkref/latest/guide/standardized-credentials.html)을 사용할 수 있습니다.

```php theme={null}
'providers' => [
    'amazon-bedrock' => [
        'driver' => 'amazon-bedrock',
        'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
    ],
],
```

```dotenv theme={null}
AWS_DEFAULT_REGION=us-east-1
```

기본 자격 증명 체인은 환경 변수, 공유 자격 증명 파일(`~/.aws/credentials`), ECS 태스크 역할, EC2 인스턴스 프로파일 등에서 자동으로 해결합니다.

### 선택적 설정 키

| 키                              | 설명                   | 기본값                                               |
| ------------------------------ | -------------------- | ------------------------------------------------- |
| `secret`                       | AWS 시크릿 액세스 키(SigV4) | —                                                 |
| `token`                        | AWS 세션 토큰(SigV4)     | —                                                 |
| `timeout`                      | HTTP 요청 타임아웃(초)      | 30                                                |
| `max_tokens`                   | 요청당 기본 max tokens    | 8096                                              |
| `models.text.default`          | 기본 텍스트 모델            | `global.anthropic.claude-sonnet-4-6`              |
| `models.text.cheapest`         | 최저가 텍스트 모델           | `global.anthropic.claude-haiku-4-5-20251001-v1:0` |
| `models.text.smartest`         | 최고 성능 텍스트 모델         | `global.anthropic.claude-opus-4-7`                |
| `models.embeddings.default`    | 기본 임베딩 모델            | `amazon.titan-embed-text-v2:0`                    |
| `models.embeddings.dimensions` | 기본 임베딩 차원 수          | `1024`                                            |
| `models.image.default`         | 기본 이미지 모델            | `stability.stable-image-core-v1:1`                |
| `models.audio.default`         | 기본 음성(TTS) 엔진        | `generative`                                      |
| `models.reranking.default`     | 기본 리랭킹 모델            | `cohere.rerank-v3-5:0`                            |

## 텍스트 생성

### Agent 클래스

Artisan 명령어로 Agent 클래스를 생성합니다.

```bash theme={null}
php artisan make:agent BedrockAgent
```

```php theme={null}
<?php

namespace App\Ai\Agents;

use Laravel\Ai\Contracts\Agent;
use Laravel\Ai\Promptable;

class BedrockAgent implements Agent
{
    use Promptable;

    public function instructions(): string
    {
        return '당신은 소프트웨어 개발 전문가입니다.';
    }
}
```

```php theme={null}
use App\Ai\Agents\BedrockAgent;

$response = (new BedrockAgent)->prompt('Laravel에 대해 알려주세요.');

echo $response->text;
```

### Anonymous Agent

클래스를 만들지 않고 간편하게 사용하려면 `agent()` 헬퍼를 이용합니다.

```php theme={null}
use function Laravel\Ai\agent;

$response = agent(
    instructions: '당신은 소프트웨어 개발 전문가입니다.',
)->prompt('Laravel에 대해 알려주세요.');

echo $response->text;
```

### 스트리밍

```php theme={null}
use App\Ai\Agents\BedrockAgent;
use Illuminate\Support\Facades\Route;

Route::get('/stream', function () {
    return (new BedrockAgent)->stream('Laravel에 대해 알려주세요.');
});
```

이벤트를 수동으로 다룰 수도 있습니다.

```php theme={null}
use Laravel\Ai\Streaming\Events\TextDelta;

use function Laravel\Ai\agent;

$stream = agent(
    instructions: '당신은 소프트웨어 개발 전문가입니다.',
)->stream('Laravel에 대해 알려주세요.');

foreach ($stream as $event) {
    if ($event instanceof TextDelta) {
        echo $event->delta;
    }
}
```

### 툴 사용(Function Calling)

생성 중에 호출되는 툴을 정의합니다.

```php theme={null}
use Illuminate\Contracts\JsonSchema\JsonSchema;
use Laravel\Ai\Contracts\Tool;
use Laravel\Ai\Tools\Request;

class GetWeather implements Tool
{
    public function description(): string
    {
        return '도시의 현재 날씨를 반환합니다.';
    }

    public function schema(JsonSchema $schema): array
    {
        return [
            'city' => $schema->string()->required()->description('도시명'),
        ];
    }

    public function handle(Request $request): string
    {
        // 여기서 날씨 API를 호출합니다
        return json_encode(['temperature' => 22, 'condition' => 'sunny']);
    }
}
```

Agent에서 이용합니다.

```php theme={null}
use App\Ai\Tools\GetWeather;
use Laravel\Ai\Attributes\MaxSteps;
use Laravel\Ai\Contracts\Agent;
use Laravel\Ai\Contracts\HasTools;
use Laravel\Ai\Promptable;

#[MaxSteps(5)]
class WeatherAgent implements Agent, HasTools
{
    use Promptable;

    public function tools(): array
    {
        return [new GetWeather];
    }

    public function instructions(): string
    {
        return '당신은 날씨 어시스턴트입니다.';
    }
}

$response = (new WeatherAgent)->prompt('도쿄의 날씨는?');
echo $response->text;
```

Anonymous Agent에서도 사용할 수 있습니다.

```php theme={null}
use function Laravel\Ai\agent;

$response = agent(
    instructions: '당신은 날씨 어시스턴트입니다.',
    tools: [new GetWeather],
    maxSteps: 5,
)->prompt('도쿄의 날씨는?');
```

스트리밍에서도 툴 호출은 동작합니다. SDK가 자동으로 툴을 실행하고, 최종 텍스트 응답이 나올 때까지 대화를 이어갑니다.

### 파일 첨부

`attachments` 파라미터로 이미지, 문서, 음성, 동영상 파일을 프롬프트에 첨부할 수 있습니다. Bedrock Converse API가 첨부 블록을 처리하지만, 실제로 어떤 형식을 사용할 수 있는지는 모델에 따라 다릅니다(예: Anthropic Claude는 이미지와 문서만 지원).

```php theme={null}
use Laravel\Ai\Files\Document;
use Laravel\Ai\Files\Image;

use function Laravel\Ai\agent;

// 로컬 경로의 이미지를 첨부
$response = agent(
    instructions: '당신은 유용한 어시스턴트입니다.',
)->prompt('이 이미지를 설명해 주세요.', attachments: [
    Image::fromPath('/path/to/photo.jpg'),
]);

// URL의 문서를 첨부
$response = agent(
    instructions: '당신은 유용한 어시스턴트입니다.',
)->prompt('이 문서를 요약해 주세요.', attachments: [
    Document::fromUrl('https://example.com/report.pdf'),
]);

// 문자열에서 첨부(포맷을 명시적으로 지정)
$response = agent(
    instructions: '당신은 유용한 어시스턴트입니다.',
)->prompt('이 텍스트를 분석해 주세요.', attachments: [
    Document::fromString($csvContent, 'text/csv')->as('data.csv'),
]);
```

지원되는 첨부 타입은 `Laravel\Ai\Files\*`의 `Image`, `Document`, `Audio`입니다. 동영상은 `Illuminate\Http\UploadedFile`을 통해 첨부할 수 있습니다.

<Info>
  서버 측 파일 업로드(`Document::fromPath()->put()`)나 ID를 통한 재사용(`Document::fromId()`)은 Bedrock에서 미지원입니다.
</Info>

### 대화 이력

여러 턴에 걸친 대화를 유지하려면 Agent 클래스에서 `Conversational` 인터페이스를 구현합니다. `messages()`에서 과거 대화 메시지를 반환하면 각 프롬프트에 자동으로 포함됩니다.

```php theme={null}
<?php

namespace App\Ai\Agents;

use App\Models\ChatHistory;
use Laravel\Ai\Contracts\Agent;
use Laravel\Ai\Contracts\Conversational;
use Laravel\Ai\Messages\Message;
use Laravel\Ai\Promptable;

class ChatAgent implements Agent, Conversational
{
    use Promptable;

    public function __construct(public int $userId) {}

    public function instructions(): string
    {
        return '당신은 유용한 어시스턴트입니다.';
    }

    public function messages(): iterable
    {
        return ChatHistory::where('user_id', $this->userId)
            ->latest()
            ->limit(20)
            ->get()
            ->reverse()
            ->map(fn ($m) => new Message($m->role, $m->content))
            ->all();
    }
}
```

```php theme={null}
$response = (new ChatAgent(auth()->id()))->prompt('지난번에 무슨 이야기를 하고 있었죠?');
```

#### `RemembersConversations`로 자동 저장

`messages()`를 직접 구현하고 싶지 않다면 `RemembersConversations` 트레이트로 완전 자동 대화 저장을 이용할 수 있습니다. AI SDK의 데이터베이스 테이블이 필요하므로, 먼저 `php artisan vendor:publish --provider="Laravel\Ai\AiServiceProvider" && php artisan migrate`를 실행하세요.

```php theme={null}
<?php

namespace App\Ai\Agents;

use Laravel\Ai\Concerns\RemembersConversations;
use Laravel\Ai\Contracts\Agent;
use Laravel\Ai\Contracts\Conversational;
use Laravel\Ai\Promptable;

class ChatAgent implements Agent, Conversational
{
    use Promptable, RemembersConversations;

    public function instructions(): string
    {
        return '당신은 유용한 어시스턴트입니다.';
    }
}
```

새로운 대화를 시작합니다.

```php theme={null}
$response = (new ChatAgent)->forUser($user)->prompt('안녕하세요!');

$conversationId = $response->conversationId;
```

기존 대화를 이어갑니다.

```php theme={null}
$response = (new ChatAgent)
    ->continue($conversationId, as: $user)
    ->prompt('좀 더 자세히 알려주세요.');
```

Bedrock 드라이버는 Bedrock Converse API 요청에 대화 이력을 자동으로 포함하므로, 지원하는 모든 모델에서 멀티턴 대화 컨텍스트를 활용할 수 있습니다.

### 구조화된 출력

`HasStructuredOutput` 인터페이스를 구현하면 타입이 지정된 응답을 얻을 수 있습니다.

```php theme={null}
use Illuminate\Contracts\JsonSchema\JsonSchema;
use Laravel\Ai\Contracts\Agent;
use Laravel\Ai\Contracts\HasStructuredOutput;
use Laravel\Ai\Promptable;

class ExtractPerson implements Agent, HasStructuredOutput
{
    use Promptable;

    public function instructions(): string
    {
        return '주어진 문장에서 인물 정보를 추출해 주세요.';
    }

    public function schema(JsonSchema $schema): array
    {
        return [
            'name' => $schema->string()->description('인물의 풀네임'),
            'age' => $schema->integer()->description('나이'),
            'occupation' => $schema->string()->description('직업'),
        ];
    }
}

$response = (new ExtractPerson)->prompt('John은 30세의 소프트웨어 엔지니어입니다.');

echo $response['name'];       // "John"
echo $response['age'];        // 30
echo $response['occupation']; // "software engineer"
```

Anonymous Agent에서도 구조화된 출력을 사용할 수 있습니다.

```php theme={null}
use function Laravel\Ai\agent;

$response = agent(
    instructions: '주어진 문장에서 인물 정보를 추출해 주세요.',
    schema: fn (JsonSchema $schema) => [
        'name' => $schema->string()->description('인물의 풀네임'),
        'age' => $schema->integer()->description('나이'),
    ],
)->prompt('Alice is 25 years old.');

echo $response['name']; // "Alice"
echo $response['age'];  // 25
```

내부적으로는 스키마에 맞는 값을 반환하도록 하는 합성 툴(`output_structured_data`)을 생성합니다. 이 방식은 Converse API를 통해 Bedrock의 모든 모델과 호환됩니다.

### Converse API(모든 모델)

모든 텍스트 생성과 스트리밍은 [Bedrock Converse API](https://docs.aws.amazon.com/bedrock/latest/userguide/conversation-inference.html)를 통해 실행됩니다. Anthropic Claude를 포함해 통일되어 있으며, Amazon Nova, Meta Llama, Mistral, Cohere, DeepSeek 등 Bedrock의 다양한 모델을 동일한 인터페이스로 이용할 수 있습니다.

```php theme={null}
use function Laravel\Ai\agent;

// Anthropic Claude(Converse API 경유)
$response = agent(
    instructions: '당신은 소프트웨어 개발 전문가입니다.',
    model: 'global.anthropic.claude-sonnet-4-6',
)->prompt('Laravel에 대해 알려주세요.');

// Amazon Nova
$response = agent(
    instructions: '당신은 유용한 어시스턴트입니다.',
    model: 'amazon.nova-pro-v1:0',
)->prompt('AWS에 대해 알려주세요.');

// Meta Llama
$response = agent(
    instructions: '당신은 유용한 어시스턴트입니다.',
    model: 'meta.llama3-1-70b-instruct-v1:0',
)->prompt('양자 컴퓨팅을 설명해 주세요.');

// Mistral
$response = agent(
    instructions: '당신은 유용한 어시스턴트입니다.',
    model: 'mistral.mistral-large-2402-v1:0',
)->prompt('코딩에 대한 하이쿠를 써 주세요.');

// Cohere Command R+
$response = agent(
    instructions: '당신은 유용한 어시스턴트입니다.',
    model: 'cohere.command-r-plus-v1:0',
)->prompt('이 텍스트를 요약해 주세요.');

// DeepSeek R1
$response = agent(
    instructions: '당신은 유용한 어시스턴트입니다.',
    model: 'deepseek.r1-v1:0',
)->prompt('이 수학 문제를 풀어 주세요.');
```

스트리밍, 툴 사용, 구조화된 출력, 파일 첨부는 각 기능을 지원하는 모델에서 동작합니다. 자세한 내용은 [Bedrock 지원 모델 목록](https://docs.aws.amazon.com/bedrock/latest/userguide/conversation-inference-supported-models-features.html)을 참조하세요.

### Provider Options

`anthropic_version` 등 Bedrock 고유 옵션을 전달하려면 `HasProviderOptions`를 구현합니다.

```php theme={null}
<?php

namespace App\Ai\Agents;

use Laravel\Ai\Contracts\Agent;
use Laravel\Ai\Contracts\HasProviderOptions;
use Laravel\Ai\Enums\Lab;
use Laravel\Ai\Promptable;

class BedrockAgent implements Agent, HasProviderOptions
{
    use Promptable;

    public function instructions(): string
    {
        return '당신은 소프트웨어 개발 전문가입니다.';
    }

    public function providerOptions(Lab|string $provider): array
    {
        return [
            'top_p' => 0.9,
        ];
    }
}
```

지원되는 Provider Options:

| 옵션                             | 설명                          | 기본값 |
| ------------------------------ | --------------------------- | --- |
| `top_k`                        | Top-K 샘플링 파라미터              | —   |
| `top_p`                        | Top-P(nucleus) 샘플링 파라미터     | —   |
| `additionalModelRequestFields` | Converse API의 모델 고유 추가 파라미터 | —   |

### Agent 설정 속성

PHP 속성으로 텍스트 생성 옵션을 설정할 수 있습니다.

```php theme={null}
use Laravel\Ai\Attributes\MaxTokens;
use Laravel\Ai\Attributes\Temperature;
use Laravel\Ai\Attributes\Timeout;
use Laravel\Ai\Contracts\Agent;
use Laravel\Ai\Promptable;

#[MaxTokens(4096)]
#[Temperature(0.7)]
#[Timeout(120)]
class BedrockAgent implements Agent
{
    use Promptable;

    // ...
}
```

## 이미지 생성

Stability AI 모델(기본값) 또는 Amazon Nova Canvas를 사용해 이미지를 생성합니다.

```php theme={null}
use Laravel\Ai\Image;
use Revolution\Amazon\Bedrock\Bedrock;

// 기본값으로 Stability AI Stable Image Core를 사용
$response = Image::of('귀여운 스팀펑크 로봇')->generate(provider: Bedrock::KEY);

// 첫 번째 이미지를 가져옴
$image = $response->firstImage();

// 디스크에 저장
$response->store('images', 's3');

// HTML의 <img> 태그로 출력
echo $response->toHtml('스팀펑크 로봇');
```

사용 가능한 Stability AI 모델(모두 `us-west-2` 리전이 필요):

```php theme={null}
// Stable Image Core — 고속·저비용(기본값)
$response = Image::of('풍경')
    ->generate(provider: Bedrock::KEY, model: 'stability.stable-image-core-v1:1');

// Stable Diffusion 3.5 Large — 고품질·대량 생성
$response = Image::of('포트레이트')
    ->generate(provider: Bedrock::KEY, model: 'stability.sd3-5-large-v1:0');

// Stable Image Ultra — 초현실적·최고 품질
$response = Image::of('고급스러운 제품')
    ->generate(provider: Bedrock::KEY, model: 'stability.stable-image-ultra-v1:1');
```

<Info>
  Stability AI 이미지 모델은 `us-west-2`에서만 이용 가능합니다. 이 모델들을 사용할 때는 `AWS_DEFAULT_REGION=us-west-2`를 설정하세요.
</Info>

### Stability AI를 이용한 이미지 편집

Stability AI Image Services의 편집 계열 모델도 `attachments()` 메서드로 이용할 수 있습니다. 입력 이미지를 전달하고 편집 모델로 변환합니다.

```php theme={null}
use Laravel\Ai\Files\Image as ImageFile;
use Laravel\Ai\Image;
use Revolution\Amazon\Bedrock\Bedrock;

$inputImage = ImageFile::fromPath('/path/to/photo.jpg');

// Inpaint — 마스크나 알파 채널로 영역을 다시 그림
$response = Image::of('배경을 숲으로 바꿔 주세요')
    ->attachments([$inputImage])
    ->generate(provider: Bedrock::KEY, model: 'stability.stable-image-inpaint-v1:0');

// Erase — 불필요한 요소를 제거
$response = Image::of('')
    ->attachments([$inputImage])
    ->generate(provider: Bedrock::KEY, model: 'stability.stable-image-erase-object-v1:0');

// 배경을 제거하여 피사체만 잘라내기
$response = Image::of('')
    ->attachments([$inputImage])
    ->generate(provider: Bedrock::KEY, model: 'stability.stable-image-remove-background-v1:0');

// Search and Replace — 프롬프트로 지정한 오브젝트를 교체
$response = Image::of('고양이')
    ->attachments([$inputImage])
    ->generate(provider: Bedrock::KEY, model: 'stability.stable-image-search-replace-v1:0');

// Style Transfer — 프롬프트의 스타일을 적용
$response = Image::of('유화 스타일')
    ->attachments([$inputImage])
    ->generate(provider: Bedrock::KEY, model: 'stability.stable-style-transfer-v1:0');
```

사용 가능한 Stability AI 편집 모델(모두 `us-east-1`, `us-east-2`, `us-west-2`에서 이용 가능):

| Model ID                                        | 설명                              |
| ----------------------------------------------- | ------------------------------- |
| `stability.stable-image-inpaint-v1:0`           | Inpaint — 선택 영역의 리페인트           |
| `stability.stable-outpaint-v1:0`                | Outpaint — 이미지를 경계 밖으로 확장       |
| `stability.stable-image-erase-object-v1:0`      | Erase — 오브젝트 제거                 |
| `stability.stable-image-remove-background-v1:0` | 배경 제거                           |
| `stability.stable-image-search-replace-v1:0`    | Search and Replace — 오브젝트 교체    |
| `stability.stable-image-search-recolor-v1:0`    | Search and Recolor — 오브젝트 색상 변경 |
| `stability.stable-image-style-guide-v1:0`       | Style Guide — 레퍼런스 이미지로 스타일 적용  |
| `stability.stable-style-transfer-v1:0`          | Style Transfer — 화풍 전이          |
| `stability.stable-image-control-sketch-v1:0`    | Control Sketch — 스케치에서 생성       |
| `stability.stable-image-control-structure-v1:0` | Control Structure — 구조를 따라 생성   |
| `stability.stable-creative-upscale-v1:0`        | Creative Upscale — 보완하면서 업스케일   |
| `stability.stable-conservative-upscale-v1:0`    | Conservative Upscale — 디테일 유지   |
| `stability.stable-fast-upscale-v1:0`            | Fast Upscale — 경량 4배 업스케일       |

Amazon Nova Canvas도 지원하지만, AWS에 의해 권장 중단이 진행되고 있습니다.

```php theme={null}
// Nova Canvas(권장하지 않음. us-east-1, ap-northeast-1, eu-west-1에서 이용 가능)
$response = Image::of('노을')
    ->size('3:2')           // '1:1', '3:2', '2:3'
    ->quality('high')       // 'low', 'medium', 'high'(Nova Canvas 전용)
    ->generate(provider: Bedrock::KEY, model: 'amazon.nova-canvas-v1:0');
```

## 음성(TTS)

[Amazon Polly](https://docs.aws.amazon.com/polly/latest/dg/what-is.html)를 사용해 텍스트에서 음성을 생성합니다.

```php theme={null}
use Laravel\Ai\Audio;
use Revolution\Amazon\Bedrock\Bedrock;

$response = Audio::of('Laravel로 코딩하는 것을 정말 좋아합니다.')->generate(provider: Bedrock::KEY);

$rawContent = (string) $response;
```

남성/여성 목소리를 지정할 수 있습니다.

```php theme={null}
$response = Audio::of('Laravel로 코딩하는 것을 정말 좋아합니다.')
    ->female()
    ->generate(provider: 'bedrock');

$response = Audio::of('Laravel로 코딩하는 것을 정말 좋아합니다.')
    ->male()
    ->generate(provider: Bedrock::KEY);
```

특정 [Polly 보이스](https://docs.aws.amazon.com/polly/latest/dg/voicelist.html)를 지정합니다.

```php theme={null}
$response = Audio::of('Laravel로 코딩하는 것을 정말 좋아합니다.')
    ->voice('Joanna')
    ->generate(provider: Bedrock::KEY);
```

생성된 음성을 저장합니다.

```php theme={null}
$response = Audio::of('Laravel로 코딩하는 것을 정말 좋아합니다.')->generate(provider: Bedrock::KEY);

$path = $response->store();
$path = $response->storeAs('audio.mp3');
```

엔진(모델)을 지정할 수도 있습니다.

```php theme={null}
// generative(기본값), neural, long-form, standard
$response = Audio::of('Laravel로 코딩하는 것을 정말 좋아합니다.')
    ->generate(provider: Bedrock::KEY, model: 'neural');
```

**기본 보이스:** `default-female` → Ruth, `default-male` → Matthew(둘 다 generative 엔진 지원).

<Warning>
  Amazon Polly는 Bedrock과는 별도의 AWS 서비스입니다. Bedrock API 키(bearer token)는 Polly에서 사용할 수 없습니다. AWS IAM 자격 증명(SigV4) 또는 기본 AWS 자격 증명 체인을 사용하세요.
</Warning>

## 임베딩

Amazon Titan Embeddings V2를 사용해 벡터 임베딩을 생성합니다.

```php theme={null}
use Laravel\Ai\Embeddings;
use Revolution\Amazon\Bedrock\Bedrock;

$response = Embeddings::for(['Hello world', 'Foo bar'])->generate(provider: Bedrock::KEY);

// 첫 번째 임베딩 벡터
$vector = $response->first();

// 모든 임베딩 순회
foreach ($response as $embedding) {
    // $embedding은 float 배열
}

echo $response->tokens; // 총 토큰 수
```

차원 수를 지정할 수 있습니다(Titan Embeddings V2는 256, 512, 1024).

```php theme={null}
$response = Embeddings::for(['Hello world'])->dimensions(512)->generate(provider: Bedrock::KEY);
```

커스텀 모델을 지정하는 예시.

```php theme={null}
$response = Embeddings::for(['Hello world'])
    ->dimensions(1024)
    ->generate(provider: Bedrock::KEY, model: 'amazon.titan-embed-text-v2:0');
```

### Cohere Embed 모델

Cohere Embed 모델은 자동으로 감지되며, 배치 API를 사용합니다. Titan이 입력별로 HTTP 요청을 보내는 것과 달리, Cohere는 모든 입력을 하나의 요청으로 묶기 때문에 여러 텍스트를 처리할 때 효율적입니다.

```php theme={null}
// Cohere Embed English V3
$response = Embeddings::for(['Hello world', 'Foo bar'])
    ->dimensions(1024)
    ->generate(provider: Bedrock::KEY, model: 'cohere.embed-english-v3');

// Cohere Embed Multilingual V3
$response = Embeddings::for(['Hello', '안녕하세요'])
    ->dimensions(1024)
    ->generate(provider: Bedrock::KEY, model: 'cohere.embed-multilingual-v3');

// Cohere Embed V4(출력 차원 256~1536 설정 가능)
$response = Embeddings::for(['Hello world'])
    ->dimensions(512)
    ->generate(provider: Bedrock::KEY, model: 'cohere.embed-v4');
```

<Info>
  Cohere Embed 모델은 토큰 수를 반환하지 않으므로, `$response->tokens`는 항상 `0`입니다.
</Info>

## 리랭킹

Cohere Rerank 3.5나 Amazon Rerank 1.0을 사용해 쿼리와의 관련도로 문서를 재정렬합니다.

```php theme={null}
use Laravel\Ai\Reranking;
use Revolution\Amazon\Bedrock\Bedrock;

$response = Reranking::of([
    'Laravel은 PHP의 웹 프레임워크입니다.',
    'Python은 프로그래밍 언어입니다.',
    'Laravel은 웹 개발을 위한 우아한 문법을 제공합니다.',
])->rerank(query: 'Laravel이란 무엇입니까?', provider: Bedrock::KEY);

// 가장 관련도가 높은 문서
echo $response->first()->document;
echo $response->first()->score;

// 모두 정렬 순으로 취득
foreach ($response as $result) {
    echo "{$result->index}: {$result->document} ({$result->score})\n";
}

// 건수 제한
$response = Reranking::of([...])
    ->limit(2)
    ->rerank(query: 'Laravel이란?', provider: Bedrock::KEY);
```

커스텀 모델을 지정하는 예시.

```php theme={null}
$response = Reranking::of([...])
    ->rerank(query: '검색 쿼리', provider: Bedrock::KEY, model: 'amazon.rerank-v1:0');
```

<Info>
  리랭킹 API는 `bedrock-agent-runtime` 엔드포인트를 사용합니다(`bedrock-runtime`이 아님). Amazon Rerank 1.0은 `us-east-1`에서 이용할 수 없으므로, 해당 리전에서는 Cohere Rerank 3.5를 사용하세요.
</Info>

## 테스트

AI SDK의 표준 테스트 기능을 그대로 이용할 수 있습니다.

공식 문서에는 기재되어 있지 않지만, `agent()` 헬퍼로 만든 Anonymous Agent는 `AnonymousAgent::fake()`, 구조화된 출력 버전은 `StructuredAnonymousAgent::fake()`로 모킹할 수 있습니다.

```php theme={null}
use Laravel\Ai\AnonymousAgent;
use Laravel\Ai\Prompts\AgentPrompt;

use function Laravel\Ai\agent;

it('can generate text', function () {
    AnonymousAgent::fake();

    $response = agent(
        instructions: '당신은 소프트웨어 개발 전문가입니다.',
    )->prompt('Laravel에 대해 알려주세요.');

    AnonymousAgent::assertPrompted(function (AgentPrompt $prompt) {
        return $prompt->contains('Laravel');
    });
});
```

<Info>
  최신 정보는 [GitHub 저장소](https://github.com/invokable/laravel-amazon-bedrock)를 참조하세요.
</Info>


## Related topics

- [봇 튜토리얼 - Laravel Bluesky](/ko/packages/laravel-bluesky/bot-tutorial.md)
- [Laravel 10에서 11로의 업그레이드](/ko/blog/upgrade-10-to-11.md)
- [Laravel AI SDK 연동 - VOICEVOX for Laravel](/ko/packages/laravel-voicevox/ai-sdk.md)
- [Illuminate\Support\Manager — 드라이버 시스템의 해부](/ko/advanced/manager.md)
- [Laravel Nostr](/ko/packages/laravel-nostr.md)
