ll7098ll commited on
Commit
a4f2fd9
·
verified ·
1 Parent(s): be2620e

Update app.py

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