项目文件夹

文件
wehub-resource-sync 85742ab165
Deploy Documentation / deploy (push) Has been cancelled
CPU Test / Test (Utilities, legacy, Python 3.10) (push) Has been cancelled
CPU Test / Test (LLM proxy, stable, Python 3.11) (push) Has been cancelled
CPU Test / Test (Others, stable, Python 3.11) (push) Has been cancelled
CPU Test / Test (Store, stable, Python 3.11) (push) Has been cancelled
CPU Test / Test (Utilities, stable, Python 3.11) (push) Has been cancelled
CPU Test / Test (Weave, stable, Python 3.11) (push) Has been cancelled
CPU Test / Test (AgentOps, stable, Python 3.12) (push) Has been cancelled
CPU Test / Test (LLM proxy, stable, Python 3.12) (push) Has been cancelled
CPU Test / Test (Others, stable, Python 3.12) (push) Has been cancelled
CPU Test / Test (Weave, latest, Python 3.13) (push) Has been cancelled
Dashboard / Chromatic (push) Has been cancelled
CPU Test / Lint - fast (push) Has been cancelled
CPU Test / Lint - next (push) Has been cancelled
CPU Test / Lint - slow (push) Has been cancelled
CPU Test / Lint - JavaScript (push) Has been cancelled
CPU Test / Build documentation (push) Has been cancelled
CPU Test / Test (AgentOps, legacy, Python 3.10) (push) Has been cancelled
CPU Test / Test (LLM proxy, legacy, Python 3.10) (push) Has been cancelled
CPU Test / Test (Others, legacy, Python 3.10) (push) Has been cancelled
CPU Test / Test (Store, legacy, Python 3.10) (push) Has been cancelled
CPU Test / Test (Weave, legacy, Python 3.10) (push) Has been cancelled
CPU Test / Test (AgentOps, stable, Python 3.11) (push) Has been cancelled
CPU Test / Test (Store, stable, Python 3.12) (push) Has been cancelled
CPU Test / Test (Utilities, stable, Python 3.12) (push) Has been cancelled
CPU Test / Test (Weave, stable, Python 3.12) (push) Has been cancelled
CPU Test / Test (AgentOps, latest, Python 3.13) (push) Has been cancelled
CPU Test / Test (LLM proxy, latest, Python 3.13) (push) Has been cancelled
CPU Test / Test (Others, latest, Python 3.13) (push) Has been cancelled
CPU Test / Test (Store, latest, Python 3.13) (push) Has been cancelled
CPU Test / Test (Utilities, latest, Python 3.13) (push) Has been cancelled
CPU Test / Test (JavaScript) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:44:17 +08:00

329 行
12 KiB
Python

