LangChain: LLMChain으로 PromptTemplate, LLM, OutputParser 연결하기

앞에서 LangChain의 거대 언어 모델 유형으로 문장 완성을 위한 LLMs와 대화를 위한 ChatModels가 있다는 것을 확인했습니다. 프롬프트 작성을 위한 PromptTemplate들도 봤고, 출력 형식 지정을 위한 OutputParser도 봤습니다.

LangChain의 Chain 기능은 여러 기능들을 연결해서(chain) 편리하게 이용할 수 있는 기능입니다. 이 기능을 이용하면 사용자의 입력을 받아 PromptTemplate을 이용해 프롬프트를 만들고 LLM에 전달한 후 OutputParser를 이용해 결과를 반환하는 하나의 Chain을 만들 수 있습니다. 필요하면 Chain들끼리 연결하는 것도 가능합니다. 여러 Chain들 중 가장 기본이 되는 Chain은 LLMChain입니다.

LLMChain: PromptTemplate + LLM

예제를 위해 먼저 LLM과 프롬프트 템플릿을 만들었습니다.

from langchain.chat_models import ChatOpenAI
from langchain.prompts import PromptTemplate

llm = ChatOpenAI(temperature=0.9)

prompt = PromptTemplate(
    input_variables=["what"],
    template="{what} 이름 세 개를 추천해줘.",
)

위에서 ChatOpenAI (gpt-3.5-turbo)를 사용했는데, 문장 완성 모델인 OpenAI (text-davinci-003)를 사용해도 됩니다. 여기서는 성능이 더 좋아서 ChatOpenAI를 선택했습니다. 이제 둘을 LLMChain으로 연결합니다.

from langchain.chains import LLMChain
chain = LLMChain(llm=llm, prompt=prompt)

print(chain.run("새로 만든 거대 언어 모델"))

### 결과
1. GigaMinds
2. MegaLinguo
3. SuperVerse

LLMChain 실행 방법

이렇게 LLMChain으로 llmprompt를 연결한 후 chain.run으로 한 번에 실행할 수 있습니다. 참고로, chain을 실행하는 방법에는 여러 가지가 있습니다.

chain.run("새로 만든 거대 언어 모델")
chain.run({"what":"새로 만든 거대 언어 모델"})
chain.predict(what="새로 만든 거대 언어 모델")

위 세 가지 방법은 앞의 결과처럼 문자열을 반환합니다.

chain("새로 만든 거대 언어 모델")

### 결과
{'what': '새로 만든 거대 언어 모델',
 'text': '1. 인지어 (CogniLang)\n2. 심대어 (MenteLingua)\n3. 우주어 (CosmoLexis)'}

위 경우에는 딕셔너리를 반환했고, 결과는 ‘text’에 들어 있습니다.

input_list = [
    {"what":"새로 만든 거대 언어 모델"},
    {"what":"새로 만든 그림 생성 AI"}
]
chain.apply(input_list)

### 결과
[{'text': '1. "Aether"\n2. "Luminex"\n3. "Omnilingua"'},
 {'text': '1. PaintPal\n2. CreativeCanvas\n3. ArtGenius'}]

리스트를 만들어 입력했고, 결과를 담은 딕셔너리들의 리스트를 받았습니다. LLM으로 ChatOpenAI를 사용했지만, 기본적으로 LLMChain은 대화를 이어가는 기능이 아닙니다. 위에서 응답 결과는 input_list 내에 있는 각각의 질문에 대한 대답입니다. 대화를 위해서는 ConversationChain이 별도로 존재합니다.

chain.generate(input_list)

### 결과
LLMResult(
generations=[
[ChatGeneration(text='1. 바나나AI\n2. 루나\n3. 메가클라우드', generation_info={'finish_reason': 'stop'}, message=AIMessage(content='1. 바나나AI\n2. 루나\n3. 메가클라우드', additional_kwargs={}, example=False))], 
[ChatGeneration(text='1. CreARTist\n2. AImagination\n3. ArtiVision', generation_info={'finish_reason': 'stop'}, message=AIMessage(content='1. CreARTist\n2. AImagination\n3. ArtiVision', additional_kwargs={}, example=False))]
],
llm_output={'token_usage': {'prompt_tokens': 62, 'completion_tokens': 40, 'total_tokens': 102}, 'model_name': 'gpt-3.5-turbo'}, 
run=[RunInfo(run_id=UUID('144c8d77-c1a6-48d3-a65a-983db734b6e9')), RunInfo(run_id=UUID('939a315a-b71c-48f1-9814-0abf6bfca23a'))]
)

generate를 사용하면 LLMResult 객체를 반환하는데, 여기에는 토큰수와 같은 추가 정보가 들어가 있습니다.

PromptTemplate에 변수를 여러 개 넣는 것도 가능하죠.

prompt = PromptTemplate(
    input_variables=["desc", "what"],
    template="{desc} {what} 이름 세 개를 추천해줘.",
)
chain2 = LLMChain(llm=llm, prompt=prompt)
print(chain2.run({
    'desc': "한국적인",
    'what': "거대 언어 모델"
    }))

PromptTemplate 대신 ChatPromptTemplate을 사용하는 것도 가능합니다.

from langchain.chat_models import ChatOpenAI
from langchain.prompts.chat import (
    ChatPromptTemplate,
    HumanMessagePromptTemplate,
)
human_message_prompt = HumanMessagePromptTemplate(
        prompt=PromptTemplate(
            template="{what} 이름 세 개를 추천해줘.",
            input_variables=["what"],
        )
    )
chat_prompt_template = ChatPromptTemplate.from_messages([human_message_prompt])
chat = ChatOpenAI(temperature=0.9)

chain = LLMChain(llm=chat, prompt=chat_prompt_template)
print(chain.run("새로 만든 거대 언어 모델"))

LLMChain: PromptTemplate + LLM + OutputParser

OutputParser도 chain으로 연결할 수 있습니다. 여기서는 CommaSeparatedListOutputParser를 사용하겠습니다. 문자열을 쉼표로 분리하여 리스트로 만들어주는 파서입니다.

from langchain.output_parsers import CommaSeparatedListOutputParser

output_parser=CommaSeparatedListOutputParser()
prompt = PromptTemplate(
    input_variables=["what"],
    template="{what} 이름 세 개를 추천해줘. \n{format_instructions}",
    partial_variables={"format_instructions": output_parser.get_format_instructions()}
)

위 코드에서 partial_variables를 사용했는데, 이는 템플릿 안의 변수들 중 일부만 미리 치환할 수 있는 기능입니다. PromptTemplate에 output_parser의 포맷 명령을 넣었는데, chain에 output_parser를 안 넣고 실행해보겠습니다.

chain = LLMChain(llm=chat, prompt=prompt)
chain.predict(what="새로 만든 거대 언어 모델")

### 결과
'GigaNLP, MegaLang, SuperGPT'

프롬프트에 출력 포맷을 지정했기 때문에 결과가 쉼표로 구분되 나오기는 했는데, 문자열이 반환되어 나왔습니다. 이번에는 chain에 output_parser를 추가해보겠습니다.

chain = LLMChain(llm=chat, prompt=prompt, output_parser=output_parser)
chain.predict(what="새로 만든 거대 언어 모델")

### 결과
['GLOMO', 'MEGALINGUA', 'LEXICON3000']

결과가 리스트로 나왔습니다! 이렇게 Chain을 이용하면 PromptTemplate과 LLM, OutputParser를 연결해 사용할 수 있습니다. Chain은 LangChain 이름에서 알 수 있는 것처럼 LangChain의 핵심 기능입니다.

댓글 남기기