LlamaIndex를 통해 Elasticsearch로 데이터를 수집하는 방법
라마인덱스를 사용하여 데이터를 수집하고 검색하는 방법에 대한 단계별 안내입니다.
이 문서에서는 데이터 색인을 생성하기 위해 LlamaIndex를 사용하여 FAQ 검색 엔진을 구현해 보겠습니다. Elasticsearch는 벡터 데이터베이스 역할을 하여 벡터 검색을 가능하게 하고, RAG(검색 증강 세대)는 컨텍스트를 보강하여 보다 정확한 응답을 제공합니다.

라마인덱스란 무엇인가요?
LlamaIndex는 특정 또는 비공개 데이터와 상호 작용할 수 있는 대규모 언어 모델(LLM)로 구동되는 에이전트 및 워크플로우를 쉽게 만들 수 있는 프레임워크입니다. 다양한 소스(API, PDF, 데이터베이스)의 데이터를 LLM과 통합하여 연구, 정보 추출, 문맥에 맞는 응답 생성 등의 작업을 수행할 수 있습니다.
주요 개념:
에이전트: 간단한 응답부터 복잡한 작업까지 다양한 작업을 수행하기 위해 LLM을 사용하는 지능형 어시스턴트입니다.
워크플로우: 고급 작업을 위해 에이전트, 데이터 커넥터 및 도구를 결합하는 다단계 프로세스입니다.
컨텍스트 증강: 외부 데이터로 LLM을 보강하여 학습의 한계를 극복하는 기술입니다.
엘라스틱서치와라마인덱스 통합:
Elasticsearch는 LlamaIndex와 함께 다양한 방식으로 사용할 수 있습니다:
데이터 소스: Elasticsearch Reader를 사용하여 문서를 추출합니다.
임베딩 모델: 시맨틱 검색을 위해 데이터를 벡터로 인코딩합니다.
벡터 저장소: 벡터화된 문서를 검색하기 위한 리포지토리로 Elasticsearch를 사용하세요.
고급 스토리지: 문서 요약 또는 지식 그래프와 같은 구조를 구성하세요.
LlamaIndex와 Elasticsearch를 사용하여 FAQ 검색 구축하기
데이터 준비
Elasticsearch 서비스 FAQ를 예로 들어보겠습니다. 각 문제는 웹사이트에서 추출하여 개별 텍스트 파일에 저장했습니다. 어떤 방식으로든 데이터를 정리할 수 있지만, 이 예에서는 파일을 로컬에 저장하는 방법을 선택했습니다.
예제 파일입니다:
File Name: what-is-elasticsearch-service.txt
Content: Elasticsearch Service is hosted and managed Elasticsearch and Kibana brought to you by the creators of Elasticsearch. Elasticsearch Service is part of Elastic Cloud and ships with features that you can only get from the company behind Elasticsearch, Kibana, Beats, and Logstash. Elasticsearch is a full text search engine that suits a range of uses, from search on websites to big data analytics and more.모든 문제를 저장한 후 디렉토리는 다음과 같이 표시됩니다:

