Spring Boot 4 – komplett guide · Lektion

Pipelines för Retrieval-Augmented Generation

Sätt samman RAG-flöden som förankrar modellsvar i kontext från hämtade dokument.

Lektion 3 av 413 steg

Pipelines för Retrieval-Augmented Generation är en gratis lektion i Spring Boot 4 – komplett guide på CoddyKit. Detta är lektion 3 av 4. Du kan läsa vilka 3 lektioner som helst i den här lärvägen kostnadsfritt i sin helhet – därefter låser CoddyKit PRO upp alla lektioner, plus praktisk övning med en inbyggd kodredigerare och en AI-lärare dygnet runt. Den ingår i lärvägen för Spring Boot 4 – komplett guide, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i Spring Boot 4 – komplett guide innehåller totalt 4 lektioner.

Varför RAG?

Retrieval-Augmented Generation (RAG) förankrar en LLM:s svar i era egna dokument i stället för att enbart förlita sig på det modellen memorerade under träningen.

  • Aktuella och privata data — svara på frågor om interna dokument som modellen aldrig har sett.
  • Mindre hallucinationer — modellen hänvisar till hämtad kontext i stället för att hitta på fakta.
  • Billigare än finjustering — ni uppdaterar ett vektorlager, inte modellvikter.

En RAG-pipeline i Spring AI har två faser: en inläsningsfas (läs → dela upp → skapa embeddings → lagra) och en frågefas (skapa embedding av frågan → hämta → utöka prompten → generera).

Pipelinen i korthet

Spring AI ger er komponerbara byggblock för båda faserna. Kärntyperna ni sätter ihop är:

  • DocumentReader — läser in råkällor (PDF, Markdown, JSON, webbsidor).
  • DocumentTransformer — delar upp dokument i delar (till exempel TokenTextSplitter).
  • EmbeddingModel — omvandlar text till vektorer.
  • VectorStore — lagrar vektorerna och utför likhetssökningar.
  • ChatClient med en RAG-advisor — kopplar automatiskt in hämtningen i prompten.

De tre första används vid inläsning; de två sista används vid frågor.

Inläsning: läs och dela upp

Under inläsningen läser ni källfiler och delar upp dem i delar som är tillräckligt små för att rymmas i modellens kontextfönster, samtidigt som den semantiska sammanhållningen bevaras. TokenTextSplitter delar upp efter tokenantal med överlapp så att betydelsen inte bryts mitt i en mening.

Nedan läses en Markdown-fil och delas upp i delar på cirka 800 token före lagring.

@Component
class DocumentIngestor {

    private final VectorStore vectorStore;

    DocumentIngestor(VectorStore vectorStore) {
        this.vectorStore = vectorStore;
    }

    void ingest(Resource markdown) {
        var reader = new TextReader(markdown);
        List<Document> raw = reader.get();

        var splitter = new TokenTextSplitter(800, 350, 5, 10000, true);
        List<Document> chunks = splitter.apply(raw);

        vectorStore.add(chunks);
    }
}

Embeddings: från text till vektorer

En embedding är en tät vektor som fångar textens betydelse. Två textavsnitt om samma ämne hamnar nära varandra i vektorrummet, vilket är det som gör likhetssökning möjlig.

Spring AI autokonfigurerar en EmbeddingModel baserat på ert starterpaket (OpenAI, Azure, Ollama med flera). Ni anropar den sällan direkt — VectorStore använder den internt — men ni kan:

@Service
class EmbeddingDemo {

    private final EmbeddingModel embeddingModel;

    EmbeddingDemo(EmbeddingModel embeddingModel) {
        this.embeddingModel = embeddingModel;
    }

    float[] embed(String text) {
        return embeddingModel.embed(text);
    }

    int dimensions() {
        return embeddingModel.dimensions();
    }
}

Konfigurera en VectorStore

VectorStore lagrar embeddings och utför likhetssökningar. Spring AI levereras med adaptrar för PgVector, Redis, Chroma, Qdrant, Milvus och ett enkelt minnesbaserat lager.

