들어가기전..
본게시물은 2024년 6월에 작성했습니다.
Java 11, Spring Boot3를 사용했으며, 자세한 소스는 GitHub에 올렸습니다.
AWS Bedrock FM 사용 신청
한국어를 사용할 수 있으며 토큰제한이 가장 큰(2024년 6월 기준) Cluade 3 모델을 사용해 보자.
먼저, 사용하려는 모델의 액세스를 요청해야 사용이 가능하다. 2024년 6월 기준 미국 버지니아 북부에서 가장 많은 모델을 사용할 수 있다.
원하는 모델의 권한요청을 하고 잠시 기다리면 요청한 모델의 권한이 부여된다.
이제 AWS Bedrock에서 제공업체 > 사용할 모델을 누르면 modelId 및 API 요청 가이드라인을 볼 수 있다.
AWS Bedrock Spring Boot3에서 사용하기
AWS SDK v2 for Java와 bedrock runtime을 import 한다.
implementation platform('software.amazon.awssdk:bom:2.26.3')
implementation 'software.amazon.awssdk:bedrockruntime'
AWS Bedrock client도 bean으로 등록한다.
@Configuration
public class AwsConfig {
@Bean
public BedrockRuntimeClient bedrockRuntimeClient() {
return BedrockRuntimeClient.builder()
.credentialsProvider(DefaultCredentialsProvider.create())
.region(Region.US_EAST_1)
.build();
}
}
선언한 client를 이용해 AWS Bedrock에게 converse api로 요청할 서비스를 만든다.
-> converse api 문서: https://docs.aws.amazon.com/ko_kr/bedrock/latest/APIReference/API_runtime_Converse.html
/**
* AWS Bedrock Claude3 Sonnet FM을 이용해서 AI와 채팅한다.
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class Claude3SonnetCatChatService implements AiChatService {
private final String MODEL_ID = "anthropic.claude-3-sonnet-20240229-v1:0";
private final String SYSTEM_PROMPT = "너는 고양이야 한국어로 질문하면 '낭'으로 문장을 구성해서 대답하고 다른 나라 언어로 그 언어에 맞춰서 고양이 울음소리로 문장을 구성해서 대답해";
private final BedrockRuntimeClient bedrockRuntimeClient;
@Override
public String send(String message) {
// AI에게 전할 message 생성
Message requestMessage = Message.builder()
.content(ContentBlock.fromText(message))
.role(ConversationRole.USER)
.build();
// 프롬프트
SystemContentBlock systemContentBlock = SystemContentBlock.builder()
.text(SYSTEM_PROMPT)
.build();
try {
// AI 요청을 날린다.
ConverseResponse response = bedrockRuntimeClient.converse(request -> request
.modelId(MODEL_ID)
.messages(requestMessage)
.system(systemContentBlock)
.inferenceConfig(config -> config
.maxTokens(512)
.temperature(0.5F)
.topP(0.9F)));
// 응답값을 return
return response.output().message().content().get(0).text();
} catch (SdkClientException e) {
log.error(e.toString(), e);
throw new RuntimeException(e);
}
}
}
이제 간단하게 controller를 만들어서 대화를 시작하면 AI가 답변을 준다.
? AI가 이상하게 답변한다.
FM을 사용할 때는 프롬프트를 어떻게 작성하냐에 따라 AI가 의도한 대로 작동할 수도 못 할 수 도 있다.
private final String SYSTEM_PROMPT = "너는 고양이야 한국어로 질문하면 "+
" '낭'으로 문장을 구성해서 대답하고 다른 나라 언어로 그 언어에 맞춰서 "+
"고양이 울음소리로 문장을 구성해서 대답해";
위 프롬프트를 통해 고양이 같은 사람 AI를 만들고 싶었지만. 진짜 고양이 울음소리만 하는 상황을 마주했다.
프롬프트를 수정해서 보다 정확하게 작성할 필요가 있다.
private final String SYSTEM_PROMPT = "너는 고양이고 이름은 'WoongCat'이야. " +
"모든 문장이 끝면 고양이같은 말투를 써야해 " +
"Q1: 안녕 너는 누구야? " +
"A1: 난 고양이 웅캣이다냥. 반갑다냥";
이렇게 작성하면, AI에게 역할을 부여하고 예시를 보여주어 AI의 답변을 의도한 방향으로 만들도록 할 수 있다.
이제야 말을 하는 고양이 같다. 의도한 방향으로 AI가 잘 답변하는 듯하다.
AI에게 이상한 질문을 한다면..?
AI에게 폭력적인 말을 하거나, 불법적인 행위의 질문 나아가서 AI가 의도한 기능 외 다른 기능을 수행한다면, 개발자는 이를 사전에 막아야 한다.
이를 해결하기 위해 AWS는 가드레일을 제공해 준다.
FM에 입력 출력값의 필터강도를 GUI로 쉽게 설정이 가능하다.
특정 주제에 대해 필터도 가능하다.
완성된 가드레일은 다음과 같다.
이제 이걸 서비스 코드로 녹이면 다음과 같다. 단, 가드레일 사용 시 converse API 호출은 가드레일 세팅을 미지원한다. 고로 invoke 방식으로 변환해 구현한다.
/**
* AWS Bedrock Claude3 Sonnet FM을 이용해서 AI와 채팅한다.
* With AWS Bedrock Guardrail
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class Claude3SonnetCatChatWithGuardRailService implements AiChatService {
private final String MODEL_ID = "anthropic.claude-3-sonnet-20240229-v1:0";
private final String SYSTEM_PROMPT = "너는 고양이고 이름은 'WoongCat'이야. " +
"모든 문장이 끝면 고양이같은 말투를 써야해 " +
"Q1: 안녕 너는 누구야? " +
"A1: 난 고양이 웅캣이다냥. 반갑다냥";
private final BedrockRuntimeClient bedrockRuntimeClient;
@Override
public String send(String message) {
// AI에게 전할 message 생성
String nativeRequestTemplate = """
{
"anthropic_version": "bedrock-2023-05-31",
"max_tokens": 512,
"temperature": 0.5,
"topP": 0.9,
"system": "{{system_prompt}}",
"messages": [{
"role": "user",
"content": "{{prompt}}"
}]
}""";
String nativeRequest = nativeRequestTemplate
.replace("{{prompt}}", message)
.replace("{{system_prompt}}", SYSTEM_PROMPT);
try {
// AI 요청을 날린다.
InvokeModelResponse invokeModelResponse = bedrockRuntimeClient.invokeModel(InvokeModelRequest.builder()
.modelId(MODEL_ID)
.body(SdkBytes.fromUtf8String(nativeRequest))
.guardrailIdentifier("s3bowsoa37sy")
.guardrailVersion("DRAFT")
.build());
// Decode the response body.
JSONObject responseBody = new JSONObject(invokeModelResponse.body().asUtf8String());
// 응답값을 return
return responseBody.getJSONArray("content").getJSONObject(0).getString("text");
} catch (SdkClientException e) {
log.error(e.toString(), e);
throw new RuntimeException(e);
}
}
}
이제는 의도한 대화만 하도록 필터링이 가능하다..!
참고한 자료
'인프라' 카테고리의 다른 글
EC2를 이용한 AWS ECS 기반 Spring Boot 3 DataDog 적용 (1) | 2024.10.03 |
---|---|
기본적인 AWS VPC 구성기 (0) | 2024.07.27 |
AWS SQS 256KB 이상 대용량 메시지 처리와 Spring Boot (0) | 2024.07.06 |
AWS SNS과 FCM 그리고 Spring Boot를 곁들인.. (0) | 2024.05.08 |
Linode Objects Storage 구성 및 Spring Cloud aws와 연동 (0) | 2023.07.12 |