Spaces:
Running
Running
[add] pydantic for parser result
Browse files- README.md +1 -1
- app/models.py +104 -0
- app/main.py → main.py +8 -16
- pyproject.toml +6 -0
- requirements.txt +1 -0
- uv.lock +54 -0
README.md
CHANGED
@@ -5,7 +5,7 @@ colorFrom: green
|
|
5 |
colorTo: indigo
|
6 |
sdk: gradio
|
7 |
sdk_version: 5.3.0
|
8 |
-
app_file:
|
9 |
pinned: false
|
10 |
license: mit
|
11 |
short_description: This project is a GUI for the gpustack/gguf-parser-go
|
|
|
5 |
colorTo: indigo
|
6 |
sdk: gradio
|
7 |
sdk_version: 5.3.0
|
8 |
+
app_file: main.py
|
9 |
pinned: false
|
10 |
license: mit
|
11 |
short_description: This project is a GUI for the gpustack/gguf-parser-go
|
app/models.py
ADDED
@@ -0,0 +1,104 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from typing import Optional
|
2 |
+
|
3 |
+
from pydantic import BaseModel, Field
|
4 |
+
|
5 |
+
|
6 |
+
class GgufParser(BaseModel):
|
7 |
+
metadata: "Metadata"
|
8 |
+
architecture: "Architecture"
|
9 |
+
tokenizer: "Tokenizer"
|
10 |
+
estimate: "Estimate"
|
11 |
+
|
12 |
+
|
13 |
+
class Metadata(BaseModel):
|
14 |
+
type_: str = Field(alias="type")
|
15 |
+
architecture: str
|
16 |
+
quantization_version: int = Field(alias="quantizationVersion")
|
17 |
+
alignment: int
|
18 |
+
name: str
|
19 |
+
file_type: int = Field(alias="fileType")
|
20 |
+
little_endian: bool = Field(alias="littleEndian")
|
21 |
+
file_size: int = Field(alias="fileSize")
|
22 |
+
size: int
|
23 |
+
parameters: int
|
24 |
+
bits_per_weight: float = Field(alias="bitsPerWeight")
|
25 |
+
|
26 |
+
|
27 |
+
class Architecture(BaseModel):
|
28 |
+
type_: str = Field(alias="type")
|
29 |
+
architecture: str
|
30 |
+
maximum_context_length: int = Field(alias="maximumContextLength")
|
31 |
+
embedding_length: int = Field(alias="embeddingLength")
|
32 |
+
block_count: int = Field(alias="blockCount")
|
33 |
+
feed_forward_length: int = Field(alias="feedForwardLength")
|
34 |
+
attention_head_count: int = Field(alias="attentionHeadCount")
|
35 |
+
attention_head_count_kv: int = Field(alias="attentionHeadCountKV")
|
36 |
+
attention_layer_norm_rmse_epsilon: float = Field(
|
37 |
+
alias="attentionLayerNormRMSEpsilon"
|
38 |
+
)
|
39 |
+
attention_key_length: int = Field(alias="attentionKeyLength")
|
40 |
+
attention_value_length: int = Field(alias="attentionValueLength")
|
41 |
+
attention_causal: bool = Field(alias="attentionCausal")
|
42 |
+
rope_dimension_count: int = Field(alias="ropeDimensionCount")
|
43 |
+
rope_frequency_base: int = Field(alias="ropeFrequencyBase")
|
44 |
+
vocabulary_length: int = Field(alias="vocabularyLength")
|
45 |
+
embedding_gqa: int = Field(alias="embeddingGQA")
|
46 |
+
embedding_key_gqa: int = Field(alias="embeddingKeyGQA")
|
47 |
+
embedding_value_gqa: int = Field(alias="embeddingValueGQA")
|
48 |
+
|
49 |
+
|
50 |
+
class Tokenizer(BaseModel):
|
51 |
+
model: str
|
52 |
+
tokens_length: int = Field(alias="tokensLength")
|
53 |
+
merges_length: int = Field(alias="mergesLength")
|
54 |
+
added_token_length: int = Field(alias="addedTokenLength")
|
55 |
+
bos_token_id: int = Field(alias="bosTokenID")
|
56 |
+
eos_token_id: int = Field(alias="eosTokenID")
|
57 |
+
eot_token_id: int = Field(alias="eotTokenID")
|
58 |
+
eom_token_id: int = Field(alias="eomTokenID")
|
59 |
+
unknown_token_id: int = Field(alias="unknownTokenID")
|
60 |
+
separator_token_id: int = Field(alias="separatorTokenID")
|
61 |
+
padding_token_id: int = Field(alias="paddingTokenID")
|
62 |
+
tokens_size: int = Field(alias="tokensSize")
|
63 |
+
merges_size: int = Field(alias="mergesSize")
|
64 |
+
|
65 |
+
|
66 |
+
class Ram(BaseModel):
|
67 |
+
handle_layers: int = Field(alias="handleLayers")
|
68 |
+
handle_last_layer: int = Field(alias="handleLastLayer")
|
69 |
+
handle_output_layer: bool = Field(alias="handleOutputLayer")
|
70 |
+
remote: bool
|
71 |
+
position: int
|
72 |
+
uma: int
|
73 |
+
nonuma: int
|
74 |
+
|
75 |
+
|
76 |
+
class Item(BaseModel):
|
77 |
+
offload_layers: int = Field(alias="offloadLayers")
|
78 |
+
full_offloaded: bool = Field(alias="fullOffloaded")
|
79 |
+
ram: "Ram"
|
80 |
+
vrams: list["Ram"]
|
81 |
+
|
82 |
+
|
83 |
+
class Estimate(BaseModel):
|
84 |
+
items: list["Item"]
|
85 |
+
type_: str = Field(alias="type")
|
86 |
+
architecture: str
|
87 |
+
context_size: int = Field(alias="contextSize")
|
88 |
+
flash_attention: bool = Field(alias="flashAttention")
|
89 |
+
no_mmap: bool = Field(alias="noMMap")
|
90 |
+
embedding_only: bool = Field(alias="embeddingOnly")
|
91 |
+
reranking: bool
|
92 |
+
distributable: bool
|
93 |
+
logical_batch_size: int = Field(alias="logicalBatchSize")
|
94 |
+
physical_batch_size: int = Field(alias="physicalBatchSize")
|
95 |
+
type_: str = Field(alias="type")
|
96 |
+
architecture: str
|
97 |
+
context_size: int = Field(alias="contextSize")
|
98 |
+
flash_attention: bool = Field(alias="flashAttention")
|
99 |
+
no_mmap: bool = Field(alias="noMMap")
|
100 |
+
embedding_only: bool = Field(alias="embeddingOnly")
|
101 |
+
reranking: bool
|
102 |
+
distributable: bool
|
103 |
+
logical_batch_size: int = Field(alias="logicalBatchSize")
|
104 |
+
physical_batch_size: int = Field(alias="physicalBatchSize")
|
app/main.py → main.py
RENAMED
@@ -5,6 +5,8 @@ from pathlib import Path
|
|
5 |
import gradio as gr
|
6 |
import pandas as pd
|
7 |
|
|
|
|
|
8 |
GGUF_PARSER_VERSION = os.getenv("GGUF_PARSER_VERSION", "v0.12.0")
|
9 |
gguf_parser = Path("gguf-parser-linux-amd64")
|
10 |
gguf_parser_url = f"https://github.com/gpustack/gguf-parser-go/releases/download/{GGUF_PARSER_VERSION}/{gguf_parser}"
|
@@ -16,27 +18,17 @@ def process_url(url, context_length):
|
|
16 |
res = os.popen(
|
17 |
f"./{gguf_parser} --ctx-size={context_length} -url {url} --json"
|
18 |
).read()
|
19 |
-
|
|
|
20 |
|
21 |
-
metadata_df = pd.DataFrame([
|
22 |
|
23 |
-
architecture_df = pd.DataFrame([
|
24 |
|
25 |
-
tokenizer_df = pd.DataFrame([
|
26 |
|
27 |
estimate_df = pd.DataFrame(
|
28 |
-
[
|
29 |
-
{
|
30 |
-
# "maximumTokensPerSecond": data["estimate"]["items"][0][
|
31 |
-
# "maximumTokensPerSecond"
|
32 |
-
# ],
|
33 |
-
"offloadLayers": data["estimate"]["items"][0]["offloadLayers"],
|
34 |
-
"fullOffloaded": data["estimate"]["items"][0]["fullOffloaded"],
|
35 |
-
"contextSize": data["estimate"]["contextSize"],
|
36 |
-
"flashAttention": data["estimate"]["flashAttention"],
|
37 |
-
"distributable": data["estimate"]["distributable"],
|
38 |
-
}
|
39 |
-
]
|
40 |
)
|
41 |
|
42 |
return metadata_df, architecture_df, tokenizer_df, estimate_df
|
|
|
5 |
import gradio as gr
|
6 |
import pandas as pd
|
7 |
|
8 |
+
from app.models import GgufParser
|
9 |
+
|
10 |
GGUF_PARSER_VERSION = os.getenv("GGUF_PARSER_VERSION", "v0.12.0")
|
11 |
gguf_parser = Path("gguf-parser-linux-amd64")
|
12 |
gguf_parser_url = f"https://github.com/gpustack/gguf-parser-go/releases/download/{GGUF_PARSER_VERSION}/{gguf_parser}"
|
|
|
18 |
res = os.popen(
|
19 |
f"./{gguf_parser} --ctx-size={context_length} -url {url} --json"
|
20 |
).read()
|
21 |
+
parser_result = GgufParser.model_validate_json(res)
|
22 |
+
# data = json.loads(res)
|
23 |
|
24 |
+
metadata_df = pd.DataFrame([parser_result.metadata.model_dump()])
|
25 |
|
26 |
+
architecture_df = pd.DataFrame([parser_result.architecture.model_dump()])
|
27 |
|
28 |
+
tokenizer_df = pd.DataFrame([parser_result.tokenizer.model_dump()])
|
29 |
|
30 |
estimate_df = pd.DataFrame(
|
31 |
+
[parser_result.estimate.model_dump(exclude_none=True)]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
32 |
)
|
33 |
|
34 |
return metadata_df, architecture_df, tokenizer_df, estimate_df
|
pyproject.toml
CHANGED
@@ -8,7 +8,13 @@ dependencies = [
|
|
8 |
"gradio==5.3.0",
|
9 |
"orjson==3.10.10",
|
10 |
"pandas>=2.2.3",
|
|
|
11 |
]
|
12 |
|
13 |
[tool.pylint]
|
14 |
max-line-length = 180
|
|
|
|
|
|
|
|
|
|
|
|
8 |
"gradio==5.3.0",
|
9 |
"orjson==3.10.10",
|
10 |
"pandas>=2.2.3",
|
11 |
+
"pydantic>=2.9.2",
|
12 |
]
|
13 |
|
14 |
[tool.pylint]
|
15 |
max-line-length = 180
|
16 |
+
|
17 |
+
[tool.uv]
|
18 |
+
dev-dependencies = [
|
19 |
+
"pytest>=8.3.3",
|
20 |
+
]
|
requirements.txt
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
pydantic>=2.9.2
|
uv.lock
CHANGED
@@ -197,6 +197,12 @@ dependencies = [
|
|
197 |
{ name = "gradio" },
|
198 |
{ name = "orjson" },
|
199 |
{ name = "pandas" },
|
|
|
|
|
|
|
|
|
|
|
|
|
200 |
]
|
201 |
|
202 |
[package.metadata]
|
@@ -204,8 +210,12 @@ requires-dist = [
|
|
204 |
{ name = "gradio", specifier = "==5.3.0" },
|
205 |
{ name = "orjson", specifier = "==3.10.10" },
|
206 |
{ name = "pandas", specifier = ">=2.2.3" },
|
|
|
207 |
]
|
208 |
|
|
|
|
|
|
|
209 |
[[package]]
|
210 |
name = "gradio"
|
211 |
version = "5.3.0"
|
@@ -324,6 +334,15 @@ wheels = [
|
|
324 |
{ url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442 },
|
325 |
]
|
326 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
327 |
[[package]]
|
328 |
name = "jinja2"
|
329 |
version = "3.1.4"
|
@@ -616,6 +635,15 @@ wheels = [
|
|
616 |
{ url = "https://files.pythonhosted.org/packages/52/3b/ce7a01026a7cf46e5452afa86f97a5e88ca97f562cafa76570178ab56d8d/pillow-10.4.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:0755ffd4a0c6f267cccbae2e9903d95477ca2f77c4fcf3a3a09570001856c8a5", size = 2554661 },
|
617 |
]
|
618 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
619 |
[[package]]
|
620 |
name = "pydantic"
|
621 |
version = "2.9.2"
|
@@ -715,6 +743,23 @@ wheels = [
|
|
715 |
{ url = "https://files.pythonhosted.org/packages/f7/3f/01c8b82017c199075f8f788d0d906b9ffbbc5a47dc9918a945e13d5a2bda/pygments-2.18.0-py3-none-any.whl", hash = "sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a", size = 1205513 },
|
716 |
]
|
717 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
718 |
[[package]]
|
719 |
name = "python-dateutil"
|
720 |
version = "2.9.0.post0"
|
@@ -891,6 +936,15 @@ wheels = [
|
|
891 |
{ url = "https://files.pythonhosted.org/packages/54/43/f185bfd0ca1d213beb4293bed51d92254df23d8ceaf6c0e17146d508a776/starlette-0.41.2-py3-none-any.whl", hash = "sha256:fbc189474b4731cf30fcef52f18a8d070e3f3b46c6a04c97579e85e6ffca942d", size = 73259 },
|
892 |
]
|
893 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
894 |
[[package]]
|
895 |
name = "tomlkit"
|
896 |
version = "0.12.0"
|
|
|
197 |
{ name = "gradio" },
|
198 |
{ name = "orjson" },
|
199 |
{ name = "pandas" },
|
200 |
+
{ name = "pydantic" },
|
201 |
+
]
|
202 |
+
|
203 |
+
[package.dev-dependencies]
|
204 |
+
dev = [
|
205 |
+
{ name = "pytest" },
|
206 |
]
|
207 |
|
208 |
[package.metadata]
|
|
|
210 |
{ name = "gradio", specifier = "==5.3.0" },
|
211 |
{ name = "orjson", specifier = "==3.10.10" },
|
212 |
{ name = "pandas", specifier = ">=2.2.3" },
|
213 |
+
{ name = "pydantic", specifier = ">=2.9.2" },
|
214 |
]
|
215 |
|
216 |
+
[package.metadata.requires-dev]
|
217 |
+
dev = [{ name = "pytest", specifier = ">=8.3.3" }]
|
218 |
+
|
219 |
[[package]]
|
220 |
name = "gradio"
|
221 |
version = "5.3.0"
|
|
|
334 |
{ url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442 },
|
335 |
]
|
336 |
|
337 |
+
[[package]]
|
338 |
+
name = "iniconfig"
|
339 |
+
version = "2.0.0"
|
340 |
+
source = { registry = "https://pypi.org/simple" }
|
341 |
+
sdist = { url = "https://files.pythonhosted.org/packages/d7/4b/cbd8e699e64a6f16ca3a8220661b5f83792b3017d0f79807cb8708d33913/iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3", size = 4646 }
|
342 |
+
wheels = [
|
343 |
+
{ url = "https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374", size = 5892 },
|
344 |
+
]
|
345 |
+
|
346 |
[[package]]
|
347 |
name = "jinja2"
|
348 |
version = "3.1.4"
|
|
|
635 |
{ url = "https://files.pythonhosted.org/packages/52/3b/ce7a01026a7cf46e5452afa86f97a5e88ca97f562cafa76570178ab56d8d/pillow-10.4.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:0755ffd4a0c6f267cccbae2e9903d95477ca2f77c4fcf3a3a09570001856c8a5", size = 2554661 },
|
636 |
]
|
637 |
|
638 |
+
[[package]]
|
639 |
+
name = "pluggy"
|
640 |
+
version = "1.5.0"
|
641 |
+
source = { registry = "https://pypi.org/simple" }
|
642 |
+
sdist = { url = "https://files.pythonhosted.org/packages/96/2d/02d4312c973c6050a18b314a5ad0b3210edb65a906f868e31c111dede4a6/pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1", size = 67955 }
|
643 |
+
wheels = [
|
644 |
+
{ url = "https://files.pythonhosted.org/packages/88/5f/e351af9a41f866ac3f1fac4ca0613908d9a41741cfcf2228f4ad853b697d/pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669", size = 20556 },
|
645 |
+
]
|
646 |
+
|
647 |
[[package]]
|
648 |
name = "pydantic"
|
649 |
version = "2.9.2"
|
|
|
743 |
{ url = "https://files.pythonhosted.org/packages/f7/3f/01c8b82017c199075f8f788d0d906b9ffbbc5a47dc9918a945e13d5a2bda/pygments-2.18.0-py3-none-any.whl", hash = "sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a", size = 1205513 },
|
744 |
]
|
745 |
|
746 |
+
[[package]]
|
747 |
+
name = "pytest"
|
748 |
+
version = "8.3.3"
|
749 |
+
source = { registry = "https://pypi.org/simple" }
|
750 |
+
dependencies = [
|
751 |
+
{ name = "colorama", marker = "sys_platform == 'win32'" },
|
752 |
+
{ name = "exceptiongroup", marker = "python_full_version < '3.11'" },
|
753 |
+
{ name = "iniconfig" },
|
754 |
+
{ name = "packaging" },
|
755 |
+
{ name = "pluggy" },
|
756 |
+
{ name = "tomli", marker = "python_full_version < '3.11'" },
|
757 |
+
]
|
758 |
+
sdist = { url = "https://files.pythonhosted.org/packages/8b/6c/62bbd536103af674e227c41a8f3dcd022d591f6eed5facb5a0f31ee33bbc/pytest-8.3.3.tar.gz", hash = "sha256:70b98107bd648308a7952b06e6ca9a50bc660be218d53c257cc1fc94fda10181", size = 1442487 }
|
759 |
+
wheels = [
|
760 |
+
{ url = "https://files.pythonhosted.org/packages/6b/77/7440a06a8ead44c7757a64362dd22df5760f9b12dc5f11b6188cd2fc27a0/pytest-8.3.3-py3-none-any.whl", hash = "sha256:a6853c7375b2663155079443d2e45de913a911a11d669df02a50814944db57b2", size = 342341 },
|
761 |
+
]
|
762 |
+
|
763 |
[[package]]
|
764 |
name = "python-dateutil"
|
765 |
version = "2.9.0.post0"
|
|
|
936 |
{ url = "https://files.pythonhosted.org/packages/54/43/f185bfd0ca1d213beb4293bed51d92254df23d8ceaf6c0e17146d508a776/starlette-0.41.2-py3-none-any.whl", hash = "sha256:fbc189474b4731cf30fcef52f18a8d070e3f3b46c6a04c97579e85e6ffca942d", size = 73259 },
|
937 |
]
|
938 |
|
939 |
+
[[package]]
|
940 |
+
name = "tomli"
|
941 |
+
version = "2.0.2"
|
942 |
+
source = { registry = "https://pypi.org/simple" }
|
943 |
+
sdist = { url = "https://files.pythonhosted.org/packages/35/b9/de2a5c0144d7d75a57ff355c0c24054f965b2dc3036456ae03a51ea6264b/tomli-2.0.2.tar.gz", hash = "sha256:d46d457a85337051c36524bc5349dd91b1877838e2979ac5ced3e710ed8a60ed", size = 16096 }
|
944 |
+
wheels = [
|
945 |
+
{ url = "https://files.pythonhosted.org/packages/cf/db/ce8eda256fa131af12e0a76d481711abe4681b6923c27efb9a255c9e4594/tomli-2.0.2-py3-none-any.whl", hash = "sha256:2ebe24485c53d303f690b0ec092806a085f07af5a5aa1464f3931eec36caaa38", size = 13237 },
|
946 |
+
]
|
947 |
+
|
948 |
[[package]]
|
949 |
name = "tomlkit"
|
950 |
version = "0.12.0"
|