종속성 설치
Python 언어를 사용하여 수집 및 검색을 구현할 것이며, 제가 사용한 버전은 3.9입니다. 전제 조건으로 다음 종속성을 설치해야 합니다:
llama-index-vector-stores-elasticsearch
llama-index
openaiElasticsearch와 Kibana는 버전 8.16.2를 실행하도록 docker-compose.yml을 통해 구성된 Docker로 생성됩니다. 이렇게 하면 로컬 환경을 더 쉽게 만들 수 있습니다.
version: '3.8'
services:
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:8.16.2
container_name: elasticsearch-8.16.2
environment:
- node.name=elasticsearch
- xpack.security.enabled=false
- discovery.type=single-node
- "ES_JAVA_OPTS=-Xms1024m -Xmx1024m"
ports:
- 9200:9200
networks:
- shared_network
kibana:
image: docker.elastic.co/kibana/kibana:8.16.2
container_name: kibana-8.16.2
restart: always
environment:
- ELASTICSEARCH_URL=http://elasticsearch:9200
ports:
- 5601:5601
depends_on:
- elasticsearch
networks:
- shared_network
networks:
shared_network:LlamaIndex를 사용한 문서 수집
문서는 LlamaIndex를 사용하여 Elasticsearch로 색인됩니다. 먼저 로컬 디렉터리에서 파일을 로드할 수 있는 SimpleDirectoryReader를 사용하여 파일을 로드합니다. 문서를 로드한 후 벡터스토어인덱스를 사용하여 색인을 생성합니다.
documents = SimpleDirectoryReader("./faq").load_data()
storage_context = StorageContext.from_defaults(vector_store=es)
index = VectorStoreIndex(documents, storage_context=storage_context, embed_model=embed_model)라마인덱스의 벡터 스토어는 문서 임베딩의 저장 및 관리를 담당합니다. LlamaIndex는 다양한 유형의 벡터 저장소를 지원하며, 이 경우에는 Elasticsearch를 사용하겠습니다. StorageContext에서 Elasticsearch 인스턴스를 구성합니다. 컨텍스트가 로컬이므로 추가 매개 변수가 필요하지 않았습니다. 다른 환경에서의 구성은 설명서를 참조하여 필요한 매개 변수를 확인하세요: ElasticsearchStore 구성.
기본적으로 LlamaIndex는 OpenAI 텍스트 임베딩-ada-002 모델을 사용하여 임베딩을 생성합니다. 하지만 이 예제에서는 텍스트 임베딩 3-소형 모델을 사용합니다. 이 모델을 사용하려면 OpenAI API 키가 필요하다는 점에 유의하세요.
아래는 문서 수집을 위한 전체 코드입니다.
import openai
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader, StorageContext
from llama_index.embeddings.openai import OpenAIEmbedding
from llama_index.vector_stores.elasticsearch import ElasticsearchStore
openai.api_key = os.environ["OPENAI_API_KEY"]
es = ElasticsearchStore(
index_name="faq",
es_url="http://localhost:9200"
)
def format_title(filename):
filename_without_ext = filename.replace('.txt', '')
text_with_spaces = filename_without_ext.replace('-', ' ')
formatted_text = text_with_spaces.title()
return formatted_text
embed_model = OpenAIEmbedding(model="text-embedding-3-small")
documents = SimpleDirectoryReader("./faq").load_data()
for doc in documents:
doc.metadata['title'] = format_title(doc.metadata['file_name'])
storage_context = StorageContext.from_defaults(vector_store=es)
index = VectorStoreIndex(documents, storage_context=storage_context, embed_model=embed_model)실행 후 문서가 아래와 같이 FAQ 색인에 색인됩니다:

