Professional Field

SQL(ORACLE) | AI | BI | 통계분석

Scientist/ML.DL

[LangChain] OpenAI 모델을 이용한 URL 챗봇 개발

K_CY 2024. 11. 20. 02:20

우선, 언어 모델을 만들기 위해 해야 하는 절차는 다음과 같다.

 

1. 가져올 뉴스데이터 URL를 확보한다.

2. TEXT를 추출한 후 파라미터를 조정해 스플릿한다.

3. 임베딩을 진행한다.

4. 벡터저장소에 저장한다.

5. 리트리버를 구성한다. 

6. 프롬프트를 작성한다. 

7. 모델에 적용한다.

 

1번 랭체인 라이브러리를 사용하였으며, URL 이 아니더라도 PDF, Log, Json 등 데이터 형태에 따라 변경한다.

from langchain.document_loaders import WebBaseLoader
import bs4
from langchain.schema import Document

loader = WebBaseLoader(
    web_paths=("https://www.news1.kr/industry/distribution/5496643",),
    bs_kwargs=dict(
        parse_only=bs4.SoupStrainer(
            "article",
            attrs={"class": ["col-lg-7 article-padding-lg-right position-relative gx-0"]},
        )
    ),
)

docs = loader.load()
print(f"문서의 수: {len(docs)}")

full_text = docs[0].page_content
cutoff_text = "hjin@news1.kr"
target_text = full_text.split(cutoff_text)[0] + cutoff_text if cutoff_text in full_text else full_text
docs = [Document(page_content=target_text, metadata=docs[0].metadata)]

print(docs)

 

2번 텍스트를 스플릿한다. 

text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=3000,  # 청크의 크기
    chunk_overlap=50  # 청크 간 중복되는 문자의 수
)

# 문서를 청크로 분할
splits = text_splitter.split_documents(docs)

 

3번 임베딩을 진행한다. OpenAI는 유료이기때문에... 실수하지 않도록 캐시를 저장해두는 것이 좋다.

# OpenAI 임베딩 설정
openai_embedding = OpenAIEmbeddings()

# 캐시 저장소 설정 (중복결제 방지)
store = LocalFileStore("./cache/")

# 캐시를 적용한 임베딩 설정
cached_embedder = CacheBackedEmbeddings.from_bytes_store(
    openai_embedding, 
    store, 
    namespace=openai_embedding.model
)

 

4번 벡터DB에 벡터화된 데이터를 저장한다.

# FAISS 벡터 데이터베이스 생성 및 저장
vector_db = FAISS.from_documents(documents=splits, embedding=cached_embedder)

 

5번 리트리버를 구성한다.

# 리트리버 구성
retriever = vector_db.as_retriever()

 

6번 프롬프트를 작성한다.

from langchain_core.prompts import PromptTemplate

# 직접 프롬프트 템플릿을 생성
prompt = PromptTemplate.from_template(
    """당신은 질문-답변(Question-Answering)을 수행하는 친절한 AI 어시스턴트입니다. 당신의 임무는 주어진 문맥(context)에서 주어진 질문(question)에 답하는 것입니다.
    검색된 다음 문맥(context)을 사용하여 질문(question)에 답하세요. 만약, 주어진 문맥(context)에서 답을 찾을 수 없다면, 답을 모른다면 '주어진 정보에서 질문에 대한 정보를 찾을 수 없습니다'라고 답하세요.
    한글로 답변해 주세요. 단, 기술적인 용어나 이름은 번역하지 않고 그대로 사용해 주세요.

    #Question: 
    {question}

    #Context: 
    {context}

    #Answer:"""
)

 

7. 언어모델에 적용한다.

llm = ChatOpenAI(model_name="gpt-4o", temperature=0)


# LLM 체인 생성
llm_chain = (
    {
        "context": retriever | format_docs, "question": RunnablePassthrough()} 
    | prompt 
    | llm 
    | StrOutputParser()
)

class StreamChain:
    def __init__(self, chain):
        self.chain = chain

    def stream(self, query):
        response = self.chain.stream(query)
        complete_response = ""
        for token in response:
            print(token, end="", flush=True)
            complete_response += token
        return complete_response


chain = StreamChain(llm_chain)

 

8. 모델을 사용하여 질문을 던져보자.

 

answer3번에 경우 질문에 해당하는 답이 없지만 할루시네이션을 일으킬 수 있어 프롬프트에 입력할 때 주어진 정보에 해당하는 답변이 없다면 답이 없다고 말하도록 설정해주어야 신뢰할 수 있는 정보가 될 수 있다.

 

꼭 OpenAI 모델을 사용해야 하는 것은 아니며, 허깅페이스나 더 낮은 무료버전 모델을 사용해도 무방하다. 

'Scientist > ML.DL' 카테고리의 다른 글

[LangChain] Text Splitter 종류  (0) 2024.08.09
[LangChain] PDF Loader 종류  (0) 2024.08.09
[ML/DL] LangChain이란?  (0) 2024.07.18
[ML/DL] NLP TF-IDF / Word2Vec  (0) 2024.07.18
[ML/DL] NLP 토크나이저 종류  (0) 2024.07.17