← Writing
AI & Generative AI

LLM Note 3

Data Mastery Series — Episode 48: RAG, RAG, and RAG

21 Feb 202533 min readLangChainRAGAI AgentDashboard
LLM Note · Part 3 of 5

LLM Note 3

Data Mastery Series — Episode 48: RAG, RAG, and RAG

Connect with me and follow our journey: Linkedin, Facebook


1) 4 เทคนิค RAG ขั้นสูง (Advanced RAG Algorithms)

(SOURCE)เนื้อหาใน Blog นี้มีภาพประกอบที่เข้าใจง่าย ลองเข้าไปดูนะครับ

RAG (Retrieval-Augmented Generation) เป็นเทคนิคที่ช่วยให้ LLM (Large Language Models) ดึงข้อมูลที่เกี่ยวข้องจากฐานข้อมูลก่อนนำไปใช้สร้างข้อความใหม่ โดยการพัฒนา RAG สามารถแบ่งออกเป็น 3 ส่วนหลัก ๆ ได้แก่:

  1. Pre-retrieval optimization (การปรับปรุงก่อนดึงข้อมูล): ปรับปรุงขั้นตอน ingestion เช่น การเลือกขนาด chunk ที่เหมาะสม, การเลือก embedding model ที่ดี และการจัดการ metadata
  2. Retrieval optimization (การปรับปรุงการดึงข้อมูล): ใช้วิธีปรับปรุงการดึงข้อมูลจาก vector database เช่น query expansion, self query และ hybrid search
  3. Post-retrieval optimization (การปรับปรุงหลังดึงข้อมูล): ปรับปรุงข้อมูลที่ดึงมาแล้ว เช่น reranking เพื่อให้ได้ข้อมูลที่เกี่ยวข้องมากที่สุด

Note: ใน Note 2 มี Technique ที่ 4 คือ Generation Techniques แต่บทความนี้ไม่ได้กล่าวถึง

ในบทความนี้ เน้นที่ Retrieval & Post-retrieval Optimization ผ่าน 4 เทคนิค:

1) Query Expansion (การขยายคำถาม)

Query Expansion เป็นเทคนิคที่ช่วยให้ระบบเข้าใจคำถามของผู้ใช้ได้ครอบคลุมมากขึ้น โดยการสร้างคำถามหลาย ๆ เวอร์ชันจากคำถามเดิม เพื่อช่วยลดข้อจำกัดของ similarity search

Example - Query Expansion

base_template.py

from abc import ABC, abstractmethod
from langchain.prompts import PromptTemplate
from pydantic import BaseModel

class BasePromptTemplate(ABC, BaseModel):
@abstractmethod
def create_template(self) -> PromptTemplate:
pass

query_expansion.py

class QueryExpansionTemplate(BasePromptTemplate):
prompt: str = """You are an AI language model assistant. Your task is to generate five
different versions of the given user question to retrieve relevant documents from a vector
database. By generating multiple perspectives on the user question, your goal is to help
the user overcome some of the limitations of the distance-based similarity search.
Provide these alternative questions seperated by newlines.
Original question: {question}"""

def create_template(self) -> PromptTemplate:  
    return PromptTemplate(template=self.prompt, input_variables=["question"], verbose=True)  

Note: คุณคือผู้ช่วย AI ที่เชี่ยวชาญด้านภาษา งานของคุณคือสร้างคำถาม 5 แบบ จากคำถามของผู้ใช้ เพื่อใช้ดึงข้อมูลที่เกี่ยวข้องจากฐานข้อมูลเวกเตอร์ โดยการสร้างมุมมองที่หลากหลายของคำถาม จะช่วยให้ผู้ใช้เอาชนะข้อจำกัดของการค้นหาแบบ similarity ได้ ให้แสดงคำถามทางเลือกโดยแยกแต่ละคำถามด้วยบรรทัดใหม่ คำถามเดิม: {question}

หมายเหตุ: โค้ดด้านบนใช้ LLM เพื่อสร้างคำถาม 5 แบบจากคำถามเดิม ช่วยให้การค้นหาครอบคลุมมากขึ้น

2) Self Query (การค้นหาด้วยตนเอง)

การ embed คำถามอย่างเดียว อาจจะไม่สามารถจับ metadata ที่เราต้องการได้ เช่น author ID, tag หรืออื่นๆ ซึ่งวิธีแก้คือ ใช้ LLM สกัด metadata จากคำถาม แล้วนำ metadata นั้นไปใช้ในการกรองข้อมูล

Example - Self Query

self_query.py

class SelfQueryTemplate(BasePromptTemplate):
prompt: str = """You are an AI language model assistant.
Your task is to extract information from a user question.
The required information that needs to be extracted is the user id.
Your response should consists of only the extracted id (e.g. 1345256),
nothing else.
User question: {question}"""

def create_template(self) -> PromptTemplate:  
    return PromptTemplate(  
        template=self.prompt, input_variables=["question"], verbose=True  
    )  

Note: คุณคือผู้ช่วย AI ที่เชี่ยวชาญด้านภาษา งานของคุณคือการสกัดข้อมูลจากคำถามของผู้ใช้ ข้อมูลที่ต้องการสกัดคือ user id คำตอบของคุณควรมีแค่ user id ที่สกัดได้เท่านั้น (เช่น 1345256) ไม่มีอย่างอื่น คำถามของผู้ใช้: {question}

