import gradio as gr from huggingface_hub import InferenceClient import os import requests from typing import List, Dict, Union import traceback from PIL import Image from io import BytesIO import asyncio from gradio_client import Client import time import threading HF_TOKEN = os.getenv("HF_TOKEN") hf_client = InferenceClient("CohereForAI/c4ai-command-r-plus-08-2024", token=HF_TOKEN) def get_headers(): if not HF_TOKEN: raise ValueError("Hugging Face token not found in environment variables") return {"Authorization": f"Bearer {HF_TOKEN}"} def get_most_liked_spaces(limit: int = 300) -> Union[List[Dict], str]: url = "https://huggingface.co/api/spaces" params = { "sort": "likes", "direction": -1, "limit": limit, "full": "true" } try: response = requests.get(url, params=params, headers=get_headers()) response.raise_for_status() return response.json() except requests.RequestException as e: return f"API request error: {str(e)}" except ValueError as e: return f"JSON decoding error: {str(e)}" def format_space(space: Dict) -> Dict: space_id = space.get('id', 'Unknown') space_name = space_id.split('/')[-1] if '/' in space_id else space_id space_author = space.get('author', 'Unknown') if isinstance(space_author, dict): space_author = space_author.get('user', space_author.get('name', 'Unknown')) space_likes = space.get('likes', 'N/A') space_url = f"https://huggingface.co/spaces/{space_id}" return { "id": space_id, "name": space_name, "author": space_author, "likes": space_likes, "url": space_url, } def format_spaces(spaces: Union[List[Dict], str]) -> List[Dict]: if isinstance(spaces, str): return [{"error": spaces}] return [format_space(space) for space in spaces if isinstance(space, dict)] def summarize_space(space: Dict) -> str: system_message = "당신은 Hugging Face Space의 내용을 요약하는 AI 조수입니다. 주어진 정보를 바탕으로 간결하고 명확한 요약을 제공해주세요." user_message = f"다음 Hugging Face Space를 요약해주세요: {space['name']} by {space['author']}. 좋아요 수: {space['likes']}. URL: {space['url']}" messages = [ {"role": "system", "content": system_message}, {"role": "user", "content": user_message} ] try: response = hf_client.chat_completion(messages, max_tokens=400, temperature=0.7) return response.choices[0].message.content except Exception as e: return f"요약 생성 중 오류 발생: {str(e)}" def get_app_py_content(space_id: str) -> str: app_py_url = f"https://huggingface.co/spaces/{space_id}/raw/main/app.py" try: response = requests.get(app_py_url, headers=get_headers()) if response.status_code == 200: content = response.text if len(content) > 500: # 내용을 500자로 제한합니다 content = content[:497] + "..." return content else: return f"app.py file not found or inaccessible for space: {space_id}" except requests.RequestException: return f"Error fetching app.py content for space: {space_id}" def on_select(space): try: print(f"Selected space: {space['name']}") summary = summarize_space(space) app_content = get_app_py_content(space['id']) info = f"선택된 Space: {space['name']} (ID: {space['id']})\n" info += f"Author: {space['author']}\n" info += f"Likes: {space['likes']}\n" info += f"URL: {space['url']}\n\n" info += f"요약:\n{summary}" print(f"Returning URL: {space['url']}") return info, app_content, space['url'] except Exception as e: print(f"Error in on_select: {str(e)}") print(traceback.format_exc()) return f"오류가 발생했습니다: {str(e)}", "", "" def update_screenshot(url, last_url, force_update=False): print(f"Updating screenshot. Current URL: {url}, Last URL: {last_url}, Force update: {force_update}") if url and (url != last_url or force_update): screenshot = take_screenshot(url) print("Screenshot updated") return screenshot, url print("No update needed") return gr.update(), last_url def refresh_screenshot(url, last_url): print(f"Refresh button clicked. URL: {url}, Last URL: {last_url}") # 항상 강제로 업데이트 return update_screenshot(url, last_url, force_update=True) def take_screenshot(url): try: print(f"Taking screenshot of URL: {url}") client = Client("ginipick/selenium-screenshot-gradio") result = client.predict(url=url, api_name="/predict") print(f"Screenshot result: {result}") if isinstance(result, str) and os.path.exists(result): return Image.open(result) else: print(f"Invalid result from API: {result}") return Image.new('RGB', (600, 360), color='lightgray') except Exception as e: print(f"Screenshot error: {str(e)}") return Image.new('RGB', (600, 360), color='lightgray') def create_ui(): try: spaces_list = get_most_liked_spaces() print(f"Type of spaces_list: {type(spaces_list)}") formatted_spaces = format_spaces(spaces_list) print(f"Total spaces loaded: {len(formatted_spaces)}") css = """ footer {visibility: hidden;} .minimal-button {min-width: 30px !important; height: 25px !important; line-height: 1 !important; font-size: 12px !important; padding: 2px 5px !important;} .space-row {margin-bottom: 5px !important;} #refresh-button { width: 100% !important; margin-top: 5px !important; } """ with gr.Blocks(css=css, theme="Nymbo/Nymbo_Theme") as demo: gr.Markdown("# 300: HuggingFace Most Liked Spaces") with gr.Row(): with gr.Column(scale=1): space_rows = [] for space in formatted_spaces: with gr.Row(elem_classes="space-row") as space_row: with gr.Column(): gr.Markdown(f"{space['name']} by {space['author']} (Likes: {space['likes']})", elem_classes="space-info") button = gr.Button("클릭", elem_classes="minimal-button") space_rows.append((space_row, button, space)) with gr.Column(scale=1): info_output = gr.Textbox(label="Space 정보 및 요약", lines=20) url_state = gr.State("") last_url_state = gr.State("") screenshot_output = gr.Image(type="pil", label="Live 화면", height=360, width=600) refresh_button = gr.Button("🔄 새로고침", elem_id="refresh-button") app_py_content = gr.Code(language="python", label="메인 소스코드") update_trigger = gr.Button("Update Screenshot", visible=False) for _, button, space in space_rows: button.click( lambda s=space: on_select(s), inputs=[], outputs=[info_output, app_py_content, url_state] ).then( update_screenshot, inputs=[url_state, last_url_state], outputs=[screenshot_output, last_url_state] ) def refresh_screenshot(url, last_url): print(f"Refresh button clicked. URL: {url}, Last URL: {last_url}") return update_screenshot(url, last_url) refresh_button.click( refresh_screenshot, inputs=[url_state, last_url_state], outputs=[screenshot_output, last_url_state] ) update_trigger.click( update_screenshot, inputs=[url_state, last_url_state], outputs=[screenshot_output, last_url_state] ) # Start a background thread to trigger updates def trigger_updates(): while True: time.sleep(5) update_trigger.click() threading.Thread(target=trigger_updates, daemon=True).start() return demo except Exception as e: print(f"Error in create_ui: {str(e)}") print(traceback.format_exc()) raise if __name__ == "__main__": try: demo = create_ui() demo.launch() except Exception as e: print(f"Error in main: {str(e)}") print(traceback.format_exc())