fix: DPO tool role KeyError (#3217), dataset hash output_dir (#3303), config validators (#3538) [skip ci]
* fix: DPO tool role KeyError, dataset hash output_dir, config validators [skip-e2e] - Add 'tool' to default role_map_inv in dpo/chat_template.py default() and argilla_chat() so datasets with tool-call messages no longer raise KeyError: 'tool' (closes #3217) - Fix generate_dataset_hash_from_config to use canonical tokenizer config + overrides content instead of tokenizer.name_or_path when added_tokens_overrides is set, preventing cache busting when only output_dir changes (closes #3303) - Add three Pydantic config validators to AxolotlConfigWCapabilities: * save_strategy: 'best' requires metric_for_best_model * streaming=True is incompatible with val_set_size > 0 * lora_target_modules list entries must be valid Python regex patterns - Tests for all three changes * review: condense comment in shared.py, swap Mistral model for SmolLM2-135M in test_hash * chore: lint * move the validators out of the w/ capabilities schema --------- Co-authored-by: Wing Lian <wing@axolotl.ai>
This commit is contained in:
@@ -294,5 +294,88 @@ class TestArgillaChatDPOChatTemplate:
|
||||
assert result["rejected"] == "party on<|end|>"
|
||||
|
||||
|
||||
class TestDPOChatTemplateToolRole:
|
||||
"""
|
||||
Test that DPO chat template strategy handles tool role messages without KeyError.
|
||||
Regression test for https://github.com/axolotl-ai-cloud/axolotl/issues/3217
|
||||
"""
|
||||
|
||||
def test_tool_role_default_no_key_error(self, llama3_tokenizer):
|
||||
"""Messages list with a 'tool' role should not raise KeyError."""
|
||||
dataset = Dataset.from_list(
|
||||
[
|
||||
{
|
||||
"messages": [
|
||||
{"role": "user", "content": "What is the weather?"},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "Let me check.",
|
||||
},
|
||||
{
|
||||
"role": "tool",
|
||||
"content": "22°C, sunny.",
|
||||
},
|
||||
],
|
||||
"chosen": {
|
||||
"role": "assistant",
|
||||
"content": "It is 22°C and sunny.",
|
||||
},
|
||||
"rejected": {
|
||||
"role": "assistant",
|
||||
"content": "I don't know.",
|
||||
},
|
||||
}
|
||||
]
|
||||
)
|
||||
transform_fn, _ = default(
|
||||
DictDefault(
|
||||
{
|
||||
"chat_template": "llama3",
|
||||
"datasets": [{"type": "chat_template"}],
|
||||
}
|
||||
)
|
||||
)
|
||||
# Should not raise KeyError: 'tool'
|
||||
result = transform_fn(dataset[0], tokenizer=llama3_tokenizer)
|
||||
assert "prompt" in result
|
||||
assert "chosen" in result
|
||||
assert "rejected" in result
|
||||
|
||||
def test_tool_role_custom_mapping_preserved(self, llama3_tokenizer):
|
||||
"""A user-supplied roles mapping that overrides 'tool' is still respected."""
|
||||
dataset = Dataset.from_list(
|
||||
[
|
||||
{
|
||||
"messages": [
|
||||
{"role": "user", "content": "hello"},
|
||||
{"role": "tool_result", "content": "42"},
|
||||
],
|
||||
"chosen": {"role": "assistant", "content": "The answer is 42."},
|
||||
"rejected": {"role": "assistant", "content": "Unknown."},
|
||||
}
|
||||
]
|
||||
)
|
||||
transform_fn, _ = default(
|
||||
DictDefault(
|
||||
{
|
||||
"chat_template": "llama3",
|
||||
"datasets": [
|
||||
{
|
||||
"type": "chat_template",
|
||||
"roles": {
|
||||
"user": ["user"],
|
||||
"assistant": ["assistant"],
|
||||
"system": ["system"],
|
||||
"tool": ["tool_result"],
|
||||
},
|
||||
}
|
||||
],
|
||||
}
|
||||
)
|
||||
)
|
||||
result = transform_fn(dataset[0], tokenizer=llama3_tokenizer)
|
||||
assert "prompt" in result
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
Reference in New Issue
Block a user