세미나 후기

[NCTM] 퇴근길 밋업 2회차 - Streamlit & HCX 활용기

graph-dev 2024. 5. 1. 12:38
728x90

네이버클라우드 퇴근길 테크밋업(NCTM) 후기

 

4월에도 기대하게 만드는 퇴근길 테크밋업, 그 후기를 남겨보았습니다.

 

NCTM 퇴근길 테크밋업 홍보 배너

 

 

1시간 안에 생성형 AI 챗봇 구현하기

아래와 같이 총 세가지 세션으로 진행되었습니다. 

  • 네이버 하이퍼클로바X 이야기
  • 하이퍼클로바X API로 챗봇 서비스 구현하기[핸즈온, 실습 포함]
  • 직무별/관심사별 네트워킹

 

핸즈온(실습) 과정이 있어서, 네이버클라우드 사용을 위해 크레딧도 제공해주셨습니다. 5만원 상당으로, 충분히 실습해볼 수 있다고 합니다!

 

크레딧 제공 화면

 

네이버 하이퍼클로바X 이야기

네이버 HCX 이야기는 하이퍼클로바 X의 역사와 함께, 다양한 생성형 AI 서비스들과 경쟁하며 HCX의 우수한 점을 요약하여 전달해주셨습니다. 그 외에도 앞으로의 개발 방향성을 함께 공유해주셔서 한눈에 알아보기 좋았습니다.

 

생성형 AI의 경제적 효과

- 이 분야가 성장 가능성이 높습니다.

아직 공개하지 않은 다양한 형태의 멀티모달 모델을 공개할 예정입니다.

이미지, 오디오, 비디오 등 특화된 모델이 많습니다.

 

초거대 AI

- 모든 산업, 사회 분야의 자동화에 따른 생산성 혁신을 가져올 것이고, 산업에서 프로세스의 파괴적인 혁신을 기대합니다.

- 외부 앱, 플랫폼 생태계, 개인 비서도 제공합니다.

- 아이디어 컨텐츠를 제작합니다.

- 클라우드 기반의 초거대 생성 AI를 만들 수 있습니다. 특히 한국어 특화된 LLM이 HCX의 강점인 것으로 보입니다.

 

511 토큰

 

HCX DASH 모델 출시

가볍고 빠른 DASH 모델, 한번 써보러 가야겠습니다.

 

 

 

 

Advanced 튜닝: 특화 모델 개발을 위한 기능

AI 기업만 아니라 누구나 "돈"만 충분하면 쓸 수 있다! 어드밴스드 튜닝이라는 기능이 있다고 합니다.

 

어드밴스 튜닝

 

 

세가지 CLOVA Studio: Basic / Exclusive / Neurocloud

CLOVA Studio는 세가지 버전으로 제공한다고 합니다. 

CLOVA Studio Basic / Exclusive, Neurocloud for HCX로 나누어 있네요.

 

세가지 클로바 스튜디오

 


 

두번째는 핸즈온(실습) 시간입니다. 생성형 AI를 활용한 챗봇 앱을 간단히 개발해볼 수 있었습니다.

 

하이퍼클로바X API로 챗봇 서비스 구현하기

핸즈온 사진(네이버클라우드 제공)

 

핸즈온(실습) 시간을 짧게 가졌습니다. 핸즈온은 늘 시간이 모자라는 게, 다양한 사람들이 직접 작업하다보니 시간차이가 조금씩 발생합니다. 그래서 완성하려면 한도 끝도 없어지죠. 그래서 자료를 공개하고 있습니다. 자료를 보면서 따라해보면 좋습니다.

 

제목은 다음과 같습니다.

 

4 월 테크밋업

HyperCLOVA X 를 활용한 챗봇 만들기

 

 

 

금일은 총 두가지 실습을 진행했습니다. 하나는 플레이그라운드 공간에서 제공하는 다양한 파라미터의 역할을, 하나씩 실행해보면서 결과를 보면서 학습해보는 시간입니다. 나머지는 메일을 작성하는 챗봇을 Streamlit을 통해 앱으로 제작해보았습니다.

 

Lab1. CLOVA Studio 파라미터 기능 알아보기

 

제목은 마케팅 문구 생성하기로 입력하고, 시스템에는 아래와 같이 입력합니다.

시스템
- 광고 문구를 생성하는 시스템
- 상품에 대한 광고 문구 만들기

 

