awacke1 commited on
Commit
728ab87
·
verified ·
1 Parent(s): 270abe3

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +188 -0
app.py ADDED
@@ -0,0 +1,188 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from typing import List, Dict
2
+ import httpx
3
+ import gradio as gr
4
+ import pandas as pd
5
+ from huggingface_hub import HfApi, ModelCard
6
+ import base64
7
+ import io
8
+ import zipfile
9
+ import asyncio
10
+ import aiohttp
11
+ from pathlib import Path
12
+ import emoji
13
+
14
+ def search_hub(query: str, search_type: str) -> pd.DataFrame:
15
+ api = HfApi()
16
+ if search_type == "Models":
17
+ results = api.list_models(search=query)
18
+ data = [{"id": model.modelId, "author": model.author, "downloads": model.downloads, "link": f"https://huggingface.co/{model.modelId}"} for model in results]
19
+ elif search_type == "Datasets":
20
+ results = api.list_datasets(search=query)
21
+ data = [{"id": dataset.id, "author": dataset.author, "downloads": dataset.downloads, "link": f"https://huggingface.co/datasets/{dataset.id}"} for dataset in results]
22
+ elif search_type == "Spaces":
23
+ results = api.list_spaces(search=query)
24
+ data = [{"id": space.id, "author": space.author, "link": f"https://huggingface.co/spaces/{space.id}"} for space in results]
25
+ else:
26
+ data = []
27
+
28
+ # Add numbering and format the link
29
+ for i, item in enumerate(data, 1):
30
+ item['number'] = i
31
+ item['formatted_link'] = format_link(item, i, search_type)
32
+
33
+ return pd.DataFrame(data)
34
+
35
+ def format_link(item: Dict, number: int, search_type: str) -> str:
36
+ link = item['link']
37
+ readme_link = f"{link}/blob/main/README.md"
38
+ title = f"{number}. {item['id']}"
39
+
40
+ metadata = f"Author: {item['author']}"
41
+ if 'downloads' in item:
42
+ metadata += f", Downloads: {item['downloads']}"
43
+
44
+ html = f"""
45
+ <div style="margin-bottom: 10px;">
46
+ <strong>{title}</strong><br>
47
+ <a href="{link}" target="_blank" style="color: #4a90e2; text-decoration: none;">View {search_type[:-1]}</a> |
48
+ <a href="{readme_link}" target="_blank" style="color: #4a90e2; text-decoration: none;">View README</a><br>
49
+ <small>{metadata}</small>
50
+ </div>
51
+ """
52
+ return html
53
+
54
+ async def download_readme(session: aiohttp.ClientSession, item: Dict) -> tuple[str, str]:
55
+ """Download README.md file for a given item."""
56
+ item_id = item['id']
57
+ raw_url = f"https://huggingface.co/{item_id}/raw/main/README.md"
58
+ try:
59
+ async with session.get(raw_url) as response:
60
+ if response.status == 200:
61
+ content = await response.text()
62
+ return item_id.replace('/', '_'), content
63
+ return item_id.replace('/', '_'), f"# Error downloading README for {item_id}\nStatus code: {response.status}"
64
+ except Exception as e:
65
+ return item_id.replace('/', '_'), f"# Error downloading README for {item_id}\nError: {str(e)}"
66
+
67
+ async def download_all_readmes(data: List[Dict]) -> str:
68
+ """Download all README files and create a zip archive."""
69
+ zip_buffer = io.BytesIO()
70
+
71
+ async with aiohttp.ClientSession() as session:
72
+ # Download all READMEs concurrently
73
+ tasks = [download_readme(session, item) for item in data]
74
+ results = await asyncio.gather(*tasks)
75
+
76
+ # Create zip file
77
+ with zipfile.ZipFile(zip_buffer, 'w', zipfile.ZIP_DEFLATED) as zip_file:
78
+ for filename, content in results:
79
+ zip_file.writestr(f"{filename}.md", content)
80
+
81
+ # Convert to base64
82
+ zip_buffer.seek(0)
83
+ base64_zip = base64.b64encode(zip_buffer.getvalue()).decode()
84
+ return base64_zip
85
+
86
+ def create_download_link(base64_zip: str) -> str:
87
+ """Create an HTML download link for the zip file."""
88
+ download_link = f"""
89
+ <a href="data:application/zip;base64,{base64_zip}"
90
+ download="readmes.zip"
91
+ style="display: inline-block; padding: 10px 20px;
92
+ background-color: #4CAF50; color: white;
93
+ text-decoration: none; border-radius: 5px;
94
+ margin-top: 10px;">
95
+ 📥 Download READMEs Archive
96
+ </a>
97
+ """
98
+ return download_link
99
+
100
+ def display_results(df: pd.DataFrame):
101
+ if df is not None and not df.empty:
102
+ html = "<div style='max-height: 400px; overflow-y: auto;'>"
103
+ for _, row in df.iterrows():
104
+ html += row['formatted_link']
105
+ html += "</div>"
106
+ return html
107
+ else:
108
+ return "<p>No results found.</p>"
109
+
110
+ def SwarmyTime(data: List[Dict]) -> Dict:
111
+ """Aggregates all content from the given data."""
112
+ aggregated = {
113
+ "total_items": len(data),
114
+ "unique_authors": set(),
115
+ "total_downloads": 0,
116
+ "item_types": {"Models": 0, "Datasets": 0, "Spaces": 0}
117
+ }
118
+
119
+ for item in data:
120
+ aggregated["unique_authors"].add(item.get("author", "Unknown"))
121
+ aggregated["total_downloads"] += item.get("downloads", 0)
122
+
123
+ if "modelId" in item:
124
+ aggregated["item_types"]["Models"] += 1
125
+ elif "dataset" in item.get("id", ""):
126
+ aggregated["item_types"]["Datasets"] += 1
127
+ else:
128
+ aggregated["item_types"]["Spaces"] += 1
129
+
130
+ aggregated["unique_authors"] = len(aggregated["unique_authors"])
131
+ return aggregated
132
+
133
+ with gr.Blocks() as demo:
134
+ gr.Markdown("## Search the Hugging Face Hub")
135
+ with gr.Row():
136
+ search_query = gr.Textbox(label="Search Query", value="awacke1")
137
+ search_type = gr.Radio(["Models", "Datasets", "Spaces"], label="Search Type", value="Models")
138
+ search_button = gr.Button("Search")
139
+
140
+ results_html = gr.HTML(label="Search Results")
141
+ download_html = gr.HTML(label="Download Link")
142
+ metadata_output = gr.Textbox(label="Metadata", lines=10)
143
+ aggregated_output = gr.JSON(label="Aggregated Content")
144
+
145
+ current_results = gr.State([]) # Store current search results
146
+
147
+ async def search_and_aggregate(query, search_type):
148
+ df = search_hub(query, search_type)
149
+ data = df.to_dict('records')
150
+ aggregated = SwarmyTime(data)
151
+ html_results = display_results(df)
152
+
153
+ # Create download button
154
+ download_button = """
155
+ <button onclick="downloadReadmes()"
156
+ style="padding: 10px 20px;
157
+ background-color: #4CAF50;
158
+ color: white;
159
+ border: none;
160
+ border-radius: 5px;
161
+ cursor: pointer;">
162
+ 📚 Download All READMEs
163
+ </button>
164
+ """
165
+
166
+ return html_results, download_button, aggregated, data
167
+
168
+ async def download_readmes(data):
169
+ if not data:
170
+ return "No results to download"
171
+
172
+ base64_zip = await download_all_readmes(data)
173
+ return create_download_link(base64_zip)
174
+
175
+ search_button.click(
176
+ search_and_aggregate,
177
+ inputs=[search_query, search_type],
178
+ outputs=[results_html, download_html, aggregated_output, current_results]
179
+ )
180
+
181
+ # Add download button click handler
182
+ download_html.click(
183
+ download_readmes,
184
+ inputs=[current_results],
185
+ outputs=[download_html]
186
+ )
187
+
188
+ demo.launch(debug=True)