[κ°•μ˜λ…ΈνŠΈ] RAG From Scratch : Query Indexing 기법

Posted by Euisuk's Dev Log on September 14, 2024

[κ°•μ˜λ…ΈνŠΈ] RAG From Scratch : Query Indexing 기법

원본 κ²Œμ‹œκΈ€: https://velog.io/@euisuk-chung/RAG-From-Scratch-12-14

  • ν•΄λ‹Ή λΈ”λ‘œκ·Έ ν¬μŠ€νŠΈλŠ” RAG From Scratch : Coursework κ°•μ˜ 파트 12 - 14 λ‚΄μš©μ„ 닀루고 μžˆμŠ΅λ‹ˆλ‹€.
λΉ„λ””μ˜€ μš”μ•½ κ°•μ˜ 링크 μŠ¬λΌμ΄λ“œ
Part 12 (닀쀑 ν‘œν˜„ 인덱싱) 효율적인 검색을 μœ„ν•΄ λ¬Έμ„œ μš”μ•½μ„ μΈλ±μ‹±ν•˜λ©΄μ„œλ„ 전체 λ¬Έμ„œμ™€ μ—°κ²°ν•˜μ—¬ 포괄적인 이해λ₯Ό μ œκ³΅ν•˜λŠ” 방법을 λ…Όμ˜ν•©λ‹ˆλ‹€. πŸ“Œ κ°•μ˜ πŸ“– 참고자료
Part 13 (RAPTOR) λ¬Έμ„œ μš”μ•½κ³Ό ν΄λŸ¬μŠ€ν„°λ§μ„ 톡해 κ³ μˆ˜μ€€ κ°œλ…μ„ ν¬μ°©ν•˜λŠ” RAPTOR 기법을 μ†Œκ°œν•©λ‹ˆλ‹€. πŸ“Œ κ°•μ˜ πŸ“– 참고자료
Part 14 (ColBERT) RAG ν”„λ ˆμž„μ›Œν¬ λ‚΄μ—μ„œ κ°•ν™”λœ 토큰 기반 검색을 μœ„ν•œ ColBERTλ₯Ό νƒκ΅¬ν•©λ‹ˆλ‹€. πŸ“Œ κ°•μ˜ πŸ“– 참고자료

ν•„μš” νŒ¨ν‚€μ§€ μ„€μΉ˜

1
# ! pip install langchain_community tiktoken langchain-openai langchainhub chromadb langchain youtube-transcript-api pytube

Part 12 (인덱싱/λ‹€μ€‘ν‘œν˜„μΈλ±μ‹±)

  • μœ„ 그림의 단계에 따라 각 κ³Όμ •μ˜ μ—­ν• κ³Ό κ°œλ…μ„ κ°„λž΅ν•˜κ²Œ μ„€λͺ…ν•˜κ² μŠ΅λ‹ˆλ‹€:

    1. Question (질문) : μ‚¬μš©μžκ°€ μ‹œμŠ€ν…œμ— μž…λ ₯ν•˜λŠ” μžμ—°μ–΄ ν˜•νƒœμ˜ μ§ˆλ¬Έμž…λ‹ˆλ‹€. μ΄λŠ” 전체 ν”„λ‘œμ„ΈμŠ€μ˜ μ‹œμž‘μ μ΄ λ©λ‹ˆλ‹€.
    2. Query Translation (쿼리 λ²ˆμ—­) : μ‚¬μš©μžμ˜ μžμ—°μ–΄ μ§ˆλ¬Έμ„ μ‹œμŠ€ν…œμ΄ 이해할 수 μžˆλŠ” ν˜•μ‹μœΌλ‘œ λ³€ν™˜ν•˜λŠ” κ³Όμ •μž…λ‹ˆλ‹€. μ΄λŠ” μžμ—°μ–΄ 처리 κΈ°μˆ μ„ ν™œμš©ν•˜μ—¬ μˆ˜ν–‰λ©λ‹ˆλ‹€.
    3. Routing (λΌμš°νŒ…) : λ³€ν™˜λœ 쿼리λ₯Ό μ μ ˆν•œ 처리 κ²½λ‘œλ‚˜ 데이터 μ†ŒμŠ€λ‘œ μ•ˆλ‚΄ν•˜λŠ” κ³Όμ •μž…λ‹ˆλ‹€. 질문의 νŠΉμ„±μ— 따라 졜적의 처리 방법을 κ²°μ •ν•©λ‹ˆλ‹€.
    4. Query Construction (쿼리 ꡬ성) : λΌμš°νŒ…λœ 정보λ₯Ό λ°”νƒ•μœΌλ‘œ μ‹€μ œ λ°μ΄ν„°λ² μ΄μŠ€λ‚˜ 검색 μ—”μ§„μ—μ„œ μ‚¬μš©ν•  수 μžˆλŠ” ν˜•νƒœμ˜ 쿼리λ₯Ό κ΅¬μ„±ν•©λ‹ˆλ‹€.
    5. Indexing (인덱싱, 이번 μ±•ν„°πŸ“Œ) : λ°μ΄ν„°λ² μ΄μŠ€λ‚˜ λ¬Έμ„œ μ»¬λ ‰μ…˜μ—μ„œ 효율적인 검색을 μœ„ν•΄ 데이터λ₯Ό κ΅¬μ‘°ν™”ν•˜κ³  μ‘°μ§ν™”ν•˜λŠ” κ³Όμ •μž…λ‹ˆλ‹€. μ΄λŠ” 주둜 μ‹œμŠ€ν…œ ꡬ좕 λ‹¨κ³„μ—μ„œ μˆ˜ν–‰λ©λ‹ˆλ‹€.
    6. Retrieval (검색) : κ΅¬μ„±λœ 쿼리λ₯Ό μ‚¬μš©ν•˜μ—¬ μΈλ±μ‹±λœ λ°μ΄ν„°μ—μ„œ κ΄€λ ¨ 정보λ₯Ό μΆ”μΆœν•˜λŠ” κ³Όμ •μž…λ‹ˆλ‹€. 이 λ‹¨κ³„μ—μ„œ 질문과 κ°€μž₯ κ΄€λ ¨μ„± 높은 정보λ₯Ό μ°Ύμ•„λƒ…λ‹ˆλ‹€.
    7. Generation (생성) : κ²€μƒ‰λœ 정보λ₯Ό λ°”νƒ•μœΌλ‘œ μ§ˆλ¬Έμ— λŒ€ν•œ 닡변을 μƒμ„±ν•˜λŠ” κ³Όμ •μž…λ‹ˆλ‹€. 이 λ‹¨κ³„μ—μ„œλŠ” 주둜 μžμ—°μ–΄ 생성 기술이 μ‚¬μš©λ©λ‹ˆλ‹€.
    8. Answer (λ‹΅λ³€) : μ΅œμ’…μ μœΌλ‘œ μƒμ„±λœ 닡변을 μ‚¬μš©μžμ—κ²Œ μ œκ³΅ν•©λ‹ˆλ‹€. μ΄λŠ” μ›λž˜ μ§ˆλ¬Έμ— λŒ€ν•œ μ‘λ‹΅μœΌλ‘œ, μžμ—°μ–΄ ν˜•νƒœλ‘œ ν‘œν˜„λ©λ‹ˆλ‹€.
  • 이번 κ°•μ˜λŠ” Indexing(인덱싱), 그리고 κ·Έ μ€‘μ—μ„œλ„ Multi-Representation Indexing(닀쀑 ν‘œν˜„ 인덱싱)μ΄λΌλŠ” κ°œλ…μ„ 닀루고 μžˆμŠ΅λ‹ˆλ‹€.
  • Multi-Representation Indexing(닀쀑 ν‘œν˜„ 인덱싱)은 벑터 μŠ€ν† μ–΄μ—μ„œ 정보λ₯Ό 효율적으둜 κ²€μƒ‰ν•˜λŠ” 데 μ€‘μš”ν•œ κΈ°λ²•μž…λ‹ˆλ‹€.

    • 이 기법은 μžμ—°μ–΄ μ§ˆλ¬Έμ— λŒ€ν•œ 졜적의 λ¬Έμ„œ 검색을 κ°€λŠ₯ν•˜κ²Œ ν•˜λ©°, 특히 κΈ΄ λ¬Έλ§₯을 μ²˜λ¦¬ν•˜λŠ” LLM(Long Context Language Models)μ—μ„œ 맀우 μœ μš©ν•©λ‹ˆλ‹€.