หมายเหตุ: ใช้ LLM เพื่อสกัด user id จากคำถาม และใช้ข้อมูลนี้เป็น metadata filter

การค้นหาข้อมูลโดยใช้ Vector Search อย่างเดียวอาจไม่ดีพอสำหรับการค้นหาคำหลักที่เฉพาะเจาะจง ดังนั้นจึงต้องใช้เทคนิค Hybrid Search ซึ่งรวมการค้นหาแบบเวกเตอร์ (Vector Search) และการค้นหาแบบคำหลัก (Keyword Search) รวมถึงการใช้ Filter จาก metadata

หลักการทำงาน

  • Vector Search: ค้นหาโดยใช้ความหมายของคำ (semantic search)
  • Keyword Search: ค้นหาโดยใช้คำหลักที่ตรงกัน (exact match)
  • Filter: กรองผลลัพธ์โดยใช้ metadata ที่ได้จาก Self Query

Example - Hybrid & Filtered Vector Search

VectorRetriever: main retriever function

Query expansion chains wrapper

retriever.py

class VectorRetriever:
...
def retrieve_top_k(self, k: int) -> list:
generated_queries = self._query_expander.generate(self.query)
metadata_filter_value = self._metadata_extractor.generate(self.query)
with ThreadPoolExecutor() as executor:
search_tasks = [
executor.submit(
self._search_single_query,
query,
metadata_filter_value,
k
)
for query in generated_queries
]

    hits = [  
        task.result() for task in as_completed(search_tasks)  
    ]  
    hits = utils.flatten(hits)  
    return hits  

chains.py

class Chain:
@staticmethod
def get(llm, template: PromptTemplate, output_key: str):
return LLMChain(
llm=llm, prompt=template, output_key=output_key
)

class QueryExpansion:
@staticmethod
def generate_response(query: str) -> list[str]:
prompt = QueryExpansionTemplate().create_template()
model = ChatOpenAI(model=settings.OPENAI_MODEL_ID, temperature=0)
chain = Chain().get(
llm=model, output_key="expanded_queries", template=prompt
)
response = chain.invoke({"question": query})
result = response["expanded_queries"]
queries = result.strip().split("\n")
return queries

VectorRetriever: main search function

retriever.py

class VectorRetriever:
...
def _search_single_query(
self, generated_query: str, metadata_filter_value: str, k: int
):
assert k >= 3, "Using a k < 3, we can't query all the collections."
vectors = [
self._qdrant_client.search(
collection_name="vector_posts",
query_filter=models.Filter(
must=[
models.FieldCondition(
key="author_id",
match=models.MatchValue(
value=metadata_filter_value,
),
)
]
),
query_vector=self._embedder.encode(generated_query).tolist(),
limit=k // 3,
),
self._qdrant_client.search(
collection_name="vector_articles", ...
),
self._qdrant_client.search(
collection_name="vector_repositories", ...
),
]
return utils.flatten(vectors)

หมายเหตุ: ใช้ Query Expansion และ Self Query เพื่อสร้างคำถามที่หลากหลาย และกรองผลลัพธ์ด้วย metadata

4) Rerank (การจัดอันดับใหม่)

ข้อมูลที่ดึงมาอาจมีบางส่วนที่ไม่เกี่ยวข้อง ซึ่งอาจทำให้ LLM สับสน การใช้ Reranking Model จะช่วยจัดลำดับความสำคัญของข้อมูลให้เหมาะสมที่สุด

Example - Rerank

Rerank chain

reranking_template.py

class RerankingTemplate(BasePromptTemplate):
prompt: str = """You are an AI language model assistant.
Your task is to rerank passages related to a query
based on their relevance. The most relevant passages
should be put at the beginning.
You should only pick at max {k} passages.
The following are passages related to this query: {question}.
Passages: {passages}"""
def create_template(self) -> PromptTemplate:
return PromptTemplate(
template=self.prompt, input_variables=["question", "passages"]
)

reranking_chain.py

class Reranker:
@staticmethod
def generate(query: str, passages: str, k: int) -> list[str]:
chain = Chain().get(
llm=ChatOpenAI(model=settings.OPENAI_MODEL_ID),
template=RerankingTemplate().create_template(),
output_key="rerank",
)
response = chain.invoke(
{"question": query, "passages": passages, "k": k}
)
return response["rerank"]

Retriever: rerank step

retriever_rerank.py

class VectorRetriever:
...
def rerank(self, hits: list) -> list[str]:
content_list = [hit.payload["content"] for hit in hits]
passages = "\n".join(content_list)
rerank_hits = self._reranker.generate_response(
query=self.query, passages=passages
)
return rerank_hits

หมายเหตุ: ใช้โมเดล Reranker เพื่อเรียงลำดับข้อมูลที่เกี่ยวข้องมากที่สุดให้อยู่ลำดับแรก

การใช้เทคนิคเหล่านี้ร่วมกันช่วยให้ RAG มีความแม่นยำและมีประสิทธิภาพมากขึ้นในการตอบคำถามของผู้ใช้


2) How to improve RAG results in your LLM apps

