Skip to content

[NPU] support multi-agent rollout pipeline#298

Open
Windfeng8 wants to merge 5 commits into
vllm-project:ascendfrom
Windfeng8:fix/multi-agent
Open

[NPU] support multi-agent rollout pipeline#298
Windfeng8 wants to merge 5 commits into
vllm-project:ascendfrom
Windfeng8:fix/multi-agent

Conversation

@Windfeng8

@Windfeng8 Windfeng8 commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Added local token/logprob parsing for compatibility with the latest VIME.Assigned the same to sibling agent samples.
[RFC] #299

Qwen3-4B 20-Rollout Pilot: Single vs. Multi-Agent Analysis

Technical Summary

The 20-rollout pilot completed for both conditions. Multi-Agent was higher in the observed AIME results: pass@1 increased from 0.333% to 0.500%, pass@8 increased from 2.547% to 3.540%, and correct-sample efficiency per output token was 1.498× the Single baseline.

Scope and Comparability

Item Single baseline Multi-Agent candidate
Run ID 20260720_201425_pilot20_single_qwen3-4b_seed42 20260720_213101_pilot20_multi_qwen3-4b_seed42
Model Qwen3-4B Qwen3-4B
Training rollouts 20 20
Training/rollout seed 42 42
AIME evaluator seed 20260720 20260720
AIME problems 30 30
Samples per problem per evaluation 8 8
Evaluation snapshots 5 5
Aggregated AIME samples 1,200 1,200

The two conditions used the same model, data, seeds, rollout budget, and AIME evaluation budget. Multi-Agent training used solver / rewriter / selector collaboration. Evaluation deliberately used the standard single-generation path for both conditions; this comparison therefore measures the model-capability effect of Multi-Agent training, not the end-to-end benefit of Multi-Agent inference orchestration.

Main Results: Multi-Agent Shows a Small Observed Gain

Metric Single Multi-Agent Multi - Single
Correct samples / 1,200 4 6 +2
pass@1 (primary score) 0.00333 (0.333%) 0.00500 (0.500%) +0.00167 (+0.167pp)
pass@8 0.02547 (2.547%) 0.03540 (3.540%) +0.00993 (+0.993pp)
pass@11 0.03432 (3.432%) 0.04615 (4.615%) +0.01184 (+1.184pp)
Total output tokens 2,436,532 2,439,460 +2,928
Correct samples / million output tokens 1.64168 2.45956 +49.82%
Correct-sample/token efficiency ratio 1.000× 1.498× +0.498×

Multi - Single means the Multi-Agent value minus the Single baseline value. A positive value indicates an observed increase; a negative value indicates a regression. For example, pass@1 is 0.00500 - 0.00333 = +0.00167, which is +0.167 percentage points, not +0.167 percent.

pass@1 estimates the probability that one randomly selected answer is correct. pass@8 and pass@11 estimate the probability of obtaining at least one correct answer with 8 or 11 samples, respectively. These are score metrics; “correct samples per million output tokens” is an efficiency metric and should not be interpreted as a replacement for correctness.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a compatibility helper for extracting token IDs and log probabilities from vLLM rollout responses, updates multi-agent rollouts to share a single rollout_id among sibling samples to prevent over-counting during loss reduction, and adds a training script for Qwen3-4B on NPU. The review feedback highlights several critical improvements: adding defensive checks to prevent TypeError when converting potentially None log probabilities, handling cases where the multi-agent function returns None or empty samples, and replacing hardcoded absolute paths in the shell script with dynamic path resolution to ensure portability.

Comment on lines +22 to +25
new_response_log_probs = [
float(item.get("logprob", 0.0)) if isinstance(item, dict) else 0.0
for item in content_items
]

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

If item.get("logprob") is explicitly None or missing, calling float(None) will raise a TypeError and crash the rollout pipeline. We should defensively check if the logprob value is not None before converting it to a float.

Suggested change
new_response_log_probs = [
float(item.get("logprob", 0.0)) if isinstance(item, dict) else 0.0
for item in content_items
]
new_response_log_probs = [
float(item.get("logprob")) if isinstance(item, dict) and item.get("logprob") is not None else 0.0
for item in content_items
]

