ginipick commited on
Commit
10ec03b
ยท
verified ยท
1 Parent(s): 2834e16

Delete app-backup.py

Browse files
Files changed (1) hide show
  1. app-backup.py +0 -429
app-backup.py DELETED
@@ -1,429 +0,0 @@
1
- """
2
- AI ๊ธฐ๋ฐ˜ ์ƒ๊ถŒ ๋ถ„์„ ์‹œ์Šคํ…œ - Gradio ๋ฒ„์ „
3
- Dataset: https://huggingface.co/datasets/ginipick/market
4
- """
5
- import gradio as gr
6
- import pandas as pd
7
- import numpy as np
8
- from typing import Dict, List, Tuple
9
- import json
10
- from datasets import load_dataset
11
- import plotly.express as px
12
- import plotly.graph_objects as go
13
- import folium
14
- from folium.plugins import HeatMap
15
- import requests
16
-
17
- # ============================================================================
18
- # ๋ฐ์ดํ„ฐ ๋กœ๋” ํด๋ž˜์Šค
19
- # ============================================================================
20
-
21
- class MarketDataLoader:
22
- """ํ—ˆ๊น…ํŽ˜์ด์Šค ์ƒ๊ถŒ ๋ฐ์ดํ„ฐ ๋กœ๋”"""
23
-
24
- REGIONS = {
25
- '์„œ์šธ': '์„œ์šธ_202506', '๊ฒฝ๊ธฐ': '๊ฒฝ๊ธฐ_202506', '๋ถ€์‚ฐ': '๋ถ€์‚ฐ_202506',
26
- '๋Œ€๊ตฌ': '๋Œ€๊ตฌ_202506', '์ธ์ฒœ': '์ธ์ฒœ_202506', '๊ด‘์ฃผ': '๊ด‘์ฃผ_202506',
27
- '๋Œ€์ „': '๋Œ€์ „_202506', '์šธ์‚ฐ': '์šธ์‚ฐ_202506', '์„ธ์ข…': '์„ธ์ข…_202506',
28
- '๊ฒฝ๋‚จ': '๊ฒฝ๋‚จ_202506', '๊ฒฝ๋ถ': '๊ฒฝ๋ถ_202506', '์ „๋‚จ': '์ „๋‚จ_202506',
29
- '์ „๋ถ': '์ „๋ถ_202506', '์ถฉ๋‚จ': '์ถฉ๋‚จ_202506', '์ถฉ๋ถ': '์ถฉ๋ถ_202506',
30
- '๊ฐ•์›': '๊ฐ•์›_202506', '์ œ์ฃผ': '์ œ์ฃผ_202506'
31
- }
32
-
33
- @staticmethod
34
- def load_region_data(region: str, sample_size: int = 30000) -> pd.DataFrame:
35
- """์ง€์—ญ๋ณ„ ๋ฐ์ดํ„ฐ ๋กœ๋“œ"""
36
- try:
37
- file_name = f"์†Œ์ƒ๊ณต์ธ์‹œ์žฅ์ง„ํฅ๊ณต๋‹จ_์ƒ๊ฐ€(์ƒ๊ถŒ)์ •๋ณด_{MarketDataLoader.REGIONS[region]}.csv"
38
- dataset = load_dataset("ginipick/market", data_files=file_name, split="train")
39
- df = dataset.to_pandas()
40
-
41
- if len(df) > sample_size:
42
- df = df.sample(n=sample_size, random_state=42)
43
-
44
- return df
45
- except Exception as e:
46
- print(f"๋ฐ์ดํ„ฐ ๋กœ๋“œ ์‹คํŒจ: {str(e)}")
47
- return pd.DataFrame()
48
-
49
- @staticmethod
50
- def load_multiple_regions(regions: List[str], sample_per_region: int = 30000) -> pd.DataFrame:
51
- """์—ฌ๋Ÿฌ ์ง€์—ญ ๋ฐ์ดํ„ฐ ๋กœ๋“œ"""
52
- dfs = []
53
- for region in regions:
54
- df = MarketDataLoader.load_region_data(region, sample_per_region)
55
- if not df.empty:
56
- dfs.append(df)
57
-
58
- if dfs:
59
- return pd.concat(dfs, ignore_index=True)
60
- return pd.DataFrame()
61
-
62
-
63
- # ============================================================================
64
- # ์ƒ๊ถŒ ๋ถ„์„ ํด๋ž˜์Šค
65
- # ============================================================================
66
-
67
- class MarketAnalyzer:
68
- """์ƒ๊ถŒ ๋ฐ์ดํ„ฐ ๋ถ„์„ ์—”์ง„"""
69
-
70
- def __init__(self, df: pd.DataFrame):
71
- self.df = df
72
- self.prepare_data()
73
-
74
- def prepare_data(self):
75
- """๋ฐ์ดํ„ฐ ์ „์ฒ˜๋ฆฌ"""
76
- if '๊ฒฝ๋„' in self.df.columns:
77
- self.df['๊ฒฝ๋„'] = pd.to_numeric(self.df['๊ฒฝ๋„'], errors='coerce')
78
- if '์œ„๋„' in self.df.columns:
79
- self.df['์œ„๋„'] = pd.to_numeric(self.df['์œ„๋„'], errors='coerce')
80
- self.df = self.df.dropna(subset=['๊ฒฝ๋„', '์œ„๋„'])
81
-
82
- def get_top_insights(self, n: int = 10) -> List[Dict]:
83
- """์ƒ์œ„ ์ธ์‚ฌ์ดํŠธ ์ถ”์ถœ"""
84
- insights = []
85
-
86
- # 1. ์—…์ข…๋ณ„ ์ ํฌ ์ˆ˜
87
- if '์ƒ๊ถŒ์—…์ข…์ค‘๋ถ„๋ฅ˜๋ช…' in self.df.columns:
88
- top_categories = self.df['์ƒ๊ถŒ์—…์ข…์ค‘๋ถ„๋ฅ˜๋ช…'].value_counts().head(n)
89
- fig = px.bar(x=top_categories.index, y=top_categories.values,
90
- labels={'x': '์—…์ข…', 'y': '์ ํฌ ์ˆ˜'},
91
- title='๐Ÿ† ์ƒ์œ„ ์—…์ข… Top 10')
92
- insights.append(('bar', fig, f"์ „์ฒด {len(self.df):,}๊ฐœ ์ ํฌ ์ค‘ ์ƒ์œ„ ์—…์ข…"))
93
-
94
- # 2. ์ง€์—ญ๋ณ„ ๋ถ„ํฌ
95
- if '์‹œ๋„๋ช…' in self.df.columns:
96
- region_counts = self.df['์‹œ๋„๋ช…'].value_counts()
97
- fig = px.pie(values=region_counts.values, names=region_counts.index,
98
- title='๐Ÿ“ ์ง€์—ญ๋ณ„ ์ ํฌ ๋ถ„ํฌ', hole=0.3)
99
- insights.append(('pie', fig, '์ „๊ตญ ์ง€์—ญ๋ณ„ ์ƒ๊ถŒ ๋ถ„ํฌ๋„'))
100
-
101
- # 3. ์‹œ๊ตฐ๊ตฌ๋ณ„
102
- if '์‹œ๊ตฐ๊ตฌ๋ช…' in self.df.columns:
103
- district_counts = self.df['์‹œ๊ตฐ๊ตฌ๋ช…'].value_counts().head(15)
104
- fig = px.bar(x=district_counts.index, y=district_counts.values,
105
- labels={'x': '์‹œ๊ตฐ๊ตฌ', 'y': '์ ํฌ ์ˆ˜'},
106
- title='๐ŸŒ† ์‹œ๊ตฐ๊ตฌ๋ณ„ ์ƒ๊ถŒ ๋ฐ€์ง‘๋„')
107
- insights.append(('bar', fig, '์ ํฌ๊ฐ€ ๊ฐ€์žฅ ๋งŽ์€ ์‹œ๊ตฐ๊ตฌ'))
108
-
109
- # 4. ์ธต๋ณ„ ๋ถ„ํฌ
110
- if '์ธต์ •๋ณด' in self.df.columns:
111
- floor_counts = self.df['์ธต์ •๋ณด'].value_counts().head(10)
112
- fig = px.bar(x=floor_counts.index, y=floor_counts.values,
113
- labels={'x': '์ธต', 'y': '์ ํฌ ์ˆ˜'},
114
- title='๐Ÿข ์ธต๋ณ„ ์ ํฌ ๋ถ„ํฌ')
115
- insights.append(('bar', fig, '1์ธต์ด ๊ฐ€์žฅ ์„ ํ˜ธ๋˜๋Š” ์ธต'))
116
-
117
- # 5. ํ”„๋žœ์ฐจ์ด์ฆˆ
118
- if '์ƒํ˜ธ๋ช…' in self.df.columns:
119
- franchise_keywords = ['์Šคํƒ€๋ฒ…์Šค', 'CU', 'GS25', '์„ธ๋ธ์ผ๋ ˆ๋ธ', '์ด๋งˆํŠธ24',
120
- '๋งฅ๋„๋‚ ๋“œ', 'BBQ', '๊ต์ดŒ', '๋ฒ„๊ฑฐํ‚น', '๋กฏ๋ฐ๋ฆฌ์•„']
121
- franchise_data = {}
122
- for keyword in franchise_keywords:
123
- count = self.df['์ƒํ˜ธ๋ช…'].str.contains(keyword, case=False, na=False).sum()
124
- if count > 0:
125
- franchise_data[keyword] = count
126
-
127
- if franchise_data:
128
- fig = px.bar(x=list(franchise_data.keys()), y=list(franchise_data.values()),
129
- labels={'x': '๋ธŒ๋žœ๋“œ', 'y': '์ ํฌ ์ˆ˜'},
130
- title='๐Ÿช ์ฃผ์š” ํ”„๋žœ์ฐจ์ด์ฆˆ ์ ํฌ ์ˆ˜')
131
- insights.append(('bar', fig, '์ „๊ตญ ์ฃผ์š” ํ”„๋žœ์ฐจ์ด์ฆˆ ๋ถ„ํฌ'))
132
-
133
- return insights[:5] # ์ƒ์œ„ 5๊ฐœ๋งŒ
134
-
135
- def create_density_map(self, sample_size: int = 1000) -> str:
136
- """์ ํฌ ๋ฐ€์ง‘๋„ ์ง€๋„ ์ƒ์„ฑ (HTML ๋ฐ˜ํ™˜)"""
137
- df_sample = self.df.sample(n=min(sample_size, len(self.df)), random_state=42)
138
-
139
- center_lat = df_sample['์œ„๋„'].mean()
140
- center_lon = df_sample['๊ฒฝ๋„'].mean()
141
-
142
- m = folium.Map(location=[center_lat, center_lon], zoom_start=11, tiles='OpenStreetMap')
143
- heat_data = [[row['์œ„๋„'], row['๊ฒฝ๋„']] for _, row in df_sample.iterrows()]
144
- HeatMap(heat_data, radius=15, blur=25, max_zoom=13).add_to(m)
145
-
146
- return m._repr_html_()
147
-
148
- def analyze_for_llm(self) -> Dict:
149
- """LLM ์ปจํ…์ŠคํŠธ์šฉ ๋ถ„์„ ๋ฐ์ดํ„ฐ"""
150
- context = {
151
- '์ด_์ ํฌ_์ˆ˜': len(self.df),
152
- '์ง€์—ญ_์ˆ˜': self.df['์‹œ๋„๋ช…'].nunique() if '์‹œ๋„๋ช…' in self.df.columns else 0,
153
- '์—…์ข…_์ˆ˜': self.df['์ƒ๊ถŒ์—…์ข…์ค‘๋ถ„๋ฅ˜๋ช…'].nunique() if '์ƒ๊ถŒ์—…์ข…์ค‘๋ถ„๋ฅ˜๋ช…' in self.df.columns else 0,
154
- }
155
-
156
- if '์ƒ๊ถŒ์—…์ข…์ค‘๋ถ„๋ฅ˜๋ช…' in self.df.columns:
157
- context['์ƒ์œ„_์—…์ข…_5'] = self.df['์ƒ๊ถŒ์—…์ข…์ค‘๋ถ„๋ฅ˜๋ช…'].value_counts().head(5).to_dict()
158
-
159
- return context
160
-
161
-
162
- # ============================================================================
163
- # LLM ์ฟผ๋ฆฌ ํ”„๋กœ์„ธ์„œ
164
- # ============================================================================
165
-
166
- class LLMQueryProcessor:
167
- """Fireworks AI ๊ธฐ๋ฐ˜ ์ž์—ฐ์–ด ์ฒ˜๋ฆฌ"""
168
-
169
- def __init__(self, api_key: str):
170
- self.api_key = api_key
171
- self.base_url = "https://api.fireworks.ai/inference/v1/chat/completions"
172
-
173
- def process_query(self, query: str, data_context: Dict, chat_history: List = None) -> str:
174
- """์ž์—ฐ์–ด ์ฟผ๋ฆฌ ์ฒ˜๋ฆฌ"""
175
- system_prompt = f"""๋‹น์‹ ์€ ํ•œ๊ตญ ์ƒ๊ถŒ ๋ฐ์ดํ„ฐ ๋ถ„์„ ์ „๋ฌธ๊ฐ€์ž…๋‹ˆ๋‹ค.
176
-
177
- ๐Ÿ“Š **ํ˜„์žฌ ๋ถ„์„ ๋ฐ์ดํ„ฐ**
178
- {json.dumps(data_context, ensure_ascii=False, indent=2)}
179
-
180
- ๊ตฌ์ฒด์ ์ธ ์ˆซ์ž์™€ ๋น„์œจ๋กœ ์ •๋Ÿ‰์  ๋ถ„์„์„ ์ œ๊ณตํ•˜์„ธ์š”.
181
- ์ฐฝ์—…, ํˆฌ์ž, ๊ฒฝ์Ÿ ๋ถ„์„ ๊ด€์ ์—์„œ ์‹ค์šฉ์  ์ธ์‚ฌ์ดํŠธ๋ฅผ ์ œ๊ณตํ•˜์„ธ์š”."""
182
-
183
- messages = [{"role": "system", "content": system_prompt}]
184
- if chat_history:
185
- messages.extend(chat_history[-6:])
186
- messages.append({"role": "user", "content": query})
187
-
188
- payload = {
189
- "model": "accounts/fireworks/models/qwen3-235b-a22b-instruct-2507",
190
- "max_tokens": 2000,
191
- "temperature": 0.7,
192
- "messages": messages
193
- }
194
-
195
- headers = {
196
- "Authorization": f"Bearer {self.api_key}",
197
- "Content-Type": "application/json"
198
- }
199
-
200
- try:
201
- response = requests.post(self.base_url, headers=headers, json=payload, timeout=30)
202
- if response.status_code == 200:
203
- return response.json()['choices'][0]['message']['content']
204
- else:
205
- return f"โš ๏ธ API ์˜ค๋ฅ˜: {response.status_code}"
206
- except Exception as e:
207
- return f"โŒ ์˜ค๋ฅ˜: {str(e)}"
208
-
209
-
210
- # ============================================================================
211
- # ์ „์—ญ ์ƒํƒœ
212
- # ============================================================================
213
-
214
- class AppState:
215
- def __init__(self):
216
- self.analyzer = None
217
- self.llm_processor = None
218
- self.chat_history = []
219
-
220
- app_state = AppState()
221
-
222
-
223
- # ============================================================================
224
- # Gradio ์ธํ„ฐํŽ˜์ด์Šค ํ•จ์ˆ˜
225
- # ============================================================================
226
-
227
- def load_data(regions):
228
- """๋ฐ์ดํ„ฐ ๋กœ๋“œ"""
229
- if not regions:
230
- return "โŒ ์ตœ์†Œ 1๊ฐœ ์ง€์—ญ์„ ์„ ํƒํ•ด์ฃผ์„ธ์š”!", None, None, None
231
-
232
- try:
233
- df = MarketDataLoader.load_multiple_regions(regions, sample_per_region=30000)
234
- if df.empty:
235
- return "โŒ ๋ฐ์ดํ„ฐ ๋กœ๋“œ ์‹คํŒจ!", None, None, None
236
-
237
- app_state.analyzer = MarketAnalyzer(df)
238
-
239
- # ๊ธฐ๋ณธ ํ†ต๊ณ„
240
- stats = f"""
241
- โœ… **๋ฐ์ดํ„ฐ ๋กœ๋“œ ์™„๋ฃŒ!**
242
-
243
- ๐Ÿ“Š **ํ†ต๊ณ„**
244
- - ์ด ์ ํฌ: {len(df):,}๊ฐœ
245
- - ๋ถ„์„ ์ง€์—ญ: {', '.join(regions)}
246
- - ์—…์ข… ์ˆ˜: {df['์ƒ๊ถŒ์—…์ข…์ค‘๋ถ„๋ฅ˜๋ช…'].nunique()}๊ฐœ
247
- """
248
-
249
- return stats, gr.update(visible=True), gr.update(visible=True), gr.update(visible=True)
250
- except Exception as e:
251
- return f"โŒ ์˜ค๋ฅ˜: {str(e)}", None, None, None
252
-
253
-
254
- def generate_insights():
255
- """์ธ์‚ฌ์ดํŠธ ์ƒ์„ฑ"""
256
- if app_state.analyzer is None:
257
- return [None] * 6
258
-
259
- insights = app_state.analyzer.get_top_insights(5)
260
- map_html = app_state.analyzer.create_density_map(sample_size=2000)
261
-
262
- result = [map_html]
263
- for _, fig, _ in insights:
264
- result.append(fig)
265
-
266
- # ๋ถ€์กฑํ•œ ์ฐจํŠธ๋Š” None์œผ๋กœ ์ฑ„์šฐ๊ธฐ
267
- while len(result) < 6:
268
- result.append(None)
269
-
270
- return result[:6]
271
-
272
-
273
- def chat_respond(message, api_key, history):
274
- """์ฑ—๋ด‡ ์‘๋‹ต"""
275
- if app_state.analyzer is None:
276
- return history + [[message, "โŒ ๋จผ์ € ๋ฐ์ดํ„ฐ๋ฅผ ๋กœ๋“œํ•ด์ฃผ์„ธ์š”!"]]
277
-
278
- data_context = app_state.analyzer.analyze_for_llm()
279
-
280
- if api_key:
281
- if app_state.llm_processor is None or app_state.llm_processor.api_key != api_key:
282
- app_state.llm_processor = LLMQueryProcessor(api_key)
283
-
284
- chat_hist = []
285
- for user_msg, bot_msg in history:
286
- chat_hist.append({"role": "user", "content": user_msg})
287
- chat_hist.append({"role": "assistant", "content": bot_msg})
288
-
289
- response = app_state.llm_processor.process_query(message, data_context, chat_hist)
290
- else:
291
- # ๊ธฐ๋ณธ ํ†ต๊ณ„
292
- response = f"""๐Ÿ“Š **๊ธฐ๋ณธ ๋ฐ์ดํ„ฐ ๋ถ„์„ ๊ฒฐ๊ณผ**
293
-
294
- **์ „์ฒด ํ˜„ํ™ฉ**
295
- - ์ด ์ ํฌ ์ˆ˜: {data_context['์ด_์ ํฌ_์ˆ˜']:,}๊ฐœ
296
- - ์—…์ข… ์ข…๋ฅ˜: {data_context['์—…์ข…_์ˆ˜']}๊ฐœ
297
-
298
- ๐Ÿ’ก API ํ‚ค๋ฅผ ์ž…๋ ฅํ•˜๋ฉด ๋” ์ƒ์„ธํ•œ AI ๋ถ„์„์„ ๋ฐ›์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค!"""
299
-
300
- history.append([message, response])
301
- return history
302
-
303
-
304
- # ============================================================================
305
- # Gradio UI
306
- # ============================================================================
307
-
308
- with gr.Blocks(title="AI ์ƒ๊ถŒ ๋ถ„์„ ์‹œ์Šคํ…œ", theme=gr.themes.Soft()) as demo:
309
- gr.Markdown("""
310
- # ๐Ÿช AI ์ƒ๊ถŒ ๋ถ„์„ ์‹œ์Šคํ…œ
311
- *์ „๊ตญ ์ƒ๊ฐ€(์ƒ๊ถŒ) ๋ฐ์ดํ„ฐ ๊ธฐ๋ฐ˜ ์‹ค์‹œ๊ฐ„ ๋ถ„์„ | Powered by Fireworks AI*
312
- """)
313
-
314
- with gr.Row():
315
- with gr.Column(scale=1):
316
- gr.Markdown("### โš™๏ธ ์„ค์ •")
317
-
318
- api_key_input = gr.Textbox(
319
- label="๐Ÿ”‘ Fireworks AI API Key (์„ ํƒ)",
320
- type="password",
321
- placeholder="API ํ‚ค๋ฅผ ์ž…๋ ฅํ•˜์„ธ์š”"
322
- )
323
-
324
- region_select = gr.CheckboxGroup(
325
- choices=list(MarketDataLoader.REGIONS.keys()),
326
- value=['์„œ์šธ'],
327
- label="๐Ÿ“ ๋ถ„์„ ์ง€์—ญ ์„ ํƒ (์ตœ๋Œ€ 5๊ฐœ ๊ถŒ์žฅ)"
328
- )
329
-
330
- load_btn = gr.Button("๐Ÿ“Š ๋ฐ์ดํ„ฐ ๋กœ๋“œ", variant="primary", size="lg")
331
-
332
- status_box = gr.Markdown("๐Ÿ‘ˆ ์ง€์—ญ์„ ์„ ํƒํ•˜๊ณ  ๋ฐ์ดํ„ฐ๋ฅผ ๋กœ๋“œํ•˜์„ธ์š”!")
333
-
334
- with gr.Column(scale=3):
335
- with gr.Tabs() as tabs:
336
- with gr.Tab("๐Ÿ“Š ์ธ์‚ฌ์ดํŠธ ๋Œ€์‹œ๋ณด๋“œ", id=0) as tab1:
337
- insights_content = gr.Column(visible=False)
338
-
339
- with insights_content:
340
- gr.Markdown("### ๐Ÿ—บ๏ธ ์ ํฌ ๋ฐ€์ง‘๋„ ํžˆํŠธ๋งต")
341
- map_output = gr.HTML()
342
-
343
- gr.Markdown("---")
344
- gr.Markdown("### ๐Ÿ“ˆ ์ƒ๊ถŒ ์ธ์‚ฌ์ดํŠธ")
345
-
346
- chart1 = gr.Plot(label="์ธ์‚ฌ์ดํŠธ 1")
347
- chart2 = gr.Plot(label="์ธ์‚ฌ์ดํŠธ 2")
348
- chart3 = gr.Plot(label="์ธ์‚ฌ์ดํŠธ 3")
349
- chart4 = gr.Plot(label="์ธ์‚ฌ์ดํŠธ 4")
350
- chart5 = gr.Plot(label="์ธ์‚ฌ์ดํŠธ 5")
351
-
352
- with gr.Tab("๐Ÿค– AI ๋ถ„์„ ์ฑ—๋ด‡", id=1) as tab2:
353
- chat_content = gr.Column(visible=False)
354
-
355
- with chat_content:
356
- gr.Markdown("""
357
- ### ๐Ÿ’ก ์ƒ˜ํ”Œ ์งˆ๋ฌธ
358
- ๊ฐ•๋‚จ์—์„œ ์นดํŽ˜ ์ฐฝ์—…? | ์น˜ํ‚จ์ง‘ ํฌํ™” ์ง€์—ญ? | 1์ธต์ด ์œ ๋ฆฌํ•œ ์—…์ข…? | ํ”„๋žœ์ฐจ์ด์ฆˆ ์ ์œ ์œจ?
359
- """)
360
-
361
- chatbot = gr.Chatbot(height=400, label="AI ์ƒ๊ถŒ ๋ถ„์„ ์–ด์‹œ์Šคํ„ดํŠธ")
362
-
363
- with gr.Row():
364
- msg_input = gr.Textbox(
365
- placeholder="๋ฌด์—‡์ด๋“  ๋ฌผ์–ด๋ณด์„ธ์š”! (์˜ˆ: ๊ฐ•๋‚จ์—์„œ ์นดํŽ˜ ์ฐฝ์—…ํ•˜๋ ค๋ฉด?)",
366
- show_label=False,
367
- scale=4
368
- )
369
- submit_btn = gr.Button("์ „์†ก", variant="primary", scale=1)
370
-
371
- # ์ƒ˜ํ”Œ ๋ฒ„ํŠผ๋“ค
372
- with gr.Row():
373
- sample_btn1 = gr.Button("๊ฐ•๋‚จ์—์„œ ์นดํŽ˜ ์ฐฝ์—…?", size="sm")
374
- sample_btn2 = gr.Button("์น˜ํ‚จ์ง‘ ํฌํ™” ์ง€์—ญ?", size="sm")
375
- sample_btn3 = gr.Button("1์ธต์ด ์œ ๋ฆฌํ•œ ์—…์ข…?", size="sm")
376
- sample_btn4 = gr.Button("ํ”„๋žœ์ฐจ์ด์ฆˆ ์ ์œ ์œจ?", size="sm")
377
-
378
- # ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ
379
- load_btn.click(
380
- fn=load_data,
381
- inputs=[region_select],
382
- outputs=[status_box, insights_content, chat_content, tab1]
383
- ).then(
384
- fn=generate_insights,
385
- outputs=[map_output, chart1, chart2, chart3, chart4, chart5]
386
- )
387
-
388
- # ์ฑ—๋ด‡ ์ด๋ฒคํŠธ
389
- submit_btn.click(
390
- fn=chat_respond,
391
- inputs=[msg_input, api_key_input, chatbot],
392
- outputs=[chatbot]
393
- ).then(
394
- fn=lambda: "",
395
- outputs=[msg_input]
396
- )
397
-
398
- msg_input.submit(
399
- fn=chat_respond,
400
- inputs=[msg_input, api_key_input, chatbot],
401
- outputs=[chatbot]
402
- ).then(
403
- fn=lambda: "",
404
- outputs=[msg_input]
405
- )
406
-
407
- # ์ƒ˜ํ”Œ ๋ฒ„ํŠผ ์ด๋ฒคํŠธ
408
- for btn, text in [
409
- (sample_btn1, "๊ฐ•๋‚จ์—์„œ ์นดํŽ˜ ์ฐฝ์—…?"),
410
- (sample_btn2, "์น˜ํ‚จ์ง‘ ํฌํ™” ์ง€์—ญ?"),
411
- (sample_btn3, "1์ธต์ด ์œ ๋ฆฌํ•œ ์—…์ข…?"),
412
- (sample_btn4, "ํ”„๋žœ์ฐจ์ด์ฆˆ ์ ์œ ์œจ?")
413
- ]:
414
- btn.click(
415
- fn=lambda t=text, h=chatbot: chat_respond(t, api_key_input.value, h.value or []),
416
- outputs=[chatbot]
417
- )
418
-
419
- gr.Markdown("""
420
- ---
421
- ### ๐Ÿ“– ์‚ฌ์šฉ ๊ฐ€์ด๋“œ
422
- 1. API ํ‚ค ์ž…๋ ฅ (์„ ํƒ) โ†’ 2. ์ง€์—ญ ์„ ํƒ โ†’ 3. ๋ฐ์ดํ„ฐ ๋กœ๋“œ โ†’ 4. ์ธ์‚ฌ์ดํŠธ ํ™•์ธ ๋˜๋Š” AI์—๊ฒŒ ์งˆ๋ฌธ
423
-
424
- ๐Ÿ’ก **Tip**: API ํ‚ค ์—†์ด๋„ ๊ธฐ๋ณธ ํ†ต๊ณ„๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค!
425
- """)
426
-
427
- # ์‹คํ–‰
428
- if __name__ == "__main__":
429
- demo.launch(server_name="0.0.0.0", server_port=7860, share=False)