Gestión de una Aplicación Java con Inteligencia Artificial mediante API Management
June 22, 2023
En este artículo, exploraremos cómo integrar la API de ChatGPT de OpenAI con una aplicación de Spring Boot y gestionar las APIs utilizando Apache APISIX, un gateway de API de código abierto. Esta integración nos permitirá aprovechar el poder de ChatGPT, un modelo de lenguaje de última generación desarrollado por OpenAI, en nuestra aplicación Spring Boot, mientras que APISIX proporcionará una forma robusta, escalable y segura de gestionar las APIs.
APIs de ChatGPT de OpenAI
La API de ChatGPT de OpenAI es una herramienta poderosa que podemos usar para integrar las capacidades del modelo ChatGPT en nuestras propias aplicaciones o servicios. La API nos permite enviar una serie de mensajes y recibir una respuesta generada por el modelo de IA a través de REST. Ofrece una variedad de APIs para crear respuestas de texto en un chatbot, completar código, generar imágenes o responder preguntas en una interfaz conversacional. En este tutorial, usaremos la API de completación de chat para generar respuestas a un mensaje (básicamente podemos preguntar cualquier cosa). Antes de comenzar con el tutorial, puedes explorar la API para entender cómo autenticarse en la API usando claves de API, cómo son los parámetros de solicitud y la respuesta de la API.
Un ejemplo de solicitud cURL a la API de completación de chat se vería así. Debes reemplazar OPENAI_API_KEY
con tu propia clave de API y colocarla en el encabezado Authorization al llamar a la 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?"}]
}'
Aquí hay un ejemplo de respuesta 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 es un gateway de API dinámico, en tiempo real y de alto rendimiento diseñado para facilitar la gestión y el enrutamiento de microservicios y APIs. Proporciona características como balanceo de carga, limitación de tasa, autenticación, autorización y control de tráfico, todo lo cual ayuda a simplificar la gestión de microservicios y APIs. Apache APISIX está construido sobre el servidor Nginx y puede soportar altos niveles de tráfico con baja latencia y alta disponibilidad. Es de código abierto y se publica bajo la licencia Apache 2.0."
},
"finish_reason": "stop",
"index": 0
}
]
}
Ejemplo de código del proyecto
El tutorial consta de dos partes. La primera parte cubre la configuración de la aplicación Spring Boot y la creación de un nuevo endpoint de API que puede manejar nuestras llamadas a la API de completación de chat de manera programática. En la segunda parte, introduciremos características de APISIX como seguridad y control de tráfico a la API de Spring Boot. Los ejemplos de código completos para este tutorial están disponibles en el repositorio de GitHub llamado apisix-java-chatgpt-openaiapi.
Requisitos previos
Antes de comenzar, asegúrate de tener lo siguiente:
- Crear una clave de API de OpenAI: Para acceder a la API de OpenAI, necesitarás crear una clave de API. Puedes hacerlo iniciando sesión en el sitio web de OpenAI y navegando a la página de gestión de claves de API.
- Docker instalado en tu máquina para ejecutar APISIX y Spring Boot.
Paso 1: Configuración de la aplicación Spring Boot
Primero, necesitamos configurar una nueva aplicación Spring Boot. Puedes usar Spring Initializr para generar un nuevo proyecto Maven con las dependencias necesarias. Para este tutorial, necesitaremos la dependencia Spring Boot Starter Web. Para integrar la API de ChatGPT, usaremos el cliente Java de OpenAI. Hay una biblioteca de la comunidad de código abierto llamada https://github.com/TheoKanning/openai-java. Proporciona clases de servicio que crean y llaman al cliente de las APIs GPT de OpenAI en Java. Por supuesto, también puedes escribir tu propia implementación en Spring que interactúe con las APIs de OpenAI. Consulta otras bibliotecas de clientes para diferentes lenguajes de programación.
<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>
Paso 2: Crear una clase Controller
En la clase ChatCompletionController.java, puedes usar el servicio de OpenAI para enviar una solicitud a la API de 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();
}
}
El endpoint de la API de chat /ai-chat
maneja solicitudes POST, crea una solicitud de chat y la envía a la API de OpenAI. Luego, devuelve el primer mensaje de la respuesta de la API.
Paso 3: Definir las propiedades de la aplicación
A continuación, proporcionamos las propiedades para la API como model
y API key
en el archivo application.properties:
openai.model=gpt-3.5-turbo
openai.api.key=YOUR_OPENAI_API_TOKEN
Paso 4: Ejecutar la aplicación Spring Boot
Ahora podemos ejecutar Application.java y probarla con Postman o el comando cURL.
Como podemos ver, la aplicación generó una respuesta a nuestra pregunta en el cuerpo de la solicitud del mensaje.
Paso 5: Crear un Dockerfile
Usamos un contenedor Docker para empaquetar nuestra aplicación Spring Boot y usarla junto con otros contenedores de APISIX en docker-compose.yml. Para hacerlo, podemos crear un Dockerfile para construir un JAR y ejecutarlo. Consulta el tutorial sobre cómo dockerizar una aplicación Spring Boot. Luego, registra el servicio en el archivo yaml de docker compose.
openaiapi:
build: openaiapi
ports:
- "8080:8080"
networks:
apisix:
Paso 6: Configuración de Apache APISIX
Para configurar APISIX, simplemente podemos ejecutar el comando docker compose up
. Porque ya hemos definido todos los servicios necesarios en docker-compose.yml. Este archivo define solo 2 contenedores, uno para APISIX y otro para la aplicación Spring Boot que implementamos en los pasos anteriores. En este proyecto de ejemplo, ejecutamos APISIX en modo independiente. Hay otras opciones de instalación y modos de despliegue de APISIX también. Ahora APISIX como un servicio separado se ejecuta en localhost:9080
y la aplicación Spring Boot en localhost:8080
.
Paso 7: Proteger la API con APISIX
Una vez que APISIX está configurado, podemos agregar características de seguridad a nuestra API existente de Spring Boot /ai-chat
para que solo los consumidores de API permitidos puedan acceder a esta API. APISIX proporciona varios plugins para proteger tus APIs. Por ejemplo, puedes usar el plugin jwt-auth para requerir un token JWT en todas las solicitudes. Aquí hay un ejemplo de cómo agregar una ruta con un upstream y plugins usando el archivo 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
Después de especificar los upstreams, rutas y objetos de consumidor y las reglas de enrutamiento en la configuración de APISIX, el archivo de configuración se carga en la memoria inmediatamente después de que el servicio del nodo APISIX se inicia en Docker. Apisix intenta detectar periódicamente si el contenido del archivo se actualiza, si hay una actualización, recarga automáticamente los cambios.
Con esta configuración, agregamos un upstream, dos rutas y un objeto de consumidor. En la primera ruta, todas las solicitudes a /ask-me-anything
(que es una ruta URI personalizada, puedes definir cualquier URI allí) deben incluir el Authorization: JWT_TOKEN
en el encabezado. Luego, APISIX reescribe la ruta URI personalizada a la API real /ai-chat
automáticamente con la ayuda del plugin proxy-rewrite y reenvía las solicitudes a la aplicación Spring Boot que se ejecuta en localhost:8080
.
Si intentas solicitar la ruta de APISIX, rechazará nuestras solicitudes devolviendo un error de autorización:
curl -i http://localhost:9080/ask-me-anything -X POST -d '
{
"prompt":"What is Apache APISIX?"
}'
El resultado de la solicitud anterior:
HTTP/1.1 401 Unauthorized
{"message":"Missing JWT token in request"}
En la segunda configuración de ruta, habilitamos el plugin public-api para exponer un nuevo endpoint /login
para firmar nuevos tokens JWT. Porque APISIX puede actuar como un proveedor de identidad para generar y validar un nuevo token desde el consumidor de API o aplicaciones cliente. Consulta el Paso 8, cómo reclamamos un nuevo token para nuestro consumidor de API.
- uri: /login
plugins:
public-api:
uri: /apisix/plugin/jwt/sign
Si notaste en el mismo archivo de configuración, registramos un consumidor de API para usar la API /ask-me-anything
impulsada por IA y nuestros usuarios pueden reclamar APISIX usando su secreto para generar un token JWT para acceder a la API:
consumers:
- username: appsmithuser
plugins:
jwt-auth:
key: appsmithuser@gmail.com
secret: my-secret-key
Paso 8: Reclamar un nuevo token JWT
Ahora podemos reclamar un nuevo token JWT para nuestro consumidor de API existente con la clave:
curl -i http://127.0.0.1:9080/login?key=user-key -i
Obtendremos el nuevo token como respuesta de APISIX:
Server: APISIX/3.0.0
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJrZXkiOiJ1c2VyLWtleSIsImV4cCI6MTY4NjU5MjE0NH0.4Kn9c2DBYKthyUx824Ah97-z0Eu2Ul9WGO2WB3IfURA
Paso 9: Solicitar la API con el token JWT
Finalmente, podemos enviar una solicitud a la API /ask-me-anything
con el token JWT en el encabezado que obtuvimos en el paso anterior.
curl -i http://localhost:9080/ask-me-anything -H 'Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJrZXkiOiJ1c2VyLWtleSIsImV4cCI6MTY4NjU5Mjk4N30.lhom9db3XMkcVd86ScpM6s4eP1_YzR-tfmXPckszsYo' -X POST -d '
{
"prompt":"What is Apache APISIX?"
}'
O usando Postman, obtendremos la respuesta de IA, pero esta vez la respuesta llega a través del Gateway de APISIX:
Conclusión
En este tutorial, exploramos la API de ChatGPT de OpenAI para generar respuestas a mensajes. Creamos una aplicación Spring Boot que llama a la API para generar respuestas a mensajes. A continuación, puedes introducir características adicionales a tu integración actualizando el archivo apisix.yml existente. También puedes revisar la rama llamada with-frontend y ejecutar el proyecto para ver la interfaz de usuario construida usando Appsmith que funciona con APISIX.