(SOURCE)ในบทความนี้ เราจะสำรวจเทคนิคต่าง ๆ ตั้งแต่พื้นฐานไปจนถึงระดับสูง เพื่อช่วยให้ระบบ RAG ทำงานได้แม่นยำขึ้น โดยเริ่มจากเวอร์ชันพื้นฐานก่อน

  • Naive RAG เป็นเวอร์ชันพื้นฐานของ RAG ที่มี 3 ขั้นตอนหลัก
    - Indexing → สร้าง Vector Embeddings ของเอกสารและจัดเก็บใน Vector Store
    - Retrieval → ค้นหาเอกสารที่ใกล้เคียงกับคำถามมากที่สุด
    - Generation → นำข้อมูลที่ดึงมาไปใช้ใน Prompt เพื่อให้ LLM สร้างคำตอบ
  • ปัญหาของ Naive RAG
    - ดึงข้อมูลผิดพลาด → อาจค้นหาเอกสารที่คล้ายกันแต่ไม่เกี่ยวข้อง
    - ขาดบริบท → เอกสารที่ดึงมาอาจขาดข้อมูลสำคัญ
    - โครงสร้างข้อมูลไม่เหมาะกับ Vector Search
  • ทางแก้ → ใช้เทคนิคขั้นสูงเพื่อปรับปรุงประสิทธิภาพของ RAG

1️⃣ Pre-retrieval Techniques (เทคนิคก่อนการดึงข้อมูล)

เทคนิคเหล่านี้จะเน้นไปที่การเตรียมข้อมูลและการปรับแต่ง query ก่อนที่จะทำการค้นหาใน vector database

A) ปรับปรุงคุณภาพของข้อมูลที่ Index:
“Garbage in, garbage out” → ถ้าข้อมูลใน Vector Store ไม่ดี การค้นหาก็จะไม่ดี
- ลบข้อมูลที่ไม่เกี่ยวข้อง → คัดกรองเฉพาะเอกสารที่เกี่ยวข้อง
- เพิ่ม Metadata ให้เอกสาร → เช่น หมวดหมู่, ผู้เขียน, วันที่
- แปลงรูปแบบข้อมูลให้เหมาะสมกับการใช้งาน → เช่น ถ้าใช้กับแชทบอท ควรแปลงเนื้อหาให้เป็นแนวสนทนา

Example - Metadata

document = {
"text": "Tom had 8 apples on the first day...",
"metadata": {"concept": "addition", "difficulty": "easy"}
}

B) Chunk Optimization (ปรับปรุงการแบ่งข้อมูล):
- Chunk เล็กเกินไป → อาจขาดข้อมูลที่สำคัญ
- Chunk ใหญ่เกินไป → อาจมีข้อมูลที่ไม่เกี่ยวข้องมากเกินไป

C) Query Rewriting (ปรับปรุงคำถามก่อนค้นหา):
บางครั้ง คำถามของผู้ใช้ไม่ตรงกับข้อมูลในฐานเวกเตอร์ เช่น:
"How to improve RAG?" → อาจไม่มีเอกสารที่ใช้คำว่า "improve"
"Techniques for optimizing RAG retrieval" → อาจช่วยค้นหาเอกสารที่เหมาะสมขึ้น

Example - ใช้ LLM ช่วยแปลงคำถามให้ตรงกับฐานข้อมูล

prompt = f"Rewrite the following query to better match documents:\nQuery: {user_query}"
rewritten_query = llm.generate(prompt)

D) ใช้ Hypothetical Document Embeddings (HyDE) - การสร้าง Hypothetical Documents ที่เกี่ยวข้องกับ query สามารถช่วยให้การค้นหามีประสิทธิภาพขึ้น
- ข้อควรระวัง: Hypothetical documents อาจจะขัดแย้งกับข้อมูลจริงได้ ดังนั้นควรดึงข้อมูลทั้งแบบมีและไม่มี hypothetical document

Example - Hypothetical documents

if your reference documents are blog articles.

prompt = f"Please generate a paragraph from a blog article on {user_query}"

if your reference documents are code documentations in markdown.

prompt = f"Please generate a code documentation for {user_query} in markdown format."

E) Query Routing (การกำหนดเส้นทางการดึงข้อมูล):
- ต้องการคำตอบเฉพาะ → ดึงข้อมูลจาก chunks ที่ตรงประเด็น
- ต้องการภาพรวม → ดึงข้อมูลจาก summary ของหลาย ๆ documents
- ต้องการเปรียบเทียบ → ใช้ sub-queries

2️⃣ Retrieval techniques (เทคนิคระหว่างการดึงข้อมูล)

เทคนิคเหล่านี้จะเน้นไปที่การปรับปรุงวิธีการค้นหาข้อมูลใน vector database

A) Using alternative search methods (ใช้วิธีค้นหาแบบอื่น)

  • Full-text search: ค้นหาด้วยคำหลัก (keyword) ที่ตรงกัน
  • Structured queries: ใช้ query ที่มีโครงสร้าง (เช่น SQL)
  • Graph-based search: ค้นหาโดยใช้ graph data structure
  • Hybrid search: ผสมผสานหลายวิธีเข้าด้วยกัน
    - Vector Search → ดีสำหรับค้นหาความหมาย
    - Keyword Search (เช่น BM25) → ดีสำหรับค้นหาคำเฉพาะ หรือเหมือนใช้ find function (“Ctrl+F”) เช่น Product Numbers: “Model AB-1234”

