728x90

전제 조건

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 생성

  1. 링크에서 좌측에 Database를 누른다.
  2. 우하단의 검은색 버튼 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

+ Recent posts