RAG로 검색
검색을 수행하기 위해 ElasticsearchStore 클라이언트를 구성하여 index_name 및 es_url 필드를 Elasticsearch URL로 설정합니다. retrieval_strategy에서 벡터 검색을 위한 AsyncDenseVectorStrategy를 정의했습니다. AsyncBM25Strategy (키워드 검색) 및 AsyncSparseVectorStrategy (희소 벡터)와 같은 다른 전략도 사용할 수 있습니다. 자세한 내용은 공식 문서에서 확인할 수 있습니다.
es = ElasticsearchStore(
index_name="faq",
es_url="http://localhost:9200",
retrieval_strategy=AsyncDenseVectorStrategy(
)
)다음으로, VectorStoreIndex 객체가 생성되며, 여기서 ElasticsearchStore 객체를 사용하여 vector_store를 구성합니다. as_retriever 메서드를 사용하면 유사성_top_k 매개변수를 통해 반환되는 결과의 수를 5로 설정하여 쿼리와 가장 관련성이 높은 문서를 검색합니다.
index = VectorStoreIndex.from_vector_store(vector_store=es)
retriever = index.as_retriever(similarity_top_k=5)
results = retriever.retrieve(query)다음 단계는 RAG입니다. 벡터 검색 결과는 LLM을 위한 형식화된 프롬프트에 통합되어 검색된 정보에 따라 상황에 맞는 응답이 가능합니다.
프롬프트 템플릿에서는 프롬프트 형식을 정의하며, 여기에는 다음이 포함됩니다:
컨텍스트 ({context_str}): 검색기가 검색한 문서입니다.
쿼리 ({query_str}): 사용자의 질문입니다.
지침: 모델이 외부 지식에 의존하지 않고 상황에 따라 대응할 수 있도록 하는 지침입니다.
qa_prompt = PromptTemplate(
"You are a helpful and knowledgeable assistant."
"Your task is to answer the user's query based solely on the context provided below."
"Do not use any prior knowledge or external information.\n"
"---------------------\n"
"Context:\n"
"{context_str}\n"
"---------------------\n"
"Query: {query_str}\n"
"Instructions:\n"
"1. Carefully read and understand the context provided.\n"
"2. If the context contains enough information to answer the query, provide a clear and concise answer.\n"
"3. Do not make up or guess any information.\n"
"Answer: "
)마지막으로 LLM이 프롬프트를 처리하고 상황에 맞는 정확한 응답을 반환합니다.
llm = OpenAI(model="gpt-4o")
context_str = "\n\n".join([n.node.get_content() for n in results])
response = llm.complete(
qa_prompt.format(context_str=context_str, query_str=query)
)
print("Answer:")
print(response)전체 코드는 아래와 같습니다:
es = ElasticsearchStore(
index_name="faq",
es_url="http://localhost:9200",
retrieval_strategy=AsyncDenseVectorStrategy(
)
)
def print_results(results):
for rank, result in enumerate(results, start=1):
title = result.metadata.get("title")
score = result.get_score()
text = result.get_text()
print(f"{rank}. title={title} \nscore={score} \ncontent={text}")
def search(query: str):
index = VectorStoreIndex.from_vector_store(vector_store=es)
retriever = index.as_retriever(similarity_top_k=10)
results = retriever.retrieve(QueryBundle(query_str=query))
print_results(results)
qa_prompt = PromptTemplate(
"You are a helpful and knowledgeable assistant."
"Your task is to answer the user's query based solely on the context provided below."
"Do not use any prior knowledge or external information.\n"
"---------------------\n"
"Context:\n"
"{context_str}\n"
"---------------------\n"
"Query: {query_str}\n"
"Instructions:\n"
"1. Carefully read and understand the context provided.\n"
"2. If the context contains enough information to answer the query, provide a clear and concise answer.\n"
"3. Do not make up or guess any information.\n"
"Answer: "
)
llm = OpenAI(model="gpt-4o")
context_str = "\n\n".join([n.node.get_content() for n in results])
response = llm.complete(
qa_prompt.format(context_str=context_str, query_str=query)
)
print("Answer:")
print(response)
question = "Elastic services are free?"
print(f"Question: {question}")
search(question)이제 검색을 수행할 수 있습니다(예: "Elastic 서비스가 무료인가요?" ) 그리고 FAQ 데이터 자체를 기반으로 상황에 맞는 답변을 얻을 수 있습니다.
Question: Elastic services are free?
Answer:
Elastic services are not entirely free. However, there is a 14-day free trial available for exploring Elastic solutions. After the trial, access to features and services depends on the subscription level.이 응답을 생성하기 위해 다음 문서가 사용되었습니다:
1. title=Can I Try Elasticsearch Service For Free
score=1.0
content=Yes, sign up for a 14-day free trial. The trial starts the moment a cluster is created.
During the free trial period get access to a deployment to explore Elastic solutions for Enterprise Search, Observability, Security, or the latest version of the Elastic Stack.
2. title=Do You Offer Elastic S Commercial Products
score=0.9941274512218439
content=Yes, all Elasticsearch Service customers have access to basic authentication, role-based access control, and monitoring.
Elasticsearch Service Gold, Platinum and Enterprise customers get complete access to all the capabilities in X-Pack: Security, Alerting, Monitoring, Reporting, Graph Analysis & Visualization. Contact us to learn more.
3. title=What Is Elasticsearch Service
score=0.9896776845746571
content=Elasticsearch Service is hosted and managed Elasticsearch and Kibana brought to you by the creators of Elasticsearch. Elasticsearch Service is part of Elastic Cloud and ships with features that you can only get from the company behind Elasticsearch, Kibana, Beats, and Logstash. Elasticsearch is a full text search engine that suits a range of uses, from search on websites to big data analytics and more.
4. title=Can I Run The Full Elastic Stack In Elasticsearch Service
score=0.9880631561979476
content=Many of the products that are part of the Elastic Stack are readily available in Elasticsearch Service, including Elasticsearch, Kibana, plugins, and features such as monitoring and security. Use other Elastic Stack products directly with Elasticsearch Service. For example, both Logstash and Beats can send their data to Elasticsearch Service. What is run is determined by the subscription level.
5. title=What Is The Difference Between Elasticsearch Service And The Amazon Elasticsearch Service
score=0.9835054890793161
content=Elasticsearch Service is the only hosted and managed Elasticsearch service built, managed, and supported by the company behind Elasticsearch, Kibana, Beats, and Logstash. With Elasticsearch Service, you always get the latest versions of the software. Our service is built on best practices and years of experience hosting and managing thousands of Elasticsearch clusters in the Cloud and on premise. For more information, check the following Amazon and Elastic Elasticsearch Service comparison page.
Please note that there is no formal partnership between Elastic and Amazon Web Services (AWS), and Elastic does not provide any support on the AWS Elasticsearch Service.결론
LlamaIndex를 사용해 벡터 데이터베이스로서 Elasticsearch를 지원하는 효율적인 FAQ 검색 시스템을 만드는 방법을 시연했습니다. 임베딩을 사용해 문서를 수집하고 색인을 생성하여 벡터 검색을 가능하게 합니다. 프롬프트 템플릿을 통해 검색 결과가 컨텍스트에 통합되어 LLM으로 전송되면 검색된 문서를 기반으로 정확한 문맥에 맞는 응답을 생성합니다.
이 워크플로는 정보 검색과 상황에 맞는 응답 생성을 통합하여 정확하고 관련성 높은 결과를 제공합니다.
참고 자료
https://www.elastic.co/guide/en/cloud/current/ec-faq-getting-started.html
https://docs.llamaindex.ai/en/stable/api_reference/readers/elasticsearch/
https://docs.llamaindex.ai/en/stable/module_guides/indexing/vector_store_index/
https://docs.llamaindex.ai/en/stable/examples/query_engine/custom_query_engine/
자주 묻는 질문
라마인덱스란 무엇인가요?
LlamaIndex는 특정 또는 비공개 데이터와 상호 작용할 수 있는 대규모 언어 모델(LLM)로 구동되는 에이전트 및 워크플로우를 쉽게 만들 수 있는 프레임워크입니다.
LlamaIndex를 Elasticsearch와 통합할 수 있나요?
예, 데이터 소스(Elasticsearch Reader를 사용하여 문서 추출), 임베딩 모델(의미 검색을 위해 데이터를 벡터로 인코딩), 벡터 스토리지(벡터화된 문서 검색을 위한 저장소로 Elasticsearch 사용), 고급 스토리지(문서 요약 또는 지식 그래프와 같은 구조 구성) 등 다양한 방식으로 LlamaIndex와 함께 Elasticsearch를 사용할 수 있습니다.




