From e2687940915a032aee1734e0925bb9fa450fe96c Mon Sep 17 00:00:00 2001
From: adibarra <93070681+adibarra@users.noreply.github.com>
Date: Mon, 10 Aug 2026 11:50:59 -0500
Subject: [PATCH 01/24] feat: add stock kimi tool-use eval
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
中文:添加基于 Kimi Vendor Verifier 原生实现的工具调用评估
---
.github/workflows/benchmark-tmpl.yml | 2 +
benchmarks/benchmark_lib.sh | 257 ++++++++-
utils/collect_eval_results.py | 4 +
utils/evals/EVALS.md | 87 ++-
utils/evals/kimi_vendor_eval.py | 255 +++++++++
utils/evals/test_kimi_vendor_eval.py | 287 ++++++++++
utils/evals/test_run_eval_dispatch.py | 506 +++++++++++++++++-
utils/evals/thresholds.yaml | 1 +
utils/test_collect_eval_results.py | 19 +
.../test_validate_reusable_sweep_artifacts.py | 70 ++-
utils/validate_reusable_sweep_artifacts.py | 12 +
11 files changed, 1480 insertions(+), 20 deletions(-)
create mode 100755 utils/evals/kimi_vendor_eval.py
create mode 100644 utils/evals/test_kimi_vendor_eval.py
diff --git a/.github/workflows/benchmark-tmpl.yml b/.github/workflows/benchmark-tmpl.yml
index 6c4fe50fe5..4dc036a06d 100644
--- a/.github/workflows/benchmark-tmpl.yml
+++ b/.github/workflows/benchmark-tmpl.yml
@@ -392,6 +392,7 @@ jobs:
path: |
meta_env.json
results*.json
+ kimi_vendor_report.json
sample*.jsonl
agent_preds.json
predictions.jsonl
@@ -409,6 +410,7 @@ jobs:
rm -f meta_env.json || true
# Remove any eval results JSONs that were moved into workspace
rm -f results*.json || true
+ rm -f kimi_vendor_report.json || true
rm -f sample*.jsonl || true
rm -f agent_preds.json predictions.jsonl swebench_report_*.json *.traj* || true
diff --git a/benchmarks/benchmark_lib.sh b/benchmarks/benchmark_lib.sh
index 1617e1190e..5519682c8f 100644
--- a/benchmarks/benchmark_lib.sh
+++ b/benchmarks/benchmark_lib.sh
@@ -8,6 +8,9 @@
export PYTHONDONTWRITEBYTECODE=1
export PYTHONPYCACHEPREFIX="${PYTHONPYCACHEPREFIX:-/tmp/inferencex-pycache}"
mkdir -p "$PYTHONPYCACHEPREFIX" 2>/dev/null || true
+INFERENCEX_BENCHMARK_LIB_DIR="$(
+ cd "$(dirname "${BASH_SOURCE[0]}")" && pwd
+)"
# Inference server port shared by every benchmark recipe. Launchers that need
# a non-default value (e.g. launch_mi355x-amds.sh derives PORT from RUNNER_NAME
@@ -816,6 +819,230 @@ _install_lm_eval_deps() {
fi
}
+_require_tool_use_python() {
+ if python3 -c 'import sys; raise SystemExit(sys.version_info < (3, 12))'; then
+ return 0
+ fi
+
+ local python_version
+ python_version="$(python3 -c 'import platform; print(platform.python_version())' 2>/dev/null || printf 'unavailable')"
+ echo "ERROR: tool-use requires Python >=3.12 (python3 is ${python_version})" >&2
+ return 2
+}
+
+_install_tool_use_eval_deps() {
+ python3 -m pip install -q --no-cache-dir --break-system-packages \
+ "httpx[http2]==0.28.1" \
+ "openai==2.14.0" \
+ "jsonschema==4.25.1" \
+ "pytest==8.4.2"
+}
+
+_kimi_vendor_checkout_is_valid() {
+ local checkout_dir="$1"
+ local expected_ref="$2"
+ local checkout_ref checkout_status tracked_status untracked_files ignored_files
+
+ [ -f "${checkout_dir}/LICENSE" ] \
+ && [ -f "${checkout_dir}/pyproject.toml" ] \
+ && [ -f "${checkout_dir}/tests/conftest.py" ] \
+ && [ -f "${checkout_dir}/tests/__init__.py" ] \
+ && [ -f "${checkout_dir}/tests/tool_call_json_schema/conftest.py" ] \
+ && [ -f "${checkout_dir}/tests/tool_call_json_schema/validator.py" ] \
+ && [ -f "${checkout_dir}/tests/tool_call_json_schema/test_tool_call_json_schema.py" ] \
+ && [ -d "${checkout_dir}/testdata/walle_validator_cases/validator_cases" ] \
+ || return 1
+ checkout_ref="$(git -C "$checkout_dir" rev-parse HEAD 2>/dev/null)" \
+ || return 1
+ [ "$checkout_ref" = "$expected_ref" ] || return 1
+ checkout_status="$(
+ git -C "$checkout_dir" status --porcelain --untracked-files=all -- \
+ LICENSE \
+ pyproject.toml \
+ tests/conftest.py \
+ tests/__init__.py \
+ tests/tool_call_json_schema \
+ testdata/walle_validator_cases
+ )" || return 1
+ [ -z "$checkout_status" ] || return 1
+ tracked_status="$(
+ git -C "$checkout_dir" status --porcelain --untracked-files=no
+ )" || return 1
+ [ -z "$tracked_status" ] || return 1
+ untracked_files="$(
+ git -C "$checkout_dir" ls-files --others --exclude-standard -- \
+ . ':(exclude,top,glob).pytest_cache/**'
+ )" || return 1
+ [ -z "$untracked_files" ] || return 1
+ ignored_files="$(
+ git -C "$checkout_dir" ls-files --others --ignored --exclude-standard -- \
+ . ':(exclude,top,glob).pytest_cache/**'
+ )" || return 1
+ [ -z "$ignored_files" ]
+}
+
+_prepare_kimi_vendor_verifier() {
+ local repo_url="$1"
+ local verifier_ref="$2"
+ local checkout_dir
+
+ if [ -n "${KIMI_VENDOR_VERIFIER_DIR:-}" ]; then
+ checkout_dir="$KIMI_VENDOR_VERIFIER_DIR"
+ if ! _kimi_vendor_checkout_is_valid "$checkout_dir" "$verifier_ref"; then
+ echo "ERROR: KIMI_VENDOR_VERIFIER_DIR must be at ${verifier_ref}" >&2
+ echo "ERROR: required verifier sources must be present and unmodified" >&2
+ return 2
+ fi
+ KIMI_VENDOR_VERIFIER_CHECKOUT_DIR="$checkout_dir"
+ return 0
+ fi
+
+ checkout_dir="/tmp/kimi-vendor-verifier-${verifier_ref}"
+ if _kimi_vendor_checkout_is_valid "$checkout_dir" "$verifier_ref"; then
+ KIMI_VENDOR_VERIFIER_CHECKOUT_DIR="$checkout_dir"
+ return 0
+ fi
+
+ command -v git >/dev/null 2>&1 || {
+ echo "ERROR: git is required to fetch Kimi-Vendor-Verifier" >&2
+ return 1
+ }
+ rm -rf "$checkout_dir"
+ mkdir -p "$(dirname "$checkout_dir")" || return $?
+ if ! (
+ git init -q "$checkout_dir" \
+ && git -C "$checkout_dir" remote add origin "$repo_url" \
+ && git -C "$checkout_dir" config remote.origin.promisor true \
+ && git -C "$checkout_dir" config remote.origin.partialclonefilter blob:none \
+ && git -C "$checkout_dir" fetch -q --filter=blob:none --depth=1 \
+ origin "$verifier_ref" \
+ && git -C "$checkout_dir" update-ref HEAD FETCH_HEAD \
+ && git -C "$checkout_dir" sparse-checkout set --no-cone \
+ /LICENSE \
+ /pyproject.toml \
+ /tests/conftest.py \
+ /tests/__init__.py \
+ /tests/tool_call_json_schema/ \
+ /testdata/walle_validator_cases/ \
+ && git -C "$checkout_dir" checkout -q --detach HEAD
+ ); then
+ rm -rf "$checkout_dir"
+ echo "ERROR: failed to fetch Kimi-Vendor-Verifier at ${verifier_ref}" >&2
+ return 1
+ fi
+ if ! _kimi_vendor_checkout_is_valid "$checkout_dir" "$verifier_ref"; then
+ rm -rf "$checkout_dir"
+ echo "ERROR: fetched Kimi-Vendor-Verifier checkout is incomplete" >&2
+ return 1
+ fi
+ KIMI_VENDOR_VERIFIER_CHECKOUT_DIR="$checkout_dir"
+}
+
+_write_tool_use_integration_error() {
+ local adapter_path="$1"
+ local model_name="$2"
+ local results_dir="$3"
+ local message="$4"
+
+ python3 "$adapter_path" \
+ --model "$model_name" \
+ --output-dir "$results_dir" \
+ --integration-error "$message" \
+ || true
+}
+
+run_tool_use_eval() {
+ local port="${PORT:-8888}"
+ local results_dir="${EVAL_RESULT_DIR:-$(mktemp -d /tmp/eval_out-XXXXXX)}"
+ local verifier_repo="https://github.com/MoonshotAI/Kimi-Vendor-Verifier.git"
+ local verifier_ref="b9ed3a6665bdff2c943246f7d2903cd003d6ddd6"
+
+ while [[ $# -gt 0 ]]; do
+ case "$1" in
+ --port|--results-dir)
+ if [[ $# -lt 2 || -z "${2:-}" || "${2:-}" == --* ]]; then
+ echo "ERROR: $1 requires a value" >&2
+ return 2
+ fi
+ case "$1" in
+ --port) port="$2" ;;
+ --results-dir) results_dir="$2" ;;
+ esac
+ shift 2
+ ;;
+ *)
+ echo "Unknown parameter: $1" >&2
+ return 2
+ ;;
+ esac
+ done
+
+ local eval_suite="${EVAL_SUITE:-kimi_tool_call_schema}"
+ if [ "$eval_suite" != "kimi_tool_call_schema" ]; then
+ echo "ERROR: tool-use supports only EVAL_SUITE=kimi_tool_call_schema" >&2
+ export EVAL_RESULT_DIR=""
+ return 2
+ fi
+ case "${IS_MULTINODE:-false}" in
+ true|1)
+ echo "ERROR: tool-use Phase 1 supports single-node evals only" >&2
+ export EVAL_RESULT_DIR=""
+ return 2
+ ;;
+ esac
+ export EVAL_FRAMEWORK=tool-use
+ export EVAL_SUITE="$eval_suite"
+
+ local _repo_root
+ _repo_root="$(cd "$INFERENCEX_BENCHMARK_LIB_DIR/.." && pwd)"
+ local model_name="${MODEL_NAME:-${MODEL:-}}"
+ local adapter_path="${_repo_root}/utils/evals/kimi_vendor_eval.py"
+
+ mkdir -p "$results_dir" || return $?
+ export EVAL_RESULT_DIR="$results_dir"
+
+ local setup_rc integration_error
+ if _require_tool_use_python; then
+ :
+ else
+ setup_rc=$?
+ integration_error="tool-use Python version check failed with exit code ${setup_rc}"
+ echo "ERROR: ${integration_error}" >&2
+ _write_tool_use_integration_error \
+ "$adapter_path" "$model_name" "$results_dir" "$integration_error"
+ return "$setup_rc"
+ fi
+ if [ "${INFERENCEX_TOOL_USE_EVAL_RUNTIME_READY:-false}" != "true" ]; then
+ if _install_tool_use_eval_deps; then
+ export INFERENCEX_TOOL_USE_EVAL_RUNTIME_READY=true
+ else
+ setup_rc=$?
+ integration_error="tool-use dependency installation failed with exit code ${setup_rc}"
+ echo "ERROR: ${integration_error}" >&2
+ _write_tool_use_integration_error \
+ "$adapter_path" "$model_name" "$results_dir" "$integration_error"
+ return "$setup_rc"
+ fi
+ fi
+ if _prepare_kimi_vendor_verifier "$verifier_repo" "$verifier_ref"; then
+ :
+ else
+ setup_rc=$?
+ integration_error="tool-use verifier checkout failed with exit code ${setup_rc}"
+ echo "ERROR: ${integration_error}" >&2
+ _write_tool_use_integration_error \
+ "$adapter_path" "$model_name" "$results_dir" "$integration_error"
+ return "$setup_rc"
+ fi
+
+ python3 "$adapter_path" \
+ --verifier-dir "$KIMI_VENDOR_VERIFIER_CHECKOUT_DIR" \
+ --base-url "http://127.0.0.1:${port}/v1" \
+ --api-key EMPTY \
+ --model "$model_name" \
+ --output-dir "$results_dir"
+}
+
_eval_patches_dir() {
cd "$(dirname "${BASH_SOURCE[0]}")/../utils/evals/patches" && pwd
}
@@ -934,6 +1161,15 @@ run_lm_eval() {
tasks_dir="$_repo_root/$tasks_dir"
fi
+ local effective_suite="${EVAL_SUITE:-}"
+ local task_basename
+ if [ -z "$effective_suite" ]; then
+ task_basename="${tasks_dir##*/}"
+ effective_suite="${task_basename%.yaml}"
+ effective_suite="${effective_suite%.yml}"
+ fi
+ export EVAL_SUITE="$effective_suite"
+
if [ "${INFERENCEX_LM_EVAL_RUNTIME_READY:-false}" != "true" ]; then
_install_lm_eval_deps
_patch_lm_eval
@@ -1141,12 +1377,22 @@ append_lm_eval_summary() {
fi
fi
fi
+ local eval_framework="${EVAL_FRAMEWORK:-lm-eval}"
+ local eval_suite="${EVAL_SUITE:-}"
+ if [ -z "$eval_suite" ] && [ -n "${EVAL_TASKS_DIR:-}" ]; then
+ eval_suite="$(basename "${EVAL_TASKS_DIR}")"
+ eval_suite="${eval_suite%.yaml}"
+ eval_suite="${eval_suite%.yml}"
+ fi
+ eval_suite="${eval_suite:-gsm8k}"
cat > "${meta_json}" < /dev/null
fi
@@ -1635,6 +1887,7 @@ run_eval() {
case "$framework" in
lm-eval|lm_eval) run_lm_eval "${forwarded[@]}" || eval_rc=$? ;;
swebench) run_swebench_eval "${forwarded[@]}" || eval_rc=$? ;;
+ tool-use) run_tool_use_eval "${forwarded[@]}" || eval_rc=$? ;;
*) echo "Unknown framework '${framework}'"; eval_rc=1 ;;
esac
diff --git a/utils/collect_eval_results.py b/utils/collect_eval_results.py
index 667e60bc6f..7bc49c5d8c 100644
--- a/utils/collect_eval_results.py
+++ b/utils/collect_eval_results.py
@@ -284,6 +284,10 @@ def build_row(meta: Dict[str, Any], m: Dict[str, Any]) -> Dict[str, Any]:
'source': m.get('source'),
}
+ for metadata_field in ('eval_framework', 'eval_suite'):
+ if metadata_field in meta:
+ row[metadata_field] = meta[metadata_field]
+
# Add universal score field (primary metric for unified comparison)
if m.get('strict') is not None:
row['score'] = m.get('strict')
diff --git a/utils/evals/EVALS.md b/utils/evals/EVALS.md
index 7320795431..07aa48b4de 100644
--- a/utils/evals/EVALS.md
+++ b/utils/evals/EVALS.md
@@ -39,9 +39,85 @@ malformed metadata, duplicates, or raw/aggregate mismatches are not. See
[workflow reuse](../../.github/workflows/README.md#reusing-an-approved-pr-full-sweep).
## How?
-`run_eval` in `benchmarks/benchmark_lib.sh` runs EleutherAI/lm-evaluation-harness against the server's OpenAI-compatible endpoint. Concurrency is set via `EVAL_CONCURRENT_REQUESTS` env var (not a CLI flag). Results are collected by `utils/collect_eval_results.py` and published as a summary table.
+`run_eval` in `benchmarks/benchmark_lib.sh` dispatches to the selected eval
+framework against the server's OpenAI-compatible endpoint. The default is
+[lm-evaluation-harness](https://github.com/EleutherAI/lm-evaluation-harness)
+(`lm-eval`) with GSM8K. Existing fixed-sequence and agentic paths preserve that
+default, and explicit agentic runs can still select SWE-bench.
-The default eval framework is [lm-evaluation-harness](https://github.com/EleutherAI/lm-evaluation-harness) (`lm-eval`). Agentic eval-only matrix jobs inherit this default and therefore run the same GSM8K task as 8k1k; explicit agentic runs can still select SWE-bench.
+The Phase 1 tool-use suite is opt-in. The Kimi-K3 B300 vLLM agentic launcher,
+like every existing launcher, continues to select lm-eval/GSM8K by default. To
+run the suite after its server is ready, use the existing entrypoint:
+
+```bash
+EVAL_FRAMEWORK=tool-use EVAL_SUITE=kimi_tool_call_schema \
+ run_eval --port "$PORT"
+```
+
+`run_tool_use_eval` supplies `kimi_tool_call_schema` when `EVAL_SUITE` is unset
+for a manual `run_eval --framework tool-use` call and rejects every other suite.
+The compatibility result continues through the existing collector, suite-aware
+artifact identity, and strict `1.0` threshold.
+Phase 1 is single-node only and rejects `IS_MULTINODE=true` or `1`; the
+multi-node workflow does not yet preserve the stock native report.
+
+### Stock Kimi tool-call schema smoke
+
+This suite runs the unmodified
+[MoonshotAI/Kimi-Vendor-Verifier](https://github.com/MoonshotAI/Kimi-Vendor-Verifier)
+at commit `b9ed3a6665bdff2c943246f7d2903cd003d6ddd6`. Its bundled Walle
+schema corpus is sourced from MoonshotAI/walle commit
+`cc1c6b7dab5496d5184677ecf4c3b95fc1bd1606` (`v0.1.10`). The upstream
+prompt, schema loading and selection, request construction, non-stream and
+stream assembly, argument validation, and report generation are all stock.
+InferenceX owns only the subprocess invocation and compatibility projection.
+
+Python 3.12 or newer is required; the runner fails with a version error before
+installing or checking out anything on older Python. At runtime it installs only
+`httpx[http2]==0.28.1`, `openai==2.14.0`, `jsonschema==4.25.1`, and
+`pytest==8.4.2`. It then makes a network checkout from GitHub using a sparse,
+detached checkout of the pinned verifier commit containing only:
+
+- `LICENSE` and `pyproject.toml`;
+- `tests/__init__.py`, `tests/conftest.py`, and
+ `tests/tool_call_json_schema/`;
+- `testdata/walle_validator_cases/`.
+
+An explicitly supplied `KIMI_VENDOR_VERIFIER_DIR` is reused only when it is at
+that exact commit, required sources are unmodified, and no extra checkout files
+can override the verifier (root `.pytest_cache/` is ignored). The verifier
+project and its unrelated benchmark dependencies are not installed.
+
+The thin `utils/evals/kimi_vendor_eval.py` wrapper runs upstream
+`tests/tool_call_json_schema/test_tool_call_json_schema.py` with:
+
+- base URL `http://127.0.0.1:${PORT}/v1`, API key `EMPTY`, and model
+ `${MODEL_NAME:-$MODEL}`;
+- `--case-dir testdata/walle_validator_cases/validator_cases`,
+ `--think-mode none --selection object --max-cases 1 --max-tokens 2048`;
+- `--tool-json-report