diff --git a/tooling/pipeline/src/main.cc b/tooling/pipeline/src/main.cc index b4b590d5..5154058a 100644 --- a/tooling/pipeline/src/main.cc +++ b/tooling/pipeline/src/main.cc @@ -25,223 +25,230 @@ namespace di = boost::di; static constexpr size_t kLogMaxCount = 512; int main(const int argc, char** argv) { - spdlog::set_level(spdlog::level::debug); - spdlog::set_pattern("│ %Y-%m-%d %H:%M:%S.%e │ %^%-7l%$ │ %v"); - BoundedChannel log_channel(kLogMaxCount); + spdlog::set_level(spdlog::level::debug); + spdlog::set_pattern("│ %Y-%m-%d %H:%M:%S.%e │ %^%-7l%$ │ %v"); + BoundedChannel log_channel(kLogMaxCount); - auto log_dispatcher = // - std::make_unique(log_channel); - std::shared_ptr log_producer = - std::make_shared(log_channel); + auto log_dispatcher = // + std::make_unique(log_channel); + std::shared_ptr log_producer = + std::make_shared(log_channel); - std::thread log_thread([&log_dispatcher] { log_dispatcher->Run(); }); + std::thread log_thread([&log_dispatcher] { log_dispatcher->Run(); }); - auto shutdown = [&](const int exit_code) { - log_channel.Close(); - log_thread.join(); - return exit_code; - }; + auto shutdown = [&](const int exit_code) { + log_channel.Close(); + log_thread.join(); + return exit_code; + }; - try { - Timer timer; + try { + Timer timer; #ifndef BIERGARTEN_MOCK_ONLY - const LlamaBackendState llama_backend_state; + const LlamaBackendState llama_backend_state; #endif - log_producer->Log({.level = LogLevel::Info, - .phase = PipelinePhase::Startup, - .message = "STARTING PIPELINE"}); + log_producer->Log({.level = LogLevel::Info, + .phase = PipelinePhase::Startup, + .message = "STARTING PIPELINE"}); - const std::optional parsed_options = - ParseArguments(argc, argv, log_producer); + const std::optional parsed_options = + ParseArguments(argc, argv, log_producer); - if (!parsed_options.has_value()) { - return shutdown(EXIT_FAILURE); - } - - const auto options = *parsed_options; - const std::string model_path = options.generator.model_path.string(); - const auto sampling = - options.generator.sampling.value_or(SamplingOptions{}); - - std::unique_ptr prompt_directory; - - if (!options.generator.use_mocked) { - try { - prompt_directory = std::make_unique( - options.pipeline.prompt_dir, log_producer); - } catch (const std::exception& dir_error) { - log_producer->Log({.level = LogLevel::Error, - .phase = PipelinePhase::Startup, - .message = std::format("Invalid --prompt-dir: {}", - dir_error.what())}); - - return shutdown(EXIT_FAILURE); + if (!parsed_options.has_value()) { + return shutdown(EXIT_FAILURE); } - } - const auto injector = di::make_injector( - di::bind().to(log_producer), - di::bind().to(options), - di::bind().to(model_path), - di::bind().to(), - di::bind().to( - [options, &log_producer]() -> std::unique_ptr { - if (options.generator.use_mocked) { + const auto options = *parsed_options; + const std::string model_path = options.generator.model_path.string(); + const auto sampling = + options.generator.sampling.value_or(SamplingOptions{}); + + std::unique_ptr prompt_directory; + + if (!options.generator.use_mocked) { + try { + prompt_directory = std::make_unique( + options.pipeline.prompt_dir, log_producer); + } catch (const std::exception& dir_error) { + log_producer->Log( + {.level = LogLevel::Error, + .phase = PipelinePhase::Startup, + .message = std::format("Invalid --prompt-dir: {}", + dir_error.what())}); + + return shutdown(EXIT_FAILURE); + } + } + + const auto injector = di::make_injector( + di::bind().to(log_producer), + di::bind().to(options), + di::bind().to(model_path), + di::bind().to(), + di::bind().to( + [options, + &log_producer]() -> std::unique_ptr { + if (options.generator.use_mocked) { + log_producer->Log( + {.level = LogLevel::Info, + .phase = PipelinePhase::Startup, + .message = "Postal code: mock (curated examples)"}); + + return std::make_unique(); + } + + log_producer->Log( + {.level = LogLevel::Info, + .phase = PipelinePhase::Startup, + .message = + "Postal code: Xeger (regex-based generation)"}); + + return std::make_unique(); + }), + di::bind().to( + [options, + &log_producer]() -> std::unique_ptr { + if (options.generator.use_mocked) { + log_producer->Log({.level = LogLevel::Info, + .phase = PipelinePhase::Startup, + .message = "Curated data: mock"}); + + return std::make_unique(); + } + + log_producer->Log({.level = LogLevel::Info, + .phase = PipelinePhase::Startup, + .message = "Curated data: JsonLoader"}); + + return std::make_unique( + CuratedDataFilePaths{ + .locations_path = "locations.json", + .personas_path = "personas.json", + .forenames_path = "forenames-by-country.json", + .surnames_path = "surnames-by-country.json", + }); + }), + di::bind().to([options, log_producer] { + if (options.generator.use_mocked) { + { + log_producer->Log( + {.level = LogLevel::Info, + .phase = PipelinePhase::Startup, + .message = "Prompt formatter: none (mock mode)"}); + } + return std::unique_ptr(nullptr); + } + { log_producer->Log( {.level = LogLevel::Info, .phase = PipelinePhase::Startup, - .message = "Postal code: mock (curated examples)"}); + .message = + "Prompt formatter: Gemma4JinjaPromptFormatter"}); + } + return std::unique_ptr( + std::make_unique()); + }), + di::bind().to([options, log_producer] { + if (options.generator.use_mocked) { + { + log_producer->Log( + {.level = LogLevel::Info, + .phase = PipelinePhase::Startup, + .message = "Web client: none (mock mode)"}); + } + return std::unique_ptr(nullptr); + } - return std::make_unique(); - } + log_producer->Log({.level = LogLevel::Info, + .phase = PipelinePhase::Startup, + .message = "Web client: HttpWebClient"}); - log_producer->Log( - {.level = LogLevel::Info, - .phase = PipelinePhase::Startup, - .message = "Postal code: Xeger (regex-based generation)"}); + return std::unique_ptr( + std::make_unique(log_producer)); + }), + di::bind().to( + [options, &log_producer]( + const auto& inj) -> std::unique_ptr { + if (options.generator.use_mocked) { + log_producer->Log({.level = LogLevel::Info, + .phase = PipelinePhase::Startup, + .message = "Enrichment: mock"}); - return std::make_unique(); - }), - di::bind().to( - [options, &log_producer]() -> std::unique_ptr { - if (options.generator.use_mocked) { - log_producer->Log({.level = LogLevel::Info, - .phase = PipelinePhase::Startup, - .message = "Curated data: mock"}); + return std::make_unique(); + } - return std::make_unique(); - } + log_producer->Log({.level = LogLevel::Info, + .phase = PipelinePhase::Startup, + .message = "Enrichment: Wikipedia"}); - log_producer->Log({.level = LogLevel::Info, - .phase = PipelinePhase::Startup, - .message = "Curated data: JsonLoader"}); + return std::make_unique( + inj.template create>(), + log_producer); + }), + di::bind().to( + [&options, &model_path, &sampling, &prompt_directory, + &log_producer]( + const auto& inj) -> std::unique_ptr { + if (options.generator.use_mocked) { + log_producer->Log({.level = LogLevel::Info, + .phase = PipelinePhase::Startup, + .message = "Generator: mock"}); - return std::make_unique( - CuratedDataFilePaths{ - .locations_path = "locations.json", - .personas_path = "personas.json", - .forenames_path = "forenames-by-country.json", - .surnames_path = "surnames-by-country.json", - }); - }), - di::bind().to([options, log_producer] { - if (options.generator.use_mocked) { - { - log_producer->Log( - {.level = LogLevel::Info, - .phase = PipelinePhase::Startup, - .message = "Prompt formatter: none (mock mode)"}); - } - return std::unique_ptr(nullptr); - } - { - log_producer->Log( - {.level = LogLevel::Info, - .phase = PipelinePhase::Startup, - .message = "Prompt formatter: Gemma4JinjaPromptFormatter"}); - } - return std::unique_ptr( - std::make_unique()); - }), - di::bind().to([options, log_producer] { - if (options.generator.use_mocked) { - { - log_producer->Log({.level = LogLevel::Info, - .phase = PipelinePhase::Startup, - .message = "Web client: none (mock mode)"}); - } - return std::unique_ptr(nullptr); - } - - log_producer->Log({.level = LogLevel::Info, - .phase = PipelinePhase::Startup, - .message = "Web client: HttpWebClient"}); - - return std::unique_ptr( - std::make_unique(log_producer)); - }), - di::bind().to( - [options, &log_producer]( - const auto& inj) -> std::unique_ptr { - if (options.generator.use_mocked) { - log_producer->Log({.level = LogLevel::Info, - .phase = PipelinePhase::Startup, - .message = "Enrichment: mock"}); - - return std::make_unique(); - } - - log_producer->Log({.level = LogLevel::Info, - .phase = PipelinePhase::Startup, - .message = "Enrichment: Wikipedia"}); - - return std::make_unique( - inj.template create>(), - log_producer); - }), - di::bind().to( - [&options, &model_path, &sampling, &prompt_directory, - &log_producer](const auto& inj) -> std::unique_ptr { - if (options.generator.use_mocked) { - log_producer->Log({.level = LogLevel::Info, - .phase = PipelinePhase::Startup, - .message = "Generator: mock"}); - - return std::make_unique(); - } + return std::make_unique(); + } #ifdef BIERGARTEN_MOCK_ONLY - // Unreachable: ParseArguments requires --mocked when - // BIERGARTEN_MOCK_ONLY is compiled in, so LlamaGenerator is - // never constructed and is not linked into this binary. - throw std::runtime_error( - "LlamaGenerator is unavailable in a BIERGARTEN_MOCK_ONLY " - "build"); + // Unreachable: ParseArguments requires --mocked when + // BIERGARTEN_MOCK_ONLY is compiled in, so LlamaGenerator is + // never constructed and is not linked into this binary. + throw std::runtime_error( + "LlamaGenerator is unavailable in a BIERGARTEN_MOCK_ONLY " + "build"); #else - log_producer->Log( - {.level = LogLevel::Info, - .phase = PipelinePhase::Startup, - .message = std::format( - "Generator: LlamaGenerator | model={} | " - "temp={:.2f} top_p={:.2f} top_k={} n_ctx={} seed={}", - model_path, sampling.temperature, sampling.top_p, - sampling.top_k, sampling.n_ctx, sampling.seed)}); + log_producer->Log( + {.level = LogLevel::Info, + .phase = PipelinePhase::Startup, + .message = std::format( + "Generator: LlamaGenerator | model={} | " + "temp={:.2f} top_p={:.2f} top_k={} n_ctx={} seed={}", + model_path, sampling.temperature, sampling.top_p, + sampling.top_k, sampling.n_ctx, sampling.seed)}); - return std::make_unique( - options, model_path, log_producer, - inj.template create>(), - std::move(prompt_directory)); + return std::make_unique( + options, model_path, log_producer, + inj.template create>(), + std::move(prompt_directory)); #endif - })); + })); - const auto orchestrator = - injector.create>(); + const auto orchestrator = + injector.create>(); - if (!orchestrator->Run()) { - log_producer->Log({.level = LogLevel::Error, + if (!orchestrator->Run()) { + log_producer->Log({.level = LogLevel::Error, + .phase = PipelinePhase::Teardown, + .message = "Pipeline execution failed"}); + return shutdown(EXIT_FAILURE); + } + + log_producer->Log({.level = LogLevel::Info, .phase = PipelinePhase::Teardown, - .message = "Pipeline execution failed"}); + .message = std::format("Pipeline complete in {} ms", + timer.Elapsed())}); + + return shutdown(EXIT_SUCCESS); + } catch (const std::exception& exception) { + const LogDTO log_entry{.level = LogLevel::Error, + .phase = PipelinePhase::Teardown, + .message = exception.what()}; + if (log_producer) { + log_producer->Log(log_entry); + } else { + std::cerr << log_entry.message << std::endl; + } + return shutdown(EXIT_FAILURE); - } - - log_producer->Log({.level = LogLevel::Info, - .phase = PipelinePhase::Teardown, - .message = std::format("Pipeline complete in {} ms", - timer.Elapsed())}); - - return shutdown(EXIT_SUCCESS); - } catch (const std::exception& exception) { - const LogDTO log_entry{.level = LogLevel::Error, - .phase = PipelinePhase::Teardown, - .message = exception.what()}; - if (log_producer) { - log_producer->Log(log_entry); - } else { - std::cerr << log_entry.message << std::endl; - } - - return shutdown(EXIT_FAILURE); - } + } }