
RAG ๊ฒ์ ์ฆ๊ฐ ์์ฑ์ ๋ชจ๋ ๊ฒ
RAG(Retrieval-Augmented Generation)๋ ์ต๊ทผ AI ๋ถ์ผ์์ ๊ฐ์ฅ ์ฃผ๋ชฉ๋ฐ๋ ๊ธฐ์ ์ค ํ๋์
๋๋ค.
ํ์ง๋ง ๋ง์ ์ฌ๋๋ค์ด RAG์ ์ ํํ ์๋ ์๋ฆฌ์ ๊ตฌํ ๋ฐฉ๋ฒ์ ๋ํด ํผ๋ํ๊ณ ์์ต๋๋ค.
์ด๋ฒ ํฌ์คํ
์์๋ RAG์ ํต์ฌ ๊ฐ๋
๋ถํฐ ์ค์ ๊ตฌํ๊น์ง ์์ธํ ๋ค๋ค๋ณด๊ฒ ์ต๋๋ค.
RAG๋ ๋ฌด์์ธ๊ฐ?
RAG๋ ์ธ ๋จ์ด์ ์กฐํฉ์
๋๋ค
- Retrieval(๊ฒ์): ์ด๋์ ๊ฐ ๊ด๋ จ ์ ๋ณด๋ฅผ ๋์ด์ค๋ ๊ฒ
- Augmented(์ฆ๊ฐ): ๊ธฐ์กด ๊ฒ์ ๊ฐํํ๊ณ ํฅ์์ํค๋ ๊ฒ
- Generation(์์ฑ): ์๋ก์ด ๋ด์ฉ์ ๋ง๋ค์ด๋ด๋ ๊ฒ
์ฆ, RAG๋ "๊ด๋ จ ์ ๋ณด๋ฅผ ๊ฒ์ํด์ ์์ฑ ๊ณผ์ ์ ํฅ์์ํค๋ ๊ธฐ์ " ์
๋๋ค.
RAG์ ํต์ฌ ๊ตฌ์ฑ ์์
1. Retrieval: ์ ๋ณด ๊ฒ์ ๊ณผ์
๊ฒ์ ๊ณผ์ ์ ๋ค์๊ณผ ๊ฐ์ด ์งํ๋ฉ๋๋ค.
- ํ
์คํธ ์๋ฒ ๋ฉ: ํ
์คํธ๋ฅผ ํน์ ์ฐจ์์ ๋ฒกํฐ๋ก ๋ณํ
- ์ ์ฌ๋ ๊ฒ์: ๊ธฐ์กด์ ์ ์ฅ๋ ๋ฒกํฐ๋ค ์ค ์ ์ฌํ ๊ฒ์ ์ฐพ์
- ์ ๋ณด ์ถ์ถ: ๊ฒ์๋ ๋ฒกํฐ์ ์ฐ๊ฒฐ๋ ์๋ณธ ์ ๋ณด๋ฅผ ๊ฐ์ ธ์ด
2. Augmented: ์ง์ง ์ฆ๊ฐ ๋์์?
๋ง์ ์ฌ๋๋ค์ด ์คํดํ๋ ๋ถ๋ถ์
๋๋ค.
RAG์์ ์ค์ ๋ก ์ฆ๊ฐ๋๋ ๊ฒ์ ์์ฑ(Generation) ์์ฒด๊ฐ ์๋๋ผ ์ปจํ
์คํธ(Context)์
๋๋ค.
- ์์คํ
ํ๋กฌํํธ๋ ์ฌ์ฉ์ ์ง์์ ์ถ๊ฐ ์ ๋ณด๋ฅผ ๋ณด๊ฐ
- ๋น์ทํ ๊ฐ๋
์ผ๋ก Tool AC(Tool-Augmented Context), Memory AC(Memory-Augmented Context) ๋ฑ์ด ์์
- ์ค์ ๋ก๋ "Retrieval Augmented Context"๋ผ๊ณ ๋ถ๋ฅด๋ ๊ฒ์ด ๋ ์ ํ
์ผ๋ฐ์ ์ธ LLM ์ฌ์ฉ vs RAG ํ์ฉ
๊ธฐ์กด LLM ์ฌ์ฉ ๋ฐฉ์
์ง์ โ LLM ํฌ์
โ ๊ฒฐ๊ณผ ์๋ น
"๋ฆฌํธ๋ฆฌ๋ฒ๋?" โ invoke(์ง์) โ print(result)
RAG๋ฅผ ํ์ฉํ LLM ์ฌ์ฉ
์ง์ โ ์๋ฒ ๋ฉ โ ๋ฒกํฐDB ๊ฒ์ โ ๊ด๋ จ ์๋ฃ ์ทจํฉ โ ์ง์ ๋ด์ฉ ๋ณด๊ฐ โ LLM ํฌ์
์ค์ ๊ตฌํ ์์
์ง์ = "๋ฆฌํธ๋ฆฌ๋ฒ๋?"
์๋ฒ ๋ฉ = [0.12, 0.34, -0.12, ...]
result = db.search([0.12, 0.34, -0.12, ...])
info = result.join(lambda x: x.data)
๋ณด๊ฐ๋_์ง์ = ์ง์ + "์ถ๊ฐ์ ๋ณด: " + info
invoke(๋ณด๊ฐ๋_์ง์)
์๋ฒ ๋ฉ(Embedding): RAG์ ํต์ฌ ๊ธฐ์
์๋ฒ ๋ฉ ๊ณผ์
- ํ ํฐํ: ๋ฌธ์ฅ์ ๊ฐ๋ณ ํ ํฐ์ผ๋ก ๋ถํดํ์ฌ ๋ฆฌ์คํธ ์์ฑ
- ์ ์ ๋ณํ: ๊ฐ ํ ํฐ์ ์ดํ ์ฌ์ ์ ํตํด ์ ์๋ก ๋ณํ
- ๋ฒกํฐ ๋ณํ: ์ ์ ๋ฆฌ์คํธ๋ฅผ ํน์ ์ฐจ์์ ๋ฒกํฐ๋ก ๋ณํ
์๋ฒ ๋ฉ ๋ชจ๋ธ์ ์ค์์ฑ
์๋ฒ ๋ฉ ๋ชจ๋ธ ์ ํ ์ ์ฃผ์์ฌํญ
- ํธํ์ฑ ๋ฌธ์ : ๋ค๋ฅธ ๋ชจ๋ธ๋ก ๋ง๋ ์๋ฒ ๋ฉ ๊ฒฐ๊ณผ๋ ์๋ก ํธํ๋์ง ์์
- ์ผ๊ด์ฑ ์ ์ง: RAG DB ๊ตฌ์ถ ์ ์ฌ์ฉํ ๋ชจ๋ธ๊ณผ ์ฌ์ฉ์ ์ง์ ์๋ฒ ๋ฉ ์ ๊ฐ์ ๋ชจ๋ธ ์ฌ์ฉ ํ์
- ๋ง์ด๊ทธ๋ ์ด์
๋น์ฉ: ๋ชจ๋ธ ๊ต์ฒด ์ ์ ์ฒด RAG DB๋ฅผ ์ฌ์๋ฒ ๋ฉํด์ผ ํจ
๋ฐ๋ผ์ ์๋ฒ ๋ฉ ๋ชจ๋ธ์ ์ ์คํ๊ฒ ์ ํํด์ผ ํฉ๋๋ค.
๊ณ ๊ธ RAG ๊ธฐ๋ฒ ์ง์ ๋ถํด
์ ์ง์ ๋ถํด๊ฐ ํ์ํ๊ฐ?
์ค์ RAG ์์คํ
์์ ์์ฃผ ๋ฐ์ํ๋ ๋ฌธ์ ์
- ์์ ๋ฐ์ดํฐ: ๋๋ถ๋ถ ์ฌ์ค ๊ธฐ๋ฐ ์ ๋ณด (A๋ B๋ค)
- ์ฌ์ฉ์ ์ง์: ์๋๋ ๋ฐฐ๊ฒฝ์ด ํฌํจ๋ ๋ณต์กํ ๋ฌธ๋งฅ
์๋ฅผ ๋ค์ด,
"์ผ์ฑ์ ์ต๊ทผ ๋น๋ฉ๋ชจ๋ฆฌ ๋ถ์ผ์์ ํฌ๊ฒ ๋ค์ณ์ง๊ณ ์์ผ๋ฉฐ ์ค์ค๋ฏธ๋ฅผ ๋น๋กฏํ ํ๋ฐ์ฃผ์์๊ฒ ์กฐ์ฐจ ๋ฐ๋ฆฐ๋ค.
๋ชจ๋ฐ์ผ AP ๋ถ์ผ ์ธ์๋ AI ์นฉ์
๋ ๊ฐ๋ฐํ์ง ๋ชปํ๋ค"๋ผ๋
์ง์๋ ์ฌ๋ฌ ์ฌ์ค์ ํฌํจํ๊ณ ์์ต๋๋ค.
์ง์ ๋ถํด ์ ๋ต
LLM์ ํ์ฉํด ๋ณต์กํ ์ง์๋ฅผ ์ฌ๋ฌ ๊ฐ์ ๋จ์ํ ์ง์๋ก ๋ถํด
- ์ผ์ฑ์ ์์ ์ต๊ทผ ๋น๋ฉ๋ชจ๋ฆฌ ๋ฐ๋์ฒด ๋ถ์ผ ์ฑ๊ณผ
- ๋น๋ฉ๋ชจ๋ฆฌ ๋ฐ๋์ฒด ์์ฅ์์ ์ผ์ฑ๊ณผ ๊ฒฝ์์ฌ ๊ฐ ๋น๊ต
- ์ค์ค๋ฏธ์ ๋ฐ๋์ฒด ๋ถ์ผ ๊ธฐ์ ์ ์ง์
- ์ผ์ฑ์ด ํ๋ฐ์ฃผ์์๊ฒ ๋ฐ๋ฆฌ๋ ๋ถ์ผ
- ์ผ์ฑ์ ์์ ๋ชจ๋ฐ์ผ AP ๊ฒฝ์๋ ฅ
- ์ผ์ฑ์ AI ์นฉ์
๊ฐ๋ฐ ํํฉ
- ์ผ์ฑ AI ์นฉ์
์ ๊ฒฝ์์ฌ ๋๋น ์์ค
์ง์ ๋ถํด์ ์ฅ์
- ๋์ ์ผ์น์จ: ์ฌ์ค ๊ธฐ๋ฐ ๊ฒ์์ผ๋ก ๋ฒกํฐ ์ ์ฌ๋ ๋งค์นญ ํ๋ฅ ์ฆ๊ฐ
- ํจ์จ์ฑ: ์ฌ๋ฌ ์ง์ ์ฒ๋ฆฌ๊ฐ GPU ์์์ ํฌ๊ฒ ์๋นํ์ง ์์
- ์ ํ์ฑ: ์ปจํ
์คํธ๋ฅผ ๋ฐฐ์ ํ ์์ํ ์ฌ์ค ์ถ์ถ๋ก ๊ฒ์ ์ ํ๋ ํฅ์
ํ๋กฌํํธ ์บ์ ์ต์ ํ
ํ๋กฌํํธ ์บ์์ ํ์ค
- ๋ฒค๋๋ง๋ค ์ ๊ณต ์ฌ๋ถ๊ฐ ๋ค๋ฆ
- OpenAI๋ ํน์ ๋ชจ๋ธ์์๋ง ์ง์ํ๋ฉฐ ์
๋ ฅ ํ ํฐ๋ง ๋์
- ์บ์ ์ ์ง ์๊ฐ๊ณผ ๋ฒ์๋ ๋ฒค๋ ์ฌ๋
OpenAI ํ๋กฌํํธ ์บ์ ์๋ ์๋ฆฌ
- Prefix ์ผ์น: ๊ธฐ์กด ์ง์์ ์ ์ง์๊ฐ ์๋ถ๋ถ๋ถํฐ ์ผ์นํ๋ ๊ตฌ๊ฐ๊น์ง ์บ์
- ์๊ฒฉํ ์ผ์น: system๊ณผ user ์์๋ง ๋ฐ๋์ด๋ ์บ์ ๋ฌดํจ
- ํน์ ํฌ๊ธฐ ์ด์: ์ผ์ ํฌ๊ธฐ ์ด์์ ์
๋ ฅ์์๋ง ์๋
์บ์ ์ต์ ํ ์ ๋ต
- ๊ณตํต ๋ถ๋ถ์ ์ต๋ํ ๋์ผํ๊ฒ ์ ์ง
- ๋ณ๊ฒฝ๋๋ ๋ถ๋ถ์ ๋งจ ๋ง์ง๋ง์ ๋ฐฐ์น
- ์ฑ
์์ ํํ ๋ณด๋ <WANT_TO_CACHE_HERE> ๊ฐ์ ํ๊ธฐ๋ ์๋ฏธ ์์
- ์ค์ ๋ก๋ ๋ง์ง๋ง ๋ถ๋ถ์ {}๋ก ์ฒ๋ฆฌํ์ฌ ์บ์ ํ์ฉ
๋ญ์ฒด์ธ ๋๊ตฌ์ธ๊ฐ ์ฅ์ ๋ฌผ์ธ๊ฐ?
๋ญ์ฒด์ธ์ ๋ณธ์ง
- ํ์ดํ๋ผ์ด๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ: Runnable๋ก ์ ์๋ Task๋ค์ ์ฐ๊ฒฐํ์ฌ ์คํ
- ๋์์ฑ ๋ผ์ด๋ธ๋ฌ๋ฆฌ: ๋ฉํฐํ๋ก์ธ์ค ๊ธฐ๋ฐ ๋์ ์คํ (ํ์ง๋ง ์ฑ๋ฅ์ด ๋ฎ์)
- ์ฌ์ ์ ์๋ ํ์คํฌ ์ ๊ณต: LLM ๊ด๋ จ ์์
๋ค์ ๋ฏธ๋ฆฌ ๊ตฌํํด์ ์ ๊ณต
๋ญ์ฒด์ธ์ ํ๊ณ
- ์ฃผ๋ก ๋
ธํธ๋ถ ํ๊ฒฝ์ ์คํ์ฉ์ผ๋ก ์ ํฉ
- ์์ฉ ์๋น์ค ๋์
์ ์ฑ๋ฅ ๋ฌธ์ ๋ก ๋๋ถ๋ถ ํฌ๊ธฐ
- ๋์์ฑ ์ฑ๋ฅ์ด๋ ์ต์ ํ์ ๋ํ ๊ฐ์ ์์ง ๋ถ์กฑ
๋ญ๊ทธ๋ํ์ Langroid ๋์
- ๋ญ๊ทธ๋ํ: ํ์คํฌ ์ฒด์ธ์ ์์ํ๊ฒ ๋ฐ์ดํฐ๋ก ํํํ๊ณ ์คํ๊ธฐ๋ ๋ณ๋ ์ ํ
- Langroid: ๊ณ ์ฑ๋ฅ asyncio ๊ธฐ๋ฐ์ผ๋ก ๋ญ์ฒด์ธ๊ณผ ์ ์ฌํ ๊ธฐ๋ฅ์ ํจ์ฌ ๋น ๋ฅด๊ฒ ์ ๊ณต
๋ญ์ฒด์ธ ์ฌ์ฉ ๊ถ์ฅ์ฌํญ
- ๊น์ด ํ๊ณ ๋ค ํ์ ์์
- ๋์์ฑ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ก๋ ๋ถ์ ํฉ
- Task ์คํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ก์์ ๊ธฐ๋ฅ์๋ง ์ง์ค
- ์ฌ์ ์ ์๋ LLM Task ํ์ฉ์ ์ด์
RAG์ ์ฐ์ํ ๊ตฌํ ํจ์ํ ํ์ดํ๋ผ์ด๋
RAG ์์คํ
์ ์ฌ๋ฌ ๋จ๊ณ์ ๋ฐ์ดํฐ ๋ณํ ๊ณผ์ ์
๋๋ค.
์ด๋ฅผ ํจ์ํ ํ๋ก๊ทธ๋๋ฐ ํจ๋ฌ๋ค์์ผ๋ก ๊ตฌํํ๋ฉด ๋์ฑ ๊น๋ํ ์ฝ๋๋ฅผ ์์ฑํ ์ ์์ต๋๋ค.
ํ์
์์ ํ ํ์ดํ๋ผ์ด๋
from typing import TypeVar, Callable
A = TypeVar('A')
B = TypeVar('B')
C = TypeVar('C')
def combine(f: Callable[[A], B], g: Callable[[B], C]) -> Callable[[A], C]:
def composed(x: A) -> C:
return g(f(x))
return composed
def tokenize(text: str) -> list[str]:
return text.split()
def embed(tokens: list[str]) -> list[float]:
return [hash(token) % 100 / 100.0 for token in tokens]
# ํ์ดํ๋ผ์ธ ๊ตฌ์ฑ
text_to_embedding = combine(tokenize, embed)
result = text_to_embedding("์๋
ํ์ธ์ RAG์
๋๋ค")
print(result) # [0.32, 0.45, 0.78]
์ด๋ฐ ๋ฐฉ์์ผ๋ก ๊ตฌํํ๋ฉด ๊ฐ ๋จ๊ณ๊ฐ ๋ช
ํํ ๋ถ๋ฆฌ๋๊ณ , ํ์
์์ ์ฑ๋ ๋ณด์ฅ๋ฉ๋๋ค.
๊ฒฐ๋ก
RAG๋ ๋จ์ํ "๊ฒ์ํด์ ์์ฑ์ ๋์์ฃผ๋ ๊ธฐ์ "์ด ์๋๋๋ค.
ํจ๊ณผ์ ์ธ RAG ์์คํ
์ ๊ตฌ์ถํ๋ ค๋ฉด
- ์ ํํ ๊ฐ๋
์ดํด: Context๋ฅผ ์ฆ๊ฐํ๋ ๊ธฐ์ ์์ ์ธ์
- ์ ์คํ ์๋ฒ ๋ฉ ๋ชจ๋ธ ์ ํ: ํ ๋ฒ ์ ํํ๋ฉด ๋ณ๊ฒฝ ๋น์ฉ์ด ํผ
- ์ง์ ๋ถํด ๊ธฐ๋ฒ ํ์ฉ: ๋ณต์กํ ์ง์๋ฅผ ๋จ์ํ ์ฌ์ค ๊ฒ์์ผ๋ก ๋ถํด
- ํ๋กฌํํธ ์บ์ ์ต์ ํ: ๊ณตํต ๋ถ๋ถ์ ์์, ๋ณ๊ฒฝ ๋ถ๋ถ์ ๋ค์
- ์ ์ ํ ๋๊ตฌ ์ ํ: ๋ญ์ฒด์ธ์ ํ๊ณ๋ฅผ ์ดํดํ๊ณ ๋์ ๊ณ ๋ ค
- ํจ์ํ ํ์ดํ๋ผ์ด๋: ํ์
์์ ํ๊ณ ์กฐํฉ ๊ฐ๋ฅํ ๊ตฌ์กฐ๋ก ์ค๊ณ
RAG๋ ์ด์ ์ ํ์ด ์๋ ํ์๊ฐ ๋์์ต๋๋ค.
ํ์ง๋ง ์ฌ๋ฐ๋ฅธ ์ดํด์ ๊ตฌํ ์์ด๋ ์คํ๋ ค ์ฑ๋ฅ ์ ํ๋ฅผ ๊ฐ์ ธ์ฌ ์ ์์ต๋๋ค.
์ด๋ฒ ํฌ์คํ
์ด ์ฌ๋ฌ๋ถ์ RAG ์ฌ์ ์ ๋์์ด ๋๊ธฐ๋ฅผ ๋ฐ๋๋๋ค.