Comment thread scripts/run-qwen3-4B-multi-agent-npu.sh Outdated
Comment on lines +5 to +20
export PYTHONPATH="/workspace/issue205/Megatron-Bridge/src:/workspace/issue205/Megatron-Bridge:/workspace/issue205/Megatron-LM:/workspace/issue205/vime-ascend:${PYTHONPATH}"
export ASCEND_RT_VISIBLE_DEVICES="${ASCEND_RT_VISIBLE_DEVICES:-0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}"
export CUDA_DEVICE_MAX_CONNECTIONS=1
export RAY_EXPERIMENTAL_NOSET_ASCEND_RT_VISIBLE_DEVICES=1
export HCCL_HOST_SOCKET_PORT_RANGE=60000-60050
export HCCL_NPU_SOCKET_PORT_RANGE=61000-61050
export HYDRA_FULL_ERROR=1
export MASTER_PORT="${MASTER_PORT:-$(shuf -i 20000-65000 -n 1)}"
export DISABLE_L2_CACHE=1
export VLLM_ASCEND_ENABLE_NZ=0

VIME_ROOT="${VIME_ROOT:-/workspace/issue205/vime-ascend}"
SCRIPT_DIR="${VIME_ROOT}/scripts"
WEIGHT_DIR="${WEIGHT_DIR:-/home/data/weights/Qwen3-4B}"
DATA_FILE="${DATA_FILE:-/home/w00893744/dataset/dapo-math-17k.jsonl}"
LOG_FILE="${LOG_FILE:-/home/w00893744/train_qwen3_4b_multi_agent_vllm.log}"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The script contains hardcoded absolute paths specific to a single user's environment (e.g., /workspace/issue205/... and /home/w00893744/...). This makes the script non-portable and prone to immediate failure on other machines or for other users.

We should dynamically resolve the project root (VIME_ROOT) and workspace directory relative to the script's location, and avoid hardcoding user-specific home directories for DATA_FILE and LOG_FILE.

Suggested change
export PYTHONPATH="/workspace/issue205/Megatron-Bridge/src:/workspace/issue205/Megatron-Bridge:/workspace/issue205/Megatron-LM:/workspace/issue205/vime-ascend:${PYTHONPATH}"
export ASCEND_RT_VISIBLE_DEVICES="${ASCEND_RT_VISIBLE_DEVICES:-0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}"
export CUDA_DEVICE_MAX_CONNECTIONS=1
export RAY_EXPERIMENTAL_NOSET_ASCEND_RT_VISIBLE_DEVICES=1
export HCCL_HOST_SOCKET_PORT_RANGE=60000-60050
export HCCL_NPU_SOCKET_PORT_RANGE=61000-61050
export HYDRA_FULL_ERROR=1
export MASTER_PORT="${MASTER_PORT:-$(shuf -i 20000-65000 -n 1)}"
export DISABLE_L2_CACHE=1
export VLLM_ASCEND_ENABLE_NZ=0
VIME_ROOT="${VIME_ROOT:-/workspace/issue205/vime-ascend}"
SCRIPT_DIR="${VIME_ROOT}/scripts"
WEIGHT_DIR="${WEIGHT_DIR:-/home/data/weights/Qwen3-4B}"
DATA_FILE="${DATA_FILE:-/home/w00893744/dataset/dapo-math-17k.jsonl}"
LOG_FILE="${LOG_FILE:-/home/w00893744/train_qwen3_4b_multi_agent_vllm.log}"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
VIME_ROOT="${VIME_ROOT:-$(cd "${SCRIPT_DIR}/.." && pwd)}"
WORKSPACE_DIR="$(cd "${VIME_ROOT}/.." && pwd)"
export PYTHONPATH="${WORKSPACE_DIR}/Megatron-Bridge/src:${WORKSPACE_DIR}/Megatron-Bridge:${WORKSPACE_DIR}/Megatron-LM:${VIME_ROOT}:${PYTHONPATH}"
export ASCEND_RT_VISIBLE_DEVICES="${ASCEND_RT_VISIBLE_DEVICES:-0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}"
export CUDA_DEVICE_MAX_CONNECTIONS=1
export RAY_EXPERIMENTAL_NOSET_ASCEND_RT_VISIBLE_DEVICES=1
export HCCL_HOST_SOCKET_PORT_RANGE=60000-60050
export HCCL_NPU_SOCKET_PORT_RANGE=61000-61050
export HYDRA_FULL_ERROR=1
export MASTER_PORT="${MASTER_PORT:-$(shuf -i 20000-65000 -n 1)}"
export DISABLE_L2_CACHE=1
export VLLM_ASCEND_ENABLE_NZ=0
WEIGHT_DIR="${WEIGHT_DIR:-/home/data/weights/Qwen3-4B}"
if [ -z "${DATA_FILE}" ]; then
echo "Error: DATA_FILE environment variable is not set." >&2
exit 1
fi
LOG_FILE="${LOG_FILE:-/tmp/train_qwen3_4b_multi_agent_vllm.log}"

