LangChain의 LCEL에 대해 알아보자

034179·2024년 11월 24일

LangChain

랭체인은 LLM을 사용하여 애플리케이션 생성을 단순화하도록 설계된 프레임워크이다.

랭체인을 이해하기 위해서는 아래의 세 가지 개념이 핵심적이다.

LCEL은 LangChain의 컴포넌트들을 선언적으로 연결하는 방식으로, LangChain이 정의한 구조이자 문법이라고 생각하면 이해하기 쉽다.

LangChain (Language + Chain)의 이름에서도 알 수 있듯이, 여러 컴포넌트를 사슬처럼 연결하여 하나의 Chain으로 만든다.

이를 통해 Chain에 input을 넣으면 첫번째 컴포넌트에서 생성된 output이 다음 input으로 입력되어, LLM 애플리케이션을 만들기 위한 복잡한 단계를 하나의 Chain으로 구성하는 것이다.

여기서 컴포넌트는 Chain을 만들기 위한 구성 요소이다. 레고 블럭처럼 컴포넌트들을 연결하여 Chain을 만드는 것이다.


LCEL

LangChain Expression Language (LCEL)

LangChain Expression Language (LCEL)은 LangChain의 컴포넌트들을 선언적으로 연결하는 방식으로, 다양한 언어 모델 워크플로우를 효율적으로 구성할 수 있는 도구입니다.
LCEL의 설계는 처음부터 프로토타입을 프로덕션 환경에 배포할 수 있도록 지원하도록 고안되었으며, 코드 변경 없이도 간단한 체인부터 복잡한 체인까지 모두 대응할 수 있습니다. LCEL을 사용하는 주요 이유는 다음과 같습니다:

  1. 스트리밍 지원: LCEL을 통해 체인을 구성하면, 최적화된 토큰 스트리밍을 지원하여 출력의 첫 번째 토큰이 나오는 시간을 줄일 수 있습니다. LLM에서 나온 토큰을 실시간으로 파싱하고, 토큰이 생성되는 즉시 출력합니다.
  2. 비동기 지원: LCEL로 구축된 체인은 동기 및 비동기 API 모두에서 호출할 수 있습니다. 예를 들어, Jupyter 노트북에서 동기 API로 프로토타입을 만들거나, 프로덕션 환경에서는 비동기 API를 통해 여러 요청을 동시에 처리할 수 있습니다.
  3. 병렬 실행 최적화: LCEL 체인이 병렬로 실행할 수 있는 단계가 있을 때, 자동으로 병렬 처리를 수행하여 최소 지연 시간을 보장합니다.
  4. 재시도 및 대체 경로: 체인의 일부 단계에서 오류가 발생할 경우, 재시도 및 대체 경로(fallbacks)를 설정하여 체인의 안정성을 높일 수 있습니다. 또한 스트리밍 지원이 추가되어, 대기 시간 없이 안정성을 확보할 수 있도록 작업 중입니다.
  5. 중간 결과 접근: 복잡한 체인의 경우, 최종 출력이 생성되기 전 중간 단계 결과에 접근하는 것이 유용할 수 있습니다. 이를 통해 사용자가 작업이 진행 중이라는 것을 알리거나, 디버깅 목적으로 중간 결과를 확인할 수 있습니다.
  6. 입출력 스키마: 각 LCEL 체인은 Pydantic과 JSONSchema 스키마를 사용하여 입력 및 출력에 대한 유효성을 검사할 수 있습니다. 이는 LangServe에서 중요한 부분으로 작용합니다.
  7. LangSmith와의 통합: 체인이 복잡해질수록 각 단계에서 무슨 일이 일어나고 있는지 파악하는 것이 중요해집니다. LCEL은 모든 단계가 LangSmith에 자동으로 로그 기록되어 최대한의 가시성과 디버깅 기능을 제공합니다.

LCEL은 이전의 체인들(예: LLMChain 또는 ConversationalRetrievalChain)에서 감춰져 있던 중요한 세부 사항을 보다 명확히 드러내며, 커스터마이징이 가능하도록 설계되었습니다.


LCEL and Composition

LangChain Expression Language(LCEL)은 Runnables를 체인으로 구성하는 선언적인 방식입니다. 이렇게 구성된 체인은 자동으로 동기(sync), 비동기(async), 배치(batch), 스트리밍(streaming)을 지원합니다.

LCEL의 주요 구성 요소(프리미티브)는 RunnableSequenceRunnableParallel입니다.

  1. RunnableSequence:
    • 이 구성 요소는 일련의 Runnables를 순차적으로 실행합니다. 하나의 Runnable의 출력이 다음 Runnable의 입력으로 사용됩니다.
    • | 연산자를 사용하거나, 여러 Runnables를 리스트로 RunnableSequence에 전달하여 구성할 수 있습니다.
    • 즉, 순차적으로 실행되어 하나의 결과가 다음 실행의 입력으로 이어지는 방식입니다.
  2. RunnableParallel:
    • 동일한 입력값을 여러 Runnable에 동시에 전달하며, 각 Runnable이 병렬로 실행됩니다.
    • 딕셔너리 형식의 리터럴을 시퀀스 내에 사용하거나, 딕셔너리를 RunnableParallel에 전달하여 구성할 수 있습니다.
    • 병렬로 실행되기 때문에, 각 실행이 같은 입력을 사용하지만 결과는 개별적으로 처리됩니다.

이 방식은 복잡한 비즈니스 로직을 체인으로 쉽게 구현할 수 있으며, 각 Runnable을 순차적으로 또는 병렬로 실행할 수 있는 유연성을 제공합니다.


Runnable interface

LangChain의 Runnable 인터페이스

LangChain에서 Runnable 프로토콜을 사용하여 사용자 정의 체인을 쉽게 만들 수 있습니다. 이 프로토콜은 다양한 컴포넌트들이 표준화된 방식으로 실행될 수 있도록 해주며, 다음과 같은 기본적인 메서드를 제공합니다:

  • stream: 출력의 일부를 실시간으로 스트리밍
  • invoke: 입력값을 사용하여 체인을 호출
  • batch: 여러 입력을 한 번에 처리

비동기 방식도 지원하며, 이를 위해 asyncioawait 구문을 사용합니다:

  • astream: 출력의 일부를 비동기적으로 스트리밍
  • ainvoke: 비동기적으로 입력을 호출
  • abatch: 여러 입력을 비동기적으로 처리

각 컴포넌트는 입력 스키마출력 스키마를 제공하며, Pydantic 모델을 기반으로 자동 생성되어 입력과 출력의 유효성을 검사하는 데 사용됩니다.

0개의 댓글