2025/03/28 TIL

김학열·2025년 3월 28일

01. 무엇을 만드나요?

✔️ **오늘 만들게 될 대시보드에 대해 알아봅니다.**
  • 오늘 배우게 될 대시보드 미리보기
    • 사이드바
      • 데이터 분석에 사용 할 데이터셋 선택
      • 추가로 CSV 파일 업로드 가능
      • 데이터 분석에 사용 할 모델 선정 가능
    • 메인 화면
      • 상단
        • API 키 입력 받기
        • 시각화 하기 위한 아이템 입력하기
      • 하단
        • 데이터 분석을 할 데이터셋을 눈으로 확인 가능

02. 기본 대시보드 만들기

✔️ **Streamlit을 활용해서 기본 대시보드를 만들고, 데이터셋을 불러오며 UI를 구성하는 방법을 다룹니다.**
  • 프로그램 코드의 구조 📌 이 프로그램은 **기본 정보 불러오기**, **기능 구현 함수**, 그리고 **메인 함수**로 구성되어 있습니다. 각 섹션이 하는 역할과 그 의미를 설명드리겠습니다.

- 파일 생성하기: 08_app_data_visualization.py

- **기본 정보 불러오기**
    - 이 섹션에서는 프로그램 실행에 필요한 주요 라이브러리들을 불러옵니다.
    
    - **pandas**: CSV, DataFrame 등의 데이터 처리를 위한 라이브러리입니다.
    
    
    
    - **streamlit**: 간단한 코드로 웹 애플리케이션을 만들 수 있는 라이브러리로, UI 구성에 사용됩니다.
    
    
    
    - **matplotlib**: 파이썬의 대표적인 시각화 라이브러리로, 그래프, 차트 등을 그릴 때 사용합니다
    
    
    
    - **openai**: OpenAI의 API를 사용해 ChatGPT 모델에 질의를 보내고 코드를 생성하는 데 사용합니다.
    
    
    

    
- **기능 구현 함수**
아래는 핵심 함수들의 예시 코드입니다.
    - API 호출, 사용자 질의 생성, 응답 후처리 등 핵심 기능을 담당하는 함수들을 모아둔 부분입니다.
        1. **`run_request`**: OpenAI ChatCompletion API를 호출하여, 사용자 질의(question_to_ask)에 대한 코드를 생성합니다.
        2. **`make_prompt`**: 사용자 질문과 데이터셋 정보를 합쳐 OpenAI 모델에게 전달할 ‘프롬프트’를 만듭니다.
    