Comment on lines +43 to 46
for sibling in samples:
sibling.rollout_id = compact_rollout_id

random.shuffle(samples)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

If the custom multi-agent function custom_multi_agent_func returns None or an empty list, iterating over samples or calling random.shuffle(samples) will raise a TypeError. We should add a defensive check to ensure samples is not None or empty before processing.

Suggested change
for sibling in samples:
sibling.rollout_id = compact_rollout_id
random.shuffle(samples)
if samples:
for sibling in samples:
if sibling is not None:
sibling.rollout_id = compact_rollout_id
random.shuffle(samples)
else:
samples = []

@Windfeng8 Windfeng8 changed the title support multi-agent rollout pipeline [NPU] support multi-agent rollout pipeline Jun 30, 2026
Comment thread scripts/run-qwen3-4B-multi-agent-npu.sh Outdated

source "${SCRIPT_DIR}/models/qwen3-4B.sh"

python "${VIME_ROOT}/train.py" \

@floatlibai floatlibai Jun 30, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use ray to submit task instead of using python directly, just ref the gpu script.

@Windfeng8 Windfeng8 Jul 1, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Modified

Comment thread scripts/run-qwen3-4B-multi-agent-npu.sh Outdated

@floatlibai floatlibai Jun 30, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should put this script under examples/multi_agent folder

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Modified

--balance-data
)

EVAL_ARGS=(

@floatlibai floatlibai Jul 1, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

EVAL_ARGS and WANDB_ARGS can be removed since they are not used.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it can be reserved for future expansion.

@floatlibai

Copy link
Copy Markdown
Contributor

Could you add a short PR description covering what changes were made to the multi-agent example and why?

@Windfeng8

Copy link
Copy Markdown
Contributor Author

Could you add a short PR description covering what changes were made to the multi-agent example and why?

done

compact_rollout_id = (
sample.rollout_id
if sample.rollout_id is not None
else sample.index

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which rule/design determines the priority selection for this sample?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not a priority rule for selecting
the best candidate response. It only determines the shared rollout_id
for all sibling samples produced by one multi-agent rollout.

The intended precedence is:

  1. Use the existing sample.rollout_id when available.
  2. Otherwise use sample.index, which is the stable per-sample ID
    assigned by VIME.

All sibling samples share this ID so that the loss reducer treats them as
one rollout instead of over-counting them. group_index is a
prompt-level grouping key rather than a rollout identifier, and
id(sample) is process-local, so they should not be used as normal
fallbacks.

export MASTER_ADDR=${MASTER_ADDR:-"127.0.0.1"}
ray start --head --node-ip-address ${MASTER_ADDR} --num-gpus 8 --disable-usage-stats --dashboard-host=0.0.0.0 --dashboard-port=8265

python "${VIME_ROOT}/train.py" \

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please launch via ray job submit (with runtime-env-json for PYTHONPATH / Ascend env), matching scripts/run-qwen3-4B-npu.sh and examples/multi_agent/run-qwen3-30B-A3B-multi-agent.sh. Direct python train.py after ray start is inconsistent with the Ascend launch convention and was already requested in review.

Image

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@CalvinXKY CalvinXKY left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. clear the DCO with sign off commit.

Image

Windfeng8 and others added 5 commits July 22, 2026 14:26
Signed-off-by: Windfeng8 <523758380@qq.com>
Signed-off-by: Windfeng8 <523758380@qq.com>
Signed-off-by: wky <wky@example.com>
Signed-off-by: wky <wky@example.com>
Signed-off-by: Windfeng8 <523758380@qq.com>
@Windfeng8

Copy link
Copy Markdown
Contributor Author

LGTM. clear the DCO with sign off commit.

Image

done

@Meihan-chen

Meihan-chen commented Jul 22, 2026

Copy link
Copy Markdown
Collaborator

Please rebase your branch onto the latest to address the NPU-CI failures.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants