PropertyGraph에서 커스텀 Retriever 정의하기
PropertyGraph에서 커스텀 Retriever 정의하기
PropertyGraph를 위한 커스텀 retriever를 정의하는 노트북이에요. 표준 그래프 검색기보다는 복잡하지만 검색 과정을 세밀하게 제어할 수 있고, 애플리케이션의 요구에 딱 맞게 커스터마이징할 수 있습니다. 벡터 검색과 text-to-Cypher 검색을 함께 수행하고, 그 결과를 reranking 모듈로 통합하는 고급 검색 워크플로도 다룹니다.
출처: 문서
본문
Cohere reranker를 사용하므로 cohere API key가 필요해요.
필요한 패키지를 설치합니다.
%pip install llama-index-core
%pip install llama-index-llms-mistralai
%pip install llama-index-embeddings-mistralai
%pip install llama-index-graph-stores-neo4j
%pip install llama-index-postprocessor-cohere-rerank
import nest_asyncio
nest_asyncio.apply()
from IPython.display import Markdown, display
설정 (Setup)
import os
os.environ['MISTRAL_API_KEY'] = 'YOUR MISTRAL API KEY'
from llama_index.embeddings.mistralai import MistralAIEmbedding
from llama_index.llms.mistralai import MistralAI
llm = MistralAI(model='mistral-large-latest')
embed_model = MistralAIEmbedding()
데이터 다운로드·로드
!mkdir -p 'data/paul_graham/'
!wget 'https://raw.githubusercontent.com/run-llama/llama_index/main/docs/docs/examples/data/paul_graham/paul_graham_essay.txt' -O 'data/paul_graham/paul_graham_essay.txt'
from llama_index.core import SimpleDirectoryReader
documents = SimpleDirectoryReader("./data/paul_graham/").load_data()
Docker 설정
APOC 플러그인을 활성화한 Neo4j 컨테이너를 띄웁니다. 첫 실행 시 로그인하고 비밀번호를 설정해야 해요. (neo4j / neo4j)
!docker run \
-p 7474:7474 -p 7687:7687 \
-v $PWD/data:/data -v $PWD/plugins:/plugins \
--name neo4j-apoc \
-e NEO4J_apoc_export_file_enabled=true \
-e NEO4J_apoc_import_file_enabled=true \
-e NEO4J_apoc_import_file_use__neo4j__config=true \
-e NEO4JLABS_PLUGINS=\[\"apoc\"\] \
neo4j:latest
Neo4j GraphStore 설정
from llama_index.graph_stores.neo4j import Neo4jPropertyGraphStore
graph_store = Neo4jPropertyGraphStore(
username="neo4j",
password="llamaindex",
url="bolt://localhost:7687",
)
PropertyGraphIndex 구성
from llama_index.core import PropertyGraphIndex
index = PropertyGraphIndex.from_documents(
documents,
llm=llm,
embed_model=embed_model,
property_graph_store=graph_store,
show_progress=True,
)
CustomRetriever (커스텀 검색기)
VectorContextRetriever·TextToCypherRetriever·Reranker를 결합한 커스텀 검색기를 정의합니다.
from llama_index.core.retrievers import (
CustomPGRetriever,
VectorContextRetriever,
TextToCypherRetriever,
)
from llama_index.core.graph_stores import PropertyGraphStore
from llama_index.core.vector_stores.types import VectorStore
from llama_index.core.embeddings import BaseEmbedding
from llama_index.core.prompts import PromptTemplate
from llama_index.core.llms import LLM
from llama_index.postprocessor.cohere_rerank import CohereRerank
from typing import Optional, Any, Union
class CustomRetriever(CustomPGRetriever):
"""Custom retriever with cohere reranking."""
def __init__(
self,
## vector context retriever params
embed_model: Optional[BaseEmbedding] = None,
vector_store: Optional[VectorStore] = None,
similarity_top_k: int = 4,
path_depth: int = 1,
## text-to-cypher params
llm: Optional[LLM] = None,
text_to_cypher_template: Optional[Union[PromptTemplate, str]] = None,
## cohere reranker params
cohere_api_key: Optional[str] = None,
cohere_top_n: int = 2,
**kwargs: Any,
) -> None:
"""Uses any kwargs passed in from class constructor."""
self.vector_retriever = VectorContextRetriever(
self.graph_store,
include_text=self.include_text,
embed_model=embed_model,
vector_store=vector_store,
similarity_top_k=similarity_top_k,
path_depth=path_depth,
)
self.cypher_retriever = TextToCypherRetriever(
self.graph_store,
llm=llm,
text_to_cypher_template=text_to_cypher_template
## NOTE: you can attach other parameters here if you'd like
)
self.reranker = CohereRerank(
api_key=cohere_api_key, top_n=cohere_top_n
)
def custom_retrieve(self, query_str: str) -> str:
"""Define custom retriever with reranking.
Could return `str`, `TextNode`, `NodeWithScore`, or a list of those.
"""
nodes_1 = self.vector_retriever.retrieve(query_str)
nodes_2 = self.cypher_retriever.retrieve(query_str)
reranked_nodes = self.reranker.postprocess_nodes(
nodes_1 + nodes_2, query_str=query_str
)
## TMP: please change
final_text = "\n\n".join(
[n.get_content(metadata_mode="llm") for n in reranked_nodes]
)
return final_text
# optional async method
# async def acustom_retrieve(self, query_str: str) -> str:
# ...
from llama_index.core import Settings
Settings.llm = llm
Settings.embed_model=embed_model
정의한 커스텀 검색기를 인스턴스화합니다. cohere API key가 필요해요.
custom_sub_retriever = CustomRetriever(
index.property_graph_store,
include_text=True,
vector_store=index.vector_store,
cohere_api_key="YOUR COHERE API KEY",
)
QueryEngine
커스텀 검색기를 붙인 RetrieverQueryEngine을 만들어 질의합니다.
from llama_index.core.query_engine import RetrieverQueryEngine
query_engine = RetrieverQueryEngine.from_args(
index.as_retriever(sub_retrievers=[custom_sub_retriever]), llm=llm
)
response = query_engine.query("What did author do at Interleaf?")
display(Markdown(f"{response.response}"))
더 알아보기 (Learn more)
- LlamaIndex PropertyGraph 문서 — 지식 그래프 인덱스 가이드
CustomPGRetriever— 커스텀 PropertyGraph 검색기 베이스 클래스TextToCypherRetriever— 질의를 Cypher로 변환해 검색하는 검색기CohereRerank— Cohere 기반 재순위화 포스트프로세서