TOP
class="layout-aside-left paging-number">
본문 바로가기
[파이썬 Projects]/<파이썬 Gen AI>

[Gen AI] 랭체인을 활용한 챗봇 업그레이드 - 1

by 기록자_Recordian 2024. 12. 13.
728x90
반응형
이전 내용
 

[Gen AI] 그라디오로 제작한 챗봇 허깅 페이스에 업로드하기

이전 내용 [Gen AI] 그라디오로 챗봇 제작하기 - 3 (소설봇)이전 내용 [Gen AI] 그라디오로 챗봇 제작하기 - 1 (상담봇)이전 내용 [Gen AI] 그라디오(Gradio)이전 내용 [Gen AI] OpenAI API 사용해보기 (로컬,

puppy-foot-it.tistory.com


랭체인(LangChain) 이란?
출처: 위키백과

 

랭체인(LangChain)은 LLM(대형 언어 모델)을 사용하여 애플리케이션 생성을 단순화하도록 설계된 프레임워크이다. 언어 모델 통합 프레임워크로서 랭체인의 사용 사례는 문서 분석 및 요약, 챗봇, 코드 분석을 포함하여 일반적인 언어 모델의 사용 사례와 크게 겹친다.

 

LangChain

LangChain’s suite of products supports developers along each step of their development journey.

www.langchain.com

 

랭체인은 LLM과 외부의 도구(웹 사이트, PDF reader, 계산기 등)를 체인으로 엮은 것처럼 결합해 주는 SDK(Software Develepmont Kit)의 한 종류다. 랭체인의 등장은 챗GPT의 등장 시기와 비슷하며, 챗GPT가 생겨난 후 수많은 LLM이 생겨나고 이 LLM을 활용한 애플리케이션을 만드는 데 랭체인의 역할이 중요해지게 되었다.

 

[LLM] 거대 언어 모델이란? (feat. GPU, NVIDIA)

챗gpt와 엔비디아 등으로 요새 LLM 이라는 단어가 주목받고 있다.그렇다면 LLM 이란 무엇인가?LLM 이란? LLM (Large Language Model)은 '거대 언어 모델' 로써, 대용량 인간 언어를 이해하고 생성할 수 

puppy-foot-it.tistory.com

 

[랭체인의 주요 기능]

랭체인을 사용하여 생성형 AI를 활용하는 여러 가지 애플리케이션을 만들 수 있는데, 주로 챗봇 등을 개발할 때 문서 또는 정형화된 데이터를 사용하여 대화를 요약 및 분석하거나 생성할 수 있다. 물론 랭체인을 사용하지 않고도 LLM 만을 이용하여 서비스를 생성할 수도 있으나, 랭체인 활용 시 애플리케이션을 효율적이고 간편하하게 개발할 수 있다는 이점이 있다.

 

랭체인의 핵심 기능 중 하나는 LLM을 활용한 대화형 애플리케이션 제작 시 이전에 입력되거나 출력된 대화를 기억해 일관성 있는 대화를 하게 도와줄 수 있다는 것이며, 이를 활용해 챗GPT나 LLama2 등의 모델과 결합 후 완성도 높은 AI 애플리케이션을 만들 수 있다.


랭체인 설치와 환경 설정 (아나콘다 프롬프트)

 

필자의 경우, 이전에 아나콘다 프롬프트에서 생성한 가상환경에 랭체인 패키지를 설치했다.

pip install langchain

 

※ 추가! 랭체인 커뮤니티도 설치해 준다.

pip install langchain_community

만약, OpenAI 패키지가 설치되어 있지 않다면, OpenAI 패키지도 설치해야 한다.

pip install openai

 

설치가 완료된 후 OpenAI API 키를 사용하기 위해 주피터 노트북에 환경 설정을 한다.

import os
from openai import OpenAI

# OpenAI 클라이언트 설정
client = OpenAI(
    api_key=os.environ['OPENAI_API_KEY'])

모델 I/O

 

모델 I/O 모듈은 랭체인에서 LLM과 상호 작용하는 데 사용하며, 프롬프트를 생성한 후 모델 API를 호출하고 모델이 추론한 결과를 효율적으로 출력하는 역할을 한다.

  • Prompts: 모델에 입력을 템플릿화하고 동적으로 선택하고 관리
  • Chat models: 언어 모델의 지원을 받지만, 채팅 메시지 목록을 입력으로 사용하고 채팅 메시지를 반환하는 모델
  • LLMs: 텍스트 문자열을 입력으로 사용하고 텍스트 문자열을 반환하는 모델
  • Output parsers: 모델 출력에서 정보 추출

1. LLMs

랭체인에서는 언어 모델을 두 가지로 구분한다.

  • LLMs: 문자를 입력받아 문자를 아웃풋으로 리턴하는 언어 모델
  • ChatModels: 메시지의 리스트를 인풋으로 받아 메시지를 리턴하는 언어 모델

◆ OpenAI LLMs 연결하기

여기서는 대화 기반으로 답변을 받는 것이 아닌, 일반적으로 질문 답변을 하는 OpenAI 모델 (gpt-3.5-turbo-instruct)을 랭체인을 통해 연결해 본다.

from langchain.llms import OpenAI

llm=OpenAI(model_name='gpt-3.5-turbo-instruct')
llm.predict('미국의 제1대 대통령은?')

※ LangChain 라이브러리에서는 BaseLLM.predict 메서드가 더 이상 권장되지 않으며, 대신 invoke 메서드를 사용해야 한다는 경고 메시지가 표시된다. 해당 경고 메시지에 맞춰 코드를 수정한 뒤 다시 실행해보면

from langchain.llms import OpenAI

llm=OpenAI(model_name='gpt-3.5-turbo-instruct')
llm.invoke('미국의 제1대 대통령은?')

▶ 좀 더 상세하게 나온다.

 

이번에는 temperature 매개변수를 통해 답변의 무작위성을 설정해 보는데, 이 값에는 0~1 사이의 값을 넣을 수 있으며, 1로 설정할수록 답변의 무작위성이 높아진다.

from langchain.llms import OpenAI

llm=OpenAI(model_name='gpt-3.5-turbo-instruct', temperature=1)
llm.invoke('미국의 제1대 대통령은?')

 

답변 결과가 길 경우 기다리는 시간이 길어지는데, StreamingStdOutCallbackHandler 를 사용하면 실시간으로 타이핑하듯이 답변이 나온다.

from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler

llm=OpenAI(model_name='gpt-3.5-turbo-instruct', streaming=True,
           callbacks=[StreamingStdOutCallbackHandler()], temperature=0)
llm.invoke('서울에서 가장 유명한 K-POP 가수는?')

 

◆ 챗GPT Chatmodel 연결하기

OpenAI의 핵심은 채팅하듯이 답변해 주는 챗GPT 모델이다. 랭체인에서도 챗GPT와 연결하여 사용할 수 있으며, 챗GPT와 연결 시 모델에 역할을 부여하는 등의 기능도 넣을 수 있다. 랭체인에는 Chat 기능을 위한 스키마(Schema)를 사용하는데, 기능은 다음과 같다.

  • SystemMessage: 챗GPT에게 해야 할 역할 설정
  • HumanMessage: 유저가 챗GPT에게 입력한 채팅
  • AIMessage: 챗GPT가 응답한 채팅
from langchain.chat_models import ChatOpenAI
from langchain.schema import AIMessage, HumanMessage, SystemMessage

chatgpt = ChatOpenAI(model_name='gpt-3.5-turbo')

messages = [
    SystemMessage(
        content="당신은 파이썬 프로그래머입니다."
    ),
    HumanMessage(
        content="파이썬에서 for 반복문의 역할은?"
    ),
]

result=chatgpt(messages)
print(result.content)

▶ 스키마 사용 시 메시지의 내용은 content 매개변수에 넣어 사용하며, 결괏값은 result.content에 저장된다.


2. 프롬프트 템플릿

LLM을 사용할 때 모델의 입력으로 사용되는 프롬프트를 생성하는 것은 매우 중요한 일이다.

예를 들어 "DUDE (필자가 예전에 운영했던 남성 쇼핑몰 - 지금은 없다.)"의 챗봇을 만들 때 " XXXX 제품이 몇 페이지에 있는 지 알려줘, 답변은 몇 페이지에 몇 번째에 있습니다로 해 주세요" 라는 프롬프트를 만들 때 앞에 XXXX 부분의 내용만 바뀌고 뒤에는 항상 같은 프롬프트로 입력해야 한다.

랭체인에서는 이러한 프롬프트를 생성하는 기능을 제공하고 있는데, 이러한 기능을 사용하면 챗GPT가 쓸데없이 긴 답변을 해 주는 것을 방지할 수 있다.

프롬프트 템플릿은 다음의 두 가지 템플릿을 제공한다.

  • Prompt Template: 일반 LLM에 사용
  • Chat Promprt Template: Chat LLM에 사용

◆ 프롬프트 템플릿 만들기

프롬프트 템플릿은 프롬프트를 생성할 때 중괄호({ })를 이용하여 매개변수를 생성할 수 있다.

from langchain.prompts import PromptTemplate

llm_prompt = PromptTemplate.from_template("{goods}의 소재에 대해 알려줘")
llm_prompt_result=llm_prompt.format_prompt(goods="무스탕 자켓")

print(llm_prompt_result)

llm_prompt_result.text를 출력하면 문자로 출력되며, 이렇게 만든 프롬프트는 llm에 chain으로 연결해 사용한다.

 

◆ Chat Prompt Template

Chat Prompt Template는 Chat LLM 모델에 사용되는 SystemMessage, HumanMessage 등에 입력하는 프롬프트를 생성하는 데 사용된다.

from langchain.prompts import ChatPromptTemplate, SystemMessagePromptTemplate, HumanMessagePromptTemplate

system_message = "당신은 {language} 선생님입니다. {language}로 대답해 주세요."

system_prompt = SystemMessagePromptTemplate.from_template(system_message)
human_template = "{text}"
human_prompt = HumanMessagePromptTemplate.from_template(human_template)

chat_prompt = ChatPromptTemplate.from_messages([system_prompt, human_prompt])

chat_prompt.format_messages(language="스페인어", text="대한민국의 보물1호는?")

 

◆ OpenAI 모델에 연결하기

먼저 프롬프트 템플릿을 통해 생성된 템플릿을 OpenAI에 적용해 본다.

기존에 책에 쓰여있던 코드는 오류가 발생하므로, 새로운 코드로 작성한다. (이거 해결하느라 시간 엄청 걸렸다.)

* 기존 코드 (오류 발생)
from langchain.prompts import PromptTemplate, ChatPromptTemplate
from langchain.llms import OpenAI

llm=OpenAI(model_name='gpt-3.5-turbo', temperature=0)

llm_prompt = PromptTemplate.from_template("{goods}의 소재에 대해 알려줘")
llm_prompt_result = llm_prompt.format_prompt(goods = "무스탕 자켓") llm.predict_messages(llm_prompt_result.to_messages())
from langchain.prompts import PromptTemplate
from langchain_community.chat_models import ChatOpenAI
from langchain.chains import LLMChain

# ChatOpenAI 모델 인스턴스 생성 (최신 모델 사용)
llm = ChatOpenAI(model_name='gpt-3.5-turbo', temperature=0)

# 프롬프트 템플릿 생성
prompt_template = PromptTemplate(template="{goods}의 소재에 대해 알려줘")

# LLM과 프롬프트 템플릿을 연결하는 체인 생성
chain = LLMChain(llm=llm, prompt=prompt_template)

# 실행할 데이터 설정
goods = "무스탕 자켓"

# 체인 실행 및 결과 출력
result = chain.run(goods=goods)
print(result)

[주요 변경 사항 설명]
1) ChatOpenAI 클래스 사용:
from langchain_community.chat_models import ChatOpenAI을 통해 ChatOpenAI 클래스를 import하고 사용.

 

