$npx -y skills add giuseppe-trisciuoglio/developer-kit --skill langchain4j-rag-implementation-patternsProvides Retrieval-Augmented Generation (RAG) implementation patterns with LangChain4j for Java. Generates document ingestion pipelines, embedding stores, vector search, and semantic search capabilities. Use when building chat-with-documents systems, document Q&A over PDFs or tex
| 1 | # LangChain4j RAG Implementation Patterns |
| 2 | |
| 3 | ## Overview |
| 4 | |
| 5 | Implements RAG systems with LangChain4j: document ingestion pipelines, embedding stores, and vector search for chat-with-documents and knowledge-enhanced AI applications. |
| 6 | |
| 7 | ## When to Use This Skill |
| 8 | |
| 9 | - Building chat-with-documents systems or document Q&A over PDFs, text files, or web pages |
| 10 | - Creating AI assistants with access to company knowledge bases or external sources |
| 11 | - Implementing semantic search or hybrid search over document repositories |
| 12 | - Building domain-specific AI with curated knowledge and source attribution |
| 13 | |
| 14 | ## Instructions |
| 15 | |
| 16 | ### Initialize RAG Project |
| 17 | |
| 18 | Create a new Spring Boot project with required dependencies: |
| 19 | |
| 20 | **pom.xml**: |
| 21 | ```xml |
| 22 | <dependency> |
| 23 | <groupId>dev.langchain4j</groupId> |
| 24 | <artifactId>langchain4j-spring-boot-starter</artifactId> |
| 25 | <version>1.8.0</version> |
| 26 | </dependency> |
| 27 | <dependency> |
| 28 | <groupId>dev.langchain4j</groupId> |
| 29 | <artifactId>langchain4j-open-ai</artifactId> |
| 30 | <version>1.8.0</version> |
| 31 | </dependency> |
| 32 | ``` |
| 33 | |
| 34 | ### Setup Document Ingestion |
| 35 | |
| 36 | Configure document loading and processing with validation: |
| 37 | |
| 38 | **Validation Checkpoint**: After ingestion, verify embedding count matches segment count and test retrieval with a sample query. |
| 39 | |
| 40 | ```java |
| 41 | @Configuration |
| 42 | public class RAGConfiguration { |
| 43 | |
| 44 | @Bean |
| 45 | public EmbeddingModel embeddingModel() { |
| 46 | return OpenAiEmbeddingModel.builder() |
| 47 | .apiKey(System.getenv("OPENAI_API_KEY")) |
| 48 | .modelName("text-embedding-3-small") |
| 49 | .build(); |
| 50 | } |
| 51 | |
| 52 | @Bean |
| 53 | public EmbeddingStore<TextSegment> embeddingStore() { |
| 54 | return new InMemoryEmbeddingStore<>(); |
| 55 | } |
| 56 | } |
| 57 | ``` |
| 58 | |
| 59 | Create document ingestion service: |
| 60 | |
| 61 | ```java |
| 62 | @Service |
| 63 | @RequiredArgsConstructor |
| 64 | public class DocumentIngestionService { |
| 65 | |
| 66 | private final EmbeddingModel embeddingModel; |
| 67 | private final EmbeddingStore<TextSegment> embeddingStore; |
| 68 | |
| 69 | public void ingestDocument(String filePath, Map<String, Object> metadata) { |
| 70 | Document document = FileSystemDocumentLoader.loadDocument(filePath); |
| 71 | document.metadata().putAll(metadata); |
| 72 | |
| 73 | DocumentSplitter splitter = DocumentSplitters.recursive( |
| 74 | 500, 50, new OpenAiTokenCountEstimator("text-embedding-3-small") |
| 75 | ); |
| 76 | |
| 77 | List<TextSegment> segments = splitter.split(document); |
| 78 | List<Embedding> embeddings = embeddingModel.embedAll(segments).content(); |
| 79 | embeddingStore.addAll(embeddings, segments); |
| 80 | |
| 81 | // Validation: verify embedding count matches segments |
| 82 | if (embeddings.size() != segments.size()) { |
| 83 | throw new IllegalStateException("Embedding count mismatch: expected " + segments.size() + ", got " + embeddings.size()); |
| 84 | } |
| 85 | } |
| 86 | |
| 87 | public boolean validateIngestion(String testQuery) { |
| 88 | // Validation: test retrieval with sample query |
| 89 | Embedding queryEmbedding = embeddingModel.embed(testQuery).content(); |
| 90 | List<EmbeddingMatch<TextSegment>> results = embeddingStore.search( |
| 91 | EmbeddingSearchRequest.builder() |
| 92 | .queryEmbedding(queryEmbedding) |
| 93 | .maxResults(1) |
| 94 | .build() |
| 95 | ).matches(); |
| 96 | return !results.isEmpty(); |
| 97 | } |
| 98 | } |
| 99 | ``` |
| 100 | |
| 101 | ### Configure Content Retrieval |
| 102 | |
| 103 | Setup content retrieval with filtering: |
| 104 | |
| 105 | **Validation Checkpoint**: After configuration, test retrieval with a known query to verify embeddings are searchable. |
| 106 | |
| 107 | ```java |
| 108 | @Configuration |
| 109 | public class ContentRetrieverConfiguration { |
| 110 | |
| 111 | @Bean |
| 112 | public ContentRetriever contentRetriever( |
| 113 | EmbeddingStore<TextSegment> embeddingStore, |
| 114 | EmbeddingModel embeddingModel) { |
| 115 | |
| 116 | return EmbeddingStoreContentRetriever.builder() |
| 117 | .embeddingStore(embeddingStore) |
| 118 | .embeddingModel(embeddingModel) |
| 119 | .maxResults(5) |
| 120 | .minScore(0.7) |
| 121 | .build(); |
| 122 | } |
| 123 | } |
| 124 | ``` |
| 125 | |
| 126 | ### Create RAG-Enabled AI Service |
| 127 | |
| 128 | Define AI service with context retrieval: |
| 129 | |
| 130 | ```java |
| 131 | interface KnowledgeAssistant { |
| 132 | @SystemMessage(""" |
| 133 | You are a knowledgeable assistant with access to a comprehensive knowledge base. |
| 134 | |
| 135 | When answering questions: |
| 136 | 1. Use the provided context from the knowledge base |
| 137 | 2. If information is not in the context, clearly state this |
| 138 | 3. Provide accurate, helpful responses |
| 139 | 4. When possible, reference specific sources |
| 140 | 5. If the context is insufficient, ask for clarification |
| 141 | """) |
| 142 | String answerQuestion(String question); |
| 143 | } |
| 144 | |
| 145 | @Service |