ChatGPT | 랭체인(LangChain) 소개

반응형

이 글은 김태영 강사님의 “유튜브 | 챗GPT에 날개를 달아줄 랭체인! (LangChain)” 강의 내용을 정리한 것입니다.

LLM(Large Language Model)만으로는 애플리케이션을 만들기가 어렵습니다. 하지만 LangChain에서 제공하는 다양한 기능을 활용하면 강력한 애플리케이션을 만들 수 있습니다.


우리가 챗GPT를 통해 하고 싶은 것

  • 내 문서(PDF)를 챗GPT에게 학습시킨 다음 질문하는 것
  • 챗GPT가 인터넷 정보를 검색하여 응답하는 것
  • 챗GPT를 다른 서비스와 연동하는 것
  • 챗GPT를 내가 정한 시나리오대로 행동하게 하는 것

랭체인(LangChain)

LangChain은 언어 모델을 기반으로 한 애플리케이션을 개발하기 위한 프레임워크입니다. LangChain은 API를 통해 언어 모델을 호출하는 것 뿐만 아니라, 외부 데이터를 인식하거나 타 시스템과의 상호 작용하는 애플리케이션을 개발하고자 노력합니다.

  1. 데이터 인식: 언어 모델을 다른 데이터 소스에 연결합니다.
  2. 에이전트화(Be agentic): 언어 모델이 환경과 상호 작용하도록 허용합니다.

LangChain에서 제공하는 것은 크게 두 가지로 나누어 볼 수 있습니다.

  1. 컴포넌트(Components): LangChain은 언어 모델과 함께 작동하는 데 필요한 컴포넌트에 대한 모듈식 추상화를 제공합니다. LangChain은 이러한 모든 추상화에 대한 구현 모음도 제공합니다. 컴포넌트는 LangChain 프레임워크의 사용 여부에 관계없이 쉽게 사용할 수 있도록 설계되었습니다.
  2. 사용 사례별 체인(Use-Case Specific Chains): 체인은 특정 사용 사례를 가장 잘 달성하기 위해 이러한 컴포넌트를 특정 방식으로 조합할 수 있습니다. 이는 사람들이 특정 사용 사례를 쉽게 시작할 수 있는 고급 인터페이스를 제공하기 위한 것입니다. 또한 사용자 정의(customizable)가 가능하도록 설계되었습니다.

컴포넌트(Components)

스키마(Schema)

  • 텍스트(Text): 언어 모델로 작업할 때 언어 모델과 상호 작용할 수 있는 기본 인터페이스는 텍스트를 통해 이루어집니다. 지나치게 단순화하자면, 많은 모델이 "텍스트 입력 → 텍스트 출력"입니다. 따라서 LangChain의 많은 인터페이스는 텍스트를 중심으로 구성되어 있습니다.
  • 채팅 메시지(ChatMessages): 사용자가 AI와 상호 작용하는 주요 인터페이스는 채팅 인터페이스입니다. 현재 지원되는 채팅 메시지 인터페이스는 시스템(System), 사람(Human), AI입니다.
    • 시스템 채팅 메시지(SystemChatMessage): AI 시스템에 대해 지시사항를 나타내는 메시지입니다.
    • 사람 채팅 메시지(HumanChatMessage): 인간이 입력하는 메시지입니다.
    • AI 채팅 메시지(AIChatMessage): AI 시스템의 출력 메시지입니다.
  • 예시(Examples): 예시는 함수에 대한 입력과 예상 출력을 나타내는 입력/출력 쌍입니다. 모델 훈련 및 평가 모두에 사용할 수 있습니다. 모델 또는 체인에 대한 입력/출력일 수 있습니다. 두 가지 유형의 예시는 서로 다른 용도로 사용됩니다.
    • 모델의 예시는 모델을 미세 조정하는 데 사용할 수 있습니다.
    • 체인에 대한 예시는 종단 간 체인을 평가하는 데 사용할 수 있으며, 전체 체인을 대체할 모델을 훈련하는 데 사용할 수도 있습니다.
  • 문서(Document): 비정형 데이터의 일부입니다. page_content(데이터의 내용)와 metadata(데이터의 속성을 설명하는 부가 정보)로 구성됩니다.

모델(Models)

  • 대규모 언어 모델(LLM): LLM 모델은 텍스트 문자열을 입력으로 받아 텍스트 문자열을 출력으로 반환합니다.
  • 채팅 모델(Chat Models): 채팅 모델은 일반적으로 언어 모델에 의해 지원되지만 API가 더 구조화되어 있습니다. 특히 채팅 모델은 채팅 메시지 목록을 입력으로 받아 채팅 메시지를 반환합니다.
  • 텍스트 임베딩 모델(Text Embedding Models): 텍스트 임베딩 모델은 텍스트를 입력으로 받아 실수(float) 목록을 반환합니다.