2)PromptTemplate 초기화:
template 매개변수를 사용하여 PromptTemplate 객체 생성.

 

3) LLMChain 초기화 및 실행:
LLMChain 객체를 생성하고 run 메서드를 사용하여 결과 출력.

 

다음으로는 앞서 만든 Chat Prompt Template를 OpenAI ChatGPT에 적용해 본다.

from langchain_community.chat_models import ChatOpenAI
from langchain.prompts import (
    ChatPromptTemplate,
    SystemMessagePromptTemplate,
    HumanMessagePromptTemplate
)

chatgpt = ChatOpenAI(model_name='gpt-3.5-turbo', temperature=0)

system_message = "당신은 {language} 선생님입니다. {language}로 대답해 주세요."
system_prompt = SystemMessagePromptTemplate.from_template(system_message)
human_template = "{text}"
human_prompt = HumanMessagePromptTemplate.from_template(human_template)

chat_prompt = ChatPromptTemplate.from_messages([system_prompt, human_prompt])

message = chat_prompt.format_messages(language="스페인어", text="대한민국의 보물1호는?")

response = chatgpt.invoke(message)
print(response.content)

스페인어로 요청했으나, 스페인어 출력이 안되어

영어로 수정하여 다시 요청하였다.

 

◆ 퓨샷(Few Shot)