1. Indexingμ΄λž€?

  • 인덱싱은 λ¬Έμ„œλ‚˜ 데이터λ₯Ό μ €μž₯ν•˜κ³  λ‚˜μ€‘μ— 검색할 수 μžˆλ„λ‘ μ€€λΉ„ν•˜λŠ” κ³Όμ •μž…λ‹ˆλ‹€.
    • 벑터 μŠ€ν† μ–΄(Vector Store)λŠ” λ¬Έμ„œλ₯Ό λ²‘ν„°λ‘œ λ³€ν™˜ν•˜μ—¬ μ €μž₯ν•˜λŠ” λ°©μ‹μœΌλ‘œ, λ¬Έμ„œμ˜ μ£Όμš” νŠΉμ§•λ“€μ„ 벑터 ν˜•νƒœλ‘œ μΈλ±μ‹±ν•˜κ³  λ‚˜μ€‘μ— μœ μ‚¬λ„ 검색을 톡해 κ΄€λ ¨ λ¬Έμ„œλ₯Ό μ°Ύμ•„λ‚Ό 수 μžˆμŠ΅λ‹ˆλ‹€.
    • 예λ₯Ό λ“€μ–΄, λ¬Έμ„œμ—μ„œ μ€‘μš”ν•œ ν‚€μ›Œλ“œλ₯Ό μΆ”μΆœν•˜μ—¬ λ²‘ν„°λ‘œ λ³€ν™˜ν•˜κ³  이λ₯Ό μ €μž₯ν•œ ν›„, 질문과 μœ μ‚¬ν•œ ν‚€μ›Œλ“œλ₯Ό κ°€μ§„ λ¬Έμ„œλ₯Ό κ²€μƒ‰ν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€.

2. Multi-Representation Indexingμ΄λž€?

  • Multi-Representation Indexing은 λ¬Έμ„œμ˜ μ—¬λŸ¬ ν‘œν˜„ 방식을 μ‚¬μš©ν•˜μ—¬ λ¬Έμ„œλ₯Ό μ €μž₯ν•˜κ³  κ²€μƒ‰ν•˜λŠ” κΈ°λ²•μž…λ‹ˆλ‹€.
    • 이 기법은 ν•œ λ¬Έμ„œλ₯Ό λ‹¨μˆœνžˆ λ‚˜λˆ„μ–΄ μ €μž₯ν•˜λŠ” 것이 μ•„λ‹ˆλΌ, LLM을 μ‚¬μš©ν•΄ λ¬Έμ„œλ₯Ό μš”μ•½ν•˜κ³  κ·Έ μš”μ•½μ„ λ²‘ν„°λ‘œ λ³€ν™˜ν•˜μ—¬ μ €μž₯ν•©λ‹ˆλ‹€.
    • λ‚˜μ€‘μ— 검색할 λ•Œ 이 μš”μ•½λœ λ‚΄μš©μ„ 톡해 λ¬Έμ„œλ₯Ό κ²€μƒ‰ν•œ ν›„, 전체 λ¬Έμ„œλ₯Ό λ°˜ν™˜ν•˜λŠ” λ°©μ‹μœΌλ‘œ λ™μž‘ν•©λ‹ˆλ‹€.

  • μ£Όμš” 절차:

    1. λ¬Έμ„œ μš”μ•½: 원본 λ¬Έμ„œλ₯Ό μš”μ•½ν•˜μ—¬ μ€‘μš”ν•œ ν‚€μ›Œλ“œλ₯Ό ν¬ν•¨ν•œ μš”μ•½λ³Έμ„ μƒμ„±ν•©λ‹ˆλ‹€.
    2. μš”μ•½λ³Έ 인덱싱: μš”μ•½λœ λ¬Έμ„œλ₯Ό λ²‘ν„°λ‘œ λ³€ν™˜ν•˜μ—¬ 벑터 μŠ€ν† μ–΄μ— μ €μž₯ν•©λ‹ˆλ‹€.
    3. 전체 λ¬Έμ„œ μ €μž₯: 원본 λ¬Έμ„œλŠ” λ³„λ„μ˜ λ¬Έμ„œ μ €μž₯μ†Œ(Doc Store)에 μ €μž₯ν•˜μ—¬ 검색 후에 원문을 λ°˜ν™˜ν•  수 μžˆλ„λ‘ μ€€λΉ„ν•©λ‹ˆλ‹€.
    4. 검색: μ‚¬μš©μžκ°€ μ§ˆλ¬Έμ„ ν•˜λ©΄, 질문과 μœ μ‚¬ν•œ μš”μ•½λ³Έμ„ 벑터 μŠ€ν† μ–΄μ—μ„œ μ°Ύμ•„λ‚΄κ³ , ν•΄λ‹Ή μš”μ•½λ³Έμ— μ—°κ²°λœ 원본 λ¬Έμ„œλ₯Ό λ¬Έμ„œ μ €μž₯μ†Œμ—μ„œ λ°˜ν™˜ν•©λ‹ˆλ‹€.
  • 이 방식은 μš”μ•½λ³Έμ„ 톡해 λΉ λ₯΄κ²Œ κ²€μƒ‰ν•œ ν›„ 전체 λ¬Έμ„œλ₯Ό λ°˜ν™˜ν•¨μœΌλ‘œμ¨ 검색 μ„±λŠ₯을 ν–₯μƒμ‹œν‚€κ³ , κΈ΄ λ¬Έμ„œλ₯Ό μ²˜λ¦¬ν•˜λŠ” 데 μœ λ¦¬ν•©λ‹ˆλ‹€.

