import gradio as gr from huggingface_hub import InferenceClient import os import requests from typing import List, Dict, Union import traceback from selenium import webdriver from selenium.common.exceptions import WebDriverException from PIL import Image from io import BytesIO from playwright.sync_api import sync_playwright 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) > 1000: # 내용이 너무 길면 잘라냅니다 content = content[:1000] + "... (content truncated)" 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: summary = summarize_space(space) app_content = get_app_py_content(space['id']) screenshot = take_screenshot(space['url']) 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}" return info, app_content, screenshot except Exception as e: print(f"Error in on_select: {str(e)}") print(traceback.format_exc()) return f"오류가 발생했습니다: {str(e)}", "", Image.new('RGB', (1, 1)) def take_screenshot(url): try: with sync_playwright() as p: browser = p.chromium.launch() page = browser.new_page() page.goto(url) screenshot = page.screenshot() browser.close() return Image.open(BytesIO(screenshot)) except Exception as e: print(f"Screenshot error: {str(e)}") return Image.new('RGB', (1, 1)) 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;} """ with gr.Blocks(css=css, theme="Nymbo/Nymbo_Theme") as demo: gr.Markdown("# Hugging Face 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=16) screenshot_output = gr.Image(type="pil", label="Live 화면", height=360, width=540) app_py_content = gr.Code(language="python", label="app.py 내용") for _, button, space in space_rows: button.click( lambda s=space: on_select(s), inputs=[], outputs=[info_output, screenshot_output, app_py_content] ) return demo except Exception as e: print(f"Error in create_ui: {str(e)}") print(traceback.format_exc()) raise if __name__ == "__main__": try: # Playwright 브라우저 및 의존성 설치 import subprocess subprocess.run(["playwright", "install", "chromium"], check=True) subprocess.run(["playwright", "install-deps"], check=True) demo = create_ui() demo.launch() except Exception as e: print(f"Error in main: {str(e)}") print(traceback.format_exc())