Spaces:
Running
Running
Create upload_ui.py
Browse files- upload_ui.py +62 -0
upload_ui.py
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Uploads for hosted sessions; no access to server filesystem paths."""
|
| 2 |
+
from pathlib import Path
|
| 3 |
+
|
| 4 |
+
import streamlit as st
|
| 5 |
+
|
| 6 |
+
from app_environment import UPLOAD_ROOT, new_session_directory, remove_session_directory
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
MAX_FILE_BYTES = 1024 * 1024 * 1024
|
| 10 |
+
MAX_TOTAL_BYTES = 2 * MAX_FILE_BYTES
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
def store_uploads(files, tokenizer=None, root=UPLOAD_ROOT):
|
| 14 |
+
if not files:
|
| 15 |
+
raise ValueError('Choose a GGUF or safetensors file.')
|
| 16 |
+
names = [item.name for item in files]
|
| 17 |
+
if any(not name or '/' in name or '\\' in name or ':' in name or '\x00' in name or Path(name).name != name for name in names):
|
| 18 |
+
raise ValueError('Use plain file names for uploaded model files.')
|
| 19 |
+
if len(set(name.casefold() for name in names)) != len(names):
|
| 20 |
+
raise ValueError('Uploaded model files must have different names.')
|
| 21 |
+
if any(Path(name).suffix.lower() not in ('.gguf', '.safetensors') for name in names):
|
| 22 |
+
raise ValueError('Upload GGUF or safetensors weights only.')
|
| 23 |
+
if any(Path(name).suffix.lower() == '.gguf' for name in names) and len(files) != 1:
|
| 24 |
+
raise ValueError('Upload one GGUF file, or one or more safetensors shards.')
|
| 25 |
+
all_files = list(files) + ([tokenizer] if tokenizer is not None else [])
|
| 26 |
+
sizes = [len(item.getbuffer()) for item in all_files]
|
| 27 |
+
if any(size > MAX_FILE_BYTES for size in sizes) or sum(sizes) > MAX_TOTAL_BYTES:
|
| 28 |
+
raise ValueError('Uploads allow up to 1 GB per file and 2 GB in total. Use Hugging Face for larger models.')
|
| 29 |
+
directory = new_session_directory(root)
|
| 30 |
+
try:
|
| 31 |
+
for item in files:
|
| 32 |
+
with (directory / item.name).open('wb') as target:
|
| 33 |
+
target.write(item.getbuffer())
|
| 34 |
+
tokenizer_path = None
|
| 35 |
+
if tokenizer is not None:
|
| 36 |
+
tokenizer_path = directory / 'tokenizer.json'
|
| 37 |
+
with tokenizer_path.open('wb') as target:
|
| 38 |
+
target.write(tokenizer.getbuffer())
|
| 39 |
+
model_path = directory / names[0] if len(names) == 1 else directory
|
| 40 |
+
return model_path, tokenizer_path, directory
|
| 41 |
+
except Exception:
|
| 42 |
+
remove_session_directory(directory, root)
|
| 43 |
+
raise
|
| 44 |
+
|
| 45 |
+
|
| 46 |
+
def render_upload_loader(activate_model):
|
| 47 |
+
st.caption('Upload a single GGUF file or safetensors weights. Up to 1 GB per file, 2 GB total.')
|
| 48 |
+
files = st.file_uploader('Model files', type=['gguf', 'safetensors'], accept_multiple_files=True, key='uploaded_models')
|
| 49 |
+
tokenizer = st.file_uploader('Matching tokenizer.json (optional)', type=['json'], key='uploaded_tokenizer')
|
| 50 |
+
st.caption('Uploads are processed by this Space in your session and removed when you clear the model. Restarting the Space also clears uploads.')
|
| 51 |
+
if st.button('Load uploaded model', key='load_upload', type='primary', disabled=not files, use_container_width=True):
|
| 52 |
+
directory = None
|
| 53 |
+
try:
|
| 54 |
+
with st.spinner('Reading uploaded model…'):
|
| 55 |
+
path, tokenizer_path, directory = store_uploads(files, tokenizer)
|
| 56 |
+
activate_model(path, tokenizer_path, 'Uploaded: ' + ', '.join(item.name for item in files))
|
| 57 |
+
st.session_state.upload_directory = directory
|
| 58 |
+
st.rerun()
|
| 59 |
+
except Exception as error:
|
| 60 |
+
if directory is not None:
|
| 61 |
+
remove_session_directory(directory, UPLOAD_ROOT)
|
| 62 |
+
st.error(f'Could not load upload: {error}')
|