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;
56 templates =
new Dictionary<string, ChatTemplate>();
57 templatesDescription =
new Dictionary<string, string>();
58 modelTemplates =
new Dictionary<string, string>();
59 chatTemplates =
new Dictionary<string, string>();
62 if (
templates.ContainsKey(
template.GetName()))
LLMUnitySetup.LogError($
"{template.GetName()} already in templates");
64 if (templatesDescription.ContainsKey(
template.GetDescription()))
LLMUnitySetup.LogError($
"{template.GetDescription()} already in templatesDescription");
65 templatesDescription[
template.GetDescription()] =
template.GetName();
68 if (modelTemplates.ContainsKey(match))
LLMUnitySetup.LogError($
"Name for {template.GetName()} already in modelTemplates");
69 modelTemplates[match] =
template.GetName();
73 if (chatTemplates.ContainsKey(match))
LLMUnitySetup.LogError($
"Chat template for {template.GetName()} already in chatTemplates");
74 chatTemplates[match] =
template.GetName();
87 if (name ==
null)
return null;
88 string nameLower = name.ToLower();
89 foreach (var pair
in modelTemplates)
91 if (nameLower.Contains(pair.Key))
return pair.Value;
103 if (
template ==
null)
return null;
104 string templateTrim =
template.Trim();
105 if (chatTemplates.TryGetValue(templateTrim, out
string value))
129 if (name !=
null)
return name;
132 if (name !=
null)
return name;
134 name =
FromName(Path.GetFileNameWithoutExtension(path));
135 if (name !=
null)
return name;
137 LLMUnitySetup.Log(
"No chat template could be matched, fallback to ChatML");
152 public virtual string GetName() {
return ""; }
160 public virtual string[]
GetStop(
string playerName,
string AIName) {
return new string[] {}; }
162 protected virtual string PromptPrefix() {
return ""; }
163 protected virtual string SystemPrefix() {
return ""; }
164 protected virtual string SystemSuffix() {
return ""; }
165 protected virtual string PlayerPrefix(
string playerName) {
return ""; }
166 protected virtual string AIPrefix(
string AIName) {
return ""; }
167 protected virtual string PrefixMessageSeparator() {
return ""; }
168 protected virtual string RequestPrefix() {
return ""; }
169 protected virtual string RequestSuffix() {
return ""; }
170 protected virtual string PairSuffix() {
return ""; }
172 protected virtual bool SystemPromptSupported() {
return true; }
179 public virtual string ComputePrompt(List<ChatMessage> chatMessages,
string playerName,
string AIName,
bool endWithPrefix =
true)
181 List<ChatMessage> messages = chatMessages;
182 if (!SystemPromptSupported())
184 if (chatMessages[0].role ==
"system")
186 string firstUserMessage = chatMessages[0].content;
188 if (chatMessages.Count > 1)
190 if (firstUserMessage !=
"") firstUserMessage +=
"\n\n";
191 firstUserMessage += chatMessages[1].content;
194 messages =
new List<ChatMessage>(){
new ChatMessage { role = playerName, content = firstUserMessage }};
195 messages.AddRange(chatMessages.GetRange(newStart, chatMessages.Count - newStart));
199 string chatPrompt = PromptPrefix();
201 if (messages[0].role ==
"system")
203 chatPrompt += RequestPrefix() + SystemPrefix() + messages[0].content + SystemSuffix();
206 for (
int i = start; i < messages.Count; i += 2)
208 if (i > start || start == 0) chatPrompt += RequestPrefix();
209 chatPrompt += PlayerPrefix(messages[i].role) + PrefixMessageSeparator() + messages[i].content + RequestSuffix();
210 if (i < messages.Count - 1)
212 chatPrompt += AIPrefix(messages[i + 1].role) + PrefixMessageSeparator() + messages[i + 1].content + PairSuffix();
215 if (endWithPrefix) chatPrompt += AIPrefix(AIName);
219 protected string[] AddStopNewlines(
string[] stop)
221 List<string> stopWithNewLines =
new List<string>();
222 foreach (
string stopword
in stop)
224 stopWithNewLines.Add(stopword);
225 stopWithNewLines.Add(
"\n" + stopword);
227 return stopWithNewLines.ToArray();
237 public override string GetName() {
return "chatml"; }
239 public override string[]
GetNameMatches() {
return new string[] {
"chatml",
"hermes",
"qwen"}; }
240 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 %}"}; }
242 protected override string SystemPrefix() {
return "<|im_start|>system\n"; }
243 protected override string SystemSuffix() {
return "<|im_end|>\n"; }
244 protected override string PlayerPrefix(
string playerName) {
return $
"<|im_start|>{playerName}\n"; }
245 protected override string AIPrefix(
string AIName) {
return $
"<|im_start|>{AIName}\n"; }
246 protected override string RequestSuffix() {
return "<|im_end|>\n"; }
247 protected override string PairSuffix() {
return "<|im_end|>\n"; }
249 public override string[]
GetStop(
string playerName,
string AIName)
251 return AddStopNewlines(
new string[] {
"<|im_start|>",
"<|im_end|>" });
261 public override string GetName() {
return "llama"; }
264 protected override string SystemPrefix() {
return "<<SYS>>\n"; }
265 protected override string SystemSuffix() {
return "\n<</SYS>> "; }
266 protected override string RequestPrefix() {
return "<s>[INST] "; }
267 protected override string RequestSuffix() {
return " [/INST]"; }
268 protected override string PairSuffix() {
return " </s>"; }
270 public override string[]
GetStop(
string playerName,
string AIName)
272 return AddStopNewlines(
new string[] {
"[INST]",
"[/INST]" });
282 public override string GetName() {
return "llama chat"; }
284 public override string[]
GetNameMatches() {
return new string[] {
"llama-2",
"llama v2"}; }
286 protected override string PlayerPrefix(
string playerName) {
return "### " + playerName +
":"; }
287 protected override string AIPrefix(
string AIName) {
return "### " + AIName +
":"; }
288 protected override string PrefixMessageSeparator() {
return " "; }
290 public override string[]
GetStop(
string playerName,
string AIName)
292 return AddStopNewlines(
new string[] {
"[INST]",
"[/INST]",
"###" });
302 public override string GetName() {
return "llama3 chat"; }
304 public override string[]
GetNameMatches() {
return new string[] {
"llama-3",
"llama v3"}; }
305 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' }}"};}
307 protected override string SystemPrefix() {
return "<|start_header_id|>system<|end_header_id|>\n\n"; }
308 protected override string SystemSuffix() {
return "<|eot_id|>"; }
310 protected override string RequestSuffix() {
return "<|eot_id|>"; }
311 protected override string PairSuffix() {
return "<|eot_id|>"; }
313 protected override string PlayerPrefix(
string playerName) {
return $
"<|start_header_id|>{playerName}<|end_header_id|>\n\n"; }
314 protected override string AIPrefix(
string AIName) {
return $
"<|start_header_id|>{AIName}<|end_header_id|>\n\n"; }
316 public override string[]
GetStop(
string playerName,
string AIName)
318 return AddStopNewlines(
new string[] {
"<|eot_id|>" });
328 public override string GetName() {
return "mistral instruct"; }
331 protected override string SystemPrefix() {
return ""; }
332 protected override string SystemSuffix() {
return "\n\n"; }
333 protected override string RequestPrefix() {
return "[INST] "; }
334 protected override string RequestSuffix() {
return " [/INST]"; }
335 protected override string PairSuffix() {
return "</s>"; }
337 public override string[]
GetStop(
string playerName,
string AIName)
339 return AddStopNewlines(
new string[] {
"</s>",
"[INST]",
"[/INST]" });
349 public override string GetName() {
return "mistral chat"; }
352 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 %}"}; }
354 protected override string PlayerPrefix(
string playerName) {
return "### " + playerName +
":"; }
355 protected override string AIPrefix(
string AIName) {
return "### " + AIName +
":"; }
356 protected override string PrefixMessageSeparator() {
return " "; }
358 public override string[]
GetStop(
string playerName,
string AIName)
360 return AddStopNewlines(
new string[] {
"</s>",
"[INST]",
"[/INST]",
"###" });
370 public override string GetName() {
return "gemma"; }
374 protected override string RequestSuffix() {
return "<end_of_turn>\n"; }
375 protected override string PairSuffix() {
return "<end_of_turn>\n"; }
377 protected override string PlayerPrefix(
string playerName) {
return "<start_of_turn>" + playerName +
"\n"; }
378 protected override string AIPrefix(
string AIName) {
return "<start_of_turn>" + AIName +
"\n"; }
380 protected override bool SystemPromptSupported() {
return false; }
382 public override string[]
GetStop(
string playerName,
string AIName)
384 return AddStopNewlines(
new string[] {
"<start_of_turn>",
"<end_of_turn>" });
394 public override string GetName() {
return "alpaca"; }
398 protected override string SystemSuffix() {
return "\n\n"; }
399 protected override string RequestSuffix() {
return "\n"; }
400 protected override string PlayerPrefix(
string playerName) {
return "### " + playerName +
":"; }
401 protected override string AIPrefix(
string AIName) {
return "### " + AIName +
":"; }
402 protected override string PrefixMessageSeparator() {
return " "; }
403 protected override string PairSuffix() {
return "\n"; }
405 public override string[]
GetStop(
string playerName,
string AIName)
407 return AddStopNewlines(
new string[] {
"###" });
417 public override string GetName() {
return "vicuna"; }
420 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 %}"}; }
422 protected override string SystemSuffix() {
return "\n"; }
423 protected override string PlayerPrefix(
string playerName) {
return "\n" + playerName +
":"; }
424 protected override string AIPrefix(
string AIName) {
return "\n" + AIName +
":"; }
425 protected override string PrefixMessageSeparator() {
return " "; }
427 public override string[]
GetStop(
string playerName,
string AIName)
429 return AddStopNewlines(
new string[] { playerName +
":", AIName +
":" });
439 public override string GetName() {
return "phi"; }
443 protected override string SystemSuffix() {
return "\n\n"; }
444 protected override string RequestSuffix() {
return "\n"; }
445 protected override string PlayerPrefix(
string playerName) {
return playerName +
":"; }
446 protected override string AIPrefix(
string AIName) {
return AIName +
":"; }
447 protected override string PrefixMessageSeparator() {
return " "; }
448 protected override string PairSuffix() {
return "\n"; }
450 public override string[]
GetStop(
string playerName,
string AIName)
452 return AddStopNewlines(
new string[] { playerName +
":", AIName +
":" });
462 public override string GetName() {
return "phi-3"; }
465 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 %}"}; }
467 protected override string PlayerPrefix(
string playerName) {
return $
"<|user|>\n"; }
468 protected override string AIPrefix(
string AIName) {
return $
"<|assistant|>\n"; }
469 protected override string RequestSuffix() {
return "<|end|>\n"; }
470 protected override string PairSuffix() {
return "<|end|>\n"; }
472 protected override bool SystemPromptSupported() {
return false; }
474 public override string[]
GetStop(
string playerName,
string AIName)
476 return AddStopNewlines(
new string[] {
"<|end|>",
"<|user|>",
"<|assistant|>" });
486 public override string GetName() {
return "phi-3.5"; }
489 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 %}"};}
491 protected override string PlayerPrefix(
string playerName) {
return $
"<|user|>\n"; }
492 protected override string AIPrefix(
string AIName) {
return $
"<|assistant|>\n"; }
493 protected override string RequestSuffix() {
return "<|end|>\n"; }
494 protected override string PairSuffix() {
return "<|end|>\n"; }
495 protected override string SystemPrefix() {
return "<|system|>\n"; }
496 protected override string SystemSuffix() {
return "<|end|>\n"; }
498 public override string[]
GetStop(
string playerName,
string AIName)
500 return AddStopNewlines(
new string[] {
"<|end|>",
"<|user|>",
"<|assistant|>" });
510 public override string GetName() {
return "zephyr"; }
513 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 %}"}; }
515 protected override string SystemPrefix() {
return "<|system|>\n"; }
516 protected override string SystemSuffix() {
return "</s>\n"; }
517 protected override string PlayerPrefix(
string playerName) {
return $
"<|user|>\n"; }
518 protected override string AIPrefix(
string AIName) {
return $
"<|assistant|>\n"; }
519 protected override string RequestSuffix() {
return "</s>\n"; }
520 protected override string PairSuffix() {
return "</s>\n"; }
522 public override string[]
GetStop(
string playerName,
string AIName)
524 return AddStopNewlines(
new string[] { $
"<|user|>", $
"<|assistant|>" });
534 public override string GetName() {
return "deepseek-v2"; }
536 public override string[]
GetNameMatches() {
return new string[] {
"deepseek-v2",
"deepseek-llm"}; }
537 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 %}"}; }
539 protected override string PrefixMessageSeparator() {
return " "; }
540 protected override string PromptPrefix() {
return "<|begin▁of▁sentence|>"; }
541 protected override string PlayerPrefix(
string playerName) {
return "User:"; }
542 protected override string AIPrefix(
string AIName) {
return "Assistant:"; }
543 protected override string PairSuffix() {
return "<|end▁of▁sentence|>"; }
544 protected override string RequestSuffix() {
return "\n\n"; }
545 protected override string SystemSuffix() {
return "\n\n"; }
549 public override string[]
GetStop(
string playerName,
string AIName)
551 return AddStopNewlines(
new string[] {
"<|end▁of▁sentence|>",
"User:",
"Assistant:" });
561 public override string GetName() {
return "deepseek-v3"; }
563 public override string[]
GetNameMatches() {
return new string[] {
"deepseek-v2.5",
"deepseek-v3"}; }
568 "{% 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 %}",
569 "{% 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 %}"
573 protected override string PrefixMessageSeparator() {
return ""; }
574 protected override string PlayerPrefix(
string playerName) {
return "<|User|>"; }
575 protected override string AIPrefix(
string AIName) {
return "<|Assistant|>"; }
576 protected override string RequestSuffix() {
return ""; }
578 public override string[]
GetStop(
string playerName,
string AIName)
580 return AddStopNewlines(
new string[] {
"<|end▁of▁sentence|>",
"<|User|>",
"<|Assistant|>" });
590 public override string GetName() {
return "deepseek-r1"; }
592 public override string[]
GetNameMatches() {
return new string[] {
"deepseek-r1"}; }
597 "{% 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 %}",
598 "{% 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 %}"
602 public override string ComputePrompt(List<ChatMessage> chatMessages,
string playerName,
string AIName,
bool endWithPrefix =
true)
604 string prompt = base.ComputePrompt(chatMessages, playerName, AIName, endWithPrefix);
605 if (endWithPrefix) prompt +=
"<think>\n\n</think>\n\n";
609 public override string[]
GetStop(
string playerName,
string AIName)
611 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.
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-3.5 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 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.