已合并
[ci]支持创建LLM .whl包 #45
gengli8创建于 2025年12月25日
[ci]支持创建LLM .whl包 #45
已合并
共 32 个文件变更+396-192
| @@ -52,7 +52,6 @@ function fn_build() | |||
| 52 | if [ "$build_type" = "release" ]; then | 52 | if [ "$build_type" = "release" ]; then |
| 53 | fn_extract_debug_symbols $OUTPUT_DIR "$CODE_ROOT/llm_debug_symbols" | 53 | fn_extract_debug_symbols $OUTPUT_DIR "$CODE_ROOT/llm_debug_symbols" |
| 54 | fi | 54 | fi |
| 55 | - fn_make_whl | ||
| 56 | fn_build_for_ci | 55 | fn_build_for_ci |
| 57 | cp $SCRIPT_DIR/set_env.sh $OUTPUT_DIR | 56 | cp $SCRIPT_DIR/set_env.sh $OUTPUT_DIR |
| 58 | } | 57 | } |
The file is empty
The file is empty
The file is empty
The file is empty
The file is empty
The file is empty
The file is empty
The file is empty
The file is empty
The file is empty
| @@ -0,0 +1,95 @@ | |||
| 1 | +#!/usr/bin/env python3 | ||
| 2 | +# Copyright (c) Huawei Technologies Co., Ltd. 2026-2026. All rights reserved. | ||
| 3 | +# MindIE is licensed under Mulan PSL v2. | ||
| 4 | +# You can use this software according to the terms and conditions of the Mulan PSL v2. | ||
| 5 | +# You may obtain a copy of Mulan PSL v2 at: | ||
| 6 | +# http://license.coscl.org.cn/MulanPSL2 | ||
| 7 | +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, | ||
| 8 | +# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, | ||
| 9 | +# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. | ||
| 10 | +# See the Mulan PSL v2 for more details. | ||
| 11 | + | ||
| 12 | +import os | ||
| 13 | +import sys | ||
| 14 | +import sysconfig | ||
| 15 | +import importlib.util | ||
| 16 | +from pathlib import Path | ||
| 17 | +from mindie_llm.utils.log.logging import logger | ||
| 18 | + | ||
| 19 | + | ||
| 20 | +def _get_pkg_dir(pkg_name: str) -> Path: | ||
| 21 | + spec = importlib.util.find_spec(pkg_name) | ||
| 22 | + if spec is None or spec.origin is None: | ||
| 23 | + raise ImportError(f"{pkg_name} is not installed") | ||
| 24 | + return Path(spec.origin).resolve().parent | ||
| 25 | + | ||
| 26 | + | ||
| 27 | +def _prepend_ld_library_path(env: dict, paths: list[Path]) -> None: | ||
| 28 | + """Prepend existing directories to LD_LIBRARY_PATH, warn if missing.""" | ||
| 29 | + valid_paths = [] | ||
| 30 | + | ||
| 31 | + for p in paths: | ||
| 32 | + if p.is_dir(): | ||
| 33 | + valid_paths.append(str(p)) | ||
| 34 | + else: | ||
| 35 | + logger.warning(f"LD_LIBRARY_PATH entry does not exist, skipped: {p}") | ||
| 36 | + | ||
| 37 | + if not valid_paths: | ||
| 38 | + return | ||
| 39 | + | ||
| 40 | + old = env.get("LD_LIBRARY_PATH", "") | ||
| 41 | + env["LD_LIBRARY_PATH"] = ":".join(([old] if old else []) + valid_paths) | ||
| 42 | + | ||
| 43 | + | ||
| 44 | +def main(): | ||
| 45 | + pkg_root = Path(__file__).resolve().parents[1] | ||
| 46 | + | ||
| 47 | + daemon_path = pkg_root / "bin" / "mindieservice_daemon" | ||
| 48 | + if not daemon_path.is_file(): | ||
| 49 | + raise RuntimeError(f"mindieservice_daemon not found at {daemon_path}") | ||
| 50 | + | ||
| 51 | + # Set configure file permission to meet safety requirement | ||
| 52 | + config_path = pkg_root / "conf" / "config.json" | ||
| 53 | + if not config_path.is_file(): | ||
| 54 | + raise RuntimeError(f"config.json not found at {config_path}") | ||
| 55 | + | ||
| 56 | + # Set environment variables | ||
| 57 | + env = os.environ.copy() | ||
| 58 | + env["MIES_INSTALL_PATH"] = str(pkg_root) | ||
| 59 | + | ||
| 60 | + lib_str = "lib" | ||
| 61 | + lib_dir = pkg_root / lib_str | ||
| 62 | + if not lib_dir.is_dir(): | ||
| 63 | + raise RuntimeError(f"Lib directory not found at {lib_dir}") | ||
| 64 | + | ||
| 65 | + # torch | ||
| 66 | + torch_dir = _get_pkg_dir("torch") | ||
| 67 | + torch_lib = torch_dir / lib_str | ||
| 68 | + torch_libs = torch_dir.parent / "torch.libs" # torch.libs is a sibling of torch/ | ||
| 69 | + | ||
| 70 | + # atb_llm | ||
| 71 | + atb_llm_dir = _get_pkg_dir("atb_llm") | ||
| 72 | + atb_llm_lib = atb_llm_dir / lib_str | ||
| 73 | + | ||
| 74 | + _prepend_ld_library_path( | ||
| 75 | + env, | ||
| 76 | + [ | ||
| 77 | + torch_lib, | ||
| 78 | + torch_libs, | ||
| 79 | + atb_llm_lib, | ||
| 80 | + lib_dir, | ||
| 81 | + lib_dir / "grpc", | ||
| 82 | + ], | ||
| 83 | + ) | ||
| 84 | + | ||
| 85 | + env["PYTHONPATH"] = f"{lib_dir}:{env.get('PYTHONPATH', '')}" | ||
| 86 | + | ||
| 87 | + os.execve( | ||
| 88 | + str(daemon_path), | ||
| 89 | + [str(daemon_path)] + sys.argv[1:], | ||
| 90 | + env, | ||
| 91 | + ) | ||
| 92 | + | ||
| 93 | + | ||
| 94 | +if __name__ == "__main__": | ||
| 95 | + main() | ||
| @@ -10,6 +10,6 @@ | |||
| 10 | # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. | 10 | # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. |
| 11 | # See the Mulan PSL v2 for more details. | 11 | # See the Mulan PSL v2 for more details. |
| 12 | 12 | ||
| 13 | -from .base import MemPool | 13 | +__all__ = ["MemPool"] |
| 14 | 14 | ||
| 15 | -__all__ = ["MemPool"] | 15 | +from .base import MemPool |
The file is empty
| @@ -10,6 +10,6 @@ | |||
| 10 | # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. | 10 | # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. |
| 11 | # See the Mulan PSL v2 for more details. | 11 | # See the Mulan PSL v2 for more details. |
| 12 | 12 | ||
| 13 | -from .tokenizer import IbisTokenizer | 13 | +__all__ = ["IbisTokenizer"] |
| 14 | 14 | ||
| 15 | -__all__ = ["IbisTokenizer"] | 15 | +from .tokenizer import IbisTokenizer |
| @@ -15,7 +15,7 @@ if(NOT EXISTS "${PROTO_SRCS}" OR "${PROTO_FILE}" IS_NEWER_THAN "${PROTO_SRCS}") | |||
| 15 | RESULT_VARIABLE CPP_GENERATE_RESULT | 15 | RESULT_VARIABLE CPP_GENERATE_RESULT |
| 16 | ERROR_VARIABLE CPP_GENERATE_ERROR | 16 | ERROR_VARIABLE CPP_GENERATE_ERROR |
| 17 | ) | 17 | ) |
| 18 | - | 18 | + |
| 19 | # 检查 C++ 生成结果 | 19 | # 检查 C++ 生成结果 |
| 20 | if(NOT CPP_GENERATE_RESULT EQUAL 0) | 20 | if(NOT CPP_GENERATE_RESULT EQUAL 0) |
| 21 | message(FATAL_ERROR "Failed to generate C++ files: ${CPP_GENERATE_ERROR}") | 21 | message(FATAL_ERROR "Failed to generate C++ files: ${CPP_GENERATE_ERROR}") |
| @@ -23,7 +23,7 @@ if(NOT EXISTS "${PROTO_SRCS}" OR "${PROTO_FILE}" IS_NEWER_THAN "${PROTO_SRCS}") | |||
| 23 | else() | 23 | else() |
| 24 | message(STATUS "No need to convert. ${PROTO_SRCS} is up to date.") | 24 | message(STATUS "No need to convert. ${PROTO_SRCS} is up to date.") |
| 25 | endif() | 25 | endif() |
| 26 | - | 26 | + |
| 27 | add_library(mindie_protobuf STATIC ${PROTO_SRCS} ${PROTO_HDRS}) | 27 | add_library(mindie_protobuf STATIC ${PROTO_SRCS} ${PROTO_HDRS}) |
| 28 | 28 | ||
| 29 | set_target_properties(mindie_protobuf PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/lib") | 29 | set_target_properties(mindie_protobuf PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/lib") |
| @@ -48,7 +48,7 @@ if(NOT EXISTS "${GRPC_DST_FILE}" OR "${PROTO_FILE}" IS_NEWER_THAN "${GRPC_DST_FI | |||
| 48 | RESULT_VARIABLE GRPC_GENERATE_RESULT | 48 | RESULT_VARIABLE GRPC_GENERATE_RESULT |
| 49 | ERROR_VARIABLE GRPC_GENERATE_ERROR | 49 | ERROR_VARIABLE GRPC_GENERATE_ERROR |
| 50 | ) | 50 | ) |
| 51 | - | 51 | + |
| 52 | # 检查 gRPC 生成结果 | 52 | # 检查 gRPC 生成结果 |
| 53 | if(NOT GRPC_GENERATE_RESULT EQUAL 0) | 53 | if(NOT GRPC_GENERATE_RESULT EQUAL 0) |
| 54 | message(FATAL_ERROR "Failed to generate gRPC files: ${GRPC_GENERATE_ERROR}") | 54 | message(FATAL_ERROR "Failed to generate gRPC files: ${GRPC_GENERATE_ERROR}") |
| @@ -69,3 +69,18 @@ target_link_libraries(mindie_grpc | |||
| 69 | ) | 69 | ) |
| 70 | set_target_properties(mindie_grpc PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/lib") | 70 | set_target_properties(mindie_grpc PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/lib") |
| 71 | install(TARGETS mindie_grpc DESTINATION lib) | 71 | install(TARGETS mindie_grpc DESTINATION lib) |
| 72 | + | ||
| 73 | +set(PY_OUT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../mindie_llm/connector/common) | ||
| 74 | +set(GENERATED_PY ${PY_OUT_DIR}/model_execute_data_pb2.py) | ||
| 75 | +if(NOT EXISTS "${GENERATED_PY}" OR "${PROTO_FILE}" IS_NEWER_THAN "${GENERATED_PY}") | ||
| 76 | + message(STATUS "Generate grpc header file to proto from model_execute_data.proto file...") | ||
| 77 | + execute_process( | ||
| 78 | + COMMAND ${PROTOBUF_PROTOC_EXECUTABLE} -I ${PROTO_PATH} | ||
| 79 | + --experimental_allow_proto3_optional | ||
| 80 | + --python_out=${PY_OUT_DIR} | ||
| 81 | + --proto_path=${CMAKE_CURRENT_SOURCE_DIR} | ||
| 82 | + ${PROTO_FILE} | ||
| 83 | + RESULT_VARIABLE GRPC_GENERATE_RESULT | ||
| 84 | + ERROR_VARIABLE GRPC_GENERATE_ERROR | ||
| 85 | + ) | ||
| 86 | +endif() | ||
| @@ -1,5 +1,5 @@ | |||
| 1 | #!/bin/bash | 1 | #!/bin/bash |
| 2 | cd $CODE_ROOT/src/kernels | 2 | cd $CODE_ROOT/src/kernels |
| 3 | bash build.sh | 3 | bash build.sh |
| 4 | -cp dist/mie_ops*.whl $OUTPUT_DIR | 4 | +pip install dist/mie_ops*.whl --force-reinstall --target $OUTPUT_DIR/lib |
| 5 | cd - | 5 | cd - |
| @@ -1,27 +1,12 @@ | |||
| 1 | #!/bin/bash | 1 | #!/bin/bash |
| 2 | function fn_build_version_info() | 2 | function fn_build_version_info() |
| 3 | { | 3 | { |
| 4 | - if [ ! -f "$CODE_ROOT"/../CI/config/version.ini ]; then | 4 | + version=${MINDIE_LLM_VERSION_OVERRIDE:-1.0.0} |
| 5 | - echo "version.ini is not existed,user default Version-config!" | ||
| 6 | - PACKAGE_NAME='1.0.RC3' | ||
| 7 | - MINDIEVERSION='1.0.RC3' | ||
| 8 | - else | ||
| 9 | - PACKAGE_NAME=$(cat $VERSION_INFO_FILE | grep "PackageName" | cut -d "=" -f 2) | ||
| 10 | - MINDIEVERSION=$(cat $VERSION_INFO_FILE | grep "MindIEVersion" | cut -d " " -f 2) | ||
| 11 | - fi | ||
| 12 | - echo "PackageName: $PACKAGE_NAME" | ||
| 13 | - echo "MindIEVersion: $MINDIEVERSION" | ||
| 14 | - if [[ ! "${PACKAGE_NAME}" =~ ^[1-9]\.[0-9]\. ]]; then | ||
| 15 | - echo "VERSION is invalid" | ||
| 16 | - exit 1 | ||
| 17 | - fi | ||
| 18 | - | ||
| 19 | branch=$(git symbolic-ref -q --short HEAD || git describe --tags --exact-match 2> /dev/null || echo $branch) | 5 | branch=$(git symbolic-ref -q --short HEAD || git describe --tags --exact-match 2> /dev/null || echo $branch) |
| 20 | commit_id=$(git rev-parse HEAD) | 6 | commit_id=$(git rev-parse HEAD) |
| 21 | touch $OUTPUT_DIR/version.info | 7 | touch $OUTPUT_DIR/version.info |
| 22 | cat>$OUTPUT_DIR/version.info<<EOF | 8 | cat>$OUTPUT_DIR/version.info<<EOF |
| 23 | - MindIE-LLM : ${PACKAGE_NAME} | 9 | + MindIE-LLM Version : ${version} |
| 24 | - MindIE-LLM Version : ${MINDIEVERSION} | ||
| 25 | Platform : ${ARCH} | 10 | Platform : ${ARCH} |
| 26 | branch : ${branch} | 11 | branch : ${branch} |
| 27 | commit id : ${commit_id} | 12 | commit id : ${commit_id} |
| @@ -45,7 +45,7 @@ function fn_make_run_package() | |||
| 45 | fi | 45 | fi |
| 46 | 46 | ||
| 47 | ( | 47 | ( |
| 48 | - cd "${src_dir}" | 48 | + cd "${src_dir}" |
| 49 | shopt -s nullglob | 49 | shopt -s nullglob |
| 50 | for pattern in "${patterns[@]}"; do | 50 | for pattern in "${patterns[@]}"; do |
| 51 | for file in ${pattern}; do | 51 | for file in ${pattern}; do |
| @@ -99,38 +99,9 @@ function fn_make_debug_symbols_package() { | |||
| 99 | cd - | 99 | cd - |
| 100 | } | 100 | } |
| 101 | 101 | ||
| 102 | -function fn_make_whl() { | ||
| 103 | - PACKAGE_NAME=$(echo $PACKAGE_NAME | sed -E 's/([0-9]+)\.([0-9]+)\.RC([0-9]+)\.([0-9]+)/\1.\2rc\3.post\4/') | ||
| 104 | - PACKAGE_NAME=$(echo $PACKAGE_NAME | sed -s 's!.T!.alpha!') | ||
| 105 | - echo "MindIELLMWHLVersion $PACKAGE_NAME" | ||
| 106 | - echo "make mindie-llm whl package" | ||
| 107 | - cd $CODE_ROOT | ||
| 108 | - python3 setup.py --setup_cmd="bdist_wheel" --version=${PACKAGE_NAME} | ||
| 109 | - cp dist/*.whl $OUTPUT_DIR | ||
| 110 | - rm -rf dist mindie_llm.egg-info | ||
| 111 | - cd - | ||
| 112 | - if [ "$build_type" = "release" ]; then | ||
| 113 | - cd $CODE_ROOT/tools | ||
| 114 | - cp $OUTPUT_DIR/lib/llm_manager_python.so $CODE_ROOT/tools/llm_manager_python_api_demo | ||
| 115 | - python3 setup.py --setup_cmd="bdist_wheel" --version=${PACKAGE_NAME} | ||
| 116 | - cp dist/*.whl $OUTPUT_DIR | ||
| 117 | - rm -rf dist llm_manager_python_api_demo.egg-info | ||
| 118 | - cd - | ||
| 119 | - fi | ||
| 120 | - echo "start to build mies tokenizer wheel" | ||
| 121 | - cd "$CODE_ROOT/src/server/tokenizer" | ||
| 122 | - python3 setup_tokenizer.py bdist_wheel | ||
| 123 | - cp -v dist/mies_tokenizer-*.whl $OUTPUT_DIR | ||
| 124 | - rm -rf *.egg-info dist | ||
| 125 | - cd - | ||
| 126 | -} | ||
| 127 | - | ||
| 128 | function fn_build_for_ci() | 102 | function fn_build_for_ci() |
| 129 | { | 103 | { |
| 130 | cd $OUTPUT_DIR | 104 | cd $OUTPUT_DIR |
| 131 | mkdir -p include | 105 | mkdir -p include |
| 132 | - if ! [ "$build_type" = "release" ]; then | ||
| 133 | - cp -r $CODE_ROOT/mindie_llm . | ||
| 134 | - fi | ||
| 135 | cp -r $CODE_ROOT/src/include/* ./include/ | 106 | cp -r $CODE_ROOT/src/include/* ./include/ |
| 136 | -} | 107 | +} |
| @@ -15,55 +15,61 @@ | |||
| 15 | 15 | ||
| 16 | path="${BASH_SOURCE[0]}" | 16 | path="${BASH_SOURCE[0]}" |
| 17 | 17 | ||
| 18 | -if [[ -f "$path" ]] && [[ "$path" =~ set_env.sh ]];then | 18 | +mindie_llm_path=$(cd $(dirname $path); pwd) |
| 19 | - mindie_llm_path=$(cd $(dirname $path); pwd) | 19 | +chmod u+w "${mindie_llm_path}" |
| 20 | - chmod u+w "${mindie_llm_path}" | 20 | +rm -rf /dev/shm/* #对于共享内存小的测试场景,每次启动前都清一下 |
| 21 | - rm -rf /dev/shm/* #对于共享内存小的测试场景,每次启动前都清一下 | 21 | +export MINDIE_LLM_HOME_PATH="${mindie_llm_path}" |
| 22 | - export MINDIE_LLM_HOME_PATH="${mindie_llm_path}" | ||
| 23 | 22 | ||
| 24 | - export MINDIE_LLM_RECOMPUTE_THRESHOLD=0.5 | 23 | +export MINDIE_LLM_RECOMPUTE_THRESHOLD=0.5 |
| 25 | - export PYTORCH_INSTALL_PATH="$(python3 -c 'import torch, os; print(os.path.dirname(os.path.abspath(torch.__file__)))')" | 24 | +export PYTORCH_INSTALL_PATH="$(python3 -c 'import torch, os; print(os.path.dirname(os.path.abspath(torch.__file__)))')" |
| 26 | - if [ -n "$PYTORCH_INSTALL_PATH" ]; then | 25 | +if [ -n "$PYTORCH_INSTALL_PATH" ]; then |
| 27 | - export LD_LIBRARY_PATH="$PYTORCH_INSTALL_PATH/lib:$PYTORCH_INSTALL_PATH/../torch.libs:$LD_LIBRARY_PATH" | 26 | + export LD_LIBRARY_PATH="$PYTORCH_INSTALL_PATH/lib:$PYTORCH_INSTALL_PATH/../torch.libs:$LD_LIBRARY_PATH" |
| 28 | - fi | ||
| 29 | - export LD_LIBRARY_PATH=$(find "$MINDIE_LLM_HOME_PATH/lib" -type d | tr '\n' ':' | sed 's/:$//'):${LD_LIBRARY_PATH} | ||
| 30 | - export PYTHONPATH=$MINDIE_LLM_HOME_PATH:$PYTHONPATH | ||
| 31 | - export PYTHONPATH=$MINDIE_LLM_HOME_PATH/lib:$PYTHONPATH | ||
| 32 | - | ||
| 33 | - export MINDIE_LOG_LEVEL=INFO | ||
| 34 | - export MINDIE_LOG_TO_STDOUT=0 | ||
| 35 | - export MINDIE_LOG_TO_FILE=1 | ||
| 36 | - export GRPC_POLL_STRATEGY=poll | ||
| 37 | - if [[ -z "$1" ]]; then | ||
| 38 | - MINDIE_LLM_BACKEND=("atb" "pt" "ms") | ||
| 39 | - else | ||
| 40 | - if [[ "$1" == "--backend="* ]]; then | ||
| 41 | - MINDIE_LLM_BACKEND="${1#*=}" | ||
| 42 | - else | ||
| 43 | - echo "Usage: source set_env.sh --backend=<backend>" | ||
| 44 | - fi | ||
| 45 | - fi | ||
| 46 | - | ||
| 47 | - for backend_opt in "${MINDIE_LLM_BACKEND[@]}"; do | ||
| 48 | - case "$backend_opt" in | ||
| 49 | - atb) | ||
| 50 | - ATB_SET_ENV_PATH=$MINDIE_LLM_HOME_PATH/../examples/atb_models/output/atb_models/set_env.sh | ||
| 51 | - if [ ! -f "$ATB_SET_ENV_PATH" ]; then | ||
| 52 | - ATB_SET_ENV_PATH=ATBMODELSETENV | ||
| 53 | - fi | ||
| 54 | - if [ -f "$ATB_SET_ENV_PATH" ]; then | ||
| 55 | - source $ATB_SET_ENV_PATH | ||
| 56 | - fi | ||
| 57 | - ;; | ||
| 58 | - pt) | ||
| 59 | - ;; | ||
| 60 | - ms) | ||
| 61 | - ;; | ||
| 62 | - *) | ||
| 63 | - echo "Inner Error: unknown option'$backend_opt'" | ||
| 64 | - ;; | ||
| 65 | - esac | ||
| 66 | - done | ||
| 67 | -else | ||
| 68 | - echo "There is no 'set_env.sh' to import" | ||
| 69 | fi | 27 | fi |
| 28 | +export LD_LIBRARY_PATH=$(find "$MINDIE_LLM_HOME_PATH/lib" -type d | tr '\n' ':' | sed 's/:$//'):${LD_LIBRARY_PATH} | ||
| 29 | +export PYTHONPATH=$MINDIE_LLM_HOME_PATH:$PYTHONPATH | ||
| 30 | +export PYTHONPATH=$MINDIE_LLM_HOME_PATH/lib:$PYTHONPATH | ||
| 31 | + | ||
| 32 | +export MINDIE_LOG_LEVEL=INFO | ||
| 33 | +export MINDIE_LOG_TO_STDOUT=0 | ||
| 34 | +export MINDIE_LOG_TO_FILE=1 | ||
| 35 | +export GRPC_POLL_STRATEGY=poll | ||
| 36 | + | ||
| 37 | +export ATB_OPERATION_EXECUTE_ASYNC=1 | ||
| 38 | +export TASK_QUEUE_ENABLE=1 | ||
| 39 | +export HCCL_BUFFSIZE=120 | ||
| 40 | + | ||
| 41 | +# Plog日志 | ||
| 42 | +export ASCEND_SLOG_PRINT_TO_STDOUT=0 | ||
| 43 | +export ASCEND_GLOBAL_LOG_LEVEL=3 | ||
| 44 | +export ASCEND_GLOBAL_EVENT_ENABLE=0 | ||
| 45 | + | ||
| 46 | +if [[ -z "$1" ]]; then | ||
| 47 | + MINDIE_LLM_BACKEND=("atb" "pt" "ms") | ||
| 48 | +else | ||
| 49 | + if [[ "$1" == "--backend="* ]]; then | ||
| 50 | + MINDIE_LLM_BACKEND="${1#*=}" | ||
| 51 | + else | ||
| 52 | + echo "Usage: source set_env.sh --backend=<backend>" | ||
| 53 | + fi | ||
| 54 | +fi | ||
| 55 | + | ||
| 56 | +for backend_opt in "${MINDIE_LLM_BACKEND[@]}"; do | ||
| 57 | + case "$backend_opt" in | ||
| 58 | + atb) | ||
| 59 | + ATB_SET_ENV_PATH=$MINDIE_LLM_HOME_PATH/../examples/atb_models/output/atb_models/set_env.sh | ||
| 60 | + if [ ! -f "$ATB_SET_ENV_PATH" ]; then | ||
| 61 | + ATB_SET_ENV_PATH=ATBMODELSETENV | ||
| 62 | + fi | ||
| 63 | + if [ -f "$ATB_SET_ENV_PATH" ]; then | ||
| 64 | + source $ATB_SET_ENV_PATH | ||
| 65 | + fi | ||
| 66 | + ;; | ||
| 67 | + pt) | ||
| 68 | + ;; | ||
| 69 | + ms) | ||
| 70 | + ;; | ||
| 71 | + *) | ||
| 72 | + echo "Inner Error: unknown option'$backend_opt'" | ||
| 73 | + ;; | ||
| 74 | + esac | ||
| 75 | +done | ||
| @@ -1,6 +1,6 @@ | |||
| 1 | #!/usr/bin/env python | 1 | #!/usr/bin/env python |
| 2 | # coding=utf-8 | 2 | # coding=utf-8 |
| 3 | -# Copyright (c) Huawei Technologies Co., Ltd. 2024-2025. All rights reserved. | 3 | +# Copyright (c) Huawei Technologies Co., Ltd. 2026-2026. All rights reserved. |
| 4 | # MindIE is licensed under Mulan PSL v2. | 4 | # MindIE is licensed under Mulan PSL v2. |
| 5 | # You can use this software according to the terms and conditions of the Mulan PSL v2. | 5 | # You can use this software according to the terms and conditions of the Mulan PSL v2. |
| 6 | # You may obtain a copy of Mulan PSL v2 at: | 6 | # You may obtain a copy of Mulan PSL v2 at: |
| @@ -10,69 +10,127 @@ | |||
| 10 | # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. | 10 | # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. |
| 11 | # See the Mulan PSL v2 for more details. | 11 | # See the Mulan PSL v2 for more details. |
| 12 | 12 | ||
| 13 | -import argparse | ||
| 14 | import os | 13 | import os |
| 15 | -import sys | ||
| 16 | import subprocess | 14 | import subprocess |
| 17 | -from setuptools import setup | 15 | +import logging |
| 18 | -from setuptools.command.build_py import build_py | 16 | +import shutil |
| 17 | +from pathlib import Path | ||
| 18 | +from setuptools.command.build_py import build_py as _build_py | ||
| 19 | +from setuptools import setup, find_packages | ||
| 20 | +from wheel.bdist_wheel import bdist_wheel as _bdist_wheel | ||
| 21 | +import torch | ||
| 19 | 22 | ||
| 20 | -os.environ["SOURCE_DATE_EPOCH"] = "0" | 23 | +logging.basicConfig(level=logging.INFO) |
| 21 | - | 24 | +# SOURCE_DATE_EPOCH is used to make builds deterministic (reproducible). |
| 22 | -parser = argparse.ArgumentParser(description="MindIE LLM Setup Parameters") | 25 | +os.environ["SOURCE_DATE_EPOCH"] = "315532800" # 315532800 means 1980-01-01 00:00:00 UTC |
| 23 | -parser.add_argument("--setup_cmd", type=str, default="bdist_wheel") | ||
| 24 | -parser.add_argument("--version", type=str, default="1.0.RC3") | ||
| 25 | - | ||
| 26 | -args = parser.parse_args() | ||
| 27 | -sys.argv = [sys.argv[0], args.setup_cmd] | ||
| 28 | -mindie_llm_version = args.version | ||
| 29 | 26 | ||
| 30 | 27 | ||
| 31 | -# 定义.proto文件路径(假设在项目根目录的protos/文件夹下) | 28 | +def get_version() -> str: |
| 32 | -class BuildPyCommand(build_py): | 29 | + """ |
| 30 | + Return version string. | ||
| 31 | + | ||
| 32 | + Priority: | ||
| 33 | + 1. Environment variable MINDIE_LLM_VERSION_OVERRIDE | ||
| 34 | + 2. Default version | ||
| 35 | + """ | ||
| 36 | + version = os.getenv("MINDIE_LLM_VERSION_OVERRIDE", "1.0.0") | ||
| 37 | + logging.info(f"Use mindie llm version: {version}") | ||
| 38 | + return version | ||
| 39 | + | ||
| 40 | + | ||
| 41 | +def use_cxx11_abi() -> str: | ||
| 42 | + """ | ||
| 43 | + Return whether to use CXX11 ABI as a string ("0" or "1"). | ||
| 44 | + """ | ||
| 45 | + try: | ||
| 46 | + abi = torch.compiled_with_cxx11_abi() | ||
| 47 | + abi_str = str(int(bool(abi))) | ||
| 48 | + logging.info(f"Detect ABI from torch, set USE_CXX11_ABI to {abi_str}") | ||
| 49 | + return abi_str | ||
| 50 | + except Exception as e: | ||
| 51 | + logging.warning("Detect ABI from torch failed.") | ||
| 52 | + raise RuntimeError("Detect ABI from torch failed.") from e | ||
| 53 | + | ||
| 54 | + | ||
| 55 | +class CustomBuildPy(_build_py): | ||
| 33 | def run(self): | 56 | def run(self): |
| 34 | - # 获取当前环境变量 | 57 | + logging.info(">>> Running build.sh to compile shared libraries...") |
| 35 | - env = os.environ.copy() | 58 | + |
| 36 | - # 添加protoc所需的动态库路径到LD_LIBRARY_PATH | 59 | + project_root = Path(__file__).resolve().parent |
| 37 | - protobuf_lib_path = os.path.abspath("./third_party/output/protobuf/lib") | 60 | + build_dir = project_root |
| 38 | - absl_lib_path = os.path.abspath("./third_party/output/abseil-cpp/lib") | 61 | + subprocess.run( |
| 39 | - if 'LD_LIBRARY_PATH' in env: | 62 | + ["/bin/bash", "build.sh", f"--use_cxx11_abi={use_cxx11_abi()}"], |
| 40 | - env['LD_LIBRARY_PATH'] = f"{protobuf_lib_path}:{absl_lib_path}:{env['LD_LIBRARY_PATH']}" | 63 | + cwd=str(build_dir), |
| 41 | - else: | 64 | + check=True, |
| 42 | - env['LD_LIBRARY_PATH'] = f"{protobuf_lib_path}:{absl_lib_path}" | 65 | + shell=False |
| 43 | - subprocess.run([ | 66 | + ) |
| 44 | - "./third_party/output/protobuf/bin/protoc", # 使用相对路径调用protoc | 67 | + |
| 45 | - "--experimental_allow_proto3_optional", | 68 | + build_pkg = Path(self.build_lib) / "mindie_llm" |
| 46 | - "--python_out=./mindie_llm/connector/common/", | 69 | + |
| 47 | - "--proto_path=./proto/", | 70 | + shutil.copytree("output", build_pkg, dirs_exist_ok=True) |
| 48 | - "model_execute_data.proto" | 71 | + shutil.copytree("src/server/scripts", build_pkg / "scripts", |
| 49 | - ], env=env, check=True) | 72 | + dirs_exist_ok=True, ignore=shutil.ignore_patterns("set_env.sh")) |
| 73 | + self.copy_third_party() | ||
| 50 | 74 | ||
| 51 | - # 继续执行默认的build_py逻辑 | ||
| 52 | super().run() | 75 | super().run() |
| 53 | 76 | ||
| 77 | + def copy_third_party(self): | ||
| 78 | + project_root = Path(__file__).resolve().parent | ||
| 79 | + build_pkg = Path(self.build_lib) / "mindie_llm" | ||
| 80 | + lib_dir = build_pkg / "lib" | ||
| 81 | + | ||
| 82 | + lib_mappings = { | ||
| 83 | + "abseil-cpp": lib_dir, | ||
| 84 | + "boost": lib_dir, | ||
| 85 | + "cares": lib_dir, | ||
| 86 | + "grpc": lib_dir / "grpc", | ||
| 87 | + "libboundscheck": lib_dir, | ||
| 88 | + "openssl": lib_dir, | ||
| 89 | + "prometheus-cpp": lib_dir, | ||
| 90 | + "protobuf": lib_dir, | ||
| 91 | + "re2": lib_dir, | ||
| 92 | + "zlib": lib_dir, | ||
| 93 | + } | ||
| 94 | + | ||
| 95 | + for lib_name, target_dir in lib_mappings.items(): | ||
| 96 | + src_dir = project_root / "third_party" / "output" / lib_name / "lib" | ||
| 97 | + if not src_dir.exists(): | ||
| 98 | + logging.warning(f"No such directory when copy it, skip: {src_dir}") | ||
| 99 | + return | ||
| 100 | + | ||
| 101 | + target_dir.mkdir(parents=True, exist_ok=True) | ||
| 102 | + for item in src_dir.iterdir(): | ||
| 103 | + if not item.is_file(): | ||
| 104 | + continue | ||
| 105 | + dst_path = target_dir / item.name | ||
| 106 | + shutil.copy2(item, dst_path) | ||
| 107 | + | ||
| 108 | + | ||
| 109 | +class BDistWheel(_bdist_wheel): | ||
| 110 | + def finalize_options(self): | ||
| 111 | + super().finalize_options() | ||
| 112 | + self.root_is_pure = False | ||
| 113 | + | ||
| 54 | 114 | ||
| 55 | setup( | 115 | setup( |
| 56 | name="mindie_llm", | 116 | name="mindie_llm", |
| 57 | - version=mindie_llm_version, | 117 | + version=get_version(), |
| 58 | author="", | 118 | author="", |
| 59 | author_email="", | 119 | author_email="", |
| 60 | description="MindIE LLM Project", | 120 | description="MindIE LLM Project", |
| 61 | long_description="", | 121 | long_description="", |
| 62 | - package_dir={'mindie_llm': 'mindie_llm'}, | ||
| 63 | install_requires=[], | 122 | install_requires=[], |
| 64 | - package_data={ | ||
| 65 | - '': ['*.xlsx', '*.h5', '*.csv', '*.so', '*.avsc', '*.xml', '*.pkl', '*.sql', '*.ini'] | ||
| 66 | - }, | ||
| 67 | zip_safe=False, | 123 | zip_safe=False, |
| 68 | python_requires=">=3.10", | 124 | python_requires=">=3.10", |
| 69 | - cmdclass={ | 125 | + packages=find_packages(), |
| 70 | - "build_py": BuildPyCommand, | ||
| 71 | - }, | ||
| 72 | - include_package_data=True, | ||
| 73 | entry_points={ | 126 | entry_points={ |
| 74 | "console_scripts": [ | 127 | "console_scripts": [ |
| 75 | - 'mindie_llm_backend = mindie_llm.connector.main:main' | 128 | + "mindie_llm_server = mindie_llm.server.main:main", |
| 129 | + "mindie_llm_backend = mindie_llm.connector.main:main" | ||
| 76 | ] | 130 | ] |
| 131 | + }, | ||
| 132 | + cmdclass={ | ||
| 133 | + "build_py": CustomBuildPy, | ||
| 134 | + "bdist_wheel": BDistWheel | ||
| 77 | } | 135 | } |
| 78 | ) | 136 | ) |
| @@ -10,7 +10,7 @@ include_directories( | |||
| 10 | ${CMAKE_CURRENT_SOURCE_DIR}/../../utils/include/mindie_llm | 10 | ${CMAKE_CURRENT_SOURCE_DIR}/../../utils/include/mindie_llm |
| 11 | ${THIRD_PARTY_OUTPUT_DIR}/nlohmann/include | 11 | ${THIRD_PARTY_OUTPUT_DIR}/nlohmann/include |
| 12 | ) | 12 | ) |
| 13 | - | 13 | + |
| 14 | execute_process( | 14 | execute_process( |
| 15 | COMMAND bash -c "python3 -m pybind11 --cmakedir" | 15 | COMMAND bash -c "python3 -m pybind11 --cmakedir" |
| 16 | OUTPUT_VARIABLE command_output | 16 | OUTPUT_VARIABLE command_output |
| @@ -70,3 +70,10 @@ add_subdirectory(daemon) | |||
| 70 | 70 | ||
| 71 | # Add security compile options | 71 | # Add security compile options |
| 72 | include(options.cmake) | 72 | include(options.cmake) |
| 73 | + | ||
| 74 | +# Install config file | ||
| 75 | +install( | ||
| 76 | + FILES ${CMAKE_CURRENT_SOURCE_DIR}/conf/config.json | ||
| 77 | + DESTINATION conf | ||
| 78 | + PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ | ||
| 79 | +) | ||
| @@ -23,12 +23,12 @@ if(NOT EXISTS "${DST_FILE_ONE}" OR "${PROTO_FILE}" IS_NEWER_THAN "${DST_FILE_ONE | |||
| 23 | RESULT_VARIABLE GRPC_GENERATE_RESULT | 23 | RESULT_VARIABLE GRPC_GENERATE_RESULT |
| 24 | ERROR_VARIABLE GRPC_GENERATE_ERROR | 24 | ERROR_VARIABLE GRPC_GENERATE_ERROR |
| 25 | ) | 25 | ) |
| 26 | - | 26 | + |
| 27 | # 检查 gRPC 生成结果 | 27 | # 检查 gRPC 生成结果 |
| 28 | if(NOT GRPC_GENERATE_RESULT EQUAL 0) | 28 | if(NOT GRPC_GENERATE_RESULT EQUAL 0) |
| 29 | message(FATAL_ERROR "Failed to generate gRPC files: ${GRPC_GENERATE_ERROR}") | 29 | message(FATAL_ERROR "Failed to generate gRPC files: ${GRPC_GENERATE_ERROR}") |
| 30 | endif() | 30 | endif() |
| 31 | - | 31 | + |
| 32 | # 生成 C++ 文件 | 32 | # 生成 C++ 文件 |
| 33 | execute_process( | 33 | execute_process( |
| 34 | COMMAND ${PROTOBUF_PROTOC_EXECUTABLE} -I ${DMI_PROTO_DIR} --cpp_out=${PROTO_INSTALL_DIR} | 34 | COMMAND ${PROTOBUF_PROTOC_EXECUTABLE} -I ${DMI_PROTO_DIR} --cpp_out=${PROTO_INSTALL_DIR} |
| @@ -36,7 +36,7 @@ if(NOT EXISTS "${DST_FILE_ONE}" OR "${PROTO_FILE}" IS_NEWER_THAN "${DST_FILE_ONE | |||
| 36 | RESULT_VARIABLE CPP_GENERATE_RESULT | 36 | RESULT_VARIABLE CPP_GENERATE_RESULT |
| 37 | ERROR_VARIABLE CPP_GENERATE_ERROR | 37 | ERROR_VARIABLE CPP_GENERATE_ERROR |
| 38 | ) | 38 | ) |
| 39 | - | 39 | + |
| 40 | # 检查 C++ 生成结果 | 40 | # 检查 C++ 生成结果 |
| 41 | if(NOT CPP_GENERATE_RESULT EQUAL 0) | 41 | if(NOT CPP_GENERATE_RESULT EQUAL 0) |
| 42 | message(FATAL_ERROR "Failed to generate C++ files: ${CPP_GENERATE_ERROR}") | 42 | message(FATAL_ERROR "Failed to generate C++ files: ${CPP_GENERATE_ERROR}") |
| @@ -64,11 +64,11 @@ include_directories( | |||
| 64 | ${CMAKE_CURRENT_SOURCE_DIR}/health_checker | 64 | ${CMAKE_CURRENT_SOURCE_DIR}/health_checker |
| 65 | ) | 65 | ) |
| 66 | 66 | ||
| 67 | -if(DEFINED ENV{MINDIE_VERSION}) | 67 | +if(DEFINED ENV{MINDIE_LLM_VERSION_OVERRIDE}) |
| 68 | - set(MINDIE_VERSION $ENV{MINDIE_VERSION}) | 68 | + set(MINDIE_VERSION $ENV{MINDIE_LLM_VERSION_OVERRIDE}) |
| 69 | - add_definitions(-DMINDIE_VERSION="${MINDIE_VERSION}") | 69 | + add_definitions(-DMINDIE_VERSION="${MINDIE_LLM_VERSION_OVERRIDE}") |
| 70 | else() | 70 | else() |
| 71 | - message(WARNING "Environment MINDIE_VERSION is not set") | 71 | + message(WARNING "Environment MINDIE_LLM_VERSION_OVERRIDE is not set") |
| 72 | endif() | 72 | endif() |
| 73 | 73 | ||
| 74 | # 编译endpoint的proto文件 | 74 | # 编译endpoint的proto文件 |
| @@ -964,7 +964,7 @@ bool TokenizerProcessPool::InitSubProcessMemory(const std::shared_ptr<ShareToken | |||
| 964 | bool TokenizerProcessPool::InitSubProcessTokenizer(std::shared_ptr<InferTokenizer> &tokenizer) | 964 | bool TokenizerProcessPool::InitSubProcessTokenizer(std::shared_ptr<InferTokenizer> &tokenizer) |
| 965 | { | 965 | { |
| 966 | try { | 966 | try { |
| 967 | - pybind11::module module = pybind11::module_::import("mies_tokenizer"); | 967 | + pybind11::module module = pybind11::module_::import("mindie_llm.tokenizer"); |
| 968 | if (!pybind11::hasattr(module, "IbisTokenizer")) { | 968 | if (!pybind11::hasattr(module, "IbisTokenizer")) { |
| 969 | return false; | 969 | return false; |
| 970 | } | 970 | } |
| @@ -1,24 +0,0 @@ | |||
| 1 | -#!/usr/bin/env python | ||
| 2 | -# coding=utf-8 | ||
| 3 | -# Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved. | ||
| 4 | -# MindIE is licensed under Mulan PSL v2. | ||
| 5 | -# You can use this software according to the terms and conditions of the Mulan PSL v2. | ||
| 6 | -# You may obtain a copy of Mulan PSL v2 at: | ||
| 7 | -# http://license.coscl.org.cn/MulanPSL2 | ||
| 8 | -# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, | ||
| 9 | -# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, | ||
| 10 | -# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. | ||
| 11 | -# See the Mulan PSL v2 for more details. | ||
| 12 | - | ||
| 13 | -import os | ||
| 14 | -from setuptools import setup | ||
| 15 | - | ||
| 16 | - | ||
| 17 | -os.environ['SOURCE_DATE_EPOCH'] = '0' | ||
| 18 | -setup( | ||
| 19 | - name='mies_tokenizer', | ||
| 20 | - version='0.0.1', | ||
| 21 | - description='ibis tokenizer', | ||
| 22 | - packages=['mies_tokenizer'], | ||
| 23 | - python_requires=">=3.10", | ||
| 24 | -) | ||
| @@ -149,10 +149,14 @@ namespace SimpleLLMInference { | |||
| 149 | std::string py = GetCwd() + "/tokenizer.py"; | 149 | std::string py = GetCwd() + "/tokenizer.py"; |
| 150 | ::unlink(py.c_str()); | 150 | ::unlink(py.c_str()); |
| 151 | } | 151 | } |
| 152 | - std::string pkgDir = GetCwd() + "/mies_tokenizer"; | 152 | + std::string pkgDir = GetCwd() + "/mindie_llm/tokenizer"; |
| 153 | std::string initPy = pkgDir + "/__init__.py"; | 153 | std::string initPy = pkgDir + "/__init__.py"; |
| 154 | ::unlink(initPy.c_str()); | 154 | ::unlink(initPy.c_str()); |
| 155 | ::rmdir(pkgDir.c_str()); | 155 | ::rmdir(pkgDir.c_str()); |
| 156 | + pkgDir = GetCwd() + "/mindie_llm"; | ||
| 157 | + initPy = pkgDir + "/__init__.py"; | ||
| 158 | + ::unlink(initPy.c_str()); | ||
| 159 | + ::rmdir(pkgDir.c_str()); | ||
| 156 | } | 160 | } |
| 157 | 161 | ||
| 158 | static void KillChildrenAndWait() | 162 | static void KillChildrenAndWait() |
| @@ -372,7 +376,10 @@ class IbisTokenizerDeleteRaise(IbisTokenizer): | |||
| 372 | 376 | ||
| 373 | // b) mies_tokenizer(子进程) | 377 | // b) mies_tokenizer(子进程) |
| 374 | { | 378 | { |
| 375 | - std::string pkgDir = GetCwd() + "/mies_tokenizer"; | 379 | + std::string pkgDir = GetCwd() + "/mindie_llm"; |
| 380 | + ::mkdir(pkgDir.c_str(), 0755); | ||
| 381 | + std::ofstream(pkgDir + "/__init__.py").close(); | ||
| 382 | + pkgDir = pkgDir + "/tokenizer"; | ||
| 376 | ::mkdir(pkgDir.c_str(), 0755); | 383 | ::mkdir(pkgDir.c_str(), 0755); |
| 377 | std::ofstream ofs(pkgDir + "/__init__.py", std::ios::out | std::ios::trunc); | 384 | std::ofstream ofs(pkgDir + "/__init__.py", std::ios::out | std::ios::trunc); |
| 378 | ofs << R"( | 385 | ofs << R"( |
| @@ -795,7 +802,7 @@ class IbisTokenizer: | |||
| 795 | { | 802 | { |
| 796 | auto &pool = TokenizerProcessPool::GetInstance(); | 803 | auto &pool = TokenizerProcessPool::GetInstance(); |
| 797 | 804 | ||
| 798 | - auto mies = pybind11::module_::import("mies_tokenizer"); | 805 | + auto mies = pybind11::module_::import("mindie_llm.tokenizer"); |
| 799 | ASSERT_TRUE(pybind11::hasattr(mies, "IbisTokenizer")); | 806 | ASSERT_TRUE(pybind11::hasattr(mies, "IbisTokenizer")); |
| 800 | 807 | ||
| 801 | std::shared_ptr<InferTokenizer> tk; | 808 | std::shared_ptr<InferTokenizer> tk; |
| @@ -807,7 +814,7 @@ class IbisTokenizer: | |||
| 807 | TEST_F(InferenceTokenizerTest, InitSubProcessTokenizer_NoClass_ReturnsFalse) | 814 | TEST_F(InferenceTokenizerTest, InitSubProcessTokenizer_NoClass_ReturnsFalse) |
| 808 | { | 815 | { |
| 809 | auto &pool = TokenizerProcessPool::GetInstance(); | 816 | auto &pool = TokenizerProcessPool::GetInstance(); |
| 810 | - auto mies = pybind11::module_::import("mies_tokenizer"); | 817 | + auto mies = pybind11::module_::import("mindie_llm.tokenizer"); |
| 811 | 818 | ||
| 812 | bool had = pybind11::hasattr(mies, "IbisTokenizer"); | 819 | bool had = pybind11::hasattr(mies, "IbisTokenizer"); |
| 813 | pybind11::object backup; | 820 | pybind11::object backup; |
| @@ -825,7 +832,7 @@ class IbisTokenizer: | |||
| 825 | TEST_F(InferenceTokenizerTest, InitSubProcessTokenizer_MissingMethods_ReturnsFalse) | 832 | TEST_F(InferenceTokenizerTest, InitSubProcessTokenizer_MissingMethods_ReturnsFalse) |
| 826 | { | 833 | { |
| 827 | auto &pool = TokenizerProcessPool::GetInstance(); | 834 | auto &pool = TokenizerProcessPool::GetInstance(); |
| 828 | - auto mies = pybind11::module_::import("mies_tokenizer"); | 835 | + auto mies = pybind11::module_::import("mindie_llm.tokenizer"); |
| 829 | 836 | ||
| 830 | ASSERT_TRUE(pybind11::hasattr(mies, "IbisTokenizer")); | 837 | ASSERT_TRUE(pybind11::hasattr(mies, "IbisTokenizer")); |
| 831 | pybind11::object backup = mies.attr("IbisTokenizer"); | 838 | pybind11::object backup = mies.attr("IbisTokenizer"); |
| @@ -847,7 +854,7 @@ class IbisTokenizer: | |||
| 847 | TEST_F(InferenceTokenizerTest, InitSubProcessTokenizer_CtorRaises_ReturnsFalse) | 854 | TEST_F(InferenceTokenizerTest, InitSubProcessTokenizer_CtorRaises_ReturnsFalse) |
| 848 | { | 855 | { |
| 849 | auto &pool = TokenizerProcessPool::GetInstance(); | 856 | auto &pool = TokenizerProcessPool::GetInstance(); |
| 850 | - auto mies = pybind11::module_::import("mies_tokenizer"); | 857 | + auto mies = pybind11::module_::import("mindie_llm.tokenizer"); |
| 851 | 858 | ||
| 852 | ASSERT_TRUE(pybind11::hasattr(mies, "IbisTokenizer")); | 859 | ASSERT_TRUE(pybind11::hasattr(mies, "IbisTokenizer")); |
| 853 | pybind11::object backup = mies.attr("IbisTokenizer"); | 860 | pybind11::object backup = mies.attr("IbisTokenizer"); |
| @@ -873,7 +880,7 @@ class IbisTokenizer: | |||
| 873 | MOCKER_CPP(&ConfigManager::GetConfigJsonStr, std::string (*)()) | 880 | MOCKER_CPP(&ConfigManager::GetConfigJsonStr, std::string (*)()) |
| 874 | .stubs().will(MOCKCPP_NS::invoke(&Ret_MissingKeysConfigJson_Value)); | 881 | .stubs().will(MOCKCPP_NS::invoke(&Ret_MissingKeysConfigJson_Value)); |
| 875 | 882 | ||
| 876 | - auto mies = pybind11::module_::import("mies_tokenizer"); | 883 | + auto mies = pybind11::module_::import("mindie_llm.tokenizer"); |
| 877 | ASSERT_TRUE(pybind11::hasattr(mies, "IbisTokenizer")); | 884 | ASSERT_TRUE(pybind11::hasattr(mies, "IbisTokenizer")); |
| 878 | 885 | ||
| 879 | std::shared_ptr<InferTokenizer> tk; | 886 | std::shared_ptr<InferTokenizer> tk; |
| @@ -893,7 +900,7 @@ class IbisTokenizer: | |||
| 893 | MOCKER_CPP(&ConfigManager::GetConfigJsonStr, std::string (*)()) | 900 | MOCKER_CPP(&ConfigManager::GetConfigJsonStr, std::string (*)()) |
| 894 | .stubs().will(MOCKCPP_NS::invoke(&Ret_InvalidConfigJson_Value)); | 901 | .stubs().will(MOCKCPP_NS::invoke(&Ret_InvalidConfigJson_Value)); |
| 895 | 902 | ||
| 896 | - auto mies = pybind11::module_::import("mies_tokenizer"); | 903 | + auto mies = pybind11::module_::import("mindie_llm.tokenizer"); |
| 897 | ASSERT_TRUE(pybind11::hasattr(mies, "IbisTokenizer")); | 904 | ASSERT_TRUE(pybind11::hasattr(mies, "IbisTokenizer")); |
| 898 | 905 | ||
| 899 | std::shared_ptr<InferTokenizer> tk; | 906 | std::shared_ptr<InferTokenizer> tk; |
| @@ -0,0 +1,85 @@ | |||
| 1 | +import os | ||
| 2 | +import sys | ||
| 3 | +import unittest | ||
| 4 | +from unittest import mock | ||
| 5 | +from pathlib import Path | ||
| 6 | + | ||
| 7 | +from mindie_llm.server.main import main | ||
| 8 | + | ||
| 9 | + | ||
| 10 | +class TestServerMain(unittest.TestCase): | ||
| 11 | + | ||
| 12 | + | ||
| 13 | + | ||
| 14 | + | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + def test_main_success_no_args( | ||
| 18 | + self, | ||
| 19 | + mock_environ, | ||
| 20 | + mock_is_file, | ||
| 21 | + mock_is_dir, | ||
| 22 | + mock_execve, | ||
| 23 | + mock_get_pkg_dir, | ||
| 24 | + ): | ||
| 25 | + # daemon + config.json exist | ||
| 26 | + mock_is_file.side_effect = [True, True] | ||
| 27 | + mock_is_dir.return_value = True | ||
| 28 | + | ||
| 29 | + # Fake package locations | ||
| 30 | + fake_site = Path("/fake/site-packages") | ||
| 31 | + mock_get_pkg_dir.side_effect = [ | ||
| 32 | + fake_site / "torch", # torch | ||
| 33 | + fake_site / "atb_llm", # atb_llm | ||
| 34 | + ] | ||
| 35 | + | ||
| 36 | + mock_environ.update({ | ||
| 37 | + "LD_LIBRARY_PATH": "/old/ld", | ||
| 38 | + "PYTHONPATH": "/old/python", | ||
| 39 | + }) | ||
| 40 | + | ||
| 41 | + with mock.patch.object(sys, "argv", ["mindie_llm_server"]): | ||
| 42 | + main() | ||
| 43 | + | ||
| 44 | + mock_execve.assert_called_once() | ||
| 45 | + exec_path, exec_argv, exec_env = mock_execve.call_args[0] | ||
| 46 | + | ||
| 47 | + pkg_root = Path(__file__).resolve().parents[4] / "mindie_llm" | ||
| 48 | + daemon_path = pkg_root / "bin" / "mindieservice_daemon" | ||
| 49 | + lib_dir = pkg_root / "lib" | ||
| 50 | + | ||
| 51 | + self.assertEqual(exec_path, str(daemon_path)) | ||
| 52 | + self.assertEqual(exec_argv, [str(daemon_path)]) | ||
| 53 | + | ||
| 54 | + # env checks | ||
| 55 | + self.assertEqual(exec_env["MIES_INSTALL_PATH"], str(pkg_root)) | ||
| 56 | + self.assertIn(str(lib_dir), exec_env["LD_LIBRARY_PATH"]) | ||
| 57 | + self.assertIn("grpc", exec_env["LD_LIBRARY_PATH"]) | ||
| 58 | + self.assertIn(str(lib_dir), exec_env["PYTHONPATH"]) | ||
| 59 | + | ||
| 60 | + | ||
| 61 | + | ||
| 62 | + def test_daemon_missing_raises(self, mock_is_file, mock_get_pkg_dir): | ||
| 63 | + mock_is_file.return_value = False | ||
| 64 | + | ||
| 65 | + with self.assertRaises(RuntimeError) as ctx: | ||
| 66 | + main() | ||
| 67 | + | ||
| 68 | + self.assertIn("mindieservice_daemon not found", str(ctx.exception)) | ||
| 69 | + | ||
| 70 | + | ||
| 71 | + | ||
| 72 | + | ||
| 73 | + def test_lib_dir_missing_raises( | ||
| 74 | + self, | ||
| 75 | + mock_is_dir, | ||
| 76 | + mock_is_file, | ||
| 77 | + mock_get_pkg_dir, | ||
| 78 | + ): | ||
| 79 | + mock_is_file.side_effect = [True, True] | ||
| 80 | + mock_is_dir.return_value = False | ||
| 81 | + | ||
| 82 | + with self.assertRaises(RuntimeError) as ctx: | ||
| 83 | + main() | ||
| 84 | + | ||
| 85 | + self.assertIn("Lib directory not found", str(ctx.exception)) | ||
| @@ -141,7 +141,7 @@ function fn_run_pythontest() | |||
| 141 | grep -o '<class name="[^"]*" filename="[^"]*" complexity="[^"]*" line-rate="[^"]*" branch-rate="[^"]*">' coverage.xml | | 141 | grep -o '<class name="[^"]*" filename="[^"]*" complexity="[^"]*" line-rate="[^"]*" branch-rate="[^"]*">' coverage.xml | |
| 142 | while read -r line; do | 142 | while read -r line; do |
| 143 | filename=$(echo "$line" | awk -F '"' '{print $4}') | 143 | filename=$(echo "$line" | awk -F '"' '{print $4}') |
| 144 | - if [[ ! "$line" =~ .*block_copy.* && ! "$line" =~ .*examples/run_generator.* && ! "$line" =~ .*examples/scheduler.* && ! "$line" =~ .*cache_manager.* && ! "$line" =~ .*utils/config.* && ! "$line" =~ .*__init__.* && ! "$line" =~ .*utils/log/logging.* && ! "$line" =~ .*mf_model_wrapper.* && ! "$line" =~ .*generator_ms.* && ! "$line" =~ .*plugin_manager_edge.* && ! "$line" =~ .*runtime.* && ! "$line" =~ .*aclgraph.* ]]; then | 144 | + if [[ ! "$line" =~ .*block_copy.* && ! "$line" =~ .*examples/run_generator.* && ! "$line" =~ .*examples/scheduler.* && ! "$line" =~ .*cache_manager.* && ! "$line" =~ .*utils/config.* && ! "$line" =~ .*__init__.* && ! "$line" =~ .*utils/log/logging.* && ! "$line" =~ .*mf_model_wrapper.* && ! "$line" =~ .*generator_ms.* && ! "$line" =~ .*plugin_manager_edge.* && ! "$line" =~ .*runtime.* && ! "$line" =~ .*aclgraph.* && ! "$line" =~ tokenizer/.*py ]]; then |
| 145 | echo "$line" | awk -F '"' '{print "mindie_llm/" $4, $8*100 "%", $10*100 "%"}' >> result.txt | 145 | echo "$line" | awk -F '"' '{print "mindie_llm/" $4, $8*100 "%", $10*100 "%"}' >> result.txt |
| 146 | fi | 146 | fi |
| 147 | done | 147 | done |