Skip to content

Commit f098b13

Browse files
committed
glm working with opencode
1 parent 84bcbd2 commit f098b13

File tree

1 file changed

+33
-72
lines changed

1 file changed

+33
-72
lines changed

common/chat.cpp

Lines changed: 33 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1330,83 +1330,41 @@ static void common_chat_parse_gpt_oss(common_chat_msg_parser & builder) {
13301330
}
13311331

13321332
static common_chat_params common_chat_params_init_glm_4_5(const common_chat_template & tmpl, const struct templates_params & inputs) {
1333+
LOG_INF("%s: initializing GLM-4.5 chat params\n", __func__);
13331334
common_chat_params data;
13341335

1335-
// Bypass minja's tool processing entirely
1336+
// Configure template inputs
13361337
minja::chat_template_inputs tmpl_inputs;
13371338
tmpl_inputs.messages = inputs.messages;
13381339
tmpl_inputs.tools = inputs.tools.empty() ? json() : inputs.tools;
13391340
tmpl_inputs.add_generation_prompt = inputs.add_generation_prompt;
13401341
tmpl_inputs.extra_context = inputs.extra_context;
1341-
tmpl_inputs.now = std::chrono::system_clock::now();
1342+
tmpl_inputs.now = inputs.now; // Use the consistent timestamp from params
13421343

1343-
// Force XML mode through context
1344-
tmpl_inputs.extra_context["xml_tool_format"] = true;
1345-
tmpl_inputs.extra_context["native_tool_support"] = true;
1346-
1344+
// Configure template options to disable polyfills and enforce native XML format
13471345
minja::chat_template_options opts;
1348-
opts.apply_polyfills = false; // Hard disable all polyfills
1349-
opts.use_bos_token = inputs.add_bos;
1350-
opts.use_eos_token = inputs.add_eos;
1351-
1352-
// Single apply call
1353-
auto result = tmpl.apply(tmpl_inputs, opts);
1354-
1355-
// Manual BOS/EOS handling (since you disabled automatic handling)
1356-
if (inputs.add_bos && string_starts_with(result, tmpl.bos_token())) {
1357-
result = result.substr(tmpl.bos_token().size());
1358-
}
1359-
if (inputs.add_eos && string_ends_with(result, tmpl.eos_token())) {
1360-
result = result.substr(0, result.size() - tmpl.eos_token().size());
1361-
}
1346+
opts.apply_polyfills = false; // Hard disable all polyfills
13621347

1363-
data.prompt = result;
1348+
// The prompt is generated here
1349+
data.prompt = tmpl.apply(tmpl_inputs, opts);
13641350
data.format = COMMON_CHAT_FORMAT_GLM_4_5;
1351+
13651352
data.preserved_tokens = {
13661353
"<|system|>", "<|assistant|>", "<|observation|>",
13671354
"<tool_call>", "</tool_call>", "<arg_key>", "</arg_key>",
13681355
"<arg_value>", "</arg_value>", "<think>", "</think>",
13691356
"<tool_response>", "</tool_response>",
13701357
};
13711358

1372-
// Store tools schema for type-aware parsing
1359+
// Store tools schema for type-aware parsing later
13731360
data.tools_schema = inputs.tools;
13741361

1362+
LOG_INF("%s: GLM-4.5 native XML format enforced\n", __func__);
13751363
return data;
13761364
}
13771365

