starsnatched commited on
Commit
34d3cc7
·
unverified ·
2 Parent(s): 3fb65e6 41db684

Merge pull request #88 from starsnatched/codex/create-frontend-for-llm-on-huggingface-gradio-space

Browse files
Files changed (1) hide show
  1. gradio_app.py +141 -0
gradio_app.py ADDED
@@ -0,0 +1,141 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import asyncio
2
+ import shutil
3
+ from pathlib import Path
4
+
5
+ import gradio as gr
6
+ from gradio.oauth import attach_oauth, OAuthToken
7
+ from huggingface_hub import HfApi
8
+
9
+ from src.team import TeamChatSession
10
+ from src.db import list_sessions_info
11
+ from src.config import UPLOAD_DIR
12
+
13
+ # Store active chat sessions
14
+ _SESSIONS: dict[tuple[str, str], TeamChatSession] = {}
15
+ _API = HfApi()
16
+
17
+
18
+ def _username(token: OAuthToken) -> str:
19
+ """Return the username for the given token."""
20
+ info = _API.whoami(token.token)
21
+ return info.get("name") or info.get("user", "unknown")
22
+
23
+
24
+ async def _get_chat(user: str, session: str) -> TeamChatSession:
25
+ """Return an active :class:`TeamChatSession` for ``user`` and ``session``."""
26
+ key = (user, session)
27
+ chat = _SESSIONS.get(key)
28
+ if chat is None:
29
+ chat = TeamChatSession(user=user, session=session)
30
+ await chat.__aenter__()
31
+ _SESSIONS[key] = chat
32
+ return chat
33
+
34
+
35
+ def _vm_host_path(user: str, vm_path: str) -> Path:
36
+ rel = Path(vm_path).relative_to("/data")
37
+ base = (Path(UPLOAD_DIR) / user).resolve()
38
+ target = (base / rel).resolve()
39
+ if not target.is_relative_to(base):
40
+ raise ValueError("Invalid path")
41
+ return target
42
+
43
+
44
+ async def send_message(message: str, history: list[tuple[str, str]], session: str, token: OAuthToken):
45
+ user = _username(token)
46
+ chat = await _get_chat(user, session)
47
+ history = history or []
48
+ history.append((message, ""))
49
+ async for part in chat.chat_stream(message):
50
+ history[-1] = (message, history[-1][1] + part)
51
+ yield history
52
+
53
+
54
+ def load_sessions(token: OAuthToken):
55
+ user = _username(token)
56
+ infos = list_sessions_info(user)
57
+ names = [info["name"] for info in infos]
58
+ table = [[info["name"], info["last_message"]] for info in infos]
59
+ value = names[0] if names else "default"
60
+ return gr.update(choices=names or ["default"], value=value), table
61
+
62
+
63
+ def list_dir(path: str, token: OAuthToken):
64
+ user = _username(token)
65
+ target = _vm_host_path(user, path)
66
+ if not target.exists() or not target.is_dir():
67
+ return []
68
+ entries = []
69
+ for entry in sorted(target.iterdir()):
70
+ entries.append({"name": entry.name, "is_dir": entry.is_dir()})
71
+ return entries
72
+
73
+
74
+ def read_file(path: str, token: OAuthToken):
75
+ user = _username(token)
76
+ target = _vm_host_path(user, path)
77
+ if not target.exists():
78
+ return "File not found"
79
+ if target.is_dir():
80
+ return "Path is a directory"
81
+ try:
82
+ return target.read_text()
83
+ except UnicodeDecodeError:
84
+ return "Binary file not supported"
85
+
86
+
87
+ def save_file(path: str, content: str, token: OAuthToken):
88
+ user = _username(token)
89
+ target = _vm_host_path(user, path)
90
+ target.parent.mkdir(parents=True, exist_ok=True)
91
+ target.write_text(content)
92
+ return "Saved"
93
+
94
+
95
+ def delete_path(path: str, token: OAuthToken):
96
+ user = _username(token)
97
+ target = _vm_host_path(user, path)
98
+ if target.is_dir():
99
+ shutil.rmtree(target)
100
+ elif target.exists():
101
+ target.unlink()
102
+ else:
103
+ return "File not found"
104
+ return "Deleted"
105
+
106
+
107
+ with gr.Blocks(theme=gr.themes.Soft()) as demo:
108
+ attach_oauth(demo.app)
109
+
110
+ login_btn = gr.LoginButton()
111
+
112
+ with gr.Tab("Chat"):
113
+ session_dd = gr.Dropdown(["default"], label="Session", value="default")
114
+ refresh = gr.Button("Refresh Sessions")
115
+ chatbox = gr.Chatbot()
116
+ msg = gr.Textbox(label="Message")
117
+ send = gr.Button("Send")
118
+
119
+ with gr.Tab("Files"):
120
+ dir_path = gr.Textbox(label="Directory", value="/data")
121
+ list_btn = gr.Button("List")
122
+ table = gr.Dataframe(headers=["name", "is_dir"], datatype=["str", "bool"])
123
+ file_path = gr.Textbox(label="File Path")
124
+ load_btn = gr.Button("Load")
125
+ content = gr.Code(label="Content", language="text")
126
+ save_btn = gr.Button("Save")
127
+ del_btn = gr.Button("Delete")
128
+
129
+ refresh.click(load_sessions, outputs=[session_dd, table])
130
+ send.click(send_message, inputs=[msg, chatbox, session_dd], outputs=chatbox)
131
+ list_btn.click(list_dir, inputs=dir_path, outputs=table)
132
+ load_btn.click(read_file, inputs=file_path, outputs=content)
133
+ save_btn.click(save_file, inputs=[file_path, content], outputs=content)
134
+ del_btn.click(delete_path, inputs=file_path, outputs=content)
135
+ send.then(lambda: "", None, msg)
136
+
137
+
138
+ demo.queue()
139
+
140
+ if __name__ == "__main__":
141
+ demo.launch()