랭체인 프로그래밍: 개념과 응용 – 004
템플릿은 일정한 형식을 유지하며 반복적인 작업을 쉽게 처리할 수 있게 해줍니다. 예를 들어, 문서 작성 템플릿을 사용하면 매번 새로운 문서를 작성할 때마다 기본적인 레이아웃과 스타일이 동일하게 유지되며, 그 안에 내용만 바꾸면 됩니다.
프롬프트를 작성하다보면 많은 부분이 같고 일부분은 다른 것들이 등장합니다. 이럴 때, 고정된 부분은 그대로 유지하고 변경 부분만 상황에 맞게 교체하는 방식으로 템플릿을 활용할 수 있습니다.
프롬프트는 지시 문자열이니, 생성 지시에서 고정 부분과 변경 부분을 구분해서 변경 부분을 대체할 수 있으면 됩니다. 이러 필요가 있을 때 사용할 수 있는 문자열 다루는 기술이 ‘문자열 포맷팅과 변수 대체’입니다.
LangChain에서는 프롬프트 템플릿을 문자열 포맷팅과 변수 대체를 구현한 PromptTemplate로 지원합니다.
어떤 포맷팅을 사용해야 할까요? 고정된 부분과 변경될 부분을 구분해야 합니다. 고정 부분은 고정된 문자열로 작성하면 되고, 변경 부분은 변수로 지정합니다.
- 변수를 다른 문자열과 구분하기 위해서 구분자를 사용합니다.
{}
중괄호를 사용해 변수 위치 표시- 예:
"안녕하세요, {name}님"
- 예:
- 변경 부분이 결정된다는 것은 변수 값이 설정된다는 것입니다. 변수 값이 설정되면 변수 부분을 변수 값으로 대체해 전체 문장을 완성합니다.
.format()
메서드나 f-스트링이나 딕셔너리 매핑을 사용합니다.- template = “안녕하세요, {name}님. {age}세이시군요.”
- result1 = template.format(name=”김철수”, age=30)
- result2 = template.format(name=”이영희”, age=25)
-
12345678template = """당신은 {character} 역할입니다.{personality}의 특성을 가지고 있습니다.상황: {scenario}요청: {task}"""
123456prompt = template.format(character="스타트업 CEO",personality="혁신적이고 도전적인",scenario="투자 유치 상황",task="투자자에게 회사의 비전 설명")
LangChain의 PromptTemplate
은 단순한 문자열 포맷팅을 넘어, LLM과의 상호작용을 더욱 정교하고 체계적으로 만들어주는 고급 도구입니다.
f-스트링(f-string)은 Python 3.6부터 도입된 문자열 포맷팅 방식으로, 문법이 간단하고 가독성이 뛰어난 것이 특징입니다. f-스트링은 문자열 앞에 기본 사용법:
장점:
|
PromptTemplate
- PromptTemplate.from_template
- 프롬프트 템플릿 문자열로 부터 PromptTemplate을 생성한다.
-
1234567template = PromptTemplate.from_template("""당신은 {role} 전문가입니다.질문: {question}응답: """" # 응답 처리 결과를 나타내는 자리 표시자)inputs = { "role": "의학", "question": "코로나19의 주요 증상은 무엇인가요?" } # 템플릿을 사용하여 프롬프트 생성 formatted_prompt = template.invoke(inputs)
-
- invoke
- 변수 값들로 프롬프트 템플릿의 가변 부분을 채워 프롬프트를 완성합니다.
- 이 템플릿은
{role}
과{question}
자리 표시자를 포함하여, 런타임 시 실제 값을 동적으로 삽입할 수 있도록 합니다.
- 이 템플릿은
-
12# 템플릿을 사용하여 프롬프트 생성formatted_prompt = template.invoke(inputs)
- 변수 값들로 프롬프트 템플릿의 가변 부분을 채워 프롬프트를 완성합니다.
- 프롬프트 템플릿 문자열로 부터 PromptTemplate을 생성한다.
랭체인은 생생성형 AI 애플리케이션 개발 프레임워크로서, 구성 요소들을 단순히 기능 단위로 제공하는 것을 넘어, 구성 요소들의 역할 자체를 추상화하여 더욱 유연하고 확장 가능한 아키텍처를 제공합니다. 즉, 특정 기능을 수행하는 구체적인 구성 요소가 아니라, 그 기능이라는 역할 자체를 정의하고, 그 역할을 수행하는 다양한 구현체를 지원합니다.
이러한 역할 중심의 추상화는 다음과 같은 이점을 제공합니다.
- 유연성 향상: 새로운 구성 요소나 기술이 등장하더라도, 기존의 역할 정의를 변경할 필요 없이 새로운 구현체를 추가하기만 하면 됩니다. 이는 LangChain 기반 애플리케이션의 유지보수 및 확장성을 크게 향상시킵니다.
- 재사용성 증대: 특정 역할을 수행하는 구성 요소는 여러 애플리케이션에서 재사용될 수 있습니다. 이는 개발 시간을 단축하고 코드 중복을 줄이는 데 기여합니다.
- 개발 편의성 증대: 개발자는 구체적인 구현에 대한 세부 사항에 신경 쓰지 않고, 역할에 집중하여 애플리케이션을 설계할 수 있습니다. 이는 개발의 복잡성을 줄이고 생산성을 높입니다.
랭체인은 역할 중심의 추상화를 넘어 역할들에 대한 추상화도 진행했습니다. 프롬프트 템플릿 역할을 PromptTemplate으로 모델 클라이언트의 역할을 OpenAI, ChatOpenAI로 정의했고, 프롬프트 템플릿도 모델 클라이언트도 그 자체가 의미 있는 것이 아니라 실행되어 의미 있는 결과를 리턴해야 하는 것으로 추상화해 보면 같은 것으로 볼 수 있습니다. 실행해야 하는 것 Runnable로 볼 수 있다는 것입니다.
랭체인은 단순히 구성 요소의 역할을 추상화하는 것을 넘어, 역할들에 대한 추상화도 진행했습니다.
- 실행 가능성(Runnable)
-
PromptTemplate
는 프롬프트를 생성하는 역할을 하고,OpenAI
나ChatOpenAI
는 LLM을 호출하는 역할을 하지만, 둘 모두 입력을 받아 출력을 생성하는 실행 가능한(Runnable) 객체로 볼 수 있습니다. 이러한 관점에서invoke
메서드는 이러한 다양한 Runnable 객체들을 일관되게 호출하고 결과를 얻기 위한 표준화된 인터페이스 역할을 합니다.- 입력을 받아 출력하는 경우를 좀 더 꼼꼼하게 살펴보겠습니다.
- 하나의 입력이 아니라 여러 입력이 있을 수도 있습니다.
invoke
를 하나의 입력을 받는 것으로batch
를 여러 입력을 받는 것으로 합니다.
- 전체 출력이 모두 만들어진다음에 리턴할 수도 있지만 처리하는 만큼씩 리턴할 수도 있습니다.
- 처리하는 만큼 리턴하는 것을
stream
이라 합니다.
- 처리하는 만큼 리턴하는 것을
- 하나의 입력이 아니라 여러 입력이 있을 수도 있습니다.
- 입력을 받아 출력하는 경우를 좀 더 꼼꼼하게 살펴보겠습니다.
- 랭체인에서는 역할들의 추상화에는 명시적인 인터페이스를 정의하지 않고, 선언적인 방식을 사용합니다.
- Runnable을 예로 들면, 다음과 같이 말할 수 있는 것입니다.
- 이런 것들은 Runnable이라고 하는데, Runnable한 것들은
invoke
,batch
,stream
을 할 수 있습니다. 당신이 만든 클래스에 이런 함수를 같으면 이렇게 처리될 것입니다.
- 이런 것들은 Runnable이라고 하는데, Runnable한 것들은
- LangChain Expression Language (LCEL)은 LangChain 구성 요소들을 결합하기 위한 선언형 언어입니다. LangChain은 LCEL 구성을 최적화된 실행 계획으로 컴파일합니다. 이 계획에는 자동 병렬 처리, 스트리밍, 추적 및 비동기 지원이 포함됩니다.
- LCEL은 구성 요소들의 연결 방식과 실행 순서를 명시적으로 정의하는 방식으로, 명령형 방식보다 더욱 간결하고 가독성이 높은 코드를 작성할 수 있게 해줍니다. 또한, LCEL은 자동으로 병렬 처리, 스트리밍, 비동기 지원 등을 제공하여 개발 효율성을 높입니다. 명령형 방식과 달리 스트리밍이나 비동기 처리를 위해 함수를 수정할 필요가 없다는 장점이 있습니다. 복잡한 작업의 경우, LCEL을 사용하면 코드의 가독성과 유지보수성을 크게 향상시킬 수 있습니다.
- Runnable을 예로 들면, 다음과 같이 말할 수 있는 것입니다.
-