Este repositorio implementa el patrón Multi-Query Expansion, utilizando Spring Boot 4 y Spring AI 2.0.
Multi-Query Expansion es una técnica avanzada de RAG (Retrieval-Augmented Generation) que mejora la robustez de la recuperación de información. En lugar de confiar en una sola versión de la pregunta del usuario, el sistema utiliza un LLM para generar múltiples variaciones semánticas de la misma consulta y recupera documentos para todas ellas, asegurando una cobertura más amplia del espacio de búsqueda.
La intuición detrás de Multi-Query es que los embeddings capturan cierta cercanía semántica, pero una pregunta puede estar fraseada de muchas formas. Al generar variaciones, superamos problemas de:
- Terminología ambigua.
- Falta de palabras clave exactas.
- Diferentes "ángulos" o perspectivas de investigación sobre el mismo tema.
Flujo Clásico (Naive RAG):
Pregunta ➡️ Búsqueda Vectorial ➡️ Documentos (Si fallas el ángulo, pierdes documentos).
Flujo Multi-Query:
Pregunta ➡️ LLM (Generar 5 Variaciones) ➡️ Lista de Consultas ➡️ Búsqueda Vectorial Paralela ➡️ Deduplicación (Set) ➡️ Documentos Relevantes
sequenceDiagram
participant User as Usuario
participant API as RagController
participant Service as RagService
participant Expander as QueryExpansionService
participant LLM as Modelo IA
participant VS as VectorStore (PgVector)
User->>API: GET /api/rag?question=...
API->>Service: retrieveAndGenerate(query)
rect rgb(240, 240, 255)
note right of Service: Paso 1: Expansión de Consultas
Service->>Expander: expandQuery(originalQuery)
Expander->>LLM: "Genera 5 versiones de esta pregunta..."
LLM-->>Expander: [Q1, Q2, Q3, Q4, Q5]
end
rect rgb(240, 255, 240)
note right of Service: Paso 2: Recuperación Multidimensional
loop Para cada Consulta (Q1...Q5)
Service->>VS: similaritySearch(Q_i)
VS-->>Service: Docs_i
end
end
rect rgb(255, 248, 240)
note right of Service: Paso 3: Agregación
Service->>Service: Unique(Docs_1 + ... + Docs_5)
end
rect rgb(255, 255, 240)
note right of Service: Paso 4: Generación Final
Service->>LLM: Prompt RAG Final (Docs Únicos + Pregunta)
LLM-->>Service: Respuesta Veraz y Fundamentada
end
Service-->>User: Respuesta Final
src/main/java/com/example/demo/rag/IngestionService.java:- Carga el PDF (
report.pdf). - Clave: Divide el texto en chunks pequeños (~300 chars) para maximizar la precisión semántica.
- Carga el PDF (
src/main/java/com/example/demo/rag/QueryExpansionService.java:- Utiliza un Prompt (
multi-query.st) para generar 5 preguntas alternativas que ayuden a encontrar la información desde diferentes ángulos.
- Utiliza un Prompt (
src/main/java/com/example/demo/rag/RagService.java:- Orquesta el algoritmo: Expansión -> Búsqueda Múltiple -> Deduplicación -> Respuesta Final.
Dentro del directorio src/main/resources/data/ se encuentra un archivo PDF (report.pdf) que actúa como la fuente de verdad ("Ground Truth") para este proyecto.
- Propósito: Demostrar cómo el sistema puede recuperar información precisa utilizando variaciones de preguntas y superando la ambigüedad.
- Personalización: Puedes reemplazar este archivo con tu propio PDF para probar el sistema con tus propios datos.
Para que el sistema RAG funcione, es necesario contar con una base de datos vectorial. Este proyecto utiliza PostgreSQL con la extensión pgvector.
graph TD
subgraph Host[Tu Máquina / Codespaces]
App["Spring Boot App<br/>(Puerto 8080)"]
Script[demo_rag.sh]
end
subgraph Docker[Docker Container]
PG[(PostgreSQL 16 <br/>+ pgvector)]
end
Script -->|1. Inicia| PG
Script -->|2. Compila y Ejecuta| App
App -->|3. Ingesta Vectores| PG
App -->|4. Consulta Vectores| PG
style PG fill:#336791,stroke:#fff,stroke-width:2px,color:#fff
style App fill:#6db33f,stroke:#fff,stroke-width:2px,color:#fff
Pasos para el entorno de Docker:
- El script
start-postgres.sh(invocado pordemo_rag.sh) se encarga de levantar un contenedor Docker con la imagenpgvector/pgvector:pg16. - La aplicación Spring Boot se conecta a este contenedor en el puerto 5432 para almacenar y recuperar los embeddings.
Se ha incluido un script automatizado para probar el flujo completo.
-
Requisitos:
- Docker corriendo (para la BD PgVector).
- Java 21 instalado.
- Un archivo PDF en
src/main/resources/data/report.pdf(Por defecto incluido).
-
Ejecución Rápida:
chmod +x demo_rag.sh ./demo_rag.sh
Este script realizará lo siguiente:
- Verificará que la BD esté arriba.
- Compilará y ejecutará la aplicación en segundo plano.
- Disparará la Ingesta (
/api/ingest). - Realizará una prueba RAG Multi-Query sobre ingresos financieros (
/api/rag). - Mostrará los resultados en consola.
Este proyecto utiliza el stack tecnológico más reciente del ecosistema Spring:
- Java: 21 (LTS)
- Spring Boot: 4.0.1
- Spring AI: 2.0.0-M1 (Milestone 1)
Nota: Al utilizar una versión
Milestone(M1), es necesario configurar repositorios adicionales de Spring (spring-milestones) en elpom.xml, ya que estas versiones no están en Maven Central estándar.
Spring AI ofrece una API portable y unificada para interactuar con diversos modelos de IA. Las capacidades actuales incluyen:
- Chat Models: Interfaz unificada para OpenAI, Azure OpenAI, Amazon Bedrock, Google Vertex AI, Ollama, Anthropic Claude, etc.
- Image Generation: Generación de imágenes (DALL-E, Stability AI).
- Audio: Transcripción (Speech-to-Text) y Texto a Voz (Text-to-Speech) usando modelos como Whisper.
- Embeddings: Conversión de texto a vectores para búsqueda semántica.
- Vector Stores: Abstracción para bases de datos vectoriales. Actualmente soporta:
- PGVector (PostgreSQL)
- Redis
- Neo4j
- MongoDB Atlas
- Chroma, Weaviate, Milvus, Qdrant, etc.
- Document Readers: Utilidades para leer PDFs, JSON, Texto, Markdown.
- Document Transformers: División de documentos (TokenTextSplitter) para indexación.
- Function Calling: Permite a los modelos de IA invocar funciones Java propias de forma transparente.
- Chat Memory: Gestión del historial de conversación para mantener el contexto.
- Evaluation: Framework para evaluar la calidad de las respuestas de la IA.
Para ejecutar este proyecto, necesitas configurar tu API Key en src/main/resources/application.properties:
spring.ai.openai.api-key=${OPENAI_API_KEY}O exportarla como variable de entorno:
export SPRING_AI_OPENAI_API_KEY=tu-clave-aquiEste proyecto es una plantilla técnica diseñada para construir sistemas de producción robustos en Java desde el inicio.
Este proyecto reconoce el valor inmenso de Python en ciencia de datos, mientras ofrece un estándar robusto para la IA empresarial en Java.
| Concepto | Enfoque Python / Data Science | Enfoque Java / Enterprise (Este Proyecto) |
|---|---|---|
| Prompting | F-strings (Rápido y flexible) | Templates versionados (Gobernable y escalable). |
| Salidas | Diccionarios dinámicos | Tipado Fuerte (Records) (Seguridad en compilación). |
| RAG | Experimentación en notebooks | ETL Robusto con Tika y DocumentReaders. |
| Orquestación | LangGraph | Spring AI Alibaba Graph / Temporal.io. |
- Fundamentos de Spring AI: Curso "Spring AI: Beginner to Guru".
- Ingeniería de Datos y RAG: Curso "Mastering Spring AI: Build AI with Java".
- Arquitectura Avanzada e Interoperabilidad: Curso "Build AI Apps with Spring AI... MCP, AI Testing".
- Teoría de Agentes: Curso "AI Agents in Java...".
Este repositorio incluye instrucciones especializadas para el agente, ubicadas en .github/instructions/springai.instructions.md.
Estas pautas aseguran que cualquier código generado por la IA respete la arquitectura de referencia:
- Enfoque Java-Nativo: Preferencia por tipado fuerte (Records, POJOs).
- Arquitectura Spring AI: Uso de
ChatClientfluente y abstracciones oficiales. - Calidad de Ingeniería: Integración de Testcontainers y Evaluators.