chenlei1983 commited on
Commit
8627484
1 Parent(s): d6f5daf

Upload 4 files

Browse files
Files changed (4) hide show
  1. app.py +118 -0
  2. git_commd.py +238 -0
  3. logger.py +89 -0
  4. requirements.txt +3 -0
app.py ADDED
@@ -0,0 +1,118 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import os
3
+ from git_commd import GitCommandWrapper
4
+ from typing import List, Optional
5
+
6
+ HF_TOKEN=os.environ['HF_TOKEN'] if 'HF_TOKEN' in os.environ else ''
7
+
8
+
9
+ def get_cache_dir():
10
+ from random_word import RandomWords
11
+ r = RandomWords()
12
+ return r.get_random_word()
13
+
14
+
15
+ def check_disk():
16
+ import os
17
+ return os.system("df -h /")
18
+
19
+
20
+ def pull_from_wisemodel(token: str,
21
+ url: str,
22
+ repo_name: str,
23
+ cache_dir,
24
+ branch: Optional[str] = None):
25
+
26
+
27
+ print(cache_dir)
28
+ os.makedirs(cache_dir, exist_ok=True)
29
+ # os.system("cd "+cache_dir)
30
+ gitCmd=GitCommandWrapper()
31
+ isLfs=gitCmd.is_lfs_installed()
32
+ if (not isLfs):
33
+ gitCmd.git_lfs_install()
34
+ gitCmd.clone(cache_dir,token,url,repo_name,branch)
35
+
36
+ return f'Pulled {branch} to temp folder {cache_dir}: {url}'
37
+
38
+
39
+ def remove_file(cache_dir, repo_name):
40
+ import os
41
+ try:
42
+ os.remove(f'{cache_dir}/{repo_name}')
43
+ except:
44
+ return ''
45
+ return 'README.md file removed'
46
+
47
+
48
+ def push_to_hf(cache_dir, WiseModel_repo_name, hf_repo_id):
49
+ from huggingface_hub import HfApi
50
+
51
+ if not HF_TOKEN:
52
+ raise gr.Error("Please enter your HF_TOKEN")
53
+
54
+ api = HfApi(token=HF_TOKEN) # Token is not persisted on the machine.
55
+ output = api.upload_folder(
56
+ folder_path=f"{cache_dir}/{WiseModel_repo_name}",
57
+ repo_id=hf_repo_id,
58
+ repo_type="model",
59
+ )
60
+ return f'Pushed to {hf_repo_id}'
61
+
62
+
63
+ def handle(wisemodel_token,wisemodel_link, hf_repo_id):
64
+ cache_dir = get_cache_dir()
65
+ wiseModel_repo_url=wisemodel_link.replace(".git","").replace("git","").replace("clone","").replace(" ","")
66
+ wiseModel_repo_info=wisemodel_link.replace(".git","").replace("git","").replace("clone","").replace(" ","").split("/")
67
+ print(wiseModel_repo_info)
68
+ wisemodel_repo_name=wiseModel_repo_info[len(wiseModel_repo_info)-1]
69
+ stages = [
70
+ (check_disk, (), {}),
71
+ # # Run all the sanity checks on README.md
72
+
73
+ (pull_from_wisemodel, (wisemodel_token,wiseModel_repo_url,wisemodel_repo_name, cache_dir,"main"), {}),
74
+ (remove_file, (wisemodel_repo_name, cache_dir), {}),
75
+ (check_disk, (), {}),
76
+ (push_to_hf, (cache_dir, wisemodel_repo_name, hf_repo_id), {}),
77
+ (check_disk, (), {}),
78
+ ]
79
+
80
+ results = []
81
+ errors = []
82
+ for func, args, kwargs in stages:
83
+ try:
84
+ results.append(str(func(*args, **kwargs)))
85
+ except Exception as e:
86
+ errors.append(str(e))
87
+ if errors:
88
+ break
89
+
90
+ return '\n\n'.join(results), '\n\n'.join(errors)
91
+
92
+
93
+ with gr.Blocks() as demo:
94
+ gr.Markdown('''
95
+ This space uploads model from WiseModel to Huggingface.
96
+
97
+ **Please make sure that you're the owner of the repo or have permission from the owner to do so!**
98
+
99
+ # How to use this Space?
100
+ - Duplicate this Space and providing WiseModel token (optional) and your read/write HF token (mandatory)
101
+ - Create your target model repo on HF. This step needs to be done manually. The Space doesn't do create an empty repo for you.
102
+ - In your own private Space, fill in information below.
103
+ - Click submit then watch for output in container log for progress.
104
+ - Create README.md file (since the metadata is not compatible with HF)
105
+ ''')
106
+ wisemodel_token= gr.Textbox(label="wisemodel user git token")
107
+ wisemodel_link = gr.Textbox(label="Copy the git download link from the model detail page of wisemodel ")
108
+ hf_repo_id = gr.Textbox(label="Target HF Model Repo ID (case sensitive). \nPlease make sure that this model has already been created")
109
+ with gr.Row():
110
+ button = gr.Button("Submit", variant="primary")
111
+ clear = gr.Button("Clear")
112
+ error = gr.Textbox(label="Error")
113
+ output = gr.Textbox(label="Output")
114
+
115
+ button.click(handle, [wisemodel_token,wisemodel_link, hf_repo_id], [output, error])
116
+
117
+ if __name__ == "__main__":
118
+ demo.launch(debug = True)
git_commd.py ADDED
@@ -0,0 +1,238 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import subprocess
3
+ from typing import List, Optional
4
+
5
+ from logger import get_logger
6
+ logger = get_logger()
7
+ class Singleton(type):
8
+ _instances = {}
9
+
10
+ def __call__(cls, *args, **kwargs):
11
+ if cls not in cls._instances:
12
+ cls._instances[cls] = super(Singleton,
13
+ cls).__call__(*args, **kwargs)
14
+ return cls._instances[cls]
15
+
16
+ class GitError(Exception):
17
+ pass
18
+ class GitCommandWrapper(metaclass=Singleton):
19
+ """Some git operation wrapper
20
+ """
21
+ default_git_path = 'git' # The default git command line
22
+ git_path='git'
23
+ MASTER_MODEL_BRANCH="main"
24
+ def __init__(self, path: str = None):
25
+ self.git_path = path or self.default_git_path
26
+
27
+ def _run_git_command(self, *args) -> subprocess.CompletedProcess:
28
+ """Run git command, if command return 0, return subprocess.response
29
+ otherwise raise GitError, message is stdout and stderr.
30
+
31
+ Args:
32
+ args: List of command args.
33
+
34
+ Raises:
35
+ GitError: Exception with stdout and stderr.
36
+
37
+ Returns:
38
+ subprocess.CompletedProcess: the command response
39
+ """
40
+ logger.debug(' '.join(args))
41
+ git_env = os.environ.copy()
42
+ git_env['GIT_TERMINAL_PROMPT'] = '0'
43
+ response = subprocess.run(
44
+ [self.git_path, *args],
45
+ stdout=subprocess.PIPE,
46
+ stderr=subprocess.PIPE,
47
+ env=git_env,
48
+ ) # compatible for python3.6
49
+ try:
50
+ response.check_returncode()
51
+ return response
52
+ except subprocess.CalledProcessError as error:
53
+ logger.error('There are error run git command.')
54
+ raise GitError(
55
+ 'stdout: %s, stderr: %s' %
56
+ (response.stdout.decode('utf8'), error.stderr.decode('utf8')))
57
+
58
+ def config_auth_token(self, repo_dir, auth_token):
59
+ url = self.get_repo_remote_url(repo_dir)
60
+ if '//oauth2' not in url:
61
+ auth_url = self._add_token(auth_token, url)
62
+ cmd_args = '-C %s remote set-url origin %s' % (repo_dir, auth_url)
63
+ cmd_args = cmd_args.split(' ')
64
+ rsp = self._run_git_command(*cmd_args)
65
+ logger.debug(rsp.stdout.decode('utf8'))
66
+
67
+ def _add_token(self, token: str, url: str):
68
+ if token:
69
+ if '//oauth2' not in url:
70
+ url = url.replace('//', '//oauth2:%s@' % token)
71
+ return url
72
+
73
+ def remove_token_from_url(self, url: str):
74
+ if url and '//oauth2' in url:
75
+ start_index = url.find('oauth2')
76
+ end_index = url.find('@')
77
+ url = url[:start_index] + url[end_index + 1:]
78
+ return url
79
+
80
+ def is_lfs_installed(self):
81
+ cmd = ['lfs', 'env']
82
+ try:
83
+ self._run_git_command(*cmd)
84
+ return True
85
+ except GitError:
86
+ return False
87
+
88
+ def git_lfs_install(self, repo_dir):
89
+ cmd = ['-C', repo_dir, 'lfs', 'install']
90
+ try:
91
+ self._run_git_command(*cmd)
92
+ return True
93
+ except GitError:
94
+ return False
95
+
96
+ def clone(self,
97
+ repo_base_dir: str,
98
+ token: str,
99
+ url: str,
100
+ repo_name: str,
101
+ branch: Optional[str] = None):
102
+ """ git clone command wrapper.
103
+ For public project, token can None, private repo, there must token.
104
+
105
+ Args:
106
+ repo_base_dir (str): The local base dir, the repository will be clone to local_dir/repo_name
107
+ token (str): The git token, must be provided for private project.
108
+ url (str): The remote url
109
+ repo_name (str): The local repository path name.
110
+ branch (str, optional): _description_. Defaults to None.
111
+
112
+ Returns:
113
+ The popen response.
114
+ """
115
+ url = self._add_token(token, url)
116
+ if branch:
117
+ clone_args = '-C %s clone %s %s --branch %s' % (repo_base_dir, url,
118
+ repo_name, branch)
119
+ else:
120
+ clone_args = '-C %s clone %s' % (repo_base_dir, url)
121
+ logger.debug(clone_args)
122
+ clone_args = clone_args.split(' ')
123
+ response = self._run_git_command(*clone_args)
124
+ logger.debug(response.stdout.decode('utf8'))
125
+ return response
126
+
127
+
128
+
129
+ def add(self,
130
+ repo_dir: str,
131
+ files: List[str] = list(),
132
+ all_files: bool = False):
133
+ if all_files:
134
+ add_args = '-C %s add -A' % repo_dir
135
+ elif len(files) > 0:
136
+ files_str = ' '.join(files)
137
+ add_args = '-C %s add %s' % (repo_dir, files_str)
138
+ add_args = add_args.split(' ')
139
+ rsp = self._run_git_command(*add_args)
140
+ logger.debug(rsp.stdout.decode('utf8'))
141
+ return rsp
142
+
143
+ def commit(self, repo_dir: str, message: str):
144
+ """Run git commit command
145
+
146
+ Args:
147
+ repo_dir (str): the repository directory.
148
+ message (str): commit message.
149
+
150
+ Returns:
151
+ The command popen response.
152
+ """
153
+ commit_args = ['-C', '%s' % repo_dir, 'commit', '-m', "'%s'" % message]
154
+ rsp = self._run_git_command(*commit_args)
155
+ logger.info(rsp.stdout.decode('utf8'))
156
+ return rsp
157
+
158
+ def checkout(self, repo_dir: str, revision: str):
159
+ cmds = ['-C', '%s' % repo_dir, 'checkout', '%s' % revision]
160
+ return self._run_git_command(*cmds)
161
+
162
+ def new_branch(self, repo_dir: str, revision: str):
163
+ cmds = ['-C', '%s' % repo_dir, 'checkout', '-b', revision]
164
+ return self._run_git_command(*cmds)
165
+
166
+ def get_remote_branches(self, repo_dir: str):
167
+ cmds = ['-C', '%s' % repo_dir, 'branch', '-r']
168
+ rsp = self._run_git_command(*cmds)
169
+ info = [
170
+ line.strip()
171
+ for line in rsp.stdout.decode('utf8').strip().split(os.linesep)
172
+ ]
173
+ if len(info) == 1:
174
+ return ['/'.join(info[0].split('/')[1:])]
175
+ else:
176
+ return ['/'.join(line.split('/')[1:]) for line in info[1:]]
177
+
178
+ def pull(self,
179
+ repo_dir: str,
180
+ remote: str = 'origin',
181
+ branch: str = 'master'):
182
+ cmds = ['-C', repo_dir, 'pull', remote, branch]
183
+ return self._run_git_command(*cmds)
184
+
185
+ def push(self,
186
+ repo_dir: str,
187
+ token: str,
188
+ url: str,
189
+ local_branch: str,
190
+ remote_branch: str,
191
+ force: bool = False):
192
+ url = self._add_token(token, url)
193
+
194
+ push_args = '-C %s push %s %s:%s' % (repo_dir, url, local_branch,
195
+ remote_branch)
196
+ if force:
197
+ push_args += ' -f'
198
+ push_args = push_args.split(' ')
199
+ rsp = self._run_git_command(*push_args)
200
+ logger.debug(rsp.stdout.decode('utf8'))
201
+ return rsp
202
+
203
+ def get_repo_remote_url(self, repo_dir: str):
204
+ cmd_args = '-C %s config --get remote.origin.url' % repo_dir
205
+ cmd_args = cmd_args.split(' ')
206
+ rsp = self._run_git_command(*cmd_args)
207
+ url = rsp.stdout.decode('utf8')
208
+ return url.strip()
209
+
210
+ def list_lfs_files(self, repo_dir: str):
211
+ cmd_args = '-C %s lfs ls-files' % repo_dir
212
+ cmd_args = cmd_args.split(' ')
213
+ rsp = self._run_git_command(*cmd_args)
214
+ out = rsp.stdout.decode('utf8').strip()
215
+ files = []
216
+ for line in out.split(os.linesep):
217
+ files.append(line.split(' ')[-1])
218
+
219
+ return files
220
+
221
+ def tag(self,
222
+ repo_dir: str,
223
+ tag_name: str,
224
+ message: str,
225
+ ref: str = MASTER_MODEL_BRANCH):
226
+ cmd_args = [
227
+ '-C', repo_dir, 'tag', tag_name, '-m',
228
+ '"%s"' % message, ref
229
+ ]
230
+ rsp = self._run_git_command(*cmd_args)
231
+ logger.debug(rsp.stdout.decode('utf8'))
232
+ return rsp
233
+
234
+ def push_tag(self, repo_dir: str, tag_name):
235
+ cmd_args = ['-C', repo_dir, 'push', 'origin', tag_name]
236
+ rsp = self._run_git_command(*cmd_args)
237
+ logger.debug(rsp.stdout.decode('utf8'))
238
+ return rsp
logger.py ADDED
@@ -0,0 +1,89 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) Alibaba, Inc. and its affiliates.
2
+
3
+ import importlib
4
+ import logging
5
+ from typing import Optional
6
+
7
+ init_loggers = {}
8
+
9
+ formatter = logging.Formatter(
10
+ '%(asctime)s - %(name)s - %(levelname)s - %(message)s')
11
+
12
+
13
+ def get_logger(log_file: Optional[str] = None,
14
+ log_level: int = logging.INFO,
15
+ file_mode: str = 'w'):
16
+ """ Get logging logger
17
+
18
+ Args:
19
+ log_file: Log filename, if specified, file handler will be added to
20
+ logger
21
+ log_level: Logging level.
22
+ file_mode: Specifies the mode to open the file, if filename is
23
+ specified (if filemode is unspecified, it defaults to 'w').
24
+ """
25
+
26
+ logger_name = __name__.split('.')[0]
27
+ logger = logging.getLogger(logger_name)
28
+ logger.propagate = False
29
+ if logger_name in init_loggers:
30
+ add_file_handler_if_needed(logger, log_file, file_mode, log_level)
31
+ return logger
32
+
33
+ # handle duplicate logs to the console
34
+ # Starting in 1.8.0, PyTorch DDP attaches a StreamHandler <stderr> (NOTSET)
35
+ # to the root logger. As logger.propagate is True by default, this root
36
+ # level handler causes logging messages from rank>0 processes to
37
+ # unexpectedly show up on the console, creating much unwanted clutter.
38
+ # To fix this issue, we set the root logger's StreamHandler, if any, to log
39
+ # at the ERROR level.
40
+ torch_dist = False
41
+ is_worker0 = True
42
+ if importlib.util.find_spec('torch') is not None:
43
+ from modelscope.utils.torch_utils import is_dist, is_master
44
+ torch_dist = is_dist()
45
+ is_worker0 = is_master()
46
+
47
+ if torch_dist:
48
+ for handler in logger.root.handlers:
49
+ if type(handler) is logging.StreamHandler:
50
+ handler.setLevel(logging.ERROR)
51
+
52
+ stream_handler = logging.StreamHandler()
53
+ handlers = [stream_handler]
54
+
55
+ if is_worker0 and log_file is not None:
56
+ file_handler = logging.FileHandler(log_file, file_mode)
57
+ handlers.append(file_handler)
58
+
59
+ for handler in handlers:
60
+ handler.setFormatter(formatter)
61
+ handler.setLevel(log_level)
62
+ logger.addHandler(handler)
63
+
64
+ if is_worker0:
65
+ logger.setLevel(log_level)
66
+ else:
67
+ logger.setLevel(logging.ERROR)
68
+
69
+ init_loggers[logger_name] = True
70
+
71
+ return logger
72
+
73
+
74
+ def add_file_handler_if_needed(logger, log_file, file_mode, log_level):
75
+ for handler in logger.handlers:
76
+ if isinstance(handler, logging.FileHandler):
77
+ return
78
+
79
+ if importlib.util.find_spec('torch') is not None:
80
+ from modelscope.utils.torch_utils import is_master
81
+ is_worker0 = is_master()
82
+ else:
83
+ is_worker0 = True
84
+
85
+ if is_worker0 and log_file is not None:
86
+ file_handler = logging.FileHandler(log_file, file_mode)
87
+ file_handler.setFormatter(formatter)
88
+ file_handler.setLevel(log_level)
89
+ logger.addHandler(file_handler)
requirements.txt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ gradio[auth]
2
+ huggingface_hub
3
+ random-word