Sayoyo commited on
Commit
f93d5f5
1 Parent(s): 357b224

[feat] first commit

Browse files
Files changed (7) hide show
  1. .gitignore +2 -0
  2. About.md +1 -0
  3. app.py +179 -0
  4. requirements.txt +4 -0
  5. src/schema.py +13 -0
  6. src/skill_db.py +98 -0
  7. src/tools.py +31 -0
.gitignore ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ venv/
2
+ __pycache__/
About.md ADDED
@@ -0,0 +1 @@
 
 
1
+ # Skill Library Hub
app.py ADDED
@@ -0,0 +1,179 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from typing import List
2
+ import streamlit as st
3
+ import extra_streamlit_components as stx
4
+ from streamlit_searchbox import st_searchbox
5
+ from pathlib import Path
6
+ from streamlit_tags import st_tags
7
+ from src.tools import hf_pull_skill, time_ago
8
+ from src.skill_db import SkillsDB
9
+ from src.schema import Skill
10
+ st.title("Skill Library Hub")
11
+
12
+ skill_db = SkillsDB('skills.db')
13
+ all_skills = skill_db.get_skills()
14
+
15
+ all_tags = skill_db.get_tags()
16
+
17
+ if all_skills is None:
18
+ all_skills = []
19
+
20
+ def search(searchterm: str) -> List[any]:
21
+ global all_skills
22
+ global skill_db
23
+ if all_skills is None:
24
+ if skill_db is None:
25
+ skill_db = SkillsDB('skills.db')
26
+ all_skills = skill_db.get_skills()
27
+ result = []
28
+ if all_skills is not None and len(all_skills) > 0:
29
+ for skill in all_skills:
30
+ if searchterm.lower() in skill.skill_name.lower():
31
+ result.append(skill.skill_name.lower())
32
+ if searchterm.lower() in skill.author.lower():
33
+ result.append(skill.author.lower())
34
+ if len(result)>10:
35
+ return result
36
+ if len(result)<3:
37
+ for skill in all_skills:
38
+ if searchterm.lower() in skill.skill_description.lower():
39
+ result.append(skill.skill_description.lower())
40
+ if len(result)>10:
41
+ return result
42
+ return result
43
+ return result
44
+
45
+ program_languages = ["python", "r", "julia", "javascript", "html", "shell", "applescript"]
46
+
47
+ def main_page():
48
+ global all_skills
49
+ global skill_db
50
+ if all_skills is None:
51
+ if skill_db is None:
52
+ skill_db = SkillsDB('skills.db')
53
+ all_skills = skill_db.get_skills()
54
+
55
+ selected_languages = []
56
+ selected_tags = []
57
+ with st.sidebar:
58
+ st.title("🎈 Search Skills")
59
+ with st.expander("✨ PROGRAM", True):
60
+ if st.checkbox("Python"):
61
+ selected_languages.append("python")
62
+ if st.checkbox("Julia"):
63
+ selected_languages.append("julia")
64
+ if st.checkbox("R"):
65
+ selected_languages.append("r")
66
+ if st.checkbox("Javascript"):
67
+ selected_languages.append("javascript")
68
+ if st.checkbox("Html"):
69
+ selected_languages.append("html")
70
+ if st.checkbox("Shell"):
71
+ selected_languages.append("shell")
72
+ if st.checkbox("AppleScript"):
73
+ selected_languages.append("applescript")
74
+
75
+ with st.expander("🔖 TAGS", True):
76
+ if all_tags is not None:
77
+ for tag in all_tags:
78
+ if st.checkbox(tag):
79
+ selected_tags.append(tag)
80
+
81
+ if not selected_languages:
82
+ selected_languages = program_languages
83
+
84
+ all_skills = [item for item in all_skills if item.skill_program_language in selected_languages]
85
+
86
+ if not selected_tags and all_tags:
87
+ selected_tags = all_tags
88
+ all_skills = [item for item in all_skills if set(item.skill_tags) & set(selected_tags)]
89
+
90
+ selected_value = st_searchbox(
91
+ search,
92
+ key="",
93
+ )
94
+
95
+ print(f"selected_value: {selected_value}")
96
+ selected_skills = all_skills
97
+ if selected_value is None and len(selected_skills)!= len(all_skills):
98
+ selected_skills = all_skills
99
+
100
+ if selected_value is not None:
101
+ all_skills = [item for item in all_skills if selected_value.lower() in item.skill_name.lower() or
102
+ selected_value.lower() in item.author.lower() or
103
+ selected_value.lower() in item.skill_description.lower()]
104
+
105
+ if all_skills is not None and len(all_skills) > 0:
106
+ for skill in all_skills:
107
+ with st.expander(f"{skill.author}/{skill.skill_name}", expanded=True):
108
+ tags = "`{}`".format("`\t\t`".join(skill.skill_tags))
109
+ st.markdown(f"{tags}")
110
+ st.markdown(f"**<a href='https://huggingface.co/spaces/{skill.repo_id}?page=detail_page&skill_name={skill.skill_name}' style='font-size: 22px;' target='_self'>{skill.author}/{skill.skill_name}</a>**", unsafe_allow_html=True)
111
+ st.markdown(f">**{skill.skill_description}**")
112
+ st.markdown("Install:")
113
+ install = f"import creator\ncreator.create(huggingface_repo_id=\"{skill.repo_id}\", huggingface_skill_path=\"{skill.skill_name}\")"
114
+ st.code(install, language=skill.skill_program_language)
115
+ st.markdown("Usage:")
116
+ usage = f"{skill.skill_usage_example}"
117
+ if skill.skill_program_language.lower() == "python":
118
+ usage = f"from {skill.repo_id.replace('/', '.')}.skill_code import {skill.skill_name}\n"+usage
119
+ st.code(usage, language=skill.skill_program_language)
120
+ st.markdown(f"`Created {time_ago(skill.created_at)}` `{skill.skill_program_language}`")
121
+ else:
122
+ st.markdown(f"### 🎉 Search results for `{selected_value}`")
123
+ st.markdown(f"**No results found**")
124
+
125
+ def about_page():
126
+ file_path = "About.md"
127
+ with open(file_path, 'r', encoding='utf-8') as file:
128
+ content = file.read()
129
+ st.write(content, unsafe_allow_html=True)
130
+
131
+ def submit_page():
132
+ global all_skills
133
+ global skill_db
134
+ if all_skills is None:
135
+ if skill_db is None:
136
+ skill_db = SkillsDB('skills.db')
137
+ all_skills = skill_db.get_skills()
138
+ st.markdown(f"### ✉️✨ Submit your skill here!")
139
+ with st.form(key='my_form'):
140
+ skill_repository = st.text_input('Skill Repo Id:')
141
+ skill_names = st_tags(
142
+ label="Skills' name:",
143
+ text='Press enter to add every skill folder',
144
+ value=[],
145
+ suggestions=[],
146
+ maxtags = 10,
147
+ key='1')
148
+
149
+ if st.form_submit_button('Submit'):
150
+ skills = []
151
+ if skill_names is not None and len(skill_names) > 0:
152
+ for skill_name in skill_names:
153
+ skill = hf_pull_skill(skill_repository, skill_name)
154
+ skill["repo_id"] = skill_repository
155
+ skills.append(skill)
156
+
157
+ if skills is not None and len(skills) > 0:
158
+ for skill in skills:
159
+ if skill is not None:
160
+ if skill not in all_skills:
161
+ skill_obj = Skill(skill["repo_id"], skill["skill_name"], skill["skill_description"], skill["skill_metadata"]["author"], skill["skill_metadata"]["created_at"], skill["skill_usage_example"], skill["skill_program_language"], skill["skill_tags"])
162
+ result = skill_db.add_skill(skill_obj)
163
+ if result != "ok":
164
+ st.error(result)
165
+ continue
166
+ all_skills.append(skill_obj)
167
+
168
+ chosen_id = stx.tab_bar(data=[
169
+ stx.TabBarItemData(id=1, title="🏅 Skill Library", description=""),
170
+ stx.TabBarItemData(id=2, title="📝 About", description=""),
171
+ stx.TabBarItemData(id=3, title="🚀 Submit here!", description=""),
172
+ ], default=1)
173
+
174
+ if chosen_id == '1':
175
+ main_page()
176
+ elif chosen_id == '2':
177
+ about_page()
178
+ elif chosen_id == '3':
179
+ submit_page()
requirements.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ streamlit-searchbox
2
+ extra_streamlit_components
3
+ streamlit-tags
4
+ huggingface_hub
src/schema.py ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ class Skill:
2
+ def __init__(self, repo_id, skill_name, skill_description, author, created_at, skill_usage_example, skill_program_language, skill_tags):
3
+ self.repo_id = repo_id
4
+ self.skill_name = skill_name
5
+ self.skill_description = skill_description
6
+ self.author = author
7
+ self.created_at = created_at
8
+ self.skill_usage_example = skill_usage_example
9
+ self.skill_program_language = skill_program_language
10
+ self.skill_tags = skill_tags
11
+
12
+ def __str__(self) -> str:
13
+ return f"Skill: repo_id: {self.repo_id}, name: {self.skill_name}, description: {self.skill_description}, author: {self.author}, created_at: {self.created_at}, skill_usage_example: {self.skill_usage_example}, skill_program_language: {self.skill_program_language}, skill_tags: {self.skill_tags}"
src/skill_db.py ADDED
@@ -0,0 +1,98 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import sqlite3
2
+ import os
3
+ from src.schema import Skill
4
+
5
+ class SkillsDB:
6
+ def __init__(self, db_name="skills.db"):
7
+ # Check if the database file exists
8
+ db_exists = os.path.exists(db_name)
9
+
10
+ # Connect to the database
11
+ self.conn = sqlite3.connect(db_name)
12
+ self.cursor = self.conn.cursor()
13
+
14
+ # If the database file didn't exist before, create and initialize the database
15
+ if not db_exists:
16
+ self.create_db()
17
+
18
+ def create_db(self):
19
+ # Create skill table
20
+ self.cursor.execute('''
21
+ CREATE TABLE IF NOT EXISTS skills (
22
+ id INTEGER PRIMARY KEY,
23
+ repo_id TEXT NOT NULL,
24
+ skill_name TEXT NOT NULL,
25
+ skill_description TEXT,
26
+ author TEXT,
27
+ created_at TEXT,
28
+ skill_usage_example TEXT,
29
+ skill_program_language TEXT,
30
+ skill_tags TEXT
31
+ );
32
+ ''')
33
+
34
+ # Create tags table
35
+ self.cursor.execute('''
36
+ CREATE TABLE IF NOT EXISTS tags (
37
+ id INTEGER PRIMARY KEY,
38
+ tag TEXT NOT NULL UNIQUE
39
+ );
40
+ ''')
41
+
42
+ self.conn.commit()
43
+
44
+ def add_skill(self, skill):
45
+ self.cursor.execute('SELECT id FROM skills WHERE skill_name = ? AND author = ?;', (skill.skill_name, skill.author))
46
+ if self.cursor.fetchone() is not None:
47
+ return f"Skill with name '{skill.skill_name}' by author '{skill.author}' already exists!"
48
+ # Handle tags: check if they exist; if not, insert them
49
+ tag_ids = []
50
+ for tag in skill.skill_tags:
51
+ self.cursor.execute('SELECT id FROM tags WHERE tag = ?;', (tag,))
52
+ tag_id = self.cursor.fetchone()
53
+ if tag_id is None:
54
+ self.cursor.execute('INSERT INTO tags (tag) VALUES (?);', (tag,))
55
+ tag_id = self.cursor.lastrowid
56
+ else:
57
+ tag_id = tag_id[0]
58
+ tag_ids.append(str(tag_id))
59
+ tags_str = ",".join(tag_ids)
60
+
61
+ # Insert skill into skills table
62
+ self.cursor.execute('''
63
+ INSERT INTO skills (repo_id, skill_name, skill_description, author, created_at, skill_usage_example, skill_program_language, skill_tags)
64
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?);
65
+ ''', (skill.repo_id, skill.skill_name, skill.skill_description, skill.author, skill.created_at, skill.skill_usage_example, skill.skill_program_language, tags_str))
66
+
67
+ self.conn.commit()
68
+ return "ok"
69
+
70
+ def get_skills(self):
71
+ # Fetch all skills from the skills table along with column names
72
+ self.cursor.execute('SELECT * FROM skills;')
73
+ col_names = [col[0] for col in self.cursor.description]
74
+ skills_data = self.cursor.fetchall()
75
+
76
+ # Extract data using column names and create Skill objects
77
+ skills = []
78
+ for skill_data in skills_data:
79
+ skill_dict = dict(zip(col_names, skill_data))
80
+ tag_ids = skill_dict['skill_tags'].split(',')
81
+ self.cursor.execute('SELECT tag FROM tags WHERE id IN (%s);' % ','.join(['?'] * len(tag_ids)), tag_ids)
82
+ tags = [tag[0] for tag in self.cursor.fetchall()]
83
+ skill_obj = Skill(skill_dict['repo_id'], skill_dict['skill_name'], skill_dict['skill_description'], skill_dict['author'],
84
+ skill_dict['created_at'], skill_dict['skill_usage_example'], skill_dict['skill_program_language'], tags)
85
+ skills.append(skill_obj)
86
+
87
+ return skills
88
+
89
+ def get_tags(self):
90
+ # Fetch all tags from the tags table
91
+ self.cursor.execute('SELECT tag FROM tags;')
92
+ tags = self.cursor.fetchall()
93
+ if tags is not None:
94
+ return [tag[0] for tag in tags]
95
+ return []
96
+
97
+ def close(self):
98
+ self.conn.close()
src/tools.py ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ from huggingface_hub import hf_hub_download
3
+ from datetime import datetime
4
+
5
+ def hf_pull_skill(repo_id, huggingface_skill_path):
6
+ return_path = hf_hub_download(repo_id=repo_id, subfolder=huggingface_skill_path, repo_type="space", filename="skill.json")
7
+ with open(return_path) as f:
8
+ skill_json = json.load(f)
9
+ return skill_json
10
+
11
+ def time_ago(updated_at_str):
12
+ now = datetime.now()
13
+ updated_at = datetime.strptime(updated_at_str, '%Y-%m-%d %H:%M:%S')
14
+ delta = now - updated_at
15
+
16
+ minutes = delta.total_seconds() / 60
17
+ hours = minutes / 60
18
+ days = hours / 24
19
+ months = days / 30.44 # An average month length
20
+ years = days / 365.25 # Account for leap years
21
+
22
+ if minutes < 60:
23
+ return f"{int(minutes)} minutes ago"
24
+ elif hours < 24:
25
+ return f"{int(hours)} hours ago"
26
+ elif days < 30.44:
27
+ return f"{int(days)} days ago"
28
+ elif months < 12:
29
+ return f"{int(months)} months ago"
30
+ else:
31
+ return f"{int(years)} years ago"