Skip to content

Commit

Permalink
v0.1.2-pre5 queued up/downloads, better quantization and conversion h…
Browse files Browse the repository at this point in the history
…andling
  • Loading branch information
christianazinn committed Apr 17, 2024
1 parent 8d6ccf1 commit ff7905a
Show file tree
Hide file tree
Showing 10 changed files with 69 additions and 92 deletions.
2 changes: 1 addition & 1 deletion Homepage.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# main.py
# Version 0.1.2-pre5: Aesthetics and minor fixes
# Version 0.1.2-pre5: Bugfixes, better quantization and conversion handling, and queued up/downloads.
import streamlit as st
st.set_page_config(layout="wide")
from st_pages import Page, Section, show_pages, add_indentation
Expand Down
4 changes: 1 addition & 3 deletions TODO.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
TODO allow gpu offload for certain tasks
TODO be able to queue later jobs for files that don't yet exist (i.e. convert then quantize) and handle errors in ordering
TODO add a page that allows you to make one great big queued op for download/convert/quantize/(imatrix)/upload/etc
TODO be able to queue later jobs for files that don't yet exist (i.e. convert then quantize) and handle errors in ordering/make a page for it
TODO LLaMA-Factory integration
TODO Lilac integration?
TODO support further cli options for relevant commands/pages

# ON DECK
TODO create scripts for download/upload and use those as commands for download/upload (shocker)
TODO imatrix creation
TODO imatrix quantization support
TODO readme creation from template!
Expand Down
2 changes: 1 addition & 1 deletion pages/Convert_Safetensors.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# FILESTATUS: pretty much done, needs testing. Last updated v0.1.2-pre3
# FILESTATUS: needs expanded functionality. Last updated v0.1.2-pre5
# IMPORTS ---------------------------------------------------------------------------------
import streamlit as st
st.set_page_config(layout="wide")
Expand Down
27 changes: 4 additions & 23 deletions pages/Hugging_Face_Downloader.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# FILESTATUS: completed, needs testing. Last updated v0.1.2-pre3
# FILESTATUS: completed, needs testing. Last updated v0.1.2-pre5
# IMPORTS ---------------------------------------------------------------------------------
import requests, streamlit as st
st.set_page_config(layout="wide")
Expand All @@ -8,29 +8,10 @@
from util.paths import *

# FUNCTIONS ---------------------------------------------------------------------------------
# TODO be able to change output directory
# TODO write new scheduler and parallelize
# TODO maybe you need to make another scheduler for just download jobs while the other is used for conversion/quantization/finetuning jobs

# write the download task to the queue
def queue_command(file_url, download_path, filename):
command = [
"aria2c", file_url,
"--max-connection-per-server=16", "--split=8", "--min-split-size=25M", "--allow-overwrite=true",
"-d", str(download_path), "-o", filename,
"--continue=true"
]
get_scheduler().add_job(command)

# queues a download task for each file in the file_links_dict
def trigger_command(file_links_dict, model_name):
folder_name = model_name.split("/")[-1]
download_path = models_dir() / folder_name
download_path.mkdir(parents=True, exist_ok=True)

for file_name, file_url in file_links_dict.items():
filename = Path(file_name).name
queue_command(file_url, download_path, filename)
def trigger_command(model_name):
get_scheduler().add_job(["python3", "util/download.py", model_name])

return "Download tasks have been queued."

Expand Down Expand Up @@ -77,7 +58,7 @@ def get_files_from_repo(url, repo_name):

if st.button("Download Files"):
if 'file_links_dict' in st.session_state and st.session_state['file_links_dict']:
queue_message = trigger_command(st.session_state['file_links_dict'], model_name)
queue_message = trigger_command(model_name)
st.text(queue_message)
else:
st.error("No files to download. Please get the file list first.")
Expand Down
2 changes: 1 addition & 1 deletion pages/Quantize_GGUF.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# FILESTATUS: migrated implementation but need to finish testing pre1 before this can be used and tested. Last updated v0.1.2-pre4
# FILESTATUS: needs expanded functionality. Last updated v0.1.2-pre5
# IMPORTS ---------------------------------------------------------------------------------
import os, streamlit as st
st.set_page_config(layout="wide")
Expand Down
80 changes: 20 additions & 60 deletions pages/Upload_Converted_To_HF.py
Original file line number Diff line number Diff line change
@@ -1,66 +1,35 @@
# FILESTATUS: needs to be migrated to the New Way of Doing Things. Last updated v0.1.2-pre3
# FILESTATUS: needs potentially expanded functionality. Last updated v0.1.2-pre5
# IMPORTS ---------------------------------------------------------------------------------
import os, streamlit as st
st.set_page_config(layout="wide")
from st_pages import add_indentation
from huggingface_hub import HfApi
from requests.exceptions import HTTPError
from util.paths import *
from util.scheduler import *
from util.key import decrypt_token

# FUNCTIONS ---------------------------------------------------------------------------------

# Search for the llama.cpp directory
if not llama_cpp_dir():
st.error("llama.cpp directory not found. Please check the file structure.")
# Gathers files and uploads to HuggingFace
def trigger_command(token, repo_name, files_to_upload, high_precision_files, medium_precision_files, selected_model):
final_upload = []

## Uses username from HF Token
def get_username_from_token(token):
api = HfApi()
user_info = api.whoami(token=token)
return user_info['name']
# Rename particular filepaths
for file_name in files_to_upload:
if file_name in high_precision_files.get(selected_model, []):
folder_path = models_dir() / selected_model / "High-Precision-Quantization"
elif file_name in medium_precision_files.get(selected_model, []):
folder_path = models_dir() / selected_model / "Medium-Precision-Quantization"
else:
continue

