kt-api / app.py
openfree's picture
Update app.py
dde530a verified
import gradio as gr
import httpx
import asyncio
import json
from typing import Generator
# API ๊ธฐ๋ณธ URL
API_BASE_URL = "https://vidraft-kt.hf.space"
# ํ˜„์žฌ ์„ธ์…˜ ์ •๋ณด ์ €์žฅ
current_session = {"session_id": None, "user_email": None}
async def create_session(user_email: str) -> str:
"""์ƒˆ ์„ธ์…˜ ์ƒ์„ฑ"""
if not user_email:
return "โŒ ์ด๋ฉ”์ผ์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”."
try:
async with httpx.AsyncClient(timeout=30.0) as client:
response = await client.post(
f"{API_BASE_URL}/session/new",
json={"user_email": user_email}
)
result = response.json()
if "error" in result:
return f"โŒ ์˜ค๋ฅ˜: {result['error']}"
current_session["session_id"] = result.get("session_id")
current_session["user_email"] = user_email
return f"โœ… ์„ธ์…˜ ์ƒ์„ฑ ์™„๋ฃŒ!\n์„ธ์…˜ ID: {result.get('session_id')}"
except Exception as e:
return f"โŒ ์—ฐ๊ฒฐ ์˜ค๋ฅ˜: {str(e)}"
async def end_session(session_id: str, user_email: str) -> str:
"""์„ธ์…˜ ์ข…๋ฃŒ"""
if not session_id or not user_email:
return "โŒ ์„ธ์…˜ ID์™€ ์ด๋ฉ”์ผ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค."
try:
async with httpx.AsyncClient(timeout=30.0) as client:
response = await client.post(
f"{API_BASE_URL}/session/end",
json={"session_id": session_id, "user_email": user_email}
)
result = response.json()
return f"โœ… ์„ธ์…˜ ์ข…๋ฃŒ ์™„๋ฃŒ: {json.dumps(result, ensure_ascii=False, indent=2)}"
except Exception as e:
return f"โŒ ์˜ค๋ฅ˜: {str(e)}"
def chat_streaming(message: str, user_email: str, session_id: str,
web_search: bool, self_learning: bool, history: list) -> Generator:
"""์ŠคํŠธ๋ฆฌ๋ฐ ์ฑ„ํŒ… - messages ํ˜•์‹ ์‚ฌ์šฉ (๋”•์…”๋„ˆ๋ฆฌ)"""
if not user_email:
history = history or []
history.append({"role": "assistant", "content": "โŒ ์ด๋ฉ”์ผ์„ ๋จผ์ € ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”."})
yield history
return
if not session_id:
history = history or []
history.append({"role": "assistant", "content": "โŒ ์„ธ์…˜์„ ๋จผ์ € ์ƒ์„ฑํ•ด์ฃผ์„ธ์š”."})
yield history
return
# ์‚ฌ์šฉ์ž ๋ฉ”์‹œ์ง€ ์ถ”๊ฐ€
history = history or []
history.append({"role": "user", "content": message})
history.append({"role": "assistant", "content": ""})
yield history
# ์ŠคํŠธ๋ฆฌ๋ฐ ์‘๋‹ต
full_response = ""
try:
with httpx.Client(timeout=120.0) as client:
with client.stream(
"POST",
f"{API_BASE_URL}/chat/text/stream",
json={
"message": message,
"user_email": user_email,
"session_id": session_id,
"web_search_enabled": web_search,
"self_learning_enabled": self_learning
}
) as response:
for line in response.iter_lines():
if line.startswith("data: "):
data = line[6:]
if data == "[DONE]":
break
try:
chunk = json.loads(data)
content = chunk.get("content", "")
full_response += content
history[-1]["content"] = full_response
yield history
except json.JSONDecodeError:
continue
except Exception as e:
history[-1]["content"] = f"โŒ ์˜ค๋ฅ˜: {str(e)}"
yield history
async def get_health_current(user_email: str) -> str:
"""ํ˜„์žฌ ๊ฑด๊ฐ• ์ƒํƒœ ์กฐํšŒ"""
if not user_email:
return "โŒ ์ด๋ฉ”์ผ์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”."
try:
async with httpx.AsyncClient(timeout=30.0) as client:
response = await client.get(
f"{API_BASE_URL}/health/current",
params={"user_email": user_email}
)
result = response.json()
return json.dumps(result, ensure_ascii=False, indent=2)
except Exception as e:
return f"โŒ ์˜ค๋ฅ˜: {str(e)}"
async def get_health_history(user_email: str, days: int) -> str:
"""๊ฑด๊ฐ• ํžˆ์Šคํ† ๋ฆฌ ์กฐํšŒ"""
if not user_email:
return "โŒ ์ด๋ฉ”์ผ์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”."
try:
async with httpx.AsyncClient(timeout=30.0) as client:
response = await client.get(
f"{API_BASE_URL}/health/history",
params={"user_email": user_email, "days": days}
)
result = response.json()
return json.dumps(result, ensure_ascii=False, indent=2)
except Exception as e:
return f"โŒ ์˜ค๋ฅ˜: {str(e)}"
async def search_memories(query: str, user_email: str, k: int, threshold: float) -> str:
"""๊ธฐ์–ต ๊ฒ€์ƒ‰"""
if not user_email or not query:
return "โŒ ์ด๋ฉ”์ผ๊ณผ ๊ฒ€์ƒ‰์–ด๋ฅผ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”."
try:
async with httpx.AsyncClient(timeout=30.0) as client:
response = await client.post(
f"{API_BASE_URL}/memory/search",
json={
"query": query,
"user_email": user_email,
"k": k,
"threshold": threshold
}
)
result = response.json()
return json.dumps(result, ensure_ascii=False, indent=2)
except Exception as e:
return f"โŒ ์˜ค๋ฅ˜: {str(e)}"
async def get_all_memories(user_email: str) -> str:
"""๋ชจ๋“  ๊ธฐ์–ต ์กฐํšŒ"""
if not user_email:
return "โŒ ์ด๋ฉ”์ผ์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”."
try:
async with httpx.AsyncClient(timeout=30.0) as client:
response = await client.get(
f"{API_BASE_URL}/memory/all",
params={"user_email": user_email}
)
result = response.json()
return json.dumps(result, ensure_ascii=False, indent=2)
except Exception as e:
return f"โŒ ์˜ค๋ฅ˜: {str(e)}"
async def delete_memory(memory_id: int, user_email: str) -> str:
"""๊ธฐ์–ต ์‚ญ์ œ"""
if not user_email or not memory_id:
return "โŒ ์ด๋ฉ”์ผ๊ณผ ๊ธฐ์–ต ID๋ฅผ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”."
try:
async with httpx.AsyncClient(timeout=30.0) as client:
response = await client.delete(
f"{API_BASE_URL}/memory/{int(memory_id)}",
params={"user_email": user_email}
)
result = response.json()
return f"โœ… ์‚ญ์ œ ์™„๋ฃŒ: {json.dumps(result, ensure_ascii=False)}"
except Exception as e:
return f"โŒ ์˜ค๋ฅ˜: {str(e)}"
async def web_search(query: str, count: int) -> str:
"""์›น ๊ฒ€์ƒ‰"""
if not query:
return "โŒ ๊ฒ€์ƒ‰์–ด๋ฅผ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”."
try:
async with httpx.AsyncClient(timeout=30.0) as client:
response = await client.post(
f"{API_BASE_URL}/search/web",
json={"query": query, "count": count}
)
result = response.json()
return json.dumps(result, ensure_ascii=False, indent=2)
except Exception as e:
return f"โŒ ์˜ค๋ฅ˜: {str(e)}"
async def crawl_url(url: str) -> str:
"""URL ํฌ๋กค๋ง"""
if not url:
return "โŒ URL์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”."
try:
async with httpx.AsyncClient(timeout=60.0) as client:
response = await client.post(
f"{API_BASE_URL}/crawl/url",
json={"url": url}
)
result = response.json()
return json.dumps(result, ensure_ascii=False, indent=2)
except Exception as e:
return f"โŒ ์˜ค๋ฅ˜: {str(e)}"
async def get_storage_info() -> str:
"""์Šคํ† ๋ฆฌ์ง€ ์ •๋ณด ์กฐํšŒ"""
try:
async with httpx.AsyncClient(timeout=30.0) as client:
response = await client.get(f"{API_BASE_URL}/storage/info")
result = response.json()
return json.dumps(result, ensure_ascii=False, indent=2)
except Exception as e:
return f"โŒ ์˜ค๋ฅ˜: {str(e)}"
# Gradio UI ๊ตฌ์„ฑ
with gr.Blocks(title="KT API ํ…Œ์ŠคํŠธ") as demo:
gr.Markdown("# ๐Ÿงช KT ์‹œ๋‹ˆ์–ด AI ๋น„์„œ API ํ…Œ์ŠคํŠธ")
gr.Markdown(f"**API URL:** `{API_BASE_URL}`")
with gr.Tabs():
# ํƒญ 1: ์ฑ„ํŒ… ํ…Œ์ŠคํŠธ
with gr.TabItem("๐Ÿ’ฌ ์ฑ„ํŒ…"):
with gr.Row():
with gr.Column(scale=1):
email_input = gr.Textbox(label="์ด๋ฉ”์ผ (ํ•„์ˆ˜)", placeholder="test@example.com")
session_input = gr.Textbox(label="์„ธ์…˜ ID", placeholder="์„ธ์…˜ ์ƒ์„ฑ ํ›„ ์ž๋™ ์ž…๋ ฅ๋จ")
with gr.Row():
create_btn = gr.Button("๐Ÿ†• ์„ธ์…˜ ์ƒ์„ฑ", variant="primary")
end_btn = gr.Button("๐Ÿ”š ์„ธ์…˜ ์ข…๋ฃŒ")
session_result = gr.Textbox(label="์„ธ์…˜ ๊ฒฐ๊ณผ", lines=3)
web_search_check = gr.Checkbox(label="์›น ๊ฒ€์ƒ‰ ํ™œ์„ฑํ™”", value=True)
self_learning_check = gr.Checkbox(label="์ž๊ฐ€ ํ•™์Šต ํ™œ์„ฑํ™”", value=True)
with gr.Column(scale=2):
# messages ํ˜•์‹ ์‚ฌ์šฉ (๊ธฐ๋ณธ๊ฐ’)
chatbot = gr.Chatbot(label="๋Œ€ํ™”", height=400)
msg_input = gr.Textbox(label="๋ฉ”์‹œ์ง€ ์ž…๋ ฅ", placeholder="๋ฉ”์‹œ์ง€๋ฅผ ์ž…๋ ฅํ•˜์„ธ์š”...")
send_btn = gr.Button("์ „์†ก", variant="primary")
# ์„ธ์…˜ ์ƒ์„ฑ ์ด๋ฒคํŠธ
async def on_create_session(email):
result = await create_session(email)
session_id = current_session.get("session_id", "")
return result, session_id
create_btn.click(
on_create_session,
inputs=[email_input],
outputs=[session_result, session_input]
)
# ์„ธ์…˜ ์ข…๋ฃŒ ์ด๋ฒคํŠธ
end_btn.click(
end_session,
inputs=[session_input, email_input],
outputs=[session_result]
)
# ์ฑ„ํŒ… ์ด๋ฒคํŠธ
send_btn.click(
chat_streaming,
inputs=[msg_input, email_input, session_input, web_search_check, self_learning_check, chatbot],
outputs=[chatbot]
).then(lambda: "", outputs=[msg_input])
msg_input.submit(
chat_streaming,
inputs=[msg_input, email_input, session_input, web_search_check, self_learning_check, chatbot],
outputs=[chatbot]
).then(lambda: "", outputs=[msg_input])
# ํƒญ 2: ๊ฑด๊ฐ• ์ƒํƒœ
with gr.TabItem("๐Ÿฅ ๊ฑด๊ฐ• ์ƒํƒœ"):
health_email = gr.Textbox(label="์ด๋ฉ”์ผ", placeholder="test@example.com")
with gr.Row():
health_current_btn = gr.Button("ํ˜„์žฌ ๊ฑด๊ฐ• ์ƒํƒœ ์กฐํšŒ", variant="primary")
health_days = gr.Slider(1, 90, value=30, step=1, label="ํžˆ์Šคํ† ๋ฆฌ ์ผ์ˆ˜")
health_history_btn = gr.Button("๊ฑด๊ฐ• ํžˆ์Šคํ† ๋ฆฌ ์กฐํšŒ")
health_result = gr.Textbox(label="๊ฒฐ๊ณผ", lines=15)
health_current_btn.click(get_health_current, inputs=[health_email], outputs=[health_result])
health_history_btn.click(get_health_history, inputs=[health_email, health_days], outputs=[health_result])
# ํƒญ 3: ๊ธฐ์–ต ๊ด€๋ฆฌ
with gr.TabItem("๐Ÿง  ๊ธฐ์–ต ๊ด€๋ฆฌ"):
memory_email = gr.Textbox(label="์ด๋ฉ”์ผ", placeholder="test@example.com")
with gr.Row():
with gr.Column():
gr.Markdown("### ๊ธฐ์–ต ๊ฒ€์ƒ‰")
search_query = gr.Textbox(label="๊ฒ€์ƒ‰์–ด")
search_k = gr.Slider(1, 50, value=10, step=1, label="๊ฒฐ๊ณผ ๊ฐœ์ˆ˜")
search_threshold = gr.Slider(0.1, 1.0, value=0.7, step=0.1, label="์œ ์‚ฌ๋„ ์ž„๊ณ„๊ฐ’")
search_btn = gr.Button("๊ฒ€์ƒ‰", variant="primary")
with gr.Column():
gr.Markdown("### ๊ธฐ์–ต ์‚ญ์ œ")
delete_id = gr.Number(label="๊ธฐ์–ต ID", precision=0)
delete_btn = gr.Button("์‚ญ์ œ", variant="stop")
get_all_btn = gr.Button("๋ชจ๋“  ๊ธฐ์–ต ์กฐํšŒ")
memory_result = gr.Textbox(label="๊ฒฐ๊ณผ", lines=15)
search_btn.click(search_memories, inputs=[search_query, memory_email, search_k, search_threshold], outputs=[memory_result])
get_all_btn.click(get_all_memories, inputs=[memory_email], outputs=[memory_result])
delete_btn.click(delete_memory, inputs=[delete_id, memory_email], outputs=[memory_result])
# ํƒญ 4: ์›น ๊ฒ€์ƒ‰ & ํฌ๋กค๋ง
with gr.TabItem("๐ŸŒ ์›น ๊ฒ€์ƒ‰"):
with gr.Row():
with gr.Column():
gr.Markdown("### ์›น ๊ฒ€์ƒ‰")
web_query = gr.Textbox(label="๊ฒ€์ƒ‰์–ด")
web_count = gr.Slider(1, 20, value=10, step=1, label="๊ฒฐ๊ณผ ๊ฐœ์ˆ˜")
web_search_btn = gr.Button("๊ฒ€์ƒ‰", variant="primary")
with gr.Column():
gr.Markdown("### URL ํฌ๋กค๋ง")
crawl_url_input = gr.Textbox(label="URL", placeholder="https://example.com")
crawl_btn = gr.Button("ํฌ๋กค๋ง", variant="primary")
web_result = gr.Textbox(label="๊ฒฐ๊ณผ", lines=15)
web_search_btn.click(web_search, inputs=[web_query, web_count], outputs=[web_result])
crawl_btn.click(crawl_url, inputs=[crawl_url_input], outputs=[web_result])
# ํƒญ 5: ์‹œ์Šคํ…œ ์ •๋ณด
with gr.TabItem("โš™๏ธ ์‹œ์Šคํ…œ"):
storage_btn = gr.Button("์Šคํ† ๋ฆฌ์ง€ ์ •๋ณด ์กฐํšŒ", variant="primary")
storage_result = gr.Textbox(label="๊ฒฐ๊ณผ", lines=15)
storage_btn.click(get_storage_info, outputs=[storage_result])
if __name__ == "__main__":
demo.launch(server_name="0.0.0.0", server_port=7860)