5분만에 챗봇 만들고 호스팅까지 (Gradio, LangChain)

정기용·2023년 8월 9일
10

Good Posting

목록 보기
1/1
post-thumbnail

그라디오(Gradio)
그라디오(Gradio)는 인공지능 서비스의 UI를 프로토타입으로 간편히 제작하기 좋은 프레임워크다. 현재 버전 3.39.0까지 릴리즈되었고 파이썬과 자바스크립트를 지원한다. 허깅페이스(Hugging Face) 플랫폼으로 독자적인 생태계를 구축하여 앞으로도 꾸준히 성장할 것으로 기대된다.

랭체인(LangChain)
랭체인(LangChain)은 언어 모델을 간편하게 개발하기 좋은 프레임워크다. 현재 버전 0.0.256까지 릴리즈되어 비교적 신생이지만, 한 달에 400만 이상의 사람이 다운받는 등 관심도와 참여도로 보아 무섭게 성장할 것으로 보인다. 여러 종류의 언어 모델은 각기 다른 입출력 형식과 자잘한 차이점들을 가지고 있다. 서로 다른 모델을 모듈화하여 레고 조립하듯이 언어 모델 서비스를 개발할 수 있다.

그라디오와 랭체인을 활용한 챗봇 서비스 개발
이 글에서는 그라디오와 랭체인을 활용하여 기초적인 챗봇 서비스를 개발하는 과정을 다룬다. 그라디오로 UI(User Interface)를 구현하고, 랭체인으로 간단한 챗봇을 개발하여 그라디오에 연결시킨다.

1. 그라디오의 기본 구조

그라디오는 블록을 쌓듯이 UI를 구현할 수 있는 프레임워크다. React.js에서 컴포넌트를 만들어 구조화하듯이 그라디오에서 제공하는 컴포넌트를 쌓고 함수를 연결하여 사용한다. 그라디오를 사용하기 위해 다음 명령어를 명령 프롬프트(cmd)에 입력한다.

pip install gradio

아래 표는 자주 사용하는 그라디오 컴포넌트에 대한 설명이다. 이를 참고하여 아래 그라디오의 기본 기능이 들어간 예제 코드를 살펴보자.

컴포넌트 이름 설명
Blocks() 인터페이스를 정의한다. 블록을 쌓을 기반이다.
Row() 내부 블록들을 가로로 쌓는다.
Column() 내부 블록들을 세로로 쌓는다.
Markdown() 파라미터에 문자열을 넣으면 마크다운 문법에 따라 인터페이스에 추가된다.
Textbox() HTML의 input(type=“text”)에 해당한다. 인터페이스에 입력 칸을 추가한다.
Button() HTML의 button에 해당한다. 인터페이스에 버튼을 추가한다.
Chatbot() 인터페이스에 채팅 화면을 추가한다.
State() 그라디오에서 사용할 변수를 추가한다. 그라디오 객체 형태로 만든다.
queue() 그라디오에서 사용할 명령어 큐를 정의한다. 큐의 작업은 순차적(동기)으로 실행된다.
launch() 인터페이스를 로컬(127.0.0.1)에서 호스팅한다. 파라미터에 ‘share=True’로 설정하면 일정 기간동안 월드와이드웹으로 호스팅해준다.

# gradio library를 가져온다. gr로 줄여서 칭한다.
import gradio as gr

# gradio 내부에서 사용할 함수다.
def update(name): 
    return f"Welcome to Gradio, {name}!"

with gr.Blocks() as iface:
    gr.Markdown("Hello, World! I’m yelling in gradio!")
    with gr.Row():
        inp = gr.Textbox(placeholder="이름이 무엇인가요?")
        out = gr.Textbox()
    btn = gr.Button("제출")

    # 버튼에 이벤트 리스너를 추가한다. 
    # 버튼 클릭시 update함수를 호출하고, inp에 입력된 문자열을 파라미터로 보낸다. 함수의 반환값은 out에 출력한다.
    btn.click(fn=update, inputs=inp, outputs=out)

iface.launch()

Fig 1. 예제 출력 화면
위 코드를 실행시키고 웹 브라우저(Chrome)로 접속한 화면이다.