file_path = folder_path / file_name
final_upload.append(str(file_path))

# Gathers files and uploads to HuggingFace
def upload_files_to_repo(token, repo_name, files_to_upload, readme_content, high_precision_files, medium_precision_files, selected_model):
try:
api = HfApi()
username = get_username_from_token(token)
repo_id = f"{username}/{repo_name}"

# Check if the repository exists, if not create it
try:
api.repo_info(repo_id=repo_id, token=token)
except HTTPError as e:
if e.response.status_code == 404:
api.create_repo(repo_id=repo_id, token=token, repo_type="model")
else:
raise

# Upload README.md if content is provided
if readme_content:
readme_path = models_dir() / 'README.md'
with open(str(readme_path), 'w') as readme_file:
readme_file.write(readme_content)
api.upload_file(path_or_fileobj=str(readme_path), path_in_repo='README.md', repo_id=repo_id, token=token)
os.remove(str(readme_path))

# Upload selected files
for file_name in files_to_upload:
if file_name in high_precision_files.get(selected_model, []):
folder_path = models_dir() / selected_model / "High-Precision-Quantization"
elif file_name in medium_precision_files.get(selected_model, []):
folder_path = models_dir() / selected_model / "Medium-Precision-Quantization"
else:
continue

file_path = folder_path / file_name
if file_path.is_file():
api.upload_file(path_or_fileobj=str(file_path), path_in_repo=file_name, repo_id=repo_id, token=token)

return f"Files uploaded successfully. View at: https://huggingface.co/{repo_id}"
except Exception as e:
return f"An error occurred: {str(e)}"
command = ["python3", "util/upload.py", token, repo_name, *final_upload]
get_scheduler().add_job(command)
return "Upload tasks have been queued."

# Cache the function to improve performance
@st.cache_data
Expand Down Expand Up @@ -103,8 +72,7 @@ def get_combined_files(model):


# Repository details and README content
repo_name = st.text_input("Repository Name", value=f"{selected_model}-GGUF")
readme_content = st.text_area("README.md Content", "Enter content for README.md")
repo_name = st.text_input("Repository Name", value=f"{selected_model}-gguf")

# Token input
use_unencrypted_token = st.checkbox("Unencrypted Token")
Expand All @@ -117,15 +85,7 @@ def get_combined_files(model):

# Upload button
if st.button("Upload Selected Files") and hf_token:
upload_message = upload_files_to_repo(
token=hf_token,
repo_name=repo_name,
files_to_upload=selected_files,
readme_content=readme_content,
high_precision_files=high_precision_files,
medium_precision_files=medium_precision_files,
selected_model=selected_model
)
upload_message = trigger_command(hf_token, repo_name, selected_files, high_precision_files, medium_precision_files, selected_model)
st.info(upload_message)

if 'HUGGINGFACE_TOKEN' in os.environ:
Expand Down
7 changes: 6 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,9 @@ cryptography
st-pages
streamlit-sortables
torch~=2.1.1
einops~=0.7.0
einops~=0.7.0
numpy~=1.24.4
sentencepiece~=0.1.98
transformers>=4.35.2,<5.0.0
gguf>=0.1.0
protobuf>=4.21.0,<5.0.0
11 changes: 11 additions & 0 deletions util/download.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# FILESTATUS Complete and tested. Last updated 0.1.2-pre5
import sys
from huggingface_hub import snapshot_download
from pathlib import Path

# Simple download script. full_model_name comes in the form of "model_creator/model_name"
full_model_name = sys.argv[1]
model_creator, model_name = full_model_name.split("/")
download_path = Path("llama.cpp/models") / model_name
download_path.mkdir(parents=True, exist_ok=True)
snapshot_download(repo_id=f"{model_creator}/{model_name}", local_dir=str(download_path))
3 changes: 1 addition & 2 deletions util/scheduler.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# FILESTATUS: fully implemented but needs significant testing for efficiency, thread safety, bugfixing, overall functionality. Last updated v0.1.2-pre4
# FILESTATUS: fully implemented but needs significant testing for efficiency, thread safety, bugfixing, overall functionality. Last updated v0.1.2-pre5
# IMPORTS ---------------------------------------------------------------------------------
from pathlib import Path
from datetime import datetime
Expand All @@ -7,7 +7,6 @@

# FUNCTIONS ---------------------------------------------------------------------------------

# TODO perhaps make download tasks independent of other tasks? but then you run into thread safety issues I think
# the scheduler singleton class (do i need st.cache_resource here?)
@st.cache_resource
class Scheduler:
Expand Down
23 changes: 23 additions & 0 deletions util/upload.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# FILESTATUS Complete and tested. Last updated 0.1.2-pre5
import sys
from huggingface_hub import HfApi
from requests.exceptions import HTTPError

# Simple upload script. full_model_name comes in the form of "model_creator/model_name"
token = sys.argv[1]
api = HfApi()
username = api.whoami(token=token)['name']
repo_id = f"{username}/{sys.argv[2]}"

# Check if the repository exists, if not create it
try:
api.repo_info(repo_id=repo_id, token=token)
except HTTPError as e:
if e.response.status_code == 404:
api.create_repo(repo_id=repo_id, token=token, repo_type="model")
else:
raise

# Upload selected files
for file_name in sys.argv[3:]:
api.upload_file(path_or_fileobj=file_name, path_in_repo=file_name, repo_id=repo_id, token=token)

0 comments on commit ff7905a

Please sign in to comment.