Inicio / Artículos / Java como lenguaje de producción para IA: Spring Boot, RAG y pgvector

Java como lenguaje de producción para IA: Spring Boot, RAG y pgvector

Un mapa práctico para desarrollar servicios RAG en la JVM con Spring AI o LangChain4j, eligiendo un almacén de vectores y gestionando aspectos como arrendamiento, costos, evaluación y soluciones alternativas.

2624 palabras

Python entrena los modelos, mientras que Java se está convirtiendo silenciosamente en el lenguaje que permite su implementación. Durante aproximadamente tres años, el ámbito de la IA parecía una conferencia dedicada a Python con un presupuesto mayor: demostraciones en cuadernos de notas, tutoriales que comenzaban con pip install, y diagramas de arquitectura en los que un pequeño recuadro llamado “servicio LLM de Python” aparecía separado del verdadero backend. Ese verdadero backend solía ser Spring Boot, que ya se encargaba de la autenticación, la facturación, los registros de auditoría y la base de datos.

Ese pequeño recuadro ya no es obligatorio. Spring AI ya superó la versión 1.0 y ahora está en la 2.0. LangChain4j es una biblioteca adecuada para JVM que cuenta con más de veinte proveedores de modelos y más de treinta almacenes de vectores. PostgreSQL almacena los embeddings a través de pgvector. Un servicio de Spring Boot que ya esté en ejecución puede llamar a un LLM, obtener contexto relevante, invocar herramientas, transmitir tokens y publicar métricas Micrometer, todo dentro de la JVM.

¿Eso convierte a Java en el nuevo rey de la IA? No en el sentido de las habituales guerras de lenguajes. Nadie está reemplazando PyTorch por Java. Lo que sí está ganando Java es el campo donde está el dinero: las aplicaciones empresariales que deben ser correctas, observables y, a la vez, lo suficientemente sencillas. Si trabajas en ese ámbito, el ganador es lo que ya ejecute tu clúster de producción, y cada vez más ese sistema utiliza Java.

El resto de este artículo describe este cambio. Explica por qué ocurrió, cómo se ve un servicio RAG en Spring Boot, cómo elegir un almacén de vectores y qué detalles de producción diferencian una demostración de algo en lo que se podría confiar con datos de clientes.

La ventaja de Python siempre fue la investigación

Python se impuso en la era de la investigación por razones válidas que siguen siendo relevantes: NumPy, PyTorch, Hugging Face, Jupyter y toda una generación de ingenieros expertos en tensores. El ajuste fino de modelos, la prueba de nuevas arquitecturas de incrustación o el entrenamiento en GPUs siguen siendo tareas propias de Python.

El despliegue en producción es otro asunto. La mayoría de las empresas nunca entrenan un modelo base. Simplemente lo llaman y entonces comienza el trabajo real: obtener documentos, aplicar políticas, separar usuarios, registrar solicitudes, limitar gastos y asegurarse de que nada genere cifras erróneas de reembolso. Eso incluye el diseño de APIs, el acceso a datos, la seguridad y las operaciones, tareas que Spring Boot maneja desde 2014.