3. Multi-Representation Indexing의 μž₯점

  • λΉ λ₯Έ 검색: μš”μ•½λœ λ‚΄μš©μ„ λ²‘ν„°λ‘œ μΈλ±μ‹±ν•˜κΈ° λ•Œλ¬Έμ— 검색 속도가 λΉ λ¦…λ‹ˆλ‹€.
  • μ •ν™•ν•œ λ¬Έμ„œ λ°˜ν™˜: 검색 ν›„μ—λŠ” 원본 λ¬Έμ„œ 전체λ₯Ό λ°˜ν™˜ν•˜μ—¬ μ§ˆλ¬Έμ— λŒ€ν•œ μΆ©λΆ„ν•œ λ¬Έλ§₯을 μ œκ³΅ν•©λ‹ˆλ‹€.
  • LLM과의 톡합: LLM이 λ¬Έμ„œλ₯Ό μš”μ•½ν•˜κ³  κ·Έ μš”μ•½λ³Έμ„ 검색에 μ‚¬μš©ν•¨μœΌλ‘œμ¨, λ¬Έμ„œμ˜ 핡심 λ‚΄μš©μ„ 기반으둜 더 μ •ν™•ν•œ 검색이 κ°€λŠ₯ν•©λ‹ˆλ‹€.

4. μ½”λ“œ μ„€λͺ…

  • λ‹€μŒμ€ 두 개의 λΈ”λ‘œκ·Έ 포슀트λ₯Ό λ‘œλ“œν•˜κ³ , μš”μ•½ν•˜μ—¬ Multi-Representation Indexing을 μˆ˜ν–‰ν•˜λŠ” μ˜ˆμ‹œμž…λ‹ˆλ‹€.

4.1 μ›Ή λ¬Έμ„œ λ‘œλ“œ 및 μš”μ•½ 생성

  • μœ„ μ½”λ“œλŠ” μ›Ήμ—μ„œ 두 개의 λ¬Έμ„œλ₯Ό λ‘œλ“œν•©λ‹ˆλ‹€. 이후 이 λ¬Έμ„œλ₯Ό μš”μ•½ν•˜μ—¬ 벑터 μŠ€ν† μ–΄μ— μ €μž₯ν•©λ‹ˆλ‹€.
1
2
3
4
5
6
7
8
9
10
from langchain_community.document_loaders import WebBaseLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter

loader = WebBaseLoader("https://lilianweng.github.io/posts/2023-06-23-agent/")
docs = loader.load()

loader = WebBaseLoader("https://lilianweng.github.io/posts/2024-02-05-human-data-quality/")
docs.extend(loader.load())

len(docs) # 2 

4.2 LLM을 μ΄μš©ν•œ λ¬Έμ„œ μš”μ•½

  • 이 μ½”λ“œλŠ” LLM을 μ‚¬μš©ν•˜μ—¬ λ¬Έμ„œλ₯Ό μš”μ•½ν•˜λŠ” 과정을 λ³΄μ—¬μ€λ‹ˆλ‹€. 각 λ¬Έμ„œλŠ” μš”μ•½λ³ΈμœΌλ‘œ λ³€ν™˜λ˜κ³ , 이 μš”μ•½λ³Έμ€ 벑터 μŠ€ν† μ–΄μ— μ €μž₯λ©λ‹ˆλ‹€.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import uuid
from langchain_core.documents import Document
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI

chain = (
    {"doc": lambda x: x.page_content}
    | ChatPromptTemplate.from_template("Summarize the following document:\n\n{doc}")
    | Azure_Chat #ChatOpenAI(model="gpt-3.5-turbo",max_retries=0)
    | StrOutputParser()
)

summaries = chain.batch(docs, {"max_concurrency": 5})
summaries
  • chain.batch(docs, {"max_concurrency": 5})μ—μ„œ max_concurrency: 5λŠ” λ‹€μŒκ³Ό 같은 의미λ₯Ό κ°€μ§‘λ‹ˆλ‹€:

    1. λ™μ‹œ 처리 λ¬Έμ„œ 수: ν•œ λ²ˆμ— μ΅œλŒ€ 5개의 λ¬Έμ„œλ₯Ό λ³‘λ ¬λ‘œ μ²˜λ¦¬ν•©λ‹ˆλ‹€.
    2. 처리 속도 μ΅œμ ν™”: 5κ°œμ”© λ¬Έμ„œλ₯Ό λ¬Άμ–΄ μ²˜λ¦¬ν•¨μœΌλ‘œμ¨ 전체 처리 μ‹œκ°„μ„ λ‹¨μΆ•ν•©λ‹ˆλ‹€.
    3. λ¦¬μ†ŒμŠ€ 관리: μ‹œμŠ€ν…œ λ¦¬μ†ŒμŠ€ μ‚¬μš©μ„ μ œμ–΄ν•˜μ—¬ κ³ΌλΆ€ν•˜λ₯Ό λ°©μ§€ν•©λ‹ˆλ‹€.
  • ν•΄λ‹Ή μ˜ˆμ‹œμ˜ 경우, λ¬Έμ„œκ°€ 2개이기 λ•Œλ¬Έμ— max_concurrency: 5둜 μ„€μ •λ˜μ–΄ μžˆλ”λΌλ„ μ‹€μ œ 처리 과정은 λ‹€μŒκ³Ό 같이 μ§„ν–‰λ©λ‹ˆλ‹€:

    1. λ™μ‹œ 처리: 두 λ¬Έμ„œ λͺ¨λ‘ λ™μ‹œμ— μ²˜λ¦¬λ©λ‹ˆλ‹€. max_concurrencyκ°€ 5둜 μ„€μ •λ˜μ–΄ μžˆμ§€λ§Œ, μ‹€μ œ λ¬Έμ„œ μˆ˜κ°€ 2κ°œμ΄λ―€λ‘œ 2개만 λ³‘λ ¬λ‘œ μ²˜λ¦¬λ©λ‹ˆλ‹€.

4.3 벑터 μŠ€ν† μ–΄ 및 λ¬Έμ„œ μ €μž₯μ†Œ μ„€μ •

  • μ—¬κΈ°μ„œλŠ” μš”μ•½λœ λ¬Έμ„œλ₯Ό 벑터 μŠ€ν† μ–΄μ— μ €μž₯ν•˜κ³ , 원본 λ¬Έμ„œλŠ” λ³„λ„μ˜ λ¬Έμ„œ μ €μž₯μ†Œμ— μ €μž₯ν•˜μ—¬ 검색할 수 μžˆλ„λ‘ μ„€μ •ν•©λ‹ˆλ‹€.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
from langchain.storage import InMemoryByteStore
from langchain_openai import OpenAIEmbeddings
from langchain_community.vectorstores import Chroma
from langchain.retrievers.multi_vector import MultiVectorRetriever

# μš”μ•½λ³Έμ„ μ €μž₯ν•  벑터 μŠ€ν† μ–΄
vectorstore = Chroma(collection_name="summaries", 
                     embedding_function=OpenAIEmbeddings())

# 원본 λ¬Έμ„œλ₯Ό μ €μž₯ν•  λ¬Έμ„œ μ €μž₯μ†Œ
store = InMemoryByteStore()

# μš”μ•½λ³Έκ³Ό 원본 λ¬Έμ„œλ₯Ό μ—°κ²°ν•˜λŠ” ν‚€
id_key = "doc_id"

# μš”μ•½λ³Έκ³Ό 원본 λ¬Έμ„œλ₯Ό ν†΅ν•©ν•˜λŠ” 검색기
retriever = MultiVectorRetriever(vectorstore=vectorstore,
                                 byte_store=store,
                                 id_key=id_key,
                                 )


4.4 λ¬Έμ„œ 검색 및 λ°˜ν™˜

  • 이 μ½”λ“œλŠ” β€œMemory in agentsβ€λΌλŠ” μ§ˆλ¬Έμ— λŒ€ν•΄ μš”μ•½λ³Έμ„ κ²€μƒ‰ν•˜κ³ , ν•΄λ‹Ή μš”μ•½λ³Έμ— μ—°κ²°λœ 원본 λ¬Έμ„œλ₯Ό λ°˜ν™˜ν•©λ‹ˆλ‹€.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# μš”μ•½λ³Έκ³Ό 원본 λ¬Έμ„œ μ—°κ²°
doc_ids = [str(uuid.uuid4()) for _ in docs]
summary_docs = [Document(page_content=s, metadata={id_key: doc_ids[i]}) for i, s in enumerate(summaries)]

# 벑터 μŠ€ν† μ–΄μ— μš”μ•½λ³Έ μΆ”κ°€
retriever.vectorstore.add_documents(summary_docs)

# λ¬Έμ„œ μ €μž₯μ†Œμ— 원본 λ¬Έμ„œ μΆ”κ°€
retriever.docstore.mset(list(zip(doc_ids, docs)))

# 검색 쿼리
query = "Memory in agents"

# μš”μ•½λ³ΈμœΌλ‘œλΆ€ν„° λ¬Έμ„œ 검색
sub_docs = vectorstore.similarity_search(query, k=1)

# κ²€μƒ‰λœ 원본 λ¬Έμ„œ λ°˜ν™˜
retrieved_docs = retriever.get_relevant_documents(query, n_results=1)
retrieved_docs[0].page_content[0:500]

정리

  • Multi-Representation Indexing은 μš”μ•½λ³Έμ„ 톡해 λΉ λ₯΄κ²Œ λ¬Έμ„œλ₯Ό κ²€μƒ‰ν•˜κ³ , κ²€μƒ‰λœ μš”μ•½λ³Έμ— μ—°κ²°λœ 원본 λ¬Έμ„œλ₯Ό λ°˜ν™˜ν•˜λŠ” λ°©μ‹μž…λ‹ˆλ‹€. μ΄λŠ” 검색 μ„±λŠ₯을 μ΅œμ ν™”ν•˜κ³ , κΈ΄ λ¬Έλ§₯을 κ°€μ§„ λ¬Έμ„œλ„ 효율적으둜 μ²˜λ¦¬ν•  수 μžˆλŠ” κΈ°λ²•μž…λ‹ˆλ‹€. 이 방식은 특히 벑터 μŠ€ν† μ–΄λ₯Ό ν™œμš©ν•œ λ¬Έμ„œ κ²€μƒ‰μ—μ„œ 맀우 μœ μš©ν•˜λ©°, LLM을 μ‚¬μš©ν•΄ λ¬Έμ„œλ₯Ό μš”μ•½ν•˜κ³  κ²€μƒ‰ν•˜λŠ” 데 큰 도움이 λ©λ‹ˆλ‹€.

Part 13 (RAPTOR)

  • RAPTORλŠ” 계측적 인덱싱(hierarchical indexing) κΈ°λ²•μœΌλ‘œ, λŒ€κ·œλͺ¨ λ¬Έμ„œλ‚˜ ν…μŠ€νŠΈ λ°μ΄ν„°μ—μ„œ 효율적으둜 정보λ₯Ό κ²€μƒ‰ν•˜λŠ” 데 μ‚¬μš©λ©λ‹ˆλ‹€.

1. RAPTOR κ°œλ…

  • RAPTOR (RECURSIVE ABSTRACTIVE PROCESSING FOR TREE-ORGANIZED RETRIEVAL)λŠ” λ¬Έμ„œ 집합을 μ—¬λŸ¬ λ‹¨κ³„λ‘œ μš”μ•½ν•˜μ—¬ 트리 ꡬ쑰λ₯Ό ν˜•μ„±ν•˜λŠ” κΈ°λ²•μž…λ‹ˆλ‹€. μ΄λŠ” λ‹€μ–‘ν•œ 질문 μœ ν˜•μ— 맞게 정보λ₯Ό μΆ”μΆœν•  수 μžˆλ„λ‘ λ•λŠ” λ°©μ‹μž…λ‹ˆλ‹€.
    • 즉, νŠΉμ • 질문이 세뢀적인 정보λ₯Ό μš”κ΅¬ν•˜λŠ” κ²½μš°μ—λŠ” ν•˜μœ„ λ…Έλ“œ(μ„ΈλΆ€ λ¬Έμ„œλ‚˜ μž‘μ€ 정보 쑰각)λ₯Ό, μƒμœ„ κ°œλ…μ„ λ‹€λ£¨λŠ” μ§ˆλ¬Έμ—λŠ” μƒμœ„ λ…Έλ“œ(λ¬Έμ„œ μš”μ•½)λ₯Ό κ²€μƒ‰ν•˜μ—¬ 닡을 μ œκ³΅ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

2. 계측적 좔상화

  • RAPTOR의 핡심 κ°œλ…μ€ λ°”λ‘œ 계측적 좔상화(hierarchical abstraction)μž…λ‹ˆλ‹€.
    • λ¬Έμ„œλ‚˜ 데이터가 μ—¬λŸ¬ 개의 μž‘μ€ 쑰각으둜 λ‚˜λ‰˜λ©°, 각 쑰각은 μƒμœ„ λ ˆλ²¨μ—μ„œ μš”μ•½λ˜κ³ , 이 과정을 λ°˜λ³΅ν•˜μ—¬ μ΅œμ’…μ μœΌλ‘œ 전체 λ¬Έμ„œλ₯Ό μš”μ•½ν•œ μ΅œμƒμœ„ μš”μ•½μ„ μƒμ„±ν•©λ‹ˆλ‹€.
    • μ΄λ ‡κ²Œ μƒμ„±λœ μš”μ•½ νŠΈλ¦¬λŠ” μ§ˆλ¬Έμ— 따라 μ μ ˆν•œ μˆ˜μ€€μ˜ 정보λ₯Ό μΆ”μΆœν•  수 μžˆλ„λ‘ ν•©λ‹ˆλ‹€.
    • 세뢀적인 μ§ˆλ¬Έμ— λŒ€ν•΄μ„œλŠ” κ°œλ³„ λ¬Έμ„œλ‚˜ μž‘μ€ 데이터 μ‘°κ°μ—μ„œ 정보λ₯Ό κ°€μ Έμ˜€κ³ , 더 큰 λ²”μœ„μ˜ μ§ˆλ¬Έμ— λŒ€ν•΄μ„œλŠ” μƒμœ„ λ ˆλ²¨μ—μ„œ μš”μ•½λœ 정보λ₯Ό κ²€μƒ‰ν•©λ‹ˆλ‹€.

3. RAPTOR의 λ™μž‘ 방식

RATOR의 λ™μž‘μ„ 더 깊이 있게 μ„€λͺ…ν•˜κΈ° μœ„ν•΄ μœ„ μ½”λ“œμ˜ μž‘λ™ 원리와 ꡬ체적인 ν”„λ‘œμ„ΈμŠ€λ₯Ό λ‹€μŒκ³Ό 같이 μ„€λͺ…ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

  • 3.1. λ¬Έμ„œ λ‘œλ“œ 및 벑터화:

    • λ¬Έμ„œμ˜ ν…μŠ€νŠΈ 데이터λ₯Ό λ¨Όμ € λ‘œλ“œν•˜κ³ , 이λ₯Ό λ²‘ν„°ν™”ν•©λ‹ˆλ‹€. λ²‘ν„°ν™”λŠ” ν…μŠ€νŠΈ 데이터λ₯Ό 숫자둜 λ³€ν™˜ν•˜μ—¬ 계산할 수 μžˆλŠ” ν˜•νƒœλ‘œ λ§Œλ“œλŠ” μ€‘μš”ν•œ κ³Όμ •μž…λ‹ˆλ‹€. 이 λ‹¨κ³„μ—μ„œλŠ” λ¬Έμ„œ λ‚΄μ—μ„œ λ‹¨μ–΄λ‚˜ λ¬Έμž₯ κ°„μ˜ 의미적 μœ μ‚¬λ„λ₯Ό λ°˜μ˜ν•  수 μžˆλ„λ‘ 각 λ¬Έμ„œκ°€ κ³ μ°¨μ›μ˜ λ²‘ν„°λ‘œ ν‘œν˜„λ©λ‹ˆλ‹€. λ²‘ν„°ν™”λœ λ°μ΄ν„°λŠ” 이후 ν΄λŸ¬μŠ€ν„°λ§μ΄λ‚˜ κ²€μƒ‰μ—μ„œ ν™œμš©λ©λ‹ˆλ‹€.

      1
      2
      3
      
      docs = loader.load()  # λ¬Έμ„œ λ‘œλ“œ
      docs_texts = [d.page_content for d in docs]  # ν…μŠ€νŠΈ μΆ”μΆœ
      text_embeddings = embd.embed_documents(docs_texts)  # λ¬Έμ„œ 벑터화
      
  • 3.2. ν΄λŸ¬μŠ€ν„°λ§ 및 μš”μ•½:

    • λ¬Έμ„œ κ°„ μœ μ‚¬μ„±μ„ κΈ°μ€€μœΌλ‘œ ν΄λŸ¬μŠ€ν„°λ§μ„ μˆ˜ν–‰ν•©λ‹ˆλ‹€. ν΄λŸ¬μŠ€ν„°λ§μ€ λΉ„μŠ·ν•œ λ¬Έμ„œλ“€μ„ λ¬Άμ–΄μ£ΌλŠ” κ³Όμ •μœΌλ‘œ, Gaussian Mixture Model (GMM)을 ν™œμš©ν•˜μ—¬ ν΄λŸ¬μŠ€ν„°μ˜ 개수λ₯Ό κ²°μ •ν•˜κ³  각 λ¬Έμ„œκ°€ μ–΄λŠ ν΄λŸ¬μŠ€ν„°μ— μ†ν•˜λŠ”μ§€ κ²°μ •ν•©λ‹ˆλ‹€. 이후 ν΄λŸ¬μŠ€ν„° λ‚΄ λ¬Έμ„œλ“€μ„ μš”μ•½ν•˜μ—¬ 각 ν΄λŸ¬μŠ€ν„°μ˜ μ£Όμš” λ‚΄μš©μ„ κ°„κ²°ν•˜κ²Œ μ •λ¦¬ν•©λ‹ˆλ‹€.

      1
      
      df_clusters, df_summary = embed_cluster_summarize_texts(docs_texts, level=1)
      
    • embed_cluster_summarize_texts ν•¨μˆ˜

      1
      2
      3
      
      def embed_cluster_summarize_texts(
          texts: List[str], level: int
      ) -> Tuple[pd.DataFrame, pd.DataFrame]:
      
      • κΈ°λŠ₯: μ£Όμ–΄μ§„ ν…μŠ€νŠΈ λͺ©λ‘μ„ μž„λ² λ”©ν•˜κ³ , ν΄λŸ¬μŠ€ν„°λ§μ„ μˆ˜ν–‰ν•œ ν›„ ν΄λŸ¬μŠ€ν„° λ‚΄μ˜ λ¬Έμ„œλ“€μ„ μš”μ•½ν•©λ‹ˆλ‹€. 결과적으둜 ν΄λŸ¬μŠ€ν„°ν™”λœ λ¬Έμ„œ 정보와 각 ν΄λŸ¬μŠ€ν„°μ˜ μš”μ•½ 정보λ₯Ό λ°˜ν™˜ν•©λ‹ˆλ‹€.
      • μž…λ ₯ 인자:

        • texts: λ¬Έμ„œμ˜ 리슀트둜, 각 λ¬Έμ„œκ°€ λ¬Έμžμ—΄λ‘œ ν‘œν˜„λ©λ‹ˆλ‹€. 이 λ¦¬μŠ€νŠΈλŠ” ν΄λŸ¬μŠ€ν„°λ§μ˜ λŒ€μƒμ΄ λ˜λŠ” ν…μŠ€νŠΈ 데이터λ₯Ό λ‹΄κ³  μžˆμŠ΅λ‹ˆλ‹€.
        • level: ν΄λŸ¬μŠ€ν„°λ§ 및 μš”μ•½μ˜ 깊이λ₯Ό λ‚˜νƒ€λ‚΄λŠ” λ§€κ°œλ³€μˆ˜μž…λ‹ˆλ‹€. 주둜 μž¬κ·€μ  μš”μ•½ κ³Όμ •μ—μ„œ 이 값이 μ¦κ°€ν•©λ‹ˆλ‹€.
      • 좜λ ₯:

        • df_clusters: 각 λ¬Έμ„œμ™€ κ·Έ μž„λ² λ”©, ν΄λŸ¬μŠ€ν„° 정보가 λ‹΄κΈ΄ DataFrame.
        • df_summary: 각 ν΄λŸ¬μŠ€ν„°μ˜ μš”μ•½ 정보가 λ‹΄κΈ΄ DataFrame.
  • 3.3. μž¬κ·€μ  μš”μ•½:

    • ν΄λŸ¬μŠ€ν„°λ³„ μš”μ•½μ„ ν•œ 번 μˆ˜ν–‰ν•œ ν›„, 이λ₯Ό λ‹€μ‹œ μƒμœ„ λ ˆλ²¨μ—μ„œ ν΄λŸ¬μŠ€ν„°λ§ν•˜κ³  μš”μ•½ν•˜λŠ” 과정을 λ°˜λ³΅ν•©λ‹ˆλ‹€. 이λ₯Ό 톡해 λ¬Έμ„œμ˜ 계측적 ꡬ쑰λ₯Ό λΆ„μ„ν•˜κ³ , κ³ μˆ˜μ€€ μš”μ•½μ„ μ μ§„μ μœΌλ‘œ 생성할 수 μžˆμŠ΅λ‹ˆλ‹€. μž¬κ·€μ  μš”μ•½μ„ 톡해 λ¬Έμ„œ 전체λ₯Ό 더 잘 이해할 수 μžˆλ„λ‘ λ•μŠ΅λ‹ˆλ‹€.

      1
      
      results = recursive_embed_cluster_summarize(docs_texts, level=1, n_levels=3)
      
    • recursive_embed_cluster_summarize ν•¨μˆ˜

      1
      2
      3
      
      def recursive_embed_cluster_summarize(
          texts: List[str], level: int = 1, n_levels: int = 3
      ) -> Dict[int, Tuple[pd.DataFrame, pd.DataFrame]]:
      
      • κΈ°λŠ₯: μ£Όμ–΄μ§„ ν…μŠ€νŠΈ λͺ©λ‘μ— λŒ€ν•΄ μž¬κ·€μ μœΌλ‘œ ν΄λŸ¬μŠ€ν„°λ§κ³Ό μš”μ•½μ„ μˆ˜ν–‰ν•˜λŠ” ν•¨μˆ˜μž…λ‹ˆλ‹€. 기본적으둜 3λ‹¨κ³„κΉŒμ§€ μž¬κ·€λ₯Ό μˆ˜ν–‰ν•˜λ©°, 각 λ‹¨κ³„μ—μ„œ μƒμ„±λœ ν΄λŸ¬μŠ€ν„°μ™€ μš”μ•½ κ²°κ³Όλ₯Ό μ €μž₯ν•©λ‹ˆλ‹€.
      • μž…λ ₯ 인자:

        • texts: ν΄λŸ¬μŠ€ν„°λ§ 및 μš”μ•½ λŒ€μƒμ΄ λ˜λŠ” ν…μŠ€νŠΈ 데이터 리슀트.
        • level: ν˜„μž¬ μž¬κ·€ μˆ˜μ€€μ„ λ‚˜νƒ€λƒ…λ‹ˆλ‹€. 기본값은 1이며, μž¬κ·€ 호좜 μ‹œ 이 값이 μ¦κ°€ν•©λ‹ˆλ‹€.
        • n_levels: μž¬κ·€ 호좜의 μ΅œλŒ€ 깊이둜, 기본값은 3μž…λ‹ˆλ‹€. μ΅œλŒ€ 3λ‹¨κ³„κΉŒμ§€ μž¬κ·€μ μœΌλ‘œ ν΄λŸ¬μŠ€ν„°λ§ 및 μš”μ•½μ„ μˆ˜ν–‰ν•©λ‹ˆλ‹€.
      • 좜λ ₯:

        • 각 μž¬κ·€ λ ˆλ²¨λ³„ ν΄λŸ¬μŠ€ν„° 및 μš”μ•½ 정보λ₯Ό λ‹΄κ³  μžˆλŠ” Dict.
        • 각 레벨의 κ²°κ³ΌλŠ” νŠœν”Œ ν˜•νƒœμ˜ (df_clusters, df_summary).
  • 3.4. 검색 κΈ°λŠ₯ κ΅¬ν˜„:

    • λ²‘ν„°ν™”λœ λ¬Έμ„œλ“€μ„ 벑터 μŠ€ν† μ–΄μ— μΈλ±μ‹±ν•˜μ—¬ μ‚¬μš©μžκ°€ μ§ˆλ¬Έν•  λ•Œ κ΄€λ ¨ λ¬Έμ„œλ₯Ό 검색할 수 μžˆλŠ” κΈ°λŠ₯을 κ΅¬ν˜„ν•©λ‹ˆλ‹€. 이λ₯Ό 톡해 μ‚¬μš©μžλŠ” λ°©λŒ€ν•œ μ–‘μ˜ λ¬Έμ„œ μ€‘μ—μ„œ μ›ν•˜λŠ” 정보λ₯Ό μ‹ μ†ν•˜κ²Œ 검색할 수 μžˆμŠ΅λ‹ˆλ‹€.

      1
      2
      
      vectorstore = Chroma.from_texts(texts=all_texts, embedding=embd)
      retriever = vectorstore.as_retriever()
      
    • 벑터 μŠ€ν† μ–΄λŠ” λ¬Έμ„œμ˜ 벑터화λ₯Ό μ €μž₯ν•˜κ³  κ΄€λ¦¬ν•˜λ©°, μƒˆλ‘œμš΄ μž…λ ₯ μ§ˆλ¬Έμ— λŒ€ν•΄ κ°€μž₯ κ΄€λ ¨μ„± 높은 λ¬Έμ„œλ“€μ„ λ°˜ν™˜ν•©λ‹ˆλ‹€.
    • retrieverλŠ” 검색 μ‹œμ— μœ μ‚¬ν•œ λ¬Έμ„œλ₯Ό μ°ΎλŠ” 역할을 ν•˜λ©°, 벑터 κ°„μ˜ 거리λ₯Ό κ³„μ‚°ν•˜μ—¬ κ°€μž₯ κ°€κΉŒμš΄ λ¬Έμ„œλ“€μ„ λ°˜ν™˜ν•©λ‹ˆλ‹€.
  • 3.5. RAG 체인 ꡬ성:

    • κ²€μƒ‰λœ λ¬Έμ„œλ“€μ„ 기반으둜 닡변을 μƒμ„±ν•˜λŠ” RAG (Retrieval-Augmented Generation) 체인을 κ΅¬μ„±ν•©λ‹ˆλ‹€. RAGλŠ” κ²€μƒ‰λœ λ¬Έμ„œλ₯Ό 기반으둜 더 ꡬ체적이고 λ§₯락에 λ§žλŠ” 닡변을 생성할 수 μžˆλŠ” λͺ¨λΈλ‘œ, 검색 κ²°κ³Όλ₯Ό λ¬Έλ§₯에 λ§žμΆ”μ–΄ 잘 μ •λ¦¬ν•˜μ—¬ μ œκ³΅ν•˜λŠ” κ°•λ ₯ν•œ λ°©λ²•λ‘ μž…λ‹ˆλ‹€.

      1
      2
      3
      4
      5
      6
      7
      
      rag_chain = (
          {"context": retriever | format_docs, "question": RunnablePassthrough()}
          | prompt
          | model
          | StrOutputParser()
      )
      rag_chain.invoke("How to define a RAG chain?")
      
    • μ§ˆλ¬Έμ„ μž…λ ₯λ°›μœΌλ©΄ κ²€μƒ‰λœ λ¬Έμ„œμ˜ λ‚΄μš©κ³Ό μ§ˆλ¬Έμ„ κ²°ν•©ν•˜μ—¬ λ¬Έμ„œμ˜ μ€‘μš”ν•œ λ‚΄μš©μ„ 기반으둜 닡변을 μƒμ„±ν•©λ‹ˆλ‹€.
    • StrOutputParserλŠ” μƒμ„±λœ ν…μŠ€νŠΈλ₯Ό ν›„μ²˜λ¦¬ν•˜μ—¬ κ΅¬μ‘°ν™”λœ 응닡을 λ°˜ν™˜ν•©λ‹ˆλ‹€.

