File size: 9,730 Bytes
1d355ad 093243b 27086b7 22032f3 d316372 22032f3 d316372 270bca0 a4f2fd9 27086b7 a4f2fd9 27086b7 270bca0 093243b 27086b7 39688bd 03d0703 a4f2fd9 e25f499 d316372 a4f2fd9 d316372 e25f499 df331ff a4f2fd9 df331ff a4f2fd9 093243b df331ff a4f2fd9 df331ff e25f499 d316372 093243b a4f2fd9 d316372 27086b7 d316372 27086b7 d316372 e25f499 093243b d316372 a4f2fd9 093243b a4f2fd9 093243b a4f2fd9 093243b a4f2fd9 093243b a4f2fd9 093243b d316372 093243b d316372 27086b7 093243b d316372 27086b7 a4f2fd9 df331ff e25f499 27086b7 d316372 093243b d316372 a4f2fd9 d316372 a4f2fd9 d316372 a4f2fd9 d316372 093243b 97b5115 a4f2fd9 d316372 093243b d316372 e25f499 d316372 e25f499 d316372 a4f2fd9 e25f499 a4f2fd9 d316372 093243b d316372 a4f2fd9 d316372 093243b d316372 093243b 97b5115 d316372 093243b 97b5115 d316372 a4f2fd9 df331ff a4f2fd9 df331ff a4f2fd9 093243b d316372 a4f2fd9 d316372 093243b a4f2fd9 d316372 093243b | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 | import os
import io
import streamlit as st
import google.generativeai as genai
import pandas as pd
from streamlit_extras.colored_header import colored_header
from streamlit_extras.add_vertical_space import add_vertical_space
# --- 1. 기본 설정 및 AI 구성 ---
st.set_page_config(layout="wide", page_title="AI 학습 데이터 만들기")
# Gemini API 키 설정
try:
genai.configure(api_key=st.secrets["GEMINI_API_KEY"])
except (KeyError, AttributeError):
st.error("🚨 GEMINI_API_KEY를 설정해주세요! (Streamlit secrets에 추가)")
st.stop()
# AI 모델 설정
generation_config = {
"temperature": 0.8, # 다변수 관계의 창의성을 위해 온도를 약간 높임
"top_p": 0.95,
"top_k": 40,
"max_output_tokens": 8192, # 더 많은 데이터와 변수를 처리하기 위해 확장
"response_mime_type": "text/plain",
}
model = genai.GenerativeModel(
model_name="gemini-1.5-flash",
generation_config=generation_config,
)
# --- 2. AI 프롬프트 (다변수 지원을 위해 대폭 개선) ---
MULTI_VARIABLE_PROMPT = """
당신은 현실적인 다변량 데이터를 시뮬레이션하는 데이터 과학자 AI입니다.
당신의 임무는 사용자가 제공한 여러 원인(X) 변수와 결과(Y) 변수들의 현실적인 관계를 고려하여, 머신러닝 회귀 분석 학습에 적합한 데이터를 **Markdown 테이블 형식**으로 생성하는 것입니다.
**사용자 입력:**
* 원인 (X 변수) 목록: "{x_names_str}"
* 결과 (Y 변수) 목록: "{y_names_str}"
* 생성할 데이터 개수: {num_rows}
**수행할 작업 (매우 중요):**
1. **현실적 다변량 관계 모델링:**
* 제공된 변수들 간의 **현실적인 상관관계**를 모델링합니다. 일부 X는 Y에 긍정적인 영향을, 다른 X는 부정적인 영향을 줄 수 있습니다.
* X 변수들 사이에도 자연스러운 상관관계가 존재할 수 있습니다. (예: '운동 시간'이 늘면 '수면의 질'도 좋아지는 경향)
2. **현실적 변동성 추가:** 관계가 완벽한 수학 공식이 아닌, 현실 데이터처럼 보이도록 적절한 무작위 변동성을 추가합니다.
3. **현실적 제약 조건 적용:** 각 변수의 의미를 고려하여 상한선(Maximum)과 하한선(Minimum)을 자연스럽게 적용합니다.
* 예를 들어, 변수 이름에 '점수', '만족도', '비율'이 포함되면 **결과값이 100을 넘지 않고, 0 미만이 되지 않도록** 데이터를 생성합니다.
* 변수 이름에 '시간', '비용', '노력' 등이 포함되면, 이 값이 커질수록 결과값의 상승폭이 점차 둔화되는 **'수확 체감(diminishing returns)' 현상**을 현실적으로 반영합니다.
4. **출력 형식 준수:** 결과는 **오직 Markdown 테이블 형식**으로만 출력합니다.
**출력 형식 (절대 변경 금지):**
* 첫 줄은 헤더 `{header_line}` 입니다.
* 두 번째 줄은 구분선 `{separator_line}` 입니다.
* 그 이후로는 `| 값1 | 값2 | ... |` 형식의 데이터 행을 {num_rows}개 만큼 생성합니다.
* 설명, 코드, ``` 등 다른 어떤 텍스트도 포함하지 마세요.
**현실적인 데이터 출력 예시 (규칙을 잘 따르는 예시):**
| 공부 시간 | 수면 시간 | 시험 점수 | 컨디션 점수 |
|---|---|---|---|
| 1.5 | 8.2 | 65.7 | 88.1 |
| 4.0 | 6.5 | 88.2 | 72.4 |
| 0.5 | 7.5 | 42.1 | 81.0 |
| 3.2 | 8.0 | 85.9 | 92.5 |
| 5.5 | 5.8 | 91.5 | 65.3 |
이제 아래 정보를 바탕으로 현실적인 제약 조건을 따른 Markdown 테이블을 생성해주세요.
"""
# --- 3. 핵심 기능 함수 ---
def generate_markdown_data(x_names, y_names, num_rows):
"""AI를 호출하여 다변량 Markdown 테이블 형식의 데이터를 받아오는 함수"""
all_vars = x_names + y_names
header_line = "| " + " | ".join(all_vars) + " |"
separator_line = "|---" * len(all_vars) + "|"
prompt = MULTI_VARIABLE_PROMPT.format(
x_names_str=", ".join(x_names),
y_names_str=", ".join(y_names),
num_rows=num_rows,
header_line=header_line,
separator_line=separator_line
)
try:
response = model.generate_content([prompt])
return response.text.strip()
except Exception as e:
st.error(f"AI 호출 중 오류가 발생했습니다: {e}")
return None
def parse_markdown_to_df(markdown_text):
"""Markdown 테이블 텍스트를 Pandas DataFrame으로 변환하는 함수"""
try:
# Markdown 테이블을 StringIO를 사용해 가상 파일처럼 읽어들임
# 이렇게 하면 pandas의 read_csv가 더 안정적으로 파싱할 수 있음
md_file = io.StringIO(markdown_text)
df = pd.read_csv(md_file, sep='|', skipinitialspace=True)
# 첫 번째와 마지막 열은 비어있으므로 제거
df = df.iloc[:, 1:-1]
# 헤더 공백 제거
df.columns = df.columns.str.strip()
# 데이터 타입 변환 및 정리
for col in df.columns:
# 첫 번째 행은 '---' 이므로 제거
df[col] = df[col].iloc[1:]
df[col] = pd.to_numeric(df[col].str.strip(), errors='coerce')
df.dropna(inplace=True)
df.reset_index(drop=True, inplace=True)
return df
except Exception as e:
st.error(f"생성된 데이터를 테이블로 변환하는 중 오류가 발생했습니다: {e}")
st.info("AI가 생성한 원본 데이터:")
st.text(markdown_text)
return None
# --- 4. Streamlit UI 구성 ---
colored_header(
label="🤖 나만의 AI 학습 데이터 만들기 (다변량 회귀용)",
description="AI가 여러 변수들의 복합적인 관계를 고려하여 '진짜 같은' 학습 데이터를 만들어줘요!",
color_name="blue-70",
)
add_vertical_space(1)
# 세션 상태 초기화
if 'generated_df' not in st.session_state:
st.session_state.generated_df = None
if 'markdown_output' not in st.session_state:
st.session_state.markdown_output = ""
# 입력 영역
st.subheader("1. 데이터 규칙 정하기")
col1, col2, col3 = st.columns([2, 2, 1])
with col1:
x_input_names_str = st.text_area(
"**원인(X) 변수 이름은?** (쉼표로 구분)",
value="공부 시간, 수면 시간, 주말 복습 횟수",
help="데이터의 원인이 되는 값의 이름들을 쉼표(,)로 구분하여 입력하세요."
)
with col2:
y_input_names_str = st.text_area(
"**결과(Y) 변수 이름은?** (쉼표로 구분)",
value="시험 점수, 과제 점수",
help="원인(X)에 따라 변하는 결과 값의 이름들을 쉼표(,)로 구분하여 입력하세요."
)
with col3:
num_data_rows = st.number_input(
"**데이터는 몇 개 만들까요?**",
min_value=10,
max_value=200,
value=50,
step=10,
help="AI를 학습시키려면 데이터가 충분해야 해요. 10개 이상을 추천해요!"
)
add_vertical_space(1)
generate_button = st.button("🚀 데이터 생성 시작!", type="primary", use_container_width=True)
add_vertical_space(2)
# 실행 및 결과 출력 영역
if generate_button:
# 입력값을 리스트로 변환
x_names_list = [name.strip() for name in x_input_names_str.split(',') if name.strip()]
y_names_list = [name.strip() for name in y_input_names_str.split(',') if name.strip()]
if not x_names_list or not y_names_list:
st.warning("⚠️ '원인(X) 변수'와 '결과(Y) 변수'를 하나 이상씩 입력해주세요!")
else:
with st.spinner("똑똑한 AI가 변수들의 복합적인 관계를 생각하며 데이터를 만들고 있어요... 🤖"):
markdown_data = generate_markdown_data(x_names_list, y_names_list, num_data_rows)
if markdown_data:
df = parse_markdown_to_df(markdown_data)
if df is not None and not df.empty:
st.session_state.generated_df = df
st.session_state.markdown_output = markdown_data
st.success("🎉 데이터 생성 완료! 아래에서 확인하고 다운로드하세요.")
else:
st.error("데이터 생성에 실패했어요. AI가 만든 데이터를 분석할 수 없는 것 같아요.")
st.session_state.generated_df = None
else:
st.error("AI가 데이터를 생성하지 못했어요. 잠시 후 다시 시도해주세요.")
st.session_state.generated_df = None
# 세션 상태에 저장된 데이터가 있으면 화면에 표시
if st.session_state.generated_df is not None:
df_to_show = st.session_state.generated_df
st.subheader("2. 생성된 데이터 미리보기")
st.dataframe(df_to_show)
st.subheader("3. 데이터 통계 요약")
st.markdown("생성된 데이터의 평균, 표준편차, 최소/최대값 등 기술 통계를 확인해보세요.")
st.dataframe(df_to_show.describe())
st.subheader("4. CSV 파일로 다운로드하기")
st.markdown("이 버튼을 눌러 위에 보이는 데이터를 CSV 파일로 컴퓨터에 저장하세요.")
csv = df_to_show.to_csv(index=False).encode('utf-8-sig')
st.download_button(
label="📥 CSV 파일 다운로드",
data=csv,
file_name="ai_generated_multivariable_data.csv",
mime="text/csv",
use_container_width=True
)
with st.expander("👀 AI가 생성한 원본 Markdown 텍스트가 궁금하다면?"):
st.text(st.session_state.markdown_output) |