Artículo

Introducción a Spring AI

Introducción a Spring AI

1. Visión general

Las aplicaciones modernas están utilizando cada vez más Large Language Models (LLMs) para construir soluciones que van más allá de las capacidades de programación tradicionales. Sin embargo, integrar estos modelos en nuestras aplicaciones suele implicar lidiar con APIs complejas, gestionar distintos proveedores de IA y afrontar diversos retos de configuración.

Spring AI, una nueva adición al ecosistema Spring, aborda estos problemas al ofrecer una capa de abstracción común para trabajar con distintos proveedores de IA empleando los patrones de programación Spring conocidos.
Elimina la necesidad de usar SDKs específicos de cada proveedor y nos permite cambiar entre diferentes modelos sin modificar el código de nuestra aplicación.

En este tutorial, exploraremos de forma práctica los conceptos fundamentales de Spring AI construyendo un servicio básico de generación de poemas.

2. Configuración del proyecto

Para nuestra demostración, construiremos nuestro servicio de generación de poemas utilizando el modelo OpenAI GPT‑5.

Sin embargo, Spring AI soporta modelos de otros proveedores como Anthropic, DeepSeek e incluso LLMs locales a través de Hugging Face o Ollama. Podemos elegir el modelo que mejor se adapte a nuestras necesidades, ya que el modelo de IA específico es irrelevante para esta implementación.

2.1. Dependencias

Comencemos añadiendo la dependencia necesaria al archivo pom.xml de nuestro proyecto:

<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-starter-model-openai</artifactId>
    <version>1.0.1</version>
</dependency>

La dependencia starter de OpenAI es un envoltorio alrededor de la Chat Completions API de OpenAI, y la utilizaremos para interactuar con el modelo GPT‑5 en nuestra aplicación.

2.2. Configuración de las propiedades LLM

A continuación, configuremos nuestra clave API de OpenAI y el modelo de chat en el archivo application.yaml:

spring:
  ai:
    openai:
      api-key: ${OPENAI_API_KEY}
      chat:
        options:
          model: gpt-5
          temperature: 1

Utilizamos el marcador de posición de propiedad ${} para cargar el valor de nuestra clave API desde una variable de entorno.

A continuación, especificamos gpt‑5 como el ID del modelo. Podemos usar un modelo diferente según los requisitos.

Adicionalmente, configuramos la temperature a 1 ya que el modelo que hemos configurado solo acepta este valor por defecto.

3. Construyendo un servicio de generación de poemas

Con nuestras configuraciones en su lugar, construyamos un servicio que genere poemas usando el LLM configurado. Comenzaremos con una implementación básica y la refactorizaremos gradualmente para utilizar características más avanzadas de Spring AI.

3.1. Uso de ChatClient para comunicarse con el LLM

En Spring AI, la clase ChatClient sirve como el punto de entrada principal para interactuar con cualquier modelo que configuramos.
Podemos obtener una instancia de ella usando el bean ChatClient.Builder, que el marco crea automáticamente para nosotros en función de las propiedades que configuramos en nuestro archivo application.yaml.

Utilicemos esto para crear una nueva clase PoetryService:

private final ChatClient chatClient;

PoetryService(ChatClient.Builder chatClientBuilder) {
    this.chatClient = chatClientBuilder.build();
}

String generate() {
    return chatClient
      .prompt("Write a playful haiku about morning coffee following the traditional 5-7-5 syllable structure.")
      .call()
      .content();
}

Aquí, inyectamos el ChatClient.Builder en el constructor de nuestro servicio y lo utilizamos para construir una instancia de ChatClient.
A continuación, en nuestro método generate() usamos el método prompt() de chatClient para enviar una solicitud solicitando un haiku.
Luego, invocamos el método call() para ejecutar la solicitud contra el LLM configurado, y content() para extraer el texto generado como una simple String.

3.2. Refactorización con PromptTemplate y salida estructurada

Aunque nuestra implementación inicial funciona, está limitada a generar haikus sobre café con un prompt fijo. Además, devolvemos una respuesta de cadena simple que puede resultar difícil de manejar para los clientes.

Para abordar estas limitaciones, refactorizaremos nuestro servicio para usar una plantilla de prompt donde podamos sustituir dinámicamente los valores de género y tema en tiempo de ejecución y mapear la respuesta del LLM a un objeto Java estructurado.

Primero, definamos un record Poem para representar la estructura de nuestra salida:

record Poem(
    String title,
    String content,
    String genre,
    String theme) {}