퓨샷은 언어 모델을 사용하여 결괏값을 추론할 때 추론된 결괏값을 원하는 형태로 나타나게 하는 것을 의미한다.

퓨샷을 사용하기 위해서는 예시가 되는 프롬프트를 먼저 생성해야 한다.

from langchain.prompts.few_shot import FewShotPromptTemplate
from langchain.prompts.prompt import PromptTemplate
from langchain.llms import OpenAI

ex_qa = [
    {
        "question": "차은우에 대해 알려줘",
        "answer": "나이: 29, 키: 183, 사는 곳: 대한민국"
    },
    {
        "question": "데이비드 베컴에 대해 알려줘",
        "answer": "나이: 45, 키: 178, 사는 곳: 영국"
    }
]

ex_prompt=PromptTemplate(input_variables=["question", "answer"],
                         template="Question: {question}\n{answer}")

 

위에서 만든 ex_prompt를 이용하여 FewShotPromptTemplate를 만든다.

prompt=FewShotPromptTemplate(
    examples=ex_qa,
    example_prompt=ex_prompt,
    suffix="Question: {input}",
    input_variables=["input"]
)

llm = ChatOpenAI(model_name='gpt-3.5-turbo', temperature=0)

prompt_result=prompt.format(input="크리스티아누 호날두에 대해 알려줘")
response = llm.invoke(prompt_result)