ตัวอย่าง: การค้นหาชื่อยาที่คล้ายกัน หรือชื่อสินค้าใน e-commerce ควรใช้ full-text search ร่วมกับ filter

B) ใช้ embedding model ที่เหมาะสม ทดลองใช้ embedding model ที่แตกต่างกัน เพราะแต่ละ model จับ semantic information ได้ไม่เหมือนกัน

C) Context-aware retrieval (ดึงข้อมูลโดยคำนึงถึงบริบท): อาทิ ParentDocumentRetriever Technique → ดึง chunk เล็ก ๆ ที่ตรงกับ query แล้วดึง parent document ที่มี chunk นั้นอยู่ด้วย

Example - Parent & Child

parent_retriever = ParentDocumentRetriever(vectorstore=vector_db, search_type="similarity")

D) Graph-based search:
- ค้นหาข้อมูลโดยใช้โครงสร้างกราฟ โดยเริ่มจาก chunk ที่เกี่ยวข้องแล้ว explore nodes ที่เชื่อมโยงกัน

E) Agentic Retrieval
- สร้าง agent ที่มี tool สำหรับ query ข้อมูล และให้ agent ตัดสินใจว่าจะค้นหาข้อมูลเพิ่ม หรือจะ return ข้อมูลที่ได้มาแล้ว (วิธีนี้อาจจะช้าและไม่ค่อย stable)

3️⃣ Post-retrieval Techniques (เทคนิคหลังการดึงข้อมูล)

เทคนิคเหล่านี้จะเน้นไปที่การปรับปรุงข้อมูลที่ดึงมาได้แล้ว ก่อนจะส่งให้ LLM สร้างคำตอบ

A) Reranking หรือ Scoring
- จัดอันดับความเกี่ยวข้องของ chunks ที่ดึงมาได้ → โดยให้ LLM ประเมิน หรือใช้ keyword frequency หรือ metadata matching

B) Information Compression
- ลดขนาดข้อมูลที่ดึงมา → โดยสรุป, paraphrasing, หรือดึง key points เพื่อลด noise และ context length

4️⃣Balancing Quality (คุณภาพ) and Latency (ความเร็ว)

  • ใช้โมเดลขนาดเล็ก → เช่น ใช้โมเดลขนาดเล็กสำหรับการ rewrite query หรือการสรุป chunk
  • ทำ Parallel Processing → รันบางขั้นตอนแบบขนาน เช่น hybrid search หรือการสรุปหลาย ๆ chunks
  • ให้ LLM เลือกแทนการ Generate → เช่น ในการ reranking ให้ LLM เลือก rank หรือ score แทนที่จะ generate คำอธิบาย
  • ใช้ Caching → เก็บคำตอบของคำถามที่พบบ่อยเพื่อลดเวลาตอบกลับ

Note: สำหรับ Generation (สร้างคำตอบ)
- ใช้ Expanded Prompt → ใส่ข้อมูลที่เกี่ยวข้องจากเอกสาร
- ใช้ Prompt Optimization → วางข้อมูลสำคัญไว้ที่ต้นหรือท้าย Prompt เพื่อลดปัญหา Lost in the Middle
- 📌 ศึกษางานวิจัย “Lost in the Middle”: ผลลัพธ์ดีที่สุดเมื่อ ข้อมูลอยู่ต้นหรือท้ายของ Context Window
- การเพิ่ม Re-ranking และ Query Optimization อาจช่วยให้โมเดลใช้ข้อมูลกลาง Context ได้ดีขึ้น

หากนำเทคนิคเหล่านี้มาปรับใช้ร่วมกัน จะช่วยให้แอปพลิเคชันที่ใช้ RAG มีความแม่นยำและรวดเร็วขึ้นอย่างมาก 🚀


3) RAG Fusion and Multi-Database RAG

🅰️ RAG-Fusion คืออะไร?

(SOURCE) RAG-Fusion คือ เทคนิคปรับปรุง RAG โดยใช้ หลายคำค้นหา (Multi-Query Search) และ Reciprocal Rank Fusion (RRF) สำหรับการ Re-Rank ข้อมูลที่ค้นมา

RRF คือ เทคนิคการจัดลำดับผลลัพธ์ (Re-Ranking) ของเอกสารที่ดึงมา จากหลายแหล่งค้นหา เพื่อให้ได้ข้อมูลที่แม่นยำและเกี่ยวข้องกับคำถามมากที่สุด
- สูตร: RRF Score(เอกสาร) = ∑ (1 / (k + rank(เอกสาร, แหล่งข้อมูล i)))

หลักการทำงานของ RAG-Fusion

  • สร้างหลายคำค้นหา → ให้ LLM สร้างคำค้นหาที่เกี่ยวข้องจากคำถามเดิม
  • ค้นหาเอกสารด้วย Vector Search → ดึงข้อมูลจากฐานเวกเตอร์สำหรับแต่ละคำค้นหา
  • ใช้ RRF จัดลำดับผลลัพธ์ใหม่ → รวมและเรียงลำดับเอกสารที่สำคัญที่สุด

🅱️ Multi-Database RAG คืออะไร?