La solución popular de colocar el modelo detrás de FastAPI conllevaba costos recurrentes:

  • dos lenguajes dentro de un mismo producto
  • pipelines de despliegue separados
  • sistemas de monitoreo independientes
  • un contrato de interfaz que cambiaba ligeramente en cada sprint
  • revisiones de seguridad que de repente incluían un servicio en Python que guardaba sus propios secretos
  • La gente aceptó esto porque Java carecía de herramientas serias para LLM. Para 2025 eso ya no era cierto. Spring AI 1.0 se puso a disposición general en mayo de 2025, y la versión 2.0 llegó en junio de 2026 junto con Spring Boot 4. LangChain4j alcanzó la versión 1.0 en el mismo período. La pila JVM ya no está intentando ponerse al día. Para los equipos que ya usan Spring, es una opción razonable por defecto.

    Qué significa “añadir IA” en una aplicación Spring

    No se requiere reescribir nada, solo tres funcionalidades.

    1. Una capa de chat. ChatClient en Spring AI, o un AiService en LangChain4j, convierte una solicitud y el historial de mensajes en una respuesta del modelo. La transmisión en tiempo real es estándar, y la salida estructurada puede almacenarse en un registro de Java, lo que evita tener que procesar JSON a partir de texto con expresiones regulares.
    2. Acceso a sus propios datos. Usted calcula los embeddings y los guarda en un almacén de vectores, de modo que las respuestas provienen de sus políticas, facturas, manuales de operaciones y documentación del producto, y no de lo que el modelo recuerda a medias. Esto se conoce como Generación Aumentada por Búsqueda (RAG).
    3. Llamadas a herramientas. El modelo puede invocar métodos de Java según sus reglas de autorización, por ejemplo para buscar un pedido, abrir un caso o consultar el saldo. Aquí resultan útiles el sistema de tipos y los servicios que ya posee. El modelo no es su fuente de verdad; simplemente razona sobre ella.

    Con Spring Security, Spring Data, Actuator y PostgreSQL ya implementados, se trata de otro tipo de cliente más, similar a lo que ocurrió con Redis o Kafka.

    RAG, explicado para desarrolladores de Java

    Si eliminamos el misterio, RAG es un pipeline de búsqueda que termina en un modelo de lenguaje. Los pasos son:

    1. Dividir los documentos en fragmentos.
    2. Convertir cada fragmento en un embedding, es decir, un vector de números flotantes que codifica su significado.
    3. Guardar los vectores junto con metadatos como el propietario, el ID del documento, la URI de origen y la fecha de registro.
    4. Cuando llega una pregunta, embedearla y buscar los fragmentos más cercanos.
    5. Incluir esos fragmentos en el prompt.
    6. Indicar al modelo que responda únicamente a partir de ellos y que admita cuando no contengan la respuesta.

    Una base de datos vectorial no sustituye a tu base de datos transaccional. Es un índice semántico, algo similar a Elasticsearch pero con un vocabulario más avanzado.

    Para las aplicaciones basadas en Spring Boot, normalmente se comienza con PostgreSQL junto a pgvector. Postgres ya está desplegado, respaldado y gestionado en grupos de recursos, por lo que instalar una extensión cuesta menos que adoptar inmediatamente Pinecone, Weaviate o Qdrant. Los motores dedicados sí son ventajosos cuando la escala es extrema o se necesita búsqueda híbrida, pero la mayoría de las aplicaciones internas de tipo RAG operan con un nivel de demanda muy por debajo de ese umbral.

    Un esqueleto listo para funcionar

    La configuración que se muestra a continuación combina Spring AI 2.0 con Boot 4; en Boot 3.4 o 3.5 se debe utilizar la versión 1.1.x en su lugar. Primero hay que incluir el BOM para que todas las dependencias estén alineadas con la misma versión:

    <dependencyManagement>
      <dependencies>
        <dependency>
          <groupId>org.springframework.ai</groupId>
          <artifactId>spring-ai-bom</artifactId>
          <version>1.1.8</version>
          <type>pom</type>
          <scope>import</scope>
        </dependency>
      </dependencies>
    </dependencyManagement>
    

    A continuación, indique solo las dependencias que necesite:

    <dependency>
      <groupId>org.springframework.ai</groupId>
      <artifactId>spring-ai-starter-model-openai</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.ai</groupId>
      <artifactId>spring-ai-starter-vector-store-pgvector</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-jdbc</artifactId>
    </dependency>
    

    JDBC se incluye intencionadamente. El starter de pgvector funciona a través de JdbcTemplate, y olvidar esa dependencia es una causa sorprendentemente frecuente de un arranque fallido.

    La configuración se encuentra en application.yml. Ese es el propósito de Spring AI: un modelo debe configurarse como una fuente de datos.

    spring:
      datasource:
        url: jdbc:postgresql://localhost:5432/app
        username: app
        password: ${DB_PASSWORD}
      ai:
        openai:
          api-key: ${OPENAI_API_KEY}
          chat:
            options:
              model: gpt-4o-mini
              temperature: 0.2
          embedding:
            options:
              model: text-embedding-3-small
        vectorstore:
          pgvector:
            initialize-schema: true
            index-type: HNSW
            distance-type: COSINE_DISTANCE
            dimensions: 1536
    

    Dos detalles en este archivo son más importantes de lo que parecen. La dimensión de incrustación debe ser igual a la que produce el modelo de incrustación, y text-embedding-3-small genera 1536. Si cambias el modelo y olvidas ese número, la búsqueda por similitud empeora sin que aparezca ningún error. El segundo detalle es utilizar una temperatura baja para RAG, ya que lo que se desea es un resultado cercano al texto recuperado, y no una reescritura creativa de un estado financiero.

    Trata la ingesta de datos como un servicio independiente en lugar de una instrucción simple dentro de un controlador. VectorStore.add(...) acepta fragmentos de tipo Document, y cada fragmento debe contener los metadatos con los que filtrarás posteriormente, como tenantId, source, docType y effectiveDate. Sin filtros, la búsqueda semántica podría mostrar el contrato de un cliente dentro de la respuesta de otro cliente.

    La consulta es igual de sencilla. QuestionAnswerAdvisor en Spring AI representa una versión predefinida de este proceso: recuperar datos, agregar contexto y llamar al modelo. Si necesita filtros, reclasificación o citas, utilice similaritySearch por sí mismo y considere filterExpression como una cláusula WHERE, ya que ese es precisamente su propósito.

    Elegir un almacén de vectores sin dogmas

    Existen cuatro opciones:

    • Postgres con pgvector. Es la opción por defecto más razonable y bien comprendida desde el punto de vista operativo. Gracias a la indexación HNSW, la supervisión del rendimiento y los bloques compactos, puede manejar decenas de millones de vectores. Sin embargo, falla cuando se requiere una búsqueda híbrida avanzada o un equipo dedicado al funcionamiento de infraestructuras de vecinos más cercanos aproximados.
  • Redis. Rápido, a menudo ya presente en las pilas Spring, y adecuado para la memoria de sesiones y pequeñas bases de conocimiento. El costo en RAM es lo que al final se debe considerar.
  • Motores diseñados específicamente (Qdrant, Weaviate, Milvus, Pinecone). Son una buena opción cuando la recuperación de información es el producto en sí: grandes corpus, consultas híbridas léxicas y vectoriales, varios índices, o un equipo que desea software diseñado para redes neuronales artificiales. Spring AI admite directamente a los más populares.
  • El motor de búsqueda que ya tienes. Elasticsearch y OpenSearch manejan el algoritmo kNN, y si tus documentos se encuentran allí, un campo vectorial denso puede ser mejor que agregar un cuarto sistema de datos.
  • El método para tomar decisiones es sencillo, y esa es su ventaja. Comience con pgvector cuando Postgres ya esté en producción. Cambie de estrategia cuando la recuperación, la latencia o la búsqueda híbrida no cumplan con los requisitos reales de rendimiento, y no porque algún artículo afirme que las aplicaciones avanzadas de IA utilizan cierto producto. Además, mantenga una referencia al registro original junto a cada vector, para poder volver a incrustarlo siempre que cambie la política.

    Ese último punto es el que los tutoriales omiten. Los modelos de incrustación se actualizan, la división en fragmentos se vuelve más inteligente y los documentos legales se modifican. Una tarea de ingesta que sea idempotente y esté indexada por versión del documento le ahorrará tiempo intentando averiguar por qué el bot muestra la tabla de tarifas del año pasado.

    Spring AI versus LangChain4j

    Ambos están listos para su uso en producción. Cuál es el más adecuado depende de la situación actual de su equipo.

    Spring AI toma la conocida idea de Spring sobre abstracciones portátiles y la aplica a los modelos. Si lo imaginas como Spring Data para LLMs, le resultará natural, ya que la autocompletación, ChatClient, los asesores, Actuator y Micrometer encajan perfectamente. Utiliza la versión 2.0 con Boot 4. En Boot 3, debes quedarte en la versión 1.1.x, ya que la 2.0 no se puede instalar directamente.

    LangChain4j está escrito primero para Java y ofrece un starter de Spring adicional. Soporta más proveedores, sus AiServices tipados se asemejan a clientes Feign orientados a modelos, y es adecuado para equipos que también utilizan Quarkus o Java puro. Aquellos que desean un control estricto sobre el ciclo del agente suelen elegirlo.

    Nada impide que utilice ambos. Una división viable es usar Spring AI para las conversaciones y RAG en los servicios orientados al cliente, con LangChain4j para cubrir necesidades específicas de ciertos proveedores o patrones de agentes. Mantenga sus componentes separados y nunca permita que dos modelos de embedding diferentes escriban vectores incompatibles en una misma tabla.

    Un entorno completamente basado en Spring-Boot que pueda programar una actualización a Boot 4 debería optar por Spring AI. Un entorno híbrido con JVM, o uno que lleve un año usando Boot 3, probablemente encontrará que LangChain4j depende menos de las versiones del framework.

    En producción es donde JVM tiene ventaja

    Cualquiera puede demostrar una respuesta. Un producto, en cambio, debe resistir una auditoría. Estos son los aspectos que deben abordarse:

    • Anclaje y rechazos. Limitar el modelo al contexto recuperado e incluir citas. Cuando las puntuaciones de similitud estén por debajo de un umbral, la respuesta debe ser “eso no está en la base de conocimientos” y no una conjetura. En finanzas, operaciones y salud, un error cometido con confianza cuesta más que un rechazo directo.
    • Arrendamiento y eliminación de datos sensibles. Filtrar los vectores por arrendatario y eliminar secretos de las solicitudes. Mantener números de tarjetas, números de cuenta y datos de salud fuera de los registros brutos de las solicitudes. Si la depuración exige registrarlos, tokenizarlos primero y conservarlos según las reglas de retención del sistema original.
    • Presupuestos para costos y latencia. Los tokens cuestan dinero, por lo que se deben registrar los tokens de entrada, los tokens de salida, el tiempo de recuperación y el tiempo del modelo. Establecer un límite máximo de tokens en cada llamada, almacenar en caché los embeddings de documentos que se repiten y enviar la clasificación o enrutamiento a un modelo más pequeño, utilizando uno mayor solo cuando sea necesario.
  • Tiempo de espera e aislamiento. Una llamada al modelo representa una operación de E/S remota con un tiempo de ejecución prolongado. Los grupos de hilos limitados, los interruptores de circuito y rutas alternativas (búsqueda por palabras clave o cola humana) impiden que una interrupción en el modelo consuma todos los hilos de Tomcat o Netty y afecte negativamente al proceso de pago.
  • Evaluación. Un prompt no puede someterse a pruebas unitarias como lo haría un cálculo fiscal, pero un conjunto fijo de treinta preguntas con respuestas conocidas puede detectar errores en la precisión numérica durante el proceso de desarrollo. También es necesario verificar la recuperación de puntuaciones en los sistemas RAG, comprobando si el fragmento correspondiente realmente se incluyó en el prompt. Muchos de los supuestos problemas de calidad del modelo son en realidad errores en la recuperación de información.
  • Revisión humana. En el software empresarial, la característica de IA más valiosa suele ser una versión preliminar y no un chatbot: una nota sugerida para un caso, una razón predefinida para una excepción o un resumen de un extenso informe de 40 páginas. Es necesario mantener a una persona en la etapa de aprobación hasta que los errores dejen de ser un problema.
  • Todo esto es algo típico de Spring: envolver una llamada remota, etiquetar una métrica, rechazar solicitudes no autenticadas. El LLM es una nueva dependencia con un SLA peor, por lo que hay que gestionarlo como tal.

    Dónde es cierta la frase “Java es el rey”

    Java es un punto de partida mejor cuando el sistema de registro ya funciona en la JVM, cuando la función de IA debe compartir identidad, tenencia y auditoría con APIs existentes, cuando necesita llamar a servicios internos en Java como herramientas, cuando el cumplimiento normativo no permite usar una capa de Python oculta, y cuando las personas de soporte técnico a las 2 a.m. ya conocen Spring Boot.

    Python sigue siendo la opción preferida cuando se está entrenando o ajustando modelos, cuando se necesita una biblioteca de investigación la misma semana en que se publica, o cuando el modelo en sí mismo es el producto y no solo una función dentro de una aplicación más grande.

    Eso son tareas separadas, y durante dos años la industria actuó como si no lo fueran. El resultado fue una avalancha de arquitecturas que incluían un componente auxiliar en Python, con la esperanza de que sus contratos permanecieran estables. El patrón que parece interesante para 2026 es mixto: Python, o un laboratorio de modelos alojado, se encarga del entrenamiento y la evaluación; Java sirve para el servicio, la búsqueda vectorial funciona junto a los datos operativos; el modelo proviene de un proveedor y la lógica del dominio queda en tus manos.

    Un primer proyecto sensato

    No comiences con un chatbot para toda la empresa sin límites. Elige un conjunto de contenido específico y valioso, además de una pregunta cuya respuesta pueda puntuarse. Algunas opciones efectivas:

    • Preguntas y respuestas tipo manual de operaciones para ingenieros de soporte, vinculadas a la página original
    • Un asistente de políticas que cita la cláusula exacta
    • Preguntas y respuestas sobre una factura o estado de cuenta que el usuario acaba de subir
  • Los resúmenes de los tickets se escriben en el registro del caso, no en un canal de chat separado
  • Póngalo detrás de una API autenticada que ya posee, registre cada consulta, muestre las citaciones en la interfaz de usuario, agregue un interruptor de apagado de configuración y averigüe el costo por solicitud antes de ampliar el corpus. El primer proyecto enseña la división en fragmentos, los metadatos, la evaluación y el control de cambios en los prompts; esas habilidades son transferibles, pero no la marca del framework.

    El entorno de ejecución en el que ya confía

    “Java es el nuevo rey de la IA” funciona como titular, pero falla como tesis. Java no ganó en el campo del aprendizaje automático; simplemente llevó la IA aplicada a la plataforma que ya alberga los sistemas de transacciones del mundo.

    Un ingeniero de Spring Boot no necesita permiso de nadie para trabajar aquí, ni tampoco un título en ciencias de datos. Lo que se requiere es un proveedor de modelos, un modelo de embedding, un índice vectorial y la misma atención operativa que se aplica a los pagos y las comunicaciones. Python sigue siendo la herramienta principal para entrenar los modelos del laboratorio. Java se está convirtiendo en el líder en el camino desde el laboratorio hasta los registros contables, donde las respuestas necesitan fundamentación, las llamadas a herramientas requieren autorización y cada factura necesita una explicación. Para la mayoría de los equipos, ese es el único reconocimiento que realmente importa.

    Si un servicio de Spring Boot ya controla la identidad, el dinero y el historial de auditoría, no hay razón para esperar a usar un componente adicional. Elige este mes un conjunto de datos específico, coloca ChatClient delante de pgvector y exige que el modelo proporcione referencias claras.

    Lecturas relacionadas

  • Arquitectura de Servicio de Modelos: Por Qué la API Es Solo la Puerta de Entrada — Una guía sobre la plataforma que está detrás de un punto final de inferencia: enrutamiento, escalado, versionado, observabilidad, seguridad y cómo llamar a modelos servidos desde Spring AI o LangChain4j.
  • Spring AI vs LangChain4j: Configuración, Primer Punto Final y Estilo de Diseño — Compare Spring AI y LangChain4j en términos de arquitectura, iniciadores de Spring Boot, configuración y un primer punto final de chat REST, y descubra qué estilo se adapta mejor a su equipo.
  • Spring AI RAG con un almacén de vectores en la JVM: Dejar de usar Qdrant y Docker — Sustituir Qdrant por la biblioteca Vectors en el mismo proceso dentro de una aplicación Spring AI RAG: dependencia, flag de JVM, configuración de persistencia y las ventajas e inconvenientes de ejecutarse dentro de la JVM.
  • Diagnosticar fallos en las construcciones CI con reglas, RAG y un LLM local — Un sistema en Java para el análisis de fallos en CI que analiza los registros de forma determinista, obtiene notas de solución de problemas desde PGVector con Ollama y luego pide a un LLM que razone.