사용자 부분에는 이렇게 입력합니다. 우리는 답변(어시스턴트)에는 문구와 해당 광고 문구가 함께 나오기를 기대합니다.

상품: 커피
문구: 고소한 바디감이 느껴지는 향기로운 커피
상품: 아이크림

 

 

결과는 아래와 같습니다.

 

 

 

그런데, 다른 분들은 "아이크림"을 "아이스크림"으로 적은 경우가 많았습니다. 저도 따라해보았습니다. 먹는 것을 예시로 들었으니, 다음 상품에도 먹을 것으로 기대할 수 있습니다.

 

 

상품: 커피
문구: 고소한 바디감이 느껴지는 향기로운 커피
상품: 아이스크림

 

아이스크림의 결과

 

문구 : 부드러운 크림과 달콤한 과일향이 어우러진 프리미엄 아이스크림

 

아주 맛있는 아이스크림이 떠오르네요.

 

1. Temperature

이번에는 Temperature라는 파라미터를 1로 변경하겠습니다. 이 파라미터를 높게 잡으면 다채롭고 창의적인 문장이 만들어진다고 합니다.

 

temperature 높인 결과

 

큰 차이는 없어 보이네요!

 

 

2. Repetition penalty

반복하면 패널티 주는 파라미터입니다. 작으면 패널티를 작게 주니, 반복을 마음껏 할 수 있습니다. 크면 못하겠죠?

시스템에 광고 문구 5개를 만들게 합니다. 상품은 커피로 해서 실행합니다.

시스템 :
- 광고 문구를 생성하는 시스템
- 상품에 대한 광고 문구 5개 만들기

 

 

사용한 파라미터는 아래와 같이 Repetition penalty 0.5로 설정하고, Maximum tokens는 1000으로 충분히 5개의 문구가 잘 나오도록 유도합니다.

 

파라미터 값

 

이번에는 Repetition penalty를 10으로 설정합니다.

 

반복 패널티 높이기

 

조금은 더 답변이 다채로워진 점이 느껴지네요! 반복되는 부분도 충분히 줄어들었습니다.

 

 

Lab2. HyperCLOVA X 를 활용한 메일 작성 챗봇 만들기

이제는 메일 작성 챗봇을 만들어보겠습니다. 이 플레이그라운드를 활용하고, 마지막에는 Streamlit이라는 것도 함께 활용합니다.

 

이런 느낌

 

이 왕관이 무엇일까요? Streamlit의 로고입니다. 이것은 시각화, 대시보드 제작에 자주 쓰이는 도구입니다.

 

1. 키워드를 포함한 이메일 초안 작성하기

이메일부터 작성해봅니다. 다시 플레이그라운드에 와서 시스템에 다음과 같이 입력했습니다.

- 키워드를 포함하여 이메일 내용을 생성합니다.
- 메일 제목과 본문 내용을 출력합니다.
- 아래 예제와 유사한 포맷으로 작성합니다.
- 예제
키워드:
* 주제: 업무 협조
* 요구사항: 요청하신 내용으로 작업했습니다. 확인해주세요.
* 발신자: graph
* 수신인: stats
제목: 작업 내용 확인
메일: 안녕하세요 stats님, 저희 회사에서 진행하고 있는 프로젝트에 대해 말씀드리려고 합니다.
현재 개발중인 웹사이트가 있는데 혹시 괜찮으시다면 디자인 시안을 한번 봐주실 수 있을까요?
가능하시다면 오늘 오후 3시쯤 뵙고 싶습니다.
감사합니다.
graph 드림

 

파라미터는 Maximum tokens 300, Temperature 0.2로 설정합니다.

이러한 포맷을 가지고, 다시 사용자에 유사한 형식으로 작성합니다. 그에 대한 메일을 잘 작성해주는지, 어시스턴트(AI의 답변)부분을 유심히 살펴봅니다.

 

 

작성 결과

 

결과는 잘 나왔네요. 이렇게 시스템에 포맷을 설정해주면, HCX도 비슷한 포맷으로 메일을 작성해줍니다.

 

하나만 더 해봅니다. 주제와 요구사항 등을 다시 키워드로 제공했습니다. AI 테크밋업 준비를 위한 미팅을 진행합니다.

 

새로운 메일 작성 결과

 

잘 답변하는 것을 확인했습니다.

 

 

