전제 조건
Vector Store에서 Hybrid Search를 지원해야 하기 때문에 이를 지원하는 vector store를 선정한다.
본 예제에서는 Astra DB를 사용한다.
Dependency 설치
우선 관련 Dependency를 설치한다. 터미널에 접속후 아래 명령어를 실행한다.
!pip install "cassio>=0.1.7"
Astra DB 회원 가입 및 DB 생성
이후 링크에 접속해서 회원가입을 하고 연결 정보를 생성한다. 우리에게 필요한건 Database ID
, application token
, keyspace
이다.
사실 위 링크에서 하라는대로 하면 된다
회원가입
이 링크에서 회원가입을 진행한다.
DB 생성
- 이 링크에서 좌측에 Database를 누른다.
- 우하단의 검은색 버튼
Create Database
를 클릭한다.
3. 여기서 Serverless(Vector)를 선택하고 DB 이름을 설정한다. 이름을 한번 설정하면 변경이 불가하니 신중하게 생성한다.
Provider마다 조금씩 region이 다르긴 한데 Lock 되어있는건 비용을 지불해야한다. Asia Region이 없으니 어쩔 수 없이 US east를 선택한다. 설정이 완료되면 Create Database
를 클릭한다.
4. Database가 active 상태가 된 이후 우측에 Application Tokens 탭의 Create Token
을 눌러서 토큰을 생성한다. Token이 생성되면 다시는 확인할 길이 없기 때문에 clipboard에 복사 후 안전한 곳에 저장하자. 해당 토큰은 자동으로 데이터베이스 관리자 역할을 부여받는다. 자세한 사항은 여기
5. 이후 Overview 옆의 Data Explorer를 클릭한다. 현재 Namespace는 "default_keyspace"인데 원하는 Namespace를 생성하면 된다. 생성하는데 시간이 조금 걸린다.
실습
앞서 얻은 정보를 토대로 아래 코드에 정보를 삽입후 실행한다.
import cassio
cassio.init(
database_id="Your database ID",
token="Your application token",
keyspace="Your key space",
)
이후 Cassandra vector store를 Standard index analyzer로 생성한다. 자세한 내용은 이 링크
Vector Store 실험
from cassio.table.cql import STANDARD_ANALYZER
from langchain_community.vectorstores import Cassandra
from langchain_openai import OpenAIEmbeddings
embeddings = OpenAIEmbeddings()
vectorstore = Cassandra(
embedding=embeddings,
table_name="test_hybrid",
body_index_options=[STANDARD_ANALYZER],
session=None,
keyspace=None,
)
vectorstore.add_texts(
[
"In 2023, I visited Paris",
"In 2022, I visited New York",
"In 2021, I visited New Orleans",
]
)
생성 후 결과는 아래와 같다
'ee2a6192e7524ff49c95bd7f82e73d36',
'0ef8aa454fe24569a6363436f8bddca3']
['271c225aaace4586b1c53e32f170013b',
'ee2a6192e7524ff49c95bd7f82e73d36',
'0ef8aa454fe24569a6363436f8bddca3']
이제 일반적인 유사도 검색을 하면 모든 문서가 검색되는 것을 확인할 수 있다.
vectorstore.as_retriever().invoke("What city did I visit last?")
결과는 아래와 같다.
[Document(page_content='In 2022, I visited New York'),
Document(page_content='In 2023, I visited Paris'),
Document(page_content='In 2021, I visited New Orleans')]
근데 Astra DB vector store의 body search
argument를 넣으면 검색 결과를 필터링 할 수 있다.
가령, New
라는 keyword가 들어간 도시 만을 찾고 싶다면 아래와 같이 적용할 수 있다.
vectorstore.as_retriever(search_kwargs={"body_search": "new"}).invoke(
"What city did I visit last?"
)
결과는 다음과 같다.
[Document(page_content='In 2022, I visited New York'),
Document(page_content='In 2021, I visited New Orleans')]
QA chain 생성
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import(
ConfigurableField,
RunnablePassthrough,
)
from langchain_openai import ChatOpenAI
- Prompt Template, model, retriever를 정의한다.
template = """Answer the question based only on the following context: {context} Question: {question} """
prompt = ChatPromptTemplate.from_template(template)
model = ChatOpenAI()
retriever = vectorstore.as_retriever()
- 여기서 Configurable field를 추가한 retriever를 생성한다. 모든 Vector store retriever들은 `search_kwargs`를 field로 가진다.
Vector store 특정 field가 저장된 딕셔너리 타입이다.
```python
configurable_retriever = retriever.configurable_fields(
search_kwargs=ConfigurableField(
id='search_kwargs',
name='Search Kwargs',
description='The search Kwargs to use',
)
)
이제 chain을 구성한다.
chain = (
{"context" : configurable_retriever, "question" : RunnablePassthrough()}
| prompt
| model
| StrOutputParser()
)
실험
cofigurable field에 값을 넣지 않고 invoke 하는 경우 결과
chain.invoke("What city did I visit last?")
결과
'Paris'
하지만 configurable field에 값을 넣은 후에는
chain.invoke(
"What city did I visit last?",
config={"configurable": {"search_kwargs":{"body_search":"new"}}}
)
결과
'New Orleans'
'인공지능 > RAG' 카테고리의 다른 글
What is Elastic Search? (0) | 2024.06.03 |
---|---|
Langchain - Ensemble Retriever (1) | 2024.05.31 |
MongoDB와 Gemma를 사용한 RAG 실습(LangChain X) (0) | 2024.05.28 |
Langchain - MessagesPlaceholder (0) | 2024.05.24 |
Langchain - ChatPromptTemplate (0) | 2024.05.23 |