Gerenciando Aplicativo Java com IA Usando API Management
June 22, 2023
Neste artigo, vamos explorar como integrar a API do ChatGPT da OpenAI com uma aplicação Spring Boot e gerenciar as APIs usando o Apache APISIX, um gateway de API de código aberto. Essa integração nos permitirá aproveitar o poder do ChatGPT, um modelo de linguagem de última geração desenvolvido pela OpenAI, em nossa aplicação Spring Boot, enquanto o APISIX fornecerá uma maneira robusta, escalável e segura de gerenciar as APIs.
APIs do ChatGPT da OpenAI
A API do ChatGPT da OpenAI é uma ferramenta poderosa que podemos usar para integrar as capacidades do modelo ChatGPT em nossas próprias aplicações ou serviços. A API nos permite enviar uma série de mensagens e receber uma mensagem gerada pelo modelo de IA em resposta via REST. Ela oferece várias APIs para criar respostas de texto em um chatbot, completar código, gerar imagens ou responder perguntas em uma interface conversacional. Neste tutorial, usaremos a API de conclusão de chat para gerar respostas a um prompt (basicamente podemos perguntar qualquer coisa). Antes de começar o tutorial, você pode explorar a API para entender como autenticar na API usando chaves de API, como são os parâmetros de solicitação e a resposta da API.
Um exemplo de solicitação cURL para a API de conclusão de chat seria assim. Você substitui OPENAI_API_KEY
pela sua própria chave de API e a coloca no cabeçalho Authorization ao chamar a API.
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?"}]
}'
Aqui está um exemplo de resposta 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 é um gateway de API dinâmico, em tempo real e de alto desempenho projetado para facilitar o gerenciamento e o roteamento de microsserviços e APIs. Ele fornece recursos como balanceamento de carga, limitação de taxa, autenticação, autorização e controle de tráfego, todos os quais ajudam a simplificar o gerenciamento de microsserviços e APIs. O Apache APISIX é construído sobre o servidor Nginx e pode suportar altos níveis de tráfego com baixa latência e alta disponibilidade. Ele é de código aberto e lançado sob a licença Apache 2.0."
},
"finish_reason": "stop",
"index": 0
}
]
}
Exemplo de código do projeto
O tutorial consiste em duas partes. A primeira parte cobre a configuração da aplicação Spring Boot e a criação de um novo endpoint de API que pode lidar com nossas chamadas de API para a API de conclusão de chat de forma programática. Na segunda parte, introduziremos recursos do APISIX, como segurança e controle de tráfego, para a API Spring Boot. Os exemplos de código completos para este tutorial estão disponíveis no repositório GitHub chamado apisix-java-chatgpt-openaiapi.
Pré-requisitos
Antes de começarmos, certifique-se de ter o seguinte:
- Crie uma Chave de API da OpenAI: Para acessar a API da OpenAI, você precisará criar uma Chave de API. Você pode fazer isso fazendo login no site da OpenAI e navegando até a página de gerenciamento de Chaves de API.
- Docker instalado em sua máquina para executar o APISIX e o Spring Boot.
Passo 1: Configurando sua aplicação Spring Boot
Primeiro, precisamos configurar uma nova aplicação Spring Boot. Você pode usar o Spring Initializr para gerar um novo projeto Maven com as dependências necessárias. Para este tutorial, precisaremos da dependência Spring Boot Starter Web. Para integrar a API do ChatGPT, usaremos o cliente Java da OpenAI. Existe uma biblioteca da comunidade de código aberto chamada https://github.com/TheoKanning/openai-java. Ela fornece classes de serviço que criam e chamam o cliente das APIs GPT da OpenAI em Java. Claro, você também pode escrever sua própria implementação no Spring que interaja com as APIs da OpenAI. Veja outras bibliotecas de clientes para diferentes linguagens de programação.
<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>
Passo 2: Criar uma classe Controller
Na classe ChatCompletionController.java, você pode usar o serviço da OpenAI para enviar uma solicitação à API do ChatGPT.
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();
}
}
O endpoint da API de chat /ai-chat
lida com solicitações POST, cria uma solicitação de chat e a envia para a API da OpenAI. Em seguida, retorna a primeira mensagem da resposta da API.
Passo 3: Definir propriedades da aplicação
Em seguida, fornecemos as propriedades para a API, como model
e chave de API
, no arquivo application.properties:
openai.model=gpt-3.5-turbo
openai.api.key=SUA_CHAVE_DE_API_DA_OPENAI
Passo 4: Executar a aplicação Spring Boot
Agora podemos executar o Application.java e testá-lo com o Postman ou o comando cURL.
Como podemos ver, a aplicação gerou uma resposta à nossa pergunta no corpo da solicitação do prompt.
Passo 5: Criar um Dockerfile
Usamos um contêiner Docker para empacotar nossa aplicação Spring Boot e usá-lo junto com outros contêineres do APISIX no docker-compose.yml. Para isso, podemos criar um Dockerfile para construir um JAR e executá-lo. Veja como dockerizar uma aplicação Spring Boot no tutorial. Em seguida, registre o serviço no arquivo yaml do docker compose.
openaiapi:
build: openaiapi
ports:
- "8080:8080"
networks:
apisix:
Passo 6: Configurando o Apache APISIX
Para configurar o APISIX, podemos simplesmente executar o comando docker compose up
. Porque já definimos todos os serviços necessários no docker-compose.yml. Este arquivo define apenas 2 contêineres, um para o APISIX e outro para a aplicação Spring Boot que implementamos nas etapas anteriores. Neste projeto de exemplo, executamos o APISIX no modo standalone. Existem outras opções de instalação e modos de implantação do APISIX também. Agora o APISIX como um serviço separado está sendo executado em localhost:9080
e a aplicação Spring Boot em localhost:8080
.
Passo 7: Protegendo a API com o APISIX
Uma vez que o APISIX estiver configurado, podemos adicionar recursos de segurança à nossa API Spring Boot existente /ai-chat
para que apenas consumidores de API permitidos possam acessar essa API. O APISIX fornece vários plugins para proteger suas APIs. Por exemplo, você pode usar o plugin jwt-auth para exigir um token JWT para todas as solicitações. Aqui está um exemplo de como adicionar uma rota com um upstream e plugins usando o arquivo 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
Depois de especificarmos os upstreams, rotas e objetos de consumidor e regras de roteamento na configuração do APISIX, o arquivo de configuração é carregado na memória imediatamente após o início do serviço do nó APISIX no Docker. O APISIX tenta detectar periodicamente se o conteúdo do arquivo foi atualizado, se houver uma atualização, ele recarrega automaticamente as alterações.
Com essa configuração, adicionamos um upstream, duas rotas e um objeto de consumidor. Na primeira rota, todas as solicitações para /ask-me-anything
(que é um caminho URI personalizado, você pode definir qualquer URI lá) devem incluir o Authorization: JWT_TOKEN
no cabeçalho. Em seguida, o APISIX reescreve o caminho URI personalizado para a API real /ai-chat
automaticamente com a ajuda do plugin proxy-rewrite e encaminha as solicitações para a aplicação Spring Boot em execução em localhost:8080
.
Se você tentar solicitar a rota do APISIX, ele rejeitará nossas solicitações retornando um erro de autorização:
curl -i http://localhost:9080/ask-me-anything -X POST -d '
{
"prompt":"What is Apache APISIX?"
}'
O resultado da solicitação acima:
HTTP/1.1 401 Unauthorized
{"message":"Missing JWT token in request"}
Na segunda configuração de rota, habilitamos o plugin public-api para expor um novo endpoint /login
para assinar novos tokens JWT. Porque o APISIX pode atuar como um provedor de identidade para gerar e validar um novo token do consumidor de API ou aplicativos cliente. Veja o Passo 8, como solicitamos um novo token para nosso consumidor de API.
- uri: /login
plugins:
public-api:
uri: /apisix/plugin/jwt/sign
Se você notou no mesmo arquivo de configuração, registramos um consumidor de API para usar a API /ask-me-anything
alimentada por IA e nossos usuários podem solicitar o APISIX usando seu segredo para gerar um token JWT para acessar a API:
consumers:
- username: appsmithuser
plugins:
jwt-auth:
key: appsmithuser@gmail.com
secret: my-secret-key
Passo 8: Solicitar um novo token JWT
Agora podemos solicitar um novo token JWT para nosso consumidor de API existente com a chave:
curl -i http://127.0.0.1:9080/login?key=user-key -i
Receberemos o novo token como uma resposta do APISIX:
Server: APISIX/3.0.0
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJrZXkiOiJ1c2VyLWtleSIsImV4cCI6MTY4NjU5MjE0NH0.4Kn9c2DBYKthyUx824Ah97-z0Eu2Ul9WGO2WB3IfURA
Passo 9: Solicitar a API com o token JWT
Finalmente, podemos enviar uma solicitação para a API /ask-me-anything
com o token JWT no cabeçalho que obtivemos na etapa anterior.
curl -i http://localhost:9080/ask-me-anything -H 'Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJrZXkiOiJ1c2VyLWtleSIsImV4cCI6MTY4NjU5Mjk4N30.lhom9db3XMkcVd86ScpM6s4eP1_YzR-tfmXPckszsYo' -X POST -d '
{
"prompt":"What is Apache APISIX?"
}'
Ou usando o Postman, obteremos a resposta da IA, mas desta vez a resposta vem através do Gateway APISIX:
Conclusão
Neste tutorial, exploramos a API do ChatGPT da OpenAI para gerar respostas a prompts. Criamos uma aplicação Spring Boot que chama a API para gerar respostas a prompts. Em seguida, você pode introduzir recursos adicionais à sua integração atualizando o arquivo apisix.yml existente. Além disso, você pode verificar o branch chamado with-frontend e executar o projeto para ver a interface de usuário construída usando Appsmith que funciona com o APISIX.