| 547 | } |
| 548 | |
| 549 | bool PackageManager::install_torch_async(const std::string& cuda_version, |
| 550 | const std::string& torch_version, |
| 551 | UvRunner::OutputCallback on_output, |
| 552 | UvRunner::CompletionCallback on_complete) { |
| 553 | if (!ensure_venv()) |
| 554 | return false; |
| 555 | |
| 556 | if (!m_runner) { |
| 557 | m_runner = std::make_unique<UvRunner>(); |
| 558 | } |
| 559 | |
| 560 | if (m_runner->is_running()) { |
| 561 | LOG_ERROR("Another UV operation is already running"); |
| 562 | return false; |
| 563 | } |
| 564 | |
| 565 | const std::string cuda_tag = core::get_pytorch_cuda_tag(cuda_version); |
| 566 | LOG_INFO("PyTorch CUDA tag (async): {}", cuda_tag); |
| 567 | |
| 568 | std::string package = "torch"; |
| 569 | if (!torch_version.empty()) |
| 570 | package += "==" + torch_version; |
| 571 | |
| 572 | const std::string index_url = std::string(PYTORCH_INDEX) + cuda_tag; |
| 573 | |
| 574 | LOG_INFO("Installing {} from {} (async)", package, cuda_tag); |
| 575 | |
| 576 | m_runner->set_output_callback(std::move(on_output)); |
| 577 | m_runner->set_completion_callback(std::move(on_complete)); |
| 578 | |
| 579 | std::vector<std::string> args = {"pip", "install", package, "--extra-index-url", index_url, |
| 580 | "--python", lfs::core::path_to_utf8(venv_python())}; |
| 581 | if (torch_version.empty()) |
| 582 | args.push_back("--upgrade"); |
| 583 | |
| 584 | return m_runner->start(args); |
| 585 | } |
| 586 | |
| 587 | bool PackageManager::install_async_raw(const std::string& package, |
| 588 | UvRunner::RawOutputCallback on_output, |