[AI] langchain + Huggingface + ollama + FAISS 적용해보자

늘 공부하는 괴짜·2025년 5월 16일
0

AI : Langchain (RAG)

목록 보기
18/38
post-thumbnail

FAISS는 페이스북에서 개발한 대용량 벡터 검색 라이브러리로, 밀집 벡터의 유사도를 빠르게 계산하고 클러스터링하는 데 사용된다. 주로 텍스트, 이미지, 음성 등 비정형 데이터를 벡터 형태로 변환하여 유사도 기반 검색 을 수행하는 데 활용된다.

chromadb 처럼 로컬에 저장해놓고 사용이 가능하다 하여 테스트해 봤다.

1. 허깅페이스 embedding

from langchain_huggingface import HuggingFaceEmbeddings
import os

# 허깅페이스 임베딩 모델명 설정
embedding_model_name = "sentence-transformers/paraphrase-xlm-r-multilingual-v1"

# 허깅페이스 토큰 설정
huggingface_token = os.getenv("HUGGINGFACE_API_KEY")

# 허깅페이스 임베딩 모델 초기화
embeddings = HuggingFaceEmbeddings(
    model_name=embedding_model_name,
    model_kwargs={"device": "mps"},
    encode_kwargs={"normalize_embeddings": True}
)

# 허깅페이스 임베딩 모델을 반환하는 함수
def getEmbeddingHuggingface():
    return embeddings

2. FAISS 설치

% pip install pytorch faiss-cpu

3. FAISS 에 데이터 넣기

from langchain_text_splitters import RecursiveCharacterTextSplitter
from embedding.huggingface_768 import getEmbeddingHuggingface  
from langchain_community.document_loaders import PyPDFLoader
from langchain_community.vectorstores.faiss import FAISS

# PDF 파일 로드
loader = PyPDFLoader("./prince.pdf")
pages = loader.load()

# 문서 분할
text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=450,
    chunk_overlap=100,
    length_function=len
)
split_docs = text_splitter.split_documents(pages)

# 임베딩 모델 불러오기
embedding_model = getEmbeddingHuggingface()

# FAISS 벡터 저장소에 문서 저장
try:
    vectorstore = FAISS.from_documents(
        documents=split_docs,
        embedding=embedding_model
    )

    # 인덱스를 로컬에 저장 (예: ./faiss_index)
    vectorstore.save_local("faiss_index")

    print("Documents processed and FAISS index saved successfully")
except Exception as e:
    print(f"Error processing documents: {e}")

insert 후에는 이런 파일들이 생긴다.

4. FAISS 데이터 사용

from langchain.chains import RetrievalQA
from langchain import hub
from langchain_community.vectorstores.faiss import FAISS
from langchain_community.llms import Ollama
from embedding.huggingface_768 import getEmbeddingHuggingface  

# 1. 허깅페이스 임베딩 로드
embeddings = getEmbeddingHuggingface()

# 2. FAISS 인덱스를 저장한 경로
faiss_index_path = "faiss_index"

vectorstore = FAISS.load_local(
    folder_path=faiss_index_path,
    embeddings=embeddings,
    allow_dangerous_deserialization=True
)

# 유사도 검색 테스트. ok
#docs = vectorstore.similarity_search("아이들에게 손수건은?")
#print(docs[0])

# 3. Retriever 설정
retriever = vectorstore.as_retriever()

# 4. LLM 설정
llm = Ollama(model="llama3.1:8b")

# 5. 프롬프트 가져오기
prompt = hub.pull("rlm/rag-prompt")


# 6. 체인 구성
chain = RetrievalQA.from_chain_type(
    llm=llm,
    retriever=retriever,
    chain_type_kwargs={"prompt": prompt}
)

# 7. 체인 실행
result = chain({"query": "소행성 B612호는 무엇인가?"})
print(result["result"])

결과는 이렇게... llama3:8b 치곤 괜찮은거 같은데 이건 테스트를 많이 해봐야겠다.

5. 프롬프트를 커스텀 했다.

from langchain.chains import RetrievalQA
from langchain import hub
from langchain_community.vectorstores.faiss import FAISS
from langchain_community.llms import Ollama
from embedding.huggingface_768 import getEmbeddingHuggingface  
from langchain.prompts import PromptTemplate

# 1. 허깅페이스 임베딩 로드
embeddings = getEmbeddingHuggingface()

# 2. FAISS 인덱스를 저장한 경로
faiss_index_path = "faiss_index"

vectorstore = FAISS.load_local(
    folder_path=faiss_index_path,
    embeddings=embeddings,
    allow_dangerous_deserialization=True
)

# 3. Retriever 설정
retriever = vectorstore.as_retriever()

# 4. LLM 설정
llm = Ollama(model="exaone3.5:7.8b")

# 5. 커스텀 프롬프트 정의
custom_prompt = PromptTemplate(
    input_variables=["context", "question"],
    template="""
        당신은 매우 정밀한 질문 응답 시스템입니다. 다음의 문맥을 참고하여 사용자의 질문에 답하세요. 

        문맥:
        {context}

        질문:
        {question}

        정확하고 간결한 답변:
    """.strip()
    )


# 6. 체인 구성
chain = RetrievalQA.from_chain_type(
    llm=llm,
    retriever=retriever,
    chain_type_kwargs={"prompt": custom_prompt}
)
# 7. 체인 실행
result = chain({"query": "소행성 B612호는 무엇인가?"})
print(result["result"])

profile
인공지능이라는 옷을 입었습니다. 뭔가 멋지면서도 잘 맞습니다.

0개의 댓글