ginipick commited on
Commit
4acdad0
ยท
verified ยท
1 Parent(s): 5ac84f7

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +293 -1
app.py CHANGED
@@ -1 +1,293 @@
1
- ss
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ from huggingface_hub import InferenceClient
3
+ import os
4
+ import requests
5
+ from typing import List, Dict, Union
6
+ import traceback
7
+ from PIL import Image
8
+ from io import BytesIO
9
+ import asyncio
10
+ from gradio_client import Client
11
+ import time
12
+ import threading
13
+
14
+ HF_TOKEN = os.getenv("HF_TOKEN")
15
+ hf_client = InferenceClient("CohereForAI/c4ai-command-r-plus-08-2024", token=HF_TOKEN)
16
+
17
+ def get_headers():
18
+ if not HF_TOKEN:
19
+ raise ValueError("Hugging Face token not found in environment variables")
20
+ return {"Authorization": f"Bearer {HF_TOKEN}"}
21
+
22
+ def get_most_liked_spaces(limit: int = 300) -> Union[List[Dict], str]:
23
+ url = "https://huggingface.co/api/spaces"
24
+ params = {
25
+ "sort": "likes",
26
+ "direction": -1,
27
+ "limit": limit,
28
+ "full": "true"
29
+ }
30
+
31
+ try:
32
+ response = requests.get(url, params=params, headers=get_headers())
33
+ response.raise_for_status()
34
+ return response.json()
35
+ except requests.RequestException as e:
36
+ return f"API request error: {str(e)}"
37
+ except ValueError as e:
38
+ return f"JSON decoding error: {str(e)}"
39
+
40
+ def format_space(space: Dict) -> Dict:
41
+ space_id = space.get('id', 'Unknown')
42
+ space_name = space_id.split('/')[-1] if '/' in space_id else space_id
43
+
44
+ space_author = space.get('author', 'Unknown')
45
+ if isinstance(space_author, dict):
46
+ space_author = space_author.get('user', space_author.get('name', 'Unknown'))
47
+
48
+ space_likes = space.get('likes', 'N/A')
49
+ space_url = f"https://huggingface.co/spaces/{space_id}"
50
+
51
+ return {
52
+ "id": space_id,
53
+ "name": space_name,
54
+ "author": space_author,
55
+ "likes": space_likes,
56
+ "url": space_url,
57
+ }
58
+
59
+ def format_spaces(spaces: Union[List[Dict], str]) -> List[Dict]:
60
+ if isinstance(spaces, str):
61
+ return [{"error": spaces}]
62
+
63
+ return [format_space(space) for space in spaces if isinstance(space, dict)]
64
+
65
+ def summarize_space(space: Dict) -> str:
66
+ system_message = "๋‹น์‹ ์€ Hugging Face Space์˜ ๋‚ด์šฉ์„ ์š”์•ฝํ•˜๋Š” AI ์กฐ์ˆ˜์ž…๋‹ˆ๋‹ค. ์ฃผ์–ด์ง„ ์ •๋ณด๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ๊ฐ„๊ฒฐํ•˜๊ณ  ๋ช…ํ™•ํ•œ ์š”์•ฝ์„ ์ œ๊ณตํ•ด์ฃผ์„ธ์š”."
67
+ user_message = f"๋‹ค์Œ Hugging Face Space๋ฅผ ์š”์•ฝํ•ด์ฃผ์„ธ์š”: {space['name']} by {space['author']}. ์ข‹์•„์š” ์ˆ˜: {space['likes']}. URL: {space['url']}"
68
+
69
+ messages = [
70
+ {"role": "system", "content": system_message},
71
+ {"role": "user", "content": user_message}
72
+ ]
73
+
74
+ try:
75
+ response = hf_client.chat_completion(messages, max_tokens=400, temperature=0.7)
76
+ return response.choices[0].message.content
77
+ except Exception as e:
78
+ return f"์š”์•ฝ ์ƒ์„ฑ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ: {str(e)}"
79
+
80
+ def get_app_py_content(space_id: str) -> str:
81
+ app_py_url = f"https://huggingface.co/spaces/{space_id}/raw/main/app.py"
82
+ try:
83
+ response = requests.get(app_py_url, headers=get_headers())
84
+ if response.status_code == 200:
85
+ content = response.text
86
+ if len(content) > 500: # ๋‚ด์šฉ์„ 500์ž๋กœ ์ œํ•œํ•ฉ๋‹ˆ๋‹ค
87
+ content = content[:497] + "..."
88
+ return content
89
+ else:
90
+ return f"app.py file not found or inaccessible for space: {space_id}"
91
+ except requests.RequestException:
92
+ return f"Error fetching app.py content for space: {space_id}"
93
+
94
+ def on_select(space):
95
+ try:
96
+ print(f"Selected space: {space['name']}")
97
+ summary = summarize_space(space)
98
+ app_content = get_app_py_content(space['id'])
99
+ info = f"์„ ํƒ๋œ Space: {space['name']} (ID: {space['id']})\n"
100
+ info += f"Author: {space['author']}\n"
101
+ info += f"Likes: {space['likes']}\n"
102
+ info += f"URL: {space['url']}\n\n"
103
+ info += f"์š”์•ฝ:\n{summary}"
104
+ print(f"Returning URL: {space['url']}")
105
+ return info, app_content, space['url']
106
+ except Exception as e:
107
+ print(f"Error in on_select: {str(e)}")
108
+ print(traceback.format_exc())
109
+ return f"์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค: {str(e)}", "", ""
110
+
111
+ def update_screenshot(url, last_url, force_update=False):
112
+ print(f"Updating screenshot. Current URL: {url}, Last URL: {last_url}, Force update: {force_update}")
113
+ if url and (url != last_url or force_update):
114
+
115
+ screenshot = take_screenshot(url)
116
+ print("Screenshot updated")
117
+ return screenshot, url
118
+ print("No update needed")
119
+ return gr.update(), last_url
120
+
121
+ def refresh_screenshot(url, last_url):
122
+ print(f"Refresh button clicked. URL: {url}, Last URL: {last_url}")
123
+ # ํ•ญ์ƒ ๊ฐ•์ œ๋กœ ์—…๋ฐ์ดํŠธ
124
+ return update_screenshot(url, last_url, force_update=True)
125
+
126
+
127
+ def take_screenshot(url):
128
+ try:
129
+ print(f"Taking screenshot of URL: {url}")
130
+ client = Client("ginipick/selenium-screenshot-gradio")
131
+ result = client.predict(url=url, api_name="/predict")
132
+ print(f"Screenshot result: {result}")
133
+ if isinstance(result, str) and os.path.exists(result):
134
+ return Image.open(result)
135
+ else:
136
+ print(f"Invalid result from API: {result}")
137
+ return Image.new('RGB', (600, 360), color='lightgray')
138
+ except Exception as e:
139
+ print(f"Screenshot error: {str(e)}")
140
+ return Image.new('RGB', (600, 360), color='lightgray')
141
+
142
+
143
+ def generate_usage_guide(app_content):
144
+ system_message = "๋‹น์‹ ์€ Python ์ฝ”๋“œ๋ฅผ ๋ถ„์„ํ•˜์—ฌ, ํ™”๋ฉด ๋ณด๋“ฏ์ด ์ด์šฉ ๋ฐฉ๋ฒ•์„ ์„ค๋ช…ํ•˜๋Š” AI ์กฐ์ˆ˜์ž…๋‹ˆ๋‹ค. app.py ์ฝ”๋“œ๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ์ฝ”๋“œ์— ๋Œ€ํ•œ ์–ธ๊ธ‰์€ ์ œ์™ธํ•˜๊ณ , ์ด์šฉ์ž ๊ด€์ ์—์„œ 1) ๊ธฐ์กด ์œ ์‚ฌ ๊ธฐ์ˆ  ๋ฐฉ์‹๊ดด ๋น„๊ตํ•ด ํŠน์ง•, ์žฅ์ ์— ๋Œ€ํ•ด ์นœ์ ˆํ•˜๊ณ  ์ž์„ธํ•˜๊ฒŒ ์ƒ์„ธํ•œ ์‚ฌ์šฉ ๋ฐฉ๋ฒ•์„ ์ œ๊ณตํ•ด์ฃผ์„ธ์š”."
145
+ user_message = f"๋‹ค์Œ Python ์ฝ”๋“œ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ™”๋ฉด UI/UX์  ์ธก๋ฉด์œผ๋กœ ํŠน์ง•๊ณผ ์‚ฌ์šฉ ๋ฐฉ๋ฒ•์„ ์„ค๋ช…ํ•ด์ฃผ์„ธ์š”:\n\n{app_content}"
146
+
147
+ messages = [
148
+ {"role": "system", "content": system_message},
149
+ {"role": "user", "content": user_message}
150
+ ]
151
+
152
+ try:
153
+ response = hf_client.chat_completion(messages, max_tokens=4000, temperature=0.7)
154
+ return response.choices[0].message.content
155
+ except Exception as e:
156
+ return f"์‚ฌ์šฉ ๋ฐฉ๋ฒ• ์ƒ์„ฑ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ: {str(e)}"
157
+
158
+ def create_ui():
159
+ try:
160
+ spaces_list = get_most_liked_spaces()
161
+ formatted_spaces = format_spaces(spaces_list)
162
+ print(f"Total spaces loaded: {len(formatted_spaces)}")
163
+
164
+ css = """
165
+ footer {visibility: hidden;}
166
+ .minimal-button {min-width: 30px !important; height: 25px !important; line-height: 1 !important; font-size: 12px !important; padding: 2px 5px !important;}
167
+ .space-row {margin-bottom: 5px !important;}
168
+ #refresh-button, #manual-button {
169
+ width: 100% !important;
170
+ margin-top: 5px !important;
171
+ }
172
+ #info-output, #usage-guide {
173
+ height: 400px; /* ๋†’์ด๋ฅผ 400px๋กœ ์ฆ๊ฐ€ */
174
+ overflow-y: auto;
175
+ padding-right: 10px;
176
+ }
177
+ #app-py-content {
178
+ height: auto !important;
179
+ max-height: none !important;
180
+ overflow-y: visible !important;
181
+ }
182
+ .output-group {
183
+ border: 1px solid #ddd;
184
+ border-radius: 5px;
185
+ padding: 10px;
186
+ margin-bottom: 20px;
187
+ }
188
+ /* ์Šคํฌ๋กค๋ฐ” ์Šคํƒ€์ผ ์ˆ˜์ • */
189
+ ::-webkit-scrollbar {
190
+ width: 10px;
191
+ }
192
+ ::-webkit-scrollbar-track {
193
+ background: #f1f1f1;
194
+ }
195
+ ::-webkit-scrollbar-thumb {
196
+ background: #888;
197
+ border-radius: 5px;
198
+ }
199
+ ::-webkit-scrollbar-thumb:hover {
200
+ background: #555;
201
+ }
202
+ """
203
+
204
+ with gr.Blocks(css=css, theme="Nymbo/Nymbo_Theme") as demo:
205
+ gr.Markdown("# 300: HuggingFace Most Liked Spaces")
206
+
207
+ with gr.Row():
208
+ with gr.Column(scale=1):
209
+ space_rows = []
210
+ for space in formatted_spaces:
211
+ with gr.Row(elem_classes="space-row") as space_row:
212
+ with gr.Column():
213
+ gr.Markdown(f"{space['name']} by {space['author']} (Likes: {space['likes']})", elem_classes="space-info")
214
+ button = gr.Button("ํด๋ฆญ", elem_classes="minimal-button")
215
+ space_rows.append((space_row, button, space))
216
+
217
+ with gr.Column(scale=1):
218
+ with gr.Group(elem_classes="output-group"):
219
+ info_output = gr.Textbox(label="Space ์ •๋ณด ๋ฐ ์š”์•ฝ", elem_id="info-output", lines=20, max_lines=30)
220
+ url_state = gr.State("")
221
+ last_url_state = gr.State("")
222
+
223
+ screenshot_output = gr.Image(type="pil", label="Live ํ™”๋ฉด", height=360, width=600)
224
+ refresh_button = gr.Button("๐Ÿ”„ ์ƒˆ๋กœ๊ณ ์นจ", elem_id="refresh-button")
225
+ manual_button = gr.Button("์„ ํƒ ์„œ๋น„์Šค ๋ฉ”๋‰ด์–ผ", elem_id="manual-button")
226
+
227
+ with gr.Group(elem_classes="output-group"):
228
+ usage_guide = gr.Textbox(label="์„ ํƒ ์„œ๋น„์Šค ํŠน์ง• ๋ฐ ์‚ฌ์šฉ๋ฒ•", elem_id="usage-guide", visible=False, lines=20, max_lines=30)
229
+
230
+ with gr.Group(elem_classes="output-group"):
231
+ app_py_content = gr.Code(language="python", label="๋ฉ”์ธ ์†Œ์Šค์ฝ”๋“œ", elem_id="app-py-content", lines=None, max_lines=None)
232
+
233
+ update_trigger = gr.Button("Update Screenshot", visible=False)
234
+
235
+ for _, button, space in space_rows:
236
+ button.click(
237
+ lambda s=space: on_select(s),
238
+ inputs=[],
239
+ outputs=[info_output, app_py_content, url_state]
240
+ ).then(
241
+ update_screenshot,
242
+ inputs=[url_state, last_url_state],
243
+ outputs=[screenshot_output, last_url_state]
244
+ )
245
+
246
+ def refresh_screenshot(url, last_url):
247
+ print(f"Refresh button clicked. URL: {url}, Last URL: {last_url}")
248
+ return update_screenshot(url, last_url)
249
+
250
+ refresh_button.click(
251
+ refresh_screenshot,
252
+ inputs=[url_state, last_url_state],
253
+ outputs=[screenshot_output, last_url_state]
254
+ )
255
+
256
+ def show_usage_guide(app_content):
257
+ usage_text = generate_usage_guide(app_content)
258
+ return gr.update(value=usage_text, visible=True)
259
+
260
+ manual_button.click(
261
+ show_usage_guide,
262
+ inputs=[app_py_content],
263
+ outputs=[usage_guide]
264
+ )
265
+
266
+ update_trigger.click(
267
+ update_screenshot,
268
+ inputs=[url_state, last_url_state],
269
+ outputs=[screenshot_output, last_url_state]
270
+ )
271
+
272
+ # Start a background thread to trigger updates
273
+ def trigger_updates():
274
+ while True:
275
+ time.sleep(5)
276
+ update_trigger.click()
277
+
278
+ threading.Thread(target=trigger_updates, daemon=True).start()
279
+
280
+ return demo
281
+
282
+ except Exception as e:
283
+ print(f"Error in create_ui: {str(e)}")
284
+ print(traceback.format_exc())
285
+ raise
286
+
287
+ if __name__ == "__main__":
288
+ try:
289
+ demo = create_ui()
290
+ demo.launch()
291
+ except Exception as e:
292
+ print(f"Error in main: {str(e)}")
293
+ print(traceback.format_exc())