12 const char *p = strstr(json, key);
22 while (*p && (*p ==
':' || *p ==
' ' || *p ==
'\t')) {
27 if (sscanf(p,
"%d", &value) != 1) {
40 if (!json || !key || !out_value) {
44 size_t key_len = strlen(key);
45 const char *
end = json + len;
46 for (
const char *p = json; p + key_len <=
end; ++p) {
47 if (memcmp(p, key, key_len) != 0) {
51 const char *colon = memchr(p + key_len,
':', (
size_t)(
end - (p + key_len)));
55 const char *v = colon + 1;
56 while (v <
end && (*v ==
' ' || *v ==
'\t' || *v ==
'\n' || *v ==
'\r')) {
61 if (v <
end && sscanf(v,
"%d", &value) == 1) {
73 const char *
const *keys,
79 for (
int i = 0; keys[i]; ++i) {
92 if (!json || !key || !out_value) {
96 size_t key_len = strlen(key);
97 const char *
end = json + len;
98 for (
const char *p = json; p + key_len <=
end; ++p) {
99 if (memcmp(p, key, key_len) != 0) {
103 const char *colon = memchr(p + key_len,
':', (
size_t)(
end - (p + key_len)));
107 const char *v = colon + 1;
108 while (v <
end && (*v ==
' ' || *v ==
'\t' || *v ==
'\n' || *v ==
'\r')) {
113 if (v <
end && sscanf(v,
"%f", &value) == 1) {
125 const char *
const *keys,
131 for (
int i = 0; keys[i]; ++i) {
141 const char **out_start,
144 if (!json || !key || !out_start || !
out_len) {
148 const char *p = strstr(json, key);
153 const char *colon = strchr(p,
':');
158 const char *brace = strchr(colon,
'{');
163 bool in_string =
false;
166 const char *
start = NULL;
168 for (
const char *cur = brace; *cur; ++cur) {
215 FILE *f = fopen(path,
"rb");
217 perror(
"ck_model_config_from_hf_json: fopen");
221 if (fseek(f, 0, SEEK_END) != 0) {
230 if (fseek(f, 0, SEEK_SET) != 0) {
235 char *buf = (
char *)malloc((
size_t)len + 1);
240 size_t nread = fread(buf, 1, (
size_t)len, f);
245 memset(&tmp, 0,
sizeof(tmp));
249 const char *scope = buf;
250 size_t scope_len = nread;
256 const char *num_layers_keys[] = {
"\"num_hidden_layers\"",
"\"n_layer\"", NULL };
257 const char *hidden_size_keys[] = {
"\"hidden_size\"",
"\"n_embd\"",
"\"d_model\"", NULL };
258 const char *intermediate_keys[] = {
"\"intermediate_size\"",
"\"n_inner\"",
"\"ffn_dim\"",
"\"mlp_dim\"", NULL };
259 const char *num_heads_keys[] = {
"\"num_attention_heads\"",
"\"n_head\"",
"\"num_heads\"", NULL };
260 const char *num_kv_heads_keys[] = {
"\"num_key_value_heads\"",
"\"num_kv_heads\"", NULL };
261 const char *vocab_keys[] = {
"\"vocab_size\"",
"\"n_vocab\"", NULL };
262 const char *context_keys[] = {
"\"max_position_embeddings\"",
"\"n_positions\"",
"\"context_length\"",
"\"seq_len\"", NULL };
263 const char *rms_eps_keys[] = {
"\"rms_norm_eps\"",
"\"layer_norm_eps\"", NULL };
264 const char *rope_theta_keys[] = {
"\"rope_theta\"",
"\"rope_base\"", NULL };
267 fprintf(stderr,
"Warning: num_hidden_layers not found in %s\n", path);
270 fprintf(stderr,
"Warning: hidden_size not found in %s\n", path);
273 fprintf(stderr,
"Warning: intermediate_size not found in %s\n", path);
276 fprintf(stderr,
"Warning: num_attention_heads not found in %s\n", path);
307 if (!cfg || !graph) {
312 const int nodes_per_layer = 10;
313 const int total_nodes = L * nodes_per_layer;
321 const uint16_t INPUT_NODE_SENTINEL = 0xFFFF;
323 for (
int layer = 0; layer < L; ++layer) {
324 const int base = layer * nodes_per_layer;
327 nodes[base + 0].
id.
layer = (uint16_t)layer;
328 nodes[base + 0].
id.
node = 0;
337 nodes[base + 1].
id.
layer = (uint16_t)layer;
338 nodes[base + 1].
id.
node = 1;
347 nodes[base + 2].
id.
layer = (uint16_t)layer;
348 nodes[base + 2].
id.
node = 2;
357 nodes[base + 3].
id.
layer = (uint16_t)layer;
358 nodes[base + 3].
id.
node = 3;
370 nodes[base + 4].
id.
layer = (uint16_t)layer;
371 nodes[base + 4].
id.
node = 4;
380 nodes[base + 5].
id.
layer = (uint16_t)layer;
381 nodes[base + 5].
id.
node = 5;
390 nodes[base + 6].
id.
layer = (uint16_t)layer;
391 nodes[base + 6].
id.
node = 6;
400 nodes[base + 7].
id.
layer = (uint16_t)layer;
401 nodes[base + 7].
id.
node = 7;
413 nodes[base + 8].
id.
layer = (uint16_t)layer;
414 nodes[base + 8].
id.
node = 8;
423 nodes[base + 9].
id.
layer = (uint16_t)layer;
424 nodes[base + 9].
id.
node = 9;
438 graph->
nodes = nodes;
458 if (!forward || !backward) {
471 for (
int i = 0; i < N; ++i) {
482 for (
int j = 0; j < f->
n_inputs; ++j) {
489 backward->
nodes = nodes;
520 default:
return "UNKNOWN";
526 if (!graph || !out) {
531 "CKIRGraph: layers=%d, hidden_size=%d, intermediate_size=%d, heads=%d, kv_heads=%d, vocab=%d, ctx=%d, eps=%.6g, rope_theta=%.6g\n",
542 for (
int i = 0; i < graph->
num_nodes; ++i) {
544 fprintf(out,
" L%u N%u %-14s outputs=[",
552 fprintf(out,
"L%u:N%u:%d",
557 fprintf(out,
"] inputs=[");
558 for (
int j = 0; j < n->
n_inputs; ++j) {
566 fprintf(out,
"L%u:N%u",
577 if (!graph || !path) {
581 FILE *f = fopen(path,
"wb");
583 perror(
"ck_ir_serialize_json: fopen");
588 fprintf(f,
" \"config\": {\n");
592 fprintf(f,
" \"num_attention_heads\": %d,\n", graph->
config.
num_heads);
602 fprintf(f,
" \"nodes\": [\n");
603 for (
int i = 0; i < graph->
num_nodes; ++i) {
606 fprintf(f,
" \"layer\": %u,\n", (
unsigned)n->
id.
layer);
607 fprintf(f,
" \"node\": %u,\n", (
unsigned)n->
id.
node);
608 fprintf(f,
" \"op\": \"%s\",\n",
op_name(n->
op));
611 fprintf(f,
" \"outputs\": [");
613 if (o > 0) fprintf(f,
", ");
614 fprintf(f,
"\"L%u:N%u:%d\"",
622 fprintf(f,
" \"inputs\": [");
623 for (
int j = 0; j < n->
n_inputs; ++j) {
625 if (j > 0) fprintf(f,
", ");
627 fprintf(f,
"\"IN\"");
629 fprintf(f,
"\"L%u:N%u:%u\"",
637 fprintf(f,
" }%s\n", (i + 1 < graph->
num_nodes) ?
"," :
"");
651 if (strcmp(s,
"ADD") == 0)
return CK_OP_ADD;
667 if (!path || !graph) {
671 FILE *f = fopen(path,
"rb");
673 perror(
"ck_ir_parse_json: fopen");
677 if (fseek(f, 0, SEEK_END) != 0) {
686 if (fseek(f, 0, SEEK_SET) != 0) {
691 char *buf = (
char *)malloc((
size_t)len + 1);
696 size_t nread = fread(buf, 1, (
size_t)len, f);
701 memset(&tmp, 0,
sizeof(tmp));
705 fprintf(stderr,
"ck_ir_parse_json: missing num_layers\n");
708 fprintf(stderr,
"ck_ir_parse_json: missing hidden_size\n");
711 fprintf(stderr,
"ck_ir_parse_json: missing intermediate_size\n");
714 fprintf(stderr,
"ck_ir_parse_json: missing num_attention_heads\n");
735 char *nodes_begin = strstr(buf,
"\"nodes\"");
740 char *p = nodes_begin;
742 while ((p = strstr(p,
"\"layer\"")) != NULL) {
759 for (
int i = 0; i < count; ++i) {
761 char *pl = strstr(p,
"\"layer\"");
762 if (!pl) { free(nodes); free(buf);
return -1; }
764 if (sscanf(strchr(pl,
':'),
" : %d", &layer) != 1) {
765 free(nodes); free(buf);
return -1;
769 char *pn = strstr(pl,
"\"node\"");
770 if (!pn) { free(nodes); free(buf);
return -1; }
772 if (sscanf(strchr(pn,
':'),
" : %d", &node) != 1) {
773 free(nodes); free(buf);
return -1;
777 char *po = strstr(pn,
"\"op\"");
778 if (!po) { free(nodes); free(buf);
return -1; }
779 char op_str[64] = {0};
780 if (sscanf(strchr(po,
':'),
" : \"%63[^\"]\"", op_str) != 1) {
781 free(nodes); free(buf);
return -1;
786 n->
id.
node = (uint16_t)node;
790 char *pout = strstr(po,
"\"outputs\"");
791 if (!pout) { free(nodes); free(buf);
return -1; }
792 char *bo = strchr(pout,
'[');
793 char *eo = strchr(pout,
']');
795 if (bo && eo && eo > bo) {
797 while ((q = strchr(q,
'"')) && q < eo) {
799 q = strchr(q + 1,
'"');
800 if (!q || q >= eo)
break;
808 char *pin = strstr(po,
"\"inputs\"");
809 if (!pin) { free(nodes); free(buf);
return -1; }
810 char *bi = strchr(pin,
'[');
811 char *ei = strchr(pin,
']');
813 if (bi && ei && ei > bi) {
816 while ((q = strchr(q,
'"')) && q < ei) {
818 if (sscanf(q,
"\"%63[^\"]\"", tok) != 1) {
821 if (strcmp(tok,
"IN") == 0) {
826 unsigned plh = 0, pnn = 0, slot = 0;
827 if (sscanf(tok,
"L%u:N%u:%u", &plh, &pnn, &slot) == 3) {
835 q = strchr(q + 1,
'"');
836 if (!q || q >= ei)
break;
849 graph->
nodes = nodes;
int ck_build_decoder_ir(const CKModelConfig *cfg, CKIRGraph *graph)
static const char * op_name(CKOpType op)
int ck_ir_serialize_json(const CKIRGraph *graph, const char *path)
int ck_build_decoder_backward_ir(const CKIRGraph *forward, CKIRGraph *backward)
static int parse_int_field_in_range(const char *json, size_t len, const char *key, int *out_value)
static int parse_float_field_in_range(const char *json, size_t len, const char *key, float *out_value)
static int parse_int_field(const char *json, const char *key, int *out_value)
void ck_ir_dump(const CKIRGraph *graph, FILE *out)
static int parse_float_field_any(const char *json, size_t len, const char *const *keys, float *out_value)
static CKOpType map_forward_to_backward(CKOpType op)
static CKOpType parse_op(const char *s)
int ck_model_config_from_hf_json(const char *path, CKModelConfig *cfg)
int ck_ir_parse_json(const char *path, CKIRGraph *graph)
static int parse_int_field_any(const char *json, size_t len, const char *const *keys, int *out_value)
static int find_object_range(const char *json, const char *key, const char **out_start, size_t *out_len)
void ck_ir_free(CKIRGraph *graph)
const int32_t int int * out_len