| | #include "llama-chat.h" |
| |
|
| | #include "llama.h" |
| |
|
| | #include <map> |
| | #include <sstream> |
| | #include <algorithm> |
| |
|
| | #if __cplusplus >= 202000L |
| | #define LU8(x) (const char*)(u8##x) |
| | #else |
| | #define LU8(x) u8##x |
| | #endif |
| |
|
| | |
| | static std::string trim(const std::string & str) { |
| | size_t start = 0; |
| | size_t end = str.size(); |
| | while (start < end && isspace(str[start])) { |
| | start += 1; |
| | } |
| | while (end > start && isspace(str[end - 1])) { |
| | end -= 1; |
| | } |
| | return str.substr(start, end - start); |
| | } |
| |
|
| | static const std::map<std::string, llm_chat_template> LLM_CHAT_TEMPLATES = { |
| | { "chatml", LLM_CHAT_TEMPLATE_CHATML }, |
| | { "llama2", LLM_CHAT_TEMPLATE_LLAMA_2 }, |
| | { "llama2-sys", LLM_CHAT_TEMPLATE_LLAMA_2_SYS }, |
| | { "llama2-sys-bos", LLM_CHAT_TEMPLATE_LLAMA_2_SYS_BOS }, |
| | { "llama2-sys-strip", LLM_CHAT_TEMPLATE_LLAMA_2_SYS_STRIP }, |
| | { "mistral-v1", LLM_CHAT_TEMPLATE_MISTRAL_V1 }, |
| | { "mistral-v3", LLM_CHAT_TEMPLATE_MISTRAL_V3 }, |
| | { "mistral-v3-tekken", LLM_CHAT_TEMPLATE_MISTRAL_V3_TEKKEN }, |
| | { "mistral-v7", LLM_CHAT_TEMPLATE_MISTRAL_V7 }, |
| | { "phi3", LLM_CHAT_TEMPLATE_PHI_3 }, |
| | { "phi4", LLM_CHAT_TEMPLATE_PHI_4 }, |
| | { "falcon3", LLM_CHAT_TEMPLATE_FALCON_3 }, |
| | { "zephyr", LLM_CHAT_TEMPLATE_ZEPHYR }, |
| | { "monarch", LLM_CHAT_TEMPLATE_MONARCH }, |
| | { "gemma", LLM_CHAT_TEMPLATE_GEMMA }, |
| | { "orion", LLM_CHAT_TEMPLATE_ORION }, |
| | { "openchat", LLM_CHAT_TEMPLATE_OPENCHAT }, |
| | { "vicuna", LLM_CHAT_TEMPLATE_VICUNA }, |
| | { "vicuna-orca", LLM_CHAT_TEMPLATE_VICUNA_ORCA }, |
| | { "deepseek", LLM_CHAT_TEMPLATE_DEEPSEEK }, |
| | { "deepseek2", LLM_CHAT_TEMPLATE_DEEPSEEK_2 }, |
| | { "deepseek3", LLM_CHAT_TEMPLATE_DEEPSEEK_3 }, |
| | { "command-r", LLM_CHAT_TEMPLATE_COMMAND_R }, |
| | { "llama3", LLM_CHAT_TEMPLATE_LLAMA_3 }, |
| | { "chatglm3", LLM_CHAT_TEMPLATE_CHATGML_3 }, |
| | { "chatglm4", LLM_CHAT_TEMPLATE_CHATGML_4 }, |
| | { "glmedge", LLM_CHAT_TEMPLATE_GLMEDGE }, |
| | { "minicpm", LLM_CHAT_TEMPLATE_MINICPM }, |
| | { "exaone3", LLM_CHAT_TEMPLATE_EXAONE_3 }, |
| | { "rwkv-world", LLM_CHAT_TEMPLATE_RWKV_WORLD }, |
| | { "granite", LLM_CHAT_TEMPLATE_GRANITE }, |
| | { "gigachat", LLM_CHAT_TEMPLATE_GIGACHAT }, |
| | { "megrez", LLM_CHAT_TEMPLATE_MEGREZ }, |
| | }; |
| |
|
| | llm_chat_template llm_chat_template_from_str(const std::string & name) { |
| | return LLM_CHAT_TEMPLATES.at(name); |
| | } |
| |
|
| | llm_chat_template llm_chat_detect_template(const std::string & tmpl) { |
| | try { |
| | return llm_chat_template_from_str(tmpl); |
| | } catch (const std::out_of_range &) { |
| | |
| | } |
| |
|
| | auto tmpl_contains = [&tmpl](const char * haystack) -> bool { |
| | return tmpl.find(haystack) != std::string::npos; |
| | }; |
| | if (tmpl_contains("<|im_start|>")) { |
| | return tmpl_contains("<|im_sep|>") |
| | ? LLM_CHAT_TEMPLATE_PHI_4 |
| | : LLM_CHAT_TEMPLATE_CHATML; |
| | } else if (tmpl.find("mistral") == 0 || tmpl_contains("[INST]")) { |
| | if (tmpl_contains("[SYSTEM_PROMPT]")) { |
| | return LLM_CHAT_TEMPLATE_MISTRAL_V7; |
| | } else if ( |
| | |
| | tmpl_contains("' [INST] ' + system_message") |
| | |
| | || tmpl_contains("[AVAILABLE_TOOLS]") |
| | ) { |
| | |
| | |
| | |
| | if (tmpl_contains(" [INST]")) { |
| | return LLM_CHAT_TEMPLATE_MISTRAL_V1; |
| | } else if (tmpl_contains("\"[INST]\"")) { |
| | return LLM_CHAT_TEMPLATE_MISTRAL_V3_TEKKEN; |
| | } |
| | return LLM_CHAT_TEMPLATE_MISTRAL_V3; |
| | } else { |
| | |
| | |
| | |
| | bool support_system_message = tmpl_contains("<<SYS>>"); |
| | bool add_bos_inside_history = tmpl_contains("bos_token + '[INST]"); |
| | bool strip_message = tmpl_contains("content.strip()"); |
| | if (strip_message) { |
| | return LLM_CHAT_TEMPLATE_LLAMA_2_SYS_STRIP; |
| | } else if (add_bos_inside_history) { |
| | return LLM_CHAT_TEMPLATE_LLAMA_2_SYS_BOS; |
| | } else if (support_system_message) { |
| | return LLM_CHAT_TEMPLATE_LLAMA_2_SYS; |
| | } else { |
| | return LLM_CHAT_TEMPLATE_LLAMA_2; |
| | } |
| | } |
| | } else if (tmpl_contains("<|assistant|>") && tmpl_contains("<|end|>")) { |
| | return LLM_CHAT_TEMPLATE_PHI_3; |
| | } else if (tmpl_contains("<|assistant|>") && tmpl_contains("<|user|>")) { |
| | return tmpl_contains("</s>") ? LLM_CHAT_TEMPLATE_FALCON_3 : LLM_CHAT_TEMPLATE_GLMEDGE; |
| | } else if (tmpl_contains("<|user|>") && tmpl_contains("<|endoftext|>")) { |
| | return LLM_CHAT_TEMPLATE_ZEPHYR; |
| | } else if (tmpl_contains("bos_token + message['role']")) { |
| | return LLM_CHAT_TEMPLATE_MONARCH; |
| | } else if (tmpl_contains("<start_of_turn>")) { |
| | return LLM_CHAT_TEMPLATE_GEMMA; |
| | } else if (tmpl_contains("'\\n\\nAssistant: ' + eos_token")) { |
| | |
| | return LLM_CHAT_TEMPLATE_ORION; |
| | } else if (tmpl_contains("GPT4 Correct ")) { |
| | |
| | return LLM_CHAT_TEMPLATE_OPENCHAT; |
| | } else if (tmpl_contains("USER: ") && tmpl_contains("ASSISTANT: ")) { |
| | |
| | if (tmpl_contains("SYSTEM: ")) { |
| | return LLM_CHAT_TEMPLATE_VICUNA_ORCA; |
| | } |
| | return LLM_CHAT_TEMPLATE_VICUNA; |
| | } else if (tmpl_contains("### Instruction:") && tmpl_contains("<|EOT|>")) { |
| | |
| | return LLM_CHAT_TEMPLATE_DEEPSEEK; |
| | } else if (tmpl_contains("<|START_OF_TURN_TOKEN|>") && tmpl_contains("<|USER_TOKEN|>")) { |
| | |
| | return LLM_CHAT_TEMPLATE_COMMAND_R; |
| | } else if (tmpl_contains("<|start_header_id|>") && tmpl_contains("<|end_header_id|>")) { |
| | return LLM_CHAT_TEMPLATE_LLAMA_3; |
| | } else if (tmpl_contains("[gMASK]sop")) { |
| | |
| | return LLM_CHAT_TEMPLATE_CHATGML_3; |
| | } else if (tmpl_contains("[gMASK]<sop>")) { |
| | return LLM_CHAT_TEMPLATE_CHATGML_4; |
| | } else if (tmpl_contains(LU8("<用户>"))) { |
| | |
| | return LLM_CHAT_TEMPLATE_MINICPM; |
| | } else if (tmpl_contains("'Assistant: ' + message['content'] + eos_token")) { |
| | return LLM_CHAT_TEMPLATE_DEEPSEEK_2; |
| | } else if (tmpl_contains(LU8("<|Assistant|>")) && tmpl_contains(LU8("<|User|>")) && tmpl_contains(LU8("<|end▁of▁sentence|>"))) { |
| | return LLM_CHAT_TEMPLATE_DEEPSEEK_3; |
| | } else if (tmpl_contains("[|system|]") && tmpl_contains("[|assistant|]") && tmpl_contains("[|endofturn|]")) { |
| | |
| | |
| | return LLM_CHAT_TEMPLATE_EXAONE_3; |
| | } else if (tmpl_contains("rwkv-world")) { |
| | return LLM_CHAT_TEMPLATE_RWKV_WORLD; |
| | } else if (tmpl_contains("<|start_of_role|>")) { |
| | return LLM_CHAT_TEMPLATE_GRANITE; |
| | } else if (tmpl_contains("message['role'] + additional_special_tokens[0] + message['content'] + additional_special_tokens[1]")) { |
| | return LLM_CHAT_TEMPLATE_GIGACHAT; |
| | } else if (tmpl_contains("<|role_start|>")) { |
| | return LLM_CHAT_TEMPLATE_MEGREZ; |
| | } |
| | return LLM_CHAT_TEMPLATE_UNKNOWN; |
| | } |
| |
|
| | |
| | |
| | int32_t llm_chat_apply_template( |
| | llm_chat_template tmpl, |
| | const std::vector<const llama_chat_message *> & chat, |
| | std::string & dest, bool add_ass) { |
| | |
| | std::stringstream ss; |
| | if (tmpl == LLM_CHAT_TEMPLATE_CHATML) { |
| | |
| | for (auto message : chat) { |
| | ss << "<|im_start|>" << message->role << "\n" << message->content << "<|im_end|>\n"; |
| | } |
| | if (add_ass) { |
| | ss << "<|im_start|>assistant\n"; |
| | } |
| | } else if (tmpl == LLM_CHAT_TEMPLATE_MISTRAL_V7) { |
| | |
| | |
| | for (auto message : chat) { |
| | std::string role(message->role); |
| | std::string content(message->content); |
| | if (role == "system") { |
| | ss << "[SYSTEM_PROMPT] " << content << "[/SYSTEM_PROMPT]"; |
| | } else if (role == "user") { |
| | ss << "[INST] " << content << "[/INST]"; |
| | } |
| | else { |
| | ss << " " << content << "</s>"; |
| | } |
| | } |
| | } else if (tmpl == LLM_CHAT_TEMPLATE_MISTRAL_V1 |
| | || tmpl == LLM_CHAT_TEMPLATE_MISTRAL_V3 |
| | || tmpl == LLM_CHAT_TEMPLATE_MISTRAL_V3_TEKKEN) { |
| | |
| | |
| | std::string leading_space = tmpl == LLM_CHAT_TEMPLATE_MISTRAL_V1 ? " " : ""; |
| | std::string trailing_space = tmpl == LLM_CHAT_TEMPLATE_MISTRAL_V3_TEKKEN ? "" : " "; |
| | bool trim_assistant_message = tmpl == LLM_CHAT_TEMPLATE_MISTRAL_V3; |
| | bool is_inside_turn = false; |
| | for (auto message : chat) { |
| | if (!is_inside_turn) { |
| | ss << leading_space << "[INST]" << trailing_space; |
| | is_inside_turn = true; |
| | } |
| | std::string role(message->role); |
| | std::string content(message->content); |
| | if (role == "system") { |
| | ss << content << "\n\n"; |
| | } else if (role == "user") { |
| | ss << content << leading_space << "[/INST]"; |
| | } else { |
| | ss << trailing_space << (trim_assistant_message ? trim(content) : content) << "</s>"; |
| | is_inside_turn = false; |
| | } |
| | } |
| | } else if ( |
| | tmpl == LLM_CHAT_TEMPLATE_LLAMA_2 |
| | || tmpl == LLM_CHAT_TEMPLATE_LLAMA_2_SYS |
| | || tmpl == LLM_CHAT_TEMPLATE_LLAMA_2_SYS_BOS |
| | || tmpl == LLM_CHAT_TEMPLATE_LLAMA_2_SYS_STRIP) { |
| | |
| | |
| | |
| | bool support_system_message = tmpl != LLM_CHAT_TEMPLATE_LLAMA_2; |
| | |
| | bool add_bos_inside_history = tmpl == LLM_CHAT_TEMPLATE_LLAMA_2_SYS_BOS; |
| | |
| | bool strip_message = tmpl == LLM_CHAT_TEMPLATE_LLAMA_2_SYS_STRIP; |
| | |
| | bool is_inside_turn = true; |
| | ss << "[INST] "; |
| | for (auto message : chat) { |
| | std::string content = strip_message ? trim(message->content) : message->content; |
| | std::string role(message->role); |
| | if (!is_inside_turn) { |
| | is_inside_turn = true; |
| | ss << (add_bos_inside_history ? "<s>[INST] " : "[INST] "); |
| | } |
| | if (role == "system") { |
| | if (support_system_message) { |
| | ss << "<<SYS>>\n" << content << "\n<</SYS>>\n\n"; |
| | } else { |
| | |
| | ss << content << "\n"; |
| | } |
| | } else if (role == "user") { |
| | ss << content << " [/INST]"; |
| | } else { |
| | ss << content << "</s>"; |
| | is_inside_turn = false; |
| | } |
| | } |
| | } else if (tmpl == LLM_CHAT_TEMPLATE_PHI_3) { |
| | |
| | for (auto message : chat) { |
| | std::string role(message->role); |
| | ss << "<|" << role << "|>\n" << message->content << "<|end|>\n"; |
| | } |
| | if (add_ass) { |
| | ss << "<|assistant|>\n"; |
| | } |
| | } else if (tmpl == LLM_CHAT_TEMPLATE_PHI_4) { |
| | |
| | for (auto message : chat) { |
| | ss << "<|im_start|>" << message->role << "<|im_sep|>" << message->content << "<|im_end|>"; |
| | } |
| | if (add_ass) { |
| | ss << "<|im_start|>assistant<|im_sep|>"; |
| | } |
| | } else if (tmpl == LLM_CHAT_TEMPLATE_FALCON_3) { |
| | |
| | for (auto message : chat) { |
| | std::string role(message->role); |
| | ss << "<|" << role << "|>\n" << message->content << "\n"; |
| | } |
| | if (add_ass) { |
| | ss << "<|assistant|>\n"; |
| | } |
| | } else if (tmpl == LLM_CHAT_TEMPLATE_ZEPHYR) { |
| | |
| | for (auto message : chat) { |
| | ss << "<|" << message->role << "|>" << "\n" << message->content << "<|endoftext|>\n"; |
| | } |
| | if (add_ass) { |
| | ss << "<|assistant|>\n"; |
| | } |
| | } else if (tmpl == LLM_CHAT_TEMPLATE_MONARCH) { |
| | |
| | for (auto message : chat) { |
| | std::string bos = (message == chat.front()) ? "" : "<s>"; |
| | ss << bos << message->role << "\n" << message->content << "</s>\n"; |
| | } |
| | if (add_ass) { |
| | ss << "<s>assistant\n"; |
| | } |
| | } else if (tmpl == LLM_CHAT_TEMPLATE_GEMMA) { |
| | |
| | std::string system_prompt = ""; |
| | for (auto message : chat) { |
| | std::string role(message->role); |
| | if (role == "system") { |
| | |
| | system_prompt = trim(message->content); |
| | continue; |
| | } |
| | |
| | role = role == "assistant" ? "model" : message->role; |
| | ss << "<start_of_turn>" << role << "\n"; |
| | if (!system_prompt.empty() && role != "model") { |
| | ss << system_prompt << "\n\n"; |
| | system_prompt = ""; |
| | } |
| | ss << trim(message->content) << "<end_of_turn>\n"; |
| | } |
| | if (add_ass) { |
| | ss << "<start_of_turn>model\n"; |
| | } |
| | } else if (tmpl == LLM_CHAT_TEMPLATE_ORION) { |
| | |
| | std::string system_prompt = ""; |
| | for (auto message : chat) { |
| | std::string role(message->role); |
| | if (role == "system") { |
| | |
| | system_prompt = message->content; |
| | continue; |
| | } else if (role == "user") { |
| | ss << "Human: "; |
| | if (!system_prompt.empty()) { |
| | ss << system_prompt << "\n\n"; |
| | system_prompt = ""; |
| | } |
| | ss << message->content << "\n\nAssistant: </s>"; |
| | } else { |
| | ss << message->content << "</s>"; |
| | } |
| | } |
| | } else if (tmpl == LLM_CHAT_TEMPLATE_OPENCHAT) { |
| | |
| | for (auto message : chat) { |
| | std::string role(message->role); |
| | if (role == "system") { |
| | ss << message->content << "<|end_of_turn|>"; |
| | } else { |
| | role[0] = toupper(role[0]); |
| | ss << "GPT4 Correct " << role << ": " << message->content << "<|end_of_turn|>"; |
| | } |
| | } |
| | if (add_ass) { |
| | ss << "GPT4 Correct Assistant:"; |
| | } |
| | } else if (tmpl == LLM_CHAT_TEMPLATE_VICUNA || tmpl == LLM_CHAT_TEMPLATE_VICUNA_ORCA) { |
| | |
| | for (auto message : chat) { |
| | std::string role(message->role); |
| | if (role == "system") { |
| | |
| | if (tmpl == LLM_CHAT_TEMPLATE_VICUNA_ORCA) { |
| | ss << "SYSTEM: " << message->content << "\n"; |
| | } else { |
| | ss << message->content << "\n\n"; |
| | } |
| | } else if (role == "user") { |
| | ss << "USER: " << message->content << "\n"; |
| | } else if (role == "assistant") { |
| | ss << "ASSISTANT: " << message->content << "</s>\n"; |
| | } |
| | } |
| | if (add_ass) { |
| | ss << "ASSISTANT:"; |
| | } |
| | } else if (tmpl == LLM_CHAT_TEMPLATE_DEEPSEEK) { |
| | |
| | for (auto message : chat) { |
| | std::string role(message->role); |
| | if (role == "system") { |
| | ss << message->content; |
| | } else if (role == "user") { |
| | ss << "### Instruction:\n" << message->content << "\n"; |
| | } else if (role == "assistant") { |
| | ss << "### Response:\n" << message->content << "\n<|EOT|>\n"; |
| | } |
| | } |
| | if (add_ass) { |
| | ss << "### Response:\n"; |
| | } |
| | } else if (tmpl == LLM_CHAT_TEMPLATE_COMMAND_R) { |
| | |
| | for (auto message : chat) { |
| | std::string role(message->role); |
| | if (role == "system") { |
| | ss << "<|START_OF_TURN_TOKEN|><|SYSTEM_TOKEN|>" << trim(message->content) << "<|END_OF_TURN_TOKEN|>"; |
| | } else if (role == "user") { |
| | ss << "<|START_OF_TURN_TOKEN|><|USER_TOKEN|>" << trim(message->content) << "<|END_OF_TURN_TOKEN|>"; |
| | } else if (role == "assistant") { |
| | ss << "<|START_OF_TURN_TOKEN|><|CHATBOT_TOKEN|>" << trim(message->content) << "<|END_OF_TURN_TOKEN|>"; |
| | } |
| | } |
| | if (add_ass) { |
| | ss << "<|START_OF_TURN_TOKEN|><|CHATBOT_TOKEN|>"; |
| | } |
| | } else if (tmpl == LLM_CHAT_TEMPLATE_LLAMA_3) { |
| | |
| | for (auto message : chat) { |
| | std::string role(message->role); |
| | ss << "<|start_header_id|>" << role << "<|end_header_id|>\n\n" << trim(message->content) << "<|eot_id|>"; |
| | } |
| | if (add_ass) { |
| | ss << "<|start_header_id|>assistant<|end_header_id|>\n\n"; |
| | } |
| | } else if (tmpl == LLM_CHAT_TEMPLATE_CHATGML_3) { |
| | |
| | ss << "[gMASK]" << "sop"; |
| | for (auto message : chat) { |
| | std::string role(message->role); |
| | ss << "<|" << role << "|>" << "\n " << message->content; |
| | } |
| | if (add_ass) { |
| | ss << "<|assistant|>"; |
| | } |
| | } else if (tmpl == LLM_CHAT_TEMPLATE_CHATGML_4) { |
| | ss << "[gMASK]" << "<sop>"; |
| | for (auto message : chat) { |
| | std::string role(message->role); |
| | ss << "<|" << role << "|>" << "\n" << message->content; |
| | } |
| | if (add_ass) { |
| | ss << "<|assistant|>"; |
| | } |
| | } else if (tmpl == LLM_CHAT_TEMPLATE_GLMEDGE) { |
| | for (auto message : chat) { |
| | std::string role(message->role); |
| | ss << "<|" << role << "|>" << "\n" << message->content; |
| | } |
| | if (add_ass) { |
| | ss << "<|assistant|>"; |
| | } |
| | } else if (tmpl == LLM_CHAT_TEMPLATE_MINICPM) { |
| | |
| | for (auto message : chat) { |
| | std::string role(message->role); |
| | if (role == "user") { |
| | ss << LU8("<用户>"); |
| | ss << trim(message->content); |
| | ss << "<AI>"; |
| | } else { |
| | ss << trim(message->content); |
| | } |
| | } |
| | } else if (tmpl == LLM_CHAT_TEMPLATE_DEEPSEEK_2) { |
| | |
| | for (auto message : chat) { |
| | std::string role(message->role); |
| | if (role == "system") { |
| | ss << message->content << "\n\n"; |
| | } else if (role == "user") { |
| | ss << "User: " << message->content << "\n\n"; |
| | } else if (role == "assistant") { |
| | ss << "Assistant: " << message->content << LU8("<|end▁of▁sentence|>"); |
| | } |
| | } |
| | if (add_ass) { |
| | ss << "Assistant:"; |
| | } |
| | } else if (tmpl == LLM_CHAT_TEMPLATE_DEEPSEEK_3) { |
| | |
| | for (auto message : chat) { |
| | std::string role(message->role); |
| | if (role == "system") { |
| | ss << message->content << "\n\n"; |
| | } else if (role == "user") { |
| | ss << LU8("<|User|>") << message->content; |
| | } else if (role == "assistant") { |
| | ss << LU8("<|Assistant|>") << message->content << LU8("<|end▁of▁sentence|>"); |
| | } |
| | } |
| | if (add_ass) { |
| | ss << LU8("<|Assistant|>"); |
| | } |
| | } else if (tmpl == LLM_CHAT_TEMPLATE_EXAONE_3) { |
| | |
| | |
| | for (auto message : chat) { |
| | std::string role(message->role); |
| | if (role == "system") { |
| | ss << "[|system|]" << trim(message->content) << "[|endofturn|]\n"; |
| | } else if (role == "user") { |
| | ss << "[|user|]" << trim(message->content) << "\n"; |
| | } else if (role == "assistant") { |
| | ss << "[|assistant|]" << trim(message->content) << "[|endofturn|]\n"; |
| | } |
| | } |
| | if (add_ass) { |
| | ss << "[|assistant|]"; |
| | } |
| | } else if (tmpl == LLM_CHAT_TEMPLATE_RWKV_WORLD) { |
| | |
| | for (auto message : chat) { |
| | std::string role(message->role); |
| | if (role == "user") { |
| | ss << "User: " << message->content << "\n\nAssistant:"; |
| | } else { |
| | ss << message->content << "\n\n"; |
| | } |
| | } |
| | } else if (tmpl == LLM_CHAT_TEMPLATE_GRANITE) { |
| | |
| | for (const auto & message : chat) { |
| | std::string role(message->role); |
| | ss << "<|start_of_role|>" << role << "<|end_of_role|>"; |
| | if (role == "assistant_tool_call") { |
| | ss << "<|tool_call|>"; |
| | } |
| | ss << message->content << "<|end_of_text|>\n"; |
| | } |
| | if (add_ass) { |
| | ss << "<|start_of_role|>assistant<|end_of_role|>\n"; |
| | } |
| | } else if (tmpl == LLM_CHAT_TEMPLATE_GIGACHAT) { |
| | |
| | bool has_system = !chat.empty() && std::string(chat[0]->role) == "system"; |
| |
|
| | |
| | if (has_system) { |
| | ss << "<s>" << chat[0]->content << "<|message_sep|>"; |
| | } else { |
| | ss << "<s>"; |
| | } |
| |
|
| | |
| | for (size_t i = has_system ? 1 : 0; i < chat.size(); i++) { |
| | std::string role(chat[i]->role); |
| | if (role == "user") { |
| | ss << "user<|role_sep|>" << chat[i]->content << "<|message_sep|>" |
| | << "available functions<|role_sep|>[]<|message_sep|>"; |
| | } else if (role == "assistant") { |
| | ss << "assistant<|role_sep|>" << chat[i]->content << "<|message_sep|>"; |
| | } |
| | } |
| |
|
| | |
| | if (add_ass) { |
| | ss << "assistant<|role_sep|>"; |
| | } |
| | } else if (tmpl == LLM_CHAT_TEMPLATE_MEGREZ) { |
| | |
| | for (auto message : chat) { |
| | std::string role(message->role); |
| | ss << "<|role_start|>" << role << "<|role_end|>" << message->content << "<|turn_end|>"; |
| | } |
| |
|
| | if (add_ass) { |
| | ss << "<|role_start|>assistant<|role_end|>"; |
| | } |
| | } else { |
| | |
| | return -1; |
| | } |
| | dest = ss.str(); |
| | return dest.size(); |
| | } |
| |
|
| | |
| |
|
| | int32_t llama_chat_builtin_templates(const char ** output, size_t len) { |
| | auto it = LLM_CHAT_TEMPLATES.begin(); |
| | for (size_t i = 0; i < std::min(len, LLM_CHAT_TEMPLATES.size()); i++) { |
| | output[i] = it->first.c_str(); |
| | std::advance(it, 1); |
| | } |
| | return (int32_t) LLM_CHAT_TEMPLATES.size(); |
| | } |
| |
|
| |
|