From b39ff27d6fd1e42dbecc2cd1ec5d23e21baf33e2 Mon Sep 17 00:00:00 2001
From: Concedo <39025047+LostRuins@users.noreply.github.com>
Date: Tue, 11 Aug 2026 15:06:30 +0800
Subject: [PATCH] muse glimmer jinja and tool calls working
---
gpttype_adapter.cpp | 22 +++++++++++-
koboldcpp.py | 85 ++++++++++++++++++++++++++++++++++++++++++---
src/llama-vocab.cpp | 2 ++
3 files changed, 104 insertions(+), 5 deletions(-)
diff --git a/gpttype_adapter.cpp b/gpttype_adapter.cpp
index 11021b4a6..af9397583 100644
--- a/gpttype_adapter.cpp
+++ b/gpttype_adapter.cpp
@@ -5107,7 +5107,27 @@ std::string gpttype_parse_chat_tool_calls(const std::string & generated_text,
parser_params.parse_tool_calls = true;
parser_params.parser.load(chat_params.parser);
- common_chat_msg parsed = common_chat_parse(generated_text, is_partial, parser_params);
+ ggml_log_callback currlogger = nullptr;
+ void * curruserdat = nullptr;
+ int oldverbosity = common_log_get_verbosity_thold();
+ llama_log_get(&currlogger, &curruserdat);
+ llama_log_set(log_callback_off, nullptr);
+ common_log_set_verbosity_thold(GGML_LOG_LEVEL_NONE);
+
+ common_chat_msg parsed;
+ try
+ {
+ parsed = common_chat_parse(generated_text, is_partial, parser_params);
+ }
+ catch(...)
+ {
+ llama_log_set(currlogger, curruserdat);
+ common_log_set_verbosity_thold(oldverbosity);
+ throw;
+ }
+
+ llama_log_set(currlogger, curruserdat);
+ common_log_set_verbosity_thold(oldverbosity);
if(parsed.tool_calls.empty())
{
return "";
diff --git a/koboldcpp.py b/koboldcpp.py
index 16758dedf..b64d89a21 100644
--- a/koboldcpp.py
+++ b/koboldcpp.py
@@ -184,6 +184,7 @@ zenity_recent_dir = os.getcwd()
zenity_permitted = True
default_rpc_port = 5551
thinkformats = [{"start":"<|channel|>analysis<|message|>","end":"<|start|>assistant<|channel|>final<|message|>"},
+ {"start":" to=self<|message|>","end":"<|eom|><|start|>assistant"},
{"start":"","end":""},
{"start":"","end":""},
{"start":"<|START_THINKING|>","end":"<|END_THINKING|>"},
@@ -200,7 +201,49 @@ tool_call_pairs = [ #third element is optional str to match in chat template bef
("<|tool_call_start|>", "<|tool_call_end|>", "CONTINUE_FINAL_MESSAGE_TAG", True), #lfm2.5
("", "", "[BEGIN FINAL RESPONSE]", True), #apriel
("<|START_ACTION|>", "<|END_ACTION|>", "<|START_OF_TURN_TOKEN|>", True), #cohere
+ ("", "", "<|eom|>", True), #muse glimmer
]
+
+address_header_formats = [
+ {
+ "required": ["<|start|>assistant", " to=", "<|message|>", "<|eom|>"],
+ "pattern": r'(?s)(?:^|<\|start\|>assistant)\s*to=[^\s<]+<\|message\|>',
+ "tail_start_pattern": r'(?:^|<\|start\|>assistant)\s*to=[^\s<]*$',
+ "tail_message_pattern": r'(?:^|<\|start\|>assistant)\s*to=[^\s<]*',
+ "tail_message_tag": "<|message|>",
+ },
+]
+
+def active_address_header_formats():
+ global cached_chat_template
+ tmpl = cached_chat_template or ""
+ return [fmt for fmt in address_header_formats if all(item in tmpl for item in fmt["required"])]
+
+def strip_address_headers(text):
+ if not text:
+ return text
+ for fmt in active_address_header_formats():
+ text = re.sub(fmt["pattern"], '', text)
+ return text
+
+def split_address_header_tail(text, stream_done=False):
+ if not text or stream_done:
+ return text, ""
+ tail = ""
+ for fmt in active_address_header_formats():
+ start_match = re.search(fmt["tail_start_pattern"], text)
+ msg_tail = fmt["tail_message_tag"]
+ for n in range(1, len(msg_tail)):
+ prefix = msg_tail[:n]
+ marker = re.search(fmt["tail_message_pattern"] + re.escape(prefix) + r'$', text)
+ if marker and len(text[marker.start():]) > len(tail):
+ tail = text[marker.start():]
+ if start_match and len(text[start_match.start():]) > len(tail):
+ tail = text[start_match.start():]
+ if tail:
+ return text[:-len(tail)], tail
+ return text, ""
+
deprecated_keys = {
"hordeconfig",
"sdconfig",
@@ -3671,6 +3714,28 @@ def coerce_tool_argtypes(tool_calls: list, tool_list: list) -> list:
def toolcall_to_normalized_json(text,start_tag,end_tag,required_match_txt): #convert weird formats into standard tool call json
global cached_chat_template
text = text.strip()
+ def parse_muse_glimmer(text: str) -> str:
+ results = []
+ for invoke in re.finditer(
+ r'\s]+)["\']?>(.*?)',
+ text, re.DOTALL
+ ):
+ fn_name = invoke.group(1).strip()
+ params = {}
+ for p in re.finditer(
+ r'\s]+)["\']?>(.*?)',
+ invoke.group(2), re.DOTALL
+ ):
+ val = p.group(2)
+ try:
+ params[p.group(1).strip()] = json.loads(val)
+ except Exception:
+ params[p.group(1).strip()] = val
+ results.append({"name": fn_name, "arguments": params})
+ if not results:
+ return text
+ return json.dumps(results) if len(results) > 1 else json.dumps(results[0])
+
def parse_qwen35(text: str) -> str:
fn_match = re.search(r"", text)
if not fn_match:
@@ -3853,6 +3918,9 @@ def toolcall_to_normalized_json(text,start_tag,end_tag,required_match_txt): #con
if "' in text: #deepseek
return parse_deepseek_r1_sep(text)
@@ -5555,6 +5623,8 @@ class KcppServerRequestHandler(http.server.SimpleHTTPRequestHandler):
recvtxt = None
currfinishreason = "tool_calls"
utfprint(f"\nExecute Toolcall: {json.dumps(tool_calls)}",1)
+ if recvtxt:
+ recvtxt = strip_address_headers(recvtxt)
modelNameToReturn = friendlymodelname
if autoswapmode and textName is not None:
@@ -5797,6 +5867,13 @@ class KcppServerRequestHandler(http.server.SimpleHTTPRequestHandler):
if sindex != -1 and trim_str!="":
tokenStr = tokenStr[:sindex]
+ tokenStr, address_header_tail = split_address_header_tail(tokenStr, streamDone)
+ if address_header_tail:
+ tokenReserve += address_header_tail
+ if tokenStr == "":
+ await asyncio.sleep(async_sleep_short)
+ continue
+
sync_potential_toolcall_splitmatch = ""
if tokenStr!="" or streamDone:
if (api_format == 4 or api_format == 7 or api_format == 9) and using_openai_tools and tool_segment_tag and not streamDone and not genparams.get("sync_toolcall_potential_triggered", False) and tool_segment_tag not in tokenStr:
@@ -5843,7 +5920,7 @@ class KcppServerRequestHandler(http.server.SimpleHTTPRequestHandler):
if pair["end"] in out2:
out2 = out2.replace(pair["end"], "")
if out2:
- delta['content'] = out2
+ delta['content'] = strip_address_headers(out2)
break
if not foundend:
# Still thinking - swallow extraneous start tags from THIS pair only
@@ -5880,7 +5957,7 @@ class KcppServerRequestHandler(http.server.SimpleHTTPRequestHandler):
delta['reasoning_content'] = out2_think
# Append anything after the end tag to the content part
if out2_content:
- delta['content'] = delta.get('content', '') + out2_content
+ delta['content'] = delta.get('content', '') + strip_address_headers(out2_content)
matched_start = True
break
# Condition C: No start tag found, just normal text
@@ -5890,10 +5967,10 @@ class KcppServerRequestHandler(http.server.SimpleHTTPRequestHandler):
# Only swallow stray end tags if we've already locked in a pair
if len(thinkpairs) == 1 and thinkpairs[0]["end"] in cleaned:
cleaned = cleaned.replace(thinkpairs[0]["end"], "")
- delta['content'] = cleaned
+ delta['content'] = strip_address_headers(cleaned)
encap_first_loop = False
else:
- delta['content'] = tokenStr
+ delta['content'] = strip_address_headers(tokenStr)
if genparams.get("sync_toolcall_potential_triggered",False) and delta: # if sync_toolcall_potential_triggered, buffer up the impending content chunk for tools in fakestreaming, in case toolcalls fail
ec = genparams.get("sync_toolcall_extra_content","")
diff --git a/src/llama-vocab.cpp b/src/llama-vocab.cpp
index 45dad6579..39b1e672d 100644
--- a/src/llama-vocab.cpp
+++ b/src/llama-vocab.cpp
@@ -3043,6 +3043,7 @@ void llama_vocab::impl::load(llama_model_loader & ml, const LLM_KV & kv) {
if (false
|| t.first == "<|eot_id|>"
+ || t.first == "<|eot|>" // muse-glimmer
|| t.first == "<|im_end|>"
|| t.first == "<|end|>"
|| t.first == "<|return|>" // o200k_harmony
@@ -3098,6 +3099,7 @@ void llama_vocab::impl::load(llama_model_loader & ml, const LLM_KV & kv) {
|| t.first=="<|START_THINKING|>" || t.first=="<|END_THINKING|>"
|| t.first=="<|START_ACTION|>" || t.first=="<|END_ACTION|>"
|| t.first == "[THINK]" || t.first == "[/THINK]"
+ || t.first == "<|eom|>" // muse-glimmer mid-turn delimiter
|| t.first == "" || t.first == ""
|| t.first == "[CALL_ID]" || t.first == "[TOOL_CONTENT]" || t.first == "[TOOL_CALLS]" || t.first == "[ARGS]") {
LLAMA_LOG_WARN("%s: setting token '%s' (%d) attribute to USER_DEFINED (%u), old attributes: %u\n",