Streamlit

GCP VM Connect to BigQuery using Streamlit (ver. 2025, 06)

개요

  • VM 만들기 Web UI가 일부 변경됨 (추가 진행하기로 함)
  • VM 생성 및 VS Code 연결
  • VM과 BigQuery 연결

VM 머신 생성

머신 구성

  • 이름과 성능 체크
  • 월별 예상 가격을 체크한다.

Screenshot 2025-06-20 at 7.54.08 PM.png

OS 및 스토리지

  • Ubuntu - Ubuntu 24.04 LTS 방식으로 진행 (x86/64) 방식 선택
  • 디스크 사이즈 : 25GB

Screenshot 2025-06-20 at 8.00.50 PM.png

  • 암호화 : Google 관리 암호화 키 선택

Screenshot 2025-06-20 at 8.02.26 PM.png

LangChain with Streamlit 논문요약 예제

개요

  • LangChain의 기본 개념에 대해 살펴본다.
  • LangChain을 활용하며 간단한 웹앱을 구현한다.
  • 각 사용자가 본인의 API를 입력하면 해당 기능을 사용할 수 있도록 구현한다.

LangChain의 기본개념

  • LangChain은 대규모 언어 모델(LLM)을 활용한 애플리케이션 개발을 위한 프레임워크입니다.
  • 주요 특징과 장점은 다음과 같다.
    • 모듈성
      • 다양한 LLM과 도구들을 쉽게 통합하고 교체할 수 있다.
      • 재사용 가능한 컴포넌트를 제공한다.
    • 체이닝(Chaining)
      • 여러 컴포넌트를 연결하여 복잡한 워크플로우를 구성할 수 있다.
      • 프롬프트, LLM 호출, 출력 파싱 등을 순차적으로 처리한다
    • 메모리 관리
      • 대화 기록을 저장하고 관리할 수 있다.
      • 문맥을 유지하면서 대화형 애플리케이션을 만들 수 있다.
    • 다양한 통합
      • 여러 AI 모델(OpenAI, Anthropic 등)을 지원한다.
      • 데이터베이스, 검색 엔진 등 외부 도구와 연동이 가능하다.
    • 개발 편의성
      • 파이썬 기반의 직관적인 API를 제공한다.
      • 풍부한 문서와 예제가 제공된다.

LangChain을 활용한 프로젝트 구조 만들기

  • API 키를 입력하면 해당 기능을 사용할 수 있도록 구현한다.
  • 구현 프로세스
    • API 키 입력 화면 구현
    • 입력된 API 키를 활용한 기능 구현
    • 웹앱 레이아웃 구성
    • 사용자 친화적인 인터페이스 제공
  • PDF논문 요약 기능 구현
    • 논문 PDF 파일 업로드
    • 논문 요약 기능 구현
    • 요약 결과 표시 (각 챕터별)
  • 웹앱 레이아웃 구성
    • 사용자 친화적인 인터페이스 제공
    • 논문 요약 기능 구현
    • 요약 결과 표시
  • 먼저 테스트성으로 jupyter notebook으로 구현
    • jupyter notebook에서는 .env 파일에 있는 API 키를 불러오는 형태로 구현한다.
    • 논문은 files 폴더에 있는 논문 1개를 사용한다.

참고 논문

jupyter notebook 테스트

  • 코드는 아래와 같다.
# 필요한 라이브러리 임포트
import os
from langchain.chat_models import ChatOpenAI  # OpenAI의 ChatGPT 모델을 사용하기 위한 클래스
from langchain_core.prompts import ChatPromptTemplate  # 채팅 프롬프트 템플릿 생성을 위한 클래스
from langchain_core.output_parsers import StrOutputParser  # 출력을 문자열로 파싱하기 위한 클래스
from langchain_community.document_loaders import PyPDFLoader  # PDF 파일을 로드하기 위한 클래스
from langchain.text_splitter import RecursiveCharacterTextSplitter  # 텍스트를 청크로 분할하기 위한 클래스
from docx import Document  # Word 문서 생성을 위한 클래스
from dotenv import load_dotenv  # 환경 변수 로드를 위한 모듈
from datetime import datetime  # 날짜/시간 처리를 위한 클래스