프롬프트(Prompts)

프롬프트(Prompts)를 통해 모델을 프로그래밍하는 새로운 방식입니다. "프롬프트(Prompts)"는 모델에 대한 입력을 의미합니다. 이 입력은 하드 코딩되는 경우는 거의 없지만 여러 컴포넌트로 구성되는 경우가 많습니다. 프롬프트 템플릿(PromptTemplate)은 이 입력의 구성을 담당합니다. LangChain은 프롬프트를 쉽게 구성하고 작업할 수 있도록 여러 클래스와 함수를 제공합니다.

  • 프롬프트 값(PromptValue): 각 모델에 맞는 정확한 입력 타입(텍스트 또는 채팅 메시지)으로 변환할 수 있는 메서드를 제공하는 클래스입니다.
  • 프롬프트 템플릿(Prompt Templates): 프롬프트 값(PromptValue)을 생성하는 클래스입니다. 입력 변수를 받아 PromptValue 구성하고 반환하는 메서드를 제공합니다.
  • 예시 선택기((Example Selectors): 사용자 입력을 받은 다음 사용할 예시 목록을 반환하는 클래스입니다. 프롬프트에 예시를 포함하는 것이 유용한 경우가 많습니다.  이러한 예시는 하드코딩할 수도 있지만 동적으로 선택하면 더 강력한 경우가 많습니다.
  • 출력 파서(Output Parsers): 언어 모델 응답을 구조화하는 데 도움이 되는 클래스입니다. 언어 모델(및 채팅 모델)은 텍스트를 출력합니다. 하지만 단순한 텍스트보다 더 구조화된 정보를 얻고 싶을 때가 많습니다. 이때 출력 파서(Output Parsers)가 필요합니다. 출력 파서는 (1) 모델에 출력 형식을 지정하고, (2) 원하는 형식으로 출력을 파싱하는 것을 담당합니다(필요한 경우 재시도 포함).
    • get_format_instructions() -> str: 언어 모델의 출력 형식을 지정하는 방법에 대한 지침이 포함된 문자열을 반환하는 메서드입니다.
    • parse(str) -> Any: 문자열(언어 모델의 응답)을 받아 어떤 구조화된 데이터로 파싱하는 메서드
    • parse_with_prompt(str) -> Any: 문자열(언어 모델의 응답)과 프롬프트(해당 응답을 생성한 프롬프트)를 받아 어떤 구조화된 데이터로 파싱하는 메서드입니다. 프롬프트는 주로 출력 파서가 어떤 식으로든 출력을 다시 시도하거나 수정하려고 할 때 제공되며, 이를 위해 프롬프트 정보가 필요합니다.

인덱스(Indexes)

인덱스는 LLM이 문서와 가장 잘 상호작용할 수 있도록 문서를 구조화하는 방법을 말합니다. 이 모듈에는 문서 작업을 위한 유틸리티 함수, 다양한 유형의 인덱스, 그리고 이러한 인덱스를 체인에서 사용하는 예시가 포함되어 있습니다.

인덱스가 체인에서 사용되는 가장 일반적인 방법은 ‘검색’ 단계입니다. 이 단계는 사용자의 쿼리를 받아 가장 관련성이 높은 문서를 반환하는 것을 말합니다. 이렇게 구분하는 이유는 (1) 인덱스는 검색 외에 다른 용도로도 사용될 수 있고, (2) 검색은 인덱스 외에 다른 로직을 사용하여 관련 문서를 찾을 수 있기 때문입니다. 따라서 우리는 “검색” 인터페이스라는 개념을 가지고 있으며, 이것이 대부분의 체인이 사용하는 인터페이스입니다.

인덱스와 검색에 대해 이야기할 때는 대부분 텍스트 문서와 같은 비정형 데이터의 인덱싱과 검색에 대해 이야기합니다. 현재 LangChain에서 지원하는 주요 인덱스 및 검색 유형은 벡터 데이터베이스를 중심으로 하고 있으며, 따라서 많은 기능들이 해당 주제에 대해 자세히 다루고 있습니다.

  • 문서 로더(Document Loaders): 다양한 소스에서 문서 로드 작업을 담당하는 클래스입니다.
    • unstructured 패키지를 사용하여 텍스트, 파워포인트, 이미지, HTML, PDF 등 모든 유형의 파일을 텍스트 데이터로 변환할 수 있습니다.
  • 텍스트 분할기(Text Splitters): 텍스트를 더 작은 청크로 분할하는 작업을 담당하는 클래스입니다.
    • 언어 모델이 큰 텍스트를 잘 처리하기 위해서는 해당 텍스트를 더 작은 조각으로 나누어야 합니다.
    • 의미론적으로 관련된 텍스트 조각을 함께 유지해야 합니다.
    • 여기서 "의미론적으로 관련된"이 의미하는 바는 텍스트의 종류에 따라 다를 수 있기 때문에 이에 관한 분할/결합/생성 등이 이뤄져야 합니다.
  • 벡터 저장소(VectorStores): 입력 텍스트를 임베딩을 통해 벡터를 생성하고, 생성된 벡터를 저장/관리/검색할 수 있는 기능을 제공하는 저장소입니다.
    • 가장 일반적인 인덱스 타입은 각 문서에 대해 숫자 임베딩(임베딩 모델 사용)을 생성하는 타입입니다.
    • 임베딩 별로 관련 문서를 빠르게 조회할 수 있고 유사도 검색이 가능합니다.
  • 검색기(Retrievers): 언어 모델과 결합할 관련 문서를 가져오기 위한 인터페이스입니다.
    • 문자열을 받아 문서 목록을 반환하는 get_relevant_documents 메서드를 제공합니다.

메모리(Memory)

메모리는 대화 과정에서 데이터를 저장하고 검색하는 개념입니다. 두 가지 메서드를 제공합니다.

  1. 입력에 따라 관련 데이터를 가져옵니다.
  2. 입력 및 출력을 기반으로 그에 따라 상태를 업데이트합니다.

메모리에는 단기 메모리(Short term memory)와 장기 메모리(Long term memory)의 두 가지 타입이 있습니다.

  • 단기 메모리(Short term memory): 단일 대화의 맥락에서 데이터를 전달하는 방법을 말합니다(일반적으로 이전 채팅메시지(ChatMessage) 또는 그 요약).
  • 장기 메모리(Long term memory): 서로의 대화에서 정보를 가져오고 업데이트하는 방법을 다룹니다.

체인(Chains)

체인은 목적을 달성하기 위해 특정한 방식으로 결합된 일련의 모듈형 컴포넌트(또는 다른 체인)로 돌아가는 매우 일반적인 개념입니다.

가장 일반적으로 사용되는 체인 유형은 프롬프트 템플릿(PromptTemplate), 모델(Model), 가드레일(Guardrails)을 결합하여 사용자 입력을 받아 그에 따라 형식을 지정하고 모델에 전달하여 응답을 받은 다음 모델 출력의 유효성을 검사하고 수정(필요한 경우)하는 LLMChain입니다.

  • Chain: 여러 개별 컴포넌트를 포괄하는 종단 간 래퍼(end-to-end wrapper)입니다.
  • LLMChain: 가장 일반적인 유형의 체인입니다.
    • PromptTemplate, 모델(LLM 또는 ChatModel), 옵셔널 출력 파서로 구성됩니다.
    • 이 체인은 여러 입력 변수를 받아 PromptTemplate을 사용하여 프롬프트로 포맷을 지정합니다. 그런 다음 이를 모델에 전달합니다.
    • 마지막으로 출력 파서(제공된 경우)를 사용하여 LLM의 출력을 최종 포맷으로 파싱합니다.
  • 프롬프트 선택기(Prompt Selector): 전달된 모델에 따라 기본 프롬프트를 선택하는 역할을 담당합니다.
  • Index-related chains: 이 체인의 목적은 인덱스에 저장된 자신의 데이터를 LLM과 결합하는 것입니다. 가장 좋은 예시는 자신의 문서에서 질문에 대한 답변을 찾는 것입니다.
    • 스터핑(Stuffing): 스터핑은 모든 관련 데이터를 프롬프트에 콘텍스트로 채워 언어 모델에 전달합니다. 스터핑은 StuffDocumentsChain으로 구현됩니다.
      • 장점: LLM을 한 번만 호출합니다. 텍스트를 생성할 때 LLM은 모든 데이터에 한 번에 액세스 할 수 있습니다.
      • 단점: 대부분의 LLM에는 입력 가능한 최대 컨텍스트 길이가 정해져 있습니다. 따라서 큰 문서(또는 많은 문서)를 프롬프트에 포함시킬 경우, 컨텍스트 길이가 제한을 넘어버리므로 작동하지 않을 수 있습니다.
    • 맵 리듀스(Map Reduce): 맵 리듀스는 각 데이터 청크에 대해 초기 프롬프트를 실행하는 것입니다(요약 작업의 경우 해당 청크에 대한 요약일 수 있고, 질문 답변 작업의 경우 해당 청크에 기반한 답변일 수 있습니다). 그런 다음 다른 프롬프트가 실행되어 모든 초기 출력을 결합합니다. 맴 리듀스는 MapReduceDocumentsChain으로 구현됩니다.
      • 장점: StuffDocumentsChain 보다 더 큰 문서(및 더 많은 문서)로 확장할 수 있습니다. 개별 문서에 대한 LLM 호출은 독립적이므로 병렬화할 수 있습니다.
      • 단점: StuffDocumentsChain 보다 훨씬 더 많은 LLM 호출이 필요합니다. 마지막 결합 호출 중에는 일부 정보가 손실됩니다.
    • 리파인(Refine): 리파인은 첫 번째 데이터 청크에서 초기 프롬프트를 실행하여 일부 출력을 생성합니다. 나머지 문서의 경우에는, 해당 출력이 다음 문서와 함께 전달되어 새 문서를 기반으로 출력을 구체화하도록 LLM에 요청합니다.
      • 장점: 더 관련성 높은 컨텍스트를 가져올 수 있으며, MapReduceDocumentsChain 보다 손실이 적을 수 있습니다.
      • 단점: StuffDocumentsChain 보다 LLM에 대한 호출이 더 많이 필요합니다. 또한 호출은 독립적이지 않으므로 MapReduceDocumentsChain 처럼 병렬로 실행할 수 없습니다. 또한 문서 순서에 대한 잠재적인 종속성이 있습니다.
    • 맵-리랭크(Map-Rerank): 맵-리랭크은 각 데이터 청크에 대해 초기 프롬프트를 실행하여 작업을 완료하려고 시도할 뿐만 아니라, 답변이 얼마나 확실한지에 대한 점수를 부여합니다. 그런 다음 이 점수에 따라 응답의 순위가 매겨지고 가장 높은 점수를 반환합니다.
      • 장점: MapReduceDocumentsChain 장점과 비슷합니다. 하지만MapReduceDocumentsChain에 비해 호출이 더 적습니다.
      • 단점: 문서 간의 정보를 결합할 수 없습니다. 즉, 하나의 문서에 하나의 간단한 답변이 있을 것으로 예상할 때 가장 유용합니다.

에이전트(Agents)

일부 애플리케이션은 LLM/기타 도구에 대한 미리 정해진 체인을 호출하는 것뿐만 아니라, 사용자의 입력에 따라 달라지는 알려지지 않은 체인이 필요할 수 있습니다. 에이전트는 도구를 사용하여 이러한 유형의 체인에 액세스할 수 있습니다. 에이전트는 사용자 입력에 따라 이러한 도구 중 어떤 도구를 호출할지 결정할 수 있습니다.

  • 도구(Tools): 언어 모델이 다른 리소스와 상호 작용하는 방법입니다.
    • 언어 모델과 쉽게 상호 작용할 수 있도록 하는 특정 기능에 대한 추상화 함수입니다.
    • 구체적으로 도구의 인터페이스는 단일 텍스트 입력과 단일 텍스트 출력을 가지고 있습니다.
  • 툴킷(Toolkits): 특정 문제를 해결하거나 특정 작업을 수행할 때 필요한 도구 세트입니다.
  • 에이전트(Agents): 의사 결정을 내리는 데 사용되는 언어 모델입니다.
    • 에이전트는 모델을 감싸는 래퍼(wrapper)로, 사용자 입력을 받아 수행할 "액션(action)"과 그에 해당하는 "입력 액션(action input)"에 해당하는 응답을 반환합니다.
  • 에이전트 실행자(Agent Executor): 도구와 함께 에이전트를 실행하기 위한 로직입니다.
    • 에이전트 실행자는 에이전트와 도구 세트입니다.
    • 에이전트 실행기는 (1) 에이전트를 호출하고, (2) "액션"과 "액션 입력"을 다시 받아서, (3) 해당 입력으로 액션이 참조하는 도구를 호출하고, (4) 도구의 출력을 가져온 다음 모든 정보를 다시 에이전트로 전달하여 (5) 다음 액션을 가져오는 일을 담당합니다.

or

[카카오페이로 후원하기] [토스페이로 후원하기]

반응형