Pinecone 벡터 스토어 - 하이브리드 검색
Pinecone 벡터 스토어 - 하이브리드 검색
Pinecone을 사용해 희소 벡터(sparse vector)와 밀집 벡터(dense vector)를 함께 활용하는 하이브리드 검색을 구현하는 방법을 보여드릴게요. add_sparse_vector=True 옵션을 켜면 각 문서의 희소 벡터까지 자동으로 계산해서 저장합니다. 검색 품질을 더 올리고 싶다면 커스텀 희소 임베딩 모델로 교체할 수도 있어요.
출처: 문서
본문
Colab에서 노트북을 여신다면 LlamaIndex 🦙를 설치해야 할 수 있어요.
%pip install llama-index-vector-stores-pinecone "transformers[torch]"
Pinecone 인덱스 만들기
from pinecone import Pinecone, ServerlessSpec
import os
os.environ["PINECONE_API_KEY"] = "..."
os.environ["OPENAI_API_KEY"] = "sk-..."
api_key = os.environ["PINECONE_API_KEY"]
pc = Pinecone(api_key=api_key)
# 필요하면 삭제
pc.delete_index("quickstart")
# 차원은 text-embedding-ada-002 용
# 참고: 하이브리드 검색에는 dotproduct 메트릭이 필요해요
pc.create_index(
name="quickstart",
dimension=1536,
metric="dotproduct",
spec=ServerlessSpec(cloud="aws", region="us-east-1"),
)
# Pod 기반 Pinecone 인덱스가 필요하다면 이렇게도 만들 수 있어요:
#
# from pinecone import Pinecone, PodSpec
#
# pc = Pinecone(api_key='xxx')
#
# pc.create_index(
# name='my-index',
# dimension=1536,
# metric='cosine',
# spec=PodSpec(
# environment='us-east1-gcp',
# pod_type='p1.x1',
# pods=1
# )
# )
#
pinecone_index = pc.Index("quickstart")
데이터 다운로드
!mkdir -p 'data/paul_graham/'
!wget 'https://raw.githubusercontent.com/run-llama/llama_index/main/docs/examples/data/paul_graham/paul_graham_essay.txt' -O 'data/paul_graham/paul_graham_essay.txt'
문서를 불러와 PineconeVectorStore 만들기
add_sparse_vector=True로 설정하면 PineconeVectorStore가 각 문서에 대해 희소 벡터를 계산해요.
기본적으로는 희소 벡터를 만들 때 단순한 토큰 빈도(token frequency)를 사용하지만, 커스텀 희소 임베딩 모델을 지정할 수도 있어요.
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader
from llama_index.vector_stores.pinecone import PineconeVectorStore
from IPython.display import Markdown, display
# 문서 로드
documents = SimpleDirectoryReader("./data/paul_graham/").load_data()
# upsert 시 희소 벡터를 계산하려면 add_sparse_vector=True 지정
from llama_index.core import StorageContext
if "OPENAI_API_KEY" not in os.environ:
raise EnvironmentError(f"Environment variable OPENAI_API_KEY is not set")
vector_store = PineconeVectorStore(
pinecone_index=pinecone_index,
add_sparse_vector=True,
)
storage_context = StorageContext.from_defaults(vector_store=vector_store)
index = VectorStoreIndex.from_documents(
documents, storage_context=storage_context
)
huggingface/tokenizers: The current process just got forked, after parallelism has already been used. Disabling parallelism to avoid deadlocks...
To disable this warning, you can either:
- Avoid using `tokenizers` before the fork if possible
- Explicitly set the environment variable TOKENIZERS_PARALLELISM=(true | false)
Upserted vectors: 0%| | 0/22 [00:00<?, ?it/s]
인덱스 질의하기 (Query Index)
인덱스가 준비되기까지 1~2분 정도 기다려야 할 수 있어요
# 더 자세한 출력을 보려면 Logging을 DEBUG로 설정
query_engine = index.as_query_engine(vector_store_query_mode="hybrid")
response = query_engine.query("What happened at Viaweb?")
display(Markdown(f"<b>{response}</b>"))
Paul Graham이 돈이 필요해서 Viaweb을 시작했다는 답변이 나옵니다. 회사가 성장하면서 큰 회사를 운영하고 싶지 않다는 걸 깨달았고, 비전의 일부를 오픈소스 프로젝트로 만들기로 했습니다. 결국 1998년 여름 Viaweb을 Yahoo에 매각했고, 이는 Paul Graham에게 큰 안도였다는 내용이네요.
희소 임베딩 모델 바꾸기
%pip install llama-index-sparse-embeddings-fastembed
# 벡터 스토어 비우기
vector_store.clear()
from llama_index.sparse_embeddings.fastembed import FastEmbedSparseEmbedding
sparse_embedding_model = FastEmbedSparseEmbedding(
model_name="prithivida/Splade_PP_en_v1"
)
vector_store = PineconeVectorStore(
pinecone_index=pinecone_index,
add_sparse_vector=True,
sparse_embedding_model=sparse_embedding_model,
)
Fetching 5 files: 0%| | 0/5 [00:00<?, ?it/s]
index = VectorStoreIndex.from_documents(
documents, storage_context=storage_context
)
Upserted vectors: 0%| | 0/22 [00:00<?, ?it/s]
업로드가 끝날 때까지 잠시 기다려 주세요.
response = query_engine.query("What happened at Viaweb?")
display(Markdown(f"<b>{response}</b>"))
Paul Graham이 돈이 필요해서 Viaweb을 시작했다는 답변이 나옵니다. 그는 팀을 모아 애플리케이션 빌더와 네트워크 인프라 구축에 집중하는 소프트웨어·서비스 개발에 매진했습니다. 그런데 여름이 반쯤 지났을 무렵 큰 회사를 운영하고 싶지 않다는 걸 깨달았고, 프로젝트의 일부를 오픈소스로 만들기로 방향을 틀었습니다. 그 결과 Arc라는 새로운 Lisp 계열 언어 개발로 이어졌고, 결국 1998년 여름 Viaweb을 Yahoo에 매각해 안도하며 인생의 새 국면으로 전환하게 됐습니다.