| 435 | } |
| 436 | |
| 437 | void cbm_sem_random_index(const char *token, cbm_sem_vec_t *out) { |
| 438 | memset(out, 0, sizeof(*out)); |
| 439 | if (!token) { |
| 440 | return; |
| 441 | } |
| 442 | |
| 443 | /* Try pretrained nomic-embed-code vector first (768d, distilled from 7B). */ |
| 444 | ensure_pretrained_map(); |
| 445 | const char *idx_str = cbm_ht_get(g_pretrained_map, token); |
| 446 | if (idx_str) { |
| 447 | char *end = NULL; |
| 448 | long idx = strtol(idx_str, &end, BASE_DECIMAL); |
| 449 | if (end != idx_str && idx >= 0 && idx < PRETRAINED_TOKEN_COUNT) { |
| 450 | const int8_t *pvec = pretrained_vec_at((int)idx); |
| 451 | for (int d = 0; d < CBM_SEM_DIM && d < PRETRAINED_DIM; d++) { |
| 452 | out->v[d] = (float)pvec[d] / CBM_SEM_INT8_MAX; |
| 453 | } |
| 454 | return; |
| 455 | } |
| 456 | } |
| 457 | |
| 458 | /* Fallback: sparse random vector for tokens not in pretrained vocab. */ |
| 459 | uint64_t seed = XXH3_64bits(token, strlen(token)); |
| 460 | for (int i = 0; i < CBM_SEM_SPARSE_NNZE; i++) { |
| 461 | uint64_t h = XXH3_64bits_withSeed(&i, sizeof(i), seed + RI_SEED_BASE); |
| 462 | int pos = (int)(h % CBM_SEM_DIM); |
| 463 | float sign = (h & SKIP_ONE) ? CBM_SEM_UNIT_POS : -CBM_SEM_UNIT_POS; |
| 464 | out->v[pos] += sign; |
| 465 | } |
| 466 | } |
| 467 | |
| 468 | void cbm_sem_normalize(cbm_sem_vec_t *v) { |
| 469 | if (!v) { |
no test coverage detected