Spaces:
Running
Running
Implement running locally with local GGUF files
Browse filesAlso added architecture related metadata defaults
- README.md +1 -1
- _hf_gguf.py +76 -1
- app.py +124 -20
- requirements.txt +2 -2
README.md
CHANGED
|
@@ -4,7 +4,7 @@ emoji: 🏢
|
|
| 4 |
colorFrom: blue
|
| 5 |
colorTo: purple
|
| 6 |
sdk: gradio
|
| 7 |
-
sdk_version: 5.
|
| 8 |
python_version: 3.11
|
| 9 |
app_file: app.py
|
| 10 |
pinned: false
|
|
|
|
| 4 |
colorFrom: blue
|
| 5 |
colorTo: purple
|
| 6 |
sdk: gradio
|
| 7 |
+
sdk_version: 5.25.2
|
| 8 |
python_version: 3.11
|
| 9 |
app_file: app.py
|
| 10 |
pinned: false
|
_hf_gguf.py
CHANGED
|
@@ -71,6 +71,8 @@ class GGUFValueType(IntEnum):
|
|
| 71 |
|
| 72 |
|
| 73 |
standard_metadata = {
|
|
|
|
|
|
|
| 74 |
"general.type": (GGUFValueType.STRING, "model"),
|
| 75 |
"general.architecture": (GGUFValueType.STRING, "llama"),
|
| 76 |
"general.quantization_version": (GGUFValueType.UINT32, 2),
|
|
@@ -141,6 +143,79 @@ standard_metadata = {
|
|
| 141 |
}
|
| 142 |
|
| 143 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 144 |
deprecated_metadata = {
|
| 145 |
"tokenizer.ggml.prefix_token_id",
|
| 146 |
"tokenizer.ggml.suffix_token_id",
|
|
@@ -374,7 +449,7 @@ class HuggingGGUFstream:
|
|
| 374 |
if (alignment := self.metadata.get('general.alignment')) is not None:
|
| 375 |
self.alignment = alignment.value
|
| 376 |
|
| 377 |
-
self.metaend = self.fp.loc
|
| 378 |
self.offset = self.metaend % self.alignment
|
| 379 |
|
| 380 |
def adjust_padding(
|
|
|
|
| 71 |
|
| 72 |
|
| 73 |
standard_metadata = {
|
| 74 |
+
"adapter.type": (GGUFValueType.STRING, "lora"),
|
| 75 |
+
"adapter.lora.alpha": (GGUFValueType.FLOAT32, 16),
|
| 76 |
"general.type": (GGUFValueType.STRING, "model"),
|
| 77 |
"general.architecture": (GGUFValueType.STRING, "llama"),
|
| 78 |
"general.quantization_version": (GGUFValueType.UINT32, 2),
|
|
|
|
| 143 |
}
|
| 144 |
|
| 145 |
|
| 146 |
+
standard_metadata_architecture = {
|
| 147 |
+
"{arch}.vocab_size": (GGUFValueType.UINT32, 0),
|
| 148 |
+
"{arch}.context_length": (GGUFValueType.UINT32, 0),
|
| 149 |
+
"{arch}.embedding_length": (GGUFValueType.UINT32, 0),
|
| 150 |
+
"{arch}.features_length": (GGUFValueType.UINT32, 0),
|
| 151 |
+
"{arch}.block_count": (GGUFValueType.UINT32, 0),
|
| 152 |
+
"{arch}.leading_dense_block_count": (GGUFValueType.UINT32, 0),
|
| 153 |
+
"{arch}.feed_forward_length": (GGUFValueType.UINT32, 0),
|
| 154 |
+
"{arch}.expert_feed_forward_length": (GGUFValueType.UINT32, 0),
|
| 155 |
+
"{arch}.expert_shared_feed_forward_length": (GGUFValueType.UINT32, 0),
|
| 156 |
+
"{arch}.use_parallel_residual": (GGUFValueType.BOOL, False),
|
| 157 |
+
"{arch}.tensor_data_layout": (GGUFValueType.STRING, "Meta AI original pth"),
|
| 158 |
+
"{arch}.expert_count": (GGUFValueType.UINT32, 0),
|
| 159 |
+
"{arch}.expert_used_count": (GGUFValueType.UINT32, 0),
|
| 160 |
+
"{arch}.expert_shared_count": (GGUFValueType.UINT32, 0),
|
| 161 |
+
"{arch}.expert_weights_scale": (GGUFValueType.FLOAT32, 1),
|
| 162 |
+
"{arch}.expert_weights_norm": (GGUFValueType.BOOL, False),
|
| 163 |
+
"{arch}.expert_gating_func": (GGUFValueType.UINT32, 1),
|
| 164 |
+
"{arch}.pooling_type": (GGUFValueType.UINT32, 0),
|
| 165 |
+
"{arch}.logit_scale": (GGUFValueType.FLOAT32, 1),
|
| 166 |
+
"{arch}.decoder_start_token_id": (GGUFValueType.UINT32, 0),
|
| 167 |
+
"{arch}.attn_logit_softcapping": (GGUFValueType.FLOAT32, 0),
|
| 168 |
+
"{arch}.final_logit_softcapping": (GGUFValueType.FLOAT32, 0),
|
| 169 |
+
"{arch}.swin_norm": (GGUFValueType.BOOL, False),
|
| 170 |
+
"{arch}.rescale_every_n_layers": (GGUFValueType.UINT32, 0),
|
| 171 |
+
"{arch}.time_mix_extra_dim": (GGUFValueType.UINT32, 0),
|
| 172 |
+
"{arch}.time_decay_extra_dim": (GGUFValueType.UINT32, 0),
|
| 173 |
+
"{arch}.residual_scale": (GGUFValueType.FLOAT32, 1),
|
| 174 |
+
"{arch}.embedding_scale": (GGUFValueType.FLOAT32, 1),
|
| 175 |
+
"{arch}.token_shift_count": (GGUFValueType.UINT32, 0),
|
| 176 |
+
"{arch}.interleave_moe_layer_step": (GGUFValueType.UINT32, 0),
|
| 177 |
+
"{arch}.attention.head_count": (GGUFValueType.UINT32, 0),
|
| 178 |
+
"{arch}.attention.head_count_kv": (GGUFValueType.UINT32, 0),
|
| 179 |
+
"{arch}.attention.max_alibi_bias": (GGUFValueType.FLOAT32, 0),
|
| 180 |
+
"{arch}.attention.clamp_kqv": (GGUFValueType.FLOAT32, 0),
|
| 181 |
+
"{arch}.attention.key_length": (GGUFValueType.UINT32, 0),
|
| 182 |
+
"{arch}.attention.value_length": (GGUFValueType.UINT32, 0),
|
| 183 |
+
"{arch}.attention.layer_norm_epsilon": (GGUFValueType.FLOAT32, 0),
|
| 184 |
+
"{arch}.attention.layer_norm_rms_epsilon": (GGUFValueType.FLOAT32, 0),
|
| 185 |
+
"{arch}.attention.group_norm_epsilon": (GGUFValueType.FLOAT32, 0),
|
| 186 |
+
"{arch}.attention.group_norm_groups": (GGUFValueType.UINT32, 0),
|
| 187 |
+
"{arch}.attention.causal": (GGUFValueType.BOOL, False),
|
| 188 |
+
"{arch}.attention.q_lora_rank": (GGUFValueType.UINT32, 0),
|
| 189 |
+
"{arch}.attention.kv_lora_rank": (GGUFValueType.UINT32, 0),
|
| 190 |
+
"{arch}.attention.decay_lora_rank": (GGUFValueType.UINT32, 0),
|
| 191 |
+
"{arch}.attention.iclr_lora_rank": (GGUFValueType.UINT32, 0),
|
| 192 |
+
"{arch}.attention.value_residual_mix_lora_rank": (GGUFValueType.UINT32, 0),
|
| 193 |
+
"{arch}.attention.gate_lora_rank": (GGUFValueType.UINT32, 0),
|
| 194 |
+
"{arch}.attention.relative_buckets_count": (GGUFValueType.UINT32, 0),
|
| 195 |
+
"{arch}.attention.sliding_window": (GGUFValueType.UINT32, 0),
|
| 196 |
+
"{arch}.attention.scale": (GGUFValueType.FLOAT32, 1),
|
| 197 |
+
"{arch}.rope.dimension_count": (GGUFValueType.UINT32, 0),
|
| 198 |
+
"{arch}.rope.dimension_sections": (GGUFValueType.UINT32, []),
|
| 199 |
+
"{arch}.rope.freq_base": (GGUFValueType.FLOAT32, 0),
|
| 200 |
+
"{arch}.rope.scaling.type": (GGUFValueType.STRING, "none"),
|
| 201 |
+
"{arch}.rope.scaling.factor": (GGUFValueType.FLOAT32, 1),
|
| 202 |
+
"{arch}.rope.scaling.attn_factor": (GGUFValueType.FLOAT32, 1),
|
| 203 |
+
"{arch}.rope.scaling.original_context_length": (GGUFValueType.UINT32, 0),
|
| 204 |
+
"{arch}.rope.scaling.finetuned": (GGUFValueType.BOOL, False),
|
| 205 |
+
"{arch}.rope.scaling.yarn_log_multiplier": (GGUFValueType.FLOAT32, 1),
|
| 206 |
+
"{arch}.ssm.conv_kernel": (GGUFValueType.UINT32, 0),
|
| 207 |
+
"{arch}.ssm.inner_size": (GGUFValueType.UINT32, 0),
|
| 208 |
+
"{arch}.ssm.state_size": (GGUFValueType.UINT32, 0),
|
| 209 |
+
"{arch}.ssm.time_step_rank": (GGUFValueType.UINT32, 0),
|
| 210 |
+
"{arch}.ssm.dt_b_c_rms": (GGUFValueType.BOOL, False),
|
| 211 |
+
"{arch}.wkv.head_size": (GGUFValueType.UINT32, 0),
|
| 212 |
+
"{arch}.posnet.embedding_length": (GGUFValueType.UINT32, 0),
|
| 213 |
+
"{arch}.posnet.block_count": (GGUFValueType.UINT32, 0),
|
| 214 |
+
"{arch}.convnext.embedding_length": (GGUFValueType.UINT32, 0),
|
| 215 |
+
"{arch}.convnext.block_count": (GGUFValueType.UINT32, 0),
|
| 216 |
+
}
|
| 217 |
+
|
| 218 |
+
|
| 219 |
deprecated_metadata = {
|
| 220 |
"tokenizer.ggml.prefix_token_id",
|
| 221 |
"tokenizer.ggml.suffix_token_id",
|
|
|
|
| 449 |
if (alignment := self.metadata.get('general.alignment')) is not None:
|
| 450 |
self.alignment = alignment.value
|
| 451 |
|
| 452 |
+
self.metaend = self.fp.loc if hasattr(self.fp, 'loc') else self.fp.tell()
|
| 453 |
self.offset = self.metaend % self.alignment
|
| 454 |
|
| 455 |
def adjust_padding(
|
app.py
CHANGED
|
@@ -1,6 +1,8 @@
|
|
| 1 |
import gradio as gr
|
| 2 |
import json
|
|
|
|
| 3 |
import posixpath
|
|
|
|
| 4 |
from fastapi import HTTPException, Path, Query, Request
|
| 5 |
from fastapi.responses import StreamingResponse
|
| 6 |
from gradio_huggingfacehub_search import HuggingfaceHubSearch
|
|
@@ -8,8 +10,15 @@ from huggingface_hub import HfApi, HfFileSystem, auth_check
|
|
| 8 |
from typing import Annotated, Any, NamedTuple
|
| 9 |
from urllib.parse import urlencode
|
| 10 |
|
| 11 |
-
|
| 12 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 13 |
|
| 14 |
|
| 15 |
hfapi = HfApi()
|
|
@@ -78,21 +87,27 @@ with gr.Blocks(
|
|
| 78 |
search_type = "model",
|
| 79 |
sumbit_on_select = True,
|
| 80 |
scale = 2,
|
|
|
|
| 81 |
)
|
| 82 |
|
| 83 |
hf_branch = gr.Dropdown(
|
| 84 |
None,
|
| 85 |
label = "Branch",
|
| 86 |
scale = 1,
|
|
|
|
| 87 |
)
|
| 88 |
|
| 89 |
gr.LoginButton(
|
| 90 |
"Sign in to access gated/private repos",
|
| 91 |
scale = 1,
|
|
|
|
| 92 |
)
|
| 93 |
|
| 94 |
hf_file = FileExplorer(
|
| 95 |
-
|
|
|
|
|
|
|
|
|
|
| 96 |
)
|
| 97 |
|
| 98 |
with gr.Row():
|
|
@@ -203,6 +218,8 @@ with gr.Blocks(
|
|
| 203 |
column_widths = ["35%", "15%", "50%"],
|
| 204 |
wrap = True,
|
| 205 |
interactive = False,
|
|
|
|
|
|
|
| 206 |
visible = False,
|
| 207 |
)
|
| 208 |
|
|
@@ -212,6 +229,46 @@ with gr.Blocks(
|
|
| 212 |
|
| 213 |
An advanced GGUF editor, reading GGUF files directly from Hugging Face repositories and applying changes to your own copies.
|
| 214 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 215 |
Below you will find a collection of example use-cases to show you how to perform a few common GGUF editing operations:
|
| 216 |
""",
|
| 217 |
)
|
|
@@ -678,7 +735,7 @@ Any framework based on `llama-cpp-python` will let you select which chat templat
|
|
| 678 |
hf_file: FileExplorer(
|
| 679 |
"**/*.gguf",
|
| 680 |
file_count = "single",
|
| 681 |
-
root_dir = repo,
|
| 682 |
branch = branch,
|
| 683 |
token = oauth_token.token if oauth_token else False,
|
| 684 |
visible = True,
|
|
@@ -815,9 +872,12 @@ Any framework based on `llama-cpp-python` will let you select which chat templat
|
|
| 815 |
if not repo_file:
|
| 816 |
return
|
| 817 |
|
| 818 |
-
|
| 819 |
-
|
| 820 |
-
|
|
|
|
|
|
|
|
|
|
| 821 |
|
| 822 |
try:
|
| 823 |
progress(0, desc = 'Loading file...')
|
|
@@ -829,11 +889,18 @@ Any framework based on `llama-cpp-python` will let you select which chat templat
|
|
| 829 |
cache_type = "readahead",
|
| 830 |
) as fp:
|
| 831 |
progress(0, desc = 'Reading header...')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 832 |
gguf = HuggingGGUFstream(fp)
|
| 833 |
num_metadata = gguf.header['metadata'].value
|
| 834 |
metadata = gguf.read_metadata()
|
| 835 |
|
| 836 |
-
meta.var['repo_file'] = repo_file
|
| 837 |
meta.var['branch'] = branch
|
| 838 |
|
| 839 |
for k, v in progress.tqdm(metadata, desc = 'Reading metadata...', total = num_metadata, unit = f' of {num_metadata} metadata keys...'):
|
|
@@ -861,10 +928,15 @@ Any framework based on `llama-cpp-python` will let you select which chat templat
|
|
| 861 |
)
|
| 862 |
return
|
| 863 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 864 |
yield {
|
| 865 |
meta_state: meta,
|
| 866 |
meta_keys: gr.Dropdown(
|
| 867 |
-
sorted(meta.key.keys() |
|
| 868 |
value = '',
|
| 869 |
visible = True,
|
| 870 |
),
|
|
@@ -892,8 +964,12 @@ Any framework based on `llama-cpp-python` will let you select which chat templat
|
|
| 892 |
meta: MetadataState,
|
| 893 |
key: str | None,
|
| 894 |
):
|
|
|
|
|
|
|
|
|
|
|
|
|
| 895 |
typ = None
|
| 896 |
-
if (val := meta.key.get(key, standard_metadata.get(key))) is not None:
|
| 897 |
typ = GGUFValueType(val[0]).name
|
| 898 |
elif key:
|
| 899 |
if key.startswith('tokenizer.chat_template.'):
|
|
@@ -944,7 +1020,11 @@ Any framework based on `llama-cpp-python` will let you select which chat templat
|
|
| 944 |
val = None
|
| 945 |
tokens = meta.key.get('tokenizer.ggml.tokens', (-1, []))[1]
|
| 946 |
|
| 947 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 948 |
typ = data[0]
|
| 949 |
val = data[1]
|
| 950 |
elif not key:
|
|
@@ -1048,9 +1128,17 @@ Any framework based on `llama-cpp-python` will let you select which chat templat
|
|
| 1048 |
for k, v in meta.key.items():
|
| 1049 |
m.append([*human_readable_metadata(meta, k, v[0], v[1])])
|
| 1050 |
|
| 1051 |
-
|
| 1052 |
-
|
| 1053 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1054 |
|
| 1055 |
permalink = None
|
| 1056 |
if meta.rem or meta.add:
|
|
@@ -1063,9 +1151,13 @@ Any framework based on `llama-cpp-python` will let you select which chat templat
|
|
| 1063 |
safe = '[]{}:"\',',
|
| 1064 |
)
|
| 1065 |
|
| 1066 |
-
if len(permalink) > 8192:
|
| 1067 |
permalink = None
|
| 1068 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1069 |
return {
|
| 1070 |
meta_state: meta,
|
| 1071 |
meta_changes: gr.HighlightedText(
|
|
@@ -1076,7 +1168,7 @@ Any framework based on `llama-cpp-python` will let you select which chat templat
|
|
| 1076 |
m,
|
| 1077 |
),
|
| 1078 |
meta_keys: gr.Dropdown(
|
| 1079 |
-
sorted(meta.key.keys() |
|
| 1080 |
value = '',
|
| 1081 |
),
|
| 1082 |
meta_permalink: gr.Markdown(
|
|
@@ -1409,9 +1501,12 @@ def stream_repo_file(
|
|
| 1409 |
rem_meta: list[str] | None,
|
| 1410 |
token: str | None = None,
|
| 1411 |
):
|
| 1412 |
-
|
| 1413 |
-
|
| 1414 |
-
|
|
|
|
|
|
|
|
|
|
| 1415 |
|
| 1416 |
with fs.open(
|
| 1417 |
repo_file,
|
|
@@ -1426,6 +1521,12 @@ def stream_repo_file(
|
|
| 1426 |
if not add_meta:
|
| 1427 |
add_meta = []
|
| 1428 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1429 |
gguf = HuggingGGUFstream(fp)
|
| 1430 |
for _ in gguf.read_metadata():
|
| 1431 |
pass
|
|
@@ -1489,12 +1590,15 @@ if __name__ == "__main__":
|
|
| 1489 |
):
|
| 1490 |
token = request.session.get('oauth_info', {}).get('access_token')
|
| 1491 |
|
| 1492 |
-
if posixpath.normpath(repo_file) != repo_file or '\\' in repo_file or repo_file.startswith('../') or repo_file.startswith('/') or repo_file.count('/') < 2:
|
| 1493 |
raise HTTPException(
|
| 1494 |
status_code = 404,
|
| 1495 |
detail = 'Invalid repository',
|
| 1496 |
)
|
| 1497 |
|
|
|
|
|
|
|
|
|
|
| 1498 |
if session and state is not None and session in request.app.state_holder and state in request.app.state_holder[session]:
|
| 1499 |
meta: MetadataState = request.app.state_holder[session][state]
|
| 1500 |
|
|
|
|
| 1 |
import gradio as gr
|
| 2 |
import json
|
| 3 |
+
import os
|
| 4 |
import posixpath
|
| 5 |
+
import sys
|
| 6 |
from fastapi import HTTPException, Path, Query, Request
|
| 7 |
from fastapi.responses import StreamingResponse
|
| 8 |
from gradio_huggingfacehub_search import HuggingfaceHubSearch
|
|
|
|
| 10 |
from typing import Annotated, Any, NamedTuple
|
| 11 |
from urllib.parse import urlencode
|
| 12 |
|
| 13 |
+
local_folder = None
|
| 14 |
+
if len(sys.argv) == 2:
|
| 15 |
+
from fsspec.implementations.local import LocalFileSystem
|
| 16 |
+
from gradio import FileExplorer
|
| 17 |
+
|
| 18 |
+
local_folder = posixpath.normpath(os.path.abspath(os.path.expanduser(sys.argv[1])).replace('\\', '/'))
|
| 19 |
+
else:
|
| 20 |
+
from _hf_explorer import FileExplorer
|
| 21 |
+
from _hf_gguf import standard_metadata, standard_metadata_architecture, deprecated_metadata, TokenType, LlamaFileType, GGUFValueType, HuggingGGUFstream
|
| 22 |
|
| 23 |
|
| 24 |
hfapi = HfApi()
|
|
|
|
| 87 |
search_type = "model",
|
| 88 |
sumbit_on_select = True,
|
| 89 |
scale = 2,
|
| 90 |
+
visible = not local_folder,
|
| 91 |
)
|
| 92 |
|
| 93 |
hf_branch = gr.Dropdown(
|
| 94 |
None,
|
| 95 |
label = "Branch",
|
| 96 |
scale = 1,
|
| 97 |
+
visible = not local_folder,
|
| 98 |
)
|
| 99 |
|
| 100 |
gr.LoginButton(
|
| 101 |
"Sign in to access gated/private repos",
|
| 102 |
scale = 1,
|
| 103 |
+
visible = not local_folder,
|
| 104 |
)
|
| 105 |
|
| 106 |
hf_file = FileExplorer(
|
| 107 |
+
"**/*.gguf",
|
| 108 |
+
file_count = "single",
|
| 109 |
+
root_dir = local_folder,
|
| 110 |
+
visible = bool(local_folder),
|
| 111 |
)
|
| 112 |
|
| 113 |
with gr.Row():
|
|
|
|
| 218 |
column_widths = ["35%", "15%", "50%"],
|
| 219 |
wrap = True,
|
| 220 |
interactive = False,
|
| 221 |
+
show_search = "filter",
|
| 222 |
+
show_copy_button = True,
|
| 223 |
visible = False,
|
| 224 |
)
|
| 225 |
|
|
|
|
| 229 |
|
| 230 |
An advanced GGUF editor, reading GGUF files directly from Hugging Face repositories and applying changes to your own copies.
|
| 231 |
|
| 232 |
+
<details>
|
| 233 |
+
<summary>Running the editor locally</summary>
|
| 234 |
+
|
| 235 |
+
* Clone the space
|
| 236 |
+
```bash
|
| 237 |
+
git clone https://huggingface.co/spaces/CISCai/gguf-editor
|
| 238 |
+
cd gguf-editor
|
| 239 |
+
```
|
| 240 |
+
* Create a virtual environment
|
| 241 |
+
```bash
|
| 242 |
+
python3 -m venv .venv
|
| 243 |
+
```
|
| 244 |
+
* Install dependencies
|
| 245 |
+
```
|
| 246 |
+
.venv/bin/pip install -r requirements.txt
|
| 247 |
+
```
|
| 248 |
+
* Gradio requires a HF_TOKEN for the LoginButton/OAuth, so log in to Hugging Face
|
| 249 |
+
```
|
| 250 |
+
.venv/bin/huggingface-cli login
|
| 251 |
+
```
|
| 252 |
+
* Start the server
|
| 253 |
+
```
|
| 254 |
+
.venv/bin/python app.py
|
| 255 |
+
```
|
| 256 |
+
* Browse to http://localhost:7860
|
| 257 |
+
|
| 258 |
+
</details>
|
| 259 |
+
|
| 260 |
+
<details>
|
| 261 |
+
<summary>Editing local GGUF files</summary>
|
| 262 |
+
|
| 263 |
+
* Set up the application locally (see above)
|
| 264 |
+
* Start the server with additional parameter
|
| 265 |
+
```
|
| 266 |
+
.venv/bin/python app.py "path/to/gguf/folder"
|
| 267 |
+
```
|
| 268 |
+
* Browse to http://localhost:7860
|
| 269 |
+
|
| 270 |
+
</details>
|
| 271 |
+
|
| 272 |
Below you will find a collection of example use-cases to show you how to perform a few common GGUF editing operations:
|
| 273 |
""",
|
| 274 |
)
|
|
|
|
| 735 |
hf_file: FileExplorer(
|
| 736 |
"**/*.gguf",
|
| 737 |
file_count = "single",
|
| 738 |
+
root_dir = local_folder or repo,
|
| 739 |
branch = branch,
|
| 740 |
token = oauth_token.token if oauth_token else False,
|
| 741 |
visible = True,
|
|
|
|
| 872 |
if not repo_file:
|
| 873 |
return
|
| 874 |
|
| 875 |
+
if local_folder:
|
| 876 |
+
fs = LocalFileSystem()
|
| 877 |
+
else:
|
| 878 |
+
fs = HfFileSystem(
|
| 879 |
+
token = oauth_token.token if oauth_token else None,
|
| 880 |
+
)
|
| 881 |
|
| 882 |
try:
|
| 883 |
progress(0, desc = 'Loading file...')
|
|
|
|
| 889 |
cache_type = "readahead",
|
| 890 |
) as fp:
|
| 891 |
progress(0, desc = 'Reading header...')
|
| 892 |
+
|
| 893 |
+
if local_folder:
|
| 894 |
+
fp.details = fs.ls(
|
| 895 |
+
repo_file,
|
| 896 |
+
detail = True,
|
| 897 |
+
)[0]
|
| 898 |
+
|
| 899 |
gguf = HuggingGGUFstream(fp)
|
| 900 |
num_metadata = gguf.header['metadata'].value
|
| 901 |
metadata = gguf.read_metadata()
|
| 902 |
|
| 903 |
+
meta.var['repo_file'] = repo_file[len(local_folder) + 1:] if local_folder else repo_file
|
| 904 |
meta.var['branch'] = branch
|
| 905 |
|
| 906 |
for k, v in progress.tqdm(metadata, desc = 'Reading metadata...', total = num_metadata, unit = f' of {num_metadata} metadata keys...'):
|
|
|
|
| 928 |
)
|
| 929 |
return
|
| 930 |
|
| 931 |
+
model_architecture = meta.key.get('general.architecture', (None, None))[1]
|
| 932 |
+
standard_metakeys = set(standard_metadata.keys())
|
| 933 |
+
if model_architecture:
|
| 934 |
+
standard_metakeys |= set(k.format(arch = model_architecture) for k in standard_metadata_architecture.keys())
|
| 935 |
+
|
| 936 |
yield {
|
| 937 |
meta_state: meta,
|
| 938 |
meta_keys: gr.Dropdown(
|
| 939 |
+
sorted(meta.key.keys() | standard_metakeys),
|
| 940 |
value = '',
|
| 941 |
visible = True,
|
| 942 |
),
|
|
|
|
| 964 |
meta: MetadataState,
|
| 965 |
key: str | None,
|
| 966 |
):
|
| 967 |
+
default_metadata = None
|
| 968 |
+
if model_architecture := meta.key.get('general.architecture', (None, None))[1]:
|
| 969 |
+
default_metadata = standard_metadata_architecture.get(key.replace(model_architecture + '.', '{arch}.'))
|
| 970 |
+
|
| 971 |
typ = None
|
| 972 |
+
if (val := meta.key.get(key, standard_metadata.get(key, default_metadata))) is not None:
|
| 973 |
typ = GGUFValueType(val[0]).name
|
| 974 |
elif key:
|
| 975 |
if key.startswith('tokenizer.chat_template.'):
|
|
|
|
| 1020 |
val = None
|
| 1021 |
tokens = meta.key.get('tokenizer.ggml.tokens', (-1, []))[1]
|
| 1022 |
|
| 1023 |
+
default_metadata = None
|
| 1024 |
+
if model_architecture := meta.key.get('general.architecture', (None, None))[1]:
|
| 1025 |
+
default_metadata = standard_metadata_architecture.get(key.replace(model_architecture + '.', '{arch}.'))
|
| 1026 |
+
|
| 1027 |
+
if (data := meta.key.get(key, standard_metadata.get(key, default_metadata))) is not None:
|
| 1028 |
typ = data[0]
|
| 1029 |
val = data[1]
|
| 1030 |
elif not key:
|
|
|
|
| 1128 |
for k, v in meta.key.items():
|
| 1129 |
m.append([*human_readable_metadata(meta, k, v[0], v[1])])
|
| 1130 |
|
| 1131 |
+
query_params = {
|
| 1132 |
+
'branch': meta.var['branch'],
|
| 1133 |
+
'session': request.session_hash,
|
| 1134 |
+
'state': str(meta_state._id),
|
| 1135 |
+
}
|
| 1136 |
+
|
| 1137 |
+
if not query_params['branch'] or query_params['branch'] == 'main':
|
| 1138 |
+
del query_params['branch']
|
| 1139 |
+
|
| 1140 |
+
link = request.request.url_for('download', repo_file = meta.var['repo_file']).include_query_params(**query_params)
|
| 1141 |
+
link = 'https' + str(link)[4:] if link.hostname not in ('localhost', '127.0.0.1', '::1') and link.scheme == 'http' else str(link)
|
| 1142 |
|
| 1143 |
permalink = None
|
| 1144 |
if meta.rem or meta.add:
|
|
|
|
| 1151 |
safe = '[]{}:"\',',
|
| 1152 |
)
|
| 1153 |
|
| 1154 |
+
if len(permalink) > 8192 or local_folder:
|
| 1155 |
permalink = None
|
| 1156 |
|
| 1157 |
+
standard_metakeys = set(standard_metadata.keys())
|
| 1158 |
+
if model_architecture := meta.key.get('general.architecture', (None, None))[1]:
|
| 1159 |
+
standard_metakeys |= set(k.format(arch = model_architecture) for k in standard_metadata_architecture.keys())
|
| 1160 |
+
|
| 1161 |
return {
|
| 1162 |
meta_state: meta,
|
| 1163 |
meta_changes: gr.HighlightedText(
|
|
|
|
| 1168 |
m,
|
| 1169 |
),
|
| 1170 |
meta_keys: gr.Dropdown(
|
| 1171 |
+
sorted(meta.key.keys() | standard_metakeys),
|
| 1172 |
value = '',
|
| 1173 |
),
|
| 1174 |
meta_permalink: gr.Markdown(
|
|
|
|
| 1501 |
rem_meta: list[str] | None,
|
| 1502 |
token: str | None = None,
|
| 1503 |
):
|
| 1504 |
+
if local_folder:
|
| 1505 |
+
fs = LocalFileSystem()
|
| 1506 |
+
else:
|
| 1507 |
+
fs = HfFileSystem(
|
| 1508 |
+
token = token,
|
| 1509 |
+
)
|
| 1510 |
|
| 1511 |
with fs.open(
|
| 1512 |
repo_file,
|
|
|
|
| 1521 |
if not add_meta:
|
| 1522 |
add_meta = []
|
| 1523 |
|
| 1524 |
+
if local_folder:
|
| 1525 |
+
fp.details = fs.ls(
|
| 1526 |
+
repo_file,
|
| 1527 |
+
detail = True,
|
| 1528 |
+
)[0]
|
| 1529 |
+
|
| 1530 |
gguf = HuggingGGUFstream(fp)
|
| 1531 |
for _ in gguf.read_metadata():
|
| 1532 |
pass
|
|
|
|
| 1590 |
):
|
| 1591 |
token = request.session.get('oauth_info', {}).get('access_token')
|
| 1592 |
|
| 1593 |
+
if posixpath.normpath(repo_file) != repo_file or '\\' in repo_file or ':' in repo_file or repo_file.startswith('../') or repo_file.startswith('/') or (repo_file.count('/') < 2 and not local_folder):
|
| 1594 |
raise HTTPException(
|
| 1595 |
status_code = 404,
|
| 1596 |
detail = 'Invalid repository',
|
| 1597 |
)
|
| 1598 |
|
| 1599 |
+
if local_folder:
|
| 1600 |
+
repo_file = os.path.join(local_folder, repo_file)
|
| 1601 |
+
|
| 1602 |
if session and state is not None and session in request.app.state_holder and state in request.app.state_holder[session]:
|
| 1603 |
meta: MetadataState = request.app.state_holder[session][state]
|
| 1604 |
|
requirements.txt
CHANGED
|
@@ -1,4 +1,4 @@
|
|
| 1 |
-
|
| 2 |
-
huggingface_hub==0.
|
| 3 |
# gradio_huggingfacehub_search==0.0.8
|
| 4 |
https://huggingface.co/spaces/CISCai/chat-template-editor/resolve/main/gradio_huggingfacehub_search-0.0.8-py3-none-any.whl
|
|
|
|
| 1 |
+
gradio[oauth]==5.25.2
|
| 2 |
+
huggingface_hub==0.30.2
|
| 3 |
# gradio_huggingfacehub_search==0.0.8
|
| 4 |
https://huggingface.co/spaces/CISCai/chat-template-editor/resolve/main/gradio_huggingfacehub_search-0.0.8-py3-none-any.whl
|