Skip to content

Commit 204739e

Browse files
authored
Adapter fixes (#1659)
* test adapters * add assistant_gen adapter key * add support for chat templates stored as .jinja files * removed mistakenly commited gated-tokenizers link * autoguess: Harmony: add missing newline prefixes to system_end
1 parent 57db0ce commit 204739e

File tree

3 files changed

+33
-19
lines changed

3 files changed

+33
-19
lines changed

kcpp_adapters/AutoGuess.json

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,8 @@
106106
"system_end": "[/INST]",
107107
"user_start": "[INST] ",
108108
"user_end": "",
109-
"assistant_start": "[/INST]",
109+
"assistant_start": "[/INST] ",
110+
"assistant_gen": "[/INST]",
110111
"assistant_end": "</s>"
111112
}
112113
}, {
@@ -168,11 +169,12 @@
168169
"search": ["<|bom|>","is_last_checked_defined"],
169170
"name": "Jamba",
170171
"adapter": {
171-
"system_start": "<|bom|><|system|>",
172+
"system_start": "<|bom|><|system|> ",
172173
"system_end": "<|eom|>",
173-
"user_start": "<|bom|><|user|>",
174+
"user_start": "<|bom|><|user|> ",
174175
"user_end": "<|eom|>",
175-
"assistant_start": "<|bom|><|assistant|>",
176+
"assistant_start": "<|bom|><|assistant|> ",
177+
"assistant_gen": "<|bom|><|assistant|>",
176178
"assistant_end": "<|eom|>"
177179
}
178180
}, {
@@ -191,7 +193,7 @@
191193
"name": "OpenAI Harmony",
192194
"adapter": {
193195
"system_start": "<|start|>developer<|message|># Instructions\n\n",
194-
"system_end": "<|end|>",
196+
"system_end": "\n\n<|end|>",
195197
"user_start": "<|start|>user<|message|>",
196198
"user_end": "<|end|>",
197199
"assistant_start": "<|start|>assistant<|channel|>final<|message|>",
@@ -206,6 +208,7 @@
206208
"user_start": "User: ",
207209
"user_end": "\n\n",
208210
"assistant_start": "Assistant: ",
211+
"assistant_gen": "Assistant:",
209212
"assistant_end": "\n\n"
210213
}
211214
}, {

koboldcpp.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2419,6 +2419,7 @@ def transform_genparams(genparams, api_format):
24192419
user_message_end = adapter_obj.get("user_end", "")
24202420
assistant_message_start = adapter_obj.get("assistant_start", "\n### Response:\n")
24212421
assistant_message_end = adapter_obj.get("assistant_end", "")
2422+
assistant_message_gen = adapter_obj.get("assistant_gen", assistant_message_start)
24222423
tools_message_start = adapter_obj.get("tools_start", "\nTool Results:\n")
24232424
tools_message_end = adapter_obj.get("tools_end", "")
24242425
images_added = []
@@ -2531,7 +2532,7 @@ def transform_genparams(genparams, api_format):
25312532
elif message['role'] == "tool":
25322533
messages_string += tools_message_end
25332534

2534-
messages_string += assistant_message_start
2535+
messages_string += assistant_message_gen
25352536
genparams["prompt"] = messages_string
25362537
if len(images_added)>0:
25372538
genparams["images"] = images_added
@@ -2552,20 +2553,22 @@ def transform_genparams(genparams, api_format):
25522553
adapter_obj = {} if chatcompl_adapter is None else chatcompl_adapter
25532554
user_message_start = adapter_obj.get("user_start", "### Instruction:")
25542555
assistant_message_start = adapter_obj.get("assistant_start", "### Response:")
2555-
genparams["prompt"] = f"{user_message_start} In one sentence, write a descriptive caption for this image.\n{assistant_message_start}"
2556+
assistant_message_gen = adapter_obj.get("assistant_gen", assistant_message_start)
2557+
genparams["prompt"] = f"{user_message_start} In one sentence, write a descriptive caption for this image.\n{assistant_message_gen}"
25562558

25572559
elif api_format==6:
25582560
detokstr = ""
25592561
tokids = genparams.get('context', [])
25602562
adapter_obj = {} if chatcompl_adapter is None else chatcompl_adapter
25612563
user_message_start = adapter_obj.get("user_start", "\n\n### Instruction:\n")
25622564
assistant_message_start = adapter_obj.get("assistant_start", "\n\n### Response:\n")
2565+
assistant_message_gen = adapter_obj.get("assistant_gen", assistant_message_start)
25632566
try:
25642567
detokstr = detokenize_ids(tokids)
25652568
except Exception as e:
25662569
utfprint("Ollama Context Error: " + str(e))
25672570
ollamasysprompt = genparams.get('system', "")
2568-
ollamabodyprompt = f"{detokstr}{user_message_start}{genparams.get('prompt', '')}{assistant_message_start}"
2571+
ollamabodyprompt = f"{detokstr}{user_message_start}{genparams.get('prompt', '')}{assistant_message_gen}"
25692572
ollamaopts = genparams.get('options', {})
25702573
if genparams.get('stop',[]) is not None:
25712574
genparams["stop_sequence"] = genparams.get('stop', [])

tests/test_autoguess.py

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@
2121
"Google Gemma 3n": "lmstudio-community/gemma-3n-E4B-it-MLX-bf16",
2222
"Llama 3.x": "Steelskull/L3.3-Shakudo-70b",
2323
"Llama 4": "nvidia/Llama-4-Scout-17B-16E-Instruct-FP8",
24-
"Mistral V7 (with system prompt)": "Doctor-Shotgun/MS3.2-24B-Magnum-Diamond",
25-
"Mistral V3": "mistralai/Mistral-7B-Instruct-v0.3",
24+
"Mistral Tekken": "Doctor-Shotgun/MS3.2-24B-Magnum-Diamond",
25+
"Mistral Non-Tekken": "mistralai/Mistral-7B-Instruct-v0.3",
2626
"GLM-4": "THUDM/glm-4-9b-chat-hf",
2727
"Phi 3.5": "microsoft/Phi-3.5-mini-instruct",
2828
"Phi 4 (mini)": "microsoft/Phi-4-mini-instruct",
@@ -31,12 +31,13 @@
3131
"Jamba": "ai21labs/Jamba-tiny-dev",
3232
"Dots": "rednote-hilab/dots.llm1.inst",
3333
"RWKV World": "fla-hub/rwkv7-1.5B-world",
34+
"OpenAI Harmony": "openai/gpt-oss-120b",
3435
"Mistral (Generic)": "mistralai/Mistral-Nemo-Instruct-2407",
3536
"ChatML (Generic)": "NewEden/Gemma-27B-chatml",
3637
}
3738

