Skip to content

Commit f058384

Browse files
committed
model : gpt-oss simulate think tags when reasoning
1 parent a3a7874 commit f058384

File tree

2 files changed

+44
-12
lines changed

2 files changed

+44
-12
lines changed

common/chat.cpp

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1314,17 +1314,56 @@ static common_chat_params common_chat_params_init_gpt_oss(const common_chat_temp
13141314
data.prompt = prompt;
13151315
data.format = COMMON_CHAT_FORMAT_GPT_OSS;
13161316

1317+
// These special tokens are required to parse properly, so we include them
1318+
// even if parse_tool_calls is false.
1319+
data.preserved_tokens = {
1320+
"<|channel|>",
1321+
"<|constrain|>",
1322+
"<|message|>",
1323+
"<|start|>",
1324+
"<|end|>",
1325+
};
1326+
13171327
// TODO: support tool calls in GPT-OSS?
13181328

13191329
return data;
13201330
}
13211331
static void common_chat_parse_gpt_oss(common_chat_msg_parser & builder) {
1322-
// TODO @ngxson : this won't work with --special enabled, we should fix that
1323-
builder.try_parse_reasoning("<|channel|>analysis<|message|>", "<|start|>assistant<|channel|>final<|message|>");
1324-
if (!builder.syntax().parse_tool_calls) {
1325-
builder.add_content(builder.consume_rest());
1326-
return;
1332+
static const common_regex end_regex("<\\|end\\|>");
1333+
static const common_regex analysis_regex("<\\|channel\\|>analysis<\\|message\\|>");
1334+
static const common_regex final_regex("<\\|channel\\|>final<\\|message\\|>");
1335+
1336+
if (builder.try_consume_regex(analysis_regex)) {
1337+
std::string reasoning;
1338+
bool has_end = false;
1339+
if (auto res = builder.try_find_regex(end_regex, std::string::npos, false)) {
1340+
reasoning = res->prelude;
1341+
has_end = true;
1342+
} else {
1343+
reasoning = builder.consume_rest();
1344+
}
1345+
1346+
if (builder.syntax().reasoning_format == COMMON_REASONING_FORMAT_NONE || builder.syntax().reasoning_in_content) {
1347+
// the templates raise an exception if <|channel|> is present
1348+
// an assistant's content, so wrap it in think tags
1349+
builder.add_content("<think>");
1350+
builder.add_content(reasoning);
1351+
if (has_end) {
1352+
builder.add_content("</think>");
1353+
}
1354+
} else {
1355+
builder.add_reasoning_content(reasoning);
1356+
}
1357+
}
1358+
1359+
if (builder.try_find_regex(final_regex, std::string::npos, false)) {
1360+
if (!builder.try_find_regex(end_regex)) {
1361+
builder.add_content(builder.consume_rest());
1362+
}
13271363
}
1364+
1365+
// no tool call support yet, so we have to consume everything else
1366+
builder.consume_rest();
13281367
}
13291368

13301369
static common_chat_params common_chat_params_init_firefunction_v2(const common_chat_template & tmpl, const struct templates_params & inputs) {

src/llama-vocab.cpp

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2339,13 +2339,6 @@ void llama_vocab::impl::load(llama_model_loader & ml, const LLM_KV & kv) {
23392339
}
23402340
}
23412341

2342-
// @ngxson : quick hack for gpt-oss, always render these tokens
2343-
for (const auto & t : token_to_id) {
2344-
if (t.first == "<|channel|>" || t.first == "<|message|>" || t.first == "<|start|>") {
2345-
id_to_token[t.second].attr = LLAMA_TOKEN_ATTR_USER_DEFINED;
2346-
}
2347-
}
2348-
23492342
// sanity checks
23502343
if (special_eos_id != LLAMA_TOKEN_NULL && special_eog_ids.count(special_eos_id) == 0) {
23512344
special_eog_ids.insert(special_eos_id);

0 commit comments

Comments
 (0)