print(response.content)

 

◆ 아웃풋 파서(Output Parser)

아웃풋 파서는 출력 형태를 지정한 형태로 출력할 수 있도록 해 주며, 핵심 기능은 아래와 같다.

  • Format instructions: 원하는 출력 형태를 LLM에 전달
  • Parser: 결괏값을 원하는 지정 형태로 추출

파서의 종류

  • List Parser: 콤마(,)로 구분된 항목 목록 반환
  • Date Time Parser: 출력을 Datetime 형식으로 반환
  • Enum Parser: 열거형 형태로 반환
  • AutoFixing Parser: 첫 출력 구문 분석기가 실패할 경우 다른 LLM을 호출하여 오류 수정
  • Pydantic(JSON) Parser: 임의의 JSON 스키마를 만들고 스키마를 준수하는 JSON 출력에 대해 LLM을 쿼리
  • Retry Parser: 원래의 프롬프트와 함께 이를 LLM에 다시 제출하여 보다 적절한 응답 생성
  • Structured output Parser: 여러 필드를 반환하려는 경우에 사용
  • XML Parser: XML 형식으로 결과 반환

이 중 List Parser를 사용하여 결괏값을 출력해 본다.

from langchain.output_parsers import CommaSeparatedListOutputParser
from langchain.prompts import PromptTemplate
from langchain.llms import OpenAI

output_parser = CommaSeparatedListOutputParser()

format_instructions = output_parser.get_format_instructions()

prompt = PromptTemplate(
    template="{subject} 5개를 추천해줘.\n{format_instructions}",
    input_variables=["subject"],
    partial_variables={"format_instructions": format_instructions}
)

llm=OpenAI(temperature=0)

prompt_result = prompt.format(subject="겨울외투")
output = llm.invoke(prompt_result)
print(output)

이를 output_parser를 사용하여 파싱해 본다.

output_parser.parse(output)

▶ 리스트 안에 콤마로 구분된 결과를 확인할 수 있다.


다음 내용

 

[Gen AI] 랭체인을 활용한 챗봇 업그레이드 - 2

이전 내용 [Gen AI] 랭체인을 활용한 챗봇 업그레이드 - 1이전 내용 [Gen AI] 그라디오로 제작한 챗봇 허깅 페이스에 업로드하기이전 내용 [Gen AI] 그라디오로 챗봇 제작하기 - 3 (소설봇)이전 내용 [

puppy-foot-it.tistory.com


[출처]

Hey, 파이썬! 생성형 AI 활용 앱 만들어줘

위키백과

랭체인 공식 홈페이지

https://brunch.co.kr/@topasvga/3902

728x90
반응형