Med beroendet spring-ai-starter-vector-store-pgvector autokonfigureras en bean från egenskaperna — ingen manuell konfigurering behövs:

spring:
  ai:
    vectorstore:
      pgvector:
        initialize-schema: true
        index-type: HNSW
        distance-type: COSINE_DISTANCE
        dimensions: 1536
  datasource:
    url: jdbc:postgresql://localhost:5432/ragdb
    username: rag
    password: secret

Fråga: likhetssökning

När en fråga ställs omvandlar ni användarens fråga till en vektor och ber lagret om de närmaste textbitarna. En SearchRequest styr hur många resultat (topK) som ska returneras samt ett lägsta similarityThreshold för att filtrera bort svaga träffar.

List<Document> retrieve(VectorStore store, String question) {
    var request = SearchRequest.builder()
            .query(question)
            .topK(4)
            .similarityThreshold(0.7)
            .build();

    List<Document> hits = store.similaritySearch(request);
    return hits;
}

Utöka prompten manuellt

Innan ni börjar använda advisors är det bra att förstå mekanismen. RAG stoppar helt enkelt in den hämtade texten i prompten och instruerar modellen att endast svara utifrån den. Detta är steget "augment":

String answer(ChatClient chat, VectorStore store, String question) {
    List<Document> docs = store.similaritySearch(
            SearchRequest.builder().query(question).topK(4).build());

    String context = docs.stream()
            .map(Document::getText)
            .collect(Collectors.joining("\n---\n"));

    return chat.prompt()
            .system("Answer using ONLY the context. If unknown, say you don't know.")
            .user(u -> u.text("Context:\n{ctx}\n\nQuestion: {q}")
                        .param("ctx", context)
                        .param("q", question))
            .call()
            .content();
}

QuestionAnswerAdvisor

Spring AI paketerar detta manuella mönster som QuestionAnswerAdvisor. Ni kopplar den till en ChatClient, varpå den transparent utför likhetssökningen och injicerar kontext vid varje anrop.

Detta är det idiomatiska, deklarativa sättet att använda RAG i Spring Boot 4:

@Service
class RagAssistant {

    private final ChatClient chatClient;

    RagAssistant(ChatClient.Builder builder, VectorStore vectorStore) {
        this.chatClient = builder
                .defaultAdvisors(new QuestionAnswerAdvisor(vectorStore))
                .build();
    }

    String ask(String question) {
        return chatClient.prompt()
                .user(question)
                .call()
                .content();
    }
}

Finjustera hämtning per förfrågan

Standardvärden är praktiska, men verkliga applikationer finjusterar hämtningen för varje förfrågan — en fokuserad FAQ kan behöva topK=2, medan en bred forskningsfråga kan behöva topK=8. Skicka med en advisor vid anropstillfället och åsidosätt dess SearchRequest, samt metadatafilter för att begränsa sökningen till en tenant eller en uppsättning dokument:

String ask(ChatClient chatClient, VectorStore store, String q, String tenant) {
    var advisor = QuestionAnswerAdvisor.builder(store)
            .searchRequest(SearchRequest.builder()
                    .topK(6)
                    .similarityThreshold(0.75)
                    .filterExpression("tenant == '" + tenant + "'")
                    .build())
            .build();

    return chatClient.prompt()
            .advisors(advisor)
            .user(q)
            .call()
            .content();
}

Modulär RAG med RetrievalAugmentationAdvisor

För avancerade pipelines erbjuder Spring AI 1.0 API:t Modular RAG via RetrievalAugmentationAdvisor. Det exponerar varje steg som en utbytbar komponent:

  • QueryTransformer — skriver om, komprimerar eller översätter frågan.
  • DocumentRetriever — källan till textbitarna (till exempel VectorStoreDocumentRetriever).
  • QueryAugmenter — styr hur kontext sammanfogas och hur tom kontext hanteras.
var retriever = VectorStoreDocumentRetriever.builder()
        .vectorStore(vectorStore)
        .similarityThreshold(0.72)
        .topK(5)
        .build();