이제 우측 상단의 저장 버튼을 누르고, 제목을 입력하고 새로 저장하기를 수행합니다. 이 저장이 되면, 테스트 앱을 생성할 수 있는 도구를 제공합니다.

 

저장 버튼

 

2. API 를 활용한 이메일 초안 작성 챗봇 구현

이제 테스트 앱을 누르고, 제목 입력 후 생성 버튼을 누릅니다.

 

테스트 앱

 

그러면 테스트 앱을 위한 정보들이 나옵니다. 이 python 코드를 잘 복사해서 저장해두거나 그대로 띄워둔 채 다음 과정을 진행합니다.

 

테스트앱

 

 

이 코드에서 따로 저장해둘 부분은 총 두가지입니다. api_key, api_key_primary_val 에 나오는 두 가지 정보를 기억해둡시다.

if __name__ == '__main__':
    completion_executor = CompletionExecutor(
        host='https://clovastudio.stream.ntruss.com',
        api_key='개인키 정보1',
        api_key_primary_val= '개인키 정보2',
		...
    )

 

 

실습을 위해 Google Colab에 접속하겠습니다.

https://colab.research.google.com

 

Google Colab

 

colab.research.google.com

 

Colab은 구글에서 제공하는 Python 전용 실행도구라고 생각해주시면 됩니다. 일종의 Jupyter Notebook처럼 코드를 넣고 실행하거나 마크다운 문법으로 글을 작성해볼 수 있습니다. 각 셀마다 코드를 넣고 그 결과가 하단에 출력되므로 편리합니다.

 

먼저 Streamlit 설치합니다.

# 스트림릿 설치
!pip install -q streamlit
!pip install streamlit_chat

 

 

Streamlit 버전을 확인합니다.

스트림릿 버전 확인
!pip list | grep streamlit

버전

 

출력 확인을 위해 Python 코드를 입력합니다. 개인키 입력 부분에는 위에서 저장한 개인키값을 차례로 입력해줍니다.

import base64
import json
import http.client
import ssl
import requests
import re

class CompletionExecutor:
    def __init__(self, host, api_key, api_key_primary_val, request_id):
        self._host = host
        self._api_key = api_key
        self._api_key_primary_val = api_key_primary_val
        self._request_id = request_id

    def execute(self, completion_request):
        headers = {
            'X-NCP-CLOVASTUDIO-API-KEY': self._api_key,
            'X-NCP-APIGW-API-KEY': self._api_key_primary_val,
            'X-NCP-CLOVASTUDIO-REQUEST-ID': self._request_id,
            'Content-Type': 'application/json; charset=utf-8',
        }
        # Initialize result variable

        response = requests.post(self._host + '/testapp/v1/chat-completions/HCX-003',headers=headers, json=completion_request, stream=False)
        json_data = json.loads(response.text)
        print(json_data['result']['message']['content'])


if __name__ == '__main__':
    completion_executor = CompletionExecutor(
        host='https://clovastudio.stream.ntruss.com',
        api_key='개인키 입력',
        api_key_primary_val='개인키 입력',
        request_id='103f6aaf-fee1-4884-a5bf-7628873adb7e'
    )


    preset_text = [{
                    "role":"system",
                    "content":"""- 키워드를 포함하여 이메일 내용을 생성합니다. \r\n
                    - 메일 제목과 본문 내용을 출력합니다. \r\n
                    - 아래 예제와 유사한 포맷으로 작성합니다. \r\n
                    - 예제 \r\n
                    키워드: \r\n
                    * 주제: 업무 협조 \r\n
                    * 요구사항: 요청하신 내용으로 작업했습니다. 확인해주세요. \r\n
                    * 발신자: graph \r\n
                    * 수신인: stats \r\n
                    제목: 작업 내용 확인 \r\n
                    메일: 안녕하세요 stats님, \
                    저희 회사에서 진행하고 있는 프로젝트에 대해 말씀드리려고 합니다. \r\n
                    현재 개발중인 웹사이트가 있는데 혹시 괜찮으시다면 디자인 시안을 한번 봐주실 수 있을까요? \r\n
                    가능하시다면 오늘 오후 3시쯤 뵙고 싶습니다. \r\n
                    감사합니다. \r\n
                    graph 드림\r"""
                    },
                     {
                         "role":"user",
                         "content":"""키워드:\r\n
                         * 주제: 미팅 파일 공유\r\n
                         * 요구사항: 미팅때 보여주셨던 파일을 보내주세요.\r\n
                         * 발신자: stats\r\n
                         * 수신인: 네클이\r"""}]
    request_data = {
        'messages': preset_text,
        'topP': 0.8,
        'topK': 0,
        'maxTokens': 300,
        'temperature': 0.3,
        'repeatPenalty': 5.0,
        'stopBefore': [],
        'includeAiFilters': True,
        'seed': 0
    }

    response_text=completion_executor.execute(request_data)

 

 

