Support DeepSeek-R1 Qwen (#3431)

Signed-off-by: Jared Van Bortel <jared@nomic.ai>
This commit is contained in:
Jared Van Bortel 2025-01-29 09:51:50 -05:00 committed by GitHub
parent 6a8a840681
commit 343a4b6b6a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 51 additions and 9 deletions

@ -1 +1 @@
Subproject commit 58a55efc4ae5dd3bc12887d47981faa7136027af
Subproject commit b06658d366abe3cea92f4e868db72165531a74da

View File

@ -6,6 +6,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
## [Unreleased]
### Added
- Support DeepSeek-R1 Qwen models ([#3431](https://github.com/nomic-ai/gpt4all/pull/3431))
### Fixed
- Fix regression while using localdocs with server API ([#3410](https://github.com/nomic-ai/gpt4all/pull/3410))
- Don't show system messages in server chat view ([#3411](https://github.com/nomic-ai/gpt4all/pull/3411))

View File

@ -64,6 +64,14 @@ namespace ranges = std::ranges;
//#define DEBUG
//#define DEBUG_MODEL_LOADING
static std::string jinjaGetStringArg(const jinja2::ValuesMap &args, const std::string &name)
{
auto arg = args.find(name);
if (arg == args.end() || !arg->second.isString())
throw std::runtime_error(fmt::format("'{}' argument to raise_exception() must be a string", name));
return arg->second.asString();
}
// NOTE: not threadsafe
static jinja2::TemplateEnv *jinjaEnv()
{
@ -75,27 +83,34 @@ static jinja2::TemplateEnv *jinjaEnv()
settings.lstripBlocks = true;
env.AddGlobal("raise_exception", jinja2::UserCallable(
/*callable*/ [](auto &params) -> jinja2::Value {
auto messageArg = params.args.find("message");
if (messageArg == params.args.end() || !messageArg->second.isString())
throw std::runtime_error("'message' argument to raise_exception() must be a string");
throw std::runtime_error(fmt::format("Jinja template error: {}", messageArg->second.asString()));
auto message = jinjaGetStringArg(params.args, "message");
throw std::runtime_error(fmt::format("Jinja template error: {}", message));
},
/*argsInfo*/ { jinja2::ArgInfo("message", /*isMandatory*/ true) }
));
env.AddGlobal("strftime_now", jinja2::UserCallable(
/*callable*/ [](auto &params) -> jinja2::Value {
using Clock = std::chrono::system_clock;
auto formatArg = params.args.find("format");
if (formatArg == params.args.end() || !formatArg->second.isString())
throw std::runtime_error("'format' argument to strftime_now() must be a string");
auto format = jinjaGetStringArg(params.args, "format");
time_t nowUnix = Clock::to_time_t(Clock::now());
auto localDate = *std::localtime(&nowUnix);
std::ostringstream ss;
ss << std::put_time(&localDate, formatArg->second.asString().c_str());
ss << std::put_time(&localDate, format.c_str());
return ss.str();
},
/*argsInfo*/ { jinja2::ArgInfo("format", /*isMandatory*/ true) }
));
env.AddGlobal("regex_replace", jinja2::UserCallable(
/*callable*/ [](auto &params) -> jinja2::Value {
auto str = jinjaGetStringArg(params.args, "str" );
auto pattern = jinjaGetStringArg(params.args, "pattern");
auto repl = jinjaGetStringArg(params.args, "repl" );
return std::regex_replace(str, std::regex(pattern), repl);
},
/*argsInfo*/ { jinja2::ArgInfo("str", /*isMandatory*/ true),
jinja2::ArgInfo("pattern", /*isMandatory*/ true),
jinja2::ArgInfo("repl", /*isMandatory*/ true) }
));
}
return &*environment;
}

View File

@ -52,6 +52,30 @@ const std::unordered_map<std::string_view, std::string_view> CHAT_TEMPLATE_SUBST
{{- '<|assistant|>\n' }}
{%- else %}
{{- eos_token }}
{%- endif %})TEMPLATE",
},
// DeepSeek-R1-Distill-Qwen-7B-Q4_0.gguf
{
// original
R"TEMPLATE({% 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>'}}{% endif %})TEMPLATE",
// replacement
R"TEMPLATE({%- if not add_generation_prompt is defined %}
{%- set add_generation_prompt = false %}
{%- endif %}
{%- if messages[0]['role'] == 'system' %}
{{- messages[0]['content'] }}
{%- endif %}
{%- for message in messages %}
{%- if message['role'] == 'user' %}
{{- '<User>' + message['content'] }}
{%- endif %}
{%- if message['role'] == 'assistant' %}
{%- set content = message['content'] | regex_replace('^[\\s\\S]*</think>', '') %}
{{- '<Assistant>' + content + '<endofsentence>' }}
{%- endif %}
{%- endfor -%}
{%- if add_generation_prompt %}
{{- '<Assistant>' }}
{%- endif %})TEMPLATE",
},
// gemma-2-9b-it-Q4_0.gguf (nomic-ai/gpt4all#3282)