12.4 LangChain & LlamaIndex 연동
12.4 LlamaIndex를 이용한 문서 기반 Q&A 시스템
앞 절에서는 LangChain을 활용한 RAG(Retrieval-Augmented Generation) 구현 방법을 살펴보았습니다. 이번 절에서는 RAG를 위한 또 다른 매우 강력한 도구인 LlamaIndex(LangChain과 통합도 가능)를 이용하여, 사용자 문서 기반 Q&A 시스템을 구축하는 방법을 상세히 다룹니다.
LlamaIndex는 문서 수집, 인덱싱, 검색 기반 프롬프트 생성, 언어 모델 호출까지 RAG 파이프라인을 구성하는 데 특화된 프레임워크입니다. 이번 절에서는 다음 내용을 중심으로 실습과 함께 구성합니다.
LlamaIndex의 전체 구조 이해
문서 수집 및 인덱싱
벡터 기반 검색
OpenAI API를 통한 질의응답
실제 서비스 형태로 시스템 통합
12.4.1 LlamaIndex란 무엇인가
LlamaIndex(구 GPT Index)는 LLM 기반 어플리케이션을 위한 데이터 연결 계층(Data Framework)입니다. 주로 아래와 같은 구성 요소를 기반으로 RAG 방식 문서 검색 및 질의 응답 시스템을 구축합니다.
주요 특징:
다양한 문서 포맷 읽기 지원 (.txt, .pdf, .docx 등)
텍스트 분할 및 벡터 임베딩 생성
다양한 벡터 DB 연동 (FAISS, Pinecone, Weaviate 등)
검색 및 프롬프트 자동화
LangChain과의 통합도 용이
🔍 키 개념:
Document: 텍스트 기반 정보 단위
Node: Document를 쪼개 벡터화한 텍스트 청크
Index: Node 임베딩 데이터베이스
Query Engine: 사용자의 질문을 처리하고 관련 노드 검색 + LLM 응답 생성
12.4.2 설치 및 개발 환경 준비
우선 LlamaIndex와 함께 사용할 주요 패키지를 설치합니다.
pip install llama-index openai faiss-cpu
필요 시 다음도 설치:
pip install PyPDF2 python-docx
또한 OpenAI API 키가 필요하며, 코드 상에서 다음과 같이 설정합니다.
import openai
openai.api_key = "your-api-key"
또는 환경 변수에 설정:
export OPENAI_API_KEY=your-api-key
12.4.3 문서 로딩 및 전처리
LlamaIndex는 다양한 입력 문서를 로딩하는 방법을 제공합니다.
예: 텍스트 파일 로딩
from llama_index import download_loader
SimpleDirectoryReader = download_loader("SimpleDirectoryReader")
documents = SimpleDirectoryReader(input_dir="./docs").load_data()
문서가 폴더로 구성되어 있고 각 문서가 .txt
, .pdf
, .docx
라면 LlamaIndex가 자동으로 처리합니다.
로드 후 LlamaIndex는 내부적으로 문서를 "Document" 객체로 표현합니다.
12.4.4 인덱스 생성: 문서 → 벡터
문서를 검색 가능하게 만들기 위해 우리가 해야 할 다음 단계는 "인덱스 생성"입니다.
from llama_index import VectorStoreIndex
index = VectorStoreIndex.from_documents(documents)
이 코드는 다음 과정을 자동으로 수행합니다:
문서를 작게 분절 (청크 단위 텍스트로 분할)
각 청크를 OpenAI Embedding API로 임베딩
내부 벡터 DB(예: FAISS 또는 기본 인메모리)에 저장
별도 설정 없이도 OpenAI의 text-embedding-ada-002 모델을 사용합니다.
청크 설정을 직접 제어하고 싶다면 다음을 활용할 수 있습니다:
from llama_index.text_splitter import TokenTextSplitter
text_splitter = TokenTextSplitter(chunk_size=512, chunk_overlap=50)
index = VectorStoreIndex.from_documents(documents, text_splitter=text_splitter)
12.4.5 질의 엔진(Query Engine) 구성
인덱스가 생성된 후, 사용자의 질문에 답변을 생성할 수 있습니다. 이를 위해 QueryEngine 객체를 사용합니다:
query_engine = index.as_query_engine()
response = query_engine.query("이 문서에서 회사 주소는 어디인가요?")
print(response)
이 코드는 다음 단계를 포함합니다:
질문을 임베딩으로 변환
기존 문서 인덱스에서 가장 유사한 청크 검색
검색된 청크를 system prompt에 포함시켜 LLM에 전달
LLM이 답변 생성
이때 내부적으로 OpenAI의 gpt-3.5-turbo 또는 gpt-4 모델이 사용됩니다 (환경에 따라 설정 가능).
12.4.6 사용자 지정 프롬프트와 템플릿 구성
기본 프롬프트 외에도 커스텀 프롬프트를 생성하여 질의 응답의 품질을 더욱 개선할 수 있습니다.
from llama_index.prompts.prompts import QuestionAnswerPrompt
from llama_index.query_engine import RetrieverQueryEngine
prompt_template_str = (
"다음 문서를 참고하여 사용자 질문에 한국어로 답하세요.\n\n"
"문서:\n{context_str}\n\n"
"질문:\n{query_str}\n\n"
"답변:"
)
qa_prompt = QuestionAnswerPrompt(prompt_template_str=prompt_template_str)
query_engine = index.as_query_engine(text_qa_template=qa_prompt)
print(query_engine.query("대표이사는 누구입니까?"))
12.4.7 외부 벡터 DB 연동 (예: FAISS)
기본 인메모리 인덱스를 사용하면 프로덕션에 적합하지 않기 때문에 FAISS, Pinecone 등의 벡터 데이터베이스를 사용하는 것이 일반적입니다.
FAISS 연동 예:
from llama_index.vector_stores.faiss import FaissVectorStore
from llama_index.storage.storage_context import StorageContext
import faiss
faiss_index = faiss.IndexFlatL2(1536)
faiss_store = FaissVectorStore(faiss_index=faiss_index)
storage_context = StorageContext.from_defaults(vector_store=faiss_store)
index = VectorStoreIndex.from_documents(documents, storage_context=storage_context)
이렇게 하면 향후 검색 속도를 빠르게 하고 대규모 데이터셋에도 대응할 수 있습니다.
12.4.8 웹 서비스 형태로 연동하기 (Flask 예제)
간단한 문서 기반 Q&A 웹 서비스를 만들기 위해 Flask를 사용할 수 있습니다.
from flask import Flask, request, jsonify
app = Flask(__name__)
query_engine = index.as_query_engine()
@app.route("/ask", methods=["POST"])
def ask():
question = request.json["question"]
response = query_engine.query(question)
return jsonify({"answer": str(response)})
if __name__ == "__main__":
app.run(debug=True)
이제 POST /ask 엔드포인트로 질문을 전달하면, 문서를 기반으로 한 응답을 얻을 수 있습니다.
12.4.9 고급 기능: 다중 문서 소스, 메타데이터 필터링
LlamaIndex는 다음 기능도 지원합니다:
문서별 메타데이터 설정 (날짜, 카테고리 등)
특정 조건의 문서만 검색하는 필터링(QueryFilter)
다국어 문서 처리 및 번역 검색 대응
PDF, HTML, 웹 페이지, Notion 등 다양한 소스 로더 제공
예를 들어:
document = Document(
text="이 문서는 내부 인사 규정입니다.",
metadata={"category": "HR", "published": "2023-10-12"}
)
필터링해서 HR 문서만 검색하게 설정할 수도 있습니다.
12.4.10 정리 및 적용 사례
📌 이 절에서 우리는 다음 내용을 실습을 통해 이해했습니다:
텍스트 문서를 벡터로 인덱싱하고 OpenAI로 질문 응답
다양한 문서 형식을 로딩해 통합
시스템 프롬프트와 검색 구조를 커스터마이징
외부 저장소 연동으로 확장성 확보
간단한 API 형태로 실서비스 구성
🏁 응용 예시:
내부 지침서 기반 챗봇
계약서 검색 및 질의응답 봇
고객 지원 DB 연동 Q&A 시스템
지식 기반 AI 도우미
LlamaIndex는 LangChain과 병행해서 사용할 수도 있으며, 더욱 유연한 문서 기반 AI Q&A 시스템 설계를 가능하게 합니다. 다음 장에서는 프론트엔드 통합을 통해 이러한 시스템을 웹 서비스로 만들어봅니다.
Last updated