Cuando se habla de desarrollar aplicaciones con LLMs, casi todos los ejemplos utilizan servicios en la nube como OpenAI, Gemini o Claude. Sin embargo, para aprender, desarrollar prototipos o incluso construir aplicaciones internas, ejecutar un modelo localmente suele ser una excelente alternativa.
El objetivo es mostrar que integrar un LLM en una aplicación Java puede ser tan simple como consumir cualquier otro servicio.
Ya hablamos de LangChain4j
Necesitamos:
- Java 21
- Spring Boot 3.5+
- Ollama instalado
Descargamos un modelo.
ollama pull llama3.2
Y lo ejecutamos
ollama serve
Por defecto queda escuchando en
http://localhost:11434
Ahora creamos el proyecto spring boot y agregamos la dependencia.
Con Maven:
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j</artifactId>
<version>1.1.0</version>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-ollama</artifactId>
<version>1.1.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
Creamos un Bean.
@Configuration
public class AIConfiguration {
@Bean
ChatLanguageModel chatLanguageModel() {
return OllamaChatModel.builder()
.baseUrl("http://localhost:11434")
.modelName("llama3.2")
.temperature(0.2)
.build();
}
}
Nada más.
No hay API Keys.
No hay cuentas.
No hay servicios externos.
Una de las características más interesantes de LangChain4j es que los prompts pueden representarse mediante interfaces Java.
interface Assistant {
String chat(String message);
}
Luego simplemente creamos una implementación dinámica.
@Bean
Assistant assistant(ChatLanguageModel model){
return AiServices.create(
Assistant.class,
model
);
}
Desde este momento tenemos un objeto Java completamente funcional.
Creamos un Controller.
@RestController
@RequestMapping("/chat")
public class ChatController {
private final Assistant assistant;
public ChatController(Assistant assistant) {
this.assistant = assistant;
}
@GetMapping
public String chat(@RequestParam String message){
return assistant.chat(message);
}
}
Probamos la aplicación.
GET /chat?message=Explain what Spring Boot is
Respuesta:
Spring Boot is...
Así de simple.
Podemos indicar el comportamiento del asistente mediante anotaciones.
interface Assistant {
@SystemMessage("""
You are a senior Java architect.
Keep answers under 150 words.
""")
String chat(String message);
}
Ahora todas las respuestas respetarán ese contexto.
También podemos utilizar parámetros.
interface Translator {
@SystemMessage("""
You are a professional translator.
Translate everything to {{language}}.
""")
String translate(
@V("language") String language,
@UserMessage String text);
}
Uso:
translator.translate(
"Spanish",
"Spring Boot is awesome."
);
LangChain4j permite agregar memoria con muy poco código.
@Bean
ChatMemory chatMemory() {
return MessageWindowChatMemory.withMaxMessages(20);
}
Luego la asociamos al servicio.
Assistant assistant(ChatLanguageModel model,
ChatMemory memory){
return AiServices.builder(Assistant.class)
.chatLanguageModel(model)
.chatMemory(memory)
.build();
}
Ahora el modelo recordará el contexto de la conversación.
Este ejemplo apenas muestra la superficie.
LangChain4j también incorpora soporte para:
- Retrieval Augmented Generation (RAG)
- Embeddings
- Document Loaders
- Vector Stores
- Tools (Function Calling)
- Streaming
- Moderation
- AI Agents
- Structured Outputs
Todo ello manteniendo una API muy natural para desarrolladores Java.
.jpeg)