빅데이타 & 머신러닝/생성형 AI (ChatGPT etc)

Langchain을 이용한 LLM 애플리케이션 개발 #13 - Chain을 이용한 워크 플로우 구현 #1

Terry Cho 2024. 1. 24. 15:04

Chain을 이용한, LLM 워크 플로우 구현 #1

조대협  (http://bcho.tistory.com)

 

LLM 기반 애플리케이션을 개발할때, 한번의 LLM 호출로 결과를 낼 수 도 있지만, 복잡한 LLM 애플리케이션의 경우,  LLM의 출력을 다시 다음 LLM의 입력으로 넣어서 LLM을 여러개를 연결해서 답변을 낼 수 도 있고, 입력 프롬프트에 따라서 알맞은 LLM이나 프롬프트를 선택하도록 분기 할 수 있다. 

예를 들어 Python Coding을 해주는 LLM에서 API 파이썬 코드를 생성한 후에, 이 코드에 맞는 Unit Test 코드를 생성하는 LLM을 호출하거나, 

<그림. 순차적으로 LLM을 호출 하는 구조>

아래 그림과 같이 학교 학생의 공부를 도와주는 챗봇에서 질문의 종류에 따라서, 영어,과학,수학 LLM을 선택적으로 호출하는 구조를 예로 들 수 있다.

<그림. 질문에 따라서 다양한 LLM으로 분기하는 구조>

이렇게 여러개의 LLM을 연결하여 LLM 애플리케이션을 개발할 수 있는 기능이 Langchain에서 Chain이라는 컴포넌트이다. 물론 직접 chatgpt api등을 사용해서 이런 복잡한 흐름을 개발할 수 있지만 Langchain의 chain은 이를 쉽게 개발 할 수 있도록 추상화된 계층을 제공한다. 

이번 장에서는 Chain에 대해서 알아보기로 한다. 

LLMChain

먼저 LLMChain의 개념을 이해해야 하는데, LLM Chain은 프롬프트 템플릿을 LLM을 합쳐서 컴포넌트화 한 것이다.  즉 입력값으로 문자열을 넣으면 프롬프트 템플릿에 의해서 프롬프트가 자동으로 완성되고, LLM 모델을 호출하여 텍스트 출력을 내주는 기능을 한다. 아래 예제를 보자.

이 예제는 도시 이름을 입력하면 출력으로 그 도시의 유명한 관광지를 리턴하는  LLM Chain을 구현한 예이다.

 

from langchain.llms import OpenAI

from langchain.prompts import PromptTemplate

from langchain.chains import LLMChain

 

OPEN_AI_APIKEY="{YOUR_OPENAI_KEY}"

model = OpenAI(openai_api_key=OPEN_AI_APIKEY)

 

prompt = PromptTemplate.from_template("what is the famous tour place in {city}?")

chain = LLMChain(llm=model, prompt=prompt)

city = "Seoul"

chain.run(city)

 

chain = LLMChain(llm=model,prompt)에서, LLMChain을 생성하였다. 이때, 사용할 프롬프트 템플릿과 LLM 모델을 지정하였다. 이 LLMChain을 호출할때는 chain.run(입력변수)를 이용해서 호출할 수 있다. 아래 출력결과는 “seoul”을 입력값으로 넣었을때 결과이다. 

 

'One of the most famous tourist attractions in Seoul is Gyeongbokgung Palace. It is a grand palace and the largest of the Five Grand Palaces built by the Joseon Dynasty. Another popular destination is N Seoul Tower, which offers panoramic views of the city. Other notable places to visit include Bukchon Hanok Village, Myeongdong shopping district, Dongdaemun Design Plaza, and the vibrant neighborhood of Hongdae.'




Sequential Chain

LLMChain 컴포넌트를 만들었으면, 이제 LLMChain들을 서로 연결하는 방법에 대해서 알아보자. 

아래 예제는 먼저 도시 이름 {city}을 입력 받은 후에, 첫번째 chain에서 그 도시의 유명한 관광지 이름을 {place}로 출력하도록 한다. 다음 두번째 chain에서는 관광지 이름 {place}를 앞의 chain에서 입력 받고, 추가적으로 교통편 {transport}를 입력받아서, 그 관광지까지 가기 위한 교통편 정보를 최종 출력으로 제공한다. 

 

< 그림. 관광지 교통 정보 제공을 위하여 LLMChain 두 개를 연결한 구조>

 

이렇게 여러 Chain을 순차적으로 연결하게 해주는 컴포넌트가 SequentialChain이다. 아래 코드를 살펴보자. 

 

from langchain.llms import OpenAI

from langchain.prompts import PromptTemplate

from langchain.chains import LLMChain

from langchain.chains import SequentialChain

 

OPEN_AI_APIKEY="{YOUR_OPENAI_KEY}"

model = OpenAI(openai_api_key=OPEN_AI_APIKEY)

 

prompt1 = PromptTemplate.from_template("what is the famous tour place in {city}? Tell me the name of the place only without additional comments.")

prompt2 = PromptTemplate.from_template("How can I get {place} by {transport}?")

chain1 = LLMChain(llm=model,prompt=prompt1,output_key="place",verbose=True)

chain2 = LLMChain(llm=model,prompt=prompt2,verbose=True)

 

chain = SequentialChain(chains=[chain1,chain2]

                        ,input_variables=["city","transport"],verbose=True)

 

chain.run({'city':'Seoul','transport':'subway'})

 

먼저 프롬프트와 LLM모델을 이용하여 LLMChain인 chain1,chain2 를 생성하였다. 이때 실행과정을 지켜보기 위해서 verbose=True로 주었다. chain1 생성시에 output_key를 명시적으로 place로 지정해준것을 볼 수 있는데, 두번째 chain2에서 chain1의 output을 입력으로 받기 위해서 output의 키 이름을 명시적으로 정의한후, chain2에서 chain1의 output을 프롬프트 내에서 지정하기 위함이다. 

chain2의 프롬프트를 보면 "How can I get {place} by {transport}?"와 같이 chain1의 output인 {place}와 ,  애플리케이션에서 추가적으로 입력받은 {transport} 부분을 입력 변수로 사용한것을 확인할 수 있다. 

 

다음으로 이 chain1과 chain2를 순차적으로 연결해야 하는데, 여기서 SequentialChain을 사용한다. 

 

chain = SequentialChain(chains=[chain1,chain2]

                        ,input_variables=["city","transport"],verbose=True)

chains를 이용하여, chain1과 chain2를 사용함을 명시적으로 지정하고, 입력 변수는 city와 tranport를 애플리케이션을 통해서 입력 받음을 명시한다. 마지막으로 chain.run을 통해서 SequentialChain을 실행하는데, 두개의 입력 변수를 요구로 하기 때문에, 딕셔너리를 통해서 city와 transport를 각각 seoul과 subway로 전달하였다. 

 

아래는 실행결과이다. 첫번째로 SequentialChain에 진입한것을 확인할 수 있고, 다음 chain1에서 “what is the famous tour place in Seoul?”프롬프트를 통하여 Seoul의 유명 관광지를 질의하였다. 두번째 chain2에서는 chain1의 결과인 “Gyeongbokgung(경복궁)”과 애플리케이션에서 입력받은 “subway”를 이용하여 “How can I get Gyeongbokgung Palace by subway?” 프롬프트를 생성하여 질의를 하고 최종 결과를 출력한것을 확인할 수 있다.  

 

> Entering new SequentialChain chain... #SequentialChain 진입



> Entering new LLMChain chain... # 첫번째 LLM Chain 호출

Prompt after formatting:

what is the famous tour place in Seoul? Tell me the name of the place only without additional comments.

 

> Finished chain.



> Entering new LLMChain chain... # 두번째 LLM Chain 호출

Prompt after formatting:

How can I get 

Gyeongbokgung Palace by subway?

 

> Finished chain.

 

> Finished chain. # SequentialChain 종료 및 최종 결과 출력

 

[38]:

'\n\nTo get to Gyeongbokgung Palace by subway, you can take Line 3 to Gyeongbokgung Station (Exit 5). From there, it is a short walk to the palace entrance.'



그리드형