LLM Day8-실습

Soyee Sung·2025년 2월 8일

LLM

목록 보기
6/34

🚀 실습 프로젝트: 벡터 저장소 구축 및 문서 검색 시스템 구현

이 실습에서는 벡터 저장소(Vector Store) 를 활용하여 문서를 저장하고, 검색하는 기능을 구현할 거야!

📌 목표:

✅ 샘플 문서를 벡터 저장소에 저장
✅ 임베딩 모델을 사용하여 벡터화
✅ 문서를 추가/삭제/검색할 수 있는 기능 구현

1️⃣ 벡터 저장소(Vector Store) 선택

✅ 왜 벡터 저장소가 필요할까?
일반 데이터베이스(SQL, NoSQL)에서는 텍스트를 문자 그대로 저장하지만,
LLM(대형 언어 모델)에서는 텍스트를 숫자로 변환(벡터화)하여 저장해야 검색 성능이 높아져.
→ 따라서 벡터 저장소(Vector Database) 가 필요함!

✅ 사용할 벡터 저장소 비교

💡 이번 실습에서는 FAISS를 사용하여 벡터 저장소를 구축할 거야! 🚀

2️⃣ 코딩 실습: FAISS 벡터 저장소 구축

이제 직접 코드를 작성해보자!
📌 (1) 필요한 라이브러리 설치

pip install langchain langchain_openai openai faiss-cpu tiktoken
python -c "import faiss; print('FAISS 설치 완료!')"

📌 (2) 벡터 저장소에 문서 저장
먼저, 샘플 문서를 벡터 저장소에 저장하는 코드를 작성할 거야.

  • 문서를 100자 크기의 청크로 나눠서 저장
  • OpenAI의 Embedding 모델을 사용해 벡터로 변환
  • FAISS 벡터 저장소에 저장
import os
from langchain_openai import OpenAIEmbeddings
from langchain.vectorstores import FAISS
from langchain.text_splitter import RecursiveCharacterTextSplitter
from dotenv import load_dotenv

# ✅ 환경 변수 로드 (OpenAI API 키 가져오기)
load_dotenv()
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")

# ✅ 문서 분할 (청크 크기 설정)
splitter = RecursiveCharacterTextSplitter(chunk_size=100, chunk_overlap=20)
chunked_docs = splitter.split_documents(doc_objects)

# ✅ OpenAI 임베딩 모델 설정
embedding_model = OpenAIEmbeddings(api_key=OPENAI_API_KEY)

# ✅ FAISS 벡터 저장소 생성
vector_store = FAISS.from_documents(chunked_docs, embedding_model)

print("✅ 문서가 벡터 저장소에 성공적으로 저장되었습니다!")

📌 (3) 새로운 문서 추가
이제 벡터 저장소에 새로운 문서를 추가해 보자!

  • add_documents()를 사용하여 새로운 문서 추가 가능
def add_new_document(content, doc_type, author):
    """새로운 문서를 벡터 저장소에 추가"""
    new_doc = Document(
        page_content=content,
        metadata={"type": doc_type, "author": author}
    )
    
    new_chunks = splitter.split_documents([new_doc])  # 청크 분할
    vector_store.add_documents(new_chunks)  # 저장소에 추가
    print(f"✅ 새로운 문서 추가 완료: {content[:30]}...")

# ✅ 새로운 문서 추가 예제
add_new_document("양자 컴퓨팅의 가능성과 한계", "research", "이도현")

📌 (4) 문서 삭제
FAISS는 기본적으로 문서를 삭제하는 기능이 없지만, 특정 문서를 제외하고 새로운 벡터 저장소를 만들면 해결 가능!

  • 기존 문서를 걸러낸 후 새로 저장소를 만드는 방식으로 문서 삭제 가능
def delete_document(title):
    """특정 문서를 벡터 저장소에서 삭제"""
    global vector_store
    filtered_docs = [doc for doc in chunked_docs if title not in doc.page_content]
    vector_store = FAISS.from_documents(filtered_docs, embedding_model)
    print(f"❌ 문서 삭제 완료: {title}")

# ✅ "인공지능 기술의 발전과 미래" 문서 삭제 예제
delete_document("인공지능 기술의 발전과 미래")

📌 (5) 문서 검색: 유사도 기반 검색
이제 문서 검색 기능을 구현해보자!
사용자가 질문하면 가장 유사한 문서를 찾아주는 기능이야.

  • similarity_search(query, k=2)를 사용하여 가장 유사한 문서 2개 검색
  • 벡터 유사도를 기반으로 검색 결과 반환
def search_documents(query, k=3):
    """질문을 입력하면 가장 유사한 문서를 반환"""
    similar_docs = vector_store.similarity_search(query, k=k)
    print(f"🔍 '{query}'에 대한 검색 결과:")
    for i, doc in enumerate(similar_docs):
        print(f"\n📌 {i+1}번째 유사 문서:\n{doc.page_content}")

# ✅ "AI 기술"에 대한 검색 예제
search_documents("AI 기술")

📌 (6) 메타데이터 필터링 검색
이제 메타데이터를 기반으로 검색하는 기능을 추가해보자!

  • metadata.get(field) == value 조건을 사용해 특정 카테고리의 문서만 필터링 가능
def filter_by_metadata(field, value):
    """메타데이터 필터링을 수행하는 함수"""
    filtered_docs = [doc for doc in chunked_docs if doc.metadata.get(field) == value]
    print(f"📂 '{field}: {value}'에 해당하는 문서:")
    for i, doc in enumerate(filtered_docs):
        print(f"\n📌 {i+1}번째 문서:\n{doc.page_content}")

# ✅ "research" 타입의 문서만 검색
filter_by_metadata("type", "research")

🎯 최종 정리
✅ 문서 저장 FAISS 벡터 저장소에 문서 저장
✅ 문서 추가 add_documents()를 사용해 문서 추가
✅ 문서 삭제 특정 문서를 제외하고 새로운 벡터 저장소 생성
✅ 유사 문서 검색 similarity_search()로 유사한 문서 찾기
✅ 메타데이터 검색 특정 키워드(예: type, author)로 문서 필터링

0개의 댓글