Volver al blog
JavaSpring BootLangChain4jLLMsTutorial

Spring Boot + LangChain4j: mi primera integración real con LLMs

Cómo integré un LLM en una aplicación Spring Boot existente usando LangChain4j. Ejemplo real con código, decisiones de arquitectura y lecciones aprendidas.

· 4 min

Cuando empecé a explorar cómo integrar LLMs en el ecosistema Java, la primera opción obvia era llamar a la API de OpenAI directamente con un RestTemplate. Funciona, pero es como usar JDBC crudo en 2026 — puedes, pero hay mejores formas. Así llegué a LangChain4j, el equivalente Java de LangChain para Python.

¿Qué es LangChain4j?

Es una librería Java que abstrae la interacción con modelos de lenguaje. Soporta OpenAI, Anthropic, Ollama (modelos locales) y otros proveedores. Lo interesante es que se integra nativamente con Spring Boot mediante un starter oficial.

Setup del proyecto

Partí de una aplicación Spring Boot 3.2 existente — un sistema de gestión de tickets de soporte. El objetivo: añadir clasificación automática de tickets por prioridad y categoría usando un LLM.

Dependencia en pom.xml:

<dependency>
    <groupId>dev.langchain4j</groupId>
    <artifactId>langchain4j-spring-boot-starter</artifactId>
    <version>0.36.2</version>
</dependency>
<dependency>
    <groupId>dev.langchain4j</groupId>
    <artifactId>langchain4j-open-ai-spring-boot-starter</artifactId>
    <version>0.36.2</version>
</dependency>

Configuración en application.yml:

langchain4j:
  open-ai:
    chat-model:
      api-key: ${OPENAI_API_KEY}
      model-name: gpt-4o-mini
      temperature: 0.1
      max-tokens: 500

Temperatura baja (0.1) porque quiero respuestas consistentes para clasificación, no creatividad.

La interfaz del servicio IA

LangChain4j usa un patrón que me encantó: defines una interfaz Java y la anotaciones hacen el resto. Sin parsear JSON manualmente, sin construir prompts como strings.

@AiService
public interface TicketClassifier {

    @UserMessage("""
        Analiza el siguiente ticket de soporte y devuelve:
        - priority: HIGH, MEDIUM o LOW
        - category: una de [BILLING, TECHNICAL, ACCOUNT, GENERAL]
        - summary: resumen en una frase

        Ticket: {{ticket}}
        """)
    TicketClassification classify(@V("ticket") String ticketContent);
}

Y el record para la respuesta:

public record TicketClassification(
    Priority priority,
    Category category,
    String summary
) {}

LangChain4j se encarga de: construir el prompt, llamar a la API, parsear la respuesta JSON y mapearla al record. Spring lo inyecta como cualquier otro bean.

Uso en el servicio de negocio

@Service
@RequiredArgsConstructor
public class TicketService {

    private final TicketRepository repository;
    private final TicketClassifier classifier;

    public Ticket createTicket(String content, String userEmail) {
        var classification = classifier.classify(content);

        var ticket = Ticket.builder()
            .content(content)
            .userEmail(userEmail)
            .priority(classification.priority())
            .category(classification.category())
            .summary(classification.summary())
            .build();

        return repository.save(ticket);
    }
}

Limpio, testeable, sin acoplamiento al proveedor de IA. Si mañana quiero cambiar a Anthropic, toco la configuración, no el código de negocio.

Lecciones aprendidas

1. La latencia importa. La llamada al LLM añade 1-3 segundos. En mi caso lo resolví haciendo la clasificación asíncrona — el ticket se crea inmediatamente y se clasifica en background con @Async.

2. El fallback es obligatorio. Si la API falla o devuelve algo inesperado, el ticket se guarda con prioridad MEDIUM y categoría GENERAL por defecto. Nunca bloquear el flujo principal por una dependencia de IA.

3. Los tests necesitan mocks. Para tests unitarios uso un mock del TicketClassifier. Para tests de integración tengo un perfil con Ollama local (llama3) que no depende de APIs externas ni cuesta dinero.

4. gpt-4o-mini es suficiente. Para clasificación no necesitas el modelo más potente. Ahorras coste y ganas velocidad. Reserva los modelos grandes para tareas que realmente los requieren.

Conclusión

LangChain4j hace que integrar LLMs en Spring Boot sea tan natural como usar Spring Data JPA. La clave no es la librería — es tener claro el caso de uso, manejar los errores con gracia, y no acoplar tu dominio al proveedor de IA.

Si vienes del mundo Java como yo, esta es probablemente la forma más productiva de empezar con IA en tus aplicaciones existentes.

Newsletter semanal sobre desarrollo e IA

Cada semana comparto lo que aprendo sobre desarrollo de software, inteligencia artificial y automatización. Sin spam, sin relleno.