본문 바로가기
Tech Insights

랭체인(LangChain) Chains 기능을 활용한 블로그 자동화

by Kudos IT Daily 2023. 11. 23.
반응형

랭체인(LangChain) Chains 기능을 활용한 블로그 자동화

목차

  • Chains & LCEL
  • 간단한 LCEL 예제
  • 자동화 블로그 글 예제
  • 마치며

 

안녕하세요. 오랜만에 랭체인 포스팅으로 돌아왔습니다. 이번 글에서는 랭체인의 Chains 기능을 활용해서 재미있고 실용적인 예제를 만들어보고자 합니다. 랭체인의 Chains 기능을 활용해서 블로그 글을 자동 생성하는 프로그램을 만들어 볼 예정입니다. 단순히 ChatGPT에 블로그 글 생성 프롬프트를 전달해서 응답을 받는 것과는 다릅니다. 블로그 글을 자동으로 생성하기 위해 언어 모델에게 키워드 찾기, 대상 독자 찾기, 블로그 글 생성 등 여러 역할을 부여할 것입니다. 이후, 여러 역할의 언어 모델이 생성한 결과물을 종합해서 최종 글을 생성할 것입니다.

 

Chains & LCEL

본격적으로 프로그램 코드를 작성하기 전에 랭체인의 체인에 대해 알아보도록 하겠습니다. 체인은 말 그대로 랭체인의 여러 컴포넌트를 '연결'하기 위한 기능입니다. 간단한 LLM(Large Language Model) 기반 프로그램은 하나의 언어모델로 동작할 수 있지만 프로그램이 복잡해지고 거대해질수록 LLM 간 상호작용이 필요합니다. 따라서, 랭체인 프레임워크를 활용해서 LLM 애플리케이션을 개발하고자 하면 '체인' 기능을 잘 활용할 수 있어야 합니다.

 

랭체인에서는 체인 기능을 활용할 수 있도록 두 가지 방법을 제공합니다. 하나는 전통적인 'Chain' 인터페이스를 사용하는 것이고 다른 하나는 LCEL(LangChain Expression Lauguage)입니다. LCEL은 기존의 Chain에서 업데이트된 기능으로 공식 문서에서 권장하는 방법입니다. LCEL 사용을 권장하는 대표적인 이유는 아래와 같습니다.

 

  • 스트리밍 지원
  • 비동기 지원
  • 최적화된 병렬 실행
  • 재시도 및 대처 방법
  • 중간 결과 접근
  • 입력 및 출력 스키마

 

위 기능 외에도 직관적인 Syntax를 사용(파이프 |)하기 때문에 기능 구현이 간편하고 가독성이 좋은 것 같습니다. LCEL에 대한 상세 내용이 궁금하실 경우, LangChain 공식 문서의 LangChain Expression Language 부분을 참고하시면 좋을 것 같습니다. 오늘 포스팅의 예제도 LCEL 인터페이스를 활용해서 구현할 예정입니다. 이제 예제를 통해 체인 기능을 확인해 볼까요?

 

간단한 LCEL 예제

이번 예제에서는 OpenAI 언어 모델을 사용할 예정입니다. 따라서, OpenAI API를 활용하기 위해 API 키가 필요합니다. 이번 오픈AI DevDay때, 신규로 업데이트된 "gpt-4-1106-preview" 모델을 사용해 보도록 하겠습니다. 아래와 같이 언어 모델을 생성합니다. 저는 API 키를 .env 파일에서 관리하고 있기 때문에 dotenv_values() 함수를 통해 키 값을 호출했습니다. 예제 구현을 위해 직접 키 값을 입력하셔도 무방합니다.

 

 

from dotenv import dotenv_values

from langchain.chat_models import ChatOpenAI
from langchain.prompts import ChatPromptTemplate

openai_key = dotenv_values(".env").get("OPENAI_API_KEY")
chat_model = ChatOpenAI(
  api_key=openai_key,
  temperature=0.9,
  model="gpt-4-1106-preview")

 

 

위와 같이 언어 모델을 생성한 후, 언어 모델에게 전달할 프롬프트의 템플릿을 생성해 보도록 하겠습니다. 프롬프트 템플릿은 말 그대로 프롬프트를 생성하기 위해 사전에 정의된 템플릿입니다. 템플릿에는 특정 지시 사항이나 샘플 예시, 주어진 작업에 대한 특정 맥락 등을 정의할 수 있습니다. 템플릿을 사용한다면 정형화된 프롬프트를 생성하고 재사용할 수 있습니다. 아래와 같이 프롬프트 템플릿을 생성해 보도록 하겠습니다.

 

 

keyword_template = ChatPromptTemplate.from_messages([
  ("system", "You are a keyword master.\
    You can select a best keyword for {topic} using only a single word."),
  ("human", "I want to create a SEO optimized a keyword for {topic}"),
])

 

 

제가 생성한 프롬프트 템플릿에서 system의 역할을 부여하고, human의 요청사항을 전달했습니다. 위 코드에서 볼 수 있듯 이후 {topic}에 대한 정보만 전달해 주면 그에 맞는 프롬프트를 생성합니다. 저는 제가 전달한 'topic'에 대해 키워드를 생성하는 역할을 부여하고, SEO(Search Engine Optimization) 최적화된 키워드를 요청했습니다.

 