실행하면 아래와 같이 답변이 의도한대로 잘 나타나는 것을 확인할 수 있습니다.

 

답변 출력 colab

 

 

이제 streamlit으로 넘어가보겠습니다. 위에서 코드를 일부 수정했습니다. streamlit은 st로 불러옵니다.

# 4. Streamlit을 활용한 챗봇 UI 제작 (개인 키 정보를 변경하여 결과 확인)
%%writefile app.py
import streamlit as st
from streamlit_chat import message
import base64
import json
import http.client
import ssl
import requests
import re

class CompletionExecutor:
    def __init__(self, host, api_key, api_key_primary_val, request_id):
        self._host = host
        self._api_key = api_key
        self._api_key_primary_val = api_key_primary_val
        self._request_id = request_id

    def execute(self, completion_request):
        headers = {
            'X-NCP-CLOVASTUDIO-API-KEY': self._api_key,
            'X-NCP-APIGW-API-KEY': self._api_key_primary_val,
            'X-NCP-CLOVASTUDIO-REQUEST-ID': self._request_id,
            'Content-Type': 'application/json; charset=utf-8',
        }
        response = requests.post(self._host + '/testapp/v1/chat-completions/HCX-003',headers=headers, json=completion_request, stream=False)
        try:
           json_data = json.loads(response.text)
           print("JSON parsing successful.")
        except json.JSONDecodeError as e:
           print("JSON parsing failed:", e)

        return json_data['result']['message']['content']

st.title("HyperCLOVA X를 활용한 이메일 작성✉️")


if 'generated' not in st.session_state:
    st.session_state['generated'] = []

if 'past' not in st.session_state:
    st.session_state['past'] = []

with st.form('form', clear_on_submit=True):
    user_input = st.text_area('You: ', '', key='input',height=200)
    submitted = st.form_submit_button('Send')
    if submitted and user_input:
        with st.spinner("Waiting for HyperCLOVA..."):

            completion_executor = CompletionExecutor(
                host='https://clovastudio.stream.ntruss.com',
                api_key='개인키 변경',
                api_key_primary_val='개인키 변경',
                request_id='103f6aaf-fee1-4884-a5bf-7628873adb7e'
            )

            preset_text = [{
                "role":"system",
                "content":"""- 키워드를 포함하여 이메일 내용을 생성합니다. \r\n
                - 메일 제목과 본문 내용을 출력합니다. \r\n
                - 아래 예제와 유사한 포맷으로 작성합니다. \r\n
                - 예제 \r\n
                키워드: \r\n
                * 주제: 업무 협조 \r\n
                * 요구사항: 요청하신 내용으로 작업했습니다. 확인해주세요. \r\n
                * 발신자: graph \r\n
                * 수신인: stats \r\n
                제목: 작업 내용 확인 \r\n
                메일: 안녕하세요 stats님, \
                저희 회사에서 진행하고 있는 프로젝트에 대해 말씀드리려고 합니다. \r\n
                현재 개발중인 웹사이트가 있는데 혹시 괜찮으시다면 디자인 시안을 한번 봐주실 수 있을까요? \r\n
                가능하시다면 오늘 오후 3시쯤 뵙고 싶습니다. \r\n
                감사합니다. \r\n
                graph 드림\r"""
                },
                  {
                      "role":"user",
                      "content":"""키워드:\r\n
                      * 주제: 미팅 파일 공유\r\n
                      * 요구사항: 미팅때 보여주셨던 파일을 보내주세요.\r\n
                      * 발신자: stats\r\n
                      * 수신인: 네클이\r"""}]

            request_data = {
                'messages': preset_text,
                'topP': 0.8,
                'topK': 0,
                'maxTokens': 300,
                'temperature': 0.3,
                'repeatPenalty': 5.0,
                'stopBefore': [],
                'includeAiFilters': True,
                'seed': 0
            }

            response_text=completion_executor.execute(request_data)
            st.session_state.past.append(user_input)
            st.session_state.generated.append(response_text)

    if st.session_state['generated']:
        for i in range(len(st.session_state['generated'])-1, -1, -1):
            message(st.session_state['past'][i], is_user=True, key=str(i) + '_user')
            message(st.session_state["generated"][i], key=str(i))

 