3839
AUTOGUESS_SKIP_ADAPTER_TESTS = {
39-
"Mistral V3": {"system"}, # Poor system support
40+
"Mistral Non-Tekken": {"system"}, # Poor system support
4041
"Mistral (Generic)": {"system"}, # Poor system support
4142
}
4243

@@ -58,10 +59,12 @@ def get_tokenizer_config_for_huggingface_model_id(huggingface_model_id: str):
5859
with open(fname) as f:
5960
return json.load(f)
6061

61-
for filename in ["tokenizer_config.json", "chat_template.json"]:
62+
for filename in ["tokenizer_config.json", "chat_template.json", "chat_template.jinja"]:
6263
url = f"https://huggingface.co/{huggingface_model_id}/resolve/main/{filename}"
6364
response = requests.get(url)
6465
if response.status_code == 200:
66+
if url.endswith(".jinja"):
67+
return {"chat_template": response.text}
6568
v = json.loads(response.text)
6669
if 'chat_template' in v:
6770
return v
@@ -113,9 +116,9 @@ def templ(rolelist):
113116
expect = system("SyS-tEm")
114117
templated = templ([{"role": "system", "content": "SyS-tEm"}, {"role": "user", "content": "user"}])
115118
if expect not in templated:
116-
return False, f"system role missing expected fragment {expect.replace("\n", "\\n")}: {templated.replace("\n", "\\n")}"
119+
return False, f"system role missing expected fragment\n\tadapter: {expect.replace("\n", "\\n")}\n\ttokenizer: {templated.replace("\n", "\\n")}"
117120

118-
# Test user/asst/usernvidia/Llama-4-Scout-17B-16E-Instruct-FP8
121+
# Test user/asst/user
119122
expect = [
120123
user("user_1"),
121124
assistant("asst_1"),
@@ -129,17 +132,21 @@ def templ(rolelist):
129132
rem = templated
130133
for sub in expect:
131134
if sub not in rem:
132-
return False, f"missing expected fragment {sub.replace("\n", "\\n")}: {rem.replace("\n", "\\n")}"
135+
return False, f"missing expected fragment\n\tadapter: {sub.replace("\n", "\\n")}\n\ttokenizer: {rem.replace("\n", "\\n")}"
133136
rem = rem.split(sub, 1)[1]
134137
except jinja2.exceptions.TemplateError as e:
135138
return False, f"template error: {e}"
136139
return True, None
137140

141+
filter = sys.argv[1] if len(sys.argv) > 1 else None
142+
138143
failures = 0
139144
seen = set()
140145
namefmt = "{name:<" + str(max(len(name) for name in AUTOGUESS_MAPPING.keys())) + "}"
141146
hmifmt = "{huggingface_model_id:<" + str(max(len(huggingface_model_id) for huggingface_model_id in AUTOGUESS_MAPPING.values())) + "}"
142147
for name, huggingface_model_id in AUTOGUESS_MAPPING.items():
148+
if filter and filter not in name:
149+
continue
143150
seen.add(name)
144151
if huggingface_model_id == "***UNKNOWN***":
145152
print(namefmt.format(name=name) + " = " + namefmt.format(name="***UNKNOWN***") + " : PENDING")
@@ -162,10 +169,11 @@ def templ(rolelist):
162169
print(namefmt.format(name=name) + " = " + namefmt.format(name=matched) + " : " + ("OK " if adaptercheck and name == matched else reason if not adaptercheck else "FAILURE") + " " + hmifmt.format(huggingface_model_id=huggingface_model_id) + " " + sub_template)
163170
failures += name != matched or not adaptercheck
164171

165-
for entry in autoguess:
166-
if entry['name'] not in seen:
167-
print(namefmt.format(name=entry['name']) + " MISSING MAPPING")
168-
failures += 1
172+
if filter is None:
173+
for entry in autoguess:
174+
if entry['name'] not in seen:
175+
print(namefmt.format(name=entry['name']) + " MISSING MAPPING")
176+
failures += 1
169177

170178
if failures > 0:
171179
print(f"There were {failures} failure(s)!")

0 commit comments

Comments
 (0)