# .env 파일에서 환경 변수 로드
load_dotenv()

# 환경 변수에서 OpenAI API 키 가져오기
openai_api_key = os.getenv("OPENAI_API_KEY")

# API 키가 존재하는지 확인
if not openai_api_key:
    raise ValueError("OPENAI_API_KEY 환경 변수를 찾을 수 없습니다. .env 파일을 확인해주세요.")

# files 디렉토리에서 PDF 파일 찾기
pdf_files = [f for f in os.listdir("files") if f.endswith('.pdf')]
if not pdf_files:
    raise ValueError("files 디렉토리에서 PDF 파일을 찾을 수 없습니다")

# 첫 번째 PDF 파일의 전체 경로 생성
pdf_path = os.path.join(os.getcwd(), "files", pdf_files[0])

# PDF 파일 로드 및 페이지 분할
loader = PyPDFLoader(pdf_path)
pages = loader.load_and_split()

# 텍스트 분할기 설정 - 큰 청크 사이즈로 설정하여 컨텍스트 유지
text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=4000,  # 각 청크의 최대 문자 수
    chunk_overlap=400,  # 청크 간 중복되는 문자 수
    length_function=len
)

# 페이지들을 청크로 분할
texts = text_splitter.split_documents(pages)

# 텍스트를 전반부와 후반부 두 개의 파트로 병합
if len(texts) > 2:
    # 전반부 텍스트 병합
    first_half = " ".join([t.page_content for t in texts[:len(texts)//2]])
    # 후반부 텍스트 병합
    second_half = " ".join([t.page_content for t in texts[len(texts)//2:]])
    texts = [
        {"content": first_half, "part": "전반부"},
        {"content": second_half, "part": "후반부"}
    ]

# LangChain의 ChatOpenAI 모델 설정
llm = ChatOpenAI(
    openai_api_key=openai_api_key,
    model="gpt-3.5-turbo",  # GPT-3.5 모델 사용
    temperature=0.1,  # 낮은 temperature로 일관된 출력 생성
    max_tokens=1000  # 충분한 길이의 요약을 위한 토큰 수 설정
)

# 요약을 위한 프롬프트 템플릿 설정
prompt = ChatPromptTemplate.from_messages([
    ("system", "당신은 전문 학술 연구원입니다. 다음 학술 논문 파트를 주요 포인트와 핵심 발견사항을 중심으로 한글로 포괄적이고 상세하게 요약해주세요."),
    ("user", "다음 텍스트를 한글로 요약해주세요. 이 텍스트는 논문의 {part}입니다:\n\n{text}\n\n반드시 한글로 요약해주시고, 영어 전문용어가 있다면 한글 설명을 덧붙여주세요.")
])

# 프롬프트, LLM, 출력 파서를 연결하는 체인 생성
chain = prompt | llm | StrOutputParser()

# Word 문서 객체 생성
doc = Document()
doc.add_heading('논문 요약', 0)

# 현재 시간을 파일명에 포함시키기 위한 형식 지정
current_time = datetime.now().strftime("%Y%m%d_%H%M%S")

# 각 파트별로 요약 실행 및 Word 문서에 추가
for i, text in enumerate(texts):
    print(f"파트 {i+1}/2 요약 중...")
    # 체인을 실행하여 요약 생성
    summary = chain.invoke({"text": text["content"], "part": text["part"]})
    
    # Word 문서에 요약 내용 추가
    doc.add_heading(f'{text["part"]} 요약', level=1)
    doc.add_paragraph(summary)
    doc.add_paragraph('-' * 40)  # 구분선 추가
    
    # 콘솔에 요약 출력
    print(f"\n{text['part']} 요약:")
    print(summary)
    print("-" * 80)

# 생성된 Word 문서를 저장
output_path = f"논문_요약_{current_time}.docx"
doc.save(output_path)
print(f"\n한글 요약본이 {output_path}에 저장되었습니다")
  • 위 코드를 실제 실행하면 다음과 같은 결과가 나온다.

Screenshot 2025-02-09 at 7.36.19 PM.png

Streamlit on Google Colab

개요

  • 개발환경설정이 어려운 환경에서 Google Colab 상에서 Streamlit 설치 및 실행을 익히고자 한다.
  • 주로 강의 목적으로 사용하기를 바란다.

Streamlit 라이브러리 설치

  • 아래 코드를 활용하여 streamlit 라이브러리 설치
!pip install -q streamlit

Untitled

Streamlit 코드 작성 샘플

%%writefile app.py

import streamlit as st
import plotly.graph_objs as go
from plotly.subplots import make_subplots
import seaborn as sns

@st.cache_data
def load_data():
    df = sns.load_dataset('tips')
    return df

def main():
    st.title("Streamlit with Plotly")   
    tips = load_data()

    # 데이터가공
    m_tips = tips.loc[tips['sex'] == 'Male', :]
    f_tips = tips.loc[tips['sex'] == 'Female', :]

    # 시각화 차트
    fig = make_subplots(rows = 1,
                        cols = 2,
                        subplot_titles=('Male', 'Female'),
                        shared_yaxes=True,
                        shared_xaxes=True,
                        x_title='Total Bill($)'
                        )
    fig.add_trace(go.Scatter(x = m_tips['total_bill'], y = m_tips['tip'], mode='markers'), row=1, col=1)
    fig.add_trace(go.Scatter(x = f_tips['total_bill'], y = f_tips['tip'], mode='markers'), row=1, col=2)
    fig.update_yaxes(title_text="Tip($)", row=1, col=1)
    fig.update_xaxes(range=[0, 60])
    fig.update_layout(showlegend=False)
    
    # 중요포인트
    # fig.show()
    st.plotly_chart(fig, use_container_width=True)

if __name__ == "__main__":
    main()

Untitled

Streamlit ML Multiclass Classification Model Prediction Sample (feat. Pipeline)

개요

  • Kaggle 데이터셋을 활용하여 Streamlit ML Multiclass Classification Model을 배포한다.
  • 각 코드에 대한 자세한 설명은 여기에서는 생략한다.

데이터 수집

Untitled

Untitled

모델 개발

  • 다음 코드는 모델을 개발하는 코드이다.
  • 주어진 데이터셋에서 종속변수 NObeyesdad을 예측하는 모델을 구성했다.
    • 파일명 : model.py
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.compose import ColumnTransformer
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.ensemble import RandomForestClassifier
from sklearn.pipeline import Pipeline
from sklearn.metrics import classification_report
from joblib import dump, load
import os

DATA_PATH = './data/train.csv'
data = pd.read_csv(DATA_PATH)

# Separate features and target variable
X = data.drop(['id', 'NObeyesdad'], axis=1)
y = data['NObeyesdad']

# Split the dataset into training and testing sets
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# Identify numerical and categorical columns
num_columns = X.select_dtypes(include=['float64']).columns
cat_columns = X.select_dtypes(include=['object']).columns

# Create the preprocessing pipeline
preprocessor = ColumnTransformer(
    transformers=[
        ('num', StandardScaler(), num_columns),
        ('cat', OneHotEncoder(handle_unknown='ignore'), cat_columns)
    ]
)

# Create the full pipeline
pipeline = Pipeline(steps=[
    ('preprocessor', preprocessor),
    ('classifier', RandomForestClassifier())
])

# Train the model
pipeline.fit(X_train, y_train)

# 모델 저장
model_directory = 'model'

if not os.path.exists(model_directory):
    os.makedirs(model_directory)

model_path = os.path.join(model_directory, 'NObeyesdad_prediction_pipeline.joblib')
dump(pipeline, model_path)
  • 위 코드에서 핵심은 모델을 저장하는 것이며, 또한 OneHotEncoder(handle_unknown='ignore') 을 지정하는 것이다.
  • 해당하는 폴더에 model 폴더가 없으면 model 폴더를 생성하고 NObeyesdad_prediction_pipeline.joblib 이름으로 모델을 저장한다.

파일 실행

  • model.py 를 실행하여 모델을 생성한다.
python model.py

Streamlit App 개발

  • 다음 코드는 Streamlit App 개발을 하는 코드이다.
    • 파일명 : app.py
import streamlit as st
import pandas as pd
from joblib import load
import os

# Assuming your model is saved in the 'model' directory with the name 'obesity_prediction_pipeline.joblib'
model_directory = 'model'
model_path = os.path.join(model_directory, 'NObeyesdad_prediction_pipeline.joblib')

def predict_NObeyesdad_level(model_path, Gender, Age, Height, Weight, family_history_with_overweight, FAVC, FCVC, NCP, CAEC, SMOKE, CH2O, SCC, FAF, TUE, CALC, MTRANS):
    
    # 모델 불러오기
    pipeline = load(model_path)
    
    # 데이터프레임 생성
    df = pd.DataFrame([{
        'Gender': Gender, 'Age': Age, 'Height': Height, 'Weight': Weight,
        'family_history_with_overweight': family_history_with_overweight, 'FAVC': FAVC,
        'FCVC': FCVC, 'NCP': NCP, 'CAEC': CAEC, 'SMOKE': SMOKE, 'CH2O': CH2O,
        'SCC': SCC, 'FAF': FAF, 'TUE': TUE, 'CALC': CALC, 'MTRANS': MTRANS
    }])
    
    # 예측 값 생성
    prediction = pipeline.predict(df)
    return prediction[0]

def main():
    st.title('Obesity Level Prediction Model')
    st.write('Predict obesity levels based on personal and health-related attributes.')

    # Create input fields for each feature
    Gender = st.selectbox('Gender', ['Male', 'Female'])
    Age = st.number_input('Age', min_value=0.0, format='%f')
    Height = st.number_input('Height (in meters)', min_value=0.0, format='%f')
    Weight = st.number_input('Weight (in kg)', min_value=0.0, format='%f')
    family_history_with_overweight = st.selectbox('Family history with overweight', ['yes', 'no'])
    FAVC = st.selectbox('Frequent consumption of high caloric food', ['yes', 'no'])
    FCVC = st.number_input('Frequency of consumption of vegetables', min_value=0.0, max_value=3.0, step=0.1)
    NCP = st.number_input('Number of main meals', min_value=1.0, max_value=4.0, step=0.1)
    CAEC = st.selectbox('Consumption of food between meals', ['No', 'Sometimes', 'Frequently', 'Always'])
    SMOKE = st.selectbox('Do you smoke?', ['yes', 'no'])
    CH2O = st.number_input('Consumption of water daily (liters)', min_value=0.0, format='%f')
    SCC = st.selectbox('Calories consumption monitoring', ['yes', 'no'])
    FAF = st.number_input('Physical activity frequency (per week)', min_value=0.0, format='%f')
    TUE = st.number_input('Time using technology devices (hours)', min_value=0.0, format='%f')
    CALC = st.selectbox('Consumption of alcohol', ['Never', 'Sometimes', 'Frequently', 'Always'])
    MTRANS = st.selectbox('Mode of transportation', ['Automobile', 'Bike', 'Motorbike', 'Public_Transportation', 'Walking'])

    if st.button('Predict Obesity Level'):
        result = predict_NObeyesdad_level(model_path, Gender, Age, Height, Weight, family_history_with_overweight, FAVC, FCVC, NCP, CAEC, SMOKE, CH2O, SCC, FAF, TUE, CALC, MTRANS)
        st.success(f'Predicted Obesity Level: {result}')

if __name__ == "__main__":
    main()
  • 위 코드에서 핵심은 predict_tip 함수이다. pipeline으로 모델을 설계하면 곧바로 predict() 저장된 모델을 불러온 후, 함수 사용이 가능하다.

테스트

  • 테스트 결과는 아래와 같이 나온다.
streamlit run app.py 

Untitled

Streamlit ML Model Prediction Sample (feat. Pipeline)

강의소개

개요

  • tips 데이터셋을 활용하여 Streamlit ML Model을 배포한다.
  • 각 코드에 대한 자세한 설명은 여기에서는 생략한다.

모델 개발

  • 다음 코드는 모델을 개발하는 코드이다.
  • 주어진 데이터셋에서 tip을 예측하는 모델을 구성했다.
    • 파일명 : model.py
import streamlit as st
import pandas as pd
import seaborn as sns
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import OneHotEncoder
from joblib import dump, load
import os

# 데이터셋 불러오기
tips = sns.load_dataset('tips')

# 데이터셋 컬럼 추출
categorical_features = ['sex', 'smoker', 'day', 'time']
numerical_features = ['total_bill', 'size']

# pipeline 모델 만들기
preprocessor = ColumnTransformer(
    transformers=[
        ('num', 'passthrough', numerical_features),
        ('cat', OneHotEncoder(), categorical_features)
    ])

pipeline = Pipeline(steps=[('preprocessor', preprocessor),
                           ('model', LinearRegression())])

# 데이터셋 분류 / 종속 변수 tip을 예측하는 모델
X = tips.drop('tip', axis=1)
y = tips['tip']

# 데이터셋 분류
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 모델 학습
pipeline.fit(X_train, y_train)

# 모델 저장
model_directory = 'model'

if not os.path.exists(model_directory):
    os.makedirs(model_directory)

model_path = os.path.join(model_directory, 'tip_prediction_pipeline.joblib')
dump(pipeline, model_path)
  • 위 코드에서 핵심은 모델을 저장하는 것이다. 마지막 코드이다.
  • 해당하는 폴더에 model 폴더가 없으면 model 폴더를 생성하고 tip_prediction_pipeline.joblib 이름으로 모델을 저장한다.
  • model.py를 실행한다.
python model.py
  • 정상적으로 모델이 만들어졌으면, model 폴더가 생겼을 것이고, 그 다음에 해당 모델이 저장되어 있을 것이다.

Streamlit App 개발

  • 다음 코드는 Streamlit App 개발을 하는 코드이다.
    • 파일명 : app.py
import streamlit as st
import pandas as pd
from joblib import load
import os

model_directory = 'model'
model_path = os.path.join(model_directory, 'tip_prediction_pipeline.joblib')

def predict_tip(model_path, total_bill, size, sex, smoker, day, time):
    
    # 모델 불러오기
    pipeline = load(model_path)
    
    # 예측 데이터 생성
    df = pd.DataFrame([{'total_bill': total_bill, 'size': size, 'sex': sex, 'smoker': smoker, 'day': day, 'time': time}])
    
    # 예측값 생성
    prediction = pipeline.predict(df)
    return prediction[0]

def main():

    st.title('팁 예측 모델')
    st.write('total_bill과 다른 요인을 고려하여 tip 예측 모델 생성')

    total_bill = st.number_input('Total Bill ($)', min_value=0.0, format='%f')
    size = st.number_input('Size of the Party', min_value=1, step=1)
    sex = st.selectbox('Sex', ['Male', 'Female'])
    smoker = st.selectbox('Smoker', ['Yes', 'No'])
    day = st.selectbox('Day', ['Thur', 'Fri', 'Sat', 'Sun'])
    time = st.selectbox('Time', ['Lunch', 'Dinner'])

    if st.button('예상 Tip 예측'):
        result = predict_tip(model_path, total_bill, size, sex, smoker, day, time)
        st.success(f'예측 Tip: ${result:.2f}')

if __name__ == "__main__":
    main()
  • 위 코드에서 핵심은 predict_tip 함수이다. pipeline으로 모델을 설계하면 곧바로 predict() 저장된 모델을 불러온 후, 함수 사용이 가능하다.

테스트

  • 테스트 결과는 아래와 같이 나온다.
streamlit run app.py 

Untitled

st-pages 라이브러리 소개

강의소개

개요

  • Streamlit 생태계에 기반한 Components를 살펴본다.
  • st-pages 라이브러리를 확인한다.

Components

  • Components는 Streamlit Community와 Creators가 직접 개발한 Streamlit 관련 라이브러리를 말한다.
  • 여기에는 다양한 라이브러리들이 존재한다.

Untitled

활용법 주의

Untitled

creating multipages in streamlit web using official docs

강의소개

개요

Streamlit에서 multipage란 무엇인가?

  • 앱의 크기가 커질수록 다중 페이지 구성은 관리와 탐색의 용이성을 제공함.
  • Streamlit은 이를 쉽게 가능하게 하며, 클릭 한 번으로 해당 페이지에 빠르게 이동할 수 있다.

폴더 및 파일 구조

  • Home.py 파일을 만든 후에는 엔트리포인트 파일과 관련된 pages/about.py 파일을 만들어 페이지를 추가할 수 있다. 다음은 다중 페이지 앱에 유효한 디렉토리 구조는 아래와 같다.

Screenshot 2024-02-25 at 11.44.33 AM.png

출간 기념, Streamlit으로 프로젝트 한방에 끝내기 with 파이썬 개정판 (2024, Sara & Evan)

  • 개정판 책을 출간하였습니다.

book.jpg

Streamlit이란

  • Streamlit은 데이터 분석가가 간단한 코드 몇줄로 빠르게 웹앱을 만들어 줄 수 있는 Python 라이브러리입니다.

누가 읽어야 할까요?

  • 데이터 분석가 : 웹개발은 모르지만 대시보드를 만들어야 하는 분
  • 국비교육 수강중인 비전공자 : Java 웹개발로 머신러닝 플랫폼을 만들어야 하는 분
  • 개별적인 포트폴리오가 필요한 취업준비생 : ML/DL 알고리즘 익히는 것도 어려운데, 웹개발은 언제 배우죠?

데모 페이지

Untitled

출간 기념, Streamlit으로 프로젝트 한방에 끝내기 with 파이썬(2023, Sara & Evan)

  • 책을 출간하였습니다.

book.jpg

Streamlit이란

  • Streamlit은 데이터 분석가가 간단한 코드 몇줄로 빠르게 웹앱을 만들어 줄 수 있는 Python 라이브러리입니다.

누가 읽어야 할까요?

  • 데이터 분석가 : 웹개발은 모르지만 대시보드를 만들어야 하는 분
  • 국비교육 수강중인 비전공자 : Java 웹개발로 머신러닝 플랫폼을 만들어야 하는 분
  • 개별적인 포트폴리오가 필요한 취업준비생 : ML/DL 알고리즘 익히는 것도 어려운데, 웹개발은 언제 배우죠?

데모 페이지

Untitled

Streamlit Matplotlib 한글폰트 적용 예제

Streamlit Matplotlib-Seaborn 한글폰트 적용

개요

  • 배포 시, matplotlib & seaborn 한글 폰트 적용 하는 방법에 대해 알아본다.
  • 나눔고딕 폰트를 적용해본다.

폰트 다운로드

Untitled

개발환경 세팅

  • git clone 명령어를 활용하여 프로젝트 repo를 다운로드 받는다.

Untitled

  • 가상환경을 설정한다.
    • virtualenv venv 실행한다.
    • source venv/Scripts/activate 실행하여 가상환경에 접속한다.
$ virtualenv venv
created virtual environment CPython3.9.13.final.0-64 in 606ms
  creator CPython3Windows(dest=C:\Users\YONSAI\Desktop\streamlit-korean-fonts\venv, clear=False, no_vcs_ignore=False, global=False)
  seeder FromAppData(download=False, pip=bundle, setuptools=bundle, wheel=bundle, via=copy, app_data_dir=C:\Users\YONSAI\AppData\Local\pypa\virtualenv)
    added seed packages: pip==23.1.2, setuptools==67.6.1, wheel==0.40.0
  activators BashActivator,BatchActivator,FishActivator,NushellActivator,PowerShellActivator,PythonActivator
$ source venv/Scripts/activate
(venv)
$ 
  • requirements.txt 파일에 다음 라이브러리만 설치한다.
streamlit
matplotlib
seaborn
pandas
numpy

폰트 폴더 설정

  • customFonts 폴더를 만들고 다운로드 받은 폴더를 추가한다.

Untitled