그러면, Writing app.py 문구가 보이고, colab 왼쪽에 app.py 파일이 나타납니다. 이것을 colab에서 실행하려면 추가적인 작업(터널링)이 필요합니다.

 

먼저 사전 작업을 수행합니다. localtunnel의 비밀번호를 구하는 코드입니다.

# 터널링
import urllib
print("Password/Enpoint IP for localtunnel is:",
      urllib.request.urlopen('https://ipv4.icanhazip.com').read().decode('utf8').strip("\n"))

 

코드를 실행하면 출력결과로 비밀번호가 나오는데, 잘 저장해둡니다.

 

 

아래 코드를 통해, Streamlit을 실행할 local tunnel을 설치합니다.

!npm install localtunnel

 

streamlit app을 백그라운드에서 실행합니다.

!streamlit run app.py &>/content/logs.txt &

 

이제 이 app을 로컬터널에서 웹상에 띄워봅니다.

!npx localtunnel --port 8501

localtunnel을 위한 colab 코드 실행 결과

 

위와 같이 주소가 뜨면, 해당 url을 클릭합니다. 아래 화면에서 Tunnel Password를 입력합니다. (위에서 저장한 비밀번호 입력)

 

터널 화면

 

Click to Submit을 누르면 아래와 같이 화면이 나타납니다. 대략 키워드를 You에 '시스템'에 작성한 내용을 그대로 입력하고, Send 버튼을 누릅니다.

 

Streamlit 메일 결과

 

결과값도 잘 나타나는 것을 확인할 수 있습니다.

 

추가로 파라미터 수정도 가능한 대시보드도 생성해볼 수 있게 도와주셨습니다.

 

코드 일부가 변경됩니다. 스트림릿의 사이드바라는 메서드를 만들어줍니다. 그 다음, request_data에는 이제 변수가 들어가는 것을 알 수 있습니다. 이걸 위 코드에 추가 및 수정해줍니다.

with st.sidebar:
  st.sidebar.title('⚙️파라미터 설정값 조정')
  topP_value = st.slider('Select top P', 0.0, 1.0,0.8)
  topK_value = st.slider('Select top K', 0, 128,0)
  token_value = st.slider('Select maximum tokens?', 0, 4096,300)
  temperature_value = st.slider('Select Temperature', 0.0, 1.0,0.3)
  repeatPenalty_value = st.slider('Select Temperature', 0.0, 10.0,5.0)
  
  
  ...
  

            request_data = {
                'messages': preset_text,
                'topP': topP_value,
                'topK': topK_value,
                'maxTokens': token_value,
                'temperature': temperature_value,
                'repeatPenalty': repeatPenalty_value,
                'stopBefore': [],
                'includeAiFilters': True,
                'seed': 0
            }

 

 

실행한 다음에, 다시 localtunnel 관련 코드를 실행해줍니다. 다시 로컬 터널로 제공된 URL을 들어가면, 비밀번호 입력 후 아래와 같이 파라미터 조절이 가능한 화면이 나타납니다.

 

파라미터 조절 화면

 

여기서 이메일 작성란에 동일하게 시스템 지시문을 넣겠습니다. 파라미터는 maximum token을 200으로 설정하고, Send 버튼을 누릅니다. 그러면 아래와 같은 결과물이 나타납니다.

 

그 결과

 

 

네트워킹: 핸즈온 뒤에 부족하지만 풍성한 시간

대망의 네트워킹이 진행되었지만, 다들 늦은 시간까지 고생하시느라 일찍 가신 분도 많이 있었습니다. 핸즈온과 네트워킹 두마리 토끼를 다 잡는 미팅은 쉽지 않아 보이네요!

 

그래도 개발자, 마케터, 분석가, 엔지니어를 한자리에 뵐 수 있어서 즐거운 시간이었습니다. 네이버클라우드 담당자 분과도 작게나마 소통할 수 있어 다양한 궁금증을 해소할 수 있던 시간이었습니다.

 

긴 글 읽어주셔서 감사합니다.