กระบวนการสร้างแบบเสริมด้วยการดึงข้อมูล
ประกอบกระบวนการ RAG ที่ทำให้คำตอบของโมเดลอ้างอิงบริบทจากเอกสารที่ดึงมา
กระบวนการสร้างแบบเสริมด้วยการดึงข้อมูล เป็นบทเรียน Spring Boot 4 Complete Guide ฟรีบน CoddyKit นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Spring Boot 4 Complete Guide และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Spring Boot 4 Complete Guide มีบทเรียนทั้งหมด 4 บทเรียน
บางส่วนของบทเรียนนี้ยังไม่ได้รับการแปล และแสดงเป็นภาษาอังกฤษ
Why RAG?
Retrieval-Augmented Generation (RAG) grounds an LLM's answers in your own documents instead of relying solely on what the model memorized during training.
- Fresh & private data — answer questions about internal docs the model never saw.
- Less hallucination — the model cites retrieved context rather than inventing facts.
- Cheaper than fine-tuning — you update a vector store, not model weights.
A Spring AI RAG pipeline has two phases: an ingestion phase (read → split → embed → store) and a query phase (embed question → retrieve → augment prompt → generate).
The Pipeline at a Glance
Spring AI gives you composable building blocks for both phases. The core types you will assemble are:
DocumentReader— loads raw sources (PDF, Markdown, JSON, web pages).DocumentTransformer— splits documents into chunks (e.g.TokenTextSplitter).EmbeddingModel— turns text into vectors.VectorStore— stores and similarity-searches those vectors.ChatClientwith a RAG advisor — wires retrieval into the prompt automatically.
The first three feed ingestion; the last two power querying.
Ingestion: Read and Split
During ingestion you read source files and split them into chunks small enough to fit the model's context window while staying semantically coherent. TokenTextSplitter chunks by token count with overlap so meaning isn't cut mid-sentence.
Below, a Markdown file is read and split into ~800-token chunks before storage.
@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: Text to Vectors
An embedding is a dense vector that captures the meaning of text. Two passages about the same topic land close together in vector space, which is what makes similarity search work.
Spring AI auto-configures an EmbeddingModel based on your starter (OpenAI, Azure, Ollama, etc.). You rarely call it directly — the VectorStore uses it internally — but you can:
@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();
}
}Configuring a VectorStore
The VectorStore persists embeddings and runs similarity searches. Spring AI ships adapters for PgVector, Redis, Chroma, Qdrant, Milvus, and a simple in-memory store.
With the spring-ai-starter-vector-store-pgvector dependency, a bean is auto-configured from properties — no manual wiring needed:
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: secretQuerying: Similarity Search
At query time you turn the user's question into a vector and ask the store for the nearest chunks. A SearchRequest controls how many results (topK) and a minimum similarityThreshold to filter out weak matches.
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;
}Augmenting the Prompt Manually
Before reaching for advisors, it helps to see the mechanic. RAG simply stuffs the retrieved text into the prompt and instructs the model to answer only from it. This is the "augment" step:
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();
}The QuestionAnswerAdvisor
Spring AI packages that manual pattern as the QuestionAnswerAdvisor. You attach it to a ChatClient and it transparently runs the similarity search and injects context for every call.
This is the idiomatic, declarative way to do RAG in 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();
}
}Per-Request Retrieval Tuning
Defaults are convenient, but real apps tune retrieval per request — a focused FAQ may need topK=2, a broad research query topK=8. Pass an advisor at call time and override its SearchRequest, plus metadata filters to scope to a tenant or document set:
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();
}Modular RAG with RetrievalAugmentationAdvisor
For advanced pipelines, Spring AI 1.0 offers the Modular RAG API via RetrievalAugmentationAdvisor. It exposes each stage as a swappable component:
QueryTransformer— rewrite, compress, or translate the query.DocumentRetriever— the source of chunks (e.g.VectorStoreDocumentRetriever).QueryAugmenter— control how context is merged and how empty-context is handled.
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();Guarding Against Empty Context
A subtle RAG failure: when retrieval finds nothing relevant, a naive prompt lets the model fall back to its training data and hallucinate. The ContextualQueryAugmenter lets you decide that policy explicitly.
Set allowEmptyContext(false) to force a graceful "I don't have information on that" instead of a confident guess:
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.Quick Check
You build a RAG assistant. When a user asks something outside your knowledge base, similarity search returns no chunks above the threshold, yet the model still answers confidently with made-up facts. Which change best fixes this?
Recap
You assembled a complete RAG pipeline in Spring AI:
- Ingestion —
DocumentReader→TokenTextSplitter→EmbeddingModel→VectorStore.add(). - Query — embed the question,
similaritySearchwithtopKandsimilarityThreshold, then augment the prompt. - Declarative RAG —
QuestionAnswerAdvisorwires retrieval into aChatClientautomatically; tune it per request with customSearchRequestand metadata filters. - Modular RAG —
RetrievalAugmentationAdvisorwith query transformers, retrievers, and augmenters for advanced control. - Safety —
ContextualQueryAugmenter.allowEmptyContext(false)prevents hallucination when nothing relevant is retrieved.
Grounding model output in retrieved context is the single most effective way to make LLM features trustworthy.
คำถามที่พบบ่อย
บทเรียน “กระบวนการสร้างแบบเสริมด้วยการดึงข้อมูล” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “กระบวนการสร้างแบบเสริมด้วยการดึงข้อมูล” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Spring Boot 4 Complete Guide ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Spring Boot 4 Complete Guide มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “กระบวนการสร้างแบบเสริมด้วยการดึงข้อมูล”
ประกอบกระบวนการ RAG ที่ทำให้คำตอบของโมเดลอ้างอิงบริบทจากเอกสารที่ดึงมา คุณปฏิบัติ Spring Boot 4 Complete Guide ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Spring Boot 4 Complete Guide หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Spring Boot 4 Complete Guide บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน
บทเรียน “กระบวนการสร้างแบบเสริมด้วยการดึงข้อมูล” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Spring Boot 4 Complete Guide นี้ได้ไหม
ได้ บทเรียน Spring Boot 4 Complete Guide ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- ChatClient พรอมต์ และผลลัพธ์แบบมีโครงสร้าง
- เวกเตอร์ฝังตัวและการดึงข้อมูลจากคลังเวกเตอร์
- กระบวนการสร้างแบบเสริมด้วยการดึงข้อมูล
- การเรียกใช้เครื่องมือและที่ปรึกษาของเอเจนต์