Fig 2. 예제 Input 입력 결과

Input(왼쪽 텍스트박스)에 이름을 입력한 결과다. Input 입력 후 버튼 클릭시 update 함수를 호출하고, Input에 입력된 문자열을 파라미터로 보낸다. 함수의 반환값은 Output(오른쪽 텍스트박스)에 출력한다.

Fig 3. 그라디오 화면 구성 (블록 쌓기)

그라디오는 UI를 만들 때 블록을 쌓듯 컴포넌트를 세로로 차곡차곡 쌓는다. Fig3은 예제 코드의 컴포넌트가 어떻게 쌓여있는지 이미지로 보여준다.

2. 그라디오로 챗봇 UI 만들기

그라디오의 옛 버전에서는 Blocks 객체 내에서 여러 블록을 쌓고, 이벤트리스너(Event Listener)를 추가하여 챗봇을 구현하였다. 하지만 업데이트된 그라디오 3.39.0버전에서는 챗봇의 기능이 대부분 담긴 ChatInterface 컴포넌트가 생겼다. ChatInterface 컴포넌트 안에 챗봇UI, 입력, 버튼, 추가 옵션들을 모두 파라미터로 설정할 수 있다.

ChatInterface 옵션설명
fn챗봇에게 말을 걸면 호출되는 함수입니다.
chatbot챗봇 채팅 화면에 대해 정의합니다.
textbox챗봇 채팅 입력칸을 정의합니다.
title챗봇 제목을 정의합니다.
description챗봇 설명을 정의합니다. 제목 밑에 작성합니다.
theme챗봇 디자인 테마를 결정합니다.
examples챗봇에게 물어볼 수 있는 예시 질문을 정의합니다.
retry_btn가장 최근 물어본 질문을 다시 물어봅니다.
undo_btn가장 최근 물어본 질문을 삭제합니다.
clear_btn채팅 기록을 전부 삭제합니다.
additional_inputs추가 블록을 정의합니다. fn에 추가 블록의 정보를 손쉽게 보낼 수 있습니다.

# 챗봇에 채팅이 입력되면 이 함수를 호출합니다. 
# message는 유저의 채팅 메시지, history는 채팅 기록, additional_input_info는 additional_inputs안 블록의 정보를 받습니다.
def response(message, history, additional_input_info):
    # additional_input_info의 텍스트를 챗봇의 대답 뒤에 추가합니다.
    return "챗봇을 미완성하였습니다 " + additional_input_info

gr.ChatInterface(
        fn=response,
        textbox=gr.Textbox(placeholder="말걸어주세요..", container=False, scale=7),
        title="어떤 챗봇을 원하심미까?",
        description="물어보면 답하는 챗봇임미다.",
        theme="soft",
        examples=[["안뇽"], ["요즘 덥다 ㅠㅠ"], ["점심메뉴 추천바람, 짜장 짬뽕 택 1"]],
        retry_btn="다시보내기 ↩",
        undo_btn="이전챗 삭제 ❌",
        clear_btn="전챗 삭제 💫",
        additional_inputs=[
            gr.Textbox("!!!", label="끝말잇기")
        ]
).launch()

Fig 4. ChatInterface로 만든 챗봇 화면

ChatInterface로 만든 챗봇 화면이다. 원하는 값만 넣었는데 결과가 꽤 멋있다!

3. 랭체인(LangChain)으로 챗봇 함수 만들기

그라디오로 유저와 상호작용할 수 있는 UI를 만들었다. 랭체인은 유저에게서 받은 메시지를 가공할 함수를 만드는 언어모델 프레임워크다. 랭체인을 활용해 OpenAI의 GPT-3.5모델을 연결하여 답변을 생성한 후 반환하는 함수를 만들어보자. 랭체인은 언어 생성 모델과 임베딩 모델을 패키징해줘 쉽게 import해 쓸 수 있다.
랭체인을 다운받기 위해 아래 커맨드를 명령 프롬프트(cmd)에 입력한다.

pip install langchain

아래는 그라디오 예제의 response함수를 랭체인을 활용해 OpenAI의 GPT-3.5모델을 연결한 코드다.


