Dentro del ecosistema de Spring tenemos múltiples starter que nos facilitan la vida cuando tenemos que agregar alguna característica a nuestro programa. Y, en el caso de la gran moda (que ha venido para quedarse), la inteligencia artificial, ¡no iba a ser menos!

Por ello ha nacido Spring Boot AI Starter que nos facilita la integración de la inteligencia artificial en nuestros desarrollos con Spring Boot. De hecho, si nos metemos a crear una aplicación en Spring Initializr vemos que ya está disponible.

Pantalla principal de Spring Initializr

Este starter nos aporta herramientas y componentes listos para usar que simplifican el desarrollo de aplicaciones que hacen uso de la inteligencia artificial. En este post, vamos a ver en detalle cómo utilizar el Spring Boot AI Starter, qué nos aporta y una guía de desarrollo paso a paso. ¡Vamos allá!

Ok, pero.. ¿qué me aporta Spring Boot AI Starter?

Entre las ventajas que nos aporta Spring Boot AI Starter, las más destacables serían las siguientes:

  1. Facilidad de Integración. Simplifica la configuración y uso de bibliotecas de IA populares como TensorFlow y PyTorch (muy conocidas en el mundo Python).
  2. Base de datos vectoriales. En vez de trabajar como hacemos habitualmente con coincidencias exactas, realizan búsquedas de similitudes. Cuando se hace una consulta con un vector, nos devuelve vectores que son "similares" al vector de consulta.
  3. ETL pensada para el trabajo con vectores (muy orientada a Big Data).
  4. Ahorro de tiempo con componentes preconfigurados en su starter que aceleran el desarrollo.
  5. Optimización de rendimiento. Ofrece optimizaciones para ejecutar modelos de IA de manera eficiente en aplicaciones Spring Boot.
  6. Orientación y compatibilidad a servicios de la nube. Fácil integración con servicios de IA en la nube como OpenAI, Azure OpenAI, Amazon Bedrock (Anthropic, Llama, Cohere, Titan, Jurassic2), HuggingFace, Google VertexAI (PaLM2, Gemini), Mistral AI, Stability AI, Ollama, PostgresML ,Transformers (ONNX), Anthropic Claude3 y MiniMax.

Configuración inicial

Añadir dependencias a nuestro proyecto

Este ejemplo está hecho con Java 17 y SpringBoot 3.3.0.

<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-openai-spring-boot-starter</artifactId>
</dependency>

Nota: Se trata de un proyecto en maduración, de hecho la versión que estoy cogiendo es <spring-ai.version>1.0.0-M1</spring-ai.version>

También he añadido el repositorio spring milestone y spring snapshot en mi configuración de Maven.

Ejemplo práctico: utilizando el API de OpenAI

Lo primero que debemos tener es un API Key que nos permita interactuar con las api que nos proporciona OpenAI. La parte negativa es que, para ello, he tenido que utilizar un método de pago para poder obtener uno. Esta opción está disponible en la parte de https://platform.openai.com/account/api-keys (pero aunque crees el API, si no llegas a pagar te dará un error 429 como que excediste la cuota aunque acabes de registrarte en OpenAI).

Paso 1: configurar el API KEY

spring:
  application:
    name: example-ia
  ai:
    openai:
      api-key: APIKEY
      chat:
        options:
          model: gpt-3.5-turbo # default option

Una de las opciones interesantes es poder jugar con el modelo que estamos utilizando aunque, por defecto, es el indicado en la parte de arriba (también tiene distintas tarifas aplicadas). Aquí está la lista incluida en OpenAI.

Paso 2: crear un controlador REST

Es tan sencillo y está tan bien documentado que para cualquier desarrollador/a es divertido y muy fácil empezar este camino.

En esta demo voy a jugar con el API de texto de imagen y de voz:

@RestController
public class OpenAIController {

    private final OpenAiChatModel chatModel;
    private final OpenAiImageModel imageModel;
    private final OpenAiAudioSpeechModel audioSpeechModel;

