# Single-node managed full stack for Ascend NPU, launched with one
# `specforge train` command. Device ordinals are injected via
# ASCEND_RT_VISIBLE_DEVICES.
model:
  target_model_path: "Qwen/Qwen3.5-4B"
  draft_model_config: "configs/qwen3.5-4b-dflash.json"
  target_backend: sglang
  trust_remote_code: true
  embedding_key: "model.language_model.embed_tokens.weight"
  torch_dtype: "bfloat16"
  sglang_attention_backend: ascend
data:
  train_data_path: "./cache/dataset/train_regen.jsonl"
  max_length: 3072
  chat_template: "qwen3.5"
  build_dataset_num_proc: 32
  cache_dir: "./cache"
training:
  strategy: "dflash"
  num_epochs: 10
  max_steps: 10000
  batch_size: 2
  accumulation_steps: 4
  learning_rate: 0.0006
  warmup_ratio: 0.04
  max_grad_norm: 1
  attention_backend: "sdpa"
  # If OOM occurs on low-memory NPU devices, retry with a smaller num_anchors value.
  num_anchors: 512
  loss_decay_gamma: 7
  save_interval: 10000
  log_interval: 50
  dist_timeout: 30
  seed: 42
tracking:
  report_to: "tensorboard"
run_id: "qwen3.5-4b-dflash-npu-managed"
output_dir: "./outputs/qwen3.5-4b-dflash-npu-managed"

deployment:
  mode: disaggregated
  trainer:
    nnodes: 1
    nproc_per_node: 14
  disaggregated:
    control_dir: outputs/qwen3.5-4b-dflash-npu-managed/control
    consumer_state_dir: outputs/qwen3.5-4b-dflash-npu-managed/consumer-state
    backend: mooncake
    managed_local:
      # 16-card A3 layout: capture server owns device 0, trainer owns 2-15.
      # On 8-card hosts use devices 1-7 with trainer.nproc_per_node: 7.
      trainer_cuda_visible_devices:
        ["2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15"]
      mooncake:
        # Host segment mounted by the capture-server sink for feature storage.
        # 16 GiB fits a 64GB-card host next to the target model and KV cache.
        global_segment_size_bytes: 17179869184
      capture_servers:
        - port: 30000
          cuda_visible_devices: ["0"]
          tp_size: 1