Part 14 (ColBERT)

  • 이번 κ°•μ˜λŠ” ColBERTλΌλŠ” μƒˆλ‘œμš΄ 검색 방법둠을 λ‹€λ£Ήλ‹ˆλ‹€. ColBERTλŠ” 기쑴의 μž„λ² λ”© λ°©μ‹μ—μ„œ λ°œμƒν•˜λŠ” ν•œκ³„λ₯Ό λ³΄μ™„ν•˜μ—¬, 더 λ‚˜μ€ λ¬Έμ„œ 검색 μ„±λŠ₯을 μ œκ³΅ν•˜λŠ” λ°©λ²•μž…λ‹ˆλ‹€. 이번 μ„€λͺ…μ—μ„œλŠ” ColBERT의 κ°œλ…κ³Ό κ·Έ κ΅¬ν˜„ 방법을 μžμ„Ένžˆ μ‚΄νŽ΄λ³΄κ² μŠ΅λ‹ˆλ‹€.

1. ColBERT의 κ°œλ…

  • λ‹€μŒ νŒ¨ν‚€μ§€λ₯Ό μ„€μΉ˜ν•˜μ…”μ•Ό μ‚¬μš©μ΄ κ°€λŠ₯ν•©λ‹ˆλ‹€:
1
! pip install -U ragatouille