Multi-Database RAG เป็นแนวทางที่ขยายความสามารถของ Retrieval-Augmented Generation (RAG) โดยให้ระบบสามารถ ดึงข้อมูลจากหลายฐานข้อมูล (Vector Databases) พร้อมกัน เพื่อให้ LLM ได้รับข้อมูลที่ครอบคลุมและแม่นยำที่สุด

หลักการทำงานของ Multi-Database RAG

  • กำหนดแหล่งข้อมูลหลายฐาน → เราอาจมีฐานข้อมูลแยกตามประเภท เช่น ฐานข้อมูลทางวิชาการ, บทความข่าว, หรือฐานความรู้ภายในองค์กร
  • สร้างตัวดึงข้อมูล (Retriever) สำหรับแต่ละฐาน → ใช้ Vector Search เพื่อค้นหาเอกสารที่เกี่ยวข้องจากแต่ละแหล่ง
  • รวมผลลัพธ์จากหลายฐานข้อมูล → สามารถใช้เทคนิคอย่าง Reciprocal Rank Fusion (RRF) หรือ Maximal Marginal Relevance (MMR) เพื่อรวมและเรียงลำดับข้อมูลที่สำคัญที่สุด
  • สร้างคำตอบโดยอิงจากแหล่งข้อมูลที่เชื่อถือได้ → LLM ใช้เอกสารที่ถูกดึงมาเป็นข้อมูลอ้างอิง ก่อนสร้างคำตอบที่แม่นยำ

4) Advanced RAG Retrieval Strategies: Flow and Modular

(SOURCE) RAG (Retrieval Augmented Generation) เป็นเทคนิคที่ช่วยให้โมเดลภาษาขนาดใหญ่ (LLMs) ใช้แหล่งข้อมูลภายนอกเพื่อเพิ่มความแม่นยำและความเกี่ยวข้องของคำตอบ การจัดโครงสร้าง RAG ในรูปแบบ Modular และ Flow ช่วยให้สามารถปรับแต่งและขยายระบบได้ง่ายขึ้น

Modular RAG เป็นแนวคิดที่ช่วยให้ระบบ Retrieval-Augmented Generation (RAG) มีความสามารถขยายตัวได้ดีขึ้น โดยแบ่งออกเป็น 3 ระดับ ได้แก่:

  • Module Types — กระบวนการหลักของ RAG เช่น retrieva หรือ generation
  • Modules — ฟังก์ชันเฉพาะในแต่ละประเภทโมดูล เช่น ตัวดึงข้อมูลที่ใช้ Vector Search
  • Operators — อัลกอริธึมเฉพาะที่ใช้ดำเนินการในโมดูล เช่น การใช้ vector databases หรือ reranking models

RAG Flow คือ กระบวนการทั้งหมด ตั้งแต่รับ Query ไปจนถึงสร้างผลลัพธ์ ซึ่งสามารถออกแบบให้มีโครงสร้างที่หลากหลาย ได้แก่:

  • Sequential (เชิงลำดับ): ทำงาน module ตามลำดับไปเรื่อยๆ
  • Conditional (ตามเงื่อนไข): เลือกเส้นทางการทำงานของ RAG ตามคำถามหรือความหมาย
  • Branching (แตกกิ่ง): มีเส้นทางการทำงานหลายทางที่ทำไปพร้อมกัน
  • Loop (วนซ้ำ): ทำงานวนซ้ำเพื่อปรับปรุงผลลัพธ์

บทความนี้จะเน้นการอธิบาย RAG แบบ Sequential เป็นหลัก

1️⃣ Basic RAG (RAG แบบพื้นฐาน): โครงสร้างพื้นฐานของ RAG pipeline ประกอบด้วย 3 โมดูลหลัก:

Figure: Basic RAG

2️⃣ การเพิ่มโมดูล Reranker เพื่อปรับลำดับผลลัพธ์ สามารถจัดเรียงผลลัพธ์ของ retriever ได้ดีขึ้น

Figure: (Basic RAG) + Reranker

3️⃣ การเพิ่ม Query Rewrite Module การใช้ HyDE (Hypothetical Document Embedding) เพื่อปรับปรุงคำถามให้ดีขึ้นก่อนการค้นหา

Figure: (Basic RAG + Reranker) + Quey_Rewriter

4️⃣ การเปลี่ยน Output Module เป็น Tree Summarization แทนที่จะใช้การสรุปแบบง่าย เราสามารถใช้ Tree Summarization เพื่อรวมผลลัพธ์แบบลำดับชั้น

Tree Summarization คือการแบ่งข้อมูลเป็นส่วนเล็ก ๆ → สรุปแต่ละส่วนแล้วเอามารวมกัน (จาก Leaf ไปยัง Root) → สรุปอีกที (Recursive Summarization)

Figure: (Basic RAG + Reranker + Quey_Rewriter) + Tree Summary Output

5️⃣ ใช้ Sentence Window Retrieval เพื่อเพิ่มความแม่นยำ

Sentence Window Retrieval เป็นเทคนิคที่ช่วยเพิ่มความแม่นยำในการดึงข้อมูลโดย ขยายขอบเขตของบริบท รอบ ๆ ข้อความที่ถูกค้นคืนมา โดยทำงานคือ 1) Split เอกสาร → Retrieve เอกสาร → ขยายการ retrieve โดยเพิ่ม ประโยคก่อนหน้าและหลัง (เช่น ±3 ประโยค) (Expand Window) → ส่งไปยัง LLM (Pass to LLM)

