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_ID와 AWS_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)
BedrockChatRequestParameters의 additionalModelRequestFields 필드는 Map<String, Object> 타입이에요. 여기에 설명된 것처럼, 공통 InferenceConfiguration으로 커버되지 않는 특정 모델 전용 추론 파라미터를 추가할 수 있게 해줘요.
요청 메타데이터 (Request Metadata)
BedrockChatRequestParameters의 requestMetadata로 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()에 저장돼 반환돼요.sendThinking—AiMessage에 저장된 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
구성
프롬프트 캐싱을 켜려면 BedrockChatRequestParameters의 promptCaching() 메서드를 사용해요:
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();
모범 사례
- 안정적인 콘텐츠 캐시하기 — 시스템 프롬프트, 툴 정의, 공통 컨텍스트처럼 자주 변하지 않는 콘텐츠에 캐싱을 쓰세요.
- 적절한 배치 고르기:
- 시스템 프롬프트가 대화 전반에 걸쳐 일관되면
AFTER_SYSTEM - 툴 정의 집합이 안정적이면
AFTER_TOOLS - 반복되는 사용자 컨텍스트 시나리오에선
AFTER_USER_MESSAGE
- 시스템 프롬프트가 대화 전반에 걸쳐 일관되면
- 캐시 히트 모니터링 — 5분 TTL은 캐시 히트마다 리셋되므로, 같은 캐시된 콘텐츠로 요청이 잦으면 캐시가 유지돼요.
- 비용 최적화 — 반복 사용되는 긴 시스템 프롬프트나 툴 정의에 캐싱이 특히 유용해요.