token-visualiser / upload_ui.py
jejunepixels's picture
Create upload_ui.py
f835889 verified
Raw History Blame Contribute Delete
3.34 kB
"""Uploads for hosted sessions; no access to server filesystem paths."""
from pathlib import Path
import streamlit as st
from app_environment import UPLOAD_ROOT, new_session_directory, remove_session_directory
MAX_FILE_BYTES = 1024 * 1024 * 1024
MAX_TOTAL_BYTES = 2 * MAX_FILE_BYTES
def store_uploads(files, tokenizer=None, root=UPLOAD_ROOT):
if not files:
raise ValueError('Choose a GGUF or safetensors file.')
names = [item.name for item in files]
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):
raise ValueError('Use plain file names for uploaded model files.')
if len(set(name.casefold() for name in names)) != len(names):
raise ValueError('Uploaded model files must have different names.')
if any(Path(name).suffix.lower() not in ('.gguf', '.safetensors') for name in names):
raise ValueError('Upload GGUF or safetensors weights only.')
if any(Path(name).suffix.lower() == '.gguf' for name in names) and len(files) != 1:
raise ValueError('Upload one GGUF file, or one or more safetensors shards.')
all_files = list(files) + ([tokenizer] if tokenizer is not None else [])
sizes = [len(item.getbuffer()) for item in all_files]
if any(size > MAX_FILE_BYTES for size in sizes) or sum(sizes) > MAX_TOTAL_BYTES:
raise ValueError('Uploads allow up to 1 GB per file and 2 GB in total. Use Hugging Face for larger models.')
directory = new_session_directory(root)
try:
for item in files:
with (directory / item.name).open('wb') as target:
target.write(item.getbuffer())
tokenizer_path = None
if tokenizer is not None:
tokenizer_path = directory / 'tokenizer.json'
with tokenizer_path.open('wb') as target:
target.write(tokenizer.getbuffer())
model_path = directory / names[0] if len(names) == 1 else directory
return model_path, tokenizer_path, directory
except Exception:
remove_session_directory(directory, root)
raise
def render_upload_loader(activate_model):
st.caption('Upload a single GGUF file or safetensors weights. Up to 1 GB per file, 2 GB total.')
files = st.file_uploader('Model files', type=['gguf', 'safetensors'], accept_multiple_files=True, key='uploaded_models')
tokenizer = st.file_uploader('Matching tokenizer.json (optional)', type=['json'], key='uploaded_tokenizer')
st.caption('Uploads are processed by this Space in your session and removed when you clear the model. Restarting the Space also clears uploads.')
if st.button('Load uploaded model', key='load_upload', type='primary', disabled=not files, use_container_width=True):
directory = None
try:
with st.spinner('Reading uploaded model…'):
path, tokenizer_path, directory = store_uploads(files, tokenizer)
activate_model(path, tokenizer_path, 'Uploaded: ' + ', '.join(item.name for item in files))
st.session_state.upload_directory = directory
st.rerun()
except Exception as error:
if directory is not None:
remove_session_directory(directory, UPLOAD_ROOT)
st.error(f'Could not load upload: {error}')