1.1 전톡적인 μž„λ² λ”© λ°©λ²•μ˜ ν•œκ³„

  • 기쑴의 λ¬Έμ„œ 검색은 λ¬Έμ„œ 전체λ₯Ό ν•˜λ‚˜μ˜ λ²‘ν„°λ‘œ μž„λ² λ”©(embedding) ν•˜μ—¬ 이λ₯Ό μ΄μš©ν•œ K-μ΅œκ·Όμ ‘ 이웃(K-Nearest Neighbors, KNN) λ°©μ‹μœΌλ‘œ 검색을 μ§„ν–‰ν•©λ‹ˆλ‹€. 즉, λ¬Έμ„œ 전체λ₯Ό ν•˜λ‚˜μ˜ λ²‘ν„°λ‘œ μΆ•μ•½ν•œ ν›„, μ§ˆλ¬Έμ„ 같은 λ°©μ‹μœΌλ‘œ λ²‘ν„°ν™”ν•˜μ—¬ 두 벑터 κ°„μ˜ μœ μ‚¬λ„λ₯Ό 계산해 κ°€μž₯ μœ μ‚¬ν•œ λ¬Έμ„œλ₯Ό μ°ΎλŠ” λ°©μ‹μž…λ‹ˆλ‹€.
    • ν•˜μ§€λ§Œ 이 방식은 λ¬Έμ„œ 전체λ₯Ό ν•˜λ‚˜μ˜ λ²‘ν„°λ‘œ μ••μΆ•ν•˜λŠ” κ³Όμ •μ—μ„œ λ§Žμ€ μ„ΈλΆ€ 정보(nuance) λ₯Ό μžƒμ„ 수 μžˆλ‹€λŠ” ν•œκ³„λ₯Ό κ°€μ§€κ³  μžˆμŠ΅λ‹ˆλ‹€.

1.2 ColBERT의 ν•΄κ²°μ±…

  • ColBERT (Contextualized Late Interaction over BERT)λŠ” μ΄λŸ¬ν•œ 문제λ₯Ό ν•΄κ²°ν•˜κΈ° μœ„ν•΄ λ¬Έμ„œλ₯Ό λ‹¨μˆœνžˆ ν•˜λ‚˜μ˜ λ²‘ν„°λ‘œ μΆ•μ•½ν•˜μ§€ μ•Šκ³ , λ¬Έμ„œλ₯Ό μ—¬λŸ¬ 토큰(token)으둜 λ‚˜λˆ„μ–΄ 각 토큰에 λŒ€ν•΄ κ°œλ³„ μž„λ² λ”©μ„ μƒμ„±ν•©λ‹ˆλ‹€.
  • 그리고 μ§ˆλ¬Έμ— λŒ€ν•΄μ„œλ„ λ™μΌν•œ λ°©μ‹μœΌλ‘œ μž„λ² λ”©μ„ μ§„ν–‰ν•˜μ—¬, 각 질문의 토큰과 λ¬Έμ„œμ˜ λͺ¨λ“  토큰 κ°„μ˜ μœ μ‚¬λ„λ₯Ό κ³„μ‚°ν•©λ‹ˆλ‹€. - 각 질문 토큰이 λ¬Έμ„œ λ‚΄μ—μ„œ κ°€μž₯ μœ μ‚¬ν•œ 토큰을 μ°Ύκ³ , 이 μœ μ‚¬λ„ κ°’λ“€μ˜ 합을 μ΅œμ’…μ μœΌλ‘œ λ¬Έμ„œμ™€ 질문 κ°„μ˜ μœ μ‚¬λ„λ‘œ μ‚¬μš©ν•©λ‹ˆλ‹€.

2. ColBERT의 λ™μž‘ 방식

2.1 토큰화 및 μž„λ² λ”©

  • λ¬Έμ„œλ₯Ό μž„λ² λ”©ν•  λ•Œ, ColBERTλŠ” λ¬Έμ„œ 전체λ₯Ό ν•˜λ‚˜μ˜ λ²‘ν„°λ‘œ μ••μΆ•ν•˜λŠ” λŒ€μ‹  토큰화(tokenization) λ₯Ό μ§„ν–‰ν•©λ‹ˆλ‹€. 토큰은 λ¬Έμ„œμ˜ 각 λ‹¨μ–΄λ‚˜ 의미 μžˆλŠ” λ‹¨μœ„λ‘œ λ‚˜λ‰©λ‹ˆλ‹€.
  • 각 토큰에 λŒ€ν•΄ κ°œλ³„μ μΈ 벑터(μž„λ² λ”©) λ₯Ό μƒμ„±ν•©λ‹ˆλ‹€. 이 κ³Όμ •μ—μ„œ 각 ν† ν°μ˜ μœ„μΉ˜ 정보(positional information) κ°€ λ°˜μ˜λ©λ‹ˆλ‹€.