- **메인 코드**
    - 프로그램의 전체적인 실행 흐름을 제어하는 부분입니다.
    - 페이지 레이아웃 설정, 사이드바, 사용자 입력과 버튼을 구성하고, 결과(그래프)를 출력합니다.
  • 기본 레이아웃 만들기
    • 사이드바(Sidebar) 구성
      • 사이드바를 사용하여 업로드된 CSV 파일을 추가하거나, 미리 지정된 여러 CSV 데이터셋 중 하나를 선택할 수 있습니다.

      • 또한 OpenAI API Key를 입력받고, 모델(gpt-4o, gpt-4o-mini) 중 하나를 선택하도록 라디오 버튼을 배치합니다.

        with st.sidebar:
            # 사용할 데이터셋 선택
            dataset_container = st.empty()
        
            # CSV 파일 업로드 기능
            try:
                uploaded_file = st.file_uploader(":computer: Load a CSV file:", type="csv")
                index_no = 0
                if uploaded_file:
                    # 업로드된 CSV를 데이터프레임으로 읽어서 datasets에 추가
                    file_name = uploaded_file.name[:-4].capitalize()
                    datasets[file_name] = pd.read_csv(uploaded_file)
                    # 방금 업로드한 데이터셋이 기본적으로 선택되도록 인덱스 설정
                    index_no = len(datasets) - 1
            except Exception as e:
                st.error("파일을 불러오지 못했습니다. 유효한 CSV 파일을 선택해 주세요.")
                print("File failed to load.\n" + str(e))
        
            # 데이터셋 선택 라디오 버튼
            chosen_dataset = dataset_container.radio(
                ":bar_chart: Choose your data:", datasets.keys(), index=index_no
            )
        
            # 모델 선택
            st.write(":brain: Choose your model(s):")
            model = st.radio(label="", options=["gpt-4o", "gpt-4o-mini"])
        
  • 인풋 위젯 만들기
    • 데이터셋 불러오기
      • 세션 상태에 datasets가 없다면, 특정 CSV 파일을 미리 로드하고 datasets 딕셔너리에 저장해둡니다.

      • 업로드된 CSV가 있다면 이를 새로 읽어와 datasets에 추가합니다.

        # 세션 상태에 datasets가 없으면 미리 지정된 CSV 파일들을 로드합니다.
        if "datasets" not in st.session_state:
            datasets = {}
            # 사전에 불러둘 데이터셋
            datasets["Movies"] = pd.read_csv("movies.csv")
            datasets["Housing"] = pd.read_csv("housing.csv")
            datasets["Cars"] = pd.read_csv("cars.csv")
            datasets["Colleges"] = pd.read_csv("colleges.csv")
            datasets["Customers & Products"] = pd.read_csv(
                "customers_and_products_contacts.csv"
            )
            datasets["Department Store"] = pd.read_csv("department_store.csv")
            datasets["Energy Production"] = pd.read_csv("energy_production.csv")
            st.session_state["datasets"] = datasets
        else:
            # 이미 세션 상태에 로드된 데이터셋 사용
            datasets = st.session_state["datasets"
        
    • OpenAI Key 입력받기
      • st.text_input를 통해 사용자로부터 API Key를 안전하게 입력받습니다.

        # OpenAI Key 입력
        openai_key = st.text_input(
            label=":key: OpenAI Key:",
            help="Required for ChatGPT-4o, ChatGPT-4o-mini",
            type="password",
        )
        
    • 차트 질문(visualisation)에 대한 사용자 입력
      • st.text_area를 통해 시각화와 관련한 질문을 받습니다.

      • 예: “매출이 시간에 따라 어떻게 변하는지 그래프를 그리고 싶어요.”

        # 사용자에게 시각화를 묻는 텍스트 입력
        question = st.text_area(":eyes: What would you like to visualise?", height=110)
        go_btn = st.button("Go...")
        
    • 데이터셋 탭으로 확인하기
      • 여러 개의 CSV 파일을 불러왔으므로, Streamlit의 st.tabs 기능을 사용해 각 데이터셋을 탭으로 분리하고, 표 형태로 내용을 확인할 수 있도록 합니다.

        tab_list = st.tabs(datasets.keys())
        for dataset_num, tab in enumerate(tab_list):
            with tab:
                dataset_name = list(datasets.keys())[dataset_num]
                st.subheader(dataset_name)
                st.dataframe(datasets[dataset_name], hide_index=True)
        

03. 채팅으로 시각화 추가 기능 구현하기

✔️ **OpenAI API를 통해 코드(그래프 생성 코드)를 자동 생성하고 실행하여 Streamlit 대시보드에 시각화를 표시합니다.**
  • 시각화 기능 구현하기
    • 사용자 입력으로부터 프롬프트 생성
      • make_prompt를 통해 선택된 데이터셋과 사용자의 질문을 합쳐 하나의 “코드를 생성해줘”라는 요청 문구를 만듭니다.
    • OpenAI API 호출
      • run_request로 ChatGPT에게 코드 생성을 요청합니다.
      • 불필요한 read_csv 부분은 제거한 뒤 최종 코드만 받아옵니다.
    • 시각화 코드 실행 후 결과 표시
      • 기존에 준비해둔 base_code(import, fig, ax 설정, df=...)와 ChatGPT가 생성한 코드를 합쳐 final_code를 구성합니다.

      • 코드 실행 전 plt.clf() 등을 통해 현재 figure를 초기화하고, 생성된 코드를 exec로 실행합니다.

      • 실행 후 plt.gcf()(현재 figure 객체)를 가져와 대시보드에 표시합니다.

      • st.pyplot(fig)로 Streamlit 대시보드에 그래프를 표시합니다.

        if go_btn and openai_key:
            # 1) 프롬프트 생성
            question_to_ask = make_prompt(
                datasets[chosen_dataset],
                'datasets["' + chosen_dataset + '"]',
                question
            )
        
            # 2) OpenAI API 호출
            answer = run_request(
                question_to_ask,
                model,
                key=openai_key,
            )
        
            # 3) 기본 패키지 코드 + GPT 응답 코드 합치기
            pimer_code = (
                "import pandas as pd\nimport matplotlib.pyplot as plt\n"
                "fig,ax = plt.subplots(1,1,figsize=(10,4))\n"
                "ax.spines['top'].set_visible(False)\nax.spines['right'].set_visible(False)\n"
                "df=" + 'datasets["' + chosen_dataset + '"]' + ".copy()\n"
            )
            final_code = pimer_code + answer
        
            # 이전 figure 초기화
            plt.clf()
            # 코드 실행
            exec(final_code)
            # 현재 figure 객체 획득
            fig = plt.gcf()
            st.pyplot(fig)
        
profile
QA/QC 1기 김학열

0개의 댓글