๐Ÿ”จ[๊ฐœ๋ฐœ] RAG๋ž€?

manduยท2025๋…„ 10์›” 15์ผ

[๊ฐœ๋ฐœ]

๋ชฉ๋ก ๋ณด๊ธฐ
9/9

1. ๊ฒ€์ƒ‰ ์ฆ๊ฐ• ์ƒ์„ฑ(RAG, Retrieval-Augmented Generation)์ด๋ž€?

RAG(Retrieval-Augmented Generation)๋Š” ๋Œ€ํ˜• ์–ธ์–ด ๋ชจ๋ธ(LLM)์ด ๊ฐ€์ง„ ํ•œ๊ณ„๋ฅผ ๋ณด์™„ํ•˜๊ธฐ ์œ„ํ•œ ํ•ต์‹ฌ ๊ธฐ์ˆ ๋กœ,
์ •๋ณด ๊ฒ€์ƒ‰ + ์ƒ์„ฑ ๋ชจ๋ธ ๊ธฐ๋ฐ˜์˜ ์ž์—ฐ์–ด ์ฒ˜๋ฆฌ(NLP) ๊ธฐ์ˆ 

RAG๋Š” ๊ธฐ์ˆ (๊ฐœ๋…)์„ ์˜๋ฏธํ•˜๊ณ , Langchain์€ RAG๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋Š” AI ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ฐœ๋ฐœ ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์˜๋ฏธ


2. Why use: LLM์˜ ํ•œ๊ณ„

๋Œ€ํ˜• ์–ธ์–ด ๋ชจ๋ธ์€ ๋งค์šฐ ๋›ฐ์–ด๋‚œ ์ž์—ฐ์–ด ์ฒ˜๋ฆฌ ๋Šฅ๋ ฅ์„ ๊ฐ€์ง€๊ณ  ์žˆ์ง€๋งŒ,
์•„๋ž˜์™€ ๊ฐ™์€ ๋ฌธ์ œ๋ฅผ ํ”ผํ•  ์ˆ˜ ์—†์Œ:

  1. ๋‹ต์ด ์—†์„ ๋•Œ ํ—ˆ์œ„ ์ •๋ณด๋ฅผ ์ƒ์„ฑํ•จ
  2. ์ตœ์‹  ์ •๋ณด ๋ฐ˜์˜ ๋ถˆ๊ฐ€ (ํ›ˆ๋ จ ์‹œ์  ์ดํ›„์˜ ๋ฐ์ดํ„ฐ ๋ฏธํฌํ•จ)
  3. ์‹ ๋ขฐํ•  ์ˆ˜ ์—†๋Š” ์ถœ์ฒ˜ ๊ธฐ๋ฐ˜์˜ ์‘๋‹ต ๊ฐ€๋Šฅ์„ฑ
  4. ๋™์ผ ์šฉ์–ด์˜ ์ค‘์˜์  ์‚ฌ์šฉ์œผ๋กœ ์ธํ•œ ๊ฐœ๋… ํ˜ผ๋™

๋”ฐ๋ผ์„œ, RAG๋Š”
๋Œ€๋‹ตํ•˜๊ธฐ ์ „์— ์ƒˆ๋กœ์šด ์ตœ์‹  ๋ฐ์ดํ„ฐ๋ฅผ ํ•œ๋ฒˆ ํ›‘์–ด๋ณธ ๋‹ค์Œ์— ๋‹ตํ•˜๋ผ๊ณ  ์ง€์‹œํ•˜๋Š” ๊ฒƒ


3. RAG์˜ ํ•ต์‹ฌ ๊ฐœ๋…

๊ฒ€์ƒ‰๊ธฐ(Search)๊ณผ ์ƒ์„ฑ๊ธฐ(Generation)๋ฅผ ๊ฒฐํ•ฉํ•œ ์•„ํ‚คํ…์ฒ˜ ์‚ฌ์šฉ

  • ๊ฒ€์ƒ‰๊ธฐ: ์ž…๋ ฅ์ด ์ฃผ์–ด์ง€๋ฉด ๊ด€๋ จ ๋ฌธ์„œ ๊ฒ€์ƒ‰
    • ๊ธฐ์กด์˜ ๊ฒ€์ƒ‰ ์‹œ์Šคํ…œ ์ฃผ๋กœ ์‚ฌ์šฉ(BM25, DPR)
  • ์ƒ์„ฑ๊ธฐ: ๊ฒ€์ƒ‰๋œ ๋ฌธ์„œ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์‘๋‹ต ์ƒ์„ฑ
    • ์ฃผ๋กœ Transformer ๊ธฐ๋ฐ˜ ์–ธ์–ด ๋ชจ๋ธ(BART, T5)
