phate334 commited on
Commit
1a8deb0
1 Parent(s): a793e12

[add] pydantic for parser result

Browse files
Files changed (6) hide show
  1. README.md +1 -1
  2. app/models.py +104 -0
  3. app/main.py → main.py +8 -16
  4. pyproject.toml +6 -0
  5. requirements.txt +1 -0
  6. 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: app/main.py
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
- data = json.loads(res)
 
20
 
21
- metadata_df = pd.DataFrame([data["metadata"]])
22
 
23
- architecture_df = pd.DataFrame([data["architecture"]])
24
 
25
- tokenizer_df = pd.DataFrame([data["tokenizer"]])
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"