var ragAdvisor = RetrievalAugmentationAdvisor.builder()
        .queryTransformers(RewriteQueryTransformer.builder()
                .chatClientBuilder(chatClientBuilder)
                .build())
        .documentRetriever(retriever)
        .build();

String answer = chatClient.prompt()
        .advisors(ragAdvisor)
        .user(question)
        .call()
        .content();

Skydda mot tom kontext

Ett subtilt RAG-fel uppstår när hämtningen inte hittar något relevant: en naiv prompt låter modellen falla tillbaka på sina träningsdata och hitta på information. Med ContextualQueryAugmenter kan ni uttryckligen bestämma denna policy.

Ange allowEmptyContext(false) för att tvinga fram ett artigt svar som "Jag har ingen information om det" i stället för en självsäker gissning:

var augmenter = ContextualQueryAugmenter.builder()
        .allowEmptyContext(false)
        .build();

var ragAdvisor = RetrievalAugmentationAdvisor.builder()
        .documentRetriever(retriever)
        .queryAugmenter(augmenter)
        .build();

// With no matching documents, the model returns a safe
// "no answer available" response instead of fabricating one.

Snabbtest

Ni bygger en RAG-assistent. När en användare frågar om något som ligger utanför er kunskapsbas returnerar likhetssökningen inga textbitar över tröskelvärdet, men modellen svarar ändå självsäkert med påhittade fakta. Vilken ändring löser detta bäst?

Sammanfattning

Ni har satt ihop en komplett RAG-pipeline i Spring AI:

  • Inläsning — DocumentReader → TokenTextSplitter → EmbeddingModel → VectorStore.add().
  • Fråga — bädda in frågan, använd similaritySearch med topK och similarityThreshold, och utöka sedan prompten.
  • Deklarativ RAG — QuestionAnswerAdvisor kopplar automatiskt in hämtning i en ChatClient; finjustera den per förfrågan med en anpassad SearchRequest och metadatafilter.
  • Modulär RAG — RetrievalAugmentationAdvisor med frågetransformatorer, hämtare och utökare för avancerad kontroll.
  • Säkerhet — ContextualQueryAugmenter.allowEmptyContext(false) förhindrar hallucinationer när inget relevant hämtas.

Att förankra modellens utdata i hämtad kontext är det enskilt mest effektiva sättet att göra LLM-funktioner tillförlitliga.

Gratis att börja

Lär dig Java med en AI-lärare – gratis

Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.

Kurser
21
Lektioner
84

Vanliga frågor

Är lektionen ”Pipelines för Retrieval-Augmented Generation” gratis?

Ja – du kan läsa vilka 3 lektioner som helst i lärvägen Spring Boot 4 – komplett guide, inklusive ”Pipelines för Retrieval-Augmented Generation”, kostnadsfritt i sin helhet här på webben. Därefter låser CoddyKit PRO upp alla lektioner, plus interaktiv övning med en inbyggd kodredigerare och en AI-lärare dygnet runt. Kursen i Spring Boot 4 – komplett guide innehåller totalt 4 lektioner.

Vad lär jag mig i ”Pipelines för Retrieval-Augmented Generation”?

Sätt samman RAG-flöden som förankrar modellsvar i kontext från hämtade dokument. Ni övar på Spring Boot 4 – komplett guide med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.

Behöver jag någon erfarenhet för att börja lära mig Spring Boot 4 – komplett guide?

Du behöver inga förkunskaper. Utbildningen i Spring Boot 4 – komplett guide på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 3 av 4.

Hur lång tid tar lektionen ”Pipelines för Retrieval-Augmented Generation”?

De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.

Kan jag skriva och köra kod i den här Spring Boot 4 – komplett guide-lektionen?

Ja. Varje Spring Boot 4 – komplett guide-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.

Alla lektioner i den här kursen

  1. ChatClient, promptar och strukturerade utdata
  2. Embeddings och hämtning från vektorlagring
  3. Pipelines för Retrieval-Augmented Generation
  4. Verktygsanrop och agentrådgivare
← Tillbaka till Spring Boot 4 – komplett guide