meta_replacer เป็น technique ที่ใช้แทนที่ Retrieval กล่าวคือเหมือนการ Retrieval ปกติ แต่รวมเนื้อหาจาก Sentence Window Retrieval เข้าไปด้วย

Figure: (Basic RAG + Reranker + Quey_Rewriter + Tree Summary Output) + Sentence Window Retrieval

6️⃣ การเพิ่ม Evaluation Module ด้วย Ragas การใช้ Ragas เพื่อประเมินคุณภาพของ RAG pipeline โดยใช้ตัวชี้วัด เช่น Faithfulness, Answer Relevancy

Figure: (Basic RAG + Reranker + Quey_Rewriter + Tree Summary Output + Sentence Window Retrieval) + Evaluation

เราได้สร้างระบบ RAG Retrieval ที่มีความยืดหยุ่นสูงโดยใช้แนวคิด Modular RAG และ Pipeline ซึ่งสามารถเพิ่มหรือลดโมดูลต่าง ๆ ได้ตามต้องการ เช่น Reranker, Query Rewriter, Tree Summarization, Sentence Window Retrieval และ Evaluation Module เพื่อให้เหมาะกับงานแต่ละประเภท.


5) เจาะลึก RAG ด้วย Visualization

🔍 RAG คืออะไร?

Retrieval-Augmented Generation (RAG) เป็นเทคนิคที่ช่วยให้ Large Language Models (LLMs) สามารถตอบคำถามจากข้อมูลภายนอกได้อย่างแม่นยำมากขึ้น

🔧 ปัญหาที่พบ:

  • คุณภาพของ embeddings ส่งผลต่อความแม่นยำของ RAG
  • ต้องมีการปรับค่า chunk size และ overlap เพื่อให้ retrieval มีประสิทธิภาพมากขึ้น

🌈 การสร้างภาพ FAISS Vector Space ด้วย t-SNE

การสร้างภาพ embeddings ใน Vector Space ช่วยให้เข้าใจการทำงานของ RAG ได้ดีขึ้น โดยเฉพาะ:

  • เข้าใจว่าข้อมูลถูกแทนค่าใน Vector Space อย่างไร
  • ระบุปัญหาที่อาจเกิดขึ้น เช่น ข้อมูลบางส่วนกระจัดกระจาย หรือไม่มีความเชื่อมโยงที่ดีพอ

🔬 วิธีที่ใช้:

  • ใช้ t-SNE (t-Distributed Stochastic Neighbor Embedding) ซึ่งเป็นวิธีการลดมิติแบบ ไม่เชิงเส้น (Non-linear) ที่เน้นการรักษาความสัมพันธ์ของจุดข้อมูลที่อยู่ใกล้กัน (Local Structure) ทำให้เหมาะสำหรับการ แสดงผลข้อมูล (Data Visualization) โดยสามารถลดมิติจากข้อมูลที่มีหลายร้อยมิติเหลือเพียง 2D หรือ 3D เพื่อให้ง่ายต่อการตีความ

Note: นอกจาก t-SNE ยังมีอีกสองวิธีที่สามารถนำมาใช้ในการลดมิติข้อมูล ได้แก่:
- PCA (Principal Component Analysis) → เทคนิค ลดมิติแบบ Linear Transformation เน้น รักษาความแปรปรวนของข้อมูล
- UMAP (Uniform Manifold Approximation and Projection) → คล้าย t-SNE แต่ เร็วกว่า

Figure: Result of t-SNE Visualization

Note: ถ้าอยากเข้าใจแบบไม่ได้อิงประเภทของเอกสาร อาจแบ่งหมวดเป็น 1) เอกสารทั้งหมดใน Vector Store, 2) เอกสารที่ถูกดึงขึ้นมาตอบ, 3) ตำแหน่ง Embedding ของคำถามเดิมและ 4) ตำแหน่ง Embedding ของคำถามที่ขยาย (ถ้ามี)

📊 ผลลัพธ์จากการวิเคราะห์ Embeddings

  • แม้ว่าการลดมิติอาจทำให้แปรผลผิดพลาดบางส่วน แต่จะเห็นได้ว่า นิทานแต่ละเรื่องเกาะกลุ่มกัน
  • จุดที่มีสีแตกต่างกันแสดงถึง การแยกกลุ่มออกเป็น 3 ส่วนหลัก:
  1. ชื่อนิทาน
  2. Moral ของนิทาน
  3. คำถาม (Question)

Figure: t-SNE Visualization focus only Question and Answer

🔮 การวิเคราะห์คำถามและผลลัพธ์จาก Retriever

  • คำถาม: “What is the moral of the story The Boy Who Cried Wolf?”
  • Retriever Result:- คำถามมี embeddings ที่ใกล้เคียงกับ ชื่อเรื่อง “The Boy Who Cried Wolf”
    - ดังนั้น 1 ใน chunk ที่ถูกดึงมาเป็นชื่อเรื่อง และ อีก 2 chunk เป็น moral
  • สังเกตว่า:
    - Chunk size และ overlap มีผลต่อการเลือก chunks ที่ถูกต้อง
    - หากแบ่ง chunk ดี ๆ จะช่วยให้ RAG ดึงข้อมูลที่เกี่ยวข้องได้ดีขึ้น

