peteralexandercharles hysts HF staff commited on
Commit
ad1cd58
0 Parent(s):

Duplicate from hysts/space-that-creates-model-demo-space

Browse files

Co-authored-by: hysts <hysts@users.noreply.huggingface.co>

Files changed (6) hide show
  1. .gitattributes +31 -0
  2. .pre-commit-config.yaml +45 -0
  3. .style.yapf +5 -0
  4. README.md +13 -0
  5. app.py +173 -0
  6. assets/template.py +36 -0
.gitattributes ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ *.7z filter=lfs diff=lfs merge=lfs -text
2
+ *.arrow filter=lfs diff=lfs merge=lfs -text
3
+ *.bin filter=lfs diff=lfs merge=lfs -text
4
+ *.bz2 filter=lfs diff=lfs merge=lfs -text
5
+ *.ftz filter=lfs diff=lfs merge=lfs -text
6
+ *.gz filter=lfs diff=lfs merge=lfs -text
7
+ *.h5 filter=lfs diff=lfs merge=lfs -text
8
+ *.joblib filter=lfs diff=lfs merge=lfs -text
9
+ *.lfs.* filter=lfs diff=lfs merge=lfs -text
10
+ *.model filter=lfs diff=lfs merge=lfs -text
11
+ *.msgpack filter=lfs diff=lfs merge=lfs -text
12
+ *.npy filter=lfs diff=lfs merge=lfs -text
13
+ *.npz filter=lfs diff=lfs merge=lfs -text
14
+ *.onnx filter=lfs diff=lfs merge=lfs -text
15
+ *.ot filter=lfs diff=lfs merge=lfs -text
16
+ *.parquet filter=lfs diff=lfs merge=lfs -text
17
+ *.pickle filter=lfs diff=lfs merge=lfs -text
18
+ *.pkl filter=lfs diff=lfs merge=lfs -text
19
+ *.pb filter=lfs diff=lfs merge=lfs -text
20
+ *.pt filter=lfs diff=lfs merge=lfs -text
21
+ *.pth filter=lfs diff=lfs merge=lfs -text
22
+ *.rar filter=lfs diff=lfs merge=lfs -text
23
+ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
24
+ *.tar.* filter=lfs diff=lfs merge=lfs -text
25
+ *.tflite filter=lfs diff=lfs merge=lfs -text
26
+ *.tgz filter=lfs diff=lfs merge=lfs -text
27
+ *.wasm filter=lfs diff=lfs merge=lfs -text
28
+ *.xz filter=lfs diff=lfs merge=lfs -text
29
+ *.zip filter=lfs diff=lfs merge=lfs -text
30
+ *.zst filter=lfs diff=lfs merge=lfs -text
31
+ *tfevents* filter=lfs diff=lfs merge=lfs -text
.pre-commit-config.yaml ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ repos:
2
+ - repo: https://github.com/pre-commit/pre-commit-hooks
3
+ rev: v4.2.0
4
+ hooks:
5
+ - id: check-executables-have-shebangs
6
+ - id: check-json
7
+ - id: check-merge-conflict
8
+ - id: check-shebang-scripts-are-executable
9
+ - id: check-toml
10
+ - id: check-yaml
11
+ - id: double-quote-string-fixer
12
+ - id: end-of-file-fixer
13
+ - id: mixed-line-ending
14
+ args: ['--fix=lf']
15
+ - id: requirements-txt-fixer
16
+ - id: trailing-whitespace
17
+ - repo: https://github.com/myint/docformatter
18
+ rev: v1.4
19
+ hooks:
20
+ - id: docformatter
21
+ args: ['--in-place']
22
+ - repo: https://github.com/pycqa/isort
23
+ rev: 5.10.1
24
+ hooks:
25
+ - id: isort
26
+ - repo: https://github.com/pre-commit/mirrors-mypy
27
+ rev: v0.812
28
+ hooks:
29
+ - id: mypy
30
+ args: ['--ignore-missing-imports']
31
+ - repo: https://github.com/google/yapf
32
+ rev: v0.32.0
33
+ hooks:
34
+ - id: yapf
35
+ args: ['--parallel', '--in-place']
36
+ - repo: https://github.com/kynan/nbstripout
37
+ rev: 0.5.0
38
+ hooks:
39
+ - id: nbstripout
40
+ args: ['--extra-keys', 'metadata.interpreter metadata.kernelspec cell.metadata.pycharm']
41
+ - repo: https://github.com/nbQA-dev/nbQA
42
+ rev: 1.3.1
43
+ hooks:
44
+ - id: nbqa-isort
45
+ - id: nbqa-yapf
.style.yapf ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ [style]
2
+ based_on_style = pep8
3
+ blank_line_before_nested_class_or_def = false
4
+ spaces_before_comment = 2
5
+ split_before_logical_operator = true
README.md ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: Space That Creates Model Demo Space
3
+ emoji: 🐠
4
+ colorFrom: yellow
5
+ colorTo: yellow
6
+ sdk: gradio
7
+ sdk_version: 3.1.6
8
+ app_file: app.py
9
+ pinned: false
10
+ duplicated_from: hysts/space-that-creates-model-demo-space
11
+ ---
12
+
13
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
app.py ADDED
@@ -0,0 +1,173 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python
2
+
3
+ from __future__ import annotations
4
+
5
+ import shutil
6
+ import tempfile
7
+
8
+ import gradio as gr
9
+ from huggingface_hub import HfApi
10
+
11
+ title = 'Model Demo Creation'
12
+ description = '''
13
+ With this Space, you can create a demo Space for models that are loadable with `gradio.Interface.load` in [Model Hub](https://huggingface.co/models).
14
+ The Space will be created under your account and private.
15
+ You need a token with write permission (See: https://huggingface.co/settings/tokens).
16
+
17
+ You can specify multiple model names by listing them separated by commas.
18
+ If you specify multiple model names, the resulting Space will show all the outputs of those models side by side for the given inputs.
19
+ '''
20
+ article = ''
21
+ examples = [
22
+ [
23
+ 'resnet-50',
24
+ 'microsoft/resnet-50',
25
+ '',
26
+ 'Demo for microsoft/resnet-50',
27
+ '',
28
+ '',
29
+ ],
30
+ [
31
+ 'compare-image-classification-models',
32
+ 'google/vit-base-patch16-224, microsoft/resnet-50',
33
+ '',
34
+ 'Compare Image Classification Models',
35
+ '',
36
+ '',
37
+ ],
38
+ [
39
+ 'compare-text-generation-models',
40
+ 'EleutherAI/gpt-j-6B, EleutherAI/gpt-neo-1.3B',
41
+ '',
42
+ 'Compare Text Generation Models',
43
+ '',
44
+ '',
45
+ ],
46
+ ]
47
+
48
+ api = HfApi()
49
+
50
+
51
+ def check_if_model_exists(model_name: str) -> bool:
52
+ return any(info.modelId == model_name
53
+ for info in api.list_models(search=model_name))
54
+
55
+
56
+ def check_if_model_loadable(model_name: str) -> bool:
57
+ try:
58
+ gr.Interface.load(model_name, src='models')
59
+ except Exception:
60
+ return False
61
+ return True
62
+
63
+
64
+ def get_model_io_types(
65
+ model_name: str) -> tuple[tuple[str, ...], tuple[str, ...]]:
66
+ iface = gr.Interface.load(model_name, src='models')
67
+ inputs = tuple(map(str, iface.input_components))
68
+ outputs = tuple(map(str, iface.output_components))
69
+ return inputs, outputs
70
+
71
+
72
+ def check_if_model_io_is_consistent(model_names: list[str]) -> bool:
73
+ if len(model_names) == 1:
74
+ return True
75
+
76
+ inputs0, outputs0 = get_model_io_types(model_names[0])
77
+ for name in model_names[1:]:
78
+ inputs, outputs = get_model_io_types(name)
79
+ if inputs != inputs0 or outputs != outputs0:
80
+ return False
81
+ return True
82
+
83
+
84
+ def save_space_info(dirname: str, filename: str, content: str) -> None:
85
+ with open(f'{dirname}/{filename}', 'w') as f:
86
+ f.write(content)
87
+
88
+
89
+ def run(space_name: str, model_names_str: str, hf_token: str, title: str,
90
+ description: str, article: str) -> str:
91
+ if space_name == '':
92
+ return 'Space Name must be specified.'
93
+ if model_names_str == '':
94
+ return 'Model Names must be specified.'
95
+ if hf_token == '':
96
+ return 'Hugging Face Token must be specified.'
97
+
98
+ model_names = [name.strip() for name in model_names_str.split(',')]
99
+ model_names_str = '\n'.join(model_names)
100
+
101
+ missing_models = [
102
+ name for name in model_names if not check_if_model_exists(name)
103
+ ]
104
+ if len(missing_models) > 0:
105
+ message = 'The following models were not found: '
106
+ for model_name in missing_models:
107
+ message += f'\n{model_name}'
108
+ return message
109
+
110
+ non_loadable_models = [
111
+ name for name in model_names if not check_if_model_loadable(name)
112
+ ]
113
+ if len(non_loadable_models) > 0:
114
+ message = 'The following models are not loadable with gradio.Interface.load: '
115
+ for model_name in non_loadable_models:
116
+ message += f'\n{model_name}'
117
+ return message
118
+
119
+ if not check_if_model_io_is_consistent(model_names):
120
+ return 'The inputs and outputs of each model must be the same.'
121
+
122
+ user_name = api.whoami(token=hf_token)['name']
123
+ repo_id = f'{user_name}/{space_name}'
124
+ try:
125
+ space_url = api.create_repo(repo_id=repo_id,
126
+ repo_type='space',
127
+ private=True,
128
+ token=hf_token,
129
+ space_sdk='gradio')
130
+ except Exception as e:
131
+ return str(e)
132
+
133
+ with tempfile.TemporaryDirectory() as temp_dir:
134
+ shutil.copy('assets/template.py', f'{temp_dir}/app.py')
135
+ save_space_info(temp_dir, 'TITLE', title)
136
+ save_space_info(temp_dir, 'DESCRIPTION', description)
137
+ save_space_info(temp_dir, 'ARTICLE', article)
138
+ save_space_info(temp_dir, 'MODEL_NAMES', model_names_str)
139
+ api.upload_folder(repo_id=repo_id,
140
+ folder_path=temp_dir,
141
+ path_in_repo='.',
142
+ token=hf_token,
143
+ repo_type='space')
144
+
145
+ return f'Successfully created: {space_url}'
146
+
147
+
148
+ gr.Interface(
149
+ fn=run,
150
+ inputs=[
151
+ gr.Textbox(
152
+ label='Space Name',
153
+ placeholder=
154
+ 'e.g. demo-resnet-50. The Space will be created under your account and private.'
155
+ ),
156
+ gr.Textbox(label='Model Names',
157
+ placeholder='e.g. microsoft/resnet-50'),
158
+ gr.Textbox(
159
+ label='Hugging Face Token',
160
+ placeholder=
161
+ 'This should be a token with write permission. See: https://huggingface.co/settings/tokens'
162
+ ),
163
+ gr.Textbox(label='Title (Optional)'),
164
+ gr.Textbox(label='Description (Optional)'),
165
+ gr.Textbox(label='Article (Optional)'),
166
+ ],
167
+ outputs=gr.Textbox(label='Output'),
168
+ title=title,
169
+ description=description,
170
+ article=article,
171
+ examples=examples,
172
+ cache_examples=False,
173
+ ).launch(enable_queue=True, share=False)
assets/template.py ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python
2
+
3
+ from __future__ import annotations
4
+
5
+ import gradio as gr
6
+
7
+
8
+ def read_info(file_name: str) -> str:
9
+ with open(file_name) as f:
10
+ content = f.read()
11
+ return content
12
+
13
+
14
+ def load_model(model_name: str) -> gr.Interface:
15
+ iface = gr.Interface.load(model_name, src='models')
16
+ for component in iface.output_components:
17
+ component.label = f'{component.label} ({model_name})'
18
+ return iface
19
+
20
+
21
+ def load_models(model_names: list[str]) -> list[gr.Interface]:
22
+ return [load_model(name) for name in model_names]
23
+
24
+
25
+ title = read_info('TITLE')
26
+ description = read_info('DESCRIPTION')
27
+ article = read_info('ARTICLE')
28
+ model_names = read_info('MODEL_NAMES').split('\n')
29
+
30
+ interfaces = load_models(model_names)
31
+ gr.Parallel(
32
+ *interfaces,
33
+ title=title,
34
+ description=description,
35
+ article=article,
36
+ ).launch()