openfree commited on
Commit
556f446
ยท
verified ยท
1 Parent(s): 4309502

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +394 -0
app.py ADDED
@@ -0,0 +1,394 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import httpx
3
+ import asyncio
4
+ import json
5
+ from typing import Generator
6
+
7
+ # API ๊ธฐ๋ณธ URL
8
+ API_BASE_URL = "https://vidraft-kt.hf.space"
9
+
10
+ # ํ˜„์žฌ ์„ธ์…˜ ์ •๋ณด ์ €์žฅ
11
+ current_session = {"session_id": None, "user_email": None}
12
+
13
+
14
+ async def create_session(user_email: str) -> str:
15
+ """์ƒˆ ์„ธ์…˜ ์ƒ์„ฑ"""
16
+ if not user_email:
17
+ return "โŒ ์ด๋ฉ”์ผ์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”."
18
+
19
+ try:
20
+ async with httpx.AsyncClient(timeout=30.0) as client:
21
+ response = await client.post(
22
+ f"{API_BASE_URL}/session/new",
23
+ json={"user_email": user_email}
24
+ )
25
+ result = response.json()
26
+
27
+ if "error" in result:
28
+ return f"โŒ ์˜ค๋ฅ˜: {result['error']}"
29
+
30
+ current_session["session_id"] = result.get("session_id")
31
+ current_session["user_email"] = user_email
32
+ return f"โœ… ์„ธ์…˜ ์ƒ์„ฑ ์™„๋ฃŒ!\n์„ธ์…˜ ID: {result.get('session_id')}"
33
+ except Exception as e:
34
+ return f"โŒ ์—ฐ๊ฒฐ ์˜ค๋ฅ˜: {str(e)}"
35
+
36
+
37
+ async def end_session(session_id: str, user_email: str) -> str:
38
+ """์„ธ์…˜ ์ข…๋ฃŒ"""
39
+ if not session_id or not user_email:
40
+ return "โŒ ์„ธ์…˜ ID์™€ ์ด๋ฉ”์ผ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค."
41
+
42
+ try:
43
+ async with httpx.AsyncClient(timeout=30.0) as client:
44
+ response = await client.post(
45
+ f"{API_BASE_URL}/session/end",
46
+ json={"session_id": session_id, "user_email": user_email}
47
+ )
48
+ result = response.json()
49
+ return f"โœ… ์„ธ์…˜ ์ข…๋ฃŒ ์™„๋ฃŒ: {json.dumps(result, ensure_ascii=False, indent=2)}"
50
+ except Exception as e:
51
+ return f"โŒ ์˜ค๋ฅ˜: {str(e)}"
52
+
53
+
54
+ def chat_streaming(message: str, user_email: str, session_id: str,
55
+ web_search: bool, self_learning: bool, history: list) -> Generator:
56
+ """์ŠคํŠธ๋ฆฌ๋ฐ ์ฑ„ํŒ…"""
57
+ if not user_email:
58
+ yield history + [{"role": "assistant", "content": "โŒ ์ด๋ฉ”์ผ์„ ๋จผ์ € ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”."}]
59
+ return
60
+
61
+ if not session_id:
62
+ yield history + [{"role": "assistant", "content": "โŒ ์„ธ์…˜์„ ๋จผ์ € ์ƒ์„ฑํ•ด์ฃผ์„ธ์š”."}]
63
+ return
64
+
65
+ # ์‚ฌ์šฉ์ž ๋ฉ”์‹œ์ง€ ์ถ”๊ฐ€
66
+ history = history + [{"role": "user", "content": message}]
67
+ yield history
68
+
69
+ # ์ŠคํŠธ๋ฆฌ๋ฐ ์‘๋‹ต
70
+ full_response = ""
71
+ try:
72
+ with httpx.Client(timeout=120.0) as client:
73
+ with client.stream(
74
+ "POST",
75
+ f"{API_BASE_URL}/chat/text/stream",
76
+ json={
77
+ "message": message,
78
+ "user_email": user_email,
79
+ "session_id": session_id,
80
+ "web_search_enabled": web_search,
81
+ "self_learning_enabled": self_learning
82
+ }
83
+ ) as response:
84
+ for line in response.iter_lines():
85
+ if line.startswith("data: "):
86
+ data = line[6:]
87
+ if data == "[DONE]":
88
+ break
89
+ try:
90
+ chunk = json.loads(data)
91
+ content = chunk.get("content", "")
92
+ full_response += content
93
+ yield history[:-1] + [
94
+ {"role": "user", "content": message},
95
+ {"role": "assistant", "content": full_response}
96
+ ]
97
+ except json.JSONDecodeError:
98
+ continue
99
+ except Exception as e:
100
+ yield history + [{"role": "assistant", "content": f"โŒ ์˜ค๋ฅ˜: {str(e)}"}]
101
+
102
+
103
+ async def get_health_current(user_email: str) -> str:
104
+ """ํ˜„์žฌ ๊ฑด๊ฐ• ์ƒํƒœ ์กฐํšŒ"""
105
+ if not user_email:
106
+ return "โŒ ์ด๋ฉ”์ผ์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”."
107
+
108
+ try:
109
+ async with httpx.AsyncClient(timeout=30.0) as client:
110
+ response = await client.get(
111
+ f"{API_BASE_URL}/health/current",
112
+ params={"user_email": user_email}
113
+ )
114
+ result = response.json()
115
+ return json.dumps(result, ensure_ascii=False, indent=2)
116
+ except Exception as e:
117
+ return f"โŒ ์˜ค๋ฅ˜: {str(e)}"
118
+
119
+
120
+ async def get_health_history(user_email: str, days: int) -> str:
121
+ """๊ฑด๊ฐ• ํžˆ์Šคํ† ๋ฆฌ ์กฐํšŒ"""
122
+ if not user_email:
123
+ return "โŒ ์ด๋ฉ”์ผ์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”."
124
+
125
+ try:
126
+ async with httpx.AsyncClient(timeout=30.0) as client:
127
+ response = await client.get(
128
+ f"{API_BASE_URL}/health/history",
129
+ params={"user_email": user_email, "days": days}
130
+ )
131
+ result = response.json()
132
+ return json.dumps(result, ensure_ascii=False, indent=2)
133
+ except Exception as e:
134
+ return f"โŒ ์˜ค๋ฅ˜: {str(e)}"
135
+
136
+
137
+ async def search_memories(query: str, user_email: str, k: int, threshold: float) -> str:
138
+ """๏ฟฝ๏ฟฝ๏ฟฝ์–ต ๊ฒ€์ƒ‰"""
139
+ if not user_email or not query:
140
+ return "โŒ ์ด๋ฉ”์ผ๊ณผ ๊ฒ€์ƒ‰์–ด๋ฅผ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”."
141
+
142
+ try:
143
+ async with httpx.AsyncClient(timeout=30.0) as client:
144
+ response = await client.post(
145
+ f"{API_BASE_URL}/memory/search",
146
+ json={
147
+ "query": query,
148
+ "user_email": user_email,
149
+ "k": k,
150
+ "threshold": threshold
151
+ }
152
+ )
153
+ result = response.json()
154
+ return json.dumps(result, ensure_ascii=False, indent=2)
155
+ except Exception as e:
156
+ return f"โŒ ์˜ค๋ฅ˜: {str(e)}"
157
+
158
+
159
+ async def get_all_memories(user_email: str) -> str:
160
+ """๋ชจ๋“  ๊ธฐ์–ต ์กฐํšŒ"""
161
+ if not user_email:
162
+ return "โŒ ์ด๋ฉ”์ผ์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”."
163
+
164
+ try:
165
+ async with httpx.AsyncClient(timeout=30.0) as client:
166
+ response = await client.get(
167
+ f"{API_BASE_URL}/memory/all",
168
+ params={"user_email": user_email}
169
+ )
170
+ result = response.json()
171
+ return json.dumps(result, ensure_ascii=False, indent=2)
172
+ except Exception as e:
173
+ return f"โŒ ์˜ค๋ฅ˜: {str(e)}"
174
+
175
+
176
+ async def delete_memory(memory_id: int, user_email: str) -> str:
177
+ """๊ธฐ์–ต ์‚ญ์ œ"""
178
+ if not user_email or not memory_id:
179
+ return "โŒ ์ด๋ฉ”์ผ๊ณผ ๊ธฐ์–ต ID๋ฅผ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”."
180
+
181
+ try:
182
+ async with httpx.AsyncClient(timeout=30.0) as client:
183
+ response = await client.delete(
184
+ f"{API_BASE_URL}/memory/{memory_id}",
185
+ params={"user_email": user_email}
186
+ )
187
+ result = response.json()
188
+ return f"โœ… ์‚ญ์ œ ์™„๋ฃŒ: {json.dumps(result, ensure_ascii=False)}"
189
+ except Exception as e:
190
+ return f"โŒ ์˜ค๋ฅ˜: {str(e)}"
191
+
192
+
193
+ async def web_search(query: str, count: int) -> str:
194
+ """์›น ๊ฒ€์ƒ‰"""
195
+ if not query:
196
+ return "โŒ ๊ฒ€์ƒ‰์–ด๋ฅผ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”."
197
+
198
+ try:
199
+ async with httpx.AsyncClient(timeout=30.0) as client:
200
+ response = await client.post(
201
+ f"{API_BASE_URL}/search/web",
202
+ json={"query": query, "count": count}
203
+ )
204
+ result = response.json()
205
+ return json.dumps(result, ensure_ascii=False, indent=2)
206
+ except Exception as e:
207
+ return f"โŒ ์˜ค๋ฅ˜: {str(e)}"
208
+
209
+
210
+ async def crawl_url(url: str) -> str:
211
+ """URL ํฌ๋กค๋ง"""
212
+ if not url:
213
+ return "โŒ URL์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”."
214
+
215
+ try:
216
+ async with httpx.AsyncClient(timeout=60.0) as client:
217
+ response = await client.post(
218
+ f"{API_BASE_URL}/crawl/url",
219
+ json={"url": url}
220
+ )
221
+ result = response.json()
222
+ return json.dumps(result, ensure_ascii=False, indent=2)
223
+ except Exception as e:
224
+ return f"โŒ ์˜ค๋ฅ˜: {str(e)}"
225
+
226
+
227
+ async def get_storage_info() -> str:
228
+ """์Šคํ† ๋ฆฌ์ง€ ์ •๋ณด ์กฐํšŒ"""
229
+ try:
230
+ async with httpx.AsyncClient(timeout=30.0) as client:
231
+ response = await client.get(f"{API_BASE_URL}/storage/info")
232
+ result = response.json()
233
+ return json.dumps(result, ensure_ascii=False, indent=2)
234
+ except Exception as e:
235
+ return f"โŒ ์˜ค๋ฅ˜: {str(e)}"
236
+
237
+
238
+ async def upload_file(file, session_id: str, user_email: str) -> str:
239
+ """ํŒŒ์ผ ์—…๋กœ๋“œ"""
240
+ if not file or not session_id or not user_email:
241
+ return "โŒ ํŒŒ์ผ, ์„ธ์…˜ ID, ์ด๋ฉ”์ผ์ด ๋ชจ๋‘ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค."
242
+
243
+ try:
244
+ async with httpx.AsyncClient(timeout=60.0) as client:
245
+ with open(file.name, "rb") as f:
246
+ files = {"file": (file.name.split("/")[-1], f)}
247
+ data = {"session_id": session_id, "user_email": user_email}
248
+ response = await client.post(
249
+ f"{API_BASE_URL}/upload/file",
250
+ files=files,
251
+ data=data
252
+ )
253
+ result = response.json()
254
+ return json.dumps(result, ensure_ascii=False, indent=2)
255
+ except Exception as e:
256
+ return f"โŒ ์˜ค๋ฅ˜: {str(e)}"
257
+
258
+
259
+ # Gradio UI ๊ตฌ์„ฑ
260
+ with gr.Blocks(title="KT API ํ…Œ์ŠคํŠธ", theme=gr.themes.Soft()) as demo:
261
+ gr.Markdown("# ๐Ÿงช KT ์‹œ๋‹ˆ์–ด AI ๋น„์„œ API ํ…Œ์ŠคํŠธ")
262
+ gr.Markdown(f"**API URL:** `{API_BASE_URL}`")
263
+
264
+ with gr.Tabs():
265
+ # ํƒญ 1: ์ฑ„ํŒ… ํ…Œ์ŠคํŠธ
266
+ with gr.TabItem("๐Ÿ’ฌ ์ฑ„ํŒ…"):
267
+ with gr.Row():
268
+ with gr.Column(scale=1):
269
+ email_input = gr.Textbox(label="์ด๋ฉ”์ผ (ํ•„์ˆ˜)", placeholder="test@example.com")
270
+ session_input = gr.Textbox(label="์„ธ์…˜ ID", placeholder="์„ธ์…˜ ์ƒ์„ฑ ํ›„ ์ž๋™ ์ž…๋ ฅ๋จ")
271
+
272
+ with gr.Row():
273
+ create_btn = gr.Button("๐Ÿ†• ์„ธ์…˜ ์ƒ์„ฑ", variant="primary")
274
+ end_btn = gr.Button("๐Ÿ”š ์„ธ์…˜ ์ข…๋ฃŒ")
275
+
276
+ session_result = gr.Textbox(label="์„ธ์…˜ ๊ฒฐ๊ณผ", lines=3)
277
+
278
+ web_search_check = gr.Checkbox(label="์›น ๊ฒ€์ƒ‰ ํ™œ์„ฑํ™”", value=True)
279
+ self_learning_check = gr.Checkbox(label="์ž๊ฐ€ ํ•™์Šต ํ™œ์„ฑํ™”", value=True)
280
+
281
+ with gr.Column(scale=2):
282
+ chatbot = gr.Chatbot(label="๋Œ€ํ™”", height=400, type="messages")
283
+ msg_input = gr.Textbox(label="๋ฉ”์‹œ์ง€ ์ž…๋ ฅ", placeholder="๋ฉ”์‹œ์ง€๋ฅผ ์ž…๋ ฅํ•˜์„ธ์š”...")
284
+ send_btn = gr.Button("์ „์†ก", variant="primary")
285
+
286
+ # ์„ธ์…˜ ์ƒ์„ฑ ์ด๋ฒคํŠธ
287
+ async def on_create_session(email):
288
+ result = await create_session(email)
289
+ session_id = current_session.get("session_id", "")
290
+ return result, session_id
291
+
292
+ create_btn.click(
293
+ on_create_session,
294
+ inputs=[email_input],
295
+ outputs=[session_result, session_input]
296
+ )
297
+
298
+ # ์„ธ์…˜ ์ข…๋ฃŒ ์ด๋ฒคํŠธ
299
+ end_btn.click(
300
+ end_session,
301
+ inputs=[session_input, email_input],
302
+ outputs=[session_result]
303
+ )
304
+
305
+ # ์ฑ„ํŒ… ์ด๋ฒคํŠธ
306
+ send_btn.click(
307
+ chat_streaming,
308
+ inputs=[msg_input, email_input, session_input, web_search_check, self_learning_check, chatbot],
309
+ outputs=[chatbot]
310
+ ).then(lambda: "", outputs=[msg_input])
311
+
312
+ msg_input.submit(
313
+ chat_streaming,
314
+ inputs=[msg_input, email_input, session_input, web_search_check, self_learning_check, chatbot],
315
+ outputs=[chatbot]
316
+ ).then(lambda: "", outputs=[msg_input])
317
+
318
+ # ํƒญ 2: ๊ฑด๊ฐ• ์ƒํƒœ
319
+ with gr.TabItem("๐Ÿฅ ๊ฑด๊ฐ• ์ƒํƒœ"):
320
+ health_email = gr.Textbox(label="์ด๋ฉ”์ผ", placeholder="test@example.com")
321
+
322
+ with gr.Row():
323
+ health_current_btn = gr.Button("ํ˜„์žฌ ๊ฑด๊ฐ• ์ƒํƒœ ์กฐํšŒ", variant="primary")
324
+ health_days = gr.Slider(1, 90, value=30, step=1, label="ํžˆ์Šคํ† ๋ฆฌ ์ผ์ˆ˜")
325
+ health_history_btn = gr.Button("๊ฑด๊ฐ• ํžˆ์Šคํ† ๋ฆฌ ์กฐํšŒ")
326
+
327
+ health_result = gr.Textbox(label="๊ฒฐ๊ณผ", lines=15)
328
+
329
+ health_current_btn.click(get_health_current, inputs=[health_email], outputs=[health_result])
330
+ health_history_btn.click(get_health_history, inputs=[health_email, health_days], outputs=[health_result])
331
+
332
+ # ํƒญ 3: ๊ธฐ์–ต ๊ด€๋ฆฌ
333
+ with gr.TabItem("๐Ÿง  ๊ธฐ์–ต ๊ด€๋ฆฌ"):
334
+ memory_email = gr.Textbox(label="์ด๋ฉ”์ผ", placeholder="test@example.com")
335
+
336
+ with gr.Row():
337
+ with gr.Column():
338
+ gr.Markdown("### ๊ธฐ์–ต ๊ฒ€์ƒ‰")
339
+ search_query = gr.Textbox(label="๊ฒ€์ƒ‰์–ด")
340
+ search_k = gr.Slider(1, 50, value=10, step=1, label="๊ฒฐ๊ณผ ๊ฐœ์ˆ˜")
341
+ search_threshold = gr.Slider(0.1, 1.0, value=0.7, step=0.1, label="์œ ์‚ฌ๋„ ์ž„๊ณ„๊ฐ’")
342
+ search_btn = gr.Button("๊ฒ€์ƒ‰", variant="primary")
343
+
344
+ with gr.Column():
345
+ gr.Markdown("### ๊ธฐ์–ต ์‚ญ์ œ")
346
+ delete_id = gr.Number(label="๊ธฐ์–ต ID", precision=0)
347
+ delete_btn = gr.Button("์‚ญ์ œ", variant="stop")
348
+ get_all_btn = gr.Button("๋ชจ๋“  ๊ธฐ์–ต ์กฐํšŒ")
349
+
350
+ memory_result = gr.Textbox(label="๊ฒฐ๊ณผ", lines=15)
351
+
352
+ search_btn.click(search_memories, inputs=[search_query, memory_email, search_k, search_threshold], outputs=[memory_result])
353
+ get_all_btn.click(get_all_memories, inputs=[memory_email], outputs=[memory_result])
354
+ delete_btn.click(delete_memory, inputs=[delete_id, memory_email], outputs=[memory_result])
355
+
356
+ # ํƒญ 4: ์›น ๊ฒ€์ƒ‰ & ํฌ๋กค๋ง
357
+ with gr.TabItem("๐ŸŒ ์›น ๊ฒ€์ƒ‰"):
358
+ with gr.Row():
359
+ with gr.Column():
360
+ gr.Markdown("### ์›น ๊ฒ€์ƒ‰")
361
+ web_query = gr.Textbox(label="๊ฒ€์ƒ‰์–ด")
362
+ web_count = gr.Slider(1, 20, value=10, step=1, label="๊ฒฐ๊ณผ ๊ฐœ์ˆ˜")
363
+ web_search_btn = gr.Button("๊ฒ€์ƒ‰", variant="primary")
364
+
365
+ with gr.Column():
366
+ gr.Markdown("### URL ํฌ๋กค๋ง")
367
+ crawl_url_input = gr.Textbox(label="URL", placeholder="https://example.com")
368
+ crawl_btn = gr.Button("ํฌ๋กค๋ง", variant="primary")
369
+
370
+ web_result = gr.Textbox(label="๊ฒฐ๊ณผ", lines=15)
371
+
372
+ web_search_btn.click(web_search, inputs=[web_query, web_count], outputs=[web_result])
373
+ crawl_btn.click(crawl_url, inputs=[crawl_url_input], outputs=[web_result])
374
+
375
+ # ํƒญ 5: ํŒŒ์ผ ์—…๋กœ๋“œ
376
+ with gr.TabItem("๐Ÿ“ ํŒŒ์ผ ์—…๋กœ๋“œ"):
377
+ upload_email = gr.Textbox(label="์ด๋ฉ”์ผ", placeholder="test@example.com")
378
+ upload_session = gr.Textbox(label="์„ธ์…˜ ID")
379
+ upload_file_input = gr.File(label="ํŒŒ์ผ ์„ ํƒ (PDF, CSV, TXT)", file_types=[".pdf", ".csv", ".txt"])
380
+ upload_btn = gr.Button("์—…๋กœ๋“œ", variant="primary")
381
+ upload_result = gr.Textbox(label="๊ฒฐ๊ณผ", lines=10)
382
+
383
+ upload_btn.click(upload_file, inputs=[upload_file_input, upload_session, upload_email], outputs=[upload_result])
384
+
385
+ # ํƒญ 6: ์‹œ์Šคํ…œ ์ •๋ณด
386
+ with gr.TabItem("โš™๏ธ ์‹œ์Šคํ…œ"):
387
+ storage_btn = gr.Button("์Šคํ† ๋ฆฌ์ง€ ์ •๋ณด ์กฐํšŒ", variant="primary")
388
+ storage_result = gr.Textbox(label="๊ฒฐ๊ณผ", lines=15)
389
+
390
+ storage_btn.click(get_storage_info, outputs=[storage_result])
391
+
392
+
393
+ if __name__ == "__main__":
394
+ demo.launch(server_name="0.0.0.0", server_port=7860)