Definimos el record con campos para title, content, genre y theme para representar la respuesta estructurada que esperamos del LLM.

A continuación, refactoricemos nuestro método de servicio:

private final static PromptTemplate PROMPT_TEMPLATE
    = new PromptTemplate("Write a {genre} haiku about {theme} following the traditional 5-7-5 syllable structure.");

Poem generate(String genre, String theme) {
    Prompt prompt = PROMPT_TEMPLATE
      .create(Map.of(
        "genre", genre,
        "theme", theme));
    return chatClient
      .prompt(prompt)
      .call()
      .entity(Poem.class);
}

En nuestra versión refactorizada, reemplazamos el prompt codificado con un PromptTemplate que contiene marcadores de posición para genre y theme. En el método generate() ahora esperamos estos valores como parámetros del método y los usamos para crear una instancia de Prompt.

Adicionalmente, reemplazamos el método content() por entity() donde especificamos nuestro record Poem. Spring AI agregará automáticamente instrucciones al prompt para dirigir al LLM a generar una respuesta que pueda ser mapeada a este record.

3.3. Exposición de una API REST y manejo de errores

Ahora que hemos implementado nuestra capa de servicio, expondremos una API REST encima de ella:

@PostMapping("/poems")
ResponseEntity<Poem> generate(@RequestBody PoemGenerationRequest request) {
    Poem response = poetryService.generate(request.genre, request.theme);
    return ResponseEntity.ok(response);
}

record PoemGenerationRequest(String genre, String theme) {}

Aquí, simplemente definimos un endpoint POST /poems que acepta un record PoemGenerationRequest como cuerpo de la solicitud y delega a nuestra capa de servicio para devolver el poema generado.

Adicionalmente, al igual que la comunicación con cualquier servicio externo, el LLM configurado a veces puede fallar. Para manejar dichos escenarios de forma elegante, Spring AI ofrece una OpenAiApiClientErrorException que proporciona una abstracción sobre todos los errores de OpenAI.

Definamos un handler de excepciones para esta clase:

private static final String LLM_COMMUNICATION_ERROR =
    "Unable to communicate with the configured LLM. Please try again later.";

@ExceptionHandler(OpenAiApiClientErrorException.class)
ProblemDetail handle(OpenAiApiClientErrorException exception) {
    logger.error("OpenAI returned an error.", exception);
    return ProblemDetail.forStatusAndDetail(HttpStatus.SERVICE_UNAVAILABLE, LLM_COMMUNICATION_ERROR);
}

Aquí, evitamos intencionadamente exponer los detalles reales del error en la respuesta para evitar revelar información sensible sobre nuestra infraestructura o claves API. En su lugar, registramos la excepción completa para propósitos de depuración y devolvemos un mensaje amigable al usuario mediante el formato de respuesta estandarizado ProblemDetail.

4. Pruebas de la aplicación

Finalmente, utilicemos el endpoint de la API que hemos expuesto para interactuar y probar nuestra aplicación.
Usaremos la CLI HTTPie para invocar la API:

http POST :8080/poems genre="frustrated" theme="code review comments"

Aquí enviamos una solicitud POST a nuestro endpoint /poems con nuestro genre y theme deseados.

Veamos qué recibimos como respuesta:

{
    "title": "Nitpick Nightmare",
    "content": "Tabs versus spaces\nThey argue while prod is down\nPriorities... where?",
    "genre": "frustrated",
    "theme": "code review comments"
}

Como podemos ver, obtenemos un haiku que captura eficazmente el género y el tema que proporcionamos.
Esto confirma que nuestra aplicación llena correctamente la plantilla de prompt y recibe la salida del LLM en un formato que puede mapearse a nuestro record Poem.

5. Conclusión

En este artículo, hemos explorado la integración de capacidades de IA en una aplicación Spring Boot usando Spring AI. Revisamos la configuración necesaria e implementamos un servicio de generación de poemas usando el modelo GPT‑5 de OpenAI. Evolucionamos nuestra implementación simple de un prompt basado en cadena a una solución más sofisticada utilizando plantillas de prompt y salidas estructuradas.

Aunque este tutorial introductorio cubre los fundamentos, Spring AI ofrece capacidades extensas de IA que pueden explorarse en nuestra colección de tutoriales de Spring AI.

Newsletter Semanal de Java

Cada viernes recibe lo más nuevo del ecosistema Java: frameworks, herramientas y mejores prácticas.

Sin spam. Cancela cuando quieras.

Compartir artículo