Amazon Bedrock 통합

Amazon Bedrock 통합

LangChain4j에서 Amazon Bedrock의 모델을 쓰는 방법을 다룰게요. AWS 계정이 있다면 BedrockChatModel로 대화형, BedrockStreamingChatModel로 스트리밍 모델을 만들 수 있고, thinking·프롬프트 캐싱처럼 AWS 고유의 기능도 파라미터 하나로 켤 수 있어요.

출처: 공식문서

Maven 의존성

<dependency>
    <groupId>dev.langchain4j</groupId>
    <artifactId>langchain4j-bedrock</artifactId>
    <version>1.20.0</version>
</dependency>

AWS 자격 증명 (credentials)

Amazon Bedrock 모델을 쓰려면 AWS 자격 증명을 구성해야 해요. 한 가지 방법은 AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEY 환경변수를 설정하는 거예요. 자세한 내용은 여기에서 볼 수 있어요. 또는 로컬에서 API 키 인증을 위해 AWS_BEARER_TOKEN_BEDROCK 환경변수를 설정할 수도 있어요. API 키에 대한 추가 내용은 문서를 참고하세요.

BedrockChatModel

:::note 현재 구현은 Guardrails를 지원하지 않아요. :::

지원 모델과 그 기능은 여기에서, 모델 id는 여기에서 찾을 수 있어요.

구성

ChatModel model = BedrockChatModel.builder()
        .client(BedrockRuntimeClient)
        .region(...)
        .modelId("us.amazon.nova-lite-v1:0")
        .returnThinking(...)
        .sendThinking(...)
        .timeout(...)
        .maxRetries(...)
        .logRequests(...)
        .logResponses(...)
        .listeners(...)
        .defaultRequestParameters(BedrockChatRequestParameters.builder()
                .modelName(...)
                .temperature(...)
                .topP(...)
                .maxOutputTokens(...)
                .stopSequences(...)
                .toolSpecifications(...)
                .toolChoice(...)
                .additionalModelRequestFields(...)
                .additionalModelRequestField(...)
                .enableReasoning(...)
                .promptCaching(...)
                .requestMetadata(Map.of("team", "platform"))
                .build())
        .build();

예시

BedrockStreamingChatModel

:::note 현재 구현은 Guardrails를 지원하지 않아요. :::

지원 모델과 그 기능은 여기에서, 모델 id는 여기에서 찾을 수 있어요.

구성

StreamingChatModel model = BedrockStreamingChatModel.builder()
        .client(BedrockRuntimeAsyncClient)
        .region(...)
        .modelId("us.amazon.nova-lite-v1:0")
        .returnThinking(...)
        .sendThinking(...)
        .timeout(...)
        .logRequests(...)
        .logResponses(...)
        .listeners(...)
        .defaultRequestParameters(BedrockChatRequestParameters.builder()
                .modelName(...)
                .temperature(...)
                .topP(...)
                .maxOutputTokens(...)
                .stopSequences(...)
                .toolSpecifications(...)
                .toolChoice(...)
                .additionalModelRequestFields(...)
                .additionalModelRequestField(...)
                .enableReasoning(...)
                .promptCaching(...)
                .requestMetadata(Map.of("team", "platform"))
                .build())
        .build();

예시

추가 모델 요청 필드 (Additional Model Request Fields)

BedrockChatRequestParametersadditionalModelRequestFields 필드는 Map<String, Object> 타입이에요. 여기에 설명된 것처럼, 공통 InferenceConfiguration으로 커버되지 않는 특정 모델 전용 추론 파라미터를 추가할 수 있게 해줘요.

요청 메타데이터 (Request Metadata)

BedrockChatRequestParametersrequestMetadata로 Converse와 ConverseStream 요청에 키-값 쌍을 추가할 수 있어요. 이 메타데이터는 Amazon Bedrock 모델 호출 로그를 필터링하는 데 쓸 수 있어요. 모델의 기본 요청 파라미터로 구성하거나 개별 요청으로 제공할 수 있어요.

BedrockChatRequestParameters parameters = BedrockChatRequestParameters.builder()
        .requestMetadata(Map.of("team", "platform"))
        .build();

요청 메타데이터에는 개인 식별 정보, 자격 증명, 기타 민감한 데이터를 넣지 마세요. 자세한 내용은 Per-request metadata tagging을 참고하세요.

Thinking / Reasoning

Claude thinking 프로세스를 켜려면 BedrockChatRequestParameters에서 enableReasoning을 호출하고 모델을 만들 때 defaultRequestParameters로 설정해요:

BedrockChatRequestParameters parameters = BedrockChatRequestParameters.builder()
        .enableReasoning(1024) // token budget
        .build();

ChatModel model = BedrockChatModel.builder()
        .modelId("us.anthropic.claude-sonnet-4-20250514-v1:0")
        .defaultRequestParameters(parameters)
        .returnThinking(true)
        .sendThinking(true)
        .build();

다음 파라미터도 thinking 동작을 제어해요:

  • returnThinking — thinking(있다면)을 AiMessage.thinking()에 반환할지, 그리고 BedrockStreamingChatModel을 쓸 때 StreamingChatResponseHandler.onPartialThinking()TokenStream.onPartialThinking() 콜백을 호출할지 제어해요. 기본 비활성. 켜면 thinking 시그니처도 AiMessage.attributes()에 저장돼 반환돼요.
  • sendThinkingAiMessage에 저장된 thinking과 시그니처를 후속 요청에서 LLM에 보낼지 제어해요. 기본 활성.

