| 1438 | } |
| 1439 | |
| 1440 | llama_tokens format_prompt_infill( |
| 1441 | const llama_vocab * vocab, |
| 1442 | const json & input_prefix, |
| 1443 | const json & input_suffix, |
| 1444 | const json & input_extra, |
| 1445 | const int n_batch, |
| 1446 | const int n_predict, |
| 1447 | const int n_ctx, |
| 1448 | const bool spm_infill, |
| 1449 | const llama_tokens & tokens_prompt |
| 1450 | ) { |
| 1451 | // TODO: optimize this block by reducing memory allocations and movement |
| 1452 | |
| 1453 | // use FIM repo-level pattern: |
| 1454 | // ref: https://arxiv.org/pdf/2409.12186 |
| 1455 | // |
| 1456 | // [FIM_REP]myproject |
| 1457 | // [FIM_SEP]filename0 |
| 1458 | // extra chunk 0 |
| 1459 | // [FIM_SEP]filename1 |
| 1460 | // extra chunk 1 |
| 1461 | // ... |
| 1462 | // [FIM_SEP]filename |
| 1463 | // [FIM_PRE]prefix[FIM_SUF]suffix[FIM_MID]prompt |
| 1464 | // |
| 1465 | llama_tokens extra_tokens; |
| 1466 | extra_tokens.reserve(n_ctx); |
| 1467 | |
| 1468 | auto tokens_prefix = tokenize_mixed(vocab, input_prefix, false, false); |
| 1469 | auto tokens_suffix = tokenize_mixed(vocab, input_suffix, false, false); |
| 1470 | |
| 1471 | if (llama_vocab_fim_rep(vocab) != LLAMA_TOKEN_NULL) { |
| 1472 | // TODO: make project name an input |
| 1473 | static const auto k_fim_repo = common_tokenize(vocab, "myproject\n", false, false); |
| 1474 | |
| 1475 | extra_tokens.push_back(llama_vocab_fim_rep(vocab)); |
| 1476 | extra_tokens.insert(extra_tokens.end(), k_fim_repo.begin(), k_fim_repo.end()); |
| 1477 | } |
| 1478 | for (const auto & chunk : input_extra) { |
| 1479 | // { "text": string, "filename": string } |
| 1480 | const std::string text = json_value(chunk, "text", std::string()); |
| 1481 | const std::string filename = json_value(chunk, "filename", std::string("tmp")); |
| 1482 | |
| 1483 | if (llama_vocab_fim_sep(vocab) != LLAMA_TOKEN_NULL) { |
| 1484 | const auto k_fim_file = common_tokenize(vocab, filename + "\n", false, false); |
| 1485 | |
| 1486 | extra_tokens.insert(extra_tokens.end(), llama_vocab_fim_sep(vocab)); |
| 1487 | extra_tokens.insert(extra_tokens.end(), k_fim_file.begin(), k_fim_file.end()); |
| 1488 | } else { |
| 1489 | // chunk separator in binary form to avoid confusing the AI |
| 1490 | static const char k_chunk_prefix_str[] = {0x0a, 0x0a, 0x2d, 0x2d, 0x2d, 0x20, 0x73, 0x6e, 0x69, 0x70, 0x70, 0x65, 0x74, 0x20, 0x2d, 0x2d, 0x2d, 0x0a, 0x0a, 0x00}; |
| 1491 | static const auto k_chunk_prefix_tokens = common_tokenize(vocab, k_chunk_prefix_str, false, false); |
| 1492 | |
| 1493 | extra_tokens.insert(extra_tokens.end(), k_chunk_prefix_tokens.begin(), k_chunk_prefix_tokens.end()); |
| 1494 | } |
| 1495 | |
| 1496 | const auto chunk_tokens = common_tokenize(vocab, text, false, false); |
| 1497 | extra_tokens.insert(extra_tokens.end(), chunk_tokens.begin(), chunk_tokens.end()); |
no test coverage detected