from langchain.chat_models import ChatOpenAI
from langchain.schema import AIMessage, HumanMessage
import os

# os의 환경변수로 OPENAI_API_KEY를 설정한다. “...”에 api key를 입력해야 동작한다.
os.envrion["OPENAI_API_KEY"] = "..."  

# langchain의 GPT-3.5 모델을 가져온다.
# temperature는 챗봇 대답의 자유도를 의미한다.
llm = ChatOpenAI(temperature=1.0, model='gpt-3.5-turbo-0613')

# 그라디오에서 유저의 질문과 채팅기록을 받아 llm의 input형식에 맞게 변환 및 입력 후 GPT-3.5의 대답을 리턴한다.
def response(message, history, additional_input_info):
        history_langchain_format = []
        for human, ai in history:
                history_langchain_format.append(HumanMessage(content=human))
                history_langchain_format.append(AIMessage(content=ai))
        history_langchain_format.append(HumanMessage(content=message))
        gpt_response = llm(history_langchain_format)
        return gpt_response.content

랭체인과 그라디오를 활용한 챗봇 만들기
위에서 살펴본 랭체인과 그라디오를 합친 전체 코드다. additional_input에서 시스템 프롬프트를 입력받아 langchain에게 전달하는 기능을 추가했다.

최종! 랭체인과 그라디오를 활용한 챗봇 만들기


from langchain.chat_models import ChatOpenAI
from langchain.schema import AIMessage, HumanMessage, SystemMessage
import gradio as gr
import os

os.envrion["OPENAI_API_KEY"] = "..." 

llm = ChatOpenAI(temperature=1.0, model='gpt-3.5-turbo-0613')

def response(message, history, additional_input_info):
        history_langchain_format = []
        # additional_input_info로 받은 시스템 프롬프트를 랭체인에게 전달할 메시지에 포함시킨다.
        history_langchain_format.append(SystemMessage(content= additional_input_info))
        for human, ai in history:
                history_langchain_format.append(HumanMessage(content=human))
                history_langchain_format.append(AIMessage(content=ai))
        history_langchain_format.append(HumanMessage(content=message))
        gpt_response = llm(history_langchain_format)
        return gpt_response.content

gr.ChatInterface(
        fn=response,
        textbox=gr.Textbox(placeholder="말걸어주세요..", container=False, scale=7),
        # 채팅창의 크기를 조절한다.
        chatbot=gr.Chatbot(height=1000),
        title="어떤 챗봇을 원하심미까?",
        description="물어보면 답하는 챗봇임미다.",
        theme="soft",
        examples=[["안뇽"], ["요즘 덥다 ㅠㅠ"], ["점심메뉴 추천바람, 짜장 짬뽕 택 1"]],
        retry_btn="다시보내기 ↩",
        undo_btn="이전챗 삭제 ❌",
        clear_btn="전챗 삭제 💫",
        additional_inputs=[
            gr.Textbox("", label="System Prompt를 입력해주세요", placeholder="I'm lovely chatbot.")
        ]
).launch()

Fig 5. 최종 챗봇 UI, 채팅 결과

꽤 괜찮다

정리하며

챗봇 프로토타입 개발 과정을 살펴보았다. 이를 응용하여 다양한 챗봇을 만들 수 있을 것이다. 그라디오와 랭체인은 메인 인공지능 설계를 제외한 작업을 간단히 만들어준다. 그러면 인공지능 설계에 들일 시간과 노력을 확보할 수 있다. Fig5의 짜장면과 짬뽕 질문에 챗봇이 두툼한 카라멜이라는 엉뚱한 대답을 내놓은 것처럼, UI와 기능을 간결하게 만들어도 핵심은 인공지능의 성능이다. 프레임워크를 활용해 인공지능을 연구할 시간을 확보할 수 있다.

참고 문헌
LangChain. LangChain Docs. 2023.08.09 검색, https://python.langchain.com/docs
Gradio. Gradio Docs. 2023.08.09 검색, https://www.gradio.app/docs

profile
SKKU CS 23

1개의 댓글

comment-user-thumbnail
2023년 9월 8일

글 잘 봤습니다!

답글 달기