3using System.Collections.Generic;
4using System.Diagnostics;
24 public static Dictionary<string, ChatTemplate>
templates;
27 public static Dictionary<string, string> templatesDescription;
28 public static Dictionary<string, string> modelTemplates;
29 public static Dictionary<string, string> chatTemplates;
58 templates =
new Dictionary<string, ChatTemplate>();
59 templatesDescription =
new Dictionary<string, string>();
60 modelTemplates =
new Dictionary<string, string>();
61 chatTemplates =
new Dictionary<string, string>();
64 if (
templates.ContainsKey(
template.GetName()))
LLMUnitySetup.LogError($
"{template.GetName()} already in templates");
66 if (templatesDescription.ContainsKey(
template.GetDescription()))
LLMUnitySetup.LogError($
"{template.GetDescription()} already in templatesDescription");
67 templatesDescription[
template.GetDescription()] =
template.GetName();
70 if (modelTemplates.ContainsKey(match))
LLMUnitySetup.LogError($
"Name for {template.GetName()} already in modelTemplates");
71 modelTemplates[match] =
template.GetName();
75 if (chatTemplates.ContainsKey(match))
LLMUnitySetup.LogError($
"Chat template for {template.GetName()} already in chatTemplates");
76 chatTemplates[match] =
template.GetName();
89 if (name ==
null)
return null;
90 string nameLower = name.ToLower();
91 foreach (var pair
in modelTemplates)
93 if (nameLower.Contains(pair.Key))
return pair.Value;
105 if (
template ==
null)
return null;
106 string templateTrim =
template.Trim();
107 if (chatTemplates.TryGetValue(templateTrim, out
string value))
131 if (name !=
null)
return name;
134 if (name !=
null)
return name;
136 name =
FromName(Path.GetFileNameWithoutExtension(path));
137 if (name !=
null)
return name;
139 LLMUnitySetup.Log(
"No chat template could be matched, fallback to ChatML");
154 public virtual string GetName() {
return ""; }
162 public virtual string[]
GetStop(
string playerName,
string AIName) {
return new string[] {}; }
164 protected virtual string PromptPrefix() {
return ""; }
165 protected virtual string SystemPrefix() {
return ""; }
166 protected virtual string SystemSuffix() {
return ""; }
167 protected virtual string PlayerPrefix(
string playerName) {
return ""; }
168 protected virtual string AIPrefix(
string AIName) {
return ""; }
169 protected virtual string PrefixMessageSeparator() {
return ""; }
170 protected virtual string RequestPrefix() {
return ""; }
171 protected virtual string RequestSuffix() {
return ""; }
172 protected virtual string PairSuffix() {
return ""; }
174 protected virtual bool SystemPromptSupported() {
return true; }
181 public virtual string ComputePrompt(List<ChatMessage> chatMessages,
string playerName,
string AIName,
bool endWithPrefix =
true)
183 List<ChatMessage> messages = chatMessages;
184 if (!SystemPromptSupported())
186 if (chatMessages[0].role ==
"system")
188 string firstUserMessage = chatMessages[0].content;
190 if (chatMessages.Count > 1)
192 if (firstUserMessage !=
"") firstUserMessage +=
"\n\n";
193 firstUserMessage += chatMessages[1].content;
196 messages =
new List<ChatMessage>(){
new ChatMessage { role = playerName, content = firstUserMessage }};
197 messages.AddRange(chatMessages.GetRange(newStart, chatMessages.Count - newStart));
201 string chatPrompt = PromptPrefix();
203 if (messages[0].role ==
"system")
205 chatPrompt += RequestPrefix() + SystemPrefix() + messages[0].content + SystemSuffix();
208 for (
int i = start; i < messages.Count; i += 2)
210 if (i > start || start == 0) chatPrompt += RequestPrefix();
211 chatPrompt += PlayerPrefix(messages[i].role) + PrefixMessageSeparator() + messages[i].content + RequestSuffix();
212 if (i < messages.Count - 1)
214 chatPrompt += AIPrefix(messages[i + 1].role) + PrefixMessageSeparator() + messages[i + 1].content + PairSuffix();
217 if (endWithPrefix) chatPrompt += AIPrefix(AIName);
221 protected string[] AddStopNewlines(
string[] stop)
223 List<string> stopWithNewLines =
new List<string>();
224 foreach (
string stopword
in stop)
226 stopWithNewLines.Add(stopword);
227 stopWithNewLines.Add(
"\n" + stopword);
229 return stopWithNewLines.ToArray();
239 public override string GetName() {
return "chatml"; }
241 public override string[]
GetNameMatches() {
return new string[] {
"chatml",
"hermes",
"qwen"}; }
242 public override string[]
GetChatTemplateMatches() {
return new string[] {
"{% for message in messages %}{{'<|im_start|>' + message['role'] + '\n' + message['content'] + '<|im_end|>' + '\n'}}{% endfor %}{% if add_generation_prompt %}{{ '<|im_start|>assistant\n' }}{% endif %}"}; }
244 protected override string SystemPrefix() {
return "<|im_start|>system\n"; }
245 protected override string SystemSuffix() {
return "<|im_end|>\n"; }
246 protected override string PlayerPrefix(
string playerName) {
return $
"<|im_start|>{playerName}\n"; }
247 protected override string AIPrefix(
string AIName) {
return $
"<|im_start|>{AIName}\n"; }
248 protected override string RequestSuffix() {
return "<|im_end|>\n"; }
249 protected override string PairSuffix() {
return "<|im_end|>\n"; }
251 public override string[]
GetStop(
string playerName,
string AIName)
253 return AddStopNewlines(
new string[] {
"<|im_start|>",
"<|im_end|>" });
263 public override string GetName() {
return "llama"; }
266 protected override string SystemPrefix() {
return "<<SYS>>\n"; }
267 protected override string SystemSuffix() {
return "\n<</SYS>> "; }
268 protected override string RequestPrefix() {
return "<s>[INST] "; }
269 protected override string RequestSuffix() {
return " [/INST]"; }
270 protected override string PairSuffix() {
return " </s>"; }
272 public override string[]
GetStop(
string playerName,
string AIName)
274 return AddStopNewlines(
new string[] {
"[INST]",
"[/INST]" });
284 public override string GetName() {
return "llama chat"; }
286 public override string[]
GetNameMatches() {
return new string[] {
"llama-2",
"llama v2"}; }
288 protected override string PlayerPrefix(
string playerName) {
return "### " + playerName +
":"; }
289 protected override string AIPrefix(
string AIName) {
return "### " + AIName +
":"; }
290 protected override string PrefixMessageSeparator() {
return " "; }
292 public override string[]
GetStop(
string playerName,
string AIName)
294 return AddStopNewlines(
new string[] {
"[INST]",
"[/INST]",
"###" });
304 public override string GetName() {
return "llama3 chat"; }
306 public override string[]
GetNameMatches() {
return new string[] {
"llama-3",
"llama v3"}; }
307 public override string[]
GetChatTemplateMatches() {
return new string[] {
"{% set loop_messages = messages %}{% for message in loop_messages %}{% set content = '<|start_header_id|>' + message['role'] + '<|end_header_id|>\n\n'+ message['content'] | trim + '<|eot_id|>' %}{% if loop.index0 == 0 %}{% set content = bos_token + content %}{% endif %}{{ content }}{% endfor %}{{ '<|start_header_id|>assistant<|end_header_id|>\n\n' }}"};}
309 protected override string SystemPrefix() {
return "<|start_header_id|>system<|end_header_id|>\n\n"; }
310 protected override string SystemSuffix() {
return "<|eot_id|>"; }
312 protected override string RequestSuffix() {
return "<|eot_id|>"; }
313 protected override string PairSuffix() {
return "<|eot_id|>"; }
315 protected override string PlayerPrefix(
string playerName) {
return $
"<|start_header_id|>{playerName}<|end_header_id|>\n\n"; }
316 protected override string AIPrefix(
string AIName) {
return $
"<|start_header_id|>{AIName}<|end_header_id|>\n\n"; }
318 public override string[]
GetStop(
string playerName,
string AIName)
320 return AddStopNewlines(
new string[] {
"<|eot_id|>" });
330 public override string GetName() {
return "mistral instruct"; }
333 protected override string SystemPrefix() {
return ""; }
334 protected override string SystemSuffix() {
return "\n\n"; }
335 protected override string RequestPrefix() {
return "[INST] "; }
336 protected override string RequestSuffix() {
return " [/INST]"; }
337 protected override string PairSuffix() {
return "</s>"; }
339 public override string[]
GetStop(
string playerName,
string AIName)
341 return AddStopNewlines(
new string[] {
"</s>",
"[INST]",
"[/INST]" });
351 public override string GetName() {
return "mistral chat"; }
354 public override string[]
GetChatTemplateMatches() {
return new string[] {
"{{ bos_token }}{% for message in messages %}{% if (message['role'] == 'user') != (loop.index0 % 2 == 0) %}{{ raise_exception('Conversation roles must alternate user/assistant/user/assistant/...') }}{% endif %}{% if message['role'] == 'user' %}{{ '[INST] ' + message['content'] + ' [/INST]' }}{% elif message['role'] == 'assistant' %}{{ message['content'] + eos_token}}{% else %}{{ raise_exception('Only user and assistant roles are supported!') }}{% endif %}{% endfor %}"}; }
356 protected override string PlayerPrefix(
string playerName) {
return "### " + playerName +
":"; }
357 protected override string AIPrefix(
string AIName) {
return "### " + AIName +
":"; }
358 protected override string PrefixMessageSeparator() {
return " "; }
360 public override string[]
GetStop(
string playerName,
string AIName)
362 return AddStopNewlines(
new string[] {
"</s>",
"[INST]",
"[/INST]",
"###" });
372 public override string GetName() {
return "gemma"; }
375 public override string[]
GetChatTemplateMatches() {
return new string[] {
"{{ bos_token }}{% if messages[0]['role'] == 'system' %}{{ raise_exception('System role not supported') }}{% endif %}{% for message in messages %}{% if (message['role'] == 'user') != (loop.index0 % 2 == 0) %}{{ raise_exception('Conversation roles must alternate user/assistant/user/assistant/...') }}{% endif %}{% if (message['role'] == 'assistant') %}{% set role = 'model' %}{% else %}{% set role = message['role'] %}{% endif %}{{ '<start_of_turn>' + role + '\n' + message['content'] | trim + '<end_of_turn>\n' }}{% endfor %}{% if add_generation_prompt %}{{'<start_of_turn>model\n'}}{% endif %}"}; }
377 protected override string RequestSuffix() {
return "<end_of_turn>\n"; }
378 protected override string PairSuffix() {
return "<end_of_turn>\n"; }
380 protected override string PlayerPrefix(
string playerName) {
return "<start_of_turn>user\n"; }
381 protected override string AIPrefix(
string AIName) {
return "<start_of_turn>model\n"; }
383 protected override bool SystemPromptSupported() {
return false; }
385 public override string[]
GetStop(
string playerName,
string AIName)
387 return AddStopNewlines(
new string[] {
"<start_of_turn>",
"<end_of_turn>" });
397 public override string GetName() {
return "alpaca"; }
401 protected override string SystemSuffix() {
return "\n\n"; }
402 protected override string RequestSuffix() {
return "\n"; }
403 protected override string PlayerPrefix(
string playerName) {
return "### " + playerName +
":"; }
404 protected override string AIPrefix(
string AIName) {
return "### " + AIName +
":"; }
405 protected override string PrefixMessageSeparator() {
return " "; }
406 protected override string PairSuffix() {
return "\n"; }
408 public override string[]
GetStop(
string playerName,
string AIName)
410 return AddStopNewlines(
new string[] {
"###" });
420 public override string GetName() {
return "vicuna"; }
423 public override string[]
GetChatTemplateMatches() {
return new string[] {
"{% if not add_generation_prompt is defined %}{% set add_generation_prompt = false %}{% endif %}{% for message in messages %}{% if message['role'] == 'system' %}{{message['content'] + ' '}}{% elif message['role'] == 'user' %}{{ 'USER: ' + message['content'] + ' '}}{% elif message['role'] == 'assistant' %}{{ 'ASSISTANT: ' + message['content'] + ' '}}{% endif %}{% endfor %}{% if add_generation_prompt %}{{ 'ASSISTANT: '}}{% endif %}"}; }
425 protected override string SystemSuffix() {
return "\n"; }
426 protected override string PlayerPrefix(
string playerName) {
return "\n" + playerName +
":"; }
427 protected override string AIPrefix(
string AIName) {
return "\n" + AIName +
":"; }
428 protected override string PrefixMessageSeparator() {
return " "; }
430 public override string[]
GetStop(
string playerName,
string AIName)
432 return AddStopNewlines(
new string[] { playerName +
":", AIName +
":" });
442 public override string GetName() {
return "phi"; }
446 protected override string SystemSuffix() {
return "\n\n"; }
447 protected override string RequestSuffix() {
return "\n"; }
448 protected override string PlayerPrefix(
string playerName) {
return playerName +
":"; }
449 protected override string AIPrefix(
string AIName) {
return AIName +
":"; }
450 protected override string PrefixMessageSeparator() {
return " "; }
451 protected override string PairSuffix() {
return "\n"; }
453 public override string[]
GetStop(
string playerName,
string AIName)
455 return AddStopNewlines(
new string[] { playerName +
":", AIName +
":" });
465 public override string GetName() {
return "phi-3"; }
468 public override string[]
GetChatTemplateMatches() {
return new string[] {
"{{ bos_token }}{% for message in messages %}{% if (message['role'] == 'user') %}{{'<|user|>' + '\n' + message['content'] + '<|end|>' + '\n' + '<|assistant|>' + '\n'}}{% elif (message['role'] == 'assistant') %}{{message['content'] + '<|end|>' + '\n'}}{% endif %}{% endfor %}"}; }
470 protected override string PlayerPrefix(
string playerName) {
return $
"<|user|>\n"; }
471 protected override string AIPrefix(
string AIName) {
return $
"<|assistant|>\n"; }
472 protected override string RequestSuffix() {
return "<|end|>\n"; }
473 protected override string PairSuffix() {
return "<|end|>\n"; }
475 protected override bool SystemPromptSupported() {
return false; }
477 public override string[]
GetStop(
string playerName,
string AIName)
479 return AddStopNewlines(
new string[] {
"<|end|>",
"<|user|>",
"<|assistant|>" });
489 public override string GetName() {
return "phi-3.5"; }
492 public override string[]
GetChatTemplateMatches() {
return new string[] {
"{% for message in messages %}{% if message['role'] == 'system' and message['content'] %}{{'<|system|>\n' + message['content'] + '<|end|>\n'}}{% elif message['role'] == 'user' %}{{'<|user|>\n' + message['content'] + '<|end|>\n'}}{% elif message['role'] == 'assistant' %}{{'<|assistant|>\n' + message['content'] + '<|end|>\n'}}{% endif %}{% endfor %}{% if add_generation_prompt %}{{ '<|assistant|>\n' }}{% else %}{{ eos_token }}{% endif %}"};}
494 protected override string PlayerPrefix(
string playerName) {
return $
"<|user|>\n"; }
495 protected override string AIPrefix(
string AIName) {
return $
"<|assistant|>\n"; }
496 protected override string RequestSuffix() {
return "<|end|>\n"; }
497 protected override string PairSuffix() {
return "<|end|>\n"; }
498 protected override string SystemPrefix() {
return "<|system|>\n"; }
499 protected override string SystemSuffix() {
return "<|end|>\n"; }
501 public override string[]
GetStop(
string playerName,
string AIName)
503 return AddStopNewlines(
new string[] {
"<|end|>",
"<|user|>",
"<|assistant|>" });
513 public override string GetName() {
return "phi-4-mini"; }
515 public override string[]
GetNameMatches() {
return new string[] {
"phi-4-mini"}; }
516 public override string[]
GetChatTemplateMatches() {
return new string[] {
"{% for message in messages %}{% if message['role'] == 'system' and 'tools' in message and message['tools'] is not none %}{{ '<|' + message['role'] + '|>' + message['content'] + '<|tool|>' + message['tools'] + '<|/tool|>' + '<|end|>' }}{% else %}{{ '<|' + message['role'] + '|>' + message['content'] + '<|end|>' }}{% endif %}{% endfor %}{% if add_generation_prompt %}{{ '<|assistant|>' }}{% else %}{{ eos_token }}{% endif %}"};}
518 protected override string PlayerPrefix(
string playerName) {
return $
"<|user|>"; }
519 protected override string AIPrefix(
string AIName) {
return $
"<|assistant|>"; }
520 protected override string RequestSuffix() {
return "<|end|>"; }
521 protected override string PairSuffix() {
return "<|end|>"; }
522 protected override string SystemPrefix() {
return "<|system|>"; }
523 protected override string SystemSuffix() {
return "<|end|>"; }
525 public override string[]
GetStop(
string playerName,
string AIName)
527 return AddStopNewlines(
new string[] {
"<|end|>",
"<|user|>",
"<|assistant|>" });
536 public override string GetName() {
return "phi-4"; }
539 public override string[]
GetChatTemplateMatches() {
return new string[] {
"{% for message in messages %}{% if (message['role'] == 'system') %}{{'<|im_start|>system<|im_sep|>' + message['content'] + '<|im_end|>'}}{% elif (message['role'] == 'user') %}{{'<|im_start|>user<|im_sep|>' + message['content'] + '<|im_end|>'}}{% elif (message['role'] == 'assistant') %}{{'<|im_start|>assistant<|im_sep|>' + message['content'] + '<|im_end|>'}}{% endif %}{% endfor %}{% if add_generation_prompt %}{{ '<|im_start|>assistant<|im_sep|>' }}{% endif %}"};}
541 protected override string PlayerPrefix(
string playerName) {
return $
"<|im_start|>user<|im_sep|>"; }
542 protected override string AIPrefix(
string AIName) {
return $
"<|im_start|>assistant<|im_sep|>"; }
543 protected override string RequestSuffix() {
return "<|im_end|>"; }
544 protected override string PairSuffix() {
return "<|im_end|>"; }
545 protected override string SystemPrefix() {
return "<|im_start|>system<|im_sep|>"; }
546 protected override string SystemSuffix() {
return "<|im_end|>"; }
548 public override string[]
GetStop(
string playerName,
string AIName)
550 return AddStopNewlines(
new string[] {
"<|im_end|>",
"<|im_start|>" });
560 public override string GetName() {
return "zephyr"; }
563 public override string[]
GetChatTemplateMatches() {
return new string[] {
"{% for message in messages %}\n{% if message['role'] == 'user' %}\n{{ '<|user|>\n' + message['content'] + eos_token }}\n{% elif message['role'] == 'system' %}\n{{ '<|system|>\n' + message['content'] + eos_token }}\n{% elif message['role'] == 'assistant' %}\n{{ '<|assistant|>\n' + message['content'] + eos_token }}\n{% endif %}\n{% if loop.last and add_generation_prompt %}\n{{ '<|assistant|>' }}\n{% endif %}\n{% endfor %}"}; }
565 protected override string SystemPrefix() {
return "<|system|>\n"; }
566 protected override string SystemSuffix() {
return "</s>\n"; }
567 protected override string PlayerPrefix(
string playerName) {
return $
"<|user|>\n"; }
568 protected override string AIPrefix(
string AIName) {
return $
"<|assistant|>\n"; }
569 protected override string RequestSuffix() {
return "</s>\n"; }
570 protected override string PairSuffix() {
return "</s>\n"; }
572 public override string[]
GetStop(
string playerName,
string AIName)
574 return AddStopNewlines(
new string[] { $
"<|user|>", $
"<|assistant|>" });
584 public override string GetName() {
return "deepseek-v2"; }
586 public override string[]
GetNameMatches() {
return new string[] {
"deepseek-v2",
"deepseek-llm"}; }
587 public override string[]
GetChatTemplateMatches() {
return new string[] {
"{% if not add_generation_prompt is defined %}{% set add_generation_prompt = false %}{% endif %}{{ bos_token }}{% for message in messages %}{% if message['role'] == 'user' %}{{ 'User: ' + message['content'] + '\n\n' }}{% elif message['role'] == 'assistant' %}{{ 'Assistant: ' + message['content'] + eos_token }}{% elif message['role'] == 'system' %}{{ message['content'] + '\n\n' }}{% endif %}{% endfor %}{% if add_generation_prompt %}{{ 'Assistant:' }}{% endif %}"}; }
589 protected override string PrefixMessageSeparator() {
return " "; }
590 protected override string PromptPrefix() {
return "<|begin▁of▁sentence|>"; }
591 protected override string PlayerPrefix(
string playerName) {
return "User:"; }
592 protected override string AIPrefix(
string AIName) {
return "Assistant:"; }
593 protected override string PairSuffix() {
return "<|end▁of▁sentence|>"; }
594 protected override string RequestSuffix() {
return "\n\n"; }
595 protected override string SystemSuffix() {
return "\n\n"; }
599 public override string[]
GetStop(
string playerName,
string AIName)
601 return AddStopNewlines(
new string[] {
"<|end▁of▁sentence|>",
"User:",
"Assistant:" });
611 public override string GetName() {
return "deepseek-v3"; }
613 public override string[]
GetNameMatches() {
return new string[] {
"deepseek-v2.5",
"deepseek-v3"}; }
618 "{% if not add_generation_prompt is defined %}{% set add_generation_prompt = false %}{% endif %}{% set ns = namespace(is_first=false, is_tool=false, is_output_first=true, system_prompt='') %}{%- for message in messages %}{%- if message['role'] == 'system' %}{% set ns.system_prompt = message['content'] %}{%- endif %}{%- endfor %}{{bos_token}}{{ns.system_prompt}}{%- for message in messages %}{%- if message['role'] == 'user' %}{%- set ns.is_tool = false -%}{{'<|User|>' + message['content']}}{%- endif %}{%- if message['role'] == 'assistant' and message['content'] is none %}{%- set ns.is_tool = false -%}{%- for tool in message['tool_calls']%}{%- if not ns.is_first %}{{'<|Assistant|><|tool▁calls▁begin|><|tool▁call▁begin|>' + tool['type'] + '<|tool▁sep|>' + tool['function']['name'] + '\\n' + '```json' + '\\n' + tool['function']['arguments'] + '\\n' + '```' + '<|tool▁call▁end|>'}}{%- set ns.is_first = true -%}{%- else %}{{'\\n' + '<|tool▁call▁begin|>' + tool['type'] + '<|tool▁sep|>' + tool['function']['name'] + '\\n' + '```json' + '\\n' + tool['function']['arguments'] + '\\n' + '```' + '<|tool▁call▁end|>'}}{{'<|tool▁calls▁end|><|end▁of▁sentence|>'}}{%- endif %}{%- endfor %}{%- endif %}{%- if message['role'] == 'assistant' and message['content'] is not none %}{%- if ns.is_tool %}{{'<|tool▁outputs▁end|>' + message['content'] + '<|end▁of▁sentence|>'}}{%- set ns.is_tool = false -%}{%- else %}{{'<|Assistant|>' + message['content'] + '<|end▁of▁sentence|>'}}{%- endif %}{%- endif %}{%- if message['role'] == 'tool' %}{%- set ns.is_tool = true -%}{%- if ns.is_output_first %}{{'<|tool▁outputs▁begin|><|tool▁output▁begin|>' + message['content'] + '<|tool▁output▁end|>'}}{%- set ns.is_output_first = false %}{%- else %}{{'\\n<|tool▁output▁begin|>' + message['content'] + '<|tool▁output▁end|>'}}{%- endif %}{%- endif %}{%- endfor -%}{% if ns.is_tool %}{{'<|tool▁outputs▁end|>'}}{% endif %}{% if add_generation_prompt and not ns.is_tool %}{{'<|Assistant|>'}}{% endif %}",
619 "{% if not add_generation_prompt is defined %}{% set add_generation_prompt = false %}{% endif %}{% set ns = namespace(is_first=false, is_tool=false, is_output_first=true, system_prompt='', is_first_sp=true) %}{%- for message in messages %}{%- if message['role'] == 'system' %}{%- if ns.is_first_sp %}{% set ns.system_prompt = ns.system_prompt + message['content'] %}{% set ns.is_first_sp = false %}{%- else %}{% set ns.system_prompt = ns.system_prompt + '\n\n' + message['content'] %}{%- endif %}{%- endif %}{%- endfor %}{{bos_token}}{{ns.system_prompt}}{%- for message in messages %}{%- if message['role'] == 'user' %}{%- set ns.is_tool = false -%}{{'<|User|>' + message['content']}}{%- endif %}{%- if message['role'] == 'assistant' and message['content'] is none %}{%- set ns.is_tool = false -%}{%- for tool in message['tool_calls']%}{%- if not ns.is_first %}{{'<|Assistant|><|tool▁calls▁begin|><|tool▁call▁begin|>' + tool['type'] + '<|tool▁sep|>' + tool['function']['name'] + '\n' + '```json' + '\n' + tool['function']['arguments'] + '\n' + '```' + '<|tool▁call▁end|>'}}{%- set ns.is_first = true -%}{%- else %}{{'\n' + '<|tool▁call▁begin|>' + tool['type'] + '<|tool▁sep|>' + tool['function']['name'] + '\n' + '```json' + '\n' + tool['function']['arguments'] + '\n' + '```' + '<|tool▁call▁end|>'}}{{'<|tool▁calls▁end|><|end▁of▁sentence|>'}}{%- endif %}{%- endfor %}{%- endif %}{%- if message['role'] == 'assistant' and message['content'] is not none %}{%- if ns.is_tool %}{{'<|tool▁outputs▁end|>' + message['content'] + '<|end▁of▁sentence|>'}}{%- set ns.is_tool = false -%}{%- else %}{{'<|Assistant|>' + message['content'] + '<|end▁of▁sentence|>'}}{%- endif %}{%- endif %}{%- if message['role'] == 'tool' %}{%- set ns.is_tool = true -%}{%- if ns.is_output_first %}{{'<|tool▁outputs▁begin|><|tool▁output▁begin|>' + message['content'] + '<|tool▁output▁end|>'}}{%- set ns.is_output_first = false %}{%- else %}{{'\n<|tool▁output▁begin|>' + message['content'] + '<|tool▁output▁end|>'}}{%- endif %}{%- endif %}{%- endfor -%}{% if ns.is_tool %}{{'<|tool▁outputs▁end|>'}}{% endif %}{% if add_generation_prompt and not ns.is_tool %}{{'<|Assistant|>'}}{% endif %}"
623 protected override string PrefixMessageSeparator() {
return ""; }
624 protected override string PlayerPrefix(
string playerName) {
return "<|User|>"; }
625 protected override string AIPrefix(
string AIName) {
return "<|Assistant|>"; }
626 protected override string RequestSuffix() {
return ""; }
628 public override string[]
GetStop(
string playerName,
string AIName)
630 return AddStopNewlines(
new string[] {
"<|end▁of▁sentence|>",
"<|User|>",
"<|Assistant|>" });
640 public override string GetName() {
return "deepseek-r1"; }
642 public override string[]
GetNameMatches() {
return new string[] {
"deepseek-r1"}; }
647 "{% if not add_generation_prompt is defined %}{% set add_generation_prompt = false %}{% endif %}{% set ns = namespace(is_first=false, is_tool=false, is_output_first=true, system_prompt='', is_first_sp=true) %}{%- for message in messages %}{%- if message['role'] == 'system' %}{%- if ns.is_first_sp %}{% set ns.system_prompt = ns.system_prompt + message['content'] %}{% set ns.is_first_sp = false %}{%- else %}{% set ns.system_prompt = ns.system_prompt + '\\n\\n' + message['content'] %}{%- endif %}{%- endif %}{%- endfor %}{{ bos_token }}{{ ns.system_prompt }}{%- for message in messages %}{%- if message['role'] == 'user' %}{%- set ns.is_tool = false -%}{{'<|User|>' + message['content']}}{%- endif %}{%- if message['role'] == 'assistant' and 'tool_calls' in message %}{%- set ns.is_tool = false -%}{%- for tool in message['tool_calls'] %}{%- if not ns.is_first %}{%- if message['content'] is none %}{{'<|Assistant|><|tool▁calls▁begin|><|tool▁call▁begin|>' + tool['type'] + '<|tool▁sep|>' + tool['function']['name'] + '\\n' + '```json' + '\\n' + tool['function']['arguments'] + '\\n' + '```' + '<|tool▁call▁end|>'}}{%- else %}{{'<|Assistant|>' + message['content'] + '<|tool▁calls▁begin|><|tool▁call▁begin|>' + tool['type'] + '<|tool▁sep|>' + tool['function']['name'] + '\\n' + '```json' + '\\n' + tool['function']['arguments'] + '\\n' + '```' + '<|tool▁call▁end|>'}}{%- endif %}{%- set ns.is_first = true -%}{%- else %}{{'\\n' + '<|tool▁call▁begin|>' + tool['type'] + '<|tool▁sep|>' + tool['function']['name'] + '\\n' + '```json' + '\\n' + tool['function']['arguments'] + '\\n' + '```' + '<|tool▁call▁end|>'}}{%- endif %}{%- endfor %}{{'<|tool▁calls▁end|><|end▁of▁sentence|>'}}{%- endif %}{%- if message['role'] == 'assistant' and 'tool_calls' not in message %}{%- if ns.is_tool %}{{'<|tool▁outputs▁end|>' + message['content'] + '<|end▁of▁sentence|>'}}{%- set ns.is_tool = false -%}{%- else %}{% set content = message['content'] %}{% if '</think>' in content %}{% set content = content.split('</think>')[-1] %}{% endif %}{{'<|Assistant|>' + content + '<|end▁of▁sentence|>'}}{%- endif %}{%- endif %}{%- if message['role'] == 'tool' %}{%- set ns.is_tool = true -%}{%- if ns.is_output_first %}{{'<|tool▁outputs▁begin|><|tool▁output▁begin|>' + message['content'] + '<|tool▁output▁end|>'}}{%- set ns.is_output_first = false %}{%- else %}{{'<|tool▁output▁begin|>' + message['content'] + '<|tool▁output▁end|>'}}{%- endif %}{%- endif %}{%- endfor -%}{% if ns.is_tool %}{{'<|tool▁outputs▁end|>'}}{% endif %}{% if add_generation_prompt and not ns.is_tool %}{{'<|Assistant|><think>\\n'}}{% endif %}",
648 "{% if not add_generation_prompt is defined %}{% set add_generation_prompt = false %}{% endif %}{% set ns = namespace(is_first=false, is_tool=false, is_output_first=true, system_prompt='') %}{%- for message in messages %}{%- if message['role'] == 'system' %}{% set ns.system_prompt = message['content'] %}{%- endif %}{%- endfor %}{{bos_token}}{{ns.system_prompt}}{%- for message in messages %}{%- if message['role'] == 'user' %}{%- set ns.is_tool = false -%}{{'<|User|>' + message['content']}}{%- endif %}{%- if message['role'] == 'assistant' and message['content'] is none %}{%- set ns.is_tool = false -%}{%- for tool in message['tool_calls']%}{%- if not ns.is_first %}{{'<|Assistant|><|tool▁calls▁begin|><|tool▁call▁begin|>' + tool['type'] + '<|tool▁sep|>' + tool['function']['name'] + '\\n' + '```json' + '\\n' + tool['function']['arguments'] + '\\n' + '```' + '<|tool▁call▁end|>'}}{%- set ns.is_first = true -%}{%- else %}{{'\\n' + '<|tool▁call▁begin|>' + tool['type'] + '<|tool▁sep|>' + tool['function']['name'] + '\\n' + '```json' + '\\n' + tool['function']['arguments'] + '\\n' + '```' + '<|tool▁call▁end|>'}}{{'<|tool▁calls▁end|><|end▁of▁sentence|>'}}{%- endif %}{%- endfor %}{%- endif %}{%- if message['role'] == 'assistant' and message['content'] is not none %}{%- if ns.is_tool %}{{'<|tool▁outputs▁end|>' + message['content'] + '<|end▁of▁sentence|>'}}{%- set ns.is_tool = false -%}{%- else %}{% set content = message['content'] %}{% if '</think>' in content %}{% set content = content.split('</think>')[-1] %}{% endif %}{{'<|Assistant|>' + content + '<|end▁of▁sentence|>'}}{%- endif %}{%- endif %}{%- if message['role'] == 'tool' %}{%- set ns.is_tool = true -%}{%- if ns.is_output_first %}{{'<|tool▁outputs▁begin|><|tool▁output▁begin|>' + message['content'] + '<|tool▁output▁end|>'}}{%- set ns.is_output_first = false %}{%- else %}{{'\\n<|tool▁output▁begin|>' + message['content'] + '<|tool▁output▁end|>'}}{%- endif %}{%- endif %}{%- endfor -%}{% if ns.is_tool %}{{'<|tool▁outputs▁end|>'}}{% endif %}{% if add_generation_prompt and not ns.is_tool %}{{'<|Assistant|><think>\\n'}}{% endif %}"
652 public override string ComputePrompt(List<ChatMessage> chatMessages,
string playerName,
string AIName,
bool endWithPrefix =
true)
654 string prompt = base.ComputePrompt(chatMessages, playerName, AIName, endWithPrefix);
655 if (endWithPrefix) prompt +=
"<think>\n\n</think>\n\n";
659 public override string[]
GetStop(
string playerName,
string AIName)
661 return AddStopNewlines(
new string[] {
"<|end▁of▁sentence|>",
"<|User|>",
"<|Assistant|>",
"</think>" });
Class implementing the Alpaca template.
override string[] GetStop(string playerName, string AIName)
Returns an array of the stopwords used by the template.
override string GetDescription()
Returns the chat template description.
override string GetName()
Returns the chat template name.
override string[] GetNameMatches()
Returns an array of names that can be used to match the chat template.
Class implementing the ChatML template.
override string GetName()
Returns the chat template name.
override string GetDescription()
Returns the chat template description.
override string[] GetChatTemplateMatches()
Returns an array of jinja templates that can be used to match the chat template.
override string[] GetNameMatches()
Returns an array of names that can be used to match the chat template.
override string[] GetStop(string playerName, string AIName)
Returns an array of the stopwords used by the template.
Class implementing the skeleton of a chat template.
static string FromGGUF(string path)
Determines the chat template name from a GGUF file. It reads the GGUF file and then determines the ch...
virtual string[] GetChatTemplateMatches()
Returns an array of jinja templates that can be used to match the chat template.
static Dictionary< string, ChatTemplate > templates
a dictionary from chat template name to chat template type. It can be used to get the chat template n...
virtual string ComputePrompt(List< ChatMessage > chatMessages, string playerName, string AIName, bool endWithPrefix=true)
Constructs the prompt using the template based on a list of ChatMessages.
virtual string[] GetStop(string playerName, string AIName)
Returns an array of the stopwords used by the template.
static string FromName(string name)
Determines the chat template name from a search name. It searches if any of the chat template names i...
virtual string[] GetNameMatches()
Returns an array of names that can be used to match the chat template.
static ChatTemplate GetTemplate(string template)
Creates the chat template based on the provided chat template name.
virtual string GetName()
Returns the chat template name.
virtual string GetDescription()
Returns the chat template description.
static string FromTemplate(string template)
Determines the chat template name from a Jinja template.
static string DefaultTemplate
the default template used when it can't be determined ("chatml")
Class implementing the DeepSeek R1 template.
override string ComputePrompt(List< ChatMessage > chatMessages, string playerName, string AIName, bool endWithPrefix=true)
Constructs the prompt using the template based on a list of ChatMessages.
override string GetName()
Returns the chat template name.
override string[] GetNameMatches()
Returns an array of names that can be used to match the chat template.
override string GetDescription()
Returns the chat template description.
override string[] GetStop(string playerName, string AIName)
Returns an array of the stopwords used by the template.
override string[] GetChatTemplateMatches()
Returns an array of jinja templates that can be used to match the chat template.
Class implementing the DeepSeek V2 template.
override string[] GetStop(string playerName, string AIName)
Returns an array of the stopwords used by the template.
override string[] GetChatTemplateMatches()
Returns an array of jinja templates that can be used to match the chat template.
override string[] GetNameMatches()
Returns an array of names that can be used to match the chat template.
override string GetDescription()
Returns the chat template description.
override string GetName()
Returns the chat template name.
Class implementing the DeepSeek V3 template.
override string GetDescription()
Returns the chat template description.
override string GetName()
Returns the chat template name.
override string[] GetChatTemplateMatches()
Returns an array of jinja templates that can be used to match the chat template.
override string[] GetNameMatches()
Returns an array of names that can be used to match the chat template.
override string[] GetStop(string playerName, string AIName)
Returns an array of the stopwords used by the template.
Class implementing the GGUF reader.
string GetStringField(string key)
Allows to retrieve a string GGUF field.
Class implementing the Gemma template.
override string[] GetNameMatches()
Returns an array of names that can be used to match the chat template.
override string[] GetStop(string playerName, string AIName)
Returns an array of the stopwords used by the template.
override string GetDescription()
Returns the chat template description.
override string GetName()
Returns the chat template name.
override string[] GetChatTemplateMatches()
Returns an array of jinja templates that can be used to match the chat template.
Class implementing helper functions for setup and process management.
Class implementing a modified version of the LLama2 template for chat.
override string[] GetStop(string playerName, string AIName)
Returns an array of the stopwords used by the template.
override string GetDescription()
Returns the chat template description.
override string[] GetNameMatches()
Returns an array of names that can be used to match the chat template.
override string GetName()
Returns the chat template name.
Class implementing the LLama2 template.
override string GetName()
Returns the chat template name.
override string GetDescription()
Returns the chat template description.
override string[] GetStop(string playerName, string AIName)
Returns an array of the stopwords used by the template.
Class implementing the LLama3 template for chat.
override string[] GetNameMatches()
Returns an array of names that can be used to match the chat template.
override string GetName()
Returns the chat template name.
override string GetDescription()
Returns the chat template description.
override string[] GetStop(string playerName, string AIName)
Returns an array of the stopwords used by the template.
override string[] GetChatTemplateMatches()
Returns an array of jinja templates that can be used to match the chat template.
Class implementing a modified version of the Mistral Instruct template for chat.
override string GetDescription()
Returns the chat template description.
override string[] GetChatTemplateMatches()
Returns an array of jinja templates that can be used to match the chat template.
override string[] GetNameMatches()
Returns an array of names that can be used to match the chat template.
override string GetName()
Returns the chat template name.
override string[] GetStop(string playerName, string AIName)
Returns an array of the stopwords used by the template.
Class implementing the Mistral Instruct template.
override string GetDescription()
Returns the chat template description.
override string GetName()
Returns the chat template name.
override string[] GetStop(string playerName, string AIName)
Returns an array of the stopwords used by the template.
Class implementing the Phi-2 template.
override string[] GetNameMatches()
Returns an array of names that can be used to match the chat template.
override string GetName()
Returns the chat template name.
override string[] GetStop(string playerName, string AIName)
Returns an array of the stopwords used by the template.
override string GetDescription()
Returns the chat template description.
Class implementing the Phi-3 template.
override string GetDescription()
Returns the chat template description.
override string[] GetNameMatches()
Returns an array of names that can be used to match the chat template.
override string[] GetStop(string playerName, string AIName)
Returns an array of the stopwords used by the template.
override string GetName()
Returns the chat template name.
override string[] GetChatTemplateMatches()
Returns an array of jinja templates that can be used to match the chat template.
Class implementing the Phi-4 mini template.
override string[] GetStop(string playerName, string AIName)
Returns an array of the stopwords used by the template.
override string GetName()
Returns the chat template name.
override string[] GetNameMatches()
Returns an array of names that can be used to match the chat template.
override string[] GetChatTemplateMatches()
Returns an array of jinja templates that can be used to match the chat template.
override string GetDescription()
Returns the chat template description.
Class implementing the Phi-4 mini template.
override string GetName()
Returns the chat template name.
override string[] GetNameMatches()
Returns an array of names that can be used to match the chat template.
override string[] GetChatTemplateMatches()
Returns an array of jinja templates that can be used to match the chat template.
override string GetDescription()
Returns the chat template description.
override string[] GetStop(string playerName, string AIName)
Returns an array of the stopwords used by the template.
Class implementing the Phi-4 template.
override string[] GetNameMatches()
Returns an array of names that can be used to match the chat template.
override string[] GetChatTemplateMatches()
Returns an array of jinja templates that can be used to match the chat template.
override string GetName()
Returns the chat template name.
override string[] GetStop(string playerName, string AIName)
Returns an array of the stopwords used by the template.
override string GetDescription()
Returns the chat template description.
Class implementing the Vicuna template.
override string GetDescription()
Returns the chat template description.
override string GetName()
Returns the chat template name.
override string[] GetNameMatches()
Returns an array of names that can be used to match the chat template.
override string[] GetChatTemplateMatches()
Returns an array of jinja templates that can be used to match the chat template.
override string[] GetStop(string playerName, string AIName)
Returns an array of the stopwords used by the template.
Class implementing the Zephyr template.
override string[] GetChatTemplateMatches()
Returns an array of jinja templates that can be used to match the chat template.
override string GetDescription()
Returns the chat template description.
override string GetName()
Returns the chat template name.
override string[] GetStop(string playerName, string AIName)
Returns an array of the stopwords used by the template.
override string[] GetNameMatches()
Returns an array of names that can be used to match the chat template.