# Copyright (c) Microsoft. All rights reserved.
"""The training helper script for Calc-X agent with VERL algorithm.
Example usage:
```bash
python train_calc_agent.py --train-file data/train.parquet --val-file data/test.parquet --llm-proxy
```
To use an external store, run a store server first:
```bash
agl store --port 9999
```
Then run the training script with the external store address:
```bash
AGL_MANAGED_STORE=0 python train_calc_agent.py --external-store-address http://localhost:9999
```
Alternatively, you can also run algorithms and runners separately if needed:
```bash
AGL_MANAGED_STORE=0 AGL_CURRENT_ROLE=algorithm python train_calc_agent.py --external-store-address http://localhost:9999
AGL_MANAGED_STORE=0 AGL_CURRENT_ROLE=runner python train_calc_agent.py --external-store-address http://localhost:9999
```
"""
import argparse
import os
import uuid
from datetime import datetime
from typing import Any, Dict, Optional, cast
from calc_agent import MathProblem, calc_agent
from datasets import Dataset as HuggingFaceDataset
import agentlightning as agl
from agentlightning.env_var import LightningEnvVar, resolve_bool_env_var, resolve_str_env_var
def verl_default_config() -> Dict[str, Any]:
config = {
"algorithm": {
"adv_estimator": "grpo",
"use_kl_in_reward": False,
},
"data": {
"train_batch_size": 32,
"max_prompt_length": 4096,
"max_response_length": 2048,
},
"actor_rollout_ref": {
"rollout": {
"tensor_model_parallel_size": 1,
"n": 4,
"log_prob_micro_batch_size_per_gpu": 4,
"multi_turn": {"format": "hermes"},
"name": "vllm",
"gpu_memory_utilization": 0.6,
"engine_kwargs": {
"vllm": {
"enable_auto_tool_choice": True,
"tool_call_parser": "hermes",
}
},
},
"actor": {
"ppo_mini_batch_size": 32,
"ppo_micro_batch_size_per_gpu": 4,
"optim": {"lr": 1e-6},
"use_kl_loss": False,
"kl_loss_coef": 0.0,
"entropy_coeff": 0,
"clip_ratio_low": 0.2,
"clip_ratio_high": 0.3,
"fsdp_config": {
"param_offload": True,
"optimizer_offload": True,
},
},
"ref": {
"log_prob_micro_batch_size_per_gpu": 8,
"fsdp_config": {"param_offload": True},
},
"model": {
"path": "Qwen/Qwen2.5-1.5B-Instruct",
"use_remove_padding": True,
"enable_gradient_checkpointing": True,
},
},
"trainer": {
"n_gpus_per_node": 1,
"val_before_train": True,
"critic_warmup": 0,
"logger": ["console", "wandb"],
"project_name": "AgentLightning",
"experiment_name": "calc_x",
"nnodes": 1,
"save_freq": 64,
"test_freq": 32,
"total_epochs": 2,
},
}
return config
def train(
*,
train_file: str,
val_file: str,
model: Optional[str],
llm_proxy: bool,
ci: bool,
ci_fast: bool,
n_runners: int,
external_store_address: str,
lora: bool,
lora_rank: int,
lora_adapter_path: Optional[str],
trajectory_level: bool = False,
weave: bool,
mongo_uri: Optional[str],
):
"""The training entrypoint function for Calc-X agent with VERL algorithm.
Args:
train_file: The path to the training parquet file.
val_file: The path to the validation parquet file.
model: The HF model id or path to override the default model.
llm_proxy: Whether to enable LLM Proxy tracing/adapter.
ci: Whether to run a minimal CI-style training loop.
n_runners: The number of runners for the Trainer.
ci_fast: Whether to cap the training loop at a single step (implies CI toggles).
external_store_address: Connects to an external store instead of creating a new one in memory.
lora: Whether to enable LoRA training.
lora_rank: LoRA rank to use when LoRA is enabled.
lora_adapter_path: Optional path to a pre-trained LoRA adapter to load.
trajectory_level: Whether to enable trajectory level in trace aggregator.
weave: Whether to enable Weave tracing.
mongo_uri: MongoDB URI to use for the store.
"""
# Load datasets (respect CLI file paths)
train_dataset = cast(agl.Dataset[MathProblem], HuggingFaceDataset.from_parquet(train_file).to_list()) # type: ignore
val_dataset = cast(agl.Dataset[MathProblem], HuggingFaceDataset.from_parquet(val_file).to_list()) # type: ignore
print("First 5 rows of train dataset:")
print(train_dataset[:5]) # type: ignore
print("First 5 rows of val dataset:")
print(val_dataset[:5]) # type: ignore
config = verl_default_config()
if model:
config["actor_rollout_ref"]["model"]["path"] = model
# Enable LoRA configuration if requested
if lora:
config["actor_rollout_ref"]["model"]["lora_rank"] = lora_rank
print(f"LoRA enabled: lora_rank={lora_rank}")
if lora_adapter_path:
config["actor_rollout_ref"]["model"]["lora_adapter_path"] = lora_adapter_path
print(f"Loading LoRA adapter from: {lora_adapter_path}")
print("LoRA configuration will trigger verl to set ref_in_actor=True (LoRA mode)")
if trajectory_level:
config["agentlightning"] = {
"trace_aggregator": {
"level": "trajectory",
"trajectory_max_prompt_length": 2048,
"trajectory_max_response_length": 8192,
}
}
print("Trajectory level enabled in trace aggregator.")
# CI toggle keeps everything else the same but you can tweak the lightweight bits here if desired
if ci or ci_fast:
# Config the experiment name and project name so that they are available to CI
timestamp = datetime.now().strftime("%Y%m%d%H%M%S")
random_suffix = uuid.uuid4().hex[:8]
EXPERIMENT_NAME = f"calc_x_{timestamp}_{random_suffix}"
PROJECT_NAME = "AgentLightningCI"
# Skip this step if AGL_CURRENT_ROLE is runner
agl_current_role = resolve_str_env_var(LightningEnvVar.AGL_CURRENT_ROLE)
if agl_current_role != "runner":
# Simulate writing to $GITHUB_OUTPUT if it’s set
github_output = os.getenv("GITHUB_OUTPUT")
if github_output:
with open(github_output, "a") as f:
f.write(f"project_name={PROJECT_NAME}\n")
f.write(f"run_name={EXPERIMENT_NAME}\n")
print("Set environment variables:")
print(f"PROJECT_NAME={PROJECT_NAME}")
print(f"EXPERIMENT_NAME={EXPERIMENT_NAME}")
# Keep it tiny/light without adding new knobs
config["actor_rollout_ref"]["rollout"]["gpu_memory_utilization"] = 0.8
config["trainer"]["total_epochs"] = 1
config["trainer"]["total_training_steps"] = 20
config["trainer"]["test_freq"] = 20
config["trainer"]["experiment_name"] = EXPERIMENT_NAME
config["trainer"]["project_name"] = PROJECT_NAME
config["trainer"].pop("save_freq", None)
if ci_fast:
# Extra fast CI toggle for testing purposes.
config["actor_rollout_ref"]["rollout"]["gpu_memory_utilization"] = 0.6
config["trainer"]["total_training_steps"] = 1
config["trainer"]["test_freq"] = 1
algorithm = agl.VERL(config)
if external_store_address:
store: Optional[agl.LightningStore] = agl.LightningStoreClient(external_store_address)
elif mongo_uri:
from agentlightning.store.mongo import MongoLightningStore
store = MongoLightningStore(mongo_uri=mongo_uri)
else:
store = None
if llm_proxy:
tracer = agl.OtelTracer() # dummy tracer for LLM Proxy
adapter = agl.LlmProxyTraceToTriplet()
trainer = agl.Trainer(algorithm=algorithm, n_runners=n_runners, store=store, tracer=tracer, adapter=adapter)
elif weave:
# NOTE: Don't import WeaveTracer at the module level or in __init__.py files.
# Always import it lazily/conditionally (behind a feature flag) to avoid interfering
# with other libraries like LiteLLM/OpenTelemetry when weave is not explicitly enabled.
from agentlightning.tracer.weave import WeaveTracer
tracer = WeaveTracer()
trainer = agl.Trainer(algorithm=algorithm, n_runners=n_runners, store=store, tracer=tracer)
else:
trainer = agl.Trainer(algorithm=algorithm, n_runners=n_runners, store=store)
trainer.fit(calc_agent, train_dataset, val_dataset=val_dataset)
def main():
parser = argparse.ArgumentParser(description="Train a math calc agent with Agent-lightning + VERL.")
parser.add_argument("--train-file", type=str, default="data/train.parquet", help="Path to train parquet file")
parser.add_argument("--val-file", type=str, default="data/test.parquet", help="Path to val parquet file")
parser.add_argument("--model", type=str, default=None, help="HF model id or path (optional)")
parser.add_argument("--llm-proxy", action="store_true", help="Enable LLM Proxy tracing/adapter")
parser.add_argument("--weave", action="store_true", help="Enable Weave tracing")
parser.add_argument("--ci", action="store_true", help="Run a minimal CI-style training loop")
parser.add_argument(
"--ci-fast", action="store_true", help="Limit the training loop to a single step (implies --ci)"
)
parser.add_argument("--n-runners", type=int, default=10, help="Number of runners for Trainer")
parser.add_argument(
"--external-store-address",
type=str,
default="",
help="Connect to an external store instead of creating a new one in memory",
)
parser.add_argument("--debug", action="store_true", help="Enable debug logging")
parser.add_argument(
"--lora",
action="store_true",
help="Enable LoRA training. When enabled, the reference policy is computed by the actor rollout worker.",
)
parser.add_argument(
"--lora-rank",
type=int,
default=32,
help="LoRA rank to use when --lora is enabled (default: 32)",
)
parser.add_argument(
"--lora-adapter-path",
type=str,
default=None,
help="Optional path to a pre-trained LoRA adapter to load when --lora is enabled",
)
parser.add_argument(
"--trajectory-level",
action="store_true",
help="Enable trajectory level in trace aggregator.",
)
parser.add_argument(
"--mongo-uri",
type=str,
default=None,
help="MongoDB URI to use for the store.",
)
args = parser.parse_args()
if args.external_store_address:
print(f"Connecting to external store at: {args.external_store_address}")
if resolve_bool_env_var(LightningEnvVar.AGL_MANAGED_STORE, fallback=True):
raise ValueError(
"When using an external store, please set the environment variable AGL_MANAGED_STORE=0. "
"Otherwise the trainer will still try to manage the store lifecycle for you!"
)
if args.ci_fast:
args.ci = True
agl.setup_logging("DEBUG" if args.debug else "INFO")
train(
train_file=args.train_file,
val_file=args.val_file,
model=args.model,
llm_proxy=args.llm_proxy,
ci=args.ci,
ci_fast=args.ci_fast,
n_runners=args.n_runners,
external_store_address=args.external_store_address,
lora=args.lora,
lora_rank=args.lora_rank,
lora_adapter_path=args.lora_adapter_path,
trajectory_level=args.trajectory_level,
weave=args.weave,
mongo_uri=args.mongo_uri,
)
if __name__ == "__main__":
main()