From abaa61ae7d3ccec37ef22b9930c81b0d9bab83a9 Mon Sep 17 00:00:00 2001
From: Li2718
Date: Tue, 21 Apr 2026 23:47:31 +0800
Subject: [PATCH] fix: accept cache_dir before cli subcommands
---
README.md | 4 +-
tools/fastllm_pytools/cli.py | 20 ++++++--
tools/fastllm_pytools/util.py | 88 +++++++++++++++++++++--------------
3 files changed, 73 insertions(+), 39 deletions(-)
diff --git a/README.md b/README.md
index 0fcb948f3..2318e4fbc 100644
--- a/README.md
+++ b/README.md
@@ -313,7 +313,7 @@ numactl -C 0-31 -m 0 ftllm server fastllm/DeepSeek-V3-0324-INT4 --device cuda --
- `--cache_dir`:
- **描述**: 指定在线Huggingface模型的缓存目录
- - **示例**: `ftllm --cache_dir /mnt`
+ - **示例**: `ftllm run Qwen/Qwen3-0.6B --cache_dir /mnt`
- `--chat_template`:
- **描述**: 指定chat_template文件
@@ -455,4 +455,4 @@ bash install.sh -DUSE_CUDA=ON -D CMAKE_CUDA_COMPILER=$(which nvcc) # 编译GPU
[json11](https://github.com/dropbox/json11)
-感谢大佬对开源社区的贡献!如发现未标明的引用代码可在issue中提出
\ No newline at end of file
+感谢大佬对开源社区的贡献!如发现未标明的引用代码可在issue中提出
diff --git a/tools/fastllm_pytools/cli.py b/tools/fastllm_pytools/cli.py
index 6217da0fe..cb3d4c5f0 100644
--- a/tools/fastllm_pytools/cli.py
+++ b/tools/fastllm_pytools/cli.py
@@ -40,11 +40,16 @@ def save_defaults_to_json(parser, filename):
print("Create config to -> \"" + filename + "\"")
def args_parser():
- parser = argparse.ArgumentParser(description = "fastllm")
+ global_shared_parser = make_normal_parser("fastllm", add_help = False,
+ include_model = False,
+ suppress_defaults = True)
+ parser = argparse.ArgumentParser(description = "fastllm",
+ parents = [global_shared_parser])
subparsers = parser.add_subparsers(dest='command', help='子命令')
# 创建共享的解析器
- shared_parser = make_normal_parser("fastllm", add_help = False)
+ shared_parser = make_normal_parser("fastllm", add_help = False,
+ suppress_defaults = True)
# 下载解析器
from ftllm.download import make_download_parser
@@ -83,8 +88,17 @@ def args_parser():
return parser
+
+def parse_args(argv = None):
+ args = args_parser().parse_args(argv)
+ shared_defaults = vars(make_normal_parser("fastllm", add_help = False).parse_args([]))
+ for key, value in shared_defaults.items():
+ if not hasattr(args, key):
+ setattr(args, key, value)
+ return args
+
def main():
- args = args_parser().parse_args()
+ args = parse_args()
if (args.version):
from . import __version__
print("ftllm version: " + __version__)
diff --git a/tools/fastllm_pytools/util.py b/tools/fastllm_pytools/util.py
index 42f309d98..9f1432eaf 100644
--- a/tools/fastllm_pytools/util.py
+++ b/tools/fastllm_pytools/util.py
@@ -2,44 +2,64 @@
import os
import sys
-def make_normal_parser(des: str, add_help = True) -> argparse.ArgumentParser:
- parser = argparse.ArgumentParser(description = des, add_help = add_help)
- parser.add_argument('model', nargs='?', help = '模型路径,fastllm模型文件或HF模型文件夹或配置文件')
- parser.add_argument('-p', '--path', type = str, required = False, default = '', help = '模型路径,fastllm模型文件或HF模型文件夹')
- parser.add_argument('-t', '--threads', type = int, default = -1, help = '线程数量')
- parser.add_argument('-l', '--low', action = 'store_true', help = '是否使用低内存模式')
- parser.add_argument('--dtype', type = str, default = "auto", help = '权重类型(读取HF模型时有效)')
- parser.add_argument('--moe_dtype', type = str, default = "", help = 'MOE层使用的权重类型(读取HF模型时有效)')
- parser.add_argument('--moe_atype', type = str, default = "", help = 'MOE层激活类型,可使用float32、float16或bfloat16')
- parser.add_argument('--atype', type = str, default = "auto", help = '推理类型,可使用float32或float16')
- parser.add_argument('--kv_cache_dtype', type = str, default = "auto", help = 'KV Cache类型,可使用auto、float16、bfloat16或fp8_e4m3')
- parser.add_argument('--cuda_embedding', action = 'store_true', help = '在cuda上进行embedding')
- parser.add_argument('--kv_cache_limit', type = str, default = "auto", help = 'kv缓存最大使用量')
- parser.add_argument('--max_batch', type = int, default = -1, help = '每次最多同时推理的询问数量')
- parser.add_argument('--chunked_prefill_size', type = int, default = -1, help = '分块 prefill 的切片大小(首块与后续块相同),如 8192')
- parser.add_argument('--device', type = str, help = '使用的设备')
- parser.add_argument('--moe_device', type = str, default = "", help = 'moe使用的设备')
- parser.add_argument('--moe_experts', type = int, default = -1, help = 'moe使用的专家数')
- parser.add_argument("--cache_history", type = str, default = "", help = "缓存历史对话")
- parser.add_argument("--cache_fast", type = str, default = "", help = "是否启用快速缓存(会消耗一定显存)")
- parser.add_argument("--enable_thinking", type = str, default = "", help = "是否开启硬思考开关(需要模型支持)")
- parser.add_argument("--cuda_shared_expert", "--cuda_se", type = str, default = "true", help = "是否使用cuda来执行共享专家")
- parser.add_argument("--enable_amx", "--amx", type = str, default = "false", help = "是否开启amx加速")
- parser.add_argument("--tokens", type = int, default = -1, help = "设置总的token数量(用于计算paged cache的最大页数)")
- parser.add_argument("--page_size", type = int, default = 128, help = "设置paged cache每页的大小(token数)")
- parser.add_argument("--gpu_mem_ratio", type = float, default = 0.9, help = "GPU显存使用比例,如0.9表示使用90%%的显存")
-
- parser.add_argument('--custom', type = str, default = "", help = '指定描述自定义模型的python文件')
- parser.add_argument('--lora', type = str, default = "", help = '指定lora路径')
- parser.add_argument('--cache_dir', type = str, default = "", help = '指定缓存模型文件的路径')
- parser.add_argument('--dtype_config', type = str, default = "", help = '指定权重类型配置文件')
- parser.add_argument('--ori', type = str, default = "", help = '原始模型权重,读取GGUF文件时可以使用')
- parser.add_argument('--tool_call_parser', type = str, default = "auto", help = '使用的tool_call_parser类型')
- parser.add_argument('--chat_template', type = str, default = "", help = '使用的chat_template文件')
+def _default_value(value, suppress_defaults: bool):
+ return argparse.SUPPRESS if suppress_defaults else value
+
+
+def add_normal_args(parser: argparse.ArgumentParser,
+ include_model: bool = True,
+ suppress_defaults: bool = False) -> argparse.ArgumentParser:
+ if include_model:
+ parser.add_argument('model', nargs='?', help = '模型路径,fastllm模型文件或HF模型文件夹或配置文件')
+ parser.add_argument('-p', '--path', type = str, required = False,
+ default = _default_value('', suppress_defaults),
+ help = '模型路径,fastllm模型文件或HF模型文件夹')
+ parser.add_argument('-t', '--threads', type = int,
+ default = _default_value(-1, suppress_defaults),
+ help = '线程数量')
+ parser.add_argument('-l', '--low', action = 'store_true',
+ default = _default_value(False, suppress_defaults),
+ help = '是否使用低内存模式')
+ parser.add_argument('--dtype', type = str, default = _default_value("auto", suppress_defaults), help = '权重类型(读取HF模型时有效)')
+ parser.add_argument('--moe_dtype', type = str, default = _default_value("", suppress_defaults), help = 'MOE层使用的权重类型(读取HF模型时有效)')
+ parser.add_argument('--moe_atype', type = str, default = _default_value("", suppress_defaults), help = 'MOE层激活类型,可使用float32、float16或bfloat16')
+ parser.add_argument('--atype', type = str, default = _default_value("auto", suppress_defaults), help = '推理类型,可使用float32或float16')
+ parser.add_argument('--kv_cache_dtype', type = str, default = _default_value("auto", suppress_defaults), help = 'KV Cache类型,可使用auto、float16、bfloat16或fp8_e4m3')
+ parser.add_argument('--cuda_embedding', action = 'store_true',
+ default = _default_value(False, suppress_defaults),
+ help = '在cuda上进行embedding')
+ parser.add_argument('--kv_cache_limit', type = str, default = _default_value("auto", suppress_defaults), help = 'kv缓存最大使用量')
+ parser.add_argument('--max_batch', type = int, default = _default_value(-1, suppress_defaults), help = '每次最多同时推理的询问数量')
+ parser.add_argument('--chunked_prefill_size', type = int, default = _default_value(-1, suppress_defaults), help = '分块 prefill 的切片大小(首块与后续块相同),如 8192')
+ parser.add_argument('--device', type = str, default = _default_value(None, suppress_defaults), help = '使用的设备')
+ parser.add_argument('--moe_device', type = str, default = _default_value("", suppress_defaults), help = 'moe使用的设备')
+ parser.add_argument('--moe_experts', type = int, default = _default_value(-1, suppress_defaults), help = 'moe使用的专家数')
+ parser.add_argument("--cache_history", type = str, default = _default_value("", suppress_defaults), help = "缓存历史对话")
+ parser.add_argument("--cache_fast", type = str, default = _default_value("", suppress_defaults), help = "是否启用快速缓存(会消耗一定显存)")
+ parser.add_argument("--enable_thinking", type = str, default = _default_value("", suppress_defaults), help = "是否开启硬思考开关(需要模型支持)")
+ parser.add_argument("--cuda_shared_expert", "--cuda_se", type = str, default = _default_value("true", suppress_defaults), help = "是否使用cuda来执行共享专家")
+ parser.add_argument("--enable_amx", "--amx", type = str, default = _default_value("false", suppress_defaults), help = "是否开启amx加速")
+ parser.add_argument("--tokens", type = int, default = _default_value(-1, suppress_defaults), help = "设置总的token数量(用于计算paged cache的最大页数)")
+ parser.add_argument("--page_size", type = int, default = _default_value(128, suppress_defaults), help = "设置paged cache每页的大小(token数)")
+ parser.add_argument("--gpu_mem_ratio", type = float, default = _default_value(0.9, suppress_defaults), help = "GPU显存使用比例,如0.9表示使用90%%的显存")
+ parser.add_argument('--custom', type = str, default = _default_value("", suppress_defaults), help = '指定描述自定义模型的python文件')
+ parser.add_argument('--lora', type = str, default = _default_value("", suppress_defaults), help = '指定lora路径')
+ parser.add_argument('--cache_dir', type = str, default = _default_value("", suppress_defaults), help = '指定缓存模型文件的路径')
+ parser.add_argument('--dtype_config', type = str, default = _default_value("", suppress_defaults), help = '指定权重类型配置文件')
+ parser.add_argument('--ori', type = str, default = _default_value("", suppress_defaults), help = '原始模型权重,读取GGUF文件时可以使用')
+
+ parser.add_argument('--tool_call_parser', type = str, default = _default_value("auto", suppress_defaults), help = '使用的tool_call_parser类型')
+ parser.add_argument('--chat_template', type = str, default = _default_value("", suppress_defaults), help = '使用的chat_template文件')
return parser
+
+def make_normal_parser(des: str, add_help = True, include_model: bool = True,
+ suppress_defaults: bool = False) -> argparse.ArgumentParser:
+ parser = argparse.ArgumentParser(description = des, add_help = add_help)
+ return add_normal_args(parser, include_model = include_model, suppress_defaults = suppress_defaults)
+
def add_server_args(parser):
parser.add_argument("--model_name", type = str, default = '', help = "部署的模型名称, 调用api时会进行名称核验")
parser.add_argument("--host", type = str, default="0.0.0.0", help = "API server host")