Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/llamafactory/data/converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,11 @@ def __call__(self, example: dict[str, Any]) -> dict[str, Any]:
)
tool_responses = []

if role not in tag_mapping:
logger.warning_rank0(f"Invalid role tag in {messages}.")
broken_data = True
break
Comment on lines +278 to +281

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.

medium

If role is None (e.g., due to a malformed message) and any of the dataset attributes in tag_mapping (such as system_tag or observation_tag) are also None (unconfigured), role not in tag_mapping will evaluate to False. This can lead to incorrect mapping or unexpected behavior.

We should explicitly guard against role being None to ensure robust validation.

Suggested change
if role not in tag_mapping:
logger.warning_rank0(f"Invalid role tag in {messages}.")
broken_data = True
break
if role is None or role not in tag_mapping:
logger.warning_rank0(f"Invalid role tag in {messages}.")
broken_data = True
break


aligned_messages.append(
{
"role": tag_mapping[role],
Expand Down
20 changes: 20 additions & 0 deletions tests/data/test_converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,23 @@ def test_sharegpt_converter():
"_videos": None,
"_audios": None,
}


@pytest.mark.runs_on(["cpu", "mps"])
def test_openai_converter_skips_invalid_role():
# A message that carries a role tag not present in tag_mapping must be
# treated as an abnormal example and skipped, not crash with a KeyError when
# the converter builds aligned_messages. The sharegpt converter already
# guards its build loop; the openai converter only validated afterwards.
dataset_attr = DatasetAttr("hf_hub", "llamafactory/tiny-supervised-dataset")
data_args = DataArguments()
example = {
"conversations": [
{"from": "human", "value": "Solve the math problem.\n3 + 4"},
{"from": "not_a_role", "value": "The answer is 7."},
]
}
dataset_converter = get_dataset_converter("openai", dataset_attr, data_args)
result = dataset_converter(example)
assert result["_prompt"] == []
assert result["_response"] == []