#!/usr/bin/env bash set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" ROOT="$(cd "${SCRIPT_DIR}/../../.." && pwd)" EXP_ROOT="${ROOT}/experiments/ablation" RUNNER="${ROOT}/experiments/lab_bench/scripts/run_labbench_with_hypobioos.py" PYTHON_BIN="${BIOMANUS_PYTHON:-/225040511/miniconda3/envs/biomni_e1/bin/python}" GRAPH_BUILDER="${ROOT}/build_generated_mcp_graph.py" GRAPH_SANITIZER="${ROOT}/experiments/lab_bench/scripts/sanitize_labbench_mcp_graph.py" BACKGROUND=0 VARIANT="all" DEBUG=0 DEV_SIZE="${BIOMANUS_LABBENCH_DEV_SIZE:-45}" TEST_SIZE="${BIOMANUS_LABBENCH_TEST_SIZE:-315}" SHARD_COUNT="${BIOMANUS_LABBENCH_SHARD_COUNT:-10}" SPLITS_TEXT="${BIOMANUS_LABBENCH_SPLITS:-test}" while [[ $# -gt 0 ]]; do case "$1" in --background) BACKGROUND=1; shift ;; --foreground) BACKGROUND=0; shift ;; --variant) VARIANT="$2"; shift 2 ;; --debug) DEBUG=1; shift ;; --dev-size) DEV_SIZE="$2"; shift 2 ;; --test-size) TEST_SIZE="$2"; shift 2 ;; --shard-count) SHARD_COUNT="$2"; shift 2 ;; --splits) SPLITS_TEXT="$2"; shift 2 ;; *) echo "Unknown argument: $1" >&2; exit 2 ;; esac done if [[ "${BACKGROUND}" -eq 1 ]]; then mkdir -p "${EXP_ROOT}/logs" LOG="${EXP_ROOT}/logs/labbench_ablation_$(date -u +%Y%m%d_%H%M%S).log" SCRIPT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/$(basename "${BASH_SOURCE[0]}")" CMD=( "${SCRIPT}" "--foreground" "--variant" "${VARIANT}" "--dev-size" "${DEV_SIZE}" "--test-size" "${TEST_SIZE}" "--shard-count" "${SHARD_COUNT}" "--splits" "${SPLITS_TEXT}" ) if [[ "${DEBUG}" -eq 1 ]]; then CMD+=("--debug"); fi nohup "${CMD[@]}" > "${LOG}" 2>&1 < /dev/null & echo "Started LAB-Bench ablation in background." echo "PID: $!" echo "Log: ${LOG}" exit 0 fi if [[ -f "${ROOT}/.env" ]]; then # shellcheck disable=SC1090 source "${ROOT}/.env" fi if [[ -n "${DEEPSEEK_API_KEY:-}" ]]; then export BIOMNI_SOURCE="${BIOMNI_SOURCE:-Custom}" export BIOMNI_LLM="${BIOMNI_LLM:-${DEEPSEEK_MODEL_NAME:-deepseek-chat}}" export BIOMNI_CUSTOM_BASE_URL="${BIOMNI_CUSTOM_BASE_URL:-${DEEPSEEK_BASE_URL:-https://api.deepseek.com/v1}}" export BIOMNI_CUSTOM_API_KEY="${BIOMNI_CUSTOM_API_KEY:-${DEEPSEEK_API_KEY}}" fi if [[ -n "${BIOMNI_CUSTOM_BASE_URL:-}" && ! "${BIOMNI_CUSTOM_BASE_URL}" =~ ^https?:// ]]; then export BIOMNI_CUSTOM_BASE_URL="${DEEPSEEK_BASE_URL:-https://api.deepseek.com/v1}" fi if [[ -z "${ANTHROPIC_API_KEY:-}" && -z "${OPENAI_API_KEY:-}" && -z "${BIOMNI_CUSTOM_API_KEY:-}" ]]; then echo "Missing LLM API key. Set DEEPSEEK_API_KEY, BIOMNI_CUSTOM_API_KEY, OPENAI_API_KEY, or ANTHROPIC_API_KEY." >&2 exit 2 fi mkdir -p "${EXP_ROOT}/logs" if [[ "${SHARD_COUNT}" -lt 1 ]]; then echo "--shard-count must be at least 1" >&2 exit 2 fi read -r -a SPLIT_ARRAY <<< "${SPLITS_TEXT}" TMP_GRAPH_DIR="" cleanup() { [[ -n "${TMP_GRAPH_DIR}" && -d "${TMP_GRAPH_DIR}" ]] && rm -rf "${TMP_GRAPH_DIR}" } trap cleanup EXIT prepare_clean_graph() { local full_graph_dir="${BIOMANUS_LABBENCH_FULL_GRAPH_DIR:-}" if [[ -z "${full_graph_dir}" ]]; then full_graph_dir="$(find "${ROOT}/graph_outputs" -maxdepth 1 -type d -name 'mcp_generated_graph_all_*' | sort | tail -n 1)" fi if [[ -z "${full_graph_dir}" ]]; then "${PYTHON_BIN}" "${GRAPH_BUILDER}" \ --preset all \ --output-root "${ROOT}/graph_outputs" \ --python-cmd "${PYTHON_BIN}" > /dev/null 2>&1 full_graph_dir="$(find "${ROOT}/graph_outputs" -maxdepth 1 -type d -name 'mcp_generated_graph_all_*' | sort | tail -n 1)" fi if [[ -z "${full_graph_dir}" || ! -d "${full_graph_dir}" ]]; then echo "Could not locate or build a full MCP graph." >&2 exit 2 fi TMP_GRAPH_DIR="$(mktemp -d /tmp/biomanus_ablation_labbench_clean_graph_XXXXXX)" "${PYTHON_BIN}" "${GRAPH_SANITIZER}" \ --source-graph-dir "${full_graph_dir}" \ --out-dir "${TMP_GRAPH_DIR}" > "${EXP_ROOT}/logs/last_labbench_graph_sanitize.json" echo "Using clean LAB-Bench MCP graph: ${TMP_GRAPH_DIR}" cat "${TMP_GRAPH_DIR}/labbench_sanitize_summary.json" } prepare_clean_graph run_variant() { local key="$1" local label="$2" shift 2 local out_root="${EXP_ROOT}/results/${key}/labbench" local agent_root="${EXP_ROOT}/agent_runtime/${key}" local shard_log_root="${EXP_ROOT}/results/${key}/labbench_shard_logs" mkdir -p "${out_root}" "${agent_root}" "${shard_log_root}" echo "=== LAB-Bench ${label} ===" for eval_name in DbQA SeqQA; do local compact="${EXP_ROOT}/results/${key}/labbench_${eval_name}.jsonl" local reasoning="${EXP_ROOT}/results/${key}/labbench_${eval_name}_reasoning.log" touch "${compact}" "${reasoning}" local -a pids=() local -a labels=() for (( shard_index=0; shard_index "${shard_log}" 2>&1 & pids+=("$!") labels+=("${run_label}") done local failed=0 for idx in "${!pids[@]}"; do local pid="${pids[$idx]}" local run_label="${labels[$idx]}" if wait "${pid}"; then echo "[launcher] shard ${run_label} completed" | tee -a "${reasoning}" else local status=$? failed=1 echo "[launcher] shard ${run_label} failed exit_code=${status} log=${shard_log_root}/${run_label}.log" | tee -a "${reasoning}" fi done if [[ "${failed}" -ne 0 ]]; then return 1 fi done } case "${VARIANT}" in biomanus) run_variant "biomanus" "full" --use-graph-retriever --use-mcp --mcp-retrieval-mode graph ;; mcp_flat) run_variant "mcp_flat" "MCP + flat retrieval" --use-graph-retriever --use-mcp --mcp-retrieval-mode flat ;; mcp_metadata) run_variant "mcp_metadata" "MCP + metadata retrieval" --use-graph-retriever --use-mcp --mcp-retrieval-mode metadata ;; minus_graph) run_variant "minus_graph" "minus graph" --no-graph-retriever --use-mcp ;; minus_mcp) run_variant "minus_mcp" "minus MCP" --use-graph-retriever --no-mcp ;; minus_mcp_graph) run_variant "minus_mcp_graph" "minus MCP and graph" --no-graph-retriever --no-mcp ;; all) run_variant "biomanus" "full" --use-graph-retriever --use-mcp --mcp-retrieval-mode graph run_variant "mcp_flat" "MCP + flat retrieval" --use-graph-retriever --use-mcp --mcp-retrieval-mode flat run_variant "mcp_metadata" "MCP + metadata retrieval" --use-graph-retriever --use-mcp --mcp-retrieval-mode metadata run_variant "minus_graph" "minus graph" --no-graph-retriever --use-mcp run_variant "minus_mcp" "minus MCP" --use-graph-retriever --no-mcp run_variant "minus_mcp_graph" "minus MCP and graph" --no-graph-retriever --no-mcp ;; *) echo "Unknown variant: ${VARIANT}" >&2 exit 2 ;; esac