Update app.py
Browse files
app.py
CHANGED
@@ -157,26 +157,48 @@ def upload_parquet(file_path: str) -> Tuple[str, str, str]:
|
|
157 |
# Parquet 파일 읽기
|
158 |
df = pd.read_parquet(file_path, engine='pyarrow')
|
159 |
|
160 |
-
# 데이터
|
161 |
-
if 'text' not in df.columns or 'label' not in df.columns:
|
162 |
-
return "필수 컬럼(text, label)이 없습니다.", "", ""
|
163 |
-
|
164 |
-
# 데이터 요약 정보 생성
|
165 |
data_info = {
|
166 |
"총 레코드 수": len(df),
|
167 |
-
"
|
168 |
-
"
|
|
|
169 |
}
|
170 |
|
171 |
-
#
|
172 |
-
|
173 |
-
|
174 |
-
-
|
175 |
-
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
180 |
# DataFrame을 JSON 문자열로 변환 (Q&A에서 사용)
|
181 |
parquet_json = df.to_json(orient='records', force_ascii=False)
|
182 |
|
@@ -184,6 +206,7 @@ def upload_parquet(file_path: str) -> Tuple[str, str, str]:
|
|
184 |
except Exception as e:
|
185 |
return f"Parquet 파일 업로드 중 오류가 발생했습니다: {str(e)}", "", ""
|
186 |
|
|
|
187 |
def respond(message: str, history: List[Dict[str, str]], system_message: str = "", max_tokens: int = 4000, temperature: float = 0.5, top_p: float = 0.9, parquet_data: str = None) -> str:
|
188 |
try:
|
189 |
if parquet_data:
|
@@ -191,25 +214,40 @@ def respond(message: str, history: List[Dict[str, str]], system_message: str = "
|
|
191 |
df = pd.read_json(io.StringIO(parquet_data))
|
192 |
|
193 |
# 데이터셋 컨텍스트 생성
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
194 |
data_context = f"""
|
195 |
현재 업로드된 데이터셋 정보:
|
196 |
- 총 {len(df)} 개의 레코드
|
197 |
-
-
|
198 |
-
|
199 |
|
200 |
-
|
201 |
-
{df.head(
|
202 |
"""
|
203 |
system_prompt = f"""당신은 업로드된 데이터셋을 분석하고 질문에 답변하는 AI 어시스턴트입니다.
|
204 |
|
205 |
주요 지침:
|
206 |
1. 반드시 한글로 답변할 것
|
207 |
-
2. 데이터셋의 내용을 기반으로 정확하게 답변할 것
|
208 |
3. 데이터에 없는 내용은 추측하지 말 것
|
209 |
4. ��변은 간단명료하게 할 것
|
210 |
5. 데이터 프라이버시를 고려하여 답변할 것
|
211 |
|
212 |
-
데이터셋
|
|
|
|
|
|
|
213 |
{data_context}
|
214 |
"""
|
215 |
else:
|
|
|
157 |
# Parquet 파일 읽기
|
158 |
df = pd.read_parquet(file_path, engine='pyarrow')
|
159 |
|
160 |
+
# 데이터 기본 정보 수집
|
|
|
|
|
|
|
|
|
161 |
data_info = {
|
162 |
"총 레코드 수": len(df),
|
163 |
+
"컬럼 목록": list(df.columns),
|
164 |
+
"데이터 타입": df.dtypes.to_dict(),
|
165 |
+
"결측치 정보": df.isnull().sum().to_dict()
|
166 |
}
|
167 |
|
168 |
+
# 데이터 요약 정보 생성
|
169 |
+
summary = []
|
170 |
+
summary.append(f"### 데이터셋 기본 정보:")
|
171 |
+
summary.append(f"- 총 레코드 수: {data_info['총 레코드 수']}")
|
172 |
+
summary.append(f"- 컬럼 목록: {', '.join(data_info['컬럼 목록'])}")
|
173 |
+
|
174 |
+
# 각 컬럼별 통계 정보 생성
|
175 |
+
summary.append("\n### 컬럼별 정보:")
|
176 |
+
for col in df.columns:
|
177 |
+
if df[col].dtype in ['int64', 'float64']:
|
178 |
+
# 수치형 데이터
|
179 |
+
stats = df[col].describe()
|
180 |
+
summary.append(f"\n{col} (수치형):")
|
181 |
+
summary.append(f"- 평균: {stats['mean']:.2f}")
|
182 |
+
summary.append(f"- 최소: {stats['min']}")
|
183 |
+
summary.append(f"- 최대: {stats['max']}")
|
184 |
+
elif df[col].dtype == 'object' or df[col].dtype == 'string':
|
185 |
+
# 문자열 데이터
|
186 |
+
unique_count = df[col].nunique()
|
187 |
+
summary.append(f"\n{col} (텍스트):")
|
188 |
+
summary.append(f"- 고유값 수: {unique_count}")
|
189 |
+
if unique_count < 10: # 고유값이 적은 경우만 표시
|
190 |
+
value_counts = df[col].value_counts().head(5)
|
191 |
+
summary.append("- 상위 5개 값:")
|
192 |
+
for val, count in value_counts.items():
|
193 |
+
summary.append(f" • {val}: {count}개")
|
194 |
+
|
195 |
+
# 미리보기 생성
|
196 |
+
preview = df.head(10).to_markdown(index=False)
|
197 |
+
summary.append("\n### 데이터 미리보기:")
|
198 |
+
summary.append(preview)
|
199 |
+
|
200 |
+
parquet_content = "\n".join(summary)
|
201 |
+
|
202 |
# DataFrame을 JSON 문자열로 변환 (Q&A에서 사용)
|
203 |
parquet_json = df.to_json(orient='records', force_ascii=False)
|
204 |
|
|
|
206 |
except Exception as e:
|
207 |
return f"Parquet 파일 업로드 중 오류가 발생했습니다: {str(e)}", "", ""
|
208 |
|
209 |
+
|
210 |
def respond(message: str, history: List[Dict[str, str]], system_message: str = "", max_tokens: int = 4000, temperature: float = 0.5, top_p: float = 0.9, parquet_data: str = None) -> str:
|
211 |
try:
|
212 |
if parquet_data:
|
|
|
214 |
df = pd.read_json(io.StringIO(parquet_data))
|
215 |
|
216 |
# 데이터셋 컨텍스트 생성
|
217 |
+
columns_info = []
|
218 |
+
for col in df.columns:
|
219 |
+
if df[col].dtype in ['int64', 'float64']:
|
220 |
+
col_type = "수치형"
|
221 |
+
stats = df[col].describe()
|
222 |
+
col_info = f"- {col} ({col_type}): 평균={stats['mean']:.2f}, 최소={stats['min']}, 최대={stats['max']}"
|
223 |
+
else:
|
224 |
+
col_type = "텍스트"
|
225 |
+
unique_count = df[col].nunique()
|
226 |
+
col_info = f"- {col} ({col_type}): 고유값 {unique_count}개"
|
227 |
+
columns_info.append(col_info)
|
228 |
+
|
229 |
data_context = f"""
|
230 |
현재 업로드된 데이터셋 정보:
|
231 |
- 총 {len(df)} 개의 레코드
|
232 |
+
- 컬럼 정보:
|
233 |
+
{chr(10).join(columns_info)}
|
234 |
|
235 |
+
샘플 데이터:
|
236 |
+
{df.head(20).to_string()}
|
237 |
"""
|
238 |
system_prompt = f"""당신은 업로드된 데이터셋을 분석하고 질문에 답변하는 AI 어시스턴트입니다.
|
239 |
|
240 |
주요 지침:
|
241 |
1. 반드시 한글로 답변할 것
|
242 |
+
2. 데이터셋의 실제 내용을 기반으로 정확하게 답변할 것
|
243 |
3. 데이터에 없는 내용은 추측하지 말 것
|
244 |
4. ��변은 간단명료하게 할 것
|
245 |
5. 데이터 프라이버시를 고려하여 답변할 것
|
246 |
|
247 |
+
데이터셋 구조 설명:
|
248 |
+
{chr(10).join(columns_info)}
|
249 |
+
|
250 |
+
참고할 데이터 샘플:
|
251 |
{data_context}
|
252 |
"""
|
253 |
else:
|