alwaysgood commited on
Commit
1f8af00
·
verified ·
1 Parent(s): 49f74c3

Update ui.py

Browse files
Files changed (1) hide show
  1. ui.py +126 -164
ui.py CHANGED
@@ -12,6 +12,34 @@ from api_utils import (
12
  api_compare_stations,
13
  api_health_check
14
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
 
16
  def create_ui(prediction_handler, chatbot_handler):
17
  """Gradio UI를 생성하고 반환합니다."""
@@ -64,213 +92,147 @@ def create_ui(prediction_handler, chatbot_handler):
64
 
65
  # 3. API 탭 (새로 추가)
66
  with gr.TabItem("🔌 API"):
67
- gr.Markdown("""
68
- ## RESTful API 엔드포인트
69
- 실무에서 바로 사용 가능한 API 기능을 제공합니다.
70
- """)
71
 
72
  with gr.Tabs():
73
- # 3-1. 현재 조위
74
- with gr.TabItem("현재 조위"):
 
75
  with gr.Row():
76
- with gr.Column():
77
- gr.Markdown("### 특정 시간 조위 조회")
78
- api1_station = gr.Dropdown(
79
- choices=[(f"{STATION_NAMES[s]} ({s})", s) for s in STATIONS],
80
- label="관측소",
81
- value="DT_0001"
82
- )
83
- api1_time = gr.Textbox(
84
- label="조회 시간 (비워두면 현재)",
85
- placeholder="2024-12-25T15:00:00"
86
- )
87
- api1_fallback = gr.Checkbox(
88
- label="조화 예측 폴백 사용",
89
- value=True
90
- )
91
- api1_btn = gr.Button("조회")
92
-
93
- with gr.Column():
94
  api1_output = gr.JSON(label="API 응답")
95
 
96
  api1_btn.click(
97
- fn=lambda s, t, f: api_get_tide_level(s, t if t else None, f),
98
- inputs=[api1_station, api1_time, api1_fallback],
99
- outputs=api1_output,
100
- api_name="tide_level"
101
  )
102
-
 
 
 
 
 
 
103
  # 3-2. 시계열 데이터
104
  with gr.TabItem("시계열"):
 
105
  with gr.Row():
106
- with gr.Column():
107
- gr.Markdown("### 시간대별 조위 데이터")
108
- api2_station = gr.Dropdown(
109
- choices=[(f"{STATION_NAMES[s]} ({s})", s) for s in STATIONS],
110
- label="관측소",
111
- value="DT_0001"
112
- )
113
- api2_start = gr.Textbox(
114
- label="시작 시간",
115
- placeholder="2024-12-25T00:00:00"
116
- )
117
- api2_end = gr.Textbox(
118
- label="종료 시간",
119
- placeholder="2024-12-26T00:00:00"
120
- )
121
- api2_interval = gr.Number(
122
- label="간격(분)",
123
- value=60,
124
- minimum=5,
125
- maximum=360
126
- )
127
- api2_btn = gr.Button("조회")
128
-
129
- with gr.Column():
130
- api2_output = gr.JSON(label="API 응답 (공공 API 형식)")
131
 
132
  api2_btn.click(
133
- fn=lambda s, st, et, i: api_get_tide_series(
134
- s, st if st else None, et if et else None, int(i)
135
- ),
136
  inputs=[api2_station, api2_start, api2_end, api2_interval],
137
- outputs=api2_output,
138
- api_name="tide_series"
139
  )
140
-
 
 
 
 
 
 
141
  # 3-3. 만조/간조
142
  with gr.TabItem("만조/간조"):
 
143
  with gr.Row():
144
- with gr.Column():
145
- gr.Markdown("### 만조/간조 정보")
146
- api3_station = gr.Dropdown(
147
- choices=[(f"{STATION_NAMES[s]} ({s})", s) for s in STATIONS],
148
- label="관측소",
149
- value="DT_0001"
150
- )
151
- api3_date = gr.Textbox(
152
- label="날짜 (YYYY-MM-DD)",
153
- placeholder=datetime.now().strftime("%Y-%m-%d")
154
- )
155
- api3_secondary = gr.Checkbox(
156
- label="부차 만조/간조 포함",
157
- value=False
158
- )
159
- api3_btn = gr.Button("조회")
160
-
161
- with gr.Column():
162
  api3_output = gr.JSON(label="만조/간조 정보")
163
 
164
  api3_btn.click(
165
- fn=lambda s, d, sec: api_get_extremes_info(
166
- s, d if d else None, sec
167
- ),
168
  inputs=[api3_station, api3_date, api3_secondary],
169
- outputs=api3_output,
170
- api_name="extremes"
171
  )
172
-
173
- # 3-4. 위험 수위
 
 
 
 
 
 
174
  with gr.TabItem("위험 알림"):
 
175
  with gr.Row():
176
- with gr.Column():
177
- gr.Markdown("### 위험 수위 체크")
178
- api4_station = gr.Dropdown(
179
- choices=[(f"{STATION_NAMES[s]} ({s})", s) for s in STATIONS],
180
- label="관측소",
181
- value="DT_0001"
182
- )
183
- api4_hours = gr.Number(
184
- label="확인 시간(시간)",
185
- value=24,
186
- minimum=1,
187
- maximum=72
188
- )
189
- api4_warning = gr.Number(
190
- label="주의 수위(cm)",
191
- value=700
192
- )
193
- api4_danger = gr.Number(
194
- label="경고 수위(cm)",
195
- value=750
196
- )
197
- api4_btn = gr.Button("체크")
198
-
199
- with gr.Column():
200
  api4_output = gr.JSON(label="위험 수위 정보")
201
 
202
  api4_btn.click(
203
- fn=lambda s, h, w, d: api_check_tide_alert(s, int(h), w, d),
204
  inputs=[api4_station, api4_hours, api4_warning, api4_danger],
205
- outputs=api4_output,
206
- api_name="alert"
207
  )
208
-
 
 
 
 
 
 
209
  # 3-5. 관측소 비교
210
  with gr.TabItem("비교"):
 
211
  with gr.Row():
212
- with gr.Column():
213
- gr.Markdown("### 다중 관측소 비교")
214
- api5_stations = gr.CheckboxGroup(
215
- choices=[(f"{STATION_NAMES[s]}", s) for s in STATIONS],
216
- label="비교할 관측소 선택",
217
- value=["DT_0001", "DT_0002", "DT_0003"]
218
- )
219
- api5_time = gr.Textbox(
220
- label="비교 시간 (비워두면 현재)",
221
- placeholder="2024-12-25T15:00:00"
222
- )
223
- api5_btn = gr.Button("비교")
224
-
225
- with gr.Column():
226
  api5_output = gr.JSON(label="비교 결과")
227
 
228
  api5_btn.click(
229
- fn=lambda s, t: api_compare_stations(s, t if t else None),
230
  inputs=[api5_stations, api5_time],
231
- outputs=api5_output,
232
- api_name="compare"
233
  )
234
-
 
 
 
 
 
 
235
  # 3-6. 상태 체크
236
  with gr.TabItem("상태"):
237
- gr.Markdown("### API 및 시스템 상태")
238
- api6_btn = gr.Button("🔍 상태 확인", variant="secondary")
239
- api6_output = gr.JSON(label="시스템 상태")
 
240
 
241
  api6_btn.click(
242
- fn=api_health_check,
243
  inputs=[],
244
- outputs=api6_output,
245
- api_name="health"
 
 
 
 
 
246
  )
247
-
248
- # API 사용 안내
249
- gr.Markdown("""
250
- ---
251
- ### 📚 API 사용 안내
252
-
253
- **Python 예제:**
254
- ```python
255
- from gradio_client import Client
256
-
257
- client = Client("https://your-space.hf.space/")
258
-
259
- # 현재 조위 조회
260
- result = client.predict(
261
- "DT_0001", # station_id
262
- "", # time (empty = current)
263
- True, # use_fallback
264
- api_name="/tide_level"
265
- )
266
- ```
267
-
268
- **특징:**
269
- - 🔄 **조화 예측 폴백**: 최종 예측이 없을 때 자동으로 조화 예측 사용
270
- - 📊 **공공 API 호환**: 기상청 API와 유사한 응답 형식
271
- - ⚠️ **위험 수위 알림**: 2단계 경보 시스템
272
- - 🏢 **다중 관측소**: 여러 관측소 동시 비교
273
- """)
274
 
275
  # 이벤트 핸들러 연결
276
  predict_btn.click(
 
12
  api_compare_stations,
13
  api_health_check
14
  )
15
+ # --- API 문서 생성을 위한 헬퍼 함수 ---
16
+ def generate_api_docs(endpoint: str, params: dict, description: str):
17
+ """엔드포인트별 API 문서 Markdown 및 코드 블록을 생성합니다."""
18
+ base_url = "https://alwaysgood-my-tide-env.hf.space"
19
+ query_string = "&".join([f"{key}={value}" for key, value in params.items()])
20
+ full_url = f'"{base_url}{endpoint}?{query_string}"'
21
+
22
+ python_code = f"""
23
+ import requests
24
+
25
+ BASE_URL = "{base_url}"
26
+ params = {params}
27
+
28
+ response = requests.get(f"{{BASE_URL}}{endpoint}", params=params)
29
+
30
+ if response.status_code == 200:
31
+ print(response.json())
32
+ else:
33
+ print(f"Error: {{response.status_code}}")
34
+ """
35
+ with gr.Blocks():
36
+ gr.Markdown("---")
37
+ gr.Markdown(f"### 📚 API 사용법: {description}")
38
+ gr.Markdown("#### cURL")
39
+ gr.Code(language="bash", value=f"curl -X GET {full_url}", interactive=False)
40
+ gr.Markdown("#### Python (`requests`)")
41
+ gr.Code(language="python", value=python_code.strip(), interactive=False)
42
+
43
 
44
  def create_ui(prediction_handler, chatbot_handler):
45
  """Gradio UI를 생성하고 반환합니다."""
 
92
 
93
  # 3. API 탭 (새로 추가)
94
  with gr.TabItem("🔌 API"):
95
+ gr.Markdown("## RESTful API 엔드포인트\n실무에서 바로 사용 가능한 API 기능을 제공합니다.")
 
 
 
96
 
97
  with gr.Tabs():
98
+ # 3-1. 특정 시간 조위
99
+ with gr.TabItem("조위 조회"):
100
+ gr.Markdown("#### 특정 관측소, 특정 시간의 조위 정보를 조회합니다.")
101
  with gr.Row():
102
+ with gr.Column(scale=1):
103
+ api1_station = gr.Dropdown(choices=[(f"{STATION_NAMES[s]} ({s})", s) for s in STATIONS], label="관측소", value="DT_0001")
104
+ api1_time = gr.Textbox(label="조회 시간 (비워두면 현재)", placeholder="2025-08-10T15:00:00")
105
+ api1_btn = gr.Button("UI에서 테스트", variant="primary")
106
+ with gr.Column(scale=2):
 
 
 
 
 
 
 
 
 
 
 
 
 
107
  api1_output = gr.JSON(label="API 응답")
108
 
109
  api1_btn.click(
110
+ fn=lambda s, t: api_handlers["tide_level"](s, t if t else None),
111
+ inputs=[api1_station, api1_time],
112
+ outputs=api1_output
 
113
  )
114
+
115
+ generate_api_docs(
116
+ endpoint="/api/tide_level",
117
+ params={"station_id": "DT_0001", "target_time": "2025-08-10T09:00:00"},
118
+ description="특정 시간 조위 조회"
119
+ )
120
+
121
  # 3-2. 시계열 데이터
122
  with gr.TabItem("시계열"):
123
+ gr.Markdown("#### 지정된 기간의 시계열 조위 데이터를 조회합니다.")
124
  with gr.Row():
125
+ with gr.Column(scale=1):
126
+ api2_station = gr.Dropdown(choices=[(f"{STATION_NAMES[s]} ({s})", s) for s in STATIONS], label="관측소", value="DT_0001")
127
+ api2_start = gr.Textbox(label="시작 시간", placeholder="2025-08-10T00:00:00")
128
+ api2_end = gr.Textbox(label="종료 시간", placeholder="2025-08-11T00:00:00")
129
+ api2_interval = gr.Number(label="간격(분)", value=60, minimum=5)
130
+ api2_btn = gr.Button("UI에서 테스트", variant="primary")
131
+ with gr.Column(scale=2):
132
+ api2_output = gr.JSON(label="API 응답 (공공 API 형식)")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
133
 
134
  api2_btn.click(
135
+ fn=lambda s, st, et, i: api_handlers["tide_series"](s, st if st else None, et if et else None, int(i)),
 
 
136
  inputs=[api2_station, api2_start, api2_end, api2_interval],
137
+ outputs=api2_output
 
138
  )
139
+
140
+ generate_api_docs(
141
+ endpoint="/api/tide_series",
142
+ params={"station_id": "DT_0001", "start_time": "2025-08-10T00:00:00", "end_time": "2025-08-11T00:00:00"},
143
+ description="기간별 시계열 데이터 조회"
144
+ )
145
+
146
  # 3-3. 만조/간조
147
  with gr.TabItem("만조/간조"):
148
+ gr.Markdown("#### 특정 날짜의 만조/간조 정보를 조회합니다.")
149
  with gr.Row():
150
+ with gr.Column(scale=1):
151
+ api3_station = gr.Dropdown(choices=[(f"{STATION_NAMES[s]} ({s})", s) for s in STATIONS], label="관측소", value="DT_0001")
152
+ api3_date = gr.Textbox(label="날짜 (YYYY-MM-DD)", placeholder=datetime.now().strftime("%Y-%m-%d"))
153
+ api3_secondary = gr.Checkbox(label="부차 만조/간조 포함", value=False)
154
+ api3_btn = gr.Button("UI에서 테스트", variant="primary")
155
+ with gr.Column(scale=2):
 
 
 
 
 
 
 
 
 
 
 
 
156
  api3_output = gr.JSON(label="만조/간조 정보")
157
 
158
  api3_btn.click(
159
+ fn=lambda s, d, sec: api_handlers["extremes"](s, d if d else None, sec),
 
 
160
  inputs=[api3_station, api3_date, api3_secondary],
161
+ outputs=api3_output
 
162
  )
163
+
164
+ generate_api_docs(
165
+ endpoint="/api/extremes",
166
+ params={"station_id": "DT_0001", "date": "2025-08-10"},
167
+ description="만조/간조 정보 조회"
168
+ )
169
+
170
+ # 3-4. 위험 알림
171
  with gr.TabItem("위험 알림"):
172
+ gr.Markdown("#### 향후 설정된 시간 동안 위험 수위 도달 여부를 체크합니다.")
173
  with gr.Row():
174
+ with gr.Column(scale=1):
175
+ api4_station = gr.Dropdown(choices=[(f"{STATION_NAMES[s]} ({s})", s) for s in STATIONS], label="관측소", value="DT_0001")
176
+ api4_hours = gr.Number(label="확인 시간(시간)", value=24, minimum=1, maximum=72)
177
+ api4_warning = gr.Number(label="주의 수위(cm)", value=700)
178
+ api4_danger = gr.Number(label="경고 수위(cm)", value=750)
179
+ api4_btn = gr.Button("UI에서 테스트", variant="primary")
180
+ with gr.Column(scale=2):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
181
  api4_output = gr.JSON(label="위험 수위 정보")
182
 
183
  api4_btn.click(
184
+ fn=lambda s, h, w, d: api_handlers["alert"](s, int(h), w, d),
185
  inputs=[api4_station, api4_hours, api4_warning, api4_danger],
186
+ outputs=api4_output
 
187
  )
188
+
189
+ generate_api_docs(
190
+ endpoint="/api/alert",
191
+ params={"station_id": "DT_0001", "warning_level": 700, "danger_level": 750},
192
+ description="위험 수위 체크"
193
+ )
194
+
195
  # 3-5. 관측소 비교
196
  with gr.TabItem("비교"):
197
+ gr.Markdown("#### 여러 관측소의 조위를 동시에 비교합니다.")
198
  with gr.Row():
199
+ with gr.Column(scale=1):
200
+ api5_stations = gr.CheckboxGroup(choices=[(f"{STATION_NAMES[s]}", s) for s in STATIONS], label="비교할 관측소 선택", value=["DT_0001", "DT_0002", "DT_0003"])
201
+ api5_time = gr.Textbox(label="비교 시간 (비워두면 현재)", placeholder="2025-08-10T15:00:00")
202
+ api5_btn = gr.Button("UI에서 테스트", variant="primary")
203
+ with gr.Column(scale=2):
 
 
 
 
 
 
 
 
 
204
  api5_output = gr.JSON(label="비교 결과")
205
 
206
  api5_btn.click(
207
+ fn=lambda s, t: api_handlers["compare"](s, t if t else None),
208
  inputs=[api5_stations, api5_time],
209
+ outputs=api5_output
 
210
  )
211
+
212
+ generate_api_docs(
213
+ endpoint="/api/compare",
214
+ params={"station_ids": ["DT_0001", "DT_0002"]}, # requests 라이브러리는 리스트를 올바르게 처리합니다.
215
+ description="다중 관측소 비교"
216
+ )
217
+
218
  # 3-6. 상태 체크
219
  with gr.TabItem("상태"):
220
+ gr.Markdown("#### API 및 시스템의 현재 상태를 확인합니다.")
221
+ with gr.Row():
222
+ api6_btn = gr.Button("🔍 상태 확인", variant="secondary", scale=1)
223
+ api6_output = gr.JSON(label="시스템 상태", scale=2)
224
 
225
  api6_btn.click(
226
+ fn=api_handlers["health"],
227
  inputs=[],
228
+ outputs=api6_output
229
+ )
230
+
231
+ generate_api_docs(
232
+ endpoint="/api/health",
233
+ params={},
234
+ description="시스템 상태 확인"
235
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
236
 
237
  # 이벤트 핸들러 연결
238
  predict_btn.click(