| 510 | } |
| 511 | |
| 512 | common_chat_templates_ptr common_chat_templates_init( |
| 513 | const struct llama_model * model, |
| 514 | const std::string & chat_template_override, |
| 515 | const std::string & bos_token_override, |
| 516 | const std::string & eos_token_override) |
| 517 | { |
| 518 | std::string default_template_src; |
| 519 | std::string template_tool_use_src; |
| 520 | |
| 521 | bool has_explicit_template = !chat_template_override.empty(); |
| 522 | if (chat_template_override.empty()) { |
| 523 | GGML_ASSERT(model != nullptr); |
| 524 | const auto * str = llama_model_chat_template(model, /* name */ nullptr); |
| 525 | if (str) { |
| 526 | default_template_src = str; |
| 527 | has_explicit_template = true; |
| 528 | } |
| 529 | str = llama_model_chat_template(model, /* name */ "tool_use"); |
| 530 | if (str) { |
| 531 | template_tool_use_src = str; |
| 532 | has_explicit_template = true; |
| 533 | } |
| 534 | } else { |
| 535 | default_template_src = chat_template_override; |
| 536 | } |
| 537 | if (default_template_src.empty() || default_template_src == "chatml") { |
| 538 | if (!template_tool_use_src.empty()) { |
| 539 | default_template_src = template_tool_use_src; |
| 540 | } else { |
| 541 | default_template_src = CHATML_TEMPLATE_SRC; |
| 542 | } |
| 543 | } |
| 544 | std::string token_bos = bos_token_override; |
| 545 | std::string token_eos = eos_token_override; |
| 546 | if (model) { |
| 547 | const auto * vocab = llama_model_get_vocab(model); |
| 548 | const auto get_token = [&](llama_token token, const char * name, const char * jinja_variable_name) { |
| 549 | if (token == LLAMA_TOKEN_NULL) { |
| 550 | if (default_template_src.find(jinja_variable_name) != std::string::npos |
| 551 | || template_tool_use_src.find(jinja_variable_name) != std::string::npos) { |
| 552 | LOG_WRN("common_chat_templates_init: warning: vocab does not have a %s token, jinja template won't work as intended.\n", name); |
| 553 | } |
| 554 | return std::string(); |
| 555 | } |
| 556 | return common_token_to_piece(vocab, token, true); |
| 557 | }; |
| 558 | token_bos = get_token(llama_vocab_bos(vocab), "BOS", "bos_token"); |
| 559 | token_eos = get_token(llama_vocab_eos(vocab), "EOS", "eos_token"); |
| 560 | } |
| 561 | common_chat_templates_ptr tmpls(new common_chat_templates()); |
| 562 | tmpls->has_explicit_template = has_explicit_template; |
| 563 | try { |
| 564 | tmpls->template_default = std::make_unique<minja::chat_template>(default_template_src, token_bos, token_eos); |
| 565 | } catch (const std::exception & e) { |
| 566 | LOG_ERR("%s: failed to parse chat template (defaulting to chatml): %s \n", __func__, e.what()); |
| 567 | tmpls->template_default = std::make_unique<minja::chat_template>(CHATML_TEMPLATE_SRC, token_bos, token_eos); |
| 568 | } |
| 569 | if (!template_tool_use_src.empty()) { |