[κ°μλ ΈνΈ] 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 (μΈλ±μ±/λ€μ€ννμΈλ±μ±)
-
μ κ·Έλ¦Όμ λ¨κ³μ λ°λΌ κ° κ³Όμ μ μν κ³Ό κ°λ μ κ°λ΅νκ² μ€λͺ νκ² μ΅λλ€:
- Question (μ§λ¬Έ) : μ¬μ©μκ° μμ€ν μ μ λ ₯νλ μμ°μ΄ ννμ μ§λ¬Έμ λλ€. μ΄λ μ 체 νλ‘μΈμ€μ μμμ μ΄ λ©λλ€.
- Query Translation (쿼리 λ²μ) : μ¬μ©μμ μμ°μ΄ μ§λ¬Έμ μμ€ν μ΄ μ΄ν΄ν μ μλ νμμΌλ‘ λ³ννλ κ³Όμ μ λλ€. μ΄λ μμ°μ΄ μ²λ¦¬ κΈ°μ μ νμ©νμ¬ μνλ©λλ€.
- Routing (λΌμ°ν ) : λ³νλ 쿼리λ₯Ό μ μ ν μ²λ¦¬ κ²½λ‘λ λ°μ΄ν° μμ€λ‘ μλ΄νλ κ³Όμ μ λλ€. μ§λ¬Έμ νΉμ±μ λ°λΌ μ΅μ μ μ²λ¦¬ λ°©λ²μ κ²°μ ν©λλ€.
- Query Construction (쿼리 ꡬμ±) : λΌμ°ν λ μ 보λ₯Ό λ°νμΌλ‘ μ€μ λ°μ΄ν°λ² μ΄μ€λ κ²μ μμ§μμ μ¬μ©ν μ μλ ννμ 쿼리λ₯Ό ꡬμ±ν©λλ€.
- Indexing (μΈλ±μ±, μ΄λ² μ±ν°π) : λ°μ΄ν°λ² μ΄μ€λ λ¬Έμ 컬λ μ μμ ν¨μ¨μ μΈ κ²μμ μν΄ λ°μ΄ν°λ₯Ό ꡬ쑰ννκ³ μ‘°μ§ννλ κ³Όμ μ λλ€. μ΄λ μ£Όλ‘ μμ€ν κ΅¬μΆ λ¨κ³μμ μνλ©λλ€.
- Retrieval (κ²μ) : ꡬμ±λ 쿼리λ₯Ό μ¬μ©νμ¬ μΈλ±μ±λ λ°μ΄ν°μμ κ΄λ ¨ μ 보λ₯Ό μΆμΆνλ κ³Όμ μ λλ€. μ΄ λ¨κ³μμ μ§λ¬Έκ³Ό κ°μ₯ κ΄λ ¨μ± λμ μ 보λ₯Ό μ°Ύμλ λλ€.
- Generation (μμ±) : κ²μλ μ 보λ₯Ό λ°νμΌλ‘ μ§λ¬Έμ λν λ΅λ³μ μμ±νλ κ³Όμ μ λλ€. μ΄ λ¨κ³μμλ μ£Όλ‘ μμ°μ΄ μμ± κΈ°μ μ΄ μ¬μ©λ©λλ€.
- 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μ μ¬μ©ν΄ λ¬Έμλ₯Ό μμ½νκ³ κ·Έ μμ½μ 벑ν°λ‘ λ³ννμ¬ μ μ₯ν©λλ€.
- λμ€μ κ²μν λ μ΄ μμ½λ λ΄μ©μ ν΅ν΄ λ¬Έμλ₯Ό κ²μν ν, μ 체 λ¬Έμλ₯Ό λ°ννλ λ°©μμΌλ‘ λμν©λλ€.
-
μ£Όμ μ μ°¨:
- λ¬Έμ μμ½: μλ³Έ λ¬Έμλ₯Ό μμ½νμ¬ μ€μν ν€μλλ₯Ό ν¬ν¨ν μμ½λ³Έμ μμ±ν©λλ€.
- μμ½λ³Έ μΈλ±μ±: μμ½λ λ¬Έμλ₯Ό 벑ν°λ‘ λ³ννμ¬ λ²‘ν° μ€ν μ΄μ μ μ₯ν©λλ€.
- μ 체 λ¬Έμ μ μ₯: μλ³Έ λ¬Έμλ λ³λμ λ¬Έμ μ μ₯μ(Doc Store)μ μ μ₯νμ¬ κ²μ νμ μλ¬Έμ λ°νν μ μλλ‘ μ€λΉν©λλ€.
- κ²μ: μ¬μ©μκ° μ§λ¬Έμ νλ©΄, μ§λ¬Έκ³Ό μ μ¬ν μμ½λ³Έμ λ²‘ν° μ€ν μ΄μμ μ°Ύμλ΄κ³ , ν΄λΉ μμ½λ³Έμ μ°κ²°λ μλ³Έ λ¬Έμλ₯Ό λ¬Έμ μ μ₯μμμ λ°νν©λλ€.
-
μ΄ λ°©μμ μμ½λ³Έμ ν΅ν΄ λΉ λ₯΄κ² κ²μν ν μ 체 λ¬Έμλ₯Ό λ°νν¨μΌλ‘μ¨ κ²μ μ±λ₯μ ν₯μμν€κ³ , κΈ΄ λ¬Έμλ₯Ό μ²λ¦¬νλ λ° μ 리ν©λλ€.
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
λ λ€μκ³Ό κ°μ μλ―Έλ₯Ό κ°μ§λλ€:- λμ μ²λ¦¬ λ¬Έμ μ: ν λ²μ μ΅λ 5κ°μ λ¬Έμλ₯Ό λ³λ ¬λ‘ μ²λ¦¬ν©λλ€.
- μ²λ¦¬ μλ μ΅μ ν: 5κ°μ© λ¬Έμλ₯Ό λ¬Άμ΄ μ²λ¦¬ν¨μΌλ‘μ¨ μ 체 μ²λ¦¬ μκ°μ λ¨μΆν©λλ€.
- 리μμ€ κ΄λ¦¬: μμ€ν 리μμ€ μ¬μ©μ μ μ΄νμ¬ κ³ΌλΆνλ₯Ό λ°©μ§ν©λλ€.
-
ν΄λΉ μμμ κ²½μ°, λ¬Έμκ° 2κ°μ΄κΈ° λλ¬Έμ
max_concurrency: 5
λ‘ μ€μ λμ΄ μλλΌλ μ€μ μ²λ¦¬ κ³Όμ μ λ€μκ³Ό κ°μ΄ μ§νλ©λλ€:- λμ μ²λ¦¬: λ λ¬Έμ λͺ¨λ λμμ μ²λ¦¬λ©λλ€.
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λ₯Ό μ¬μ©νλ μ½λ μμλ₯Ό μ΄ν΄λ³΄κ² μ΅λλ€.
- μ¬κΈ°μλ RAG λ°©μμ ColBERTλ₯Ό μ μ©νμ¬ λ¬Έμ κ²μμ μνν©λλ€.
- λ§ν¬ : https://python.langchain.com/docs/integrations/retrievers/ragatouille/
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λ₯Ό μ¬μ©νμ¬ κ²μ κΈ°λ₯μ κ°νν μ μμ΅λλ€.