Spaces:
Runtime error
Runtime error
| # ============================== | |
| # Generate metadata.jsonl before training | |
| # Configure variables directly in this file. | |
| # Environment variable override: QWEN_IMAGE_TYPE (edit-2509, edit-2511, layered) | |
| # ============================== | |
| echo "[QIE] Torch version check" | |
| python - <<'PY' | |
| try: | |
| import torch | |
| print(f"[QIE] torch: {torch.__version__}") | |
| except Exception as e: | |
| print(f"[QIE] torch: not available ({e})") | |
| PY | |
| DATA_ROOT="/workspace/data" | |
| DATASET_NAME="" | |
| # Required inputs | |
| CAPTION="" | |
| IMAGE_FOLDER="image" | |
| # CONTROL_FOLDER_0="" | |
| # CONTROL_FOLDER_1="" | |
| # CONTROL_FOLDER_2="" | |
| # CONTROL_FOLDER_3="" | |
| # CONTROL_FOLDER_4="" | |
| # CONTROL_FOLDER_5="" | |
| # CONTROL_FOLDER_6="" | |
| # CONTROL_FOLDER_7="" | |
| RUN_NAME="${DATASET_NAME%/}" | |
| DATASET_DIR="${DATA_ROOT%/}/${DATASET_NAME}" | |
| OUTPUT_DIR_BASE="/workspace/auto/train_LoRA" | |
| DATASET_CONFIG="/workspace/auto/dataset_QIE.toml" | |
| OUTPUT_JSON="${DATASET_DIR%/}/metadata.jsonl" | |
| # Training hyperparameters (can be overridden by app) | |
| LEARNING_RATE="1e-3" | |
| NETWORK_DIM=4 | |
| SEED=42 | |
| MAX_TRAIN_EPOCHS=100 | |
| SAVE_EVERY_N_EPOCHS=10 | |
| # Model type (edit-2509, edit-2511, layered) | |
| MODEL_VERSION="${QWEN_IMAGE_TYPE:-edit-2509}" | |
| if [[ "$MODEL_VERSION" != "edit-2509" && "$MODEL_VERSION" != "edit-2511" && "$MODEL_VERSION" != "layered" ]]; then | |
| echo "[QIE] Unsupported QWEN_IMAGE_TYPE: $MODEL_VERSION, defaulting to edit-2509" | |
| MODEL_VERSION="edit-2509" | |
| fi | |
| if [[ "$MODEL_VERSION" == "layered" ]]; then | |
| DIT_FILENAME="qwen_image_layered_bf16.safetensors" | |
| VAE_FILENAME="qwen_image_layered_vae.safetensors" | |
| else | |
| DIT_SUFFIX="${MODEL_VERSION#edit-}" | |
| DIT_FILENAME="qwen_image_edit_${DIT_SUFFIX}_bf16.safetensors" | |
| VAE_FILENAME="diffusion_pytorch_model.safetensors" | |
| fi | |
| # Build control args from folder names with auto-detect fallback | |
| CONTROL_ARGS=() | |
| for i in {0..7}; do | |
| var="CONTROL_FOLDER_${i}" | |
| folder_name=${!var} | |
| cpath="" | |
| if [[ -n "$folder_name" ]]; then | |
| cpath="${DATASET_DIR%/}/$folder_name" | |
| elif [[ -d "${DATASET_DIR%/}/control_${i}" ]]; then | |
| cpath="${DATASET_DIR%/}/control_${i}" | |
| elif [[ $i -eq 0 && -d "${DATASET_DIR%/}/control" ]]; then | |
| # Special fallback: allow single control folder named "control" for control_0 | |
| cpath="${DATASET_DIR%/}/control" | |
| fi | |
| [[ -n "$cpath" ]] && CONTROL_ARGS+=("--control_dir_${i}" "$cpath") | |
| done | |
| # Sync dataset config's image_jsonl_file with OUTPUT_JSON if present | |
| if [[ -f "$DATASET_CONFIG" ]]; then | |
| python - "$DATASET_CONFIG" "$OUTPUT_JSON" <<'PY' | |
| import sys, re, os | |
| path, out = sys.argv[1], sys.argv[2] | |
| txt = open(path, 'r', encoding='utf-8').read() | |
| base = os.path.dirname(path) | |
| cache = os.path.join(base, 'cache').replace('\\\\', '/') | |
| # Update image_jsonl_file | |
| new = re.sub(r"(?m)^\s*image_jsonl_file\s*=.*$", f'image_jsonl_file = "{out}"', txt) | |
| if new == txt and 'image_jsonl_file' not in txt: | |
| new = txt.rstrip('\n') + f"\nimage_jsonl_file = \"{out}\"\n" | |
| # Update cache_directory to a writable folder under the config directory | |
| if re.search(r"(?m)^\s*cache_directory\s*=", new): | |
| new = re.sub(r"(?m)^\s*cache_directory\s*=.*$", f'cache_directory = "{cache}"', new) | |
| else: | |
| new = new.rstrip('\n') + f"\ncache_directory = \"{cache}\"\n" | |
| open(path, 'w', encoding='utf-8').write(new) | |
| print("[QIE] Updated {}: image_jsonl_file -> {}".format(path, out)) | |
| print("[QIE] Updated {}: cache_directory -> {}".format(path, cache)) | |
| PY | |
| mkdir -p "$(dirname "$DATASET_CONFIG")/cache" | |
| else | |
| echo "[QIE] WARN: Dataset config not found at $DATASET_CONFIG. Ensure it points to $OUTPUT_JSON" | |
| fi | |
| cd /workspace/auto | |
| if [[ "$MODEL_VERSION" == "layered" ]]; then | |
| echo "[QIE] Layered mode: skip metadata generation (expects prebuilt JSONL)." | |
| else | |
| echo "[QIE] Generating metadata: $OUTPUT_JSON" | |
| python create_image_caption_json.py \ | |
| -i "${DATASET_DIR%/}/${IMAGE_FOLDER}" \ | |
| -c "$CAPTION" \ | |
| -o "$OUTPUT_JSON" \ | |
| --image-dir "${DATASET_DIR%/}/${IMAGE_FOLDER}" \ | |
| "${CONTROL_ARGS[@]}" | |
| fi | |
| cd /musubi-tuner | |
| python qwen_image_cache_latents.py \ | |
| --dataset_config "$DATASET_CONFIG" \ | |
| --vae "/workspace/Qwen-Image_models/vae/${VAE_FILENAME}" \ | |
| --model_version "$MODEL_VERSION" \ | |
| --vae_spatial_tile_sample_min_size 16384 | |
| python qwen_image_cache_text_encoder_outputs.py \ | |
| --dataset_config "$DATASET_CONFIG" \ | |
| --text_encoder "/workspace/Qwen-Image_models/text_encoder/qwen_2.5_vl_7b.safetensors" \ | |
| --model_version "$MODEL_VERSION" \ | |
| --batch_size 16 | |
| accelerate launch src/musubi_tuner/qwen_image_train_network.py \ | |
| --model_version "$MODEL_VERSION" \ | |
| --dit "/workspace/Qwen-Image_models/dit/${DIT_FILENAME}" \ | |
| --vae "/workspace/Qwen-Image_models/vae/${VAE_FILENAME}" \ | |
| --text_encoder "/workspace/Qwen-Image_models/text_encoder/qwen_2.5_vl_7b.safetensors" \ | |
| --dataset_config "$DATASET_CONFIG" \ | |
| --mixed_precision bf16 \ | |
| --sdpa \ | |
| --timestep_sampling shift \ | |
| --weighting_scheme none \ | |
| --discrete_flow_shift 2.0 \ | |
| --optimizer_type adamw8bit \ | |
| --learning_rate "$LEARNING_RATE" \ | |
| --gradient_checkpointing \ | |
| --max_data_loader_n_workers 2 \ | |
| --persistent_data_loader_workers \ | |
| --network_module networks.lora_qwen_image \ | |
| --network_dim "$NETWORK_DIM" \ | |
| --max_train_epochs "$MAX_TRAIN_EPOCHS" \ | |
| --save_every_n_epochs "$SAVE_EVERY_N_EPOCHS" \ | |
| --seed "$SEED" \ | |
| --output_dir "${OUTPUT_DIR_BASE}/${RUN_NAME}" \ | |
| --output_name "${RUN_NAME}" \ | |
| --ddp_gradient_as_bucket_view \ | |
| --ddp_static_graph | |