이제, 프롬프트 템플릿과 언어 모델을 하나로 엮기 위해 체인을 사용해 보도록 하겠습니다. 체인을 사용하는 방법은 아주 간단합니다. 템플릿과 언어 모델 사이에 파이프(|) 하나만 작성하면 체인으로 연결됩니다. 아래 코드의 의미를 설명드리면 keyword_template에서 생성된 PromptValue가 파이프 오른쪽 chat_model에게 전달되는 것입니다.

 

 

keyword_chain = keyword_template | chat_model
keyword_chain.invoke({"topic":"how can we be python experts"})

 

 

아래의 그림을 보시면 이해하기 수월할 것입니다. 아래와 같이 invoke에서 전달된 topic이 딕셔너리 형태로 템플릿에 전달되고 템플릿에 전달된 topic을 통해 프롬프트가 생성됩니다. 생성된 프롬프트는 파이프로 연결된 언어 모델에 전달되는 것입니다. LCEL을 통해 체인으로 연결될 수 있는 인터페이스는 아래의 표를 참고해 주세요.

 

 

LCEL 인터페이스

 

이제 체인을 invoke 해서 생성된 결과를 확인해 볼까요? 아래와 같은 결과를 응답받았습니다. "how can we be python experts"에 대한 주제를 한 가지 키워드로 요약하면 "PythonMastery"라고 하네요. 이제 이와 같은 체인을 여러 개 생성해서 체인으로 다시 엮는 작업을 수행해 보겠습니다.

 

 

AIMessage(content='"PythonMastery"')

 

 

자동화 블로그 글 예제

위의 간단한 예제에서 체인을 하나 만들어보았으니 본격적으로 체인을 여러 개 생성하고 통합하는 작업을 진행해 보겠습니다. 오늘 진행할 예제의 전체 구조는 아래와 같습니다. 키워드를 생성하는 체인, 대상 독자의 연령대를 찾는 체인, 포스팅을 수행하는 체인 세 가지를 다시 체인으로 엮어 블로그 글을 생성해 보도록 하겠습니다.

 

Keyword Chain

 

keyword_template = ChatPromptTemplate.from_messages([
  ("system", "You are a keyword master.\
    You can select a best keyword for {topic} using only a single word."),
  ("human", "I want to create a SEO optimized a keyword for {topic}"),
])
keyword_chain = keyword_template | chat_model
# keyword_chain.invoke({"topic":topic}) 	# Invoke는 최종 체인에서 수행합니다.

 

 

Age Chain

 

age_template = ChatPromptTemplate.from_messages([
  ("system", "You are a marketing master.\
    You can select t the optimal age group for {topic} using only a single word."),
  ("human", "I want to select the best age group for {topic} using only a single word."),
])
age_chain = age_template | chat_model
# age_chain.invoke({"topic":topic}) 	# Invoke는 최종 체인에서 수행합니다.

 

 

Posting Chain

 

posting_template = ChatPromptTemplate.from_messages([
  ("system", "You are a blog post master.\
    you can create a SEO optimized blog post with a keyword."),
  ("human", "I want to create a SEO optimized blog post for {keyword}.\
    And SEO optimized to {age_group} \
    And you should create a blog post over 1000 words."),
])
blog_post_chain = posting_template | chat_model

 

 

최종 체인 구성 후 Invoke 하기

아래와 같이 최종 체인을 구성했습니다. keyword는 keyword_chain을 통해 생성한 결과를 age_group은 age_chain을 통해 생성한 결과를 딕셔너리 형태로 구성합니다. 이후, 입력인 topic을 입력하여 체인을 invoke 합니다.

 

 

chain = {"keyword": keyword_chain, "age_group": age_chain} | posting_chain
response = chain.invoke({"topic": "how can we be python experts"})

 

 

생성된 결과에서 '\n', '\t'가 '\\n', '\\t'로 생성되어 아래와 같이 제대로 인식되도록 대체해 줍니다.

 

 

result = response.content.replace('\\n', '\n').replace('\\t', '\t')

 

 

생성된 최종 결과는 아래와 같습니다. 젊은(Youth) 사람들을 대상으로 한 'PythonMastary'에 대한 글이 생성되었고 내용 또한 흥미롭습니다.

 

 

마치며

오늘은 랭체인의 체인 기능을 활용해서 블로그를 자동으로 생성하는 프로그램을 작성했습니다. OpenAI 모델을 활용해서 여러 역할을 수행하는 체인을 구성했고, 구성한 체인을 하나로 통합해서 최종적인 결과물을 도출해 냈습니다. 오늘 예제에서는 간단하게 보여드리기 위해 키워드 추출, 대상 독자 그룹 추출, 포스팅 생성하는 기능으로 분류했지만 API를 활용해서 수집된 데이터를 결합하거나 랭체인의 다른 컴포넌트를 결합한다면 더 큰 효과를 얻을 수 있을 것입니다.

 

OpenAI DevDay 이후, 랭체인에 위기가 오고 있다는 글을 자주 접할 수 있었습니다. 하지만, 랭체인의 기능을 오히려 제대로 활용한다면 새로 출시된 ChatGPT 기능의 효과를 훨씬 증가시켜 줄 것이라고 생각됩니다. 오늘도 많은 도움이 되셨기를 바라면서 포스팅 마치겠습니다. 고맙습니다.

반응형