API 관리를 통해 AI 기반 Java 애플리케이션 관리하기
June 22, 2023
이 글에서는 OpenAI의 ChatGPT API를 Spring Boot 애플리케이션과 통합하고, 오픈소스 API 게이트웨이인 Apache APISIX를 사용하여 API를 관리하는 방법을 탐구해 보겠습니다. 이 통합을 통해 우리는 OpenAI에서 개발한 최신 언어 모델인 ChatGPT의 힘을 Spring Boot 애플리케이션에서 활용할 수 있으며, APISIX는 API를 관리하는 강력하고 확장 가능하며 안전한 방법을 제공할 것입니다.
OpenAI ChatGPT API
OpenAI의 ChatGPT API는 우리가 ChatGPT 모델의 기능을 우리 자신의 애플리케이션이나 서비스에 통합할 수 있는 강력한 도구입니다. 이 API를 통해 우리는 일련의 메시지를 보내고 AI 모델이 생성한 응답 메시지를 REST를 통해 받을 수 있습니다. 이 API는 챗봇에서 텍스트 응답 생성, 코드 완성, 이미지 생성, 또는 대화형 인터페이스에서 질문에 답변하는 등 다양한 기능을 제공합니다. 이 튜토리얼에서는 채팅 완성 API를 사용하여 프롬프트에 대한 응답을 생성할 것입니다(기본적으로 무엇이든 질문할 수 있습니다). 튜토리얼을 시작하기 전에 API 키를 사용하여 API에 인증하는 방법, API 요청 매개변수 및 응답이 어떻게 보이는지 이해하기 위해 API를 탐색해 볼 수 있습니다.
채팅 완성 API에 대한 샘플 cURL 요청은 다음과 같습니다. OPENAI_API_KEY
를 자신의 API 키로 대체하고 API를 호출할 때 Authorization 헤더에 넣어야 합니다.
curl https://api.openai.com/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-d '{
"model": "gpt-3.5-turbo",
"messages": [{"role": "user", "content": "What is Apache APISIX?"}]
}'
다음은 샘플 JSON 응답입니다:
{
"id": "chatcmpl-7PtycrYOTJGv4jw8FQPD7LCCw0tOE",
"object": "chat.completion",
"created": 1686407730,
"model": "gpt-3.5-turbo-0301",
"usage": {
"prompt_tokens": 15,
"completion_tokens": 104,
"total_tokens": 119
},
"choices": [
{
"message": {
"role": "assistant",
"content": "Apache APISIX는 마이크로서비스와 API의 관리 및 라우팅을 용이하게 하기 위해 설계된 동적, 실시간, 고성능 API 게이트웨이입니다. 로드 밸런싱, 속도 제한, 인증, 권한 부여 및 트래픽 제어와 같은 기능을 제공하여 마이크로서비스와 API의 관리를 단순화합니다. Apache APISIX는 Nginx 서버 위에 구축되었으며 낮은 지연 시간과 높은 가용성으로 높은 수준의 트래픽을 지원할 수 있습니다. 이는 오픈 소스이며 Apache 2.0 라이선스로 배포됩니다."
},
"finish_reason": "stop",
"index": 0
}
]
}
프로젝트 코드 예제
이 튜토리얼은 두 부분으로 구성됩니다. 첫 번째 부분은 Spring Boot 애플리케이션을 설정하고 채팅 완성 API에 대한 API 호출을 프로그래밍 방식으로 처리할 수 있는 새로운 API 엔드포인트를 생성하는 것입니다. 두 번째 부분에서는 APISIX의 보안 및 트래픽 제어와 같은 기능을 Spring Boot API에 도입할 것입니다. 이 튜토리얼의 전체 코드 예제는 apisix-java-chatgpt-openaiapi라는 GitHub 저장소에서 확인할 수 있습니다.
사전 요구 사항
시작하기 전에 다음 사항을 확인하세요:
- OpenAI API 키 생성: OpenAI API에 접근하려면 API 키를 생성해야 합니다. OpenAI 웹사이트에 로그인하여 API 키 관리 페이지로 이동하여 생성할 수 있습니다.
- Docker가 머신에 설치되어 있어야 합니다. APISIX와 Spring Boot를 실행하기 위해 필요합니다.
1단계: Spring Boot 애플리케이션 설정
먼저, 새로운 Spring Boot 애플리케이션을 설정해야 합니다. Spring Initializr를 사용하여 필요한 종속성을 포함한 새로운 Maven 프로젝트를 생성할 수 있습니다. 이 튜토리얼에서는 Spring Boot Starter Web 종속성이 필요합니다. ChatGPT API를 통합하기 위해 OpenAI Java 클라이언트를 사용할 것입니다. https://github.com/TheoKanning/openai-java라는 오픈소스 커뮤니티 라이브러리가 있습니다. 이 라이브러리는 Java에서 OpenAI의 GPT API 클라이언트를 생성하고 호출하는 서비스 클래스를 제공합니다. 물론, OpenAI API와 상호 작용하는 Spring에서 자신만의 구현을 작성할 수도 있습니다. 다른 프로그래밍 언어에 대한 클라이언트 라이브러리도 확인해 보세요.
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.theokanning.openai-gpt3-java</groupId>
<artifactId>service</artifactId>
<version>0.12.0</version>
</dependency>
</dependencies>
2단계: 컨트롤러 클래스 생성
ChatCompletionController.java 클래스에서 OpenAI 서비스를 사용하여 ChatGPT API에 요청을 보낼 수 있습니다.
import com.theokanning.openai.completion.chat.ChatCompletionChoice;
import com.theokanning.openai.completion.chat.ChatCompletionRequest;
import com.theokanning.openai.completion.chat.ChatMessage;
import com.theokanning.openai.completion.chat.ChatMessageRole;
import com.theokanning.openai.service.OpenAiService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
@RestController
public class ChatCompletionController {
@Value("${openai.model}")
private String model;
@Value("${openai.api.key}")
private String openaiApiKey;
@PostMapping("/ai-chat")
public String chat(@RequestBody String prompt) {
OpenAiService service = new OpenAiService(openaiApiKey);
final List<ChatMessage> messages = new ArrayList<>();
final ChatMessage systemMessage = new ChatMessage(
ChatMessageRole.USER.value(), prompt);
messages.add(systemMessage);
ChatCompletionRequest chatCompletionRequest = ChatCompletionRequest
.builder()
.model(model)
.messages(messages)
.maxTokens(250)
.build();
List<ChatCompletionChoice> choices = service
.createChatCompletion(chatCompletionRequest).getChoices();
if (choices == null || choices.isEmpty()) {
return "No response";
}
return choices.get(0).getMessage().getContent();
}
}
/ai-chat
채팅 API 엔드포인트는 POST 요청을 처리하고, 채팅 요청을 생성하여 OpenAI API로 보낸 다음, API 응답의 첫 번째 메시지를 반환합니다.
3단계: 애플리케이션 속성 정의
다음으로, model
및 API 키
와 같은 API 속성을 application.properties 파일에 제공합니다:
openai.model=gpt-3.5-turbo
openai.api.key=YOUR_OPENAI_API_TOKEN
4단계: Spring Boot 앱 실행
이제 Application.java를 실행하고 Postman 또는 cURL 명령으로 테스트할 수 있습니다.
보시다시피, 애플리케이션은 프롬프트 요청 본문의 질문에 대한 응답을 생성했습니다.
5단계: Dockerfile 생성
Spring Boot 애플리케이션을 래핑하고 docker-compose.yml에서 다른 APISIX 컨테이너와 함께 사용하기 위해 Docker 컨테이너를 사용합니다. 이를 위해 JAR을 빌드하고 실행할 Dockerfile을 생성할 수 있습니다. Spring Boot 앱 도커라이징 튜토리얼을 참조하세요. 그런 다음, docker compose yaml 파일에 서비스를 등록합니다.
openaiapi:
build: openaiapi
ports:
- "8080:8080"
networks:
apisix:
6단계: Apache APISIX 설정
APISIX를 설정하려면 docker compose up
명령을 실행하면 됩니다. 이미 docker-compose.yml에 필요한 모든 서비스를 정의했기 때문입니다. 이 파일은 APISIX용 컨테이너 하나와 이전 단계에서 구현한 Spring Boot 애플리케이션용 컨테이너 하나만 정의합니다. 이 샘플 프로젝트에서는 APISIX를 독립 실행 모드로 실행합니다. APISIX의 다른 설치 옵션 및 배포 모드도 있습니다. 이제 APISIX는 별도의 서비스로 localhost:9080
에서 실행되고, Spring Boot 앱은 **localhost:8080
**에서 실행됩니다.
7단계: APISIX로 API 보안 설정
APISIX가 설정되면, 기존 Spring Boot API /ai-chat
에 보안 기능을 추가하여 허용된 API 소비자만 이 API에 접근할 수 있도록 할 수 있습니다. APISIX는 API를 보호하기 위해 여러 플러그인을 제공합니다. 예를 들어, jwt-auth 플러그인을 사용하여 모든 요청에 JWT 토큰을 요구할 수 있습니다. 다음은 apisix.yml
파일을 사용하여 업스트림과 플러그인을 추가하는 예제입니다:
upstreams:
- id: 1
type: roundrobin
nodes:
"openaiapi:8080": 1
routes:
- uri: /ask-me-anything
upstream_id: 1
plugins:
proxy-rewrite:
uri: /ai-chat
jwt-auth: {}
- uri: /login
plugins:
public-api:
uri: /apisix/plugin/jwt/sign
consumers:
- username: appsmithuser
plugins:
jwt-auth:
key: appsmithuser@gmail.com
secret: my-secret-key
업스트림, 라우트, 소비자 객체 및 라우팅 규칙을 APISIX 구성에 지정한 후, 구성 파일은 Docker에서 APISIX 노드 서비스가 시작된 후 즉시 메모리에 로드됩니다. Apisix는 파일 내용이 업데이트되었는지 주기적으로 감지하고, 업데이트가 있으면 자동으로 변경 사항을 다시 로드합니다.
이 구성에서 하나의 업스트림, 두 개의 라우트 및 하나의 소비자 객체를 추가했습니다. 첫 번째 라우트에서 /ask-me-anything
(사용자 정의 URI 경로, 여기에 어떤 URI든 정의할 수 있음)에 대한 모든 요청은 헤더에 Authorization: JWT_TOKEN
을 포함해야 합니다. 그런 다음, APISIX는 proxy-rewrite 플러그인의 도움으로 사용자 정의 URI 경로를 실제 API /ai-chat
로 자동으로 재작성하고 localhost:8080
에서 실행 중인 Spring Boot 애플리케이션으로 요청을 전달합니다.
APISIX 라우트에 요청을 시도하면, 권한 오류를 반환하여 요청을 거부할 것입니다:
curl -i http://localhost:9080/ask-me-anything -X POST -d '
{
"prompt":"What is Apache APISIX?"
}'
위 요청의 결과:
HTTP/1.1 401 Unauthorized
{"message":"Missing JWT token in request"}
두 번째 라우트 구성에서 public-api 플러그인을 활성화하여 새로운 엔드포인트 /login
을 노출하여 새로운 JWT 토큰을 서명할 수 있도록 했습니다. APISIX는 API 소비자 또는 클라이언트 앱에서 새로운 토큰을 생성하고 검증할 수 있는 ID 공급자 역할을 할 수 있습니다. 8단계에서 API 소비자를 위한 새로운 토큰을 요청하는 방법을 확인하세요.
- uri: /login
plugins:
public-api:
uri: /apisix/plugin/jwt/sign
동일한 구성 파일에서, /ask-me-anything
AI 기반 API를 사용하기 위해 API 소비자를 등록했으며, 사용자는 자신의 비밀을 사용하여 APISIX를 통해 JWT 토큰을 생성하여 API에 접근할 수 있습니다:
consumers:
- username: appsmithuser
plugins:
jwt-auth:
key: appsmithuser@gmail.com
secret: my-secret-key
8단계: 새로운 JWT 토큰 요청
이제 기존 API 소비자를 위한 새로운 JWT 토큰을 키로 요청할 수 있습니다:
curl -i http://127.0.0.1:9080/login?key=user-key -i
APISIX로부터 새로운 토큰을 응답으로 받을 것입니다:
Server: APISIX/3.0.0
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJrZXkiOiJ1c2VyLWtleSIsImV4cCI6MTY4NjU5MjE0NH0.4Kn9c2DBYKthyUx824Ah97-z0Eu2Ul9WGO2WB3IfURA
9단계: JWT 토큰으로 API 요청
마지막으로, 이전 단계에서 얻은 JWT 토큰을 헤더에 포함하여 API /ask-me-anything
에 요청을 보낼 수 있습니다.
curl -i http://localhost:9080/ask-me-anything -H 'Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJrZXkiOiJ1c2VyLWtleSIsImV4cCI6MTY4NjU5Mjk4N30.lhom9db3XMkcVd86ScpM6s4eP1_YzR-tfmXPckszsYo' -X POST -d '
{
"prompt":"What is Apache APISIX?"
}'
또는 Postman을 사용하여 AI 응답을 얻을 수 있지만, 이번에는 APISIX 게이트웨이를 통해 응답이 전달됩니다:
결론
이 튜토리얼에서는 OpenAI ChatGPT API를 사용하여 프롬프트에 대한 응답을 생성하는 방법을 탐구했습니다. 프롬프트에 대한 응답을 생성하기 위해 API를 호출하는 Spring Boot 애플리케이션을 생성했습니다. 다음으로, 기존 apisix.yml 파일을 업데이트하여 추가 기능을 통합에 도입할 수 있습니다. 또한, with-frontend라는 브랜치를 확인하고 프로젝트를 실행하여 APISIX와 함께 작동하는 Appsmith를 사용하여 구축된 UI 인터페이스를 확인할 수 있습니다.