LLM 개발이 상용화 되고 있는 건 알겠는데,,, 초심자가 접근하기에 정보가 너무 많다...!
그래서 준비했습니다
RAG 한판 정리..!
사실 한판에 정리한다는건 말도 안되지만, 그냥 한눈에 보기 편한(?)
[개발 진행 순서]
이렇게만 보면 아무도 이해 못하거든요.. 찾기도 귀찮고
간단하게 예제를 만들어보았습니다.
저는 위키피디아를 이용해서 LCA에 대한 내용을 학습시켜 보았습니다!
1. 문서업로드
url1 , url2를 추가해서 여러 url을 불러올 수 있습니다.
class에 들어갈 내용은 "개발자 모드" 에서 html 파서를 적절하게 배치하면 된답니다
from langchain_community.document_loaders import WebBaseLoader # 웹 로더 임포트
from langchain.text_splitter import RecursiveCharacterTextSplitter # 텍스트 분할기
from langchain_huggingface import HuggingFaceEmbeddings
from langchain_community.vectorstores import FAISS # 벡터 저장소
import bs4
# 1. 웹페이지 로드: 문서 로드
url1 = 'https://ko.wikipedia.org/wiki/%ED%83%84%EC%86%8C_%EB%B0%9C%EC%9E%90%EA%B5%AD'
url2 = 'https://ko.wikipedia.org/wiki/%EC%A0%84_%EA%B3%BC%EC%A0%95_%ED%8F%89%EA%B0%80'
loader = WebBaseLoader(
web_path=(url1,url2),
bs_kwargs=dict(
parse_only=bs4.SoupStrainer(
class_= ("mw-page-title-main", "mw-content-ltr mw-parser-output")
)
),
)
docs = loader.load()
2. 텍스트 분할
텍스트 분할이 참 과정이 어려운데요,
핵심은 결국 문장을 어디서 자를것인지(chunk_size)
자른 문장끼리 얼마나 연결 시킬건지(chunk_overlap) <- 앞 뒤 문맥을 알아야 하잖아요?
아래와 같이 원하는 청크를 적절하게 수정해봅니다
# 2. 텍스트 분할: 긴 문서를 검색할 수 있는 짧은 청크로 분할
text_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=50)
split_docs = text_splitter.split_documents(docs)
3. 벡터 저장소(vector DB)
벡터 저장소는 참 중요한 부분중의 하나인데요, 원리가 복잡하지만
간단하게 설명하면 임베딩(수치화) 해서 유사도(코사인,유클리디안) 등으로 검색을 하기위한
"성능 향상 작업" 이라고 보시면 됩니다.
# 3. 벡터 저장소 구축: 문서 청크를 벡터로 변환하고 인덱싱
embedding_model = HuggingFaceEmbeddings(model_name="sentence-transformers/all-MiniLM-L6-v2") # 적절한 모델 이름 사용
vector_store = FAISS.from_documents(split_docs, embedding_model)
4. 검색기 설정
prompt를 지정해주고 (양식 지정)
콜백 부분은 API 통신 내용이라 필요 없습니다!
스트리밍 LLM과 챗봇 체인을 확인하시면
prompt | llm | StrOutputParser()
prompt(미리 양식을 주고) -> llm(모델에 전달) -> StrOutputParser(대답)
이런 구조입니다.
# 4. 검색기 설정: 벡터 저장소를 사용하는 검색기 설정
retriever = vector_store.as_retriever()
# 챗봇의 기본 프롬프트 설정
prompt = ChatPromptTemplate.from_messages(
[
(
"system",
"당신은 Question-Answering 챗봇입니다. 주어진 질문에 대한 답변을 제공해주세요.",
),
MessagesPlaceholder(variable_name="history"),
("human", "{input}"),
]
)
# 콜백 관리자를 생성하고, 스트리밍 핸들러를 추가
manager = AsyncCallbackManager([])
stream_manager = AsyncCallbackManager([stream_handler])
# 트레이싱 활성화 시, 트레이서를 설정하고 콜백 관리자가 이를 처리하도록 추가
if tracing:
tracer = LangChainTracer()
tracer.load_default_session()
manager.add_handler(tracer)
stream_manager.add_handler(tracer)
# 스트리밍 LLM 설정 (여기서는 Ollama 모델 사용)
llm = ChatOllama(model="ollama-bllossom",
temperature=0,
)
# 챗봇 체인 생성
chain = prompt | llm | StrOutputParser()
chain_with_history = RunnableWithMessageHistory(
chain,
lambda session_id: RedisChatMessageHistory(session_id, url=REDIS_URL),
input_messages_key="input",
history_messages_key="history",
)
return chain_with_history
간단하게 프론트로 보여주고 질문을 던졌더니, 아래와 같은 답변을 해주네요!
'머신러닝 > 자연어처리의 모든것' 카테고리의 다른 글
RAG와 Lang chain에 대하여 (0) | 2024.08.01 |
---|