    @Autowired
    public OpenAIController(OpenAiChatModel chatModel, OpenAiImageModel imageModel, OpenAiAudioSpeechModel audioSpeechModel) {
        this.chatModel = chatModel;
        this.imageModel = imageModel;
        this.audioSpeechModel = audioSpeechModel;
    }
// ...
}

Vamos a hacer algunos endpoints sencillos, en el primero vamos a interactuar con el API del chat como si estuviéramos preguntando directamente desde ChatGPT.

@GetMapping("/ai/generateStream")
public Flux<ChatResponse> generateStream(@RequestParam(value = "message", defaultValue = "Tell me a joke") String message) {
        Prompt prompt = new Prompt(new UserMessage(message));
        return chatModel.stream(prompt);
    }

Para el segundo, vamos a usar el API de generación de imágenes para que nos retorne la imagen directamente. En este ejemplo, hemos jugado con las opciones para que nos devuelva un array de bytes y poder pintarlas en el navegador. Existen más opciones como la calidad, el tamaño…

@GetMapping(value = "/ai/generateImage", produces = MediaType.IMAGE_JPEG_VALUE)
public ResponseEntity<byte[]> getImage(@RequestParam(value = "message", defaultValue = "nice logo") String message) {

   ImagePrompt prompt = new ImagePrompt(message, OpenAiImageOptions.builder().withResponseFormat("b64_json").build());

   ImageResponse imageResponse =  imageModel.call(prompt);

   String base64Image = imageResponse.getResults().get(0).getOutput().getB64Json();
   byte[] imageBytes = Base64.getDecoder().decode(base64Image);
   HttpHeaders headers = new HttpHeaders();
   headers.setContentType(MediaType.IMAGE_JPEG);

   return new ResponseEntity<>(imageBytes, headers, HttpStatus.OK);
}

Para el último ejemplo he usado el API de chat y la salida la he volcado en el API de audio para que se reproduzca (sería un mini Alexa con entrada de texto, faltaría un speech to text). Dentro de las configuraciones que admite este API están la velocidad, la voz…

@GetMapping(value = "/ai/generateAudio")
public ResponseEntity<byte[]> getAudio(@RequestParam(value = "message", defaultValue = "Tell me a joke") String message) {

   String joke =  chatModel.call(message);
   SpeechPrompt speechPrompt = new SpeechPrompt(new SpeechMessage(joke));

   String format = "audio/wav";
   HttpHeaders headers = new HttpHeaders();
   headers.setContentType(MediaType.parseMediaType(format));

   SpeechResponse response = audioSpeechModel.call(speechPrompt);

   return new ResponseEntity<>(response.getResult().getOutput(), headers, HttpStatus.OK);
}

Paso 3: probar el endpoint

Se trata de un microservicio de Spring Boot que levanta un controlador y podemos probar muy fácilmente.

Imagen que muestra la pantalla principal del controlador con un ejemplo de Paradigma Digital
Imagen que muestra la consulta de "how to create a microservice"

Conclusión

Destacaría lo fácil que es empezar a consumir servicios de IA en nuestros microservicios sin tener que codificar y el abanico de posibilidades que se nos abren de combinar llamadas de diferentes servicios para cubrir distintos casos de uso. Nos olvidamos de las integraciones y empezamos directamente el desarrollo de aplicaciones inteligentes sin preocuparnos de configurar y manejar modelos de IA.

Otra parte muy positiva es que estamos en el ecosistema de Spring con todas las funcionalidades que tenemos ya conocidas respecto a seguridad, auditoría…. y que es un entorno de trabajo muy conocido para la mayoría de desarrolladores/as back end.

Este post explora parte de las funcionalidades que aporta este nuevo starter pero tiene muchas posibilidades y está encontrando un punto de encuentro entre el mundo de la inteligencia artificial y nuestro querido mundo de Spring Boot.

Dejo el código disponible en mi github.

Cuéntanos qué te parece.

Los comentarios serán moderados. Serán visibles si aportan un argumento constructivo. Si no estás de acuerdo con algún punto, por favor, muestra tus opiniones de manera educada.

Suscríbete