2.2 μ§ˆλ¬Έμ— λŒ€ν•œ 처리

  • μ§ˆλ¬Έλ„ λ¬Έμ„œμ™€ λ™μΌν•œ λ°©μ‹μœΌλ‘œ 토큰화 및 μž„λ² λ”©μ΄ μ΄λ£¨μ–΄μ§‘λ‹ˆλ‹€. 질문의 각 토큰에 λŒ€ν•΄ μž„λ² λ”© 벑터가 μƒμ„±λ˜λ©°, λ¬Έμ„œμ™€μ˜ μœ μ‚¬λ„λ₯Ό 계산할 μ€€λΉ„λ₯Ό ν•©λ‹ˆλ‹€.

2.3 μœ μ‚¬λ„ 계산

  • 질문의 각 토큰에 λŒ€ν•΄, λ¬Έμ„œμ˜ λͺ¨λ“  토큰과 μœ μ‚¬λ„λ₯Ό κ³„μ‚°ν•©λ‹ˆλ‹€. 각 질문 토큰에 λŒ€ν•΄ λ¬Έμ„œμ—μ„œ κ°€μž₯ μœ μ‚¬ν•œ 토큰을 μ°Ύκ³ , 이 μœ μ‚¬λ„ 값을 μ €μž₯ν•©λ‹ˆλ‹€.
  • 질문의 λͺ¨λ“  토큰에 λŒ€ν•΄ 이 과정을 λ°˜λ³΅ν•œ ν›„, μœ μ‚¬λ„ κ°’λ“€μ˜ ν•©(sum of maximum similarities) 을 μ΅œμ’… μœ μ‚¬λ„λ‘œ μ‚¬μš©ν•©λ‹ˆλ‹€.
  • 이 방식은 λ¬Έμ„œ μ „μ²΄μ˜ 정보λ₯Ό ν•˜λ‚˜λ‘œ μ••μΆ•ν•˜λŠ” λŒ€μ‹ , 각각의 μ„ΈλΆ€ 정보가 μœ μ§€λ˜λ„λ‘ ν•˜μ—¬ 더 μ •ν™•ν•œ 검색 κ²°κ³Όλ₯Ό μ œκ³΅ν•©λ‹ˆλ‹€.

3. ColBERT의 νŠΉμ§•

  • ColBERTλŠ” λ¬Έμ„œμ˜ 세뢀적인 정보λ₯Ό 효과적으둜 λ°˜μ˜ν•˜κΈ° λ•Œλ¬Έμ—, κΈ΄ λ¬Έμ„œλ‚˜ λ³΅μž‘ν•œ μ§ˆλ¬Έμ— λŒ€ν•œ 검색 μ„±λŠ₯이 λ›°μ–΄λ‚©λ‹ˆλ‹€.
    • ν•˜μ§€λ§Œ 이 방식은 λͺ¨λ“  토큰 κ°„μ˜ μœ μ‚¬λ„λ₯Ό κ³„μ‚°ν•˜κΈ° λ•Œλ¬Έμ— 처리 속도가 느릴 수 있으며, μ‹€μ‹œκ°„ 응닡이 ν•„μš”ν•œ ν™˜κ²½μ—μ„œλŠ” μ„±λŠ₯ λ¬Έμ œκ°€ λ°œμƒν•  수 μžˆμŠ΅λ‹ˆλ‹€.

4. ColBERT κ΅¬ν˜„ μ˜ˆμ‹œ

  • 이제 ColBERTλ₯Ό μ‚¬μš©ν•˜λŠ” μ½”λ“œ μ˜ˆμ‹œλ₯Ό μ‚΄νŽ΄λ³΄κ² μŠ΅λ‹ˆλ‹€.

4.1 Load Pretrained Model

1
2
from ragatouille import RAGPretrainedModel
RAG = RAGPretrainedModel.from_pretrained("colbert-ir/colbertv2.0")

4.2 Load Docs from Wikipedia

  • 이 μ½”λ“œλŠ” ColBERT λͺ¨λΈμ„ μ‚¬μš©ν•˜μ—¬ Hayao Miyazaki의 Wikipedia νŽ˜μ΄μ§€λ₯Ό κ°€μ Έμ™€μ„œ 토큰화 및 인덱싱을 μ§„ν–‰ν•˜λŠ” κ³Όμ •μž…λ‹ˆλ‹€.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
import requests

def get_wikipedia_page(title: str):
    """
    Retrieve the full text content of a Wikipedia page.

    :param title: str - Title of the Wikipedia page.
    :return: str - Full text content of the page as raw string.
    """
    # Wikipedia API endpoint
    URL = "https://en.wikipedia.org/w/api.php"

    # Parameters for the API request
    params = {
        "action": "query",
        "format": "json",
        "titles": title,
        "prop": "extracts",
        "explaintext": True,
    }

    # Custom User-Agent header to comply with Wikipedia's best practices
    headers = {"User-Agent": "RAGatouille_tutorial/0.0.1 (ben@clavie.eu)"}

    response = requests.get(URL, params=params, headers=headers)
    data = response.json()

    # Extracting page content
    page = next(iter(data["query"]["pages"].values()))
    return page["extract"] if "extract" in page else None

# Get Document
full_document = get_wikipedia_page("Hayao_Miyazaki")

# Create Index
RAG.index(
    collection=[full_document],
    index_name="Miyazaki-123",
    max_document_length=180,
    split_documents=True,
)

4.3 Search Query

  • 이제 λ¬Έμ„œμ— λŒ€ν•΄ μ§ˆλ¬Έμ„ 던져 κ²€μƒ‰ν•˜λŠ” 과정을 μ§„ν–‰ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
1
2
3
results = RAG.search(query="What animation studio did Miyazaki found?", k=3)

results
  • μœ„ μ½”λ“œλ₯Ό μ‹€ν–‰ν•˜λ©΄, β€œMiyazakiκ°€ μ„€λ¦½ν•œ μ• λ‹ˆλ©”μ΄μ…˜ μŠ€νŠœλ””μ˜€λŠ”?β€μ΄λΌλŠ” μ§ˆλ¬Έμ— λŒ€ν•΄ κ΄€λ ¨λœ 닡변이 κ²€μƒ‰λ©λ‹ˆλ‹€.

4.4 Merge with LangChain

  • LangChain λ‚΄μ—μ„œ ColBERTλ₯Ό retriever둜 μ‚¬μš©ν•˜μ—¬ 더 λ³΅μž‘ν•œ 응닡을 μ²˜λ¦¬ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
1
2
3
retriever = RAG.as_langchain_retriever(k=3)

retriever.invoke("What animation studio did Miyazaki found?")
  • 이 μ½”λ“œλ₯Ό 톡해 LangChainμ—μ„œ ColBERTλ₯Ό μ‚¬μš©ν•˜μ—¬ 검색 κΈ°λŠ₯을 κ°•ν™”ν•  수 μžˆμŠ΅λ‹ˆλ‹€.



-->