benchscope 1.0.4__tar.gz → 1.0.6__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- benchscope-1.0.6/PKG-INFO +85 -0
- benchscope-1.0.6/README.md +50 -0
- benchscope-1.0.6/benchscope/__init__.py +4 -0
- benchscope-1.0.6/benchscope/benches/base.py +192 -0
- benchscope-1.0.6/benchscope/benches/runner.py +376 -0
- {benchscope-1.0.4 → benchscope-1.0.6}/benchscope/benches/sglang_bench.py +8 -1
- {benchscope-1.0.4 → benchscope-1.0.6}/benchscope/benches/vllm_bench.py +8 -1
- benchscope-1.0.6/benchscope/builtin_datasets.py +103 -0
- {benchscope-1.0.4 → benchscope-1.0.6}/benchscope/cli.py +22 -2
- benchscope-1.0.6/benchscope/config.py +234 -0
- {benchscope-1.0.4 → benchscope-1.0.6}/benchscope/constants.py +11 -3
- benchscope-1.0.6/benchscope/env_info.py +145 -0
- {benchscope-1.0.4 → benchscope-1.0.6}/benchscope/parser.py +28 -7
- benchscope-1.0.6/benchscope/server/api_config.py +431 -0
- benchscope-1.0.6/benchscope/server/api_dashboard.py +90 -0
- {benchscope-1.0.4 → benchscope-1.0.6}/benchscope/server/api_logs.py +188 -24
- benchscope-1.0.6/benchscope/server/api_sessions.py +85 -0
- benchscope-1.0.6/benchscope/server/api_tasks.py +199 -0
- {benchscope-1.0.4 → benchscope-1.0.6}/benchscope/server/app.py +39 -12
- benchscope-1.0.6/benchscope/server/state.py +23 -0
- {benchscope-1.0.4 → benchscope-1.0.6}/benchscope/server/test_manager.py +27 -8
- benchscope-1.0.6/benchscope/session_manager.py +388 -0
- benchscope-1.0.6/benchscope/task_manager.py +585 -0
- benchscope-1.0.6/benchscope/webui/assets/AccuracyView-BjuVpuFU.css +1 -0
- benchscope-1.0.6/benchscope/webui/assets/AccuracyView-DuYXlzdF.js +1 -0
- benchscope-1.0.6/benchscope/webui/assets/DashboardView-B9NSQxgY.js +1 -0
- benchscope-1.0.6/benchscope/webui/assets/DashboardView-efxhNbZA.css +1 -0
- benchscope-1.0.6/benchscope/webui/assets/DatasAnalysisView-D4kMXxJP.css +1 -0
- benchscope-1.0.6/benchscope/webui/assets/DatasAnalysisView-Dq2PU74U.js +1 -0
- benchscope-1.0.6/benchscope/webui/assets/DatasEvalsView-CKDm5d0o.js +1 -0
- benchscope-1.0.6/benchscope/webui/assets/DatasEvalsView-Dw2s8Caq.css +1 -0
- benchscope-1.0.6/benchscope/webui/assets/DatasPerfsView-CiHoLV4u.js +22 -0
- benchscope-1.0.6/benchscope/webui/assets/DatasPerfsView-iOsgANDF.css +1 -0
- benchscope-1.0.6/benchscope/webui/assets/DatasView-CelHF7nF.js +1 -0
- benchscope-1.0.6/benchscope/webui/assets/DatasView-RZvG0ZHh.css +1 -0
- benchscope-1.0.6/benchscope/webui/assets/MetricsTable-BqMrqOR7.css +1 -0
- benchscope-1.0.6/benchscope/webui/assets/MetricsTable-CnuI6iCF.js +1 -0
- benchscope-1.0.6/benchscope/webui/assets/PerfCreateView-CuS38i63.js +5 -0
- benchscope-1.0.6/benchscope/webui/assets/PerfCreateView-snqxkmyk.css +1 -0
- benchscope-1.0.6/benchscope/webui/assets/PerformanceView-CHLBhiQ5.css +1 -0
- benchscope-1.0.6/benchscope/webui/assets/PerformanceView-KOF5Mglm.js +2 -0
- benchscope-1.0.6/benchscope/webui/assets/SessionsView-DD5s41VZ.js +4 -0
- benchscope-1.0.6/benchscope/webui/assets/SessionsView-M3-edhM0.css +1 -0
- benchscope-1.0.6/benchscope/webui/assets/SettingsView-8-rKWxWv.css +1 -0
- benchscope-1.0.6/benchscope/webui/assets/SettingsView-zpGCDV5m.js +1 -0
- benchscope-1.0.4/benchscope/webui/assets/antd-CmFZS0N1.js → benchscope-1.0.6/benchscope/webui/assets/antd-CEH7kT1R.js +97 -97
- benchscope-1.0.4/benchscope/webui/assets/echarts-Bb6yjXMn.js → benchscope-1.0.6/benchscope/webui/assets/echarts-52vywGac.js +24 -24
- benchscope-1.0.4/benchscope/webui/assets/index-N9BkGck-.css → benchscope-1.0.6/benchscope/webui/assets/index-BOkjDk-W.css +1 -1
- benchscope-1.0.6/benchscope/webui/assets/index-DN0xzMJ_.js +2 -0
- benchscope-1.0.4/benchscope/webui/assets/vue-Ch4zjUb1.js → benchscope-1.0.6/benchscope/webui/assets/vue-q1XafS6H.js +11 -11
- benchscope-1.0.6/benchscope/webui/blue_logo.png +0 -0
- benchscope-1.0.6/benchscope/webui/bs-logo.png +0 -0
- {benchscope-1.0.4 → benchscope-1.0.6}/benchscope/webui/index.html +5 -4
- benchscope-1.0.6/benchscope.egg-info/PKG-INFO +85 -0
- benchscope-1.0.6/benchscope.egg-info/SOURCES.txt +69 -0
- {benchscope-1.0.4 → benchscope-1.0.6}/benchscope.egg-info/requires.txt +1 -0
- {benchscope-1.0.4 → benchscope-1.0.6}/pyproject.toml +7 -2
- benchscope-1.0.4/PKG-INFO +0 -133
- benchscope-1.0.4/README.md +0 -99
- benchscope-1.0.4/benchscope/__init__.py +0 -3
- benchscope-1.0.4/benchscope/benches/base.py +0 -54
- benchscope-1.0.4/benchscope/benches/runner.py +0 -185
- benchscope-1.0.4/benchscope/config.py +0 -91
- benchscope-1.0.4/benchscope/server/api_config.py +0 -97
- benchscope-1.0.4/benchscope/server/state.py +0 -18
- benchscope-1.0.4/benchscope/webui/assets/LogView-BDFIduo7.css +0 -1
- benchscope-1.0.4/benchscope/webui/assets/LogView-TcA_htXa.js +0 -1
- benchscope-1.0.4/benchscope/webui/assets/MetricsCharts-2foAhO3l.js +0 -1
- benchscope-1.0.4/benchscope/webui/assets/MetricsCharts-D1wU0LbK.css +0 -1
- benchscope-1.0.4/benchscope/webui/assets/SettingsView-7uuTFqXU.css +0 -1
- benchscope-1.0.4/benchscope/webui/assets/SettingsView-DNICupmh.js +0 -1
- benchscope-1.0.4/benchscope/webui/assets/TestView-BAwcOtR2.css +0 -1
- benchscope-1.0.4/benchscope/webui/assets/TestView-CkHWJhib.js +0 -4
- benchscope-1.0.4/benchscope/webui/assets/index-CySBHSRE.js +0 -2
- benchscope-1.0.4/benchscope.egg-info/PKG-INFO +0 -133
- benchscope-1.0.4/benchscope.egg-info/SOURCES.txt +0 -46
- {benchscope-1.0.4 → benchscope-1.0.6}/LICENSE +0 -0
- {benchscope-1.0.4 → benchscope-1.0.6}/benchscope/__main__.py +0 -0
- {benchscope-1.0.4 → benchscope-1.0.6}/benchscope/benches/__init__.py +0 -0
- {benchscope-1.0.4 → benchscope-1.0.6}/benchscope/datasets.py +0 -0
- {benchscope-1.0.4 → benchscope-1.0.6}/benchscope/gpu.py +0 -0
- {benchscope-1.0.4 → benchscope-1.0.6}/benchscope/server/__init__.py +0 -0
- {benchscope-1.0.4 → benchscope-1.0.6}/benchscope/server/api_test.py +0 -0
- {benchscope-1.0.4 → benchscope-1.0.6}/benchscope/server/status.py +0 -0
- {benchscope-1.0.4 → benchscope-1.0.6}/benchscope/server/ws.py +0 -0
- {benchscope-1.0.4 → benchscope-1.0.6}/benchscope/summary.py +0 -0
- {benchscope-1.0.4 → benchscope-1.0.6}/benchscope.egg-info/dependency_links.txt +0 -0
- {benchscope-1.0.4 → benchscope-1.0.6}/benchscope.egg-info/entry_points.txt +0 -0
- {benchscope-1.0.4 → benchscope-1.0.6}/benchscope.egg-info/top_level.txt +0 -0
- {benchscope-1.0.4 → benchscope-1.0.6}/setup.cfg +0 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: benchscope
|
|
3
|
+
Version: 1.0.6
|
|
4
|
+
Summary: LLM inference performance testing tool. Supports vLLM, SGLang, and any OpenAI-compatible API.
|
|
5
|
+
Author-email: benchscope <labelnet@foxmail.com>
|
|
6
|
+
License-Expression: Apache-2.0
|
|
7
|
+
Project-URL: Homepage, https://github.com/LABELNET/benchscope
|
|
8
|
+
Project-URL: Documentation, https://github.com/LABELNET/benchscope#readme
|
|
9
|
+
Project-URL: Source, https://github.com/LABELNET/benchscope
|
|
10
|
+
Keywords: vllm,sglang,benchmark,llm,performance-test,inference,openai-api,web-ui,benchscope
|
|
11
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Intended Audience :: Science/Research
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
20
|
+
Classifier: Topic :: System :: Benchmark
|
|
21
|
+
Classifier: Framework :: FastAPI
|
|
22
|
+
Requires-Python: >=3.9
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
License-File: LICENSE
|
|
25
|
+
Requires-Dist: fastapi>=0.110
|
|
26
|
+
Requires-Dist: uvicorn[standard]>=0.29
|
|
27
|
+
Requires-Dist: requests>=2.31
|
|
28
|
+
Requires-Dist: openpyxl>=3.1
|
|
29
|
+
Requires-Dist: pydantic>=2
|
|
30
|
+
Requires-Dist: python-multipart>=0.0.9
|
|
31
|
+
Requires-Dist: pyyaml>=6.0
|
|
32
|
+
Provides-Extra: modelscope
|
|
33
|
+
Requires-Dist: modelscope>=1.15; extra == "modelscope"
|
|
34
|
+
Dynamic: license-file
|
|
35
|
+
|
|
36
|
+
<div align="center">
|
|
37
|
+
<img src="asserts/black_logo.png" width="120" height="120" alt="BenchScope logo" />
|
|
38
|
+
</div>
|
|
39
|
+
|
|
40
|
+
<h1 align="center" style="font-size: 48px; margin-top: 12px;">BenchScope</h1>
|
|
41
|
+
|
|
42
|
+
<p align="center"><strong>English</strong> | <a href="README.zh-CN.md">简体中文</a></p>
|
|
43
|
+
|
|
44
|
+
BenchScope is an open‑source LLM inference benchmarking platform built with herness coding.
|
|
45
|
+
|
|
46
|
+
A visualization testing platform for LLM model **performance & accuracy**, supporting models deployed with vLLM / SGLang and any OpenAI-compatible inference service.
|
|
47
|
+
|
|
48
|
+
<div align="center">
|
|
49
|
+
<img src="asserts/main-performance.png" width="72%" alt="BenchScope main performance screenshot" />
|
|
50
|
+
</div>
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Features
|
|
55
|
+
|
|
56
|
+
- **Easy to install** — `pip install` and one command starts the whole web platform.
|
|
57
|
+
- **Performance testing dual mode** — Concurrency Mode (multi-level concurrency load) and Threshold Mode (auto-search the max concurrency meeting the threshold).
|
|
58
|
+
- **Accuracy testing dual mode** — Online / offline testing (planned, v5.0).
|
|
59
|
+
- **Real-time data feedback** — every concurrency result streams into tables, charts and progress in real time.
|
|
60
|
+
- **Visualization curves** — multi-dimensional charts for throughput / TTFT / TPOT / ITL.
|
|
61
|
+
- **Log cache & download** — run logs, mean/P99 summaries and Excel export with online preview & download.
|
|
62
|
+
|
|
63
|
+
## Quick Start
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
# Install from PyPI
|
|
67
|
+
pip install benchscope
|
|
68
|
+
|
|
69
|
+
# Start
|
|
70
|
+
benchscope
|
|
71
|
+
|
|
72
|
+
# Options
|
|
73
|
+
benchscope --port 8080 --no-browser
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Development
|
|
77
|
+
|
|
78
|
+
See [docs/Readme.md](docs/Readme.md).
|
|
79
|
+
|
|
80
|
+
## Open Source
|
|
81
|
+
|
|
82
|
+
- **License** — [Apache License 2.0](LICENSE)
|
|
83
|
+
- **Published on** — [PyPI: benchscope](https://pypi.org/project/benchscope/)
|
|
84
|
+
- **Source** — <https://github.com/LABELNET/benchscope>
|
|
85
|
+
- **Contributing** — Feel free to open issues / pull requests on the source repository.
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
<img src="asserts/black_logo.png" width="120" height="120" alt="BenchScope logo" />
|
|
3
|
+
</div>
|
|
4
|
+
|
|
5
|
+
<h1 align="center" style="font-size: 48px; margin-top: 12px;">BenchScope</h1>
|
|
6
|
+
|
|
7
|
+
<p align="center"><strong>English</strong> | <a href="README.zh-CN.md">简体中文</a></p>
|
|
8
|
+
|
|
9
|
+
BenchScope is an open‑source LLM inference benchmarking platform built with herness coding.
|
|
10
|
+
|
|
11
|
+
A visualization testing platform for LLM model **performance & accuracy**, supporting models deployed with vLLM / SGLang and any OpenAI-compatible inference service.
|
|
12
|
+
|
|
13
|
+
<div align="center">
|
|
14
|
+
<img src="asserts/main-performance.png" width="72%" alt="BenchScope main performance screenshot" />
|
|
15
|
+
</div>
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Features
|
|
20
|
+
|
|
21
|
+
- **Easy to install** — `pip install` and one command starts the whole web platform.
|
|
22
|
+
- **Performance testing dual mode** — Concurrency Mode (multi-level concurrency load) and Threshold Mode (auto-search the max concurrency meeting the threshold).
|
|
23
|
+
- **Accuracy testing dual mode** — Online / offline testing (planned, v5.0).
|
|
24
|
+
- **Real-time data feedback** — every concurrency result streams into tables, charts and progress in real time.
|
|
25
|
+
- **Visualization curves** — multi-dimensional charts for throughput / TTFT / TPOT / ITL.
|
|
26
|
+
- **Log cache & download** — run logs, mean/P99 summaries and Excel export with online preview & download.
|
|
27
|
+
|
|
28
|
+
## Quick Start
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
# Install from PyPI
|
|
32
|
+
pip install benchscope
|
|
33
|
+
|
|
34
|
+
# Start
|
|
35
|
+
benchscope
|
|
36
|
+
|
|
37
|
+
# Options
|
|
38
|
+
benchscope --port 8080 --no-browser
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Development
|
|
42
|
+
|
|
43
|
+
See [docs/Readme.md](docs/Readme.md).
|
|
44
|
+
|
|
45
|
+
## Open Source
|
|
46
|
+
|
|
47
|
+
- **License** — [Apache License 2.0](LICENSE)
|
|
48
|
+
- **Published on** — [PyPI: benchscope](https://pypi.org/project/benchscope/)
|
|
49
|
+
- **Source** — <https://github.com/LABELNET/benchscope>
|
|
50
|
+
- **Contributing** — Feel free to open issues / pull requests on the source repository.
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
"""bench 命令构建的公共定义。"""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from dataclasses import dataclass, field
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@dataclass
|
|
9
|
+
class ParamDef:
|
|
10
|
+
"""UI 表单中一个可配置参数的定义。"""
|
|
11
|
+
|
|
12
|
+
key: str # 表单字段名
|
|
13
|
+
flag: str # 实际 CLI flag,如 "--temperature"
|
|
14
|
+
label: str # 中文标签
|
|
15
|
+
help: str = ""
|
|
16
|
+
type: str = "str" # str | int | float | bool | select
|
|
17
|
+
default: Any = None
|
|
18
|
+
options: list = field(default_factory=list)
|
|
19
|
+
advanced: bool = False # 是否归入“高级参数”折叠区
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@dataclass
|
|
23
|
+
class BenchOptions:
|
|
24
|
+
"""一次 bench 执行所需的全部选项。"""
|
|
25
|
+
|
|
26
|
+
framework: str
|
|
27
|
+
model: str
|
|
28
|
+
api: dict # {host, port, base_url, endpoint, api_key, extra_headers}
|
|
29
|
+
dataset: dict # {type, path, input_len, output_len, sharegpt_output_len}
|
|
30
|
+
concurrency: int
|
|
31
|
+
request_rate: str | float = "inf"
|
|
32
|
+
curated: dict = field(default_factory=dict) # 表单参数 key -> value
|
|
33
|
+
extra_args: list = field(default_factory=list) # [{"flag": "--x", "value": "y"}]
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def build_arg_list(flags: list[list]) -> list[str]:
|
|
37
|
+
"""将 [["--flag","value"], ["--bool",""]] 展开为命令行列表。"""
|
|
38
|
+
out: list[str] = []
|
|
39
|
+
for item in flags:
|
|
40
|
+
flag, value = item[0], item[1] if len(item) > 1 else ""
|
|
41
|
+
if isinstance(value, bool):
|
|
42
|
+
if value:
|
|
43
|
+
out.append(flag)
|
|
44
|
+
continue
|
|
45
|
+
if value is None or value == "":
|
|
46
|
+
out.append(flag)
|
|
47
|
+
else:
|
|
48
|
+
out.extend([flag, str(value)])
|
|
49
|
+
return out
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def flag_value(flag: str, value: Any) -> list[str]:
|
|
53
|
+
"""单个 flag 的展开(供参数校验后使用)。"""
|
|
54
|
+
return build_arg_list([[flag, value]])
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
# 命令核心参数(由 payload / dataset 直接生成),yaml 参数附加时跳过以免重复
|
|
58
|
+
_CORE_FLAGS = {
|
|
59
|
+
"--model", "--tokenizer", "--max-concurrency", "--num-prompts",
|
|
60
|
+
"--random-input-len", "--random-output-len", "--dataset-name",
|
|
61
|
+
"--dataset-path", "--request-rate", "--host", "--port",
|
|
62
|
+
"--base-url", "--endpoint", "--backend", "--sharegpt-output-len",
|
|
63
|
+
"--sharegpt-context-len", "--apply-chat-template",
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
# ---------------------------------------------------------------------------
|
|
68
|
+
# 框架参数 yaml 的出厂默认内容(仅用于对比:命令只附加“被修改的参数”)
|
|
69
|
+
# 与 benchscope/configs/{framework}-default.yaml 的初始内容保持一致;
|
|
70
|
+
# 用户修改保存后,configs 文件变化,但此处出厂值不变,作为差异基线。
|
|
71
|
+
# ---------------------------------------------------------------------------
|
|
72
|
+
PARAM_YAML_DEFAULTS: dict[str, str] = {
|
|
73
|
+
"vllm": """version: vLLM v0.21.0
|
|
74
|
+
backend: openai-chat
|
|
75
|
+
endpoint: /v1/chat/completions
|
|
76
|
+
trust-remote-code: true
|
|
77
|
+
ignore-eos: true
|
|
78
|
+
burstiness: 1.0
|
|
79
|
+
seed: 0
|
|
80
|
+
num-warmups: 0
|
|
81
|
+
metric-percentiles: "99"
|
|
82
|
+
temperature: 0.0
|
|
83
|
+
top-p: 1.0
|
|
84
|
+
top-k: -1
|
|
85
|
+
min-p: 0.0
|
|
86
|
+
frequency-penalty: 0.0
|
|
87
|
+
presence-penalty: 0.0
|
|
88
|
+
sharegpt-output-len: 128
|
|
89
|
+
max-model-len: 32768
|
|
90
|
+
gpu-memory-utilization: 0.90
|
|
91
|
+
""",
|
|
92
|
+
"sglang": """version: SGLang v0.5.7
|
|
93
|
+
backend: openai
|
|
94
|
+
endpoint: /v1/chat/completions
|
|
95
|
+
trust-remote-code: true
|
|
96
|
+
ignore-eos: true
|
|
97
|
+
burstiness: 1.0
|
|
98
|
+
seed: 1
|
|
99
|
+
num-warmups: 0
|
|
100
|
+
metric-percentiles: "99"
|
|
101
|
+
temperature: 0.0
|
|
102
|
+
top-p: 1.0
|
|
103
|
+
top-k: -1
|
|
104
|
+
min-p: 0.0
|
|
105
|
+
frequency-penalty: 0.0
|
|
106
|
+
presence-penalty: 0.0
|
|
107
|
+
sharegpt-output-len: 128
|
|
108
|
+
max-model-len: 32768
|
|
109
|
+
mem-fraction-static: 0.90
|
|
110
|
+
""",
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def _parse_yaml_map(content: str | None) -> dict[str, str]:
|
|
115
|
+
"""解析 yaml 文本为 {key: value},跳过注释、空行与 version 行。"""
|
|
116
|
+
out: dict[str, str] = {}
|
|
117
|
+
for ln in (content or "").splitlines():
|
|
118
|
+
s = ln.strip()
|
|
119
|
+
if not s or s.startswith("#") or ":" not in s:
|
|
120
|
+
continue
|
|
121
|
+
k, v = s.split(":", 1)
|
|
122
|
+
k, v = k.strip(), v.strip()
|
|
123
|
+
if not k or k == "version":
|
|
124
|
+
continue
|
|
125
|
+
out[k] = v
|
|
126
|
+
return out
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def yaml_params_to_args(content: str | None, defaults_map: dict[str, str] | None = None) -> list[str]:
|
|
130
|
+
"""将框架默认参数 yaml 文本(每行 key: value)解析为 --key=value 列表。
|
|
131
|
+
跳过注释、空行与 version 行(版本仅展示用,不进入命令)。
|
|
132
|
+
若提供 defaults_map(出厂默认值),只输出“与默认值不同”的参数行——
|
|
133
|
+
即仅把 Step2 中用户修改过的参数附加到测试命令,未修改的默认参数不进入命令。"""
|
|
134
|
+
args: list[str] = []
|
|
135
|
+
for ln in (content or "").splitlines():
|
|
136
|
+
s = ln.strip()
|
|
137
|
+
if not s or s.startswith("#") or ":" not in s:
|
|
138
|
+
continue
|
|
139
|
+
k, v = s.split(":", 1)
|
|
140
|
+
k, v = k.strip(), v.strip()
|
|
141
|
+
if not k or k == "version":
|
|
142
|
+
continue
|
|
143
|
+
# 差异过滤:与出厂默认一致则跳过(未修改参数不进入命令)
|
|
144
|
+
if defaults_map is not None and defaults_map.get(k) == v:
|
|
145
|
+
continue
|
|
146
|
+
args.append(f"--{k}={v}" if v else f"--{k}")
|
|
147
|
+
return args
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
def merge_extra_args(payload: dict, extra_args: list | None = None) -> list:
|
|
151
|
+
"""合并 payload.extra_args 与 Step2 编辑的 params_yaml[framework] 参数,
|
|
152
|
+
跳过核心参数与已存在的 flag,避免命令中出现重复参数。"""
|
|
153
|
+
framework = payload.get("framework", "vllm")
|
|
154
|
+
extra = list(extra_args if extra_args is not None else (payload.get("extra_args") or []))
|
|
155
|
+
used = set()
|
|
156
|
+
for item in extra:
|
|
157
|
+
if isinstance(item, str):
|
|
158
|
+
used.add(item.split("=", 1)[0])
|
|
159
|
+
elif isinstance(item, dict):
|
|
160
|
+
used.add(item.get("flag", ""))
|
|
161
|
+
py = (payload.get("params_yaml") or {}).get(framework)
|
|
162
|
+
if py:
|
|
163
|
+
defaults_map = _parse_yaml_map(PARAM_YAML_DEFAULTS.get(framework))
|
|
164
|
+
for a in yaml_params_to_args(py, defaults_map):
|
|
165
|
+
key = a.split("=", 1)[0]
|
|
166
|
+
if key in _CORE_FLAGS or key in used:
|
|
167
|
+
continue
|
|
168
|
+
extra.append(a)
|
|
169
|
+
used.add(key)
|
|
170
|
+
return extra
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
def normalize_extra_args(extra_args: list | None) -> list[list]:
|
|
174
|
+
"""将 extra_args 统一为 [[flag, value]] 形式,供 build_command 追加。
|
|
175
|
+
兼容两种来源:字符串("--temperature=0.7" / "--flag")与 dict({"flag","value"})。"""
|
|
176
|
+
out: list[list] = []
|
|
177
|
+
for item in extra_args or []:
|
|
178
|
+
if isinstance(item, str):
|
|
179
|
+
s = item.strip()
|
|
180
|
+
if not s:
|
|
181
|
+
continue
|
|
182
|
+
if "=" in s:
|
|
183
|
+
flag, value = s.split("=", 1)
|
|
184
|
+
out.append([flag, value])
|
|
185
|
+
else:
|
|
186
|
+
out.append([s, ""])
|
|
187
|
+
elif isinstance(item, dict):
|
|
188
|
+
flag = (item.get("flag") or "").strip()
|
|
189
|
+
if not flag:
|
|
190
|
+
continue
|
|
191
|
+
out.append([flag, item.get("value", "")])
|
|
192
|
+
return out
|