| 446 | } |
| 447 | |
| 448 | void server_models::load(const std::string & name) { |
| 449 | if (!has_model(name)) { |
| 450 | throw std::runtime_error("model name=" + name + " is not found"); |
| 451 | } |
| 452 | unload_lru(); |
| 453 | |
| 454 | std::lock_guard<std::mutex> lk(mutex); |
| 455 | |
| 456 | auto meta = mapping[name].meta; |
| 457 | if (meta.status != SERVER_MODEL_STATUS_UNLOADED) { |
| 458 | SRV_INF("model %s is not ready\n", name.c_str()); |
| 459 | return; |
| 460 | } |
| 461 | |
| 462 | // prepare new instance info |
| 463 | instance_t inst; |
| 464 | inst.meta = meta; |
| 465 | inst.meta.port = get_free_port(); |
| 466 | inst.meta.status = SERVER_MODEL_STATUS_LOADING; |
| 467 | inst.meta.last_used = ggml_time_ms(); |
| 468 | |
| 469 | if (inst.meta.port <= 0) { |
| 470 | throw std::runtime_error("failed to get a port number"); |
| 471 | } |
| 472 | |
| 473 | inst.subproc = std::make_shared<subprocess_s>(); |
| 474 | { |
| 475 | SRV_INF("spawning server instance with name=%s on port %d\n", inst.meta.name.c_str(), inst.meta.port); |
| 476 | |
| 477 | inst.meta.update_args(ctx_preset, bin_path); // render args |
| 478 | |
| 479 | std::vector<std::string> child_args = inst.meta.args; // copy |
| 480 | std::vector<std::string> child_env = base_env; // copy |
| 481 | child_env.push_back("LLAMA_SERVER_ROUTER_PORT=" + std::to_string(base_params.port)); |
| 482 | |
| 483 | SRV_INF("%s", "spawning server instance with args:\n"); |
| 484 | for (const auto & arg : child_args) { |
| 485 | SRV_INF(" %s\n", arg.c_str()); |
| 486 | } |
| 487 | inst.meta.args = child_args; // save for debugging |
| 488 | |
| 489 | std::vector<char *> argv = to_char_ptr_array(child_args); |
| 490 | std::vector<char *> envp = to_char_ptr_array(child_env); |
| 491 | |
| 492 | // TODO @ngxson : maybe separate stdout and stderr in the future |
| 493 | // so that we can use stdout for commands and stderr for logging |
| 494 | int options = subprocess_option_no_window | subprocess_option_combined_stdout_stderr; |
| 495 | int result = subprocess_create_ex(argv.data(), options, envp.data(), inst.subproc.get()); |
| 496 | if (result != 0) { |
| 497 | throw std::runtime_error("failed to spawn server instance"); |
| 498 | } |
| 499 | |
| 500 | inst.stdin_file = subprocess_stdin(inst.subproc.get()); |
| 501 | } |
| 502 | |
| 503 | // start a thread to manage the child process |
| 504 | // captured variables are guaranteed to be destroyed only after the thread is joined |
| 505 | inst.th = std::thread([this, name, child_proc = inst.subproc, port = inst.meta.port, stop_timeout = inst.meta.stop_timeout]() { |
nothing calls this directly
no test coverage detected