1378-
static void debug_print_raw_input(const std::string& input) {
1379-
LOG_INF("=== GLM-4.5 RAW INPUT ===\n");
1380-
for (size_t i = 0; i < input.size(); ++i) {
1381-
char ch = input[i];
1382-
if (ch == '\n') LOG_INF("\\n");
1383-
else if (ch == '\t') LOG_INF("\\t");
1384-
else if (ch == '\r') LOG_INF("\\r");
1385-
else if (std::isspace(ch)) LOG_INF("·"); // visible space
1386-
else LOG_INF("%c", ch);
1387-
}
1388-
LOG_INF("\n=== END RAW INPUT ===\n");
1389-
}
1390-
1391-
static void debug_print_parse_position(const std::string& input, size_t pos, const char* context) {
1392-
size_t start = (pos < 50) ? 0 : pos - 50;
1393-
size_t end = std::min(input.size(), pos + 50);
1394-
LOG_INF("=== %s at position %zu ===\n", context, pos);
1395-
for (size_t i = start; i < end; ++i) {
1396-
if (i == pos) LOG_INF(">>>");
1397-
char ch = input[i];
1398-
if (ch == '\n') LOG_INF("\\n");
1399-
else if (ch == '\t') LOG_INF("\\t");
1400-
else LOG_INF("%c", ch);
1401-
if (i == pos) LOG_INF("<<<");
1402-
}
1403-
LOG_INF("\n=== END POSITION ===\n");
1404-
}
1405-
14061366
static void common_chat_parse_glm_4_5(common_chat_msg_parser & builder) {
1407-
debug_print_raw_input(builder.input());
1408-
1409-
// Helper function to get expected type from tool schema
1367+
14101368
auto get_expected_type = [&](const std::string& tool_name, const std::string& param_name) -> std::string {
14111369
// Access tools schema from builder syntax
14121370
const auto& tools_schema = builder.syntax().tools_schema;
@@ -1462,7 +1420,7 @@ static void common_chat_parse_glm_4_5(common_chat_msg_parser & builder) {
14621420
builder.consume_spaces();
14631421

14641422
size_t arg_key_start = builder.input().find("<arg_key>", tool_call_start);
1465-
if (arg_key_start == std::string::npos) {
1423+
if (arg_key_start == std::string::npos || arg_key_start > tool_call_end) {
14661424
std::string function_content = builder.input().substr(builder.pos(), tool_call_end - builder.pos());
14671425
std::string function_name = string_strip(function_content);
14681426

@@ -1479,13 +1437,8 @@ static void common_chat_parse_glm_4_5(common_chat_msg_parser & builder) {
14791437
json args_json = json::object();
14801438
builder.move_to(arg_key_start);
14811439

1482-
while (builder.pos() < tool_call_end) {
1483-
if (!builder.try_consume_literal("<arg_key>")) {
1484-
builder.consume_spaces();
1485-
if (!builder.try_consume_literal("<arg_key>")) {
1486-
break;
1487-
}
1488-
}
1440+
while (builder.pos() < tool_call_end && builder.input().substr(builder.pos()).find("<arg_key>") == 0) {
1441+
if (!builder.try_consume_literal("<arg_key>")) break;
14891442

14901443
auto key_close = builder.try_find_literal("</arg_key>");
14911444
if (!key_close || key_close->groups[0].end > tool_call_end) {
@@ -1514,29 +1467,36 @@ static void common_chat_parse_glm_4_5(common_chat_msg_parser & builder) {
15141467
std::string expected_type = get_expected_type(function_name, key);
15151468
json parsed_value;
15161469

1517-
if (expected_type == "integer" || expected_type == "number") {
1518-
try {
1519-
parsed_value = std::stod(value); // or std::stoi for integers
1520-
} catch (...) {
1521-
parsed_value = value; // Fallback to string
1522-
}
1523-
} else if (expected_type == "boolean") {
1524-
parsed_value = (value == "true");
1525-
} else if (expected_type == "array" || expected_type == "object") {
1470+
if (expected_type == "array" || expected_type == "object") {
15261471
try {
15271472
parsed_value = json::parse(value);
15281473
} catch (...) {
15291474
parsed_value = value;
15301475
}
15311476
} else {
1532-
// Default to string
1477+
// For all other types, store as string and let the unpacking logic handle it
15331478
parsed_value = value;
15341479
}
15351480

15361481
args_json[key] = parsed_value;
1537-
15381482
builder.consume_spaces();
15391483
}
1484+
1485+
if (args_json.size() == 1) {
1486+
const auto key = args_json.begin().key();
1487+
auto& value = args_json.begin().value();
1488+
1489+
if (value.is_string()) {
1490+
try {
1491+
json unpacked_json = json::parse(value.get<std::string>());
1492+
if (unpacked_json.is_object()) {
1493+
args_json = unpacked_json;
1494+
}
1495+
} catch (const std::exception&) {
1496+
// Not a valid JSON string, proceed as normal
1497+
}
1498+
}
1499+
}
15401500

15411501
if (!builder.add_tool_call(function_name, "", args_json.dump())) {
15421502
LOG_INF("%s: failed to add tool call with arguments\n", __func__);
@@ -1552,6 +1512,7 @@ static void common_chat_parse_glm_4_5(common_chat_msg_parser & builder) {
15521512
LOG_INF("%s: no progress in parsing, stopping to avoid infinite loop\n", __func__);
15531513
break;
15541514
}
1515+
curr_pos = builder.pos();
15551516
}
15561517

15571518
if (builder.pos() < builder.input().size()) {

0 commit comments

Comments
 (0)