LangChain을 활용한 정보 검색 및 검증 파이프라인 구축

2024. 11. 20. 00:10 개발 이야기/머신러닝(딥러닝)

이번 포스팅에서는 LangChain을 사용하여 웹에서 정보를 가져오고, 그것이 얼마나 관련이 있고 정확한지를 검증하는 방법을 소개하겠습니다. 이 과정에서는 ChatGPT와 같은 언어 모델과 함께 WebBaseLoader, Chroma, 그리고 다양한 PromptTemplate을 활용하여 정보를 검색하고 사용자의 질문에 가장 적합한 답변을 제공하는 파이프라인을 구축합니다. 코드의 주요 기능과 흐름을 설명하고, 각각의 단계가 어떤 역할을 하는지 설명드리겠습니다.

 

1. 전체 파이프라인 흐름

파이프라인의 기본적인 흐름은 다음과 같습니다.

  1. Query -> Docs Retrieval -> Relevant Check -> Generate Answer -> Hallucination Check -> Answer to User
    • 사용자의 질의를 처리하고, 관련된 문서를 검색한 후, 문서의 관련성을 평가합니다.
    • 이후 답변을 생성하고, 그 답변이 '환상'에 기반한 내용인지 아닌지를 검증하는 흐름입니다.

이렇게 단계별로 정보를 처리함으로써, 단순히 검색된 결과를 전달하는 것이 아닌, 사용자의 질문에 대해 정확하고 신뢰할 수 있는 답변을 제공하도록 설계되었습니다.

2. 웹 문서 로드 및 분할

코드의 첫 단계는 웹에서 문서를 가져오는 것입니다. 여기에서는 WebBaseLoader를 사용하여 지정된 URL로부터 문서를 가져옵니다. 필요한 HTML 요소만을 파싱하도록 bs4.SoupStrainer를 사용해 효율적으로 문서를 로드하고 있습니다.

loader = WebBaseLoader(
    web_path=web_docs,
    bs_kwargs=dict(
        parse_only=bs4.SoupStrainer(
            class_=("post-content", "post-title", "post-header")
        )
    ),
)

로드된 문서는 RecursiveCharacterTextSplitter를 통해 일정한 크기로 분할됩니다. 이렇게 함으로써 언어 모델이 처리하기 쉬운 단위로 나누어 보다 정확한 답변을 제공할 수 있습니다.

3. 벡터스토어 생성 및 검색

분할된 문서들은 임베딩 모델(OpenAIEmbeddings)을 사용해 벡터화한 후, Chroma 벡터스토어에 저장됩니다. 이렇게 생성된 벡터스토어는 사용자의 질의에 대해 관련 있는 문서를 검색하는 데 사용됩니다.

def get_vectorstore(splits_docs, embeddings):
    return Chroma.from_documents(documents=splits_docs, embedding=embeddings)

이 과정은 효율적인 검색 기능을 제공하며, 가장 관련성 높은 정보를 찾는 데 매우 유용합니다.

4. 관련성 및 환상 검증

검색된 결과가 사용자의 질문에 관련이 있는지를 확인하기 위해 relevance_prompt를 사용합니다. 이 프롬프트는 모델에게 검색된 결과가 사용자 질의에 직접적으로 답변하는지 혹은 관련 있는 컨텍스트를 제공하는지를 평가하도록 합니다.

relevance_prompt = PromptTemplate(
    template=(
        "You are a system designed to evaluate the relevance of a retrieved document chunk to a user query.\n"
        "Assess if the retrieved chunk answers the user query directly or provides useful context for the query.\n"
        "Relevance is true/false \n"
        "Respond with a JSON object indicating relevance using the following format:\n"
        "{format_instructions}\n\n"
        "User Query: {query}\n\n"
        "Retrieved Chunk: {retrieved_chunk}"
    ),
    input_variables=["query", "retrieved_chunk"],
    partial_variables={"format_instructions": parser.get_format_instructions()},
)

관련성이 있다고 판단되면 답변을 생성하고, 생성된 답변이 '환상'에 기반한 것인지 검증하는 단계가 이어집니다. 이를 통해 보다 신뢰성 있는 답변을 사용자가 받을 수 있습니다.

5. 프롬프트 엔지니어링의 원리와 실제 사용 방법

프롬프트 엔지니어링은 언어 모델에게 적절한 방식으로 질문을 제시하여 원하는 답변을 얻는 기술입니다. 프롬프트의 구조와 내용에 따라 모델이 생성하는 응답의 품질이 크게 달라질 수 있기 때문에, 프롬프트 엔지니어링은 언어 모델의 성능을 최대한 이끌어내기 위한 중요한 과정입니다.

5.1 프롬프트 엔지니어링의 원리

프롬프트 엔지니어링의 핵심은 모델이 문맥을 이해하고 적절한 응답을 생성하도록 프롬프트를 설계하는 것입니다. 좋은 프롬프트는 다음과 같은 특징을 가집니다:

  • 명확성: 질문의 내용이 명확해야 합니다. 모호한 질문은 모델이 잘못된 답변을 하게 만들 수 있습니다.
  • 구체성: 질문이 구체적일수록 모델이 더 정확하게 응답할 가능성이 높습니다. 필요한 정보를 구체적으로 지정하는 것이 중요합니다.
  • 맥락 제공: 모델에게 필요한 배경 정보를 제공하여, 모델이 질문의 의미를 제대로 이해할 수 있도록 해야 합니다.

5.2 실제로 사용하는 방법

프롬프트 엔지니어링을 실제로 적용할 때는 다양한 형태의 질문을 실험해보며 모델의 반응을 살펴보는 과정이 필요합니다. 예를 들어, 다음과 같은 프롬프트를 사용할 수 있습니다:

  1. 정보 요청: "다음 텍스트에 대한 요약을 제공하세요."
    • 모델에게 요약을 요청할 때 간결하고 명확한 요청을 통해 응답의 품질을 높일 수 있습니다.
  2. 행동 지시: "다음 텍스트를 기반으로 Q&A 형식으로 답변하세요."
    • 특정 형식을 지정해줌으로써 모델이 해당 형식에 맞게 응답하도록 유도합니다.
  3. 조건 설정: "이 문장에서 긍정적인 부분만 골라내어 설명하세요."
    • 조건을 부여함으로써 모델이 특정 부분에 집중하도록 할 수 있습니다.

또한, 프롬프트를 작성할 때는 실험과 피드백이 매우 중요합니다. 다양한 프롬프트를 적용해보면서 어떤 방식이 가장 효과적인지 알아가는 과정이 필요합니다.

 

6. 결론

LangChain을 활용한 이 파이프라인은 사용자의 질문에 대해 검색된 정보의 관련성과 정확성을 평가하고, 모델이 제공하는 답변이 얼마나 신뢰할 수 있는지를 검증하는 과정을 포함합니다. 이를 통해 단순히 정보를 찾는 것에 그치지 않고, 보다 높은 신뢰성을 갖춘 답변을 제공할 수 있습니다.

또한, 프롬프트 엔지니어링을 통해 언어 모델의 성능을 극대화하는 방법을 이해하고 적용할 수 있습니다. 프롬프트 설계의 중요성을 알고 이를 통해 모델의 답변 품질을 향상시키는 것은 매우 유용한 기술입니다.

앞으로는 이러한 기법을 확장하여 다양한 종류의 문서와 질의에 대해 적용할 수 있을 것이며, 이를 통해 더욱 향상된 사용자 경험을 제공할 수 있을 것입니다. 여러분도 이 코드를 활용하여 다양한 정보 검색 및 검증 시스템을 만들어 보시길 권장드립니다!