๊ตฌ๋ถ„BM25DPR
๋ฐฉ์‹ํ†ต๊ณ„ ๊ธฐ๋ฐ˜ (๋‹จ์–ด ์ผ์น˜)๋”ฅ๋Ÿฌ๋‹ ๊ธฐ๋ฐ˜ (์˜๋ฏธ ์œ ์‚ฌ๋„)
์ž…๋ ฅ ๋‹จ์œ„๋‹จ์–ด (bag-of-words)๋ฌธ์žฅ/๋ฌธ์„œ ์ž„๋ฒ ๋”ฉ (vector)
์žฅ์ ๋น ๋ฅด๊ณ  ๊ฐ€๋ฒผ์›€, ํ•ด์„ ์šฉ์ด์˜๋ฏธ ๊ธฐ๋ฐ˜ ๊ฒ€์ƒ‰, ์œ ์—ฐํ•œ ๋งค์นญ
๋‹จ์ ๋™์˜์–ด/๋ฌธ๋งฅ ์ดํ•ด ๋ถˆ๊ฐ€๋ชจ๋ธ ํ•™์Šต ํ•„์š”, ๊ณ„์‚ฐ๋Ÿ‰ ํผ
ํ™œ์šฉ ์˜ˆ๋‰ด์Šคยทํ‚ค์›Œ๋“œ ๊ฒ€์ƒ‰, ๊ณ ์ „ IR ์‹œ์Šคํ…œRAG, QA ์ฑ—๋ด‡, ์‹œ๋งจํ‹ฑ ๊ฒ€์ƒ‰

4. RAG Flow

  1. ์‚ฌ์šฉ์ž ์งˆ๋ฌธ ์ž…๋ ฅ
  2. ์งˆ๋ฌธ์„ ๋ฒกํ„ฐ(์ž„๋ฒ ๋”ฉ)๋กœ ๋ณ€ํ™˜ ํ›„ ๋ฒกํ„ฐ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๊ฒ€์ƒ‰(์ธ์ฝ”๋”ฉ & ์œ ์‚ฌ๋„ ๊ณ„์‚ฐ)
  3. ๊ด€๋ จ ๋ฌธ์„œยท์ง€์‹ ์กฐ๊ฐ(Retrieved Documents) ํš๋“
  4. ๊ฒ€์ƒ‰๋œ ์ •๋ณด๋ฅผ LLM ์ž…๋ ฅ ํ”„๋กฌํ”„ํŠธ์— ์ถ”๊ฐ€ (Context Expansion)
  5. LLM์ด ์ตœ์‹  ์ •๋ณด ๊ธฐ๋ฐ˜์œผ๋กœ ์‘๋‹ต ์ƒ์„ฑ


5. RAG์˜ ์ฃผ์š” ์ด์ 

1. ๋น„์šฉ ํšจ์œจ์„ฑ

  • ํŒŒ์šด๋ฐ์ด์…˜ ๋ชจ๋ธ(FM)์„ ๋‹ค์‹œ ํ•™์Šต์‹œํ‚ค๋Š” ๊ฒƒ์€ ๋ง‰๋Œ€ํ•œ ๋น„์šฉ์ด ๋“ฆ
  • RAG๋Š” LLM์„ ์žฌํ•™์Šตํ•˜์ง€ ์•Š๊ณ ๋„ ์ƒˆ ๋ฐ์ดํ„ฐ๋ฅผ ์—ฐ๊ฒฐํ•  ์ˆ˜ ์žˆ์–ด ํ›จ์”ฌ ๊ฒฝ์ œ์ 

2. ์ตœ์‹ ์„ฑ

  • ๋ชจ๋ธ์ด ๊ณผ๊ฑฐ ํ•™์Šต ๋ฐ์ดํ„ฐ๋งŒ์œผ๋กœ ๋‹ตํ•˜์ง€ ์•Š๊ณ ,
    ์‹ค์‹œ๊ฐ„์œผ๋กœ ์™ธ๋ถ€ ์†Œ์Šค(API, DB, ๋ฌธ์„œ ์ €์žฅ์†Œ ๋“ฑ)๋ฅผ ์กฐํšŒํ•˜์—ฌ ์ตœ์‹  ์ •๋ณด๋ฅผ ๋ฐ˜์˜ํ•  ์ˆ˜ ์žˆ์Œ

