250 lines
8.5 KiB
Python
250 lines
8.5 KiB
Python
# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
import os
|
|
from pathlib import Path
|
|
from typing import List, Tuple, Type
|
|
|
|
from uvicorn.config import LOGGING_CONFIG
|
|
|
|
from paddlenlp.utils.import_utils import is_package_available
|
|
|
|
# check whether the package is available and give friendly description.
|
|
if not is_package_available("typer"):
|
|
raise ModuleNotFoundError(
|
|
"paddlenlp-cli tools is not installed correctly, you can use the following command"
|
|
" to install paddlenlp cli tool: >>> pip install paddlenlp[cli]"
|
|
)
|
|
|
|
import importlib
|
|
import inspect
|
|
import shutil
|
|
|
|
import typer
|
|
|
|
from paddlenlp.cli.download import load_community_models
|
|
from paddlenlp.cli.install import install_package_from_bos
|
|
from paddlenlp.cli.server import start_backend
|
|
from paddlenlp.cli.utils.tabulate import print_example_code, tabulate
|
|
from paddlenlp.transformers import (
|
|
AutoModel,
|
|
AutoTokenizer,
|
|
PretrainedModel,
|
|
PretrainedTokenizer,
|
|
)
|
|
from paddlenlp.transformers.utils import find_transformer_model_type
|
|
from paddlenlp.utils.downloader import is_url
|
|
from paddlenlp.utils.log import logger
|
|
|
|
|
|
def load_all_models(include_community: bool = False) -> List[Tuple[str, str]]:
|
|
"""load all model_name infos
|
|
|
|
Returns:
|
|
List[Tuple[str, str]]: [model_type, model_name]
|
|
"""
|
|
# 1. load official models
|
|
module = importlib.import_module("paddlenlp.transformers")
|
|
model_names = []
|
|
model_names_dict = {}
|
|
for attr_name in dir(module):
|
|
if attr_name.startswith("_"):
|
|
continue
|
|
obj = getattr(module, attr_name)
|
|
if not inspect.isclass(obj):
|
|
continue
|
|
if not issubclass(obj, PretrainedModel):
|
|
continue
|
|
|
|
obj: Type[PretrainedModel] = obj
|
|
if not obj.__name__.endswith("PretrainedModel"):
|
|
continue
|
|
configurations = obj.pretrained_init_configuration
|
|
model_type = find_transformer_model_type(obj)
|
|
for model_name in configurations.keys():
|
|
# get model type with refactoring
|
|
model_names.append((model_type, model_name))
|
|
model_names_dict[model_name] = True
|
|
|
|
logger.info(f"find {len(model_names)} official models ...")
|
|
|
|
# 2. load & extend community models
|
|
if include_community:
|
|
community_model_names = load_community_models()
|
|
for model_name in community_model_names:
|
|
# there are some same model-names between codebase and community models
|
|
if model_name in model_names_dict:
|
|
continue
|
|
|
|
model_names.append(model_name)
|
|
# 3. sort result
|
|
model_names.sort(key=lambda item: item[0] + item[1])
|
|
return model_names
|
|
|
|
|
|
app = typer.Typer()
|
|
|
|
|
|
@app.command()
|
|
def download(
|
|
model_name: str,
|
|
cache_dir: str = typer.Option(
|
|
"./pretrained_models", "--cache-dir", "-c", help="cache_dir for download pretrained model"
|
|
),
|
|
force_download: bool = typer.Option(False, "--force-download", "-f", help="force download pretrained model"),
|
|
):
|
|
"""download the paddlenlp models with command, you can specific `model_name`
|
|
|
|
>>> paddlenlp download bert \n
|
|
>>> paddlenlp download -c ./my-models -f bert \n
|
|
|
|
Args:\n
|
|
model_name (str): pretrained model name, you can checkout all of model from source code. \n
|
|
cache_dir (str, optional): the cache_dir. Defaults to "./models".
|
|
"""
|
|
if not os.path.isabs(cache_dir):
|
|
cache_dir = os.path.join(os.getcwd(), cache_dir)
|
|
|
|
if is_url(model_name):
|
|
logger.error("<MODEL_NAME> can not be url")
|
|
return
|
|
|
|
cache_dir = os.path.join(cache_dir, model_name)
|
|
if force_download:
|
|
shutil.rmtree(cache_dir, ignore_errors=True)
|
|
|
|
model: PretrainedModel = AutoModel.from_pretrained(model_name)
|
|
model.save_pretrained(cache_dir)
|
|
|
|
tokenizer: PretrainedTokenizer = AutoTokenizer.from_pretrained(model_name)
|
|
tokenizer.save_pretrained(cache_dir)
|
|
|
|
logger.info(f"successfully saved model into <{cache_dir}>")
|
|
|
|
|
|
@app.command()
|
|
def search(
|
|
query=typer.Argument(..., help="the query of searching model"),
|
|
include_community: bool = typer.Option(
|
|
False, "--include-community", "-i", help="whether searching community models"
|
|
),
|
|
):
|
|
"""search the model with query, eg: paddlenlp search bert
|
|
|
|
>>> paddlenlp search bert \n
|
|
>>> paddlenlp search -i bert \n
|
|
|
|
Args: \n
|
|
query (Optional[str]): the str fragment of bert-name \n
|
|
include_community (Optional[bool]): whether searching community models
|
|
"""
|
|
logger.info("start to search models ...")
|
|
model_names = load_all_models(include_community)
|
|
|
|
tables = []
|
|
for model_type, model_name in model_names:
|
|
# TODO(wj-Mcat): ignore the model_category info
|
|
if not query or query in model_name:
|
|
tables.append([model_type, model_name])
|
|
tabulate(tables, headers=["model type", "model name"], highlight_word=query)
|
|
print_example_code()
|
|
|
|
logger.info(f"the retrieved number of models results is {len(tables)} ...")
|
|
|
|
|
|
@app.command(help="Start the PaddleNLP SimpleServer.")
|
|
def server(
|
|
app: str,
|
|
host: str = typer.Option("127.0.0.1", "--host", help="Bind socket to this host."),
|
|
port: int = typer.Option("8000", "--port", help="Bind socket to this port."),
|
|
app_dir: str = typer.Option(None, "--app_dir", help="The application directory path."),
|
|
workers: int = typer.Option(
|
|
None,
|
|
"--workers",
|
|
help="Number of worker processes. Defaults to the $WEB_CONCURRENCY environment"
|
|
" variable if available, or 1. Not valid with --reload.",
|
|
),
|
|
log_level: int = typer.Option(None, "--log_level", help="Log level. [default: info]"),
|
|
limit_concurrency: int = typer.Option(
|
|
None, "--limit-concurrency", help="Maximum number of concurrent connections or tasks to allow, before issuing"
|
|
),
|
|
limit_max_requests: int = typer.Option(
|
|
None, "--limit-max-requests", help="Maximum number of requests to service before terminating the process."
|
|
),
|
|
timeout_keep_alive: int = typer.Option(
|
|
15, "--timeout-keep-alive", help="Close Keep-Alive connections if no new data is received within this timeout."
|
|
),
|
|
reload: bool = typer.Option(False, "--reload", help="Reload the server when the app_dir is changed."),
|
|
):
|
|
"""The main function for the staring the SimpleServer"""
|
|
logger.info("starting to PaddleNLP SimpleServer...")
|
|
if app_dir is None:
|
|
app_dir = str(Path(os.getcwd()))
|
|
# Flags of uvicorn
|
|
backend_kwargs = {
|
|
"host": host,
|
|
"port": port,
|
|
"log_config": LOGGING_CONFIG,
|
|
"log_level": log_level,
|
|
"workers": workers,
|
|
"limit_concurrency": limit_concurrency,
|
|
"limit_max_requests": limit_max_requests,
|
|
"timeout_keep_alive": timeout_keep_alive,
|
|
"app_dir": app_dir,
|
|
"reload": reload,
|
|
}
|
|
start_backend(app, **backend_kwargs)
|
|
|
|
|
|
@app.command(
|
|
help="install the target version of paddlenlp, eg: paddlenlp install / paddlenlp install paddlepaddle==latest"
|
|
)
|
|
def install(
|
|
package: str = typer.Argument(default="paddlenlp==latest", help="install the target version of paddlenlp")
|
|
):
|
|
"""The main function for the staring the SimpleServer"""
|
|
package = package.replace(" ", "").strip()
|
|
|
|
if not package:
|
|
raise ValueError("please assign the package name")
|
|
|
|
# 1. parse the version of paddlenlp
|
|
splits = [item for item in package.split("==")]
|
|
if len(splits) == 0 or len(splits) > 2:
|
|
raise ValueError(
|
|
"please set the valid package: <package-name>==<version>, eg: paddlenlp==latest, paddlenlp==3099, "
|
|
f"but received: {package}"
|
|
)
|
|
|
|
tag = "latest"
|
|
package_name = splits[0]
|
|
|
|
# TODO(wj-Mcat): will support `pipelines`, `ppdiffusers` later.
|
|
assert package_name in ["paddlenlp"], "we only support paddlenlp"
|
|
|
|
if len(splits) == 2:
|
|
tag = splits[1]
|
|
|
|
# 2. download & install package from bos server
|
|
install_package_from_bos(package_name=package_name, tag=tag)
|
|
|
|
|
|
def main():
|
|
"""the PaddleNLP CLI entry"""
|
|
app()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|