From d4823eb10eede67e3eacc5b2a69b10ab88b0633a Mon Sep 17 00:00:00 2001 From: shubham singhal Date: Mon, 28 Sep 2026 09:17:33 +0530 Subject: [PATCH] [xpu] add Intel XPU support to test infrastructure and runs_on markers (#10835) Co-authored-by: Claude Opus 5 --- tests/conftest.py | 4 + tests/data/processor/test_feedback.py | 2 +- tests/data/processor/test_pairwise.py | 2 +- tests/data/processor/test_processor_utils.py | 2 +- tests/data/processor/test_supervised.py | 8 +- tests/data/processor/test_unsupervised.py | 2 +- tests/data/test_collator.py | 8 +- tests/data/test_converter.py | 4 +- tests/data/test_formatter.py | 84 +++++++++---------- tests/data/test_loader.py | 6 +- tests/data/test_mm_plugin.py | 32 +++---- tests/data/test_template.py | 40 ++++----- tests/e2e/test_chat.py | 4 +- tests/e2e/test_train.py | 4 +- tests/eval/test_eval_template.py | 4 +- tests_v1/accelerator/test_interface.py | 2 +- tests_v1/conftest.py | 4 + .../plugins/model_plugins/test_ulysses_cp.py | 2 +- tests_v1/sampler/test_cli_sampler.py | 2 +- tests_v1/trainers/test_fsdp2_dpo_trainer.py | 2 +- tests_v1/trainers/test_fsdp2_sft_trainer.py | 2 +- 21 files changed, 114 insertions(+), 106 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 69403937c..dc1302df1 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -78,6 +78,8 @@ def _get_visible_devices_env() -> str | None: return "CUDA_VISIBLE_DEVICES" elif CURRENT_DEVICE == "npu": return "ASCEND_RT_VISIBLE_DEVICES" + elif CURRENT_DEVICE == "xpu": + return "ZE_AFFINITY_MASK" else: return None @@ -160,6 +162,8 @@ def _manage_distributed_env(request: FixtureRequest, monkeypatch: MonkeyPatch) - monkeypatch.setattr(torch.cuda, "device_count", lambda: 1) elif CURRENT_DEVICE == "npu": monkeypatch.setattr(torch.npu, "device_count", lambda: 1) + elif CURRENT_DEVICE == "xpu": + monkeypatch.setattr(torch.xpu, "device_count", lambda: 1) @pytest.fixture diff --git a/tests/data/processor/test_feedback.py b/tests/data/processor/test_feedback.py index f2c69d08a..f384d8dac 100644 --- a/tests/data/processor/test_feedback.py +++ b/tests/data/processor/test_feedback.py @@ -43,7 +43,7 @@ TRAIN_ARGS = { } -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) @pytest.mark.parametrize("num_samples", [16]) def test_feedback_data(num_samples: int): train_dataset = load_dataset_module(**TRAIN_ARGS)["train_dataset"] diff --git a/tests/data/processor/test_pairwise.py b/tests/data/processor/test_pairwise.py index 17d560984..628c25c63 100644 --- a/tests/data/processor/test_pairwise.py +++ b/tests/data/processor/test_pairwise.py @@ -52,7 +52,7 @@ def _convert_sharegpt_to_openai(messages: list[dict[str, str]]) -> list[dict[str return new_messages -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) @pytest.mark.parametrize("num_samples", [16]) def test_pairwise_data(num_samples: int): train_dataset = load_dataset_module(**TRAIN_ARGS)["train_dataset"] diff --git a/tests/data/processor/test_processor_utils.py b/tests/data/processor/test_processor_utils.py index a2a3b7ebe..97d18d4b3 100644 --- a/tests/data/processor/test_processor_utils.py +++ b/tests/data/processor/test_processor_utils.py @@ -18,7 +18,7 @@ import pytest from llamafactory.data.processor.processor_utils import infer_seqlen -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) @pytest.mark.parametrize( "test_input,test_output", [ diff --git a/tests/data/processor/test_supervised.py b/tests/data/processor/test_supervised.py index f515852e1..edc7f75e3 100644 --- a/tests/data/processor/test_supervised.py +++ b/tests/data/processor/test_supervised.py @@ -43,7 +43,7 @@ TRAIN_ARGS = { } -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) @pytest.mark.parametrize("num_samples", [16]) def test_supervised_single_turn(num_samples: int): train_dataset = load_dataset_module(dataset_dir="ONLINE", dataset=TINY_DATA, **TRAIN_ARGS)["train_dataset"] @@ -72,7 +72,7 @@ def test_supervised_single_turn(num_samples: int): assert train_dataset["labels"][index] == ref_label_ids -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) @pytest.mark.parametrize("num_samples", [8]) def test_supervised_multi_turn(num_samples: int): train_dataset = load_dataset_module(dataset_dir="REMOTE:" + DEMO_DATA, dataset="system_chat", **TRAIN_ARGS)[ @@ -90,7 +90,7 @@ def test_supervised_multi_turn(num_samples: int): assert train_dataset["input_ids"][index] == ref_input_ids -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) @pytest.mark.parametrize("num_samples", [4]) def test_supervised_train_on_prompt(num_samples: int): train_dataset = load_dataset_module( @@ -108,7 +108,7 @@ def test_supervised_train_on_prompt(num_samples: int): assert train_dataset["labels"][index] == ref_input_ids -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) @pytest.mark.parametrize("num_samples", [4]) def test_supervised_mask_history(num_samples: int): train_dataset = load_dataset_module( diff --git a/tests/data/processor/test_unsupervised.py b/tests/data/processor/test_unsupervised.py index 2d06219fc..ef527ad2e 100644 --- a/tests/data/processor/test_unsupervised.py +++ b/tests/data/processor/test_unsupervised.py @@ -47,7 +47,7 @@ TRAIN_ARGS = { } -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) @pytest.mark.parametrize("num_samples", [16]) def test_unsupervised_data(num_samples: int): train_dataset = load_dataset_module(**TRAIN_ARGS)["train_dataset"] diff --git a/tests/data/test_collator.py b/tests/data/test_collator.py index 0cc7d7bd4..4c801fde6 100644 --- a/tests/data/test_collator.py +++ b/tests/data/test_collator.py @@ -32,7 +32,7 @@ from llamafactory.model import load_tokenizer TINY_LLAMA3 = os.getenv("TINY_LLAMA3", "llamafactory/tiny-random-Llama-3") -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) def test_base_collator(): model_args, data_args, *_ = get_infer_args({"model_name_or_path": TINY_LLAMA3, "template": "default"}) tokenizer_module = load_tokenizer(model_args) @@ -76,7 +76,7 @@ def test_base_collator(): assert batch_input[k].eq(torch.tensor(expected_input[k])).all() -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) def test_multimodal_collator(): model_args, data_args, *_ = get_infer_args( {"model_name_or_path": "Qwen/Qwen2-VL-2B-Instruct", "template": "qwen2_vl"} @@ -270,7 +270,7 @@ def _get_expected_position_ids( return torch.cat(all_position_ids, dim=-1) -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) def test_multimodal_collator_with_packing(): model_args, data_args, *_ = get_infer_args( {"model_name_or_path": "Qwen/Qwen2-VL-2B-Instruct", "template": "qwen2_vl"} @@ -322,7 +322,7 @@ def test_multimodal_collator_with_packing(): assert batch_input["position_ids"][1:, :, :valid_len].eq(expected_position_ids).all() -@pytest.mark.runs_on(["cpu"]) +@pytest.mark.runs_on(["cpu", "xpu"]) def test_4d_attention_mask(): o = 0.0 x = torch.finfo(torch.float16).min diff --git a/tests/data/test_converter.py b/tests/data/test_converter.py index 6b411aed5..0ceb5a661 100644 --- a/tests/data/test_converter.py +++ b/tests/data/test_converter.py @@ -20,7 +20,7 @@ from llamafactory.data.parser import DatasetAttr from llamafactory.hparams import DataArguments -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) def test_alpaca_converter(): dataset_attr = DatasetAttr("hf_hub", "llamafactory/tiny-supervised-dataset") data_args = DataArguments() @@ -41,7 +41,7 @@ def test_alpaca_converter(): } -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) def test_sharegpt_converter(): dataset_attr = DatasetAttr("hf_hub", "llamafactory/tiny-supervised-dataset") data_args = DataArguments() diff --git a/tests/data/test_formatter.py b/tests/data/test_formatter.py index 8a9748c5b..1d9e9ef2e 100644 --- a/tests/data/test_formatter.py +++ b/tests/data/test_formatter.py @@ -38,19 +38,19 @@ TOOLS = [ ] -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) def test_empty_formatter(): formatter = EmptyFormatter(slots=["\n"]) assert formatter.apply() == ["\n"] -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) def test_string_formatter(): formatter = StringFormatter(slots=["", "Human: {{content}}\nAssistant:"]) assert formatter.apply(content="Hi") == ["", "Human: Hi\nAssistant:"] -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) def test_function_formatter(): formatter = FunctionFormatter(slots=["{{content}}", ""], tool_format="default") tool_calls = json.dumps(FUNCTION) @@ -60,7 +60,7 @@ def test_function_formatter(): ] -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) def test_multi_function_formatter(): formatter = FunctionFormatter(slots=["{{content}}", ""], tool_format="default") tool_calls = json.dumps([FUNCTION] * 2) @@ -71,7 +71,7 @@ def test_multi_function_formatter(): ] -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) def test_default_tool_formatter(): formatter = ToolFormatter(tool_format="default") assert formatter.apply(content=json.dumps(TOOLS)) == [ @@ -90,14 +90,14 @@ def test_default_tool_formatter(): ] -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) def test_default_tool_extractor(): formatter = ToolFormatter(tool_format="default") result = """Action: test_tool\nAction Input: {"foo": "bar", "size": 10}""" assert formatter.extract(result) == [("test_tool", """{"foo": "bar", "size": 10}""")] -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) def test_default_multi_tool_extractor(): formatter = ToolFormatter(tool_format="default") result = ( @@ -110,14 +110,14 @@ def test_default_multi_tool_extractor(): ] -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) def test_glm4_function_formatter(): formatter = FunctionFormatter(slots=["{{content}}"], tool_format="glm4") tool_calls = json.dumps(FUNCTION) assert formatter.apply(content=tool_calls) == ["""tool_name\n{"foo": "bar", "size": 10}"""] -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) def test_glm4_tool_formatter(): formatter = ToolFormatter(tool_format="glm4") assert formatter.apply(content=json.dumps(TOOLS)) == [ @@ -128,14 +128,14 @@ def test_glm4_tool_formatter(): ] -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) def test_glm4_tool_extractor(): formatter = ToolFormatter(tool_format="glm4") result = """test_tool\n{"foo": "bar", "size": 10}\n""" assert formatter.extract(result) == [("test_tool", """{"foo": "bar", "size": 10}""")] -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) def test_llama3_function_formatter(): formatter = FunctionFormatter(slots=["{{content}}<|eot_id|>"], tool_format="llama3") tool_calls = json.dumps(FUNCTION) @@ -144,7 +144,7 @@ def test_llama3_function_formatter(): ] -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) def test_llama3_multi_function_formatter(): formatter = FunctionFormatter(slots=["{{content}}<|eot_id|>"], tool_format="llama3") tool_calls = json.dumps([FUNCTION] * 2) @@ -155,7 +155,7 @@ def test_llama3_multi_function_formatter(): ] -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) def test_llama3_tool_formatter(): formatter = ToolFormatter(tool_format="llama3") date = datetime.now().strftime("%d %b %Y") @@ -169,14 +169,14 @@ def test_llama3_tool_formatter(): ] -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) def test_llama3_tool_extractor(): formatter = ToolFormatter(tool_format="llama3") result = """{"name": "test_tool", "parameters": {"foo": "bar", "size": 10}}\n""" assert formatter.extract(result) == [("test_tool", """{"foo": "bar", "size": 10}""")] -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) def test_llama3_multi_tool_extractor(): formatter = ToolFormatter(tool_format="llama3") result = ( @@ -189,7 +189,7 @@ def test_llama3_multi_tool_extractor(): ] -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) def test_mistral_function_formatter(): formatter = FunctionFormatter(slots=["[TOOL_CALLS] {{content}}", ""], tool_format="mistral") tool_calls = json.dumps(FUNCTION) @@ -199,7 +199,7 @@ def test_mistral_function_formatter(): ] -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) def test_mistral_multi_function_formatter(): formatter = FunctionFormatter(slots=["[TOOL_CALLS] {{content}}", ""], tool_format="mistral") tool_calls = json.dumps([FUNCTION] * 2) @@ -211,7 +211,7 @@ def test_mistral_multi_function_formatter(): ] -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) def test_mistral_tool_formatter(): formatter = ToolFormatter(tool_format="mistral") wrapped_tool = {"type": "function", "function": TOOLS[0]} @@ -220,14 +220,14 @@ def test_mistral_tool_formatter(): ] -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) def test_mistral_tool_extractor(): formatter = ToolFormatter(tool_format="mistral") result = """{"name": "test_tool", "arguments": {"foo": "bar", "size": 10}}""" assert formatter.extract(result) == [("test_tool", """{"foo": "bar", "size": 10}""")] -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) def test_mistral_multi_tool_extractor(): formatter = ToolFormatter(tool_format="mistral") result = ( @@ -240,7 +240,7 @@ def test_mistral_multi_tool_extractor(): ] -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) def test_qwen_function_formatter(): formatter = FunctionFormatter(slots=["{{content}}<|im_end|>\n"], tool_format="qwen") tool_calls = json.dumps(FUNCTION) @@ -249,7 +249,7 @@ def test_qwen_function_formatter(): ] -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) def test_qwen_multi_function_formatter(): formatter = FunctionFormatter(slots=["{{content}}<|im_end|>\n"], tool_format="qwen") tool_calls = json.dumps([FUNCTION] * 2) @@ -260,7 +260,7 @@ def test_qwen_multi_function_formatter(): ] -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) def test_qwen_tool_formatter(): formatter = ToolFormatter(tool_format="qwen") wrapped_tool = {"type": "function", "function": TOOLS[0]} @@ -274,14 +274,14 @@ def test_qwen_tool_formatter(): ] -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) def test_qwen_tool_extractor(): formatter = ToolFormatter(tool_format="qwen") result = """\n{"name": "test_tool", "arguments": {"foo": "bar", "size": 10}}\n""" assert formatter.extract(result) == [("test_tool", """{"foo": "bar", "size": 10}""")] -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) def test_qwen38_tool_formatter(): formatter = ToolFormatter(tool_format="qwen3_8") wrapped_tool = {"type": "function", "function": TOOLS[0]} @@ -289,7 +289,7 @@ def test_qwen38_tool_formatter(): assert json.dumps(wrapped_tool, ensure_ascii=False) in output -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) def test_qwen_multi_tool_extractor(): formatter = ToolFormatter(tool_format="qwen") result = ( @@ -302,7 +302,7 @@ def test_qwen_multi_tool_extractor(): ] -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) def test_lfm2_function_formatter(): formatter = FunctionFormatter(slots=["{{content}}<|im_end|>\n"], tool_format="lfm2") tool_calls = json.dumps(FUNCTION) @@ -311,7 +311,7 @@ def test_lfm2_function_formatter(): ] -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) def test_lfm2_multi_function_formatter(): formatter = FunctionFormatter(slots=["{{content}}<|im_end|>\n"], tool_format="lfm2") tool_calls = json.dumps([FUNCTION] * 2) @@ -321,7 +321,7 @@ def test_lfm2_multi_function_formatter(): ] -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) def test_lfm2_tool_formatter(): formatter = ToolFormatter(tool_format="lfm2") assert formatter.apply(content=json.dumps(TOOLS)) == [ @@ -329,14 +329,14 @@ def test_lfm2_tool_formatter(): ] -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) def test_lfm2_tool_extractor(): formatter = ToolFormatter(tool_format="lfm2") result = """<|tool_call_start|>[test_tool(foo="bar", size=10)]<|tool_call_end|>""" assert formatter.extract(result) == [("test_tool", """{"foo": "bar", "size": 10}""")] -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) def test_lfm2_multi_tool_extractor(): formatter = ToolFormatter(tool_format="lfm2") result = """<|tool_call_start|>[test_tool(foo="bar", size=10), another_tool(foo="job", size=2)]<|tool_call_end|>""" @@ -346,7 +346,7 @@ def test_lfm2_multi_tool_extractor(): ] -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) def test_lfm2_tool_extractor_with_nested_dict(): formatter = ToolFormatter(tool_format="lfm2") result = """<|tool_call_start|>[search(query="test", options={"limit": 10, "offset": 0})]<|tool_call_end|>""" @@ -358,7 +358,7 @@ def test_lfm2_tool_extractor_with_nested_dict(): assert args["options"] == {"limit": 10, "offset": 0} -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) def test_lfm2_tool_extractor_with_list_arg(): formatter = ToolFormatter(tool_format="lfm2") result = """<|tool_call_start|>[batch_process(items=[1, 2, 3], enabled=True)]<|tool_call_end|>""" @@ -370,7 +370,7 @@ def test_lfm2_tool_extractor_with_list_arg(): assert args["enabled"] is True -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) def test_lfm2_tool_extractor_no_match(): formatter = ToolFormatter(tool_format="lfm2") result = "This is a regular response without tool calls." @@ -378,7 +378,7 @@ def test_lfm2_tool_extractor_no_match(): assert extracted == result -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) def test_lfm2_tool_round_trip(): formatter = FunctionFormatter(slots=["{{content}}"], tool_format="lfm2") tool_formatter = ToolFormatter(tool_format="lfm2") @@ -390,7 +390,7 @@ def test_lfm2_tool_round_trip(): assert json.loads(extracted[0][1]) == original["arguments"] -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) def test_minicpm5_function_formatter(): formatter = FunctionFormatter(slots=["{{content}}<|im_end|>\n"], tool_format="minicpm5") tool_calls = json.dumps(FUNCTION) @@ -399,7 +399,7 @@ def test_minicpm5_function_formatter(): ] -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) def test_minicpm5_multi_function_formatter(): formatter = FunctionFormatter(slots=["{{content}}<|im_end|>\n"], tool_format="minicpm5") tool_calls = json.dumps([FUNCTION] * 2) @@ -411,7 +411,7 @@ def test_minicpm5_multi_function_formatter(): ] -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) def test_minicpm5_tool_formatter(): formatter = ToolFormatter(tool_format="minicpm5") wrapped = json.dumps({"type": "function", "function": TOOLS[0]}, ensure_ascii=False) @@ -427,28 +427,28 @@ def test_minicpm5_tool_formatter(): ] -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) def test_minicpm5_tool_extractor(): formatter = ToolFormatter(tool_format="minicpm5") result = 'bar10' assert formatter.extract(result) == [("test_tool", """{"foo": "bar", "size": 10}""")] -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) def test_minicpm5_tool_extractor_cdata(): formatter = ToolFormatter(tool_format="minicpm5") result = '' assert formatter.extract(result) == [("test_tool", json.dumps({"foo": "a < b\nsecond line"}))] -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) def test_minicpm5_tool_extractor_malformed_value(): formatter = ToolFormatter(tool_format="minicpm5") result = '{[1, 2], [3, 4]}' assert formatter.extract(result) == [("test_tool", json.dumps({"foo": "{[1, 2], [3, 4]}"}))] -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) @pytest.mark.parametrize( "arguments", [ diff --git a/tests/data/test_loader.py b/tests/data/test_loader.py index 907bda347..f589cc858 100644 --- a/tests/data/test_loader.py +++ b/tests/data/test_loader.py @@ -40,21 +40,21 @@ TRAIN_ARGS = { } -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) def test_load_train_only(): dataset_module = load_dataset_module(**TRAIN_ARGS) assert dataset_module.get("train_dataset") is not None assert dataset_module.get("eval_dataset") is None -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) def test_load_val_size(): dataset_module = load_dataset_module(val_size=0.1, **TRAIN_ARGS) assert dataset_module.get("train_dataset") is not None assert dataset_module.get("eval_dataset") is not None -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) def test_load_eval_data(): dataset_module = load_dataset_module(eval_dataset=TINY_DATA, **TRAIN_ARGS) assert dataset_module.get("train_dataset") is not None diff --git a/tests/data/test_mm_plugin.py b/tests/data/test_mm_plugin.py index 73225ebaa..4c4dda47f 100644 --- a/tests/data/test_mm_plugin.py +++ b/tests/data/test_mm_plugin.py @@ -180,7 +180,7 @@ def _check_plugin( ) -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) def test_base_plugin(): tokenizer_module = _load_tokenizer_module(model_name_or_path=TINY_LLAMA3) base_plugin = get_mm_plugin(name="base") @@ -188,7 +188,7 @@ def test_base_plugin(): _check_plugin(**check_inputs) -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) @pytest.mark.skipif(not HF_TOKEN, reason="Gated model.") @pytest.mark.skipif(not is_transformers_version_greater_than("4.50.0"), reason="Requires transformers>=4.50.0") def test_gemma3_plugin(): @@ -211,7 +211,7 @@ def test_gemma3_plugin(): _check_plugin(**check_inputs) -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) @pytest.mark.skipif(not is_transformers_version_greater_than("5.6.0"), reason="Requires transformers>=5.6.0") def test_gemma4_plugin(): tokenizer_module = _load_tokenizer_module(model_name_or_path="google/gemma-4-31B-it") @@ -244,7 +244,7 @@ def test_gemma4_plugin(): _check_plugin(**check_inputs) -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) @pytest.mark.skipif(not is_transformers_version_greater_than("4.52.0"), reason="Requires transformers>=4.52.0") def test_internvl_plugin(): image_seqlen = 256 @@ -263,7 +263,7 @@ def test_internvl_plugin(): _check_plugin(**check_inputs) -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) @pytest.mark.skipif(not is_transformers_version_greater_than("4.51.0"), reason="Requires transformers>=4.51.0") def test_llama4_plugin(): tokenizer_module = _load_tokenizer_module(model_name_or_path=TINY_LLAMA4) @@ -285,7 +285,7 @@ def test_llama4_plugin(): _check_plugin(**check_inputs) -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) def test_llava_plugin(): image_seqlen = 576 tokenizer_module = _load_tokenizer_module(model_name_or_path="llava-hf/llava-1.5-7b-hf") @@ -299,7 +299,7 @@ def test_llava_plugin(): _check_plugin(**check_inputs) -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) def test_llava_next_plugin(): image_seqlen = 1176 tokenizer_module = _load_tokenizer_module(model_name_or_path="llava-hf/llava-v1.6-vicuna-7b-hf") @@ -313,7 +313,7 @@ def test_llava_next_plugin(): _check_plugin(**check_inputs) -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) def test_llava_next_video_plugin(): image_seqlen = 1176 tokenizer_module = _load_tokenizer_module(model_name_or_path="llava-hf/LLaVA-NeXT-Video-7B-hf") @@ -327,7 +327,7 @@ def test_llava_next_video_plugin(): _check_plugin(**check_inputs) -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) @pytest.mark.skipif(not HF_TOKEN, reason="Gated model.") def test_paligemma_plugin(): image_seqlen = 256 @@ -347,7 +347,7 @@ def test_paligemma_plugin(): _check_plugin(**check_inputs) -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) @pytest.mark.skipif(not is_transformers_version_greater_than("4.50.0"), reason="Requires transformers>=4.50.0") def test_pixtral_plugin(): image_slice_height, image_slice_width = 2, 2 @@ -370,7 +370,7 @@ def test_pixtral_plugin(): _check_plugin(**check_inputs) -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) @pytest.mark.skipif(not is_transformers_version_greater_than("4.52.0"), reason="Requires transformers>=4.52.0") def test_qwen2_omni_plugin(): image_seqlen, audio_seqlen = 4, 2 @@ -401,7 +401,7 @@ def test_qwen2_omni_plugin(): _check_plugin(**check_inputs) -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) def test_qwen2_vl_plugin(): image_seqlen = 4 tokenizer_module = _load_tokenizer_module(model_name_or_path="Qwen/Qwen2-VL-7B-Instruct") @@ -436,7 +436,7 @@ def test_moss_vl_plugin(): assert messages[0]["content"] == "First , finally ." -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) @pytest.mark.skipif(not is_transformers_version_greater_than("4.57.0"), reason="Requires transformers>=4.57.0") def test_qwen3_vl_plugin(): frame_seqlen = 1 @@ -470,7 +470,7 @@ def test_qwen3_vl_plugin(): ] -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) @pytest.mark.skipif(not is_transformers_version_greater_than("4.57.0"), reason="Requires transformers>=4.57.0") @pytest.mark.skipif(not is_pyav_available(), reason="Requires pyav") def test_qwen3_vl_plugin_video_path(): @@ -504,7 +504,7 @@ def test_qwen3_vl_plugin_video_path(): ) -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) @pytest.mark.skipif(not is_transformers_version_greater_than("4.47.0"), reason="Requires transformers>=4.47.0") def test_video_llava_plugin(): image_seqlen = 256 @@ -519,7 +519,7 @@ def test_video_llava_plugin(): _check_plugin(**check_inputs) -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) def test_lfm2_vl_plugin(): """Test LFM2.5-VL plugin instantiation.""" # Test plugin can be instantiated with correct tokens diff --git a/tests/data/test_template.py b/tests/data/test_template.py index a08cfe0ca..9549f80a6 100644 --- a/tests/data/test_template.py +++ b/tests/data/test_template.py @@ -139,7 +139,7 @@ def test_qwen38_registration(): assert {"qwen3_5_moe_text", "qwen3_5_text"} <= MCA_SUPPORTED_MODELS -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) def test_encode_oneturn(): tokenizer = AutoTokenizer.from_pretrained(TINY_LLAMA3) template = get_template_and_fix_tokenizer(tokenizer, DataArguments(template="llama3")) @@ -154,7 +154,7 @@ def test_encode_oneturn(): _check_tokenization(tokenizer, (prompt_ids, answer_ids), (prompt_str, answer_str)) -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) def test_encode_multiturn(): tokenizer = AutoTokenizer.from_pretrained(TINY_LLAMA3) template = get_template_and_fix_tokenizer(tokenizer, DataArguments(template="llama3")) @@ -175,7 +175,7 @@ def test_encode_multiturn(): ) -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) @pytest.mark.parametrize("cot_messages", [True, False]) @pytest.mark.parametrize("enable_thinking", [True, False, None]) def test_reasoning_encode_oneturn(cot_messages: bool, enable_thinking: bool): @@ -201,7 +201,7 @@ def test_reasoning_encode_oneturn(cot_messages: bool, enable_thinking: bool): _check_tokenization(tokenizer, (prompt_ids, answer_ids), (prompt_str, answer_str)) -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) @pytest.mark.parametrize("cot_messages", [True, False]) @pytest.mark.parametrize("enable_thinking", [True, False, None]) def test_reasoning_encode_multiturn(cot_messages: bool, enable_thinking: bool): @@ -230,7 +230,7 @@ def test_reasoning_encode_multiturn(cot_messages: bool, enable_thinking: bool): ) -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) @pytest.mark.parametrize("enable_thinking", [True, False, None]) @pytest.mark.parametrize("discarding_history_cot", [True, False]) def test_reasoning_encode_multiturn_discarding_history_cot(enable_thinking: bool, discarding_history_cot: bool): @@ -266,7 +266,7 @@ def test_reasoning_encode_multiturn_discarding_history_cot(enable_thinking: bool ) -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) def test_qwen38_reasoning_instruction(): tokenizer = CharTokenizer() template = deepcopy(TEMPLATES["qwen3_8"]) @@ -284,7 +284,7 @@ def test_qwen38_reasoning_instruction(): assert answer_text == "\n\n\n\nI am fine!<|im_end|>\n" -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) def test_qwen38_tool_system_order(): tokenizer = CharTokenizer() template = deepcopy(TEMPLATES["qwen3_8"]) @@ -308,7 +308,7 @@ def test_qwen38_tool_system_order(): ) -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) def test_jinja_template(): tokenizer = AutoTokenizer.from_pretrained(TINY_LLAMA3) ref_tokenizer = AutoTokenizer.from_pretrained(TINY_LLAMA3) @@ -318,7 +318,7 @@ def test_jinja_template(): assert tokenizer.apply_chat_template(MESSAGES) == ref_tokenizer.apply_chat_template(MESSAGES) -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) def test_ollama_modelfile(): tokenizer = AutoTokenizer.from_pretrained(TINY_LLAMA3) template = get_template_and_fix_tokenizer(tokenizer, DataArguments(template="llama3")) @@ -336,14 +336,14 @@ def test_ollama_modelfile(): ) -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) def test_get_stop_token_ids(): tokenizer = AutoTokenizer.from_pretrained(TINY_LLAMA3) template = get_template_and_fix_tokenizer(tokenizer, DataArguments(template="llama3")) assert set(template.get_stop_token_ids(tokenizer)) == {128008, 128009} -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) @pytest.mark.skipif(not HF_TOKEN, reason="Gated model.") def test_gemma_template(): prompt_str = ( @@ -356,7 +356,7 @@ def test_gemma_template(): _check_template("google/gemma-3-4b-it", "gemma", prompt_str, answer_str) -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) @pytest.mark.skipif(not HF_TOKEN, reason="Gated model.") def test_gemma2_template(): prompt_str = ( @@ -369,7 +369,7 @@ def test_gemma2_template(): _check_template("google/gemma-2-2b-it", "gemma2", prompt_str, answer_str) -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) @pytest.mark.skipif(not HF_TOKEN, reason="Gated model.") def test_llama3_template(): prompt_str = ( @@ -382,7 +382,7 @@ def test_llama3_template(): _check_template("meta-llama/Meta-Llama-3-8B-Instruct", "llama3", prompt_str, answer_str) -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) def test_llama4_template(): prompt_str = ( f"<|begin_of_text|><|header_start|>user<|header_end|>\n\n{MESSAGES[0]['content']}<|eot|>" @@ -394,7 +394,7 @@ def test_llama4_template(): _check_template(TINY_LLAMA4, "llama4", prompt_str, answer_str) -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) def test_phi4_template(): prompt_str = ( f"<|im_start|>user<|im_sep|>{MESSAGES[0]['content']}<|im_end|>" @@ -406,7 +406,7 @@ def test_phi4_template(): _check_template("microsoft/phi-4", "phi4", prompt_str, answer_str) -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) @pytest.mark.xfail(not HF_TOKEN, reason="Authorization.") def test_qwen2_5_template(): prompt_str = ( @@ -420,7 +420,7 @@ def test_qwen2_5_template(): _check_template("Qwen/Qwen2.5-7B-Instruct", "qwen", prompt_str, answer_str) -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) @pytest.mark.parametrize("cot_messages", [True, False]) def test_qwen3_template(cot_messages: bool): prompt_str = ( @@ -439,7 +439,7 @@ def test_qwen3_template(cot_messages: bool): _check_template("Qwen/Qwen3-8B", "qwen3", prompt_str, answer_str, messages=messages) -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) def test_parse_llama3_template(): tokenizer = AutoTokenizer.from_pretrained(TINY_LLAMA3) template = parse_template(tokenizer) @@ -453,7 +453,7 @@ def test_parse_llama3_template(): assert template.default_system == "" -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) @pytest.mark.xfail(not HF_TOKEN, reason="Authorization.") def test_parse_qwen_template(): tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen2.5-7B-Instruct") @@ -466,7 +466,7 @@ def test_parse_qwen_template(): assert template.default_system == "You are Qwen, created by Alibaba Cloud. You are a helpful assistant." -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) @pytest.mark.xfail(not HF_TOKEN, reason="Authorization.") def test_parse_qwen3_template(): tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen3-8B") diff --git a/tests/e2e/test_chat.py b/tests/e2e/test_chat.py index e33f32c56..3ba41c979 100644 --- a/tests/e2e/test_chat.py +++ b/tests/e2e/test_chat.py @@ -37,13 +37,13 @@ MESSAGES = [ EXPECTED_RESPONSE = "_rho" -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) def test_chat(): chat_model = ChatModel(INFER_ARGS) assert chat_model.chat(MESSAGES)[0].response_text == EXPECTED_RESPONSE -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) def test_stream_chat(): chat_model = ChatModel(INFER_ARGS) response = "" diff --git a/tests/e2e/test_train.py b/tests/e2e/test_train.py index dabb888b9..16b7002ef 100644 --- a/tests/e2e/test_train.py +++ b/tests/e2e/test_train.py @@ -49,7 +49,7 @@ INFER_ARGS = { OS_NAME = os.getenv("OS_NAME", "") -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) @pytest.mark.parametrize( "stage,dataset", [ @@ -66,7 +66,7 @@ def test_run_exp(stage: str, dataset: str): assert os.path.exists(output_dir) -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) def test_export(): export_dir = os.path.join("output", "llama3_export") export_model({"export_dir": export_dir, **INFER_ARGS}) diff --git a/tests/eval/test_eval_template.py b/tests/eval/test_eval_template.py index 783d0b9e3..d0a477c09 100644 --- a/tests/eval/test_eval_template.py +++ b/tests/eval/test_eval_template.py @@ -17,7 +17,7 @@ import pytest from llamafactory.eval.template import get_eval_template -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) def test_eval_template_en(): support_set = [ { @@ -56,7 +56,7 @@ def test_eval_template_en(): ] -@pytest.mark.runs_on(["cpu", "mps"]) +@pytest.mark.runs_on(["cpu", "mps", "xpu"]) def test_eval_template_zh(): support_set = [ { diff --git a/tests_v1/accelerator/test_interface.py b/tests_v1/accelerator/test_interface.py index 38ec83b39..cda01130e 100644 --- a/tests_v1/accelerator/test_interface.py +++ b/tests_v1/accelerator/test_interface.py @@ -52,7 +52,7 @@ def test_all_device(): assert DistributedInterface().get_local_world_size() == int(os.getenv("LOCAL_WORLD_SIZE", "1")) -@pytest.mark.runs_on(["cuda", "npu"]) +@pytest.mark.runs_on(["cuda", "npu", "xpu"]) @pytest.mark.require_distributed(2) def test_multi_device(): master_port = find_available_port() diff --git a/tests_v1/conftest.py b/tests_v1/conftest.py index 34797227a..3d8f70a09 100644 --- a/tests_v1/conftest.py +++ b/tests_v1/conftest.py @@ -79,6 +79,8 @@ def _get_visible_devices_env() -> str | None: return "CUDA_VISIBLE_DEVICES" elif CURRENT_DEVICE == "npu": return "ASCEND_RT_VISIBLE_DEVICES" + elif CURRENT_DEVICE == "xpu": + return "ZE_AFFINITY_MASK" else: return None @@ -172,6 +174,8 @@ def _manage_distributed_env(request: FixtureRequest, monkeypatch: MonkeyPatch) - monkeypatch.setattr(torch.cuda, "device_count", lambda: 1) elif CURRENT_DEVICE == "npu": monkeypatch.setattr(torch.npu, "device_count", lambda: 1) + elif CURRENT_DEVICE == "xpu": + monkeypatch.setattr(torch.xpu, "device_count", lambda: 1) @pytest.fixture(scope="session", autouse=True) diff --git a/tests_v1/plugins/model_plugins/test_ulysses_cp.py b/tests_v1/plugins/model_plugins/test_ulysses_cp.py index 4d4fcb79f..228e676f2 100644 --- a/tests_v1/plugins/model_plugins/test_ulysses_cp.py +++ b/tests_v1/plugins/model_plugins/test_ulysses_cp.py @@ -96,7 +96,7 @@ def _test_sequence_parallel_loss( assert loss is not None -@pytest.mark.runs_on(["cuda", "npu"]) +@pytest.mark.runs_on(["cuda", "npu", "xpu"]) @pytest.mark.require_distributed(2) @pytest.mark.parametrize(("cp_size", "dp_size", "batch_size"), [(2, 1, 1), (2, 1, 2)]) def test_sequence_parallel_loss(cp_size, dp_size, batch_size): diff --git a/tests_v1/sampler/test_cli_sampler.py b/tests_v1/sampler/test_cli_sampler.py index db23f1fae..16dee6d67 100644 --- a/tests_v1/sampler/test_cli_sampler.py +++ b/tests_v1/sampler/test_cli_sampler.py @@ -19,7 +19,7 @@ from llamafactory.v1.core.model_engine import ModelEngine from llamafactory.v1.samplers.cli_sampler import SyncSampler -@pytest.mark.runs_on(["cuda", "npu"]) +@pytest.mark.runs_on(["cuda", "npu", "xpu"]) def test_sync_sampler(): model_args = ModelArguments(model="Qwen/Qwen3-4B-Instruct-2507") sample_args = SampleArguments() diff --git a/tests_v1/trainers/test_fsdp2_dpo_trainer.py b/tests_v1/trainers/test_fsdp2_dpo_trainer.py index dcd63d319..0d242e91a 100644 --- a/tests_v1/trainers/test_fsdp2_dpo_trainer.py +++ b/tests_v1/trainers/test_fsdp2_dpo_trainer.py @@ -21,7 +21,7 @@ import pytest @pytest.mark.xfail(reason="CI machines may OOM when heavily loaded.") -@pytest.mark.runs_on(["cuda", "npu"]) +@pytest.mark.runs_on(["cuda", "npu", "xpu"]) def test_fsdp2_dpo_trainer(tmp_path: Path): """Test FSDP2 DPO trainer with sigmoid loss by simulating `llamafactory-cli dpo config.yaml`.""" config_yaml = """\ diff --git a/tests_v1/trainers/test_fsdp2_sft_trainer.py b/tests_v1/trainers/test_fsdp2_sft_trainer.py index 256b8098d..30e14e05b 100644 --- a/tests_v1/trainers/test_fsdp2_sft_trainer.py +++ b/tests_v1/trainers/test_fsdp2_sft_trainer.py @@ -20,7 +20,7 @@ import pytest @pytest.mark.xfail(reason="CI machines may OOM when heavily loaded.") -@pytest.mark.runs_on(["cuda", "npu"]) +@pytest.mark.runs_on(["cuda", "npu", "xpu"]) def test_fsdp2_sft_trainer(tmp_path: Path): """Test FSDP2 SFT trainer by simulating `llamafactory-cli sft config.yaml` behavior.""" config_yaml = """\