프롬프트 캐싱 (Prompt Caching)

AWS Bedrock은 비슷한 프롬프트로 반복 API 호출을 할 때 성능을 높이고 비용을 줄이는 프롬프트 캐싱을 지원해요. 이 기능은 캐시된 콘텐츠에 대해 지연 시간을 최대 85%, 비용을 최대 90% 줄일 수 있어요.

동작 원리

프롬프트 캐싱을 쓰면 대화에서 특정 지점을 캐시 대상으로 표시할 수 있어요. 같은 캐시된 콘텐츠로 이후 API 호출을 하면 Bedrock이 캐시된 부분을 재사용해 처리 시간과 비용을 크게 줄여줘요. 캐시 TTL은 5분이고, 캐시 히트가 있을 때마다 리셋돼요.

지원 모델

프롬프트 캐싱은 다음 모델에서 지원돼요:

  • Claude Opus 4.5
  • Claude Opus 4.1
  • Claude Opus 4
  • Claude Sonnet 4.5
  • Claude Haiku 4.5
  • Claude Sonnet 4
  • Claude 3.7 Sonnet
  • Claude 3.5 Sonnet
  • Claude 3.5 Haiku
  • Amazon Nova models

구성

프롬프트 캐싱을 켜려면 BedrockChatRequestParameterspromptCaching() 메서드를 사용해요:

import dev.langchain4j.model.bedrock.BedrockChatRequestParameters;
import dev.langchain4j.model.bedrock.BedrockCachePointPlacement;

BedrockChatRequestParameters params = BedrockChatRequestParameters.builder()
        .promptCaching(BedrockCachePointPlacement.AFTER_SYSTEM)
        .temperature(0.7)
        .maxOutputTokens(500)
        .build();

ChatModel model = BedrockChatModel.builder()
        .modelId("us.amazon.nova-micro-v1:0")
        .region(Region.US_EAST_1)
        .defaultRequestParameters(params)
        .build();

캐시 지점 배치 옵션 (Cache Point Placement Options)

BedrockCachePointPlacement enum은 대화에서 캐시 지점을 어디 둘지 세 가지 옵션을 제공해요.

  • AFTER_SYSTEM — 시스템 메시지 뒤에 캐시 지점을 둬요. 여러 대화에서 재사용하고 싶은 일관된 시스템 프롬프트가 있을 때 이상적이에요.
  • AFTER_USER_MESSAGE — 사용자 메시지 뒤에 캐시 지점을 둬요. 표준 사용자 프롬프트나 컨텍스트가 같을 때 유용해요.
  • AFTER_TOOLS — 툴 정의 뒤에 캐시 지점을 둬요. 캐시하고 싶은 일관된 툴 집합이 있을 때 유용해요.

예시

시스템 메시지 캐싱 기본 사용

// Configure prompt caching to cache after system message
BedrockChatRequestParameters params = BedrockChatRequestParameters.builder()
        .promptCaching(BedrockCachePointPlacement.AFTER_SYSTEM)
        .build();

ChatModel model = BedrockChatModel.builder()
        .modelId("us.anthropic.claude-sonnet-4-6")
        .defaultRequestParameters(params)
        .build();

// First request - establishes the cache
ChatRequest request1 = ChatRequest.builder()
        .messages(Arrays.asList(
                SystemMessage.from("You are a helpful coding assistant with expertise in Java."),
                UserMessage.from("What is dependency injection?")
        ))
        .build();

ChatResponse response1 = model.chat(request1);

// Second request - benefits from cached system message
ChatRequest request2 = ChatRequest.builder()
        .messages(Arrays.asList(
                SystemMessage.from("You are a helpful coding assistant with expertise in Java."),
                UserMessage.from("What is the singleton pattern?")
        ))
        .build();

ChatResponse response2 = model.chat(request2); // Faster response due to caching

다른 기능과 결합

프롬프트 캐싱은 reasoning 같은 다른 Bedrock 기능과 결합할 수 있어요:

BedrockChatRequestParameters params = BedrockChatRequestParameters.builder()
        .promptCaching(BedrockCachePointPlacement.AFTER_SYSTEM)
        .enableReasoning(1000)  // Enable reasoning with 1000 token budget
        .temperature(0.3)
        .maxOutputTokens(2000)
        .build();

ChatModel model = BedrockChatModel.builder()
        .modelId("us.anthropic.claude-sonnet-4-6")
        .defaultRequestParameters(params)
        .build();

모범 사례

  1. 안정적인 콘텐츠 캐시하기 — 시스템 프롬프트, 툴 정의, 공통 컨텍스트처럼 자주 변하지 않는 콘텐츠에 캐싱을 쓰세요.
  2. 적절한 배치 고르기:
    • 시스템 프롬프트가 대화 전반에 걸쳐 일관되면 AFTER_SYSTEM
    • 툴 정의 집합이 안정적이면 AFTER_TOOLS
    • 반복되는 사용자 컨텍스트 시나리오에선 AFTER_USER_MESSAGE
  3. 캐시 히트 모니터링 — 5분 TTL은 캐시 히트마다 리셋되므로, 같은 캐시된 콘텐츠로 요청이 잦으면 캐시가 유지돼요.
  4. 비용 최적화 — 반복 사용되는 긴 시스템 프롬프트나 툴 정의에 캐싱이 특히 유용해요.

추가 자료

더 알아보기