6) The Best Practices of RAG

(Source) แม้ว่าบทความนี้จะเก่าไปหน่อย แต่ผมว่าแนวคิดยังใช้ได้ โดยบทความนี้สรุปงานวิจัยใหม่ “Searching for Best Practices in Retrieval-Augmented Generation” ซึ่งศึกษาวิธีที่ดีที่สุดในการออกแบบ RAG ผ่านการทดลองเชิงลึก

Figure 1: Retrieval-augmented generation workflow. The optional methods considered for each component are indicated in bold fonts, while the methods underlined indicate the default choice for individual modules. The methods indicated in blue font denote the best-performing selections identified empirically. Source: Searching for Best Practices in Retrieval-Augmented Generation.

🔹 กระบวนการของ RAG

กระบวนการของ RAG มีหลายขั้นตอน ซึ่งแต่ละขั้นตอนมีทางเลือกที่ส่งผลต่อประสิทธิภาพโดยรวม ได้แก่:

  1. Query Classification — ตรวจสอบว่าคำถามของผู้ใช้จำเป็นต้องใช้ RAG หรือไม่
  2. Retrieval — ค้นหาข้อมูลที่เกี่ยวข้อง
  3. Re-ranking — ปรับลำดับเอกสารที่ค้นพบตามความเกี่ยวข้อง
  4. Re-packing — จัดรูปแบบเอกสารใหม่ให้เหมาะสม
  5. Summarization — สรุปเนื้อหาเพื่อลดความซ้ำซ้อน

🔹 Best Practices สำหรับแต่ละโมดูล

  1. Query Classification
    - ไม่ใช่ทุกคำถามที่ต้องใช้ RAG บางครั้ง LLM สามารถตอบได้โดยไม่ต้องดึงข้อมูลเพิ่มเติม
    - ผลลัพธ์: ช่วยลดเวลาตอบคำถาม และเพิ่มความแม่นยำของระบบ
  2. Chunking (การแบ่งเอกสารเป็นส่วนเล็กๆ)
    - ขนาดของ Chunk มีผลต่อประสิทธิภาพ เช่น ขนาดใหญ่ → บริบทครบถ้วนแต่ใช้เวลามาก
    - แนะนำ: ใช้ Sentence-level Chunking เพื่อรักษาความหมายโดยรวม
  3. Embedding Model
    ควรเลือกโมเดลที่สมดุลระหว่างขนาดและความแม่นยำ
  4. Vector Database
    ควรพิจารณาในหลายมิติเช่น
    - รองรับ Multiple Index Type → ยืดหยุ่นในการเลือกอัลกอริธึมจัดเก็บข้อมูล
    - Billion-Scale → จัดการข้อมูลขนาดใหญ่ได้ดี
    - Hybrid Search → รองรับทั้ง Vector Search และ Keyword Search
    - Cloud-Native → ออกแบบให้ทำงานได้ดีบน Cloud
  5. Retrieval (การค้นหาข้อมูล)
    เทคนิคการค้นหาที่แนะนำ:
    Hybrid Search + HyDE (Hypothetical Document Embeddings) — ให้ผลลัพธ์ดีที่สุด
    Query Rewriting — ปรับคำถามให้แม่นยำขึ้นก่อนค้นหา
    Query Decomposition — แยกคำถามออกเป็นประเด็นย่อยเพื่อค้นหาข้อมูลได้ละเอียดขึ้น
  6. Re-ranking (การเรียงลำดับเอกสาร)
    อาจต้องไปศึกษาเพิ่มเติมว่าปัจจุบันมีเทคนิคอะไรบ้าง แต่ถ้าในบทความสรุปไว้ว่า
    - เน้นคุณภาพ → ใช้ RankLLaMA (แต่ช้า)
    - สมดุลประสิทธิภาพและความเร็ว → ใช้ monoT5
    - ต้องการความเร็วสูงสุด → ใช้ TILDEv2
  7. Re-packing (การจัดรูปแบบเอกสารก่อนป้อนเข้า LLM)
    เป็นขั้นตอนที่จัดเรียงเอกสาร หลังจากผ่าน Re-ranking ก่อนป้อนเข้า LLM
    - Forward → เรียงตามความเกี่ยวข้องจากสูงไปต่ำ
    - Reverse → เรียงจากต่ำไปสูง
    - Sides → กระจายข้อมูลสำคัญไว้ต้นและท้าย (ป้องกัน Lost in the Middle)
  8. Summarization (การสรุปข้อมูลก่อนป้อนเข้า LLM)
    อาจต้องไปศึกษาเพิ่มเติมว่าปัจจุบันมีเทคนิคอะไรบ้าง แต่ถ้าในบทความสรุปได้เทียบ 2 แนวทางหลักคือ
    1. Extractive Summarization → ดึงประโยคสำคัญจากเอกสาร เช่น BM25, Recomp (extractive)
    2. Abstractive Summarization → สร้างสรุปใหม่จากหลายแหล่ง เช่น Recomp (abstractive), LongLLMLingua
    ซึ่งจากการทดลอง Recomp เป็นวิธีที่ดีที่สุด และหากต้องการเพิ่มประสิทธิภาพ อาจใช้ Selective Context Filtering เพื่อลดข้อมูลที่ไม่จำเป็น
  9. Fine-tuning LLM Generator
    การฝึกโมเดลโดยใช้ ข้อมูลจริง + ข้อมูลที่ไม่เกี่ยวข้องผสมกัน (Mixed Relevant & Random Documents) ช่วยให้โมเดลแยกแยะข้อมูลที่มีประโยชน์ได้ดีขึ้น