3. ์‹ ๋ขฐ์„ฑ

  • LLM์ด ์‘๋‹ต ์‹œ ์ถœ์ฒ˜(Source) ๋˜๋Š” ์ธ์šฉ(Reference)์„ ํ•จ๊ป˜ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์Œ
  • โ€œ์™œ ์ด๋Ÿฐ ๋‹ต์„ ํ–ˆ๋Š”๊ฐ€?โ€์— ๋Œ€ํ•œ ํˆฌ๋ช…์„ฑ์„ ํ™•๋ณดํ•ด ์‚ฌ์šฉ์ž์˜ ์‹ ๋ขฐ๋ฅผ ๋†’์ž„
  1. ๊ฐœ๋ฐœ์ž ์ œ์–ด ๊ฐ•ํ™”
  • LLM์ด ์‚ฌ์šฉํ•  ์ง€์‹ ์†Œ์Šค๋ฅผ ์กฐ์ง ๋‚ด๋ถ€ ๋ฐ์ดํ„ฐ๋กœ ์ œํ•œํ•˜๊ฑฐ๋‚˜ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์Œ
  • ๋˜ํ•œ, ํŠน์ • ์ธ์ฆ ์ˆ˜์ค€์— ๋”ฐ๋ผ ์ •๋ณด ์ ‘๊ทผ์„ ์ œ์–ดํ•˜๋Š” ๊ฒƒ๋„ ๊ฐ€๋Šฅํ•จ
  • LLM์ด ์ฐธ๊ณ ํ•˜๋Š” ์ง€์‹์˜ ํ’ˆ์งˆ๊ณผ ๋ฒ”์œ„๋ฅผ ๊ฐœ๋ฐœ์ž๊ฐ€ ์ง์ ‘ ํ†ต์ œํ•  ์ˆ˜ ์žˆ์Œ

6. ์ตœ์†Œ ์˜ˆ์‹œ (LangChain ๊ธฐ์ค€, ๊ฐœ๋… ๋ง›๋ณด๊ธฐ)

# โœ… 0. ํŒจํ‚ค์ง€ ์„ค์น˜
# pip install langchain openai faiss-cpu tiktoken

# โœ… 1. ๋ฌธ์„œ โ†’ ์ฒญํฌ ๋ถ„๋ฆฌ
from langchain.text_splitter import RecursiveCharacterTextSplitter

docs = [
    "์‚ฌ๋‚ด ํœด๊ฐ€ ๊ทœ์ •: ์—ฐ์ฐจ๋Š” ์ž…์‚ฌ ์›” ๊ธฐ์ค€์œผ๋กœ ๋ฐœ์ƒํ•จ.",
    "๊ฒฝ์กฐ์‚ฌ ํœด๊ฐ€ ๊ทœ์ •: ๊ฒฐํ˜ผ ์‹œ 5์ผ, ๋ถ€๋ชจ์ƒ 7์ผ, ์ž๋…€ ์ถœ์‚ฐ 3์ผ."
]

splitter = RecursiveCharacterTextSplitter(chunk_size=400, chunk_overlap=50)
chunks = splitter.create_documents(docs)

print(f"โœ… ์ƒ์„ฑ๋œ ์ฒญํฌ ์ˆ˜: {len(chunks)}")
print(chunks[0].page_content)

# โœ… 2. ์ž„๋ฒ ๋”ฉ & ๋ฒกํ„ฐDB ๊ตฌ์ถ• (FAISS)
from langchain_openai import OpenAIEmbeddings
from langchain_community.vectorstores import FAISS

embeddings = OpenAIEmbeddings()
vdb = FAISS.from_documents(chunks, embeddings)

# โœ… 3. ๋ฆฌํŠธ๋ฆฌ๋ฒ„ & ์ƒ์„ฑ ์ฒด์ธ ๊ตฌ์„ฑ
from langchain.chains import RetrievalQA
from langchain_openai import ChatOpenAI

llm = ChatOpenAI(temperature=0, model="gpt-3.5-turbo")

qa_chain = RetrievalQA.from_chain_type(
    llm=llm,
    retriever=vdb.as_retriever(search_kwargs={"k": 3}),
    return_source_documents=True
)

# โœ… 4. ์งˆ์˜ ์ˆ˜ํ–‰
query = "๊ฒฐํ˜ผํ•˜๋ฉด ๋ฉฐ์น  ํœด๊ฐ€์ž„?"
res = qa_chain({"query": query})

print("๐Ÿงพ ์งˆ๋ฌธ:", query)
print("๐Ÿ’ฌ ๋‹ต๋ณ€:", res["result"])
print("๐Ÿ“š ๊ทผ๊ฑฐ ๋ฌธ์„œ:")
for doc in res["source_documents"]:
    print("-", doc.page_content)

์‹ค์ œ ์„œ๋น„์Šค์—์„œ๋Š” PDF/์›น/DB ๋กœ๋”, ๊ถŒํ•œ ํ•„ํ„ฐ, ํ•˜์ด๋ธŒ๋ฆฌ๋“œ ๊ฒ€์ƒ‰ ๋“ฑ์„ ๋ง๋ถ™์ด๋ฉด ๋จ

profile
๋งŒ๋‘๋Š” ๋ชฉ๋ง๋ผ

0๊ฐœ์˜ ๋Œ“๊ธ€