7) The Insanity of Relying on Vector Embeddings: Why RAG Fails

(Source) อีก 1 ปัญหาของ RAG คือ Vector Embeddings ไม่สามารถค้นหาความเหมือนที่แท้จริง (Semantic Similarity) ได้ดีพอ ทำให้ RAG ล้มเหลวใน Production

📌 ตัวอย่างข้อผิดพลาดของ Vector Search

  • King vs. Queen vs. Ruler (ผู้ปกครอง, ผู้มีอำนาจปกครอง)→ “King” ควรคล้าย “Ruler” มากกว่า “Queen” แต่ Vector Search ให้ Queen (92%) > Ruler (83%)
  • Cat vs. Dog vs. Feline (สัตว์ตระกูลแมว) → “Cat” ควรคล้าย “Feline” มากกว่า “Dog” แต่ Vector Search ให้ Dog (86%) > Feline (85%)
  • 1900s vs. 1700s vs. 20th Century → “1900s” ควรตรงกับ “20th Century” แต่ Vector Search ให้ 1700s (91%) > 20th Century (89%)

🔹 วิธีแก้ปัญหา: ใช้ Vector Embeddings เป็น “ตัวช่วย” ไม่ใช่ “วิธีหลัก”

  • ใช้ Vector Embeddings เพื่อกรองข้อมูลตามหมวดหมู่กว้างๆ
  • เสริมด้วย NLP Techniques เช่น:
    - Synonyms, Hyponyms, Hypernyms (คำเหมือน, คำเฉพาะ, คำกว้าง)
    - Structured Search & Knowledge Graphs
    - Rule-based Filtering & Hybrid Search

8) RAG Viz.

รวบรวมภาพสวยๆ เผื่อใช้ในอนาคต

A comprehensive RAG Cheat Sheet detailing motivations for RAG as well as techniques and strategies for progressing beyond Basic or Naive RAG builds. (high-resolution version) (Source: A Cheat Sheet and Some Recipes For Building Advanced RAG)

Source (https://www.linkedin.com/posts/eordax%5Fai-rag-genai-activity-7289045334339543040-ZLCY?utm%5Fsource=share&utm%5Fmedium=member%5Fdesktop&rcm=ACoAABPzthoBgjeUDp6rawsljy9MgwZEiZRs8qg)

Source (https://www.linkedin.com/posts/aurimas-griciunas%5Fllm-ai-machinelearning-activity-7296134869338746881-w9aT?utm%5Fsource=share&utm%5Fmedium=member%5Fdesktop&rcm=ACoAABPzthoBgjeUDp6rawsljy9MgwZEiZRs8qg)

Various Retrieval Techniques (Source: Beyond Naïve RAG: Advanced Techniques for Building Smarter and Reliable AI Systems)

Iterative, Recursive and Adaptive retrieval incorporate repeated retrieval cycles. (Source — Adapted from Retrieval-Augmented Generation for Large Language Models: A Survey, Gao et al)

An advanced RAG pipeline (Source: Beyond Naïve RAG: Advanced Techniques for Building Smarter and Reliable AI Systems)


🔥 บทสรุป

สิ่งที่ได้เรียนรู้จากการใช้ t-SNE เพื่อวิเคราะห์ RAG:

  • RAG ช่วยให้ LLM ตอบคำถามที่ไม่มีใน training data ได้ดีขึ้น
  • คุณภาพของ Embeddings มีผลต่อความแม่นยำของคำตอบ
  • t-SNE ช่วยให้เห็นภาพว่าเอกสารถูกแทนค่าอย่างไรใน Vector Space
  • การปรับค่า Chunk Size และ Overlap ช่วยเพิ่มประสิทธิภาพของ Retrieval

หากต้องการให้ RAG ของคุณมีความแม่นยำมากขึ้น อย่าลืมใช้ visualization ช่วยในการวิเคราะห์! 🚀

การประเมินประสิทธิภาพของระบบที่ใช้ LLM เป็นสิ่งสำคัญสำหรับการทำ production code ในยุคนี้ เราสามารถใช้ LLM มาช่วยประเมิน LLM ด้วยกันเองได้ ซึ่งช่วยให้ประหยัดค่าใช้จ่ายและเวลาได้มาก สิ่งสำคัญคือต้องเข้าใจความแตกต่างของการประเมิน LLM model และ LLM system รวมถึงเลือก metric ที่เหมาะสม และทดสอบ LLM eval อย่างละเอียดก่อนนำไปใช้จริง


Data Science Explore the world of data science with Donato_Story

Dashboard Discover the power of data visualization with Donato_Story

Donato_Journey Join me on my journey (Thai version)

Course_Review Discover the training courses with Donato_Story (Thai version)

Let’s Connect!

Your thoughts and feedback are invaluable. Feel free to